From: Eric Botcazou <ebotca...@adacore.com> A qualified expression around a function call may cause a temporary to be created and, therefore, cannot be bypassed in Expand_Ctrl_Function_Call.
gcc/ada/ChangeLog: * exp_util.ads (Unqualified_Unconditional_Parent): New function. * exp_util.adb (Unconditional_Parent): Do not look through qualified expressions. (Unqualified_Unconditional_Parent): New function identical to the original Unconditional_Parent. * exp_aggr.adb (Convert_To_Assignments): Replace Unconditional_Parent with Unqualified_Unconditional_Parent. (Expand_Array_Aggregate): Likewse. * exp_ch4.adb (Expand_N_Case_Expression): Likewise. (Expand_N_If_Expression): Likewise. * exp_ch6.adb (Expand_Ctrl_Function_Call): Do not bypass an enclosing qualified expression in the parent chain. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/exp_aggr.adb | 4 ++-- gcc/ada/exp_ch4.adb | 6 ++++-- gcc/ada/exp_ch6.adb | 5 ++++- gcc/ada/exp_util.adb | 33 ++++++++++++++++++++++++++++++++- gcc/ada/exp_util.ads | 4 ++++ 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 6b4f4a19d1f9..d62b7351e862 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4283,7 +4283,7 @@ package body Exp_Aggr is -- Set the Expansion_Delayed flag in the cases where the transformation -- will be done top down from above. - Parent_Node := Unconditional_Parent (N); + Parent_Node := Unqualified_Unconditional_Parent (N); if -- Internal aggregates (transformed when expanding the parent), @@ -6254,7 +6254,7 @@ package body Exp_Aggr is -- Set the Expansion_Delayed flag in the cases where the transformation -- will be done top down from above. - Parent_Node := Unconditional_Parent (N); + Parent_Node := Unqualified_Unconditional_Parent (N); if -- Internal aggregates (transformed when expanding the parent), diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 23a59de6f872..8fba1c4e71fa 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -5198,7 +5198,8 @@ package body Exp_Ch4 is if not Expansion_Delayed (N) then declare - Uncond_Par : constant Node_Id := Unconditional_Parent (N); + Uncond_Par : constant Node_Id := + Unqualified_Unconditional_Parent (N); begin if Nkind (Uncond_Par) = N_Simple_Return_Statement or else Is_Optimizable_Declaration (Uncond_Par) @@ -5807,7 +5808,8 @@ package body Exp_Ch4 is if not Expansion_Delayed (N) then declare - Uncond_Par : constant Node_Id := Unconditional_Parent (N); + Uncond_Par : constant Node_Id := + Unqualified_Unconditional_Parent (N); begin if Nkind (Uncond_Par) = N_Simple_Return_Statement or else Is_Optimizable_Declaration (Uncond_Par) diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 32e96bed2349..5056b1f990fa 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -5793,11 +5793,14 @@ package body Exp_Ch6 is is Par : constant Node_Id := Parent (N); Uncond_Par : constant Node_Id := Unconditional_Parent (N); + -- Beware that a qualified expression around a function call cannot be + -- considered as transparent (like around an aggregate) because it may + -- cause a temporary to be created. begin -- Optimization: if the returned value is returned again, then no need -- to copy/readjust/finalize, we can just pass the value through (see - -- Expand_N_Simple_Return_Statement), and thus no attachment is needed. + -- Expand_Simple_Function_Return), and thus no attachment is needed. -- Note that simple return statements are distributed into conditional -- expressions, but we may be invoked before this distribution is done. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 6ce6c0cd81d6..4135e24424d3 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -14903,6 +14903,37 @@ package body Exp_Util is Node : Node_Id := N; Parent_Node : Node_Id := Parent (Node); + begin + loop + case Nkind (Parent_Node) is + when N_Case_Expression_Alternative => + null; + + when N_Case_Expression => + exit when Node = Expression (Parent_Node); + + when N_If_Expression => + exit when Node = First (Expressions (Parent_Node)); + + when others => + exit; + end case; + + Node := Parent_Node; + Parent_Node := Parent (Node); + end loop; + + return Parent_Node; + end Unconditional_Parent; + + -------------------------------------- + -- Unqualified_Unconditional_Parent -- + -------------------------------------- + + function Unqualified_Unconditional_Parent (N : Node_Id) return Node_Id is + Node : Node_Id := N; + Parent_Node : Node_Id := Parent (Node); + begin loop case Nkind (Parent_Node) is @@ -14927,7 +14958,7 @@ package body Exp_Util is end loop; return Parent_Node; - end Unconditional_Parent; + end Unqualified_Unconditional_Parent; ------------------------------- -- Update_Primitives_Mapping -- diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 4226fcc93777..b7d8a185f4bd 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -1344,6 +1344,10 @@ package Exp_Util is function Unconditional_Parent (N : Node_Id) return Node_Id; -- Return the first parent of arbitrary node N that is not a conditional + -- expression, one of whose dependent expressions is N, recursively. + + function Unqualified_Unconditional_Parent (N : Node_Id) return Node_Id; + -- Return the first parent of arbitrary node N that is not a conditional -- expression, one of whose dependent expressions is N, and that is not -- a qualified expression, whose expression is N, recursively. -- 2.43.0