re PR c++/67364 ("accessing uninitialized member" error in constexpr context)

PR c++/67364
	* constexpr.c (cxx_eval_store_expression): Replace
	CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.

From-SVN: r234013
This commit is contained in:
Jason Merrill 2016-03-06 01:47:22 -05:00 committed by Jason Merrill
parent 260e910b11
commit d96e840784
3 changed files with 60 additions and 29 deletions

View File

@ -1,3 +1,9 @@
2016-03-05 Jason Merrill <jason@redhat.com>
PR c++/67364
* constexpr.c (cxx_eval_store_expression): Replace
CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.
2016-03-05 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/66786

View File

@ -2939,39 +2939,34 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* Don't share a CONSTRUCTOR that might be changed later. */
init = unshare_expr (init);
if (target == object)
/* The hash table might have moved since the get earlier. */
valp = ctx->values->get (object);
if (TREE_CODE (init) == CONSTRUCTOR)
{
/* 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 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;
/* 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;
*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;
}
}
/* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
CONSTRUCTORs, if any. */
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)

View File

@ -0,0 +1,30 @@
// PR c++/67364
// { dg-do compile { target c++11 } }
template <typename Xn>
struct tuple {
Xn storage_;
constexpr tuple(Xn const& xn)
: storage_(xn)
{ }
template <typename ...dummy>
constexpr tuple(tuple const& other)
: storage_(other.storage_)
{ }
template <typename ...dummy>
constexpr tuple(tuple& other)
: tuple(const_cast<tuple const&>(other))
{ }
};
template <typename T>
struct wrapper { T value; };
template <typename T>
constexpr wrapper<T> wrap(T t) { return {t}; }
constexpr wrapper<tuple<int>> t = wrap(tuple<int>{2});
static_assert(t.value.storage_ == 2, "");