summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-18 13:34:08 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-18 13:34:08 +0000
commitbbcc9042c56a12308c08452ac790353667257b94 (patch)
treec02e1cc1ad1d88205b9940959b4708dca434d9bb
parent0001b9440a35391d83cfc48b7beb304a9e7527d5 (diff)
downloadgcc-bbcc9042c56a12308c08452ac790353667257b94.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217713 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/constexpr.c14
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-mutable2.C10
5 files changed, 34 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6e7f657c6ee..1afd3cfa46a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+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>
PR c++/33911
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5b2565413b0..2f0708b40ec 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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);
- if (TREE_CODE (t) != CONSTRUCTOR
- && cp_has_mutable_p (TREE_TYPE (t)))
+ /* Mutable logic is a bit tricky: we want to allow initialization of
+ 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)
- error ("%qT cannot be the type of a complete constant expression "
- "because it has mutable sub-objects", type);
+ error ("%qE is not a constant expression because it refers to "
+ "mutable subobjects of %qT", t, type);
non_constant_p = true;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d3722d73f61..35423442ece 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -109,6 +109,7 @@ c-common.h, not after.
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF)
AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
+ CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR)
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -3497,6 +3498,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define CONSTRUCTOR_NO_IMPLICIT_ZERO(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) \
(BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE))
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 01a0671341e..5748650ccf4 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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 = 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)
|| error_operand_p (value));
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable2.C
new file mode 100644
index 00000000000..c449c3aabc0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable2.C
@@ -0,0 +1,10 @@
+// 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" }