diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2024-12-01 23:42:36 +0100 |
---|---|---|
committer | Marc Poulhiès <dkm@gcc.gnu.org> | 2024-12-13 09:36:02 +0100 |
commit | ad51d92159fa6788175b1fc05912669eb1ea1c0a (patch) | |
tree | 949dc84577166ace84441cbc6992a423ce3f3c7f /gcc | |
parent | 9f67d3d3f4db180933d3fe402efc190c885fdbca (diff) | |
download | gcc-ad51d92159fa6788175b1fc05912669eb1ea1c0a.zip gcc-ad51d92159fa6788175b1fc05912669eb1ea1c0a.tar.gz gcc-ad51d92159fa6788175b1fc05912669eb1ea1c0a.tar.bz2 |
ada: Improve expansion of nested conditional expressions in return statements
This arranges for nested conditional expressions in simple return statements
to have their expansion delayed until the returns are distributed into their
dependent expressions. This comprises the case of the elsif part of an if
expression present in the source code.
This also distributes qualified expressions into the dependent expressions
of conditional expressions, although this seems to occur rarely in practice.
gcc/ada/ChangeLog:
* exp_aggr.ads (Is_Delayed_Conditional_Expression): Move to...
* exp_aggr.adb (Is_Delayed_Conditional_Expression): Move to...
(Convert_To_Assignments): Use Delay_Conditional_Expressions_Between.
* exp_ch3.adb (Expand_N_Object_Declaration): Reset the Analyzed flag
by means of Unanalyze_Delayed_Conditional_Expression.
* exp_ch4.adb (Expand_N_Case_Expression): Likewise. Delay expanding
the expression if it is in the context of a simple return statement.
(Expand_N_If_Expression): Likewise.
(Expand_N_Qualified_Expression): Fold identical operand. Distribute
the expression into an operand that is a conditional expression with
expansion delayed.
(Process_Transient_In_Expression): Also test the parent node for the
presence of a simple return statement.
* exp_ch6.adb (Expand_Ctrl_Function_Call): Test the unconditional
parent node for the presence of a simple return statement.
* exp_util.ads (Delayed Expansion): New description.
(Delay_Conditional_Expressions_Between): New procedure.
(Is_Delayed_Conditional_Expression): ...here.
(Unanalyze_Delayed_Conditional_Expression): New procedure.
(Unconditional_Parent): New function.
* exp_util.adb (Find_Hook_Context): Take into account conditional
statements coming from conditional expressions.
(Within_Conditional_Expression): Likewise.
(Delay_Conditional_Expressions_Between): New procedure.
(Is_Delayed_Conditional_Expression): ...here.
(Unanalyze_Delayed_Conditional_Expression): New procedure.
(Unconditional_Parent): New function.
* sinfo.ads (Expansion_Delayed): Adjust description.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/exp_aggr.adb | 32 | ||||
-rw-r--r-- | gcc/ada/exp_aggr.ads | 4 | ||||
-rw-r--r-- | gcc/ada/exp_ch3.adb | 5 | ||||
-rw-r--r-- | gcc/ada/exp_ch4.adb | 200 | ||||
-rw-r--r-- | gcc/ada/exp_ch6.adb | 10 | ||||
-rw-r--r-- | gcc/ada/exp_util.adb | 112 | ||||
-rw-r--r-- | gcc/ada/exp_util.ads | 56 | ||||
-rw-r--r-- | gcc/ada/sinfo.ads | 4 |
8 files changed, 332 insertions, 91 deletions
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 9aabd58..344e4d1 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4217,7 +4217,7 @@ package body Exp_Aggr is -- First, climb the parent chain, looking through qualified expressions -- and dependent expressions of conditional expressions. - while True loop + loop case Nkind (Parent_Node) is when N_Case_Expression_Alternative => null; @@ -4276,25 +4276,13 @@ package body Exp_Aggr is or else Is_Build_In_Place_Aggregate_Return (Parent_Node) then - Node := N; - -- Mark the aggregate, as well as all the intermediate conditional -- expressions, as having expansion delayed. This will block the -- usual (bottom-up) expansion of the marked nodes and replace it -- with a top-down expansion from the parent node. - while Node /= Parent_Node loop - if Nkind (Node) in N_Aggregate - | N_Case_Expression - | N_Extension_Aggregate - | N_If_Expression - then - Set_Expansion_Delayed (Node); - end if; - - Node := Parent (Node); - end loop; - + Set_Expansion_Delayed (N); + Delay_Conditional_Expressions_Between (N, Parent_Node); return; end if; @@ -8650,7 +8638,7 @@ package body Exp_Aggr is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (Expression (Init_Stmt)) then - Set_Analyzed (Expression (Init_Stmt), False); + Unanalyze_Delayed_Conditional_Expression (Expression (Init_Stmt)); end if; Append_To (Blk_Stmts, Init_Stmt); @@ -8765,18 +8753,6 @@ package body Exp_Aggr is and then Expansion_Delayed (Unqual_N); end Is_Delayed_Aggregate; - --------------------------------------- - -- Is_Delayed_Conditional_Expression -- - --------------------------------------- - - function Is_Delayed_Conditional_Expression (N : Node_Id) return Boolean is - Unqual_N : constant Node_Id := Unqualify (N); - - begin - return Nkind (Unqual_N) in N_Case_Expression | N_If_Expression - and then Expansion_Delayed (Unqual_N); - end Is_Delayed_Conditional_Expression; - ---------------------------------------- -- Is_Static_Dispatch_Table_Aggregate -- ---------------------------------------- diff --git a/gcc/ada/exp_aggr.ads b/gcc/ada/exp_aggr.ads index 2bbaeb2..b14ab82 100644 --- a/gcc/ada/exp_aggr.ads +++ b/gcc/ada/exp_aggr.ads @@ -54,10 +54,6 @@ package Exp_Aggr is -- Returns True if N is an aggregate of some kind whose Expansion_Delayed -- flag is set (see sinfo for meaning of flag). - function Is_Delayed_Conditional_Expression (N : Node_Id) return Boolean; - -- Returns True if N is a conditional expression whose Expansion_Delayed - -- flag is set (see sinfo for meaning of flag). - function Is_Two_Pass_Aggregate (N : Node_Id) return Boolean; -- Return True if N is an aggregate that is to be expanded in two passes. -- This is the case if it consists only of iterated component associations diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 0c13ab5..2a0b0e6 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -7723,14 +7723,15 @@ package body Exp_Ch3 is if not Special_Ret_Obj then declare + Rhs : constant Node_Id := Relocate_Node (Expr); Assign : constant Node_Id := Make_Assignment_Statement (Loc, Name => New_Occurrence_Of (Def_Id, Loc), - Expression => Relocate_Node (Expr)); + Expression => Rhs); begin Set_Assignment_OK (Name (Assign)); - Set_Analyzed (Expression (Assign), False); + Unanalyze_Delayed_Conditional_Expression (Rhs); Set_No_Finalize_Actions (Assign); Insert_Action_After (Init_After, Assign); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 6d8aa0e..6f54b5c 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4986,22 +4986,6 @@ package body Exp_Ch4 is Scop : constant Entity_Id := Current_Scope; Typ : constant Entity_Id := Etype (N); - Optimize_Return_Stmt : constant Boolean := - Nkind (Par) = N_Simple_Return_Statement; - -- Small optimization: when the case expression appears in the context - -- of a simple return statement, expand into - - -- case X is - -- when A => - -- return AX; - -- when B => - -- return BX; - -- ... - -- end case; - - -- This makes the expansion much easier when expressions are calls to - -- build-in-place functions. - function Is_Copy_Type (Typ : Entity_Id) return Boolean; -- Return True if we can copy objects of this type when expanding a case -- expression. @@ -5039,9 +5023,39 @@ package body Exp_Ch4 is -- This makes the expansion much more efficient in the context of an -- aggregate converted into assignments. + Optimize_Return_Stmt : Boolean := False; + -- Small optimization: when the case expression appears in the context + -- of a simple return statement, expand into + + -- case X is + -- when A => + -- return AX; + -- when B => + -- return BX; + -- ... + -- end case; + + -- This makes the expansion much easier when expressions are calls to + -- build-in-place functions. + -- Start of processing for Expand_N_Case_Expression begin + -- If the expression is in the context of a simple return statement, + -- possibly through intermediate conditional expressions, we delay + -- expansion until the (immediate) parent is rewritten as a return + -- statement (or is already the return statement). + + if not Expansion_Delayed (N) then + declare + Uncond_Par : constant Node_Id := Unconditional_Parent (N); + begin + if Nkind (Uncond_Par) = N_Simple_Return_Statement then + Delay_Conditional_Expressions_Between (N, Uncond_Par); + end if; + end; + end if; + -- If the expansion of the expression has been delayed, we wait for the -- rewriting of its parent as an assignment or return statement; when -- that's done, we optimize the assignment or the return statement (the @@ -5051,8 +5065,8 @@ package body Exp_Ch4 is if Nkind (Par) = N_Assignment_Statement then Optimize_Assignment_Stmt := True; - elsif Optimize_Return_Stmt then - null; + elsif Nkind (Par) = N_Simple_Return_Statement then + Optimize_Return_Stmt := True; else return; @@ -5211,7 +5225,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (Alt_Expr) then - Set_Analyzed (Alt_Expr, False); + Unanalyze_Delayed_Conditional_Expression (Alt_Expr); end if; -- Generate: @@ -5226,7 +5240,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (Alt_Expr) then - Set_Analyzed (Alt_Expr, False); + Unanalyze_Delayed_Conditional_Expression (Alt_Expr); end if; -- Take the unrestricted access of the expression value for non- @@ -5470,20 +5484,6 @@ package body Exp_Ch4 is Par : constant Node_Id := Parent (N); Typ : constant Entity_Id := Etype (N); - Optimize_Return_Stmt : constant Boolean := - Nkind (Par) = N_Simple_Return_Statement; - -- Small optimization: when the if expression appears in the context of - -- a simple return statement, expand into - - -- if cond then - -- return then-expr - -- else - -- return else-expr; - -- end if; - - -- This makes the expansion much easier when expressions are calls to - -- build-in-place functions. - Force_Expand : constant Boolean := Is_Anonymous_Access_Actual (N); -- Determine if we are dealing with a special case of a conditional -- expression used as an actual for an anonymous access type which @@ -5537,9 +5537,38 @@ package body Exp_Ch4 is -- This makes the expansion much more efficient in the context of an -- aggregate converted into assignments. + Optimize_Return_Stmt : Boolean := False; + -- Small optimization: when the if expression appears in the context of + -- a simple return statement, expand into + + -- if cond then + -- return then-expr + -- else + -- return else-expr; + -- end if; + + -- This makes the expansion much easier when expressions are calls to + -- build-in-place functions. + -- Start of processing for Expand_N_If_Expression begin + -- If the expression is in the context of a simple return statement, + -- possibly through intermediate conditional expressions, we delay + -- expansion until the (immediate) parent is rewritten as a return + -- statement (or is already the return statement). Note that this + -- deals with the case of the elsif part of the if expression. + + if not Expansion_Delayed (N) then + declare + Uncond_Par : constant Node_Id := Unconditional_Parent (N); + begin + if Nkind (Uncond_Par) = N_Simple_Return_Statement then + Delay_Conditional_Expressions_Between (N, Uncond_Par); + end if; + end; + end if; + -- If the expansion of the expression has been delayed, we wait for the -- rewriting of its parent as an assignment or return statement; when -- that's done, we optimize the assignment or the return statement (the @@ -5549,8 +5578,8 @@ package body Exp_Ch4 is if Nkind (Par) = N_Assignment_Statement then Optimize_Assignment_Stmt := True; - elsif Optimize_Return_Stmt then - null; + elsif Nkind (Par) = N_Simple_Return_Statement then + Optimize_Return_Stmt := True; else return; @@ -5604,7 +5633,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (Expr) then - Set_Analyzed (Expr, False); + Unanalyze_Delayed_Conditional_Expression (Expr); end if; Insert_Actions (N, Actions); @@ -5642,7 +5671,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (Expression (New_Then)) then - Set_Analyzed (Expression (New_Then), False); + Unanalyze_Delayed_Conditional_Expression (Expression (New_Then)); end if; New_Else := New_Copy (Par); @@ -5651,7 +5680,7 @@ package body Exp_Ch4 is Set_Expression (New_Else, Relocate_Node (Elsex)); if Is_Delayed_Conditional_Expression (Expression (New_Else)) then - Set_Analyzed (Expression (New_Else), False); + Unanalyze_Delayed_Conditional_Expression (Expression (New_Else)); end if; If_Stmt := @@ -5685,7 +5714,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (New_Then) then - Set_Analyzed (New_Then, False); + Unanalyze_Delayed_Conditional_Expression (New_Then); end if; New_Else := Relocate_Node (Elsex); @@ -5694,7 +5723,7 @@ package body Exp_Ch4 is -- expansion has been delayed, analyze it again and expand it. if Is_Delayed_Conditional_Expression (New_Else) then - Set_Analyzed (New_Else, False); + Unanalyze_Delayed_Conditional_Expression (New_Else); end if; If_Stmt := @@ -10064,10 +10093,91 @@ package body Exp_Ch4 is ----------------------------------- procedure Expand_N_Qualified_Expression (N : Node_Id) is - Operand : constant Node_Id := Expression (N); - Target_Type : constant Entity_Id := Entity (Subtype_Mark (N)); + Loc : constant Source_Ptr := Sloc (N); + Operand : constant Node_Id := Expression (N); + Target_Type : constant Entity_Id := Entity (Subtype_Mark (N)); begin + -- Nothing to do if the operand is an identical qualified expression + + if Nkind (Operand) = N_Qualified_Expression + and then Entity (Subtype_Mark (Operand)) = Target_Type + then + Rewrite (N, Relocate_Node (Operand)); + return; + + -- An allocator expects a qualified expression in all cases + + elsif Nkind (Parent (N)) = N_Allocator then + null; + + -- Distribute the qualified expression into the dependent expressions + -- of a delayed conditional expression. The goal is to enable further + -- optimizations, for example within a return statement, by exposing + -- the conditional expression. + + elsif Nkind (Operand) = N_Case_Expression + and then Expansion_Delayed (Operand) + then + declare + New_Alts : constant List_Id := New_List; + New_Case : constant Node_Id := + Make_Case_Expression (Loc, + Expression => Relocate_Node (Expression (Operand)), + Alternatives => New_Alts); + + Alt : Node_Id; + New_Alt : Node_Id; + + begin + Alt := First (Alternatives (Operand)); + while Present (Alt) loop + New_Alt := + Make_Case_Expression_Alternative (Sloc (Alt), + Discrete_Choices => Discrete_Choices (Alt), + Expression => + Make_Qualified_Expression (Loc, + Subtype_Mark => New_Occurrence_Of (Target_Type, Loc), + Expression => Relocate_Node (Expression (Alt)))); + Append_To (New_Alts, New_Alt); + Set_Actions (New_Alt, Actions (Alt)); + + Next (Alt); + end loop; + + Rewrite (N, New_Case); + Analyze_And_Resolve (N); + return; + end; + + elsif Nkind (Operand) = N_If_Expression + and then Expansion_Delayed (Operand) + then + declare + Cond : constant Node_Id := First (Expressions (Operand)); + Thenx : constant Node_Id := Next (Cond); + Elsex : constant Node_Id := Next (Thenx); + New_If : constant Node_Id := + Make_If_Expression (Loc, + Expressions => New_List ( + Relocate_Node (Cond), + Make_Qualified_Expression (Loc, + Subtype_Mark => New_Occurrence_Of (Target_Type, Loc), + Expression => Relocate_Node (Thenx)), + Make_Qualified_Expression (Loc, + Subtype_Mark => New_Occurrence_Of (Target_Type, Loc), + Expression => Relocate_Node (Elsex)))); + + begin + Set_Then_Actions (New_If, Then_Actions (Operand)); + Set_Else_Actions (New_If, Else_Actions (Operand)); + + Rewrite (N, New_If); + Analyze_And_Resolve (N); + return; + end; + end if; + -- Do validity check if validity checking operands if Validity_Checks_On and Validity_Check_Operands then @@ -14298,7 +14408,9 @@ package body Exp_Ch4 is -- insert the finalization call after the return statement as -- this will render it unreachable. - if Nkind (Fin_Context) = N_Simple_Return_Statement then + if Nkind (Fin_Context) = N_Simple_Return_Statement + or else Nkind (Parent (Expr)) = N_Simple_Return_Statement + then null; -- Finalize the object after the context has been evaluated diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index ec105f0..39cc9ab 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -5368,13 +5368,7 @@ package body Exp_Ch6 is -- Note that simple return statements are distributed into conditional -- expressions but we may be invoked before this distribution is done. - if Nkind (Par) = N_Simple_Return_Statement - or else (Nkind (Par) = N_If_Expression - and then Nkind (Parent (Par)) = N_Simple_Return_Statement) - or else (Nkind (Par) = N_Case_Expression_Alternative - and then - Nkind (Parent (Parent (Par))) = N_Simple_Return_Statement) - then + if Nkind (Unconditional_Parent (N)) = N_Simple_Return_Statement then return; end if; @@ -5402,7 +5396,7 @@ package body Exp_Ch6 is return; end if; - -- Avoid expansions to catch an error when the function call is on the + -- Avoid expansion to catch the error when the function call is on the -- left-hand side of an assignment. if Nkind (Par) = N_Assignment_Statement and then N = Name (Par) then diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index b431336..27d8233 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -5033,6 +5033,23 @@ package body Exp_Util is return Decls; end Current_Sem_Unit_Declarations; + ------------------------------------------- + -- Delay_Conditional_Expressions_Between -- + ------------------------------------------- + + procedure Delay_Conditional_Expressions_Between (From, To : Node_Id) is + N : Node_Id := From; + + begin + while N /= To loop + if Nkind (N) in N_Case_Expression | N_If_Expression then + Set_Expansion_Delayed (N); + end if; + + N := Parent (N); + end loop; + end Delay_Conditional_Expressions_Between; + ----------------------- -- Duplicate_Subexpr -- ----------------------- @@ -6716,8 +6733,14 @@ package body Exp_Util is Par := N; Top := N; while Present (Par) loop - if Nkind (Original_Node (Par)) in - N_Case_Expression | N_If_Expression + if Nkind (Original_Node (Par)) in N_Case_Expression + | N_If_Expression + then + Top := Par; + + elsif Nkind (Par) in N_Case_Statement + | N_If_Statement + and then From_Conditional_Expression (Par) then Top := Par; @@ -8557,6 +8580,18 @@ package body Exp_Util is and then Is_Formal (Entity (N))); end Is_Conversion_Or_Reference_To_Formal; + --------------------------------------- + -- Is_Delayed_Conditional_Expression -- + --------------------------------------- + + function Is_Delayed_Conditional_Expression (N : Node_Id) return Boolean is + Unqual_N : constant Node_Id := Unqualify (N); + + begin + return Nkind (Unqual_N) in N_Case_Expression | N_If_Expression + and then Expansion_Delayed (Unqual_N); + end Is_Delayed_Conditional_Expression; + -------------------------------------------------- -- Is_Expanded_Class_Wide_Interface_Object_Decl -- -------------------------------------------------- @@ -14656,6 +14691,62 @@ package body Exp_Util is end if; end Type_May_Have_Bit_Aligned_Components; + ---------------------------------------------- + -- Unanalyze_Delayed_Conditional_Expression -- + ---------------------------------------------- + + procedure Unanalyze_Delayed_Conditional_Expression (N : Node_Id) is + Expr : Node_Id := N; + + begin + -- Is_Delayed_Conditional_Expression looks through qualified expressions + -- surrounding conditional expressions, so we need to reset the Analyzed + -- flag on them as well. + + loop + Set_Analyzed (Expr, False); + + exit when Nkind (Expr) in N_Case_Expression | N_If_Expression; + + pragma Assert (Nkind (Expr) = N_Qualified_Expression); + Expr := Expression (Expr); + end loop; + end Unanalyze_Delayed_Conditional_Expression; + + -------------------------- + -- Unconditional_Parent -- + -------------------------- + + function 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 + 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 N_Qualified_Expression => + null; + + when others => + exit; + end case; + + Node := Parent_Node; + Parent_Node := Parent (Node); + end loop; + + return Parent_Node; + end Unconditional_Parent; + ------------------------------- -- Update_Primitives_Mapping -- ------------------------------- @@ -14682,8 +14773,9 @@ package body Exp_Util is begin -- Locate an enclosing case or if expression. Note that these constructs - -- can be expanded into Expression_With_Actions, hence the test of the - -- original node. + -- can be rewritten as Expression_With_Actions nodes, hence the test of + -- the original node. Moreover, we need to take into account conditional + -- statements synthesized out of these expressions. Nod := N; Par := Parent (Nod); @@ -14699,6 +14791,18 @@ package body Exp_Util is then return True; + elsif Nkind (Par) = N_Case_Statement + and then From_Conditional_Expression (Par) + and then Nod /= Expression (Par) + then + return True; + + elsif Nkind (Par) = N_If_Statement + and then From_Conditional_Expression (Par) + and then Nod /= Condition (Par) + then + return True; + -- Stop at contexts where temporaries may be contained elsif Nkind (Par) in N_Aggregate diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index b906dcc..fc70ac5 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -174,6 +174,57 @@ package Exp_Util is procedure Insert_Library_Level_Actions (L : List_Id); -- Similar, but inserts a list of actions + ------------------------ + -- Delayed Expansion -- + ------------------------ + + -- The default, bottom-up expansion of expressions is not appropriate for + -- some specific situations, either because it would generate problematic + -- constructs in the expanded code, for example temporaries of a limited + -- type, or because it would generate superfluous copy operations. These + -- situations involve either aggregates or conditional expressions (or a + -- combination of them) of composite types: + + -- 1. For aggregates, the default expansion model is to instantiate the + -- anonymous object where elaboration is performed, in other words to + -- create a temporary. This can be directly avoided if the aggregate + -- is the initialization expression of an object, but cannot be if the + -- aggregate is nested in another aggregate, or else is the dependent + -- expression of a conditional expression. + + -- 2. For (most) conditional expressions of composite types, the default + -- expansion model is to take 'Unrestricted_Access of their dependent + -- expressions and to replace them with the dereference of the access + -- value designating the dependent expression chosen by the condition. + -- Now taking 'Unrestricted_Access of an expression, for example again + -- an aggregate or a function call, forces the creation of a temporary + -- to hold the value of the expression. + + -- In these specific situations, it is desirable, if not required, to delay + -- the expansion of the expression until after that of the parent construct + -- has started or has completed, so that it can drive this expansion in the + -- first case or completely rewrite the expression in the second case. + + -- This is achieved by means of the Expansion_Delayed flag that may be set + -- on aggregates and conditional expressions: when the above situations are + -- recognized, expansion is blocked, the flag is set, and Expand returns + -- after setting the Analyzed flag on the expression as usual, which means + -- that it is up to the parent construct either to perform the expansion of + -- the expression directly (case of nested aggregates), or to reset the + -- Analyzed flag on the expression so that Expand can give it another try + -- in a modified context (case of conditional expressions). + + procedure Delay_Conditional_Expressions_Between (From, To : Node_Id); + -- Mark all the conditional expressions in the tree between From and To + -- as having their expansion delayed (From included, To excluded). + + function Is_Delayed_Conditional_Expression (N : Node_Id) return Boolean; + -- Returns True if N is a conditional expression whose Expansion_Delayed + -- flag is set. + + procedure Unanalyze_Delayed_Conditional_Expression (N : Node_Id); + -- Schedule the reanalysis of the delayed conditional expression N + ----------------------- -- Other Subprograms -- ----------------------- @@ -1286,6 +1337,11 @@ package Exp_Util is -- is conservative, in that a result of False is decisive. A result of True -- means that such a component may or may not be present. + 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, and that is not + -- a qualified expression, whose expression is N, recursively. + procedure Update_Primitives_Mapping (Inher_Id : Entity_Id; Subp_Id : Entity_Id); diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 09385e9..64f6112 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -1281,7 +1281,9 @@ package Sinfo is -- target of the assignment or initialization is used to generate the -- left-hand side of individual assignment to each subcomponent. -- Also set on conditional expressions whose dependent expressions are - -- nested aggregates, in order to avoid creating a temporary for them. + -- nested aggregates (recursively), or which are expressions of simple + -- return statements (recursively again), in order to avoid creating a + -- temporary for them. -- Expression_Copy -- Present in N_Pragma_Argument_Association nodes. Contains a copy of the |