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?
commit 0cbf28df997d109615545f113b01ac233d64879f
Author: Jason Merrill <ja...@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; }