On Mon, Mar 26, 2018 at 01:17:22PM -0400, Jason Merrill wrote: > On Sat, Mar 24, 2018 at 6:59 AM, Marek Polacek <pola...@redhat.com> wrote: > > Recently the code in finish_static_assert was changed to use > > perform_implicit_conversion_flags followed by fold_non_dependent_expr. That > > broke this test becase when in a template, p_i_c_f merely wraps the expr in > > an IMPLICIT_CONV_EXPR. fold_non_dependent_expr should be able to fold it to > > a constant but it gave up because is_nondependent_constant_expression > > returned > > false. Jason suggested to fix this roughly like the following, i.e. > > consider > > conversions from classes to literal types potentially constant. > > > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > > > 2018-03-24 Marek Polacek <pola...@redhat.com> > > > > PR c++/85032 > > * constexpr.c (potential_constant_expression_1): Consider > > conversions > > from classes to literal types potentially constant. > > > > * g++.dg/cpp0x/pr51225.C: Adjust error message. > > * g++.dg/cpp1z/constexpr-if17.C: New test. > > > > diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c > > index bebd9f5b5d0..c4b5afe90a2 100644 > > --- gcc/cp/constexpr.c > > +++ gcc/cp/constexpr.c > > @@ -5768,6 +5768,23 @@ potential_constant_expression_1 (tree t, bool > > want_rval, bool strict, bool now, > > TREE_TYPE (t)); > > return false; > > } > > + /* This might be a conversion from a class to a literal type. Let's > > + consider it potentially constant since the conversion might be > > + a constexpr user-defined conversion. */ > > + else if (cxx_dialect >= cxx11 > > + && COMPLETE_TYPE_P (TREE_TYPE (t)) > > + && literal_type_p (TREE_TYPE (t)) > > We probably need to allow dependent types here, too. And incomplete > classes, which might turn out to be literal later.
Ok, I've allowed incomplete types, too. And I think the patch also allows dependent types. Or did you mean using && (TREE_TYPE (t) == NULL_TREE || !COMPLETE_TYPE_P (TREE_TYPE (t)) || literal_type_p (TREE_TYPE (t))) ? That doesn't seem to be needed. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2018-04-06 Marek Polacek <pola...@redhat.com> PR c++/85032 * constexpr.c (potential_constant_expression_1): Consider conversions from classes to literal types potentially constant. * g++.dg/cpp0x/pr51225.C: Adjust error message. * g++.dg/cpp1z/constexpr-if20.C: New test. diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c index 3cc196b4d17..916060312f0 100644 --- gcc/cp/constexpr.c +++ gcc/cp/constexpr.c @@ -5777,6 +5777,23 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, TREE_TYPE (t)); return false; } + /* This might be a conversion from a class to a (potentially) literal + type. Let's consider it potentially constant since the conversion + might be a constexpr user-defined conversion. */ + else if (cxx_dialect >= cxx11 + && (!COMPLETE_TYPE_P (TREE_TYPE (t)) + || literal_type_p (TREE_TYPE (t))) + && TREE_OPERAND (t, 0)) + { + tree type = TREE_TYPE (TREE_OPERAND (t, 0)); + /* If this is a dependent type, it could end up being a class + with conversions. */ + if (type == NULL_TREE || WILDCARD_TYPE_P (type)) + return true; + /* Or a non-dependent class which has conversions. */ + else if (CLASS_TYPE_P (type) && TYPE_HAS_CONVERSION (type)) + return true; + } return (RECUR (TREE_OPERAND (t, 0), TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)); diff --git gcc/testsuite/g++.dg/cpp0x/pr51225.C gcc/testsuite/g++.dg/cpp0x/pr51225.C index f80bd0e778e..5b4e432f7ed 100644 --- gcc/testsuite/g++.dg/cpp0x/pr51225.C +++ gcc/testsuite/g++.dg/cpp0x/pr51225.C @@ -5,7 +5,7 @@ template<int> struct A {}; template<typename> void foo() { - A<int(x)> a; // { dg-error "not declared|invalid type" } + A<int(x)> a; // { dg-error "not declared|could not convert" } } template<typename> struct bar diff --git gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C index e69de29bb2d..56e108be4ad 100644 --- gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C +++ gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C @@ -0,0 +1,22 @@ +// PR c++/85032 +// { dg-options -std=c++17 } + +struct A +{ + constexpr operator bool () { return true; } + int i; +}; + +A a; + +template <class T> +void f() +{ + constexpr bool b = a; + static_assert (a); +} + +int main() +{ + f<int>(); +} Marek