Blob Blame History Raw
2004-12-01  Alexandre Oliva  <aoliva@redhat.com>

	* calls.c (initialize_argument_information): Treat NOP_EXPR
	of TARGET_EXPR the same as TARGET_EXPR itself.

2005-01-03  Jakub Jelinek  <jakub@redhat.com>

	* g++.dg/other/destruct1.C: New test.

--- gcc/calls.c.jj	2003-09-16 16:57:44.000000000 +0200
+++ gcc/calls.c	2005-01-03 11:00:11.604022891 +0100
@@ -1239,7 +1239,10 @@ initialize_argument_information (num_act
 					   args[i].tree_value);
 	      type = build_pointer_type (type);
 	    }
-	  else if (TREE_CODE (args[i].tree_value) == TARGET_EXPR)
+	  else if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
+		   || (TREE_CODE (args[i].tree_value) == NOP_EXPR
+		       && (TREE_CODE (TREE_OPERAND (args[i].tree_value, 0))
+			   == TARGET_EXPR)))
 	    {
 	      /* In the V3 C++ ABI, parameters are destroyed in the caller.
 		 We implement this by passing the address of the temporary
--- gcc/testsuite/g++.dg/other/destruct1.C.jj	2005-01-03 11:02:26.440730539 +0100
+++ gcc/testsuite/g++.dg/other/destruct1.C	2005-01-03 11:02:44.971392180 +0100
@@ -0,0 +1,41 @@
+// { dg-do run }
+
+int i, j, k;
+extern "C" void abort ();
+
+struct S
+{
+  S () { ++i; }
+  S (const S &x) { ++k; }
+  S &operator= (const S &x) { abort (); return *this; }
+  ~S () { ++j; }
+};
+
+const S foo ()
+{
+  S s;
+  return s;
+}
+
+S bar (S x)
+{
+  return S ();
+}
+
+S baz (S x)
+{
+  return x;
+}
+
+void test ()
+{
+  S a = bar (foo ());
+  S b = baz (foo ());
+}
+
+int main ()
+{
+  test ();
+  if (i != 3 || j != 4 || k != 1)
+    abort ();
+}