diff mbox

C++ PATCH for c++/49528 (omitting destructor for temporary with constant value)

Message ID 4E073B73.7010704@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 26, 2011, 2 p.m. UTC
The constant expression evaluation code was happily replacing an 
expression involving a temporary with its constant value even if the 
temporary had a destructor that needed to be run.

After fixing that, I needed to adjust expand_default_init to avoid 
adding a TARGET_EXPR when we aren't really creating a temporary.

Tested x86_64-pc-linux-gnu, applying to trunk.  Jakub, should this go 
into 4.6.1 or .2?

Comments

Jason Merrill June 26, 2011, 2:13 p.m. UTC | #1
On 06/26/2011 10:00 AM, Jason Merrill wrote:
> Tested x86_64-pc-linux-gnu, applying to trunk. Jakub, should this go
> into 4.6.1 or .2?

I think it's fine to wait for .2, since a class with a non-trivial 
destructor is likely to also have a non-trivial, non-constexpr 
constructor, which would prevent A() from having a constant value.

Jason
Gabriel Dos Reis June 26, 2011, 2:53 p.m. UTC | #2
On Sun, Jun 26, 2011 at 9:00 AM, Jason Merrill <jason@redhat.com> wrote:
> The constant expression evaluation code was happily replacing an expression
> involving a temporary with its constant value even if the temporary had a
> destructor that needed to be run.

I thought we wanted literal types to have trivial destructor; did that change?

-- Gaby
Jakub Jelinek June 26, 2011, 4:50 p.m. UTC | #3
On Sun, Jun 26, 2011 at 10:13:23AM -0400, Jason Merrill wrote:
> On 06/26/2011 10:00 AM, Jason Merrill wrote:
> >Tested x86_64-pc-linux-gnu, applying to trunk. Jakub, should this go
> >into 4.6.1 or .2?
> 
> I think it's fine to wait for .2, since a class with a non-trivial
> destructor is likely to also have a non-trivial, non-constexpr
> constructor, which would prevent A() from having a constant value.

Yeah, I'd prefer to defer it for 4.6.2 and be able to roll the release tomorrow.

	Jakub
diff mbox

Patch

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.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3c347a4..3ceed90 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
 	}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f4aa350..5404c9f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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);
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C
new file mode 100644
index 0000000..b3fb9a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C
@@ -0,0 +1,9 @@ 
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i;
+  ~A();
+};
+
+constexpr int i = A().i;	// { dg-error "destruction" }
diff --git a/gcc/testsuite/g++.dg/init/ref19.C b/gcc/testsuite/g++.dg/init/ref19.C
new file mode 100644
index 0000000..ed78c93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ref19.C
@@ -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;
+}