Commit 023d89c7 by Jason Merrill Committed by Jason Merrill

re PR c++/58102 (rejects valid initialization of constexpr object with mutable member)

	PR c++/58102
	* typeck2.c (store_init_value): Set it.
	* cp-tree.h (CONSTRUCTOR_MUTABLE_POISON): New.
	* constexpr.c (cxx_eval_outermost_constant_expr): Check it.

From-SVN: r217713
parent bee1d478
2014-11-18 Jason Merrill <jason@redhat.com>
PR c++/58102
* typeck2.c (store_init_value): Set it.
* cp-tree.h (CONSTRUCTOR_MUTABLE_POISON): New.
* constexpr.c (cxx_eval_outermost_constant_expr): Check it.
2014-11-17 Jason Merrill <jason@redhat.com> 2014-11-17 Jason Merrill <jason@redhat.com>
PR c++/33911 PR c++/33911
......
...@@ -3315,15 +3315,15 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, ...@@ -3315,15 +3315,15 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
if (TREE_CODE (t) != CONSTRUCTOR /* Mutable logic is a bit tricky: we want to allow initialization of
&& cp_has_mutable_p (TREE_TYPE (t))) constexpr variables with mutable members, but we can't copy those
members to another constexpr variable. */
if (TREE_CODE (r) == CONSTRUCTOR
&& CONSTRUCTOR_MUTABLE_POISON (r))
{ {
/* We allow a mutable type if the original expression was a
CONSTRUCTOR so that we can do aggregate initialization of
constexpr variables. */
if (!allow_non_constant) if (!allow_non_constant)
error ("%qT cannot be the type of a complete constant expression " error ("%qE is not a constant expression because it refers to "
"because it has mutable sub-objects", type); "mutable subobjects of %qT", t, type);
non_constant_p = true; non_constant_p = true;
} }
......
...@@ -109,6 +109,7 @@ c-common.h, not after. ...@@ -109,6 +109,7 @@ c-common.h, not after.
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF) REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF)
AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR)
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK) FN_TRY_BLOCK_P (in TRY_BLOCK)
...@@ -3497,6 +3498,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -3497,6 +3498,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define CONSTRUCTOR_NO_IMPLICIT_ZERO(NODE) \ #define CONSTRUCTOR_NO_IMPLICIT_ZERO(NODE) \
(TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (NODE))) (TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (NODE)))
/* True if this CONSTRUCTOR should not be used as a variable initializer
because it was loaded from a constexpr variable with mutable fields. */
#define CONSTRUCTOR_MUTABLE_POISON(NODE) \
(TREE_LANG_FLAG_2 (CONSTRUCTOR_CHECK (NODE)))
#define DIRECT_LIST_INIT_P(NODE) \ #define DIRECT_LIST_INIT_P(NODE) \
(BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE)) (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE))
......
...@@ -809,6 +809,10 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) ...@@ -809,6 +809,10 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
value = cxx_constant_value (value, decl); value = cxx_constant_value (value, decl);
} }
value = maybe_constant_init (value, decl); value = maybe_constant_init (value, decl);
if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type))
/* Poison this CONSTRUCTOR so it can't be copied to another
constexpr variable. */
CONSTRUCTOR_MUTABLE_POISON (value) = true;
const_init = (reduced_constant_expression_p (value) const_init = (reduced_constant_expression_p (value)
|| error_operand_p (value)); || error_operand_p (value));
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init; DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
......
// PR c++/58102
// { dg-do compile { target c++11 } }
struct S {
mutable int n;
constexpr S() : n() {}
};
constexpr S s = {};
constexpr S s2 = s; // { dg-error "mutable" }
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