diff options
-rw-r--r-- | gcc/ada/einfo.ads | 4 | ||||
-rw-r--r-- | gcc/ada/exp_aggr.adb | 123 | ||||
-rw-r--r-- | gcc/ada/exp_ch3.adb | 31 | ||||
-rw-r--r-- | gcc/ada/exp_ch4.adb | 368 | ||||
-rw-r--r-- | gcc/ada/exp_ch6.adb | 14 | ||||
-rw-r--r-- | gcc/ada/exp_ch7.adb | 3 | ||||
-rw-r--r-- | gcc/ada/exp_util.adb | 41 | ||||
-rw-r--r-- | gcc/ada/exp_util.ads | 3 | ||||
-rw-r--r-- | gcc/ada/sem_ch3.adb | 15 |
9 files changed, 455 insertions, 147 deletions
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 1a8760c..0254652 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -2804,6 +2804,10 @@ package Einfo is -- case of private and incomplete types, this flag is set in both the -- partial view and the full view. +-- This flag is also set on the Master_Node objects generated by the +-- compiler (see Finalization_Master_Node above) to indicate that the +-- associated finalizable object has relaxed finalization semantics. + -- Is_Initial_Condition_Procedure -- Defined in functions and procedures. Set for a generated procedure -- which verifies the assumption of pragma Initial_Condition at run time. diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 344e4d1..1f1f580 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4119,7 +4119,6 @@ package body Exp_Aggr is -- Local variables - Parent_Kind : Node_Kind; Parent_Node : Node_Id; -- Start of processing for In_Place_Assign_OK @@ -4132,11 +4131,9 @@ package body Exp_Aggr is end if; Parent_Node := Parent (N); - Parent_Kind := Nkind (Parent_Node); - if Parent_Kind = N_Qualified_Expression then + if Nkind (Parent_Node) = N_Qualified_Expression then Parent_Node := Parent (Parent_Node); - Parent_Kind := Nkind (Parent_Node); end if; -- On assignment, sliding can take place, so we cannot do the @@ -4161,44 +4158,11 @@ package body Exp_Aggr is procedure Convert_To_Assignments (N : Node_Id; Typ : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); - function Known_Size (Decl : Node_Id; Cond_Init : Boolean) return Boolean; - -- Decl is an N_Object_Declaration node. Return true if it declares an - -- object with a known size; in this context, that is always the case, - -- except for a declaration without explicit constraints of an object, - -- either whose nominal subtype is class-wide, or whose initialization - -- contains a conditional expression and whose nominal subtype is both - -- discriminated and unconstrained. - - ---------------- - -- Known_Size -- - ---------------- - - function Known_Size (Decl : Node_Id; Cond_Init : Boolean) return Boolean - is - begin - if Is_Entity_Name (Object_Definition (Decl)) then - declare - Typ : constant Entity_Id := Entity (Object_Definition (Decl)); - - begin - return not Is_Class_Wide_Type (Typ) - and then not (Cond_Init - and then Has_Discriminants (Typ) - and then not Is_Constrained (Typ)); - end; - - else - return True; - end if; - end Known_Size; - -- Local variables Aggr_Code : List_Id; Full_Typ : Entity_Id; - In_Cond_Expr : Boolean; Instr : Node_Id; - Node : Node_Id; Parent_Node : Node_Id; Target_Expr : Node_Id; Temp : Entity_Id; @@ -4210,40 +4174,11 @@ package body Exp_Aggr is pragma Assert (not Is_Static_Dispatch_Table_Aggregate (N)); pragma Assert (Is_Record_Type (Typ)); - In_Cond_Expr := False; - Node := N; - Parent_Node := Parent (Node); - - -- First, climb the parent chain, looking through qualified expressions - -- and dependent expressions of conditional expressions. - - loop - case Nkind (Parent_Node) is - when N_Case_Expression_Alternative => - null; - - when N_Case_Expression => - exit when Node = Expression (Parent_Node); - In_Cond_Expr := True; - - when N_If_Expression => - exit when Node = First (Expressions (Parent_Node)); - In_Cond_Expr := True; - - when N_Qualified_Expression => - null; - - when others => - exit; - end case; - - Node := Parent_Node; - Parent_Node := Parent (Node); - end loop; - -- Set the Expansion_Delayed flag in the cases where the transformation -- will be done top down from above. + Parent_Node := Unconditional_Parent (N); + if -- Internal aggregates (transformed when expanding the parent), -- excluding container aggregates as these are transformed into @@ -4259,11 +4194,15 @@ package body Exp_Aggr is or else Nkind (Parent_Node) = N_Allocator - -- Object declaration (see Convert_Aggr_In_Object_Decl). So far only - -- declarations with a known size are supported. + -- Object declaration (see Convert_Aggr_In_Object_Decl). Class-wide + -- declarations are excluded so far. or else (Nkind (Parent_Node) = N_Object_Declaration - and then Known_Size (Parent_Node, In_Cond_Expr)) + and then not + (Is_Entity_Name (Object_Definition (Parent_Node)) + and then + Is_Class_Wide_Type + (Entity (Object_Definition (Parent_Node))))) -- Safe assignment (see Convert_Aggr_In_Assignment). So far only the -- assignments in init procs are taken into account. @@ -5894,7 +5833,6 @@ package body Exp_Aggr is -- Holds the declaration of Tmp Parent_Node : Node_Id; - Parent_Kind : Node_Kind; -- Start of processing for Expand_Array_Aggregate @@ -6110,13 +6048,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 := Parent (N); - Parent_Kind := Nkind (Parent_Node); - - if Parent_Kind = N_Qualified_Expression then - Parent_Node := Parent (Parent_Node); - Parent_Kind := Nkind (Parent_Node); - end if; + Parent_Node := Unconditional_Parent (N); if -- Internal aggregates (transformed when expanding the parent), @@ -6124,10 +6056,10 @@ package body Exp_Aggr is -- subprogram calls later. So far aggregates with self-references -- are not supported if they appear in a conditional expression. - (Parent_Kind = N_Component_Association + (Nkind (Parent_Node) = N_Component_Association and then not Is_Container_Aggregate (Parent (Parent_Node))) - or else (Parent_Kind in N_Aggregate | N_Extension_Aggregate + or else (Nkind (Parent_Node) in N_Aggregate | N_Extension_Aggregate and then not Is_Container_Aggregate (Parent_Node)) -- Allocator (see Convert_Aggr_In_Allocator). Sliding cannot be done @@ -6146,7 +6078,7 @@ package body Exp_Aggr is -- Object declaration (see Convert_Aggr_In_Object_Decl). Sliding -- cannot be done in place for the time being. - or else (Parent_Kind = N_Object_Declaration + or else (Nkind (Parent_Node) = N_Object_Declaration and then (Aggr_Assignment_OK_For_Backend (N) or else Is_Limited_Type (Typ) @@ -6163,7 +6095,7 @@ package body Exp_Aggr is -- assignments in init procs are taken into account, as well those -- directly performed by the back end. - or else (Parent_Kind = N_Assignment_Statement + or else (Nkind (Parent_Node) = N_Assignment_Statement and then (Inside_Init_Proc or else @@ -6174,7 +6106,16 @@ package body Exp_Aggr is or else Is_Build_In_Place_Aggregate_Return (Parent_Node) then - Set_Expansion_Delayed (N, not Static_Array_Aggregate (N)); + if not Static_Array_Aggregate (N) then + -- 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. + + Set_Expansion_Delayed (N); + Delay_Conditional_Expressions_Between (N, Parent_Node); + end if; + return; end if; @@ -6184,6 +6125,14 @@ package body Exp_Aggr is Establish_Transient_Scope (N, Manage_Sec_Stack => False); end if; + -- Now get back to the immediate parent, modulo qualified expression + + Parent_Node := Parent (N); + + if Nkind (Parent_Node) = N_Qualified_Expression then + Parent_Node := Parent (Parent_Node); + end if; + -- STEP 5 -- Check whether in-place aggregate expansion is possible @@ -6193,7 +6142,7 @@ package body Exp_Aggr is -- protected objects or tasks. For other cases we create a temporary. Maybe_In_Place_OK := - Parent_Kind = N_Assignment_Statement + Nkind (Parent_Node) = N_Assignment_Statement and then (Is_Limited_Type (Typ) or else (not Has_Default_Init_Comps (N) and then not Is_Bit_Packed_Array (Typ) @@ -6259,14 +6208,14 @@ package body Exp_Aggr is -- around the aggregate for this purpose. if Ekind (Current_Scope) = E_Loop - and then Parent_Kind = N_Allocator + and then Nkind (Parent_Node) = N_Allocator then Establish_Transient_Scope (N, Manage_Sec_Stack => False); -- If the parent is an assignment for which no controlled actions -- should take place, prevent the temporary from being finalized. - elsif Parent_Kind = N_Assignment_Statement + elsif Nkind (Parent_Node) = N_Assignment_Statement and then No_Ctrl_Actions (Parent_Node) then Mutate_Ekind (Tmp, E_Variable); diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 2a0b0e6..afcb0a9 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -38,7 +38,6 @@ with Exp_Ch4; use Exp_Ch4; with Exp_Ch6; use Exp_Ch6; with Exp_Ch7; use Exp_Ch7; with Exp_Ch9; use Exp_Ch9; -with Exp_Dbug; use Exp_Dbug; with Exp_Disp; use Exp_Disp; with Exp_Dist; use Exp_Dist; with Exp_Put_Image; @@ -9134,35 +9133,7 @@ package body Exp_Ch3 is -- illegal code if written by hand, but that's OK. if Rewrite_As_Renaming then - Rewrite (N, - Make_Object_Renaming_Declaration (Loc, - Defining_Identifier => Def_Id, - Subtype_Mark => New_Occurrence_Of (Etype (Def_Id), Loc), - Name => Expr_Q)); - - -- Keep original aspects - - Move_Aspects (Original_Node (N), N); - - -- We do not analyze this renaming declaration, because all its - -- components have already been analyzed, and if we were to go - -- ahead and analyze it, we would in effect be trying to generate - -- another declaration of X, which won't do. - - Set_Renamed_Object (Def_Id, Expr_Q); - Set_Analyzed (N); - - -- We do need to deal with debug issues for this renaming - - -- First, if entity comes from source, then mark it as needing - -- debug information, even though it is defined by a generated - -- renaming that does not come from source. - - Set_Debug_Info_Defining_Id (N); - - -- Now call the routine to generate debug info for the renaming - - Insert_Action (N, Debug_Renaming_Declaration (N)); + Rewrite_Object_Declaration_As_Renaming (N, Expr_Q); end if; -- Exception on library entity not available diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7fda622..8db729f 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -191,6 +191,15 @@ package body Exp_Ch4 is -- Return the size of a small signed integer type covering Lo .. Hi, the -- main goal being to return a size lower than that of standard types. + procedure Insert_Conditional_Object_Declaration + (Obj_Id : Entity_Id; + Expr : Node_Id; + Decl : Node_Id); + -- Expr is the dependent expression of a conditional expression and Decl + -- is the declaration of an object whose initialization expression is the + -- conditional expression. Insert in the actions of Expr the declaration + -- of Obj_Id modeled on Decl and with Expr as initialization expression. + procedure Insert_Dereference_Action (N : Node_Id); -- N is an expression whose type is an access. When the type of the -- associated storage pool is derived from Checked_Pool, generate a @@ -4259,7 +4268,7 @@ package body Exp_Ch4 is function Size_In_Storage_Elements (E : Entity_Id) return Node_Id is Idx : Node_Id := First_Index (E); - Len : Node_Id; + Len : Node_Id := Empty; Res : Node_Id := Empty; begin @@ -4987,6 +4996,9 @@ package body Exp_Ch4 is -- Return True if we can copy objects of this type when expanding a case -- expression. + function Is_Optimizable_Declaration (N : Node_Id) return Boolean; + -- Return True if N is an object declaration that can be optimized + ------------------ -- Is_Copy_Type -- ------------------ @@ -4996,12 +5008,28 @@ package body Exp_Ch4 is return Is_Elementary_Type (Underlying_Type (Typ)); end Is_Copy_Type; + -------------------------------- + -- Is_Optimizable_Declaration -- + -------------------------------- + + function Is_Optimizable_Declaration (N : Node_Id) return Boolean is + begin + return Nkind (N) = N_Object_Declaration + and then not (Is_Entity_Name (Object_Definition (N)) + and then Is_Class_Wide_Type + (Entity (Object_Definition (N)))) + and then not Is_Return_Object (Defining_Identifier (N)) + and then not Is_Copy_Type (Typ); + end Is_Optimizable_Declaration; + -- Local variables Acts : List_Id; Alt : Node_Id; Case_Stmt : Node_Id; Decl : Node_Id; + New_N : Node_Id; + Par_Obj : Node_Id; Target : Entity_Id := Empty; Target_Typ : Entity_Id; @@ -5035,6 +5063,25 @@ package body Exp_Ch4 is -- This makes the expansion much easier when expressions are calls to -- build-in-place functions. + Optimize_Object_Decl : Boolean := False; + -- Small optimization: when the case expression appears in the context + -- of an object declaration of a type not Is_Copy_Type, expand into + + -- case X is + -- when A => + -- then-obj : typ := then_expr; + -- target := then-obj'Unrestricted_Access; + -- when B => + -- else-obj : typ := else-expr; + -- target := else-obj'Unrestricted_Access; + -- ... + -- end case + -- + -- obj : typ renames target.all; + + -- This makes the expansion much easier when expressions are calls to + -- build-in-place functions. + -- Start of processing for Expand_N_Case_Expression begin @@ -5047,7 +5094,9 @@ package body Exp_Ch4 is declare Uncond_Par : constant Node_Id := Unconditional_Parent (N); begin - if Nkind (Uncond_Par) = N_Simple_Return_Statement then + if Nkind (Uncond_Par) = N_Simple_Return_Statement + or else Is_Optimizable_Declaration (Uncond_Par) + then Delay_Conditional_Expressions_Between (N, Uncond_Par); end if; end; @@ -5065,6 +5114,9 @@ package body Exp_Ch4 is elsif Nkind (Par) = N_Simple_Return_Statement then Optimize_Return_Stmt := True; + elsif Is_Optimizable_Declaration (Par) then + Optimize_Object_Decl := True; + else return; end if; @@ -5148,7 +5200,7 @@ package body Exp_Ch4 is -- No need for Target_Typ in the case of statements if Optimize_Assignment_Stmt or else Optimize_Return_Stmt then - null; + Target_Typ := Empty; -- Scalar/Copy case @@ -5159,7 +5211,7 @@ package body Exp_Ch4 is -- 'Unrestricted_Access. -- Generate: - -- type Ptr_Typ is not null access all Typ; + -- type Ptr_Typ is not null access all [constant] Typ; else Target_Typ := Make_Temporary (Loc, 'P'); @@ -5171,7 +5223,9 @@ package body Exp_Ch4 is Make_Access_To_Object_Definition (Loc, All_Present => True, Null_Exclusion_Present => True, - Subtype_Indication => New_Occurrence_Of (Typ, Loc)))); + Subtype_Indication => New_Occurrence_Of (Typ, Loc), + Constant_Present => + Optimize_Object_Decl and then Constant_Present (Par)))); end if; -- Create the declaration of the target which captures the value of the @@ -5199,11 +5253,19 @@ package body Exp_Ch4 is Alt := First (Alternatives (N)); while Present (Alt) loop + -- When the alternative's expression involves controlled function + -- calls, generated temporaries are chained on the corresponding + -- list of actions. These temporaries need to be finalized after + -- the case expression is evaluated. + + Process_Transients_In_Expression (N, Actions (Alt)); + declare Alt_Loc : constant Source_Ptr := Sloc (Expression (Alt)); Alt_Expr : Node_Id := Relocate_Node (Expression (Alt)); LHS : Node_Id; + Obj : Node_Id; Stmts : List_Id; begin @@ -5240,12 +5302,34 @@ package body Exp_Ch4 is Unanalyze_Delayed_Conditional_Expression (Alt_Expr); end if; + -- Generate: + -- Obj : [constant] Typ := AX; + -- Target := Obj'Unrestricted_Access; + + elsif Optimize_Object_Decl then + Obj := Make_Temporary (Loc, 'C', Alt_Expr); + + Insert_Conditional_Object_Declaration (Obj, Alt_Expr, Par); + + Alt_Expr := + Make_Attribute_Reference (Alt_Loc, + Prefix => New_Occurrence_Of (Obj, Alt_Loc), + Attribute_Name => Name_Unrestricted_Access); + + LHS := New_Occurrence_Of (Target, Loc); + Set_Assignment_OK (LHS); + + Stmts := New_List ( + Make_Assignment_Statement (Alt_Loc, + Name => LHS, + Expression => Alt_Expr)); + -- Take the unrestricted access of the expression value for non- -- scalar types. This approach avoids big copies and covers the -- limited and unconstrained cases. -- Generate: - -- Target := AX['Unrestricted_Access]; + -- Target := AX'Unrestricted_Access; else if not Is_Copy_Type (Typ) then @@ -5288,12 +5372,6 @@ package body Exp_Ch4 is Make_Case_Statement_Alternative (Sloc (Alt), Discrete_Choices => Discrete_Choices (Alt), Statements => Stmts)); - - -- Finalize any transient objects on exit from the alternative. - -- Note that this needs to be done only after Stmts is attached - -- to the Alternatives list above (for Safe_To_Capture_Value). - - Process_Transients_In_Expression (N, Stmts); end; Next (Alt); @@ -5305,24 +5383,48 @@ package body Exp_Ch4 is Rewrite (Par, Case_Stmt); Analyze (Par); + elsif Optimize_Object_Decl then + Append_To (Acts, Case_Stmt); + Insert_Actions (Par, Acts); + + New_N := + Make_Explicit_Dereference (Loc, + Prefix => New_Occurrence_Of (Target, Loc)); + + -- The renaming is not analyzed so complete the decoration of the + -- object and set the type of the name directly. + + Par_Obj := Defining_Identifier (Par); + if Constant_Present (Par) then + Mutate_Ekind (Par_Obj, E_Constant); + Set_Is_True_Constant (Par_Obj); + else + Mutate_Ekind (Par_Obj, E_Variable); + end if; + + Set_Etype (New_N, Etype (Par_Obj)); + + Rewrite_Object_Declaration_As_Renaming (Par, New_N); + -- Otherwise rewrite the case expression itself else Append_To (Acts, Case_Stmt); if Is_Copy_Type (Typ) then - Rewrite (N, + New_N := Make_Expression_With_Actions (Loc, Expression => New_Occurrence_Of (Target, Loc), - Actions => Acts)); + Actions => Acts); else Insert_Actions (N, Acts); - Rewrite (N, + New_N := Make_Explicit_Dereference (Loc, - Prefix => New_Occurrence_Of (Target, Loc))); + Prefix => New_Occurrence_Of (Target, Loc)); end if; + Rewrite (N, New_N); Analyze_And_Resolve (N, Typ); end if; end Expand_N_Case_Expression; @@ -5488,11 +5590,44 @@ package body Exp_Ch4 is -- actions in order to create a temporary to capture the level of the -- expression in each branch. + function Is_Copy_Type (Typ : Entity_Id) return Boolean; + -- Return True if we can copy objects of this type when expanding an if + -- expression. + + function Is_Optimizable_Declaration (N : Node_Id) return Boolean; + -- Return True if N is an object declaration that can be optimized + function OK_For_Single_Subtype (T1, T2 : Entity_Id) return Boolean; -- Return true if it is acceptable to use a single subtype for two -- dependent expressions of subtype T1 and T2 respectively, which are -- unidimensional arrays whose index bounds are known at compile time. + ------------------ + -- Is_Copy_Type -- + ------------------ + + function Is_Copy_Type (Typ : Entity_Id) return Boolean is + Utyp : constant Entity_Id := Underlying_Type (Typ); + + begin + return Is_Definite_Subtype (Utyp) + and then not Is_By_Reference_Type (Utyp); + end Is_Copy_Type; + + -------------------------------- + -- Is_Optimizable_Declaration -- + -------------------------------- + + function Is_Optimizable_Declaration (N : Node_Id) return Boolean is + begin + return Nkind (N) = N_Object_Declaration + and then not (Is_Entity_Name (Object_Definition (N)) + and then Is_Class_Wide_Type + (Entity (Object_Definition (N)))) + and then not Is_Return_Object (Defining_Identifier (N)) + and then not Is_Copy_Type (Typ); + end Is_Optimizable_Declaration; + --------------------------- -- OK_For_Single_Subtype -- --------------------------- @@ -5526,7 +5661,7 @@ package body Exp_Ch4 is -- a safe assignment statement, expand into -- if cond then - -- lhs := then-expr + -- lhs := then-expr; -- else -- lhs := else-expr; -- end if; @@ -5539,7 +5674,7 @@ package body Exp_Ch4 is -- a simple return statement, expand into -- if cond then - -- return then-expr + -- return then-expr; -- else -- return else-expr; -- end if; @@ -5547,6 +5682,23 @@ package body Exp_Ch4 is -- This makes the expansion much easier when expressions are calls to -- build-in-place functions. + Optimize_Object_Decl : Boolean := False; + -- Small optimization: when the if expression appears in the context of + -- an object declaration of a type not Is_Copy_Type, expand into + + -- if cond then + -- then-obj : typ := then_expr; + -- target := then-obj'Unrestricted_Access; + -- else + -- else-obj : typ := else-expr; + -- target := else-obj'Unrestricted_Access; + -- end if; + -- + -- obj : typ renames target.all; + + -- This makes the expansion much easier when expressions are calls to + -- build-in-place functions. + -- Start of processing for Expand_N_If_Expression begin @@ -5560,7 +5712,9 @@ package body Exp_Ch4 is declare Uncond_Par : constant Node_Id := Unconditional_Parent (N); begin - if Nkind (Uncond_Par) = N_Simple_Return_Statement then + if Nkind (Uncond_Par) = N_Simple_Return_Statement + or else Is_Optimizable_Declaration (Uncond_Par) + then Delay_Conditional_Expressions_Between (N, Uncond_Par); end if; end; @@ -5578,6 +5732,9 @@ package body Exp_Ch4 is elsif Nkind (Par) = N_Simple_Return_Statement then Optimize_Return_Stmt := True; + elsif Is_Optimizable_Declaration (Par) then + Optimize_Object_Decl := True; + else return; end if; @@ -5685,6 +5842,8 @@ package body Exp_Ch4 is Condition => Relocate_Node (Cond), Then_Statements => New_List (New_Then), Else_Statements => New_List (New_Else)); + Decl := Empty; + New_N := Empty; -- Preserve the original context for which the if statement is -- being generated. This is needed by the finalization machinery @@ -5732,6 +5891,8 @@ package body Exp_Ch4 is Else_Statements => New_List ( Make_Simple_Return_Statement (Sloc (New_Else), Expression => New_Else))); + Decl := Empty; + New_N := Empty; -- Preserve the original context for which the if statement is -- being generated. This is needed by the finalization machinery @@ -5740,6 +5901,99 @@ package body Exp_Ch4 is Set_From_Conditional_Expression (If_Stmt); + elsif Optimize_Object_Decl then + -- When the "then" or "else" expressions involve controlled function + -- calls, generated temporaries are chained on the corresponding list + -- of actions. These temporaries need to be finalized after the if + -- expression is evaluated. + + Process_Transients_In_Expression (N, Then_Actions (N)); + Process_Transients_In_Expression (N, Else_Actions (N)); + + declare + Par_Obj : constant Entity_Id := Defining_Identifier (Par); + Then_Obj : constant Entity_Id := Make_Temporary (Loc, 'C', Thenx); + Else_Obj : constant Entity_Id := Make_Temporary (Loc, 'C', Elsex); + Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'A'); + Target : constant Entity_Id := Make_Temporary (Loc, 'C', N); + + begin + Insert_Conditional_Object_Declaration (Then_Obj, Thenx, Par); + Insert_Conditional_Object_Declaration (Else_Obj, Elsex, Par); + + -- Generate: + -- type Ptr_Typ is not null access all [constant] Typ; + + Insert_Action (Par, + Make_Full_Type_Declaration (Loc, + Defining_Identifier => Ptr_Typ, + Type_Definition => + Make_Access_To_Object_Definition (Loc, + All_Present => True, + Null_Exclusion_Present => True, + Subtype_Indication => New_Occurrence_Of (Typ, Loc), + Constant_Present => Constant_Present (Par)))); + + -- Generate: + -- Target : Ptr_Typ; + + Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Target, + Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc)); + Set_No_Initialization (Decl); + Insert_Action (Par, Decl); + + -- Generate: + -- if Cond then + -- Target := <Then_Obj>'Unrestricted_Access; + -- else + -- Target := <Else_Obj>'Unrestricted_Access; + -- end if; + + If_Stmt := + Make_Implicit_If_Statement (N, + Condition => Relocate_Node (Cond), + Then_Statements => New_List ( + Make_Assignment_Statement (Sloc (Thenx), + Name => New_Occurrence_Of (Target, Sloc (Thenx)), + Expression => + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (Then_Obj, Loc), + Attribute_Name => Name_Unrestricted_Access))), + + Else_Statements => New_List ( + Make_Assignment_Statement (Sloc (Elsex), + Name => New_Occurrence_Of (Target, Sloc (Elsex)), + Expression => + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (Else_Obj, Loc), + Attribute_Name => Name_Unrestricted_Access)))); + + -- Preserve the original context for which the if statement is + -- being generated. This is needed by the finalization machinery + -- to prevent the premature finalization of controlled objects + -- found within the if statement. + + Set_From_Conditional_Expression (If_Stmt); + + New_N := + Make_Explicit_Dereference (Loc, + Prefix => New_Occurrence_Of (Target, Loc)); + + -- The renaming is not analyzed so complete the decoration of the + -- object and set the type of the name directly. + + if Constant_Present (Par) then + Mutate_Ekind (Par_Obj, E_Constant); + Set_Is_True_Constant (Par_Obj); + else + Mutate_Ekind (Par_Obj, E_Variable); + end if; + + Set_Etype (New_N, Etype (Par_Obj)); + end; + -- If the result is a unidimensional unconstrained array but the two -- dependent expressions have constrained subtypes with known bounds, -- then we expand as follows: @@ -5984,8 +6238,8 @@ package body Exp_Ch4 is High_Bound => Build_New_Bound (Then_Hi, Else_Hi, Slice_Hi))); end; - -- If the type is by reference or else not definite, then we expand as - -- follows to avoid the possibility of improper copying. + -- If the type cannot be copied, then we expand as follows to avoid the + -- possibility of improper copying. -- type Ptr_Typ is not null access all Typ; -- Target : Ptr; @@ -5999,9 +6253,7 @@ package body Exp_Ch4 is -- and replace the if expression by a reference to Target.all. - elsif Is_By_Reference_Type (Typ) - or else not Is_Definite_Subtype (Typ) - then + elsif not Is_Copy_Type (Typ) then -- When the "then" or "else" expressions involve controlled function -- calls, generated temporaries are chained on the corresponding list -- of actions. These temporaries need to be finalized after the if @@ -6240,6 +6492,10 @@ package body Exp_Ch4 is Rewrite (Par, If_Stmt); Analyze (Par); + elsif Optimize_Object_Decl then + Insert_Action (Par, If_Stmt); + Rewrite_Object_Declaration_As_Renaming (Par, New_N); + -- Otherwise rewrite the if expression itself else @@ -12931,6 +13187,70 @@ package body Exp_Ch4 is end if; end Get_Size_For_Range; + ------------------------------------------- + -- Insert_Conditional_Object_Declaration -- + ------------------------------------------- + + procedure Insert_Conditional_Object_Declaration + (Obj_Id : Entity_Id; + Expr : Node_Id; + Decl : Node_Id) + is + Loc : constant Source_Ptr := Sloc (Expr); + Obj_Decl : constant Node_Id := + Make_Object_Declaration (Loc, + Defining_Identifier => Obj_Id, + Aliased_Present => Aliased_Present (Decl), + Constant_Present => Constant_Present (Decl), + Object_Definition => New_Copy_Tree (Object_Definition (Decl)), + Expression => Relocate_Node (Expr)); + + Master_Node_Decl : Node_Id; + Master_Node_Id : Entity_Id; + + begin + -- If the expression is itself a conditional expression whose + -- expansion has been delayed, analyze it again and expand it. + + if Is_Delayed_Conditional_Expression (Expression (Obj_Decl)) then + Unanalyze_Delayed_Conditional_Expression (Expression (Obj_Decl)); + end if; + + Insert_Action (Expr, Obj_Decl); + + -- If the object needs finalization, we need to insert its Master_Node + -- manually because 1) the machinery in Exp_Ch7 will not pick it since + -- it will be declared in the arm of a conditional statement and 2) we + -- cannot invoke Process_Transients_In_Expression on it since it is not + -- a transient object (it has the lifetime of the original object). + + if Nkind (Obj_Decl) = N_Object_Declaration + and then Needs_Finalization (Base_Type (Etype (Obj_Id))) + then + Master_Node_Id := Make_Temporary (Loc, 'N'); + Master_Node_Decl := + Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj_Id); + + -- The master is the innermost enclosing non-transient construct + + Insert_Action (Find_Hook_Context (Expr), Master_Node_Decl); + + -- Propagate the relaxed finalization semantics + + Set_Is_Independent + (Master_Node_Id, + Has_Relaxed_Finalization (Base_Type (Etype (Obj_Id)))); + + -- Generate the attachment of the object to the Master_Node + + Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id); + + -- Mark the transient object to avoid double finalization + + Set_Is_Finalized_Transient (Obj_Id); + end if; + end Insert_Conditional_Object_Declaration; + ------------------------------- -- Insert_Dereference_Action -- ------------------------------- diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 39cc9ab..ef5faa1 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -5359,7 +5359,8 @@ package body Exp_Ch6 is procedure Expand_Ctrl_Function_Call (N : Node_Id; Use_Sec_Stack : Boolean) is - Par : constant Node_Id := Parent (N); + Par : constant Node_Id := Parent (N); + Uncond_Par : constant Node_Id := Unconditional_Parent (N); begin -- Optimization: if the returned value is returned again, then no need @@ -5368,7 +5369,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 (Unconditional_Parent (N)) = N_Simple_Return_Statement then + if Nkind (Uncond_Par) = N_Simple_Return_Statement then return; end if; @@ -5381,8 +5382,15 @@ package body Exp_Ch6 is if Nkind (Par) in N_Object_Declaration | N_Delta_Aggregate and then Expression (Par) = N - and then not Use_Sec_Stack then + if not Use_Sec_Stack then + return; + end if; + + -- Note that object declarations are also distributed into conditional + -- expressions but we may be invoked before this distribution is done. + + elsif Nkind (Uncond_Par) = N_Object_Declaration then return; end if; diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 017f16f..171ad4e 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -2546,7 +2546,8 @@ package body Exp_Ch7 is elsif Ekind (Obj_Id) = E_Variable and then Is_RTE (Obj_Typ, RE_Master_Node) then - Processing_Actions (Decl); + Processing_Actions + (Decl, Strict => not Is_Independent (Obj_Id)); -- The object is of the form: -- Obj : [constant] Typ [:= Expr]; diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 27d8233..e449d45 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -36,6 +36,7 @@ with Exp_Aggr; use Exp_Aggr; with Exp_Ch6; use Exp_Ch6; with Exp_Ch7; use Exp_Ch7; with Exp_Ch11; use Exp_Ch11; +with Exp_Dbug; use Exp_Dbug; with Freeze; use Freeze; with Ghost; use Ghost; with Inline; use Inline; @@ -13556,6 +13557,46 @@ package body Exp_Util is return False; end Requires_Cleanup_Actions; + -------------------------------------------- + -- Rewrite_Object_Declaration_As_Renaming -- + -------------------------------------------- + + procedure Rewrite_Object_Declaration_As_Renaming (N, Nam : Node_Id) is + Def_Id : constant Entity_Id := Defining_Identifier (N); + Loc : constant Source_Ptr := Sloc (N); + + begin + Rewrite (N, + Make_Object_Renaming_Declaration (Loc, + Defining_Identifier => Def_Id, + Subtype_Mark => New_Occurrence_Of (Etype (Def_Id), Loc), + Name => Nam)); + + -- Keep original aspects + + Move_Aspects (Original_Node (N), N); + + -- We do not analyze this renaming declaration, because all its + -- components have already been analyzed, and if we were to go + -- ahead and analyze it, we would in effect be trying to generate + -- another declaration of X, which won't do. + + Set_Renamed_Object (Def_Id, Nam); + Set_Analyzed (N); + + -- We do need to deal with debug issues for this renaming + + -- First, if entity comes from source, then mark it as needing + -- debug information, even though it is defined by a generated + -- renaming that does not come from source. + + Set_Debug_Info_Defining_Id (N); + + -- Now call the routine to generate debug info for the renaming + + Insert_Action (N, Debug_Renaming_Declaration (N)); + end Rewrite_Object_Declaration_As_Renaming; + ------------------------------------ -- Safe_Unchecked_Type_Conversion -- ------------------------------------ diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index fc70ac5..81e51af 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -1243,6 +1243,9 @@ package Exp_Util is -- These cases require special actions on scope exit. Lib_Level is True if -- the construct is at library level, and False otherwise. + procedure Rewrite_Object_Declaration_As_Renaming (N, Nam : Node_Id); + -- Rewrite object declaration N as an object renaming declaration of Nam + function Safe_Unchecked_Type_Conversion (Exp : Node_Id) return Boolean; -- Given the node for an N_Unchecked_Type_Conversion, return True if this -- is an unchecked conversion that Gigi can handle directly. Otherwise diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 76ae53b..eb53d59 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -4689,11 +4689,22 @@ package body Sem_Ch3 is if Back_End_Inlining and then Expander_Active and then Nkind (E) = N_Function_Call - and then Nkind (Name (E)) in N_Has_Entity + and then Is_Entity_Name (Name (E)) and then Is_Inlined (Entity (Name (E))) and then not Is_Constrained (Etype (E)) - and then Analyzed (N) and then No (Expression (N)) + and then Analyzed (N) + then + goto Leave; + end if; + + -- No further action needed if E is a conditional expression and N + -- has been replaced by a renaming declaration during its expansion + -- (see Expand_N_Case_Expression and Expand_N_If_Expression). + + if Expander_Active + and then Nkind (E) in N_Case_Expression | N_If_Expression + and then Nkind (N) = N_Object_Renaming_Declaration then goto Leave; end if; |