Recent discussion on the committee reflector pointed out issues with
mutable and constexpr; this patch implements what I think is a
reasonable solution.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4b41346ab344632f6c22adb3d947a093cdb770ac
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Oct 27 14:56:21 2011 -0400
* semantics.c (cxx_eval_outermost_constant_expr): Check
cp_has_mutable_p.
(cxx_eval_component_reference): Check DECL_MUTABLE_P.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fa8ab99..d76df51 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6680,6 +6680,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
error ("%qE is not a constant expression", orig_whole);
*non_constant_p = true;
}
+ if (DECL_MUTABLE_P (part))
+ {
+ if (!allow_non_constant)
+ error ("mutable %qD is not usable in a constant expression", part);
+ *non_constant_p = true;
+ }
if (*non_constant_p)
return t;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
@@ -7665,6 +7671,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
verify_constant (r, allow_non_constant, &non_constant_p);
+ if (TREE_CODE (t) != CONSTRUCTOR
+ && cp_has_mutable_p (TREE_TYPE (t)))
+ {
+ /* 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", TREE_TYPE (t));
+ non_constant_p = true;
+ }
+
if (non_constant_p && !allow_non_constant)
return error_mark_node;
else if (non_constant_p && TREE_CONSTANT (t))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
new file mode 100644
index 0000000..a14d611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+ int i;
+ mutable int j;
+};
+
+constexpr A a = { 0, 1 };
+constexpr A b = a; // { dg-error "mutable" }
+constexpr int i = a.i;
+constexpr int j = a.j; // { dg-error "mutable" }