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?