Commit 2d63bc39 by Jason Merrill Committed by Jason Merrill

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
parent 3671c996
2016-01-26 Jason Merrill <jason@redhat.com>
PR c++/68782
* tree.c (recompute_constructor_flags): Split out from
build_constructor.
(verify_constructor_flags): New.
* tree.h: Declare them.
2016-01-26 Iain Buclaw <ibuclaw@gdcproject.org> 2016-01-26 Iain Buclaw <ibuclaw@gdcproject.org>
PR rtl-optimization/69217 PR rtl-optimization/69217
......
2016-01-26 Jason Merrill <jason@redhat.com>
PR c++/68782
* constexpr.c (cxx_eval_bare_aggregate): Update TREE_CONSTANT
and TREE_SIDE_EFFECTS.
(cxx_eval_constant_expression) [CONSTRUCTOR]: Call
verify_constructor_flags.
2016-01-26 Jakub Jelinek <jakub@redhat.com> 2016-01-26 Jakub Jelinek <jakub@redhat.com>
PR c++/68357 PR c++/68357
......
...@@ -2214,7 +2214,10 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, ...@@ -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<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
vec_alloc (*p, vec_safe_length (v)); 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) FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value)
{ {
constexpr_ctx new_ctx; constexpr_ctx new_ctx;
...@@ -2231,6 +2234,11 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, ...@@ -2231,6 +2234,11 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
break; break;
if (elt != value) if (elt != value)
changed = true; 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) if (index && TREE_CODE (index) == COMPONENT_REF)
{ {
/* This is an initialization of a vfield inside a base /* This is an initialization of a vfield inside a base
...@@ -2264,6 +2272,8 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, ...@@ -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 /* We're done building this CONSTRUCTOR, so now we can interpret an
element without an explicit initializer as value-initialized. */ element without an explicit initializer as value-initialized. */
CONSTRUCTOR_NO_IMPLICIT_ZERO (t) = false; 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))) if (VECTOR_TYPE_P (TREE_TYPE (t)))
t = fold (t); t = fold (t);
return t; return t;
...@@ -2826,6 +2836,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, ...@@ -2826,6 +2836,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
} }
type = TREE_TYPE (object); type = TREE_TYPE (object);
bool no_zero_init = true; bool no_zero_init = true;
vec<tree,va_gc> *ctors = make_tree_vector ();
while (!refs->is_empty()) while (!refs->is_empty())
{ {
if (*valp == NULL_TREE) if (*valp == NULL_TREE)
...@@ -2837,6 +2849,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, ...@@ -2837,6 +2849,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
subobjects will also be zero-initialized. */ subobjects will also be zero-initialized. */
no_zero_init = CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp); no_zero_init = CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp);
vec_safe_push (ctors, *valp);
enum tree_code code = TREE_CODE (type); enum tree_code code = TREE_CODE (type);
type = refs->pop(); type = refs->pop();
tree index = refs->pop(); tree index = refs->pop();
...@@ -2889,14 +2903,36 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, ...@@ -2889,14 +2903,36 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* The hash table might have moved since the get earlier. */ /* The hash table might have moved since the get earlier. */
valp = ctx->values->get (object); valp = ctx->values->get (object);
if (TREE_CODE (init) == CONSTRUCTOR) if (TREE_CODE (init) == CONSTRUCTOR)
/* An outer ctx->ctor might be pointing to *valp, so just replace {
its contents. */ /* An outer ctx->ctor might be pointing to *valp, so replace
CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init); its contents. */
CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
}
else else
*valp = init; *valp = init;
} }
else 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) if (*non_constant_p)
return t; return t;
...@@ -3579,9 +3615,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -3579,9 +3615,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case CONSTRUCTOR: case CONSTRUCTOR:
if (TREE_CONSTANT (t)) if (TREE_CONSTANT (t))
/* Don't re-process a constant CONSTRUCTOR, but do fold it to {
VECTOR_CST if applicable. */ /* Don't re-process a constant CONSTRUCTOR, but do fold it to
return fold (t); 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, r = cxx_eval_bare_aggregate (ctx, t, lval,
non_constant_p, overflow_p); non_constant_p, overflow_p);
break; break;
......
// PR c++/68782
// { dg-do compile { target c++11 } }
#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
struct holder { int& value; };
constexpr holder from_value(int& value)
{ return { value }; }
struct aggr { int i; };
constexpr holder from_aggr(aggr& a)
{ return from_value(a.i); }
int main()
{
aggr a { 42 };
// these don't fire
assert( &from_value(a.i).value != nullptr );
assert( &a.i == &from_value(a.i).value );
// those do
assert( &from_aggr(a).value != nullptr );
assert( &a.i == &from_aggr(a).value );
}
...@@ -1790,34 +1790,66 @@ build_vector_from_val (tree vectype, tree sc) ...@@ -1790,34 +1790,66 @@ build_vector_from_val (tree vectype, tree sc)
} }
} }
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values /* Something has messed with the elements of CONSTRUCTOR C after it was built;
are in the vec pointed to by VALS. */ calculate TREE_CONSTANT and TREE_SIDE_EFFECTS. */
tree
build_constructor (tree type, vec<constructor_elt, va_gc> *vals) void
recompute_constructor_flags (tree c)
{ {
tree c = make_node (CONSTRUCTOR);
unsigned int i; unsigned int i;
constructor_elt *elt; tree val;
bool constant_p = true; bool constant_p = true;
bool side_effects_p = false; bool side_effects_p = false;
vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
TREE_TYPE (c) = type; FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
CONSTRUCTOR_ELTS (c) = vals;
FOR_EACH_VEC_SAFE_ELT (vals, i, elt)
{ {
/* Mostly ctors will have elts that don't have side-effects, so /* Mostly ctors will have elts that don't have side-effects, so
the usual case is to scan all the elements. Hence a single the usual case is to scan all the elements. Hence a single
loop for both const and side effects, rather than one loop loop for both const and side effects, rather than one loop
each (with early outs). */ each (with early outs). */
if (!TREE_CONSTANT (elt->value)) if (!TREE_CONSTANT (val))
constant_p = false; constant_p = false;
if (TREE_SIDE_EFFECTS (elt->value)) if (TREE_SIDE_EFFECTS (val))
side_effects_p = true; side_effects_p = true;
} }
TREE_SIDE_EFFECTS (c) = side_effects_p; TREE_SIDE_EFFECTS (c) = side_effects_p;
TREE_CONSTANT (c) = constant_p; TREE_CONSTANT (c) = constant_p;
}
/* Make sure that TREE_CONSTANT and TREE_SIDE_EFFECTS are correct for
CONSTRUCTOR C. */
void
verify_constructor_flags (tree c)
{
unsigned int i;
tree val;
bool constant_p = TREE_CONSTANT (c);
bool side_effects_p = TREE_SIDE_EFFECTS (c);
vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
{
if (constant_p && !TREE_CONSTANT (val))
internal_error ("non-constant element in constant CONSTRUCTOR");
if (!side_effects_p && TREE_SIDE_EFFECTS (val))
internal_error ("side-effects element in no-side-effects CONSTRUCTOR");
}
}
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in the vec pointed to by VALS. */
tree
build_constructor (tree type, vec<constructor_elt, va_gc> *vals)
{
tree c = make_node (CONSTRUCTOR);
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
recompute_constructor_flags (c);
return c; return c;
} }
......
...@@ -3918,6 +3918,8 @@ extern tree build_vector_stat (tree, tree * MEM_STAT_DECL); ...@@ -3918,6 +3918,8 @@ extern tree build_vector_stat (tree, tree * MEM_STAT_DECL);
#define build_vector(t,v) build_vector_stat (t, v MEM_STAT_INFO) #define build_vector(t,v) build_vector_stat (t, v MEM_STAT_INFO)
extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *); extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
extern tree build_vector_from_val (tree, tree); extern tree build_vector_from_val (tree, tree);
extern void recompute_constructor_flags (tree);
extern void verify_constructor_flags (tree);
extern tree build_constructor (tree, vec<constructor_elt, va_gc> *); extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);
extern tree build_constructor_single (tree, tree, tree); extern tree build_constructor_single (tree, tree, tree);
extern tree build_constructor_from_list (tree, tree); extern tree build_constructor_from_list (tree, tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment