When r265789 changed instantiation_dependent_r in such a way that TEMPLATE_PARM_INDEXes are instantiation-dependent only when their types are dependent, it broke this test. The test uses a combination of SFINAE and narrow conversions to detect if an expression is constexpr. "p" is a template parameter whose type is not dependent, so now it's not considered instantiation-dependent.
The problem is that when finish_decltype_type sees something that isn't instantiation_dependent_uneval_expression_p, it just looks at the type of the expression and lets it go. But it misses a narrowing conversion in decltype(int{(p(), 0U)}) which is narrowing or not depending on if p() is constant. To figure that out we need to create a DECLTYPE_TYPE so that we actually instantiate the expression. The question is what, specifically, should we check in instantiation_dependent_r. I went with checking if a compound literal has something value dependent, then we need to instantion so as not to lose a possible narrowing conversion. In a non-SFINAE context we don't give any narrowing warnings, that's a bug I have another patch for, but it's not dependent on this patch. Though I can imagine there's a patch fixing both these cases. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-01-17 Marek Polacek <pola...@redhat.com> PR c++/88815 - narrowing conversion lost in decltype. * pt.c (instantiation_dependent_r): Consider a compound literal with a value-dependent expression dependent. * g++.dg/cpp0x/constexpr-decltype3.C: New test. diff --git gcc/cp/pt.c gcc/cp/pt.c index e4f76478f54..d0f5dbeec8e 100644 --- gcc/cp/pt.c +++ gcc/cp/pt.c @@ -25800,6 +25800,14 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, return *tp; break; + case CONSTRUCTOR: + /* A compound literal with a value-dependent expression + might contain narrowing conversion. */ + if (TREE_HAS_CONSTRUCTOR (*tp) + && value_dependent_expression_p (*tp)) + return *tp; + break; + default: break; } diff --git gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C new file mode 100644 index 00000000000..fd05366de50 --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C @@ -0,0 +1,25 @@ +// PR c++/88815 +// { dg-do compile { target c++11 } } + +struct true_type { + constexpr operator bool() const { return true; } +}; + +struct false_type { + constexpr operator bool() const { return false; } +}; + +template<int (*p)()> +true_type is_constexpr_impl(decltype(int{(p(), 0U)})); + +template<int (*p)()> +false_type is_constexpr_impl(...); + +template<int (*p)()> +using is_constexpr = decltype(is_constexpr_impl<p>(0)); + +constexpr int f() { return 0; } +int g() { return 0; } + +static_assert(is_constexpr<f>(), ""); +static_assert(!is_constexpr<g>(), "");