Hi! The last testcase in the patch diagnoses invalid constexpr in the ptr case, but doesn't for arr. The array is constexpr, so we do: value = fold_non_dependent_expr (value); if (DECL_DECLARED_CONSTEXPR_P (decl) || (DECL_IN_AGGR_P (decl) && DECL_INITIALIZED_IN_CLASS_P (decl))) { /* Diagnose a non-constant initializer for constexpr variable or non-inline in-class-initialized static data member. */ if (!require_constant_expression (value)) value = error_mark_node; else if (processing_template_decl) /* In a template we might not have done the necessary transformations to make value actually constant, e.g. extend_ref_init_temps. */ value = maybe_constant_init (value, decl, true); else value = cxx_constant_init (value, decl); } but require_constant_expression returned true even when there are REINTERPRET_CAST_Ps in the CONSTRUCTOR, and then cxx_constant_init doesn't reject it, because: case CONSTRUCTOR: if (TREE_CONSTANT (t) && reduced_constant_expression_p (t)) { /* Don't re-process a constant CONSTRUCTOR, but do fold it to VECTOR_CST if applicable. */ verify_constructor_flags (t); if (TREE_CONSTANT (t)) return fold (t); } r = cxx_eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p); break; and reduced_constant_expression_p is true on it, so we never try to evaluate it.
The following patch changes potential_constant_expression_1 to reject the REINTERPRET_CAST_P, not really sure if that is the best way though. In any case, bootstrapped/regtested on x86_64-linux and i686-linux. 2019-03-07 Jakub Jelinek <ja...@redhat.com> PR c++/89599 * constexpr.c (potential_constant_expression_1): Reject REINTERPRET_CAST_P NOP_EXPRs. * g++.dg/ubsan/vptr-4.C: Adjust expected diagnostics. * g++.dg/parse/array-size2.C: Likewise. * g++.dg/cpp0x/constexpr-89599.C: New test. --- gcc/cp/constexpr.c.jj 2019-03-07 14:03:00.040329107 +0100 +++ gcc/cp/constexpr.c 2019-03-07 15:36:30.831721422 +0100 @@ -5997,6 +5997,13 @@ potential_constant_expression_1 (tree t, return true; case NOP_EXPR: + if (REINTERPRET_CAST_P (t)) + { + if (flags & tf_error) + error_at (loc, "a reinterpret_cast is not a constant expression"); + return false; + } + /* FALLTHRU */ case CONVERT_EXPR: case VIEW_CONVERT_EXPR: /* -- a reinterpret_cast. FIXME not implemented, and this rule --- gcc/testsuite/g++.dg/ubsan/vptr-4.C.jj 2019-02-21 22:20:24.886099340 +0100 +++ gcc/testsuite/g++.dg/ubsan/vptr-4.C 2019-03-07 15:59:34.853143085 +0100 @@ -19,7 +19,7 @@ struct T : S { }; constexpr T t; -constexpr const T *p = t.foo (); // { dg-message "expansion of" } +constexpr const T *p = t.foo (); // { dg-error "called in a constant expression" } template <typename U> struct V { @@ -39,17 +39,16 @@ struct W : V<U> { }; constexpr W<int> w; -constexpr const W<int> *s = w.foo (); // { dg-error "is not a constant expression" } -// { dg-message "expansion of" "" { target *-*-* } .-1 } +constexpr const W<int> *s = w.foo (); // { dg-error "called in a constant expression" } template <typename U> int foo (void) { static constexpr T t; - static constexpr const T *p = t.foo (); // { dg-message "expansion of" } + static constexpr const T *p = t.foo (); // { dg-error "called in a constant expression" } static constexpr W<U> w; - static constexpr const W<U> *s = w.foo (); // { dg-error "is not a constant expression" } - return t.b + w.b; // { dg-message "expansion of" "" { target *-*-* } .-1 } + static constexpr const W<U> *s = w.foo (); // { dg-error "called in a constant expression" } + return t.b + w.b; } int x = foo <char> (); --- gcc/testsuite/g++.dg/parse/array-size2.C.jj 2018-11-29 23:11:40.225616846 +0100 +++ gcc/testsuite/g++.dg/parse/array-size2.C 2019-03-07 15:51:12.998330254 +0100 @@ -15,6 +15,8 @@ void foo (void) { char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "40:size of array .g. is not an integral constant-expression" } + // { dg-error "narrowing conversion" "" { target c++11 } .-1 } + // { dg-message "expression has a constant value but is not a C.. constant-expression" "" { target c++11 } .-2 } char h[(__SIZE_TYPE__) &((struct S *) 8)->b]; // { dg-error "10:size of array .h. is not an integral constant-expression" } bar (g, h); } --- gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C.jj 2019-03-07 16:04:43.526107447 +0100 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C 2019-03-07 16:04:14.519580648 +0100 @@ -0,0 +1,6 @@ +// PR c++/89599 +// { dg-do compile { target c++11 } } + +void foo (int x) {} +constexpr void *arr[2] = { (void*) &foo, (void *) foo };// { dg-error "a reinterpret_cast is not a constant expression" } +constexpr void *ptr = (void *) &foo; // { dg-error "a reinterpret_cast is not a constant expression" } Jakub