Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

DR 2543 clarifies that constinit variables should follow the language, and
diagnose non-constant initializers (according to [expr.const]) even if they
can actually initialize the variables statically.

        DR 2543

gcc/cp/ChangeLog:

        * constexpr.cc (cxx_eval_outermost_constant_expr): Preserve
        TARGET_EXPR flags.
        (potential_constant_expression_1): Check TARGET_EXPR_ELIDING_P.
        * typeck2.cc (store_init_value): Diagnose constinit sooner.

gcc/testsuite/ChangeLog:

        * g++.dg/DRs/dr2543.C: New test.
---
 gcc/cp/constexpr.cc               | 12 +++++++
 gcc/cp/typeck2.cc                 | 55 +++++++++++++++++--------------
 gcc/testsuite/g++.dg/DRs/dr2543.C |  5 +++
 3 files changed, 48 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/DRs/dr2543.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 7b8090625e8..8f7f0b7d325 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8448,6 +8448,17 @@ cxx_eval_outermost_constant_expr (tree t, bool 
allow_non_constant,
        }
     }
 
+  if (TREE_CODE (t) == TARGET_EXPR
+      && TREE_CODE (r) == TARGET_EXPR)
+    {
+      /* Preserve this flag for potential_constant_expression, and the others
+        for good measure.  */
+      TARGET_EXPR_ELIDING_P (r) = TARGET_EXPR_ELIDING_P (t);
+      TARGET_EXPR_IMPLICIT_P (r) = TARGET_EXPR_IMPLICIT_P (t);
+      TARGET_EXPR_LIST_INIT_P (r) = TARGET_EXPR_LIST_INIT_P (t);
+      TARGET_EXPR_DIRECT_INIT_P (r) = TARGET_EXPR_DIRECT_INIT_P (t);
+    }
+
   /* Remember the original location if that wouldn't need a wrapper.  */
   if (location_t loc = EXPR_LOCATION (t))
     protected_set_expr_location (r, loc);
@@ -9774,6 +9785,7 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
 
     case TARGET_EXPR:
       if (!TARGET_EXPR_DIRECT_INIT_P (t)
+         && !TARGET_EXPR_ELIDING_P (t)
          && !literal_type_p (TREE_TYPE (t)))
        {
          if (flags & tf_error)
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index bf03967a71f..f5cc7c8371c 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -843,23 +843,45 @@ store_init_value (tree decl, tree init, vec<tree, 
va_gc>** cleanups, int flags)
       bool const_init;
       tree oldval = value;
       if (DECL_DECLARED_CONSTEXPR_P (decl)
+         || DECL_DECLARED_CONSTINIT_P (decl)
          || (DECL_IN_AGGR_P (decl)
              && DECL_INITIALIZED_IN_CLASS_P (decl)))
        {
          value = fold_non_dependent_expr (value, tf_warning_or_error,
                                           /*manifestly_const_eval=*/true,
                                           decl);
+         if (value == error_mark_node)
+           ;
          /* 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 if (!is_constant_expression (value))
+           {
+             /* Maybe we want to give this message for constexpr variables as
+                well, but that will mean a lot of testsuite adjustment.  */
+             if (DECL_DECLARED_CONSTINIT_P (decl))
+             error_at (location_of (decl),
+                       "%<constinit%> variable %qD does not have a "
+                       "constant initializer", decl);
+             require_constant_expression (value);
+             value = error_mark_node;
+           }
          else
-           value = cxx_constant_init (value, decl);
+           {
+             value = maybe_constant_init (value, decl, true);
+
+             /* In a template we might not have done the necessary
+                transformations to make value actually constant,
+                e.g. extend_ref_init_temps.  */
+             if (!processing_template_decl
+                 && !TREE_CONSTANT (value))
+               {
+                 if (DECL_DECLARED_CONSTINIT_P (decl))
+                 error_at (location_of (decl),
+                           "%<constinit%> variable %qD does not have a "
+                           "constant initializer", decl);
+                 value = cxx_constant_init (value, decl);
+               }
+           }
        }
       else
        value = fold_non_dependent_init (value, tf_warning_or_error,
@@ -875,22 +897,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** 
cleanups, int flags)
       if (!TYPE_REF_P (type))
        TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
       if (!const_init)
-       {
-         /* [dcl.constinit]/2 "If a variable declared with the constinit
-            specifier has dynamic initialization, the program is
-            ill-formed."  */
-         if (DECL_DECLARED_CONSTINIT_P (decl))
-           {
-             error_at (location_of (decl),
-                       "%<constinit%> variable %qD does not have a constant "
-                       "initializer", decl);
-             if (require_constant_expression (value))
-               cxx_constant_init (value, decl);
-             value = error_mark_node;
-           }
-         else
-           value = oldval;
-       }
+       value = oldval;
     }
   /* Don't fold initializers of automatic variables in constexpr functions,
      that might fold away something that needs to be diagnosed at constexpr
diff --git a/gcc/testsuite/g++.dg/DRs/dr2543.C 
b/gcc/testsuite/g++.dg/DRs/dr2543.C
new file mode 100644
index 00000000000..87512d30455
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2543.C
@@ -0,0 +1,5 @@
+// CWG 2543
+// { dg-do compile { target c++20 } }
+
+float f;
+constinit int * pi = (int*) &f;        // { dg-error "constant" } 
reinterpret_cast, not constant-initialized
-- 
2.31.1

Reply via email to