[Bug c++/68782] [6 regression] bad reference member formed with constexpr

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Dec 14 18:45:00 GMT 2015


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68782

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think the problem is constexpr.c creates invalid trees, in particular
CONSTRUCTORs that have non-TREE_CONSTANT elements, yet they have TREE_CONSTANT
set on them (and possibly also TREE_SIDE_EFFECTS similarly).
build_constructor with NULL vals creates TREE_CONSTANT and !TREE_SIDE_EFFECTS
CONSTRUCTOR, and constexpr.c later modifies the elts without updating those
flags.

--- constexpr.c.jj4     2015-12-07 12:17:56.000000000 +0100
+++ constexpr.c 2015-12-14 19:40:24.054131253 +0100
@@ -2174,6 +2174,8 @@ cxx_eval_bare_aggregate (const constexpr
 {
   vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
   bool changed = false;
+  bool constant_p = true;
+  bool side_effects_p = false;
   gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t));

   verify_ctor_sanity (ctx, TREE_TYPE (t));
@@ -2222,7 +2224,13 @@ cxx_eval_bare_aggregate (const constexpr
          (*p)->last().value = elt;
        }
       else
-       CONSTRUCTOR_APPEND_ELT (*p, index, elt);
+       {
+         CONSTRUCTOR_APPEND_ELT (*p, index, elt);
+         if (!TREE_CONSTANT (elt))
+           constant_p = false;
+         if (TREE_SIDE_EFFECTS (elt))
+           side_effects_p = true;
+       }
     }
   if (*non_constant_p || !changed)
     return t;
@@ -2230,6 +2238,10 @@ cxx_eval_bare_aggregate (const constexpr
   /* We're done building this CONSTRUCTOR, so now we can interpret an
      element without an explicit initializer as value-initialized.  */
   CONSTRUCTOR_NO_IMPLICIT_ZERO (t) = false;
+  if (!constant_p)
+    TREE_CONSTANT (t) = false;
+  if (side_effects_p)
+    TREE_SIDE_EFFECTS (t) = true;
   if (VECTOR_TYPE_P (TREE_TYPE (t)))
     t = fold (t);
   return t;
@@ -2847,9 +2859,13 @@ cxx_eval_store_expression (const constex
       /* The hash table might have moved since the get earlier.  */
       valp = ctx->values->get (object);
       if (TREE_CODE (init) == CONSTRUCTOR)
-       /* An outer ctx->ctor might be pointing to *valp, so just replace
-          its contents.  */
-       CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
+       {
+         /* An outer ctx->ctor might be pointing to *valp, so just replace
+            its contents.  */
+         CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
+         TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
+         TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
+       }
       else
        *valp = init;
     }

is untested fix that cures this testcase, but the cxx_eval_bare_aggregate
changes are incomplete, there are other ways how a new elt is stored too.  Or
perhaps it could just in another loop go over all elements and compute those
flags.  Jason, any thoughts on this?


More information about the Gcc-bugs mailing list