diff --git a/gcc/testsuite/gnat.dg/lto28.adb b/gcc/testsuite/gnat.dg/lto28.adb new file mode 100644 index 0000000000000000000000000000000000000000..f5f1804af866bd71df38bb6929391586953c37d8 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto28.adb @@ -0,0 +1,9 @@ +-- { dg-do run } +-- { dg-options "-O -flto" { target lto } } + +with Lto28_Pkg1; + +procedure Lto28 is +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/lto28_pkg1.ads b/gcc/testsuite/gnat.dg/lto28_pkg1.ads new file mode 100644 index 0000000000000000000000000000000000000000..8205cdae7315ad3f85e514af62d7a4defde21e0d --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto28_pkg1.ads @@ -0,0 +1,5 @@ +with Lto28_Pkg2; + +package Lto28_Pkg1 is + package I is new Lto28_Pkg2.G; +end Lto28_Pkg1; diff --git a/gcc/testsuite/gnat.dg/lto28_pkg2.adb b/gcc/testsuite/gnat.dg/lto28_pkg2.adb new file mode 100644 index 0000000000000000000000000000000000000000..f592d119c40f46b5b5e24cb33ac576a8b0c1e816 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto28_pkg2.adb @@ -0,0 +1,10 @@ +package body Lto28_Pkg2 is + + function F return Lto28_Pkg3.Q_Rec is + begin + return Result : Lto28_Pkg3.Q_Rec := Lto28_Pkg3.Default_Q_Rec do + Result.A := 1.0; + end return; + end; + +end Lto28_Pkg2; diff --git a/gcc/testsuite/gnat.dg/lto28_pkg2.ads b/gcc/testsuite/gnat.dg/lto28_pkg2.ads new file mode 100644 index 0000000000000000000000000000000000000000..ba2d0ae5781c9e7904c387877e740c9910d19634 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto28_pkg2.ads @@ -0,0 +1,11 @@ +with Lto28_Pkg3; + +package Lto28_Pkg2 is + + function F return Lto28_Pkg3.Q_Rec; + + generic + Q_Conf : Lto28_Pkg3.Q_Rec := F; + package G is end; + +end Lto28_Pkg2; diff --git a/gcc/testsuite/gnat.dg/lto28_pkg3.ads b/gcc/testsuite/gnat.dg/lto28_pkg3.ads new file mode 100644 index 0000000000000000000000000000000000000000..026ffb9f97c44bdbb940c9e3012e9b61c6cd915f --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto28_pkg3.ads @@ -0,0 +1,19 @@ +package Lto28_Pkg3 is + + type Discr_Type is (P, Q); + + type Rec (Discr : Discr_Type) is record + case Discr is + when Q => + A : Duration := 0.0; + B : Duration := 0.0; + when P => + null; + end case; + end record; + + subtype Q_Rec is Rec (Q); + + Default_Q_Rec : constant Q_Rec := (Discr => Q, others => <>); + +end Lto28_Pkg3; diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index f31a34ac41055db3135211c4cf53bcca1c6763aa..037fd1e946ae1e2bc6c99760a98daa6d69412d1c 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -5130,9 +5130,23 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, if (DECL_P (modify_dest)) suppress_warning (modify_dest, OPT_Wuninitialized); + /* If we have a return slot, we can assign it the result directly, + except in the case where it is a global variable that is only + written to because, the callee being permitted to read or take + the address of its DECL_RESULT, this could invalidate the flag + on the global variable; instead we preventively remove the store, + which would have happened later if the call was not inlined. */ if (gimple_call_return_slot_opt_p (call_stmt)) { - return_slot = modify_dest; + tree base = get_base_address (modify_dest); + + if (VAR_P (base) + && (TREE_STATIC (base) || DECL_EXTERNAL (base)) + && varpool_node::get (base)->writeonly) + return_slot = NULL; + else + return_slot = modify_dest; + modify_dest = NULL; } }