diff mbox

PATCHes for c++/48118 (accepts-invalid with volatile class), 23372 and 35315

Message ID 4D837442.6030807@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 18, 2011, 3:03 p.m. UTC
48118 turned out to be caused by the patch for 23372; if we skip the 
ck_rvalue, then we never determine that there is no suitable constructor 
to use for copying from a volatile variable.  Removing that code fixes 
48118.

But that reintroduces 23372 (redundant copying of PODs on argument 
passing), so we need to fix that differently.  The best way to do that 
seems to be stripping the offending TARGET_EXPR in gimplify_arg, since 
the bug is due to a limitation of GIMPLE.

The fix for 48118 also breaks part of attrib32.C; Doug had added a bit 
to the test to check that duplicating a union in order to add 
transparent_union to a typedef worked properly, and it starts blowing up 
when we stop stripping the ck_rvalue.  But we shouldn't be duplicating 
the union in the first place, as it breaks the C++ type system; the 
point of my fix for 35315 was to support the uses of transparent_union 
in C headers without requiring that kind of duplication.  So the third 
patch disables that duplication in C++ mode; if the typedef isn't a 
naming typedef, we just ignore the attribute.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit a0880749cf975786e886c5799a67ac3ff27d606c
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 18 10:33:03 2011 -0400

    	PR c++/48118
    	* call.c (build_over_call): Don't skip ck_rvalue.
commit 65f231e2f988d3a944712509dcaeb52c37cf6a07
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 18 10:31:54 2011 -0400

    	PR c++/23372
    	* gimplify.c (gimplify_arg): Strip redundant TARGET_EXPR.

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 400493f..0b314a0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2255,7 +2255,17 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
   if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
     test = is_gimple_val, fb = fb_rvalue;
   else
-    test = is_gimple_lvalue, fb = fb_either;
+    {
+      test = is_gimple_lvalue, fb = fb_either;
+      /* Also strip a TARGET_EXPR that would force an extra copy.  */
+      if (TREE_CODE (*arg_p) == TARGET_EXPR)
+	{
+	  tree init = TARGET_EXPR_INITIAL (*arg_p);
+	  if (init
+	      && !VOID_TYPE_P (TREE_TYPE (init)))
+	    *arg_p = init;
+	}
+    }
 
   /* If this is a variable sized type, we must remember the size.  */
   maybe_with_size_expr (arg_p);
diff --git a/gcc/testsuite/g++.dg/opt/pr23372.C b/gcc/testsuite/g++.dg/opt/pr23372.C
new file mode 100644
index 0000000..9be4c9c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr23372.C
@@ -0,0 +1,15 @@
+// PR c++/23372
+// { dg-options -fdump-tree-gimple }
+
+// There shouldn't be an assignment to a temporary in the GIMPLE,
+// as that represents a redundant copy.
+// { dg-final { scan-tree-dump-not "=" gimple } }
+
+struct A {
+  int a[1000];
+  //A(A const &);
+};
+void f(A);
+void g(A *a) { f(*a); }
+
+// { dg-final { cleanup-tree-dump gimple } }
commit 459e2323d965f57f6b4ce5e8c0318b511cb8fb72
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 18 00:33:19 2011 -0400

    	PR c++/35315
    	* c-common.c (handle_transparent_union_attribute): Don't
    	make a duplicate type in C++.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6674c58..799f815 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6152,6 +6152,7 @@ handle_transparent_union_attribute (tree *node, tree name,
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
 	{
 	  if (TYPE_FIELDS (type) == NULL_TREE
+	      || c_dialect_cxx ()
 	      || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type)))
 	    goto ignored;
 
diff --git a/gcc/testsuite/g++.dg/ext/attrib32.C b/gcc/testsuite/g++.dg/ext/attrib32.C
index 77f71de..e4dfe4e 100644
--- a/gcc/testsuite/g++.dg/ext/attrib32.C
+++ b/gcc/testsuite/g++.dg/ext/attrib32.C
@@ -10,10 +10,10 @@ void bar()
   foo(0);
 }
 
-typedef union U1 { int i; } U2 __attribute__((transparent_union));
+typedef union U1 { int i; } U2 __attribute__((transparent_union)); // { dg-warning "ignored" }
 
-static void foo2(U1) {}
-static void foo2(U2) {}
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
 
 void bar2(U1 u1, U2 u2)
 {
diff mbox

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d040ec8..93383c6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6168,12 +6168,6 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 
       conv = convs[i];
 
-      /* Don't make a copy here if build_call is going to.  */
-      if (conv->kind == ck_rvalue
-	  && COMPLETE_TYPE_P (complete_type (type))
-	  && !TREE_ADDRESSABLE (type))
-	conv = conv->u.next;
-
       /* Warn about initializer_list deduction that isn't currently in the
 	 working draft.  */
       if (cxx_dialect > cxx98
diff --git a/gcc/testsuite/g++.dg/overload/volatile1.C b/gcc/testsuite/g++.dg/overload/volatile1.C
new file mode 100644
index 0000000..baf467d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/volatile1.C
@@ -0,0 +1,14 @@ 
+// PR c++/48118
+// { dg-prune-output "note" }
+
+struct A { };
+
+void f (A);			// { dg-error "argument 1" }
+void (*g)(A);
+
+int main()
+{
+  volatile A a;
+  f(a);				// { dg-error "no match" }
+  g(a);				// { dg-error "no match" }
+}