diff mbox

RFA: cgraph PATCH for c++/59645 (ICE with covariant virtual function with volatile parameter)

Message ID 52E9CAF5.1090806@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 30, 2014, 3:45 a.m. UTC
If a parameter of a covariant virtual function is volatile, we can't 
just use the parameter directly in the call we build for the thunk, or 
the gimple verifier will complain.  We need to copy it into a temporary 
first.

Tested x86_64-pc-linux-gnu.  OK for trunk?

Comments

Richard Biener Jan. 30, 2014, 1:33 p.m. UTC | #1
On Thu, Jan 30, 2014 at 4:45 AM, Jason Merrill <jason@redhat.com> wrote:
> If a parameter of a covariant virtual function is volatile, we can't just
> use the parameter directly in the call we build for the thunk, or the gimple
> verifier will complain.  We need to copy it into a temporary first.
>
> Tested x86_64-pc-linux-gnu.  OK for trunk?

Please use

  if (!is_gimple_val (arg))

instead of testing TREE_THIS_VOLATILE, then it's also obvious that
you can remove the assert (I suppose it would trip for an argument
of volatile struct X for example?).

Ok with that change.

Thanks,
Richard.
diff mbox

Patch

commit 0cbf28df997d109615545f113b01ac233d64879f
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 29 20:47:54 2014 -0500

    	PR c++/59645
    	* cgraphunit.c (expand_thunk): Copy volatile arg to a temporary.

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index d22265a..38c91df 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1592,7 +1592,18 @@  expand_thunk (struct cgraph_node *node, bool output_asm_thunks)
 
       if (nargs)
         for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
-	  vargs.quick_push (arg);
+	  {
+	    tree tmp = arg;
+	    if (TREE_THIS_VOLATILE (TREE_TYPE (arg)))
+	      {
+		gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
+		tmp = create_tmp_reg (TYPE_MAIN_VARIANT
+				      (TREE_TYPE (arg)), "arg");
+		gimple stmt = gimple_build_assign (tmp, arg);
+		gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
+	      }
+	    vargs.quick_push (tmp);
+	  }
       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
       node->callees->call_stmt = call;
       gimple_call_set_from_thunk (call, true);
diff --git a/gcc/testsuite/g++.dg/inherit/covariant21.C b/gcc/testsuite/g++.dg/inherit/covariant21.C
new file mode 100644
index 0000000..42cdf87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/covariant21.C
@@ -0,0 +1,17 @@ 
+// PR c++/59645
+
+struct A { virtual ~A(); };
+struct B { virtual ~B(); };
+struct C : A, B {};
+
+struct X
+{
+  virtual B* foo(volatile int);
+};
+
+struct Y : X
+{
+  virtual C* foo(volatile int);
+};
+
+C* Y::foo(volatile int) { return 0; }