commit e42fdb0afe8827e3320239e252d804e2e3bbd63d
Author: Jason Merrill <jason@redhat.com>
Date: Sat Jun 25 20:52:43 2011 -0400
PR c++/49528
* semantics.c (potential_constant_expression_1): A TARGET_EXPR
with a cleanup isn't constant.
(cxx_eval_constant_expression): Likewise.
* init.c (expand_default_init): Use maybe_constant_init.
@@ -1514,7 +1514,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
tree fn = get_callee_fndecl (rval);
if (fn && DECL_DECLARED_CONSTEXPR_P (fn))
{
- tree e = maybe_constant_value (rval);
+ tree e = maybe_constant_init (rval);
if (TREE_CONSTANT (e))
rval = build2 (INIT_EXPR, type, exp, e);
}
@@ -7020,6 +7020,16 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
break;
case TARGET_EXPR:
+ /* A cleanup isn't constant. */
+ if (TARGET_EXPR_CLEANUP (t))
+ {
+ if (!allow_non_constant)
+ error ("temporary of type %qT needing destruction in a "
+ "constant expression", TREE_TYPE (t));
+ *non_constant_p = true;
+ break;
+ }
+ /* else fall through. */
case INIT_EXPR:
/* Pass false for 'addr' because these codes indicate
initialization of a temporary. */
@@ -7840,8 +7850,16 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
want_rval, flags);
- case INIT_EXPR:
case TARGET_EXPR:
+ /* A cleanup isn't constant. */
+ if (TARGET_EXPR_CLEANUP (t))
+ {
+ if (flags & tf_error)
+ error ("temporary of type %qT needing destruction in a "
+ "constant expression", TREE_TYPE (t));
+ return false;
+ }
+ case INIT_EXPR:
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
rval, flags);
new file mode 100644
@@ -0,0 +1,9 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+ int i;
+ ~A();
+};
+
+constexpr int i = A().i; // { dg-error "destruction" }
new file mode 100644
@@ -0,0 +1,17 @@
+// PR c++/49528
+// { dg-do run }
+
+int d;
+
+struct A
+{
+ int i;
+ ~A() { ++d; };
+};
+
+int main()
+{
+ const int &r = A().i;
+ if (d != 1)
+ return 1;
+}