aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-01-26 16:34:10 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-01-26 16:34:10 -0500
commit2d63bc398f7221edbec3e3f1d4ecbacac87cb3a5 (patch)
treed035f1d3c7a75a68a3d60f7179cbe147b4437151 /gcc/cp/constexpr.c
parent3671c99673af214992ef23e4fd9a28ab2417f33a (diff)
downloadgcc-2d63bc398f7221edbec3e3f1d4ecbacac87cb3a5.zip
gcc-2d63bc398f7221edbec3e3f1d4ecbacac87cb3a5.tar.gz
gcc-2d63bc398f7221edbec3e3f1d4ecbacac87cb3a5.tar.bz2
re PR c++/68782 (bad reference member formed with constexpr)
PR c++/68782 gcc/ * tree.c (recompute_constructor_flags): Split out from build_constructor. (verify_constructor_flags): New. * tree.h: Declare them. gcc/cp/ * constexpr.c (cxx_eval_bare_aggregate): Update TREE_CONSTANT and TREE_SIDE_EFFECTS. (cxx_eval_constant_expression) [CONSTRUCTOR]: Call verify_constructor_flags. From-SVN: r232847
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r--gcc/cp/constexpr.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 6b0e5a8..eed7308 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2214,7 +2214,10 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
vec_alloc (*p, vec_safe_length (v));
- unsigned i; tree index, value;
+ unsigned i;
+ tree index, value;
+ bool constant_p = true;
+ bool side_effects_p = false;
FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value)
{
constexpr_ctx new_ctx;
@@ -2231,6 +2234,11 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
break;
if (elt != value)
changed = true;
+
+ if (!TREE_CONSTANT (elt))
+ constant_p = false;
+ if (TREE_SIDE_EFFECTS (elt))
+ side_effects_p = true;
if (index && TREE_CODE (index) == COMPONENT_REF)
{
/* This is an initialization of a vfield inside a base
@@ -2264,6 +2272,8 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
/* 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;
+ TREE_CONSTANT (t) = constant_p;
+ TREE_SIDE_EFFECTS (t) = side_effects_p;
if (VECTOR_TYPE_P (TREE_TYPE (t)))
t = fold (t);
return t;
@@ -2826,6 +2836,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
}
type = TREE_TYPE (object);
bool no_zero_init = true;
+
+ vec<tree,va_gc> *ctors = make_tree_vector ();
while (!refs->is_empty())
{
if (*valp == NULL_TREE)
@@ -2837,6 +2849,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
subobjects will also be zero-initialized. */
no_zero_init = CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp);
+ vec_safe_push (ctors, *valp);
+
enum tree_code code = TREE_CODE (type);
type = refs->pop();
tree index = refs->pop();
@@ -2889,14 +2903,36 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* 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 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;
}
else
- *valp = init;
+ {
+ *valp = init;
+
+ /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
+ CONSTRUCTORs. */
+ tree elt;
+ unsigned i;
+ bool c = TREE_CONSTANT (init);
+ bool s = TREE_SIDE_EFFECTS (init);
+ if (!c || s)
+ FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
+ {
+ if (!c)
+ TREE_CONSTANT (elt) = false;
+ if (s)
+ TREE_SIDE_EFFECTS (elt) = true;
+ }
+ }
+ release_tree_vector (ctors);
if (*non_constant_p)
return t;
@@ -3579,9 +3615,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case CONSTRUCTOR:
if (TREE_CONSTANT (t))
- /* Don't re-process a constant CONSTRUCTOR, but do fold it to
- VECTOR_CST if applicable. */
- return fold (t);
+ {
+ /* Don't re-process a constant CONSTRUCTOR, but do fold it to
+ VECTOR_CST if applicable. */
+ /* FIXME after GCC 6 branches, make the verify unconditional. */
+ if (CHECKING_P)
+ verify_constructor_flags (t);
+ else
+ recompute_constructor_flags (t);
+ if (TREE_CONSTANT (t))
+ return fold (t);
+ }
r = cxx_eval_bare_aggregate (ctx, t, lval,
non_constant_p, overflow_p);
break;