aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cgraphunit.c6
-rw-r--r--gcc/function.c12
-rw-r--r--gcc/testsuite/gnat.dg/thunk1.adb9
-rw-r--r--gcc/testsuite/gnat.dg/thunk1_pkg1.ads7
-rw-r--r--gcc/testsuite/gnat.dg/thunk1_pkg2.adb10
-rw-r--r--gcc/testsuite/gnat.dg/thunk1_pkg2.ads14
6 files changed, 52 insertions, 6 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 26d3995..bedb6e2 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2171,7 +2171,10 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
}
}
else
- gimple_call_set_tail (call, true);
+ {
+ gimple_call_set_tail (call, true);
+ cfun->tail_call_marked = true;
+ }
/* Build return value. */
if (!DECL_BY_REFERENCE (resdecl))
@@ -2184,6 +2187,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
else
{
gimple_call_set_tail (call, true);
+ cfun->tail_call_marked = true;
remove_edge (single_succ_edge (bb));
}
diff --git a/gcc/function.c b/gcc/function.c
index de59479..c4c9930 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -3322,13 +3322,15 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
else
emit_move_insn (parmreg, validated_mem);
- /* If we were passed a pointer but the actual value can safely live
- in a register, retrieve it and use it directly. */
+ /* If we were passed a pointer but the actual value can live in a register,
+ retrieve it and use it directly. Note that we cannot use nominal_mode,
+ because it will have been set to Pmode above, we must use the actual mode
+ of the parameter instead. */
if (data->arg.pass_by_reference && TYPE_MODE (TREE_TYPE (parm)) != BLKmode)
{
- /* We can't use nominal_mode, because it will have been set to
- Pmode above. We must use the actual mode of the parm. */
- if (use_register_for_decl (parm))
+ /* Use a stack slot for debugging purposes, except if a tail call is
+ involved because this would create a dangling reference. */
+ if (use_register_for_decl (parm) || cfun->tail_call_marked)
{
parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
mark_user_reg (parmreg);
diff --git a/gcc/testsuite/gnat.dg/thunk1.adb b/gcc/testsuite/gnat.dg/thunk1.adb
new file mode 100644
index 0000000..278e023
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/thunk1.adb
@@ -0,0 +1,9 @@
+-- { dg-do run }
+
+with Thunk1_Pkg1; use Thunk1_Pkg1;
+
+procedure Thunk1 is
+ D: Derived;
+begin
+ D.Op ("Message");
+end;
diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg1.ads b/gcc/testsuite/gnat.dg/thunk1_pkg1.ads
new file mode 100644
index 0000000..edb3eac
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/thunk1_pkg1.ads
@@ -0,0 +1,7 @@
+with Thunk1_Pkg2; use Thunk1_Pkg2;
+
+package Thunk1_Pkg1 is
+
+ type Derived is new Ext with null record;
+
+end Thunk1_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg2.adb b/gcc/testsuite/gnat.dg/thunk1_pkg2.adb
new file mode 100644
index 0000000..71ad45d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/thunk1_pkg2.adb
@@ -0,0 +1,10 @@
+package body Thunk1_Pkg2 is
+
+ procedure Op (This : in out Ext; S : String) is
+ begin
+ if S /= "Message" then
+ raise Program_Error;
+ end if;
+ end;
+
+end Thunk1_Pkg2;
diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg2.ads b/gcc/testsuite/gnat.dg/thunk1_pkg2.ads
new file mode 100644
index 0000000..82a48d5
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/thunk1_pkg2.ads
@@ -0,0 +1,14 @@
+package Thunk1_Pkg2 is
+
+ type Root is tagged record
+ I : Integer;
+ end record;
+
+ type Iface is interface;
+ procedure Op (This : in out Iface; S : String) is abstract;
+
+ type Ext is new Root and Iface with null record;
+
+ procedure Op (This : in out Ext; S : String);
+
+end Thunk1_Pkg2;