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 <ja...@redhat.com>
Date:   Fri Mar 18 10:33:03 2011 -0400

        PR c++/48118
        * call.c (build_over_call): Don't skip ck_rvalue.

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" }
+}
commit 65f231e2f988d3a944712509dcaeb52c37cf6a07
Author: Jason Merrill <ja...@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 <ja...@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)
 {

Reply via email to