Commit 15529d0a by Pierre-Marie de Rodat

exp_ch6.adb: (Make_Build_In_Place_Call_In_Object_Declaration): Remove the code at the end of...

gcc/ada/

2017-10-09  Bob Duff  <duff@adacore.com>

	* exp_ch6.adb: (Make_Build_In_Place_Call_In_Object_Declaration): Remove
	the code at the end of this procedure that was setting the type of a
	class-wide object to the specific type returned by a function call.
	Treat this case as indefinite instead.

2017-10-09  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch4.adb (Try_Class_Wide_Operation, Traverse_Homonyms):
	Suppress spurious ambiguity error when two traversals of the homonym
	chain (first directly, and then through an examination of relevant
	interfaces) retrieve the same operation, when other irrelevant homonyms
	of the operatioh are also present.

2017-10-09  Ed Schonberg  <schonberg@adacore.com>

	* sem_util.adb (Object_Access_Level): If the object is the return
	statement of an expression function, return the level of the function.
	This is relevant when the object involves an implicit conversion
	between access types and the expression function is a completion, which
	forces the analysis of the expression before rewriting it as a body, so
	that freeze nodes can appear in the proper scope.

2017-10-09  Bob Duff  <duff@adacore.com>

	* atree.adb: Make nnd apply to everything "interesting", including
	Rewrite.  Remove rrd.

2017-10-09  Javier Miranda  <miranda@adacore.com>

	* exp_ch3.adb (Expand_N_Object_Declaration): Avoid never-ending loop
	processing the declaration of the dummy object internally created by
	Make_DT to compute the offset to the top of components referencing
	secondary dispatch tables.
	(Initialize_Tag): Do not initialize the offset-to-top field if it has
	been initialized initialized.
	* exp_disp.ads (Building_Static_Secondary_DT): New subprogram.
	* exp_disp.adb (Building_Static_Secondary_DT): New subprogram.
	(Make_DT): Create a dummy constant object if we can statically build
	secondary dispatch tables.
	(Make_Secondary_DT): For statically allocated secondary dispatch tables
	use the dummy object to compute the offset-to-top field value by means
	of the attribute 'Position.

gcc/testsuite/

2017-10-09  Ed Schonberg  <schonberg@adacore.com>

	* gnat.dg/class_wide3.adb, gnat.dg/class_wide3_pkg.ads: New testcase.

From-SVN: r253550
parent 5168a9b3
2017-10-09 Bob Duff <duff@adacore.com> 2017-10-09 Bob Duff <duff@adacore.com>
* exp_ch6.adb: (Make_Build_In_Place_Call_In_Object_Declaration): Remove
the code at the end of this procedure that was setting the type of a
class-wide object to the specific type returned by a function call.
Treat this case as indefinite instead.
2017-10-09 Ed Schonberg <schonberg@adacore.com>
* sem_ch4.adb (Try_Class_Wide_Operation, Traverse_Homonyms):
Suppress spurious ambiguity error when two traversals of the homonym
chain (first directly, and then through an examination of relevant
interfaces) retrieve the same operation, when other irrelevant homonyms
of the operatioh are also present.
2017-10-09 Ed Schonberg <schonberg@adacore.com>
* sem_util.adb (Object_Access_Level): If the object is the return
statement of an expression function, return the level of the function.
This is relevant when the object involves an implicit conversion
between access types and the expression function is a completion, which
forces the analysis of the expression before rewriting it as a body, so
that freeze nodes can appear in the proper scope.
2017-10-09 Bob Duff <duff@adacore.com>
* atree.adb: Make nnd apply to everything "interesting", including
Rewrite. Remove rrd.
2017-10-09 Javier Miranda <miranda@adacore.com>
* exp_ch3.adb (Expand_N_Object_Declaration): Avoid never-ending loop
processing the declaration of the dummy object internally created by
Make_DT to compute the offset to the top of components referencing
secondary dispatch tables.
(Initialize_Tag): Do not initialize the offset-to-top field if it has
been initialized initialized.
* exp_disp.ads (Building_Static_Secondary_DT): New subprogram.
* exp_disp.adb (Building_Static_Secondary_DT): New subprogram.
(Make_DT): Create a dummy constant object if we can statically build
secondary dispatch tables.
(Make_Secondary_DT): For statically allocated secondary dispatch tables
use the dummy object to compute the offset-to-top field value by means
of the attribute 'Position.
2017-10-09 Bob Duff <duff@adacore.com>
* exp_ch6.adb (Expand_N_Extended_Return_Statement): Add self-checking * exp_ch6.adb (Expand_N_Extended_Return_Statement): Add self-checking
code so if BIPAlloc is not passed in, it will likely raise code so if BIPAlloc is not passed in, it will likely raise
Program_Error instead of cause miscellaneous chaos. Program_Error instead of cause miscellaneous chaos.
......
...@@ -73,11 +73,12 @@ package body Atree is ...@@ -73,11 +73,12 @@ package body Atree is
-- ww := 12345 -- ww := 12345
-- and set a breakpoint on New_Node_Breakpoint (nickname "nn"). Continue. -- and set a breakpoint on New_Node_Breakpoint (nickname "nn"). Continue.
-- Either way, gnat1 will stop when node 12345 is created -- Either way, gnat1 will stop when node 12345 is created, or certain other
-- interesting operations are performed, such as Rewrite. To see exactly
-- which operations, search for "pragma Debug" below.
-- The second method is much faster -- The second method is much faster if the amount of Ada code being
-- compiled is large.
-- Similarly, rr and rrd allow breaking on rewriting of a given node
ww : Node_Id'Base := Node_Id'First - 1; ww : Node_Id'Base := Node_Id'First - 1;
pragma Export (Ada, ww); -- trick the optimizer pragma Export (Ada, ww); -- trick the optimizer
...@@ -103,24 +104,8 @@ package body Atree is ...@@ -103,24 +104,8 @@ package body Atree is
-- If Node = Watch_Node, this prints out the new node and calls -- If Node = Watch_Node, this prints out the new node and calls
-- New_Node_Breakpoint. Otherwise, does nothing. -- New_Node_Breakpoint. Otherwise, does nothing.
procedure rr;
pragma Export (Ada, rr);
procedure Rewrite_Breakpoint renames rr;
-- This doesn't do anything interesting; it's just for setting breakpoint
-- on as explained above.
procedure rrd (Old_Node, New_Node : Node_Id);
pragma Export (Ada, rrd);
procedure Rewrite_Debugging_Output
(Old_Node, New_Node : Node_Id) renames rrd;
-- For debugging. If debugging is turned on, Rewrite calls this. If debug
-- flag N is turned on, this prints out the new node.
--
-- If Old_Node = Watch_Node, this prints out the old and new nodes and
-- calls Rewrite_Breakpoint. Otherwise, does nothing.
procedure Node_Debug_Output (Op : String; N : Node_Id); procedure Node_Debug_Output (Op : String; N : Node_Id);
-- Common code for nnd and rrd, writes Op followed by information about N -- Called by nnd; writes Op followed by information about N
procedure Print_Statistics; procedure Print_Statistics;
pragma Export (Ada, Print_Statistics); pragma Export (Ada, Print_Statistics);
...@@ -751,6 +736,8 @@ package body Atree is ...@@ -751,6 +736,8 @@ package body Atree is
Save_Link : constant Union_Id := Nodes.Table (Destination).Link; Save_Link : constant Union_Id := Nodes.Table (Destination).Link;
begin begin
pragma Debug (New_Node_Debugging_Output (Source));
pragma Debug (New_Node_Debugging_Output (Destination));
Nodes.Table (Destination) := Nodes.Table (Source); Nodes.Table (Destination) := Nodes.Table (Source);
Nodes.Table (Destination).In_List := Save_In_List; Nodes.Table (Destination).In_List := Save_In_List;
Nodes.Table (Destination).Link := Save_Link; Nodes.Table (Destination).Link := Save_Link;
...@@ -1348,6 +1335,8 @@ package body Atree is ...@@ -1348,6 +1335,8 @@ package body Atree is
Temp_Flg : Flags_Byte; Temp_Flg : Flags_Byte;
begin begin
pragma Debug (New_Node_Debugging_Output (E1));
pragma Debug (New_Node_Debugging_Output (E2));
pragma Assert (True pragma Assert (True
and then Has_Extension (E1) and then Has_Extension (E1)
and then Has_Extension (E2) and then Has_Extension (E2)
...@@ -1746,7 +1735,6 @@ package body Atree is ...@@ -1746,7 +1735,6 @@ package body Atree is
begin begin
Write_Str ("Watched node "); Write_Str ("Watched node ");
Write_Int (Int (Watch_Node)); Write_Int (Int (Watch_Node));
Write_Str (" created");
Write_Eol; Write_Eol;
end nn; end nn;
...@@ -1759,7 +1747,7 @@ package body Atree is ...@@ -1759,7 +1747,7 @@ package body Atree is
begin begin
if Debug_Flag_N or else Node_Is_Watched then if Debug_Flag_N or else Node_Is_Watched then
Node_Debug_Output ("Allocate", N); Node_Debug_Output ("Node", N);
if Node_Is_Watched then if Node_Is_Watched then
New_Node_Breakpoint; New_Node_Breakpoint;
...@@ -2163,6 +2151,8 @@ package body Atree is ...@@ -2163,6 +2151,8 @@ package body Atree is
(not Has_Extension (Old_Node) (not Has_Extension (Old_Node)
and not Has_Extension (New_Node) and not Has_Extension (New_Node)
and not Nodes.Table (New_Node).In_List); and not Nodes.Table (New_Node).In_List);
pragma Debug (New_Node_Debugging_Output (Old_Node));
pragma Debug (New_Node_Debugging_Output (New_Node));
-- Do copy, preserving link and in list status and required flags -- Do copy, preserving link and in list status and required flags
...@@ -2214,7 +2204,8 @@ package body Atree is ...@@ -2214,7 +2204,8 @@ package body Atree is
(not Has_Extension (Old_Node) (not Has_Extension (Old_Node)
and not Has_Extension (New_Node) and not Has_Extension (New_Node)
and not Nodes.Table (New_Node).In_List); and not Nodes.Table (New_Node).In_List);
pragma Debug (Rewrite_Debugging_Output (Old_Node, New_Node)); pragma Debug (New_Node_Debugging_Output (Old_Node));
pragma Debug (New_Node_Debugging_Output (New_Node));
if Nkind (Old_Node) in N_Subexpr then if Nkind (Old_Node) in N_Subexpr then
Old_Paren_Count := Paren_Count (Old_Node); Old_Paren_Count := Paren_Count (Old_Node);
...@@ -2264,36 +2255,6 @@ package body Atree is ...@@ -2264,36 +2255,6 @@ package body Atree is
end if; end if;
end Rewrite; end Rewrite;
-------------------------
-- Rewrite_Breakpoint --
-------------------------
procedure rr is
begin
Write_Str ("Watched node ");
Write_Int (Int (Watch_Node));
Write_Str (" rewritten");
Write_Eol;
end rr;
------------------------------
-- Rewrite_Debugging_Output --
------------------------------
procedure rrd (Old_Node, New_Node : Node_Id) is
Node_Is_Watched : constant Boolean := Old_Node = Watch_Node;
begin
if Debug_Flag_N or else Node_Is_Watched then
Node_Debug_Output ("Rewrite", Old_Node);
Node_Debug_Output ("into", New_Node);
if Node_Is_Watched then
Rewrite_Breakpoint;
end if;
end if;
end rrd;
------------------ ------------------
-- Set_Analyzed -- -- Set_Analyzed --
------------------ ------------------
......
...@@ -6138,6 +6138,19 @@ package body Exp_Ch3 is ...@@ -6138,6 +6138,19 @@ package body Exp_Ch3 is
return; return;
end if; end if;
-- No action needed for the internal imported dummy object added by
-- Make_DT to compute the offset of the components that reference
-- secondary dispatch tables; required to avoid never-ending loop
-- processing this internal object declaration.
if Tagged_Type_Expansion
and then Is_Internal (Def_Id)
and then Is_Imported (Def_Id)
and then Related_Type (Def_Id) = Implementation_Base_Type (Typ)
then
return;
end if;
-- First we do special processing for objects of a tagged type where -- First we do special processing for objects of a tagged type where
-- this is the point at which the type is frozen. The creation of the -- this is the point at which the type is frozen. The creation of the
-- dispatch table and the initialization procedure have to be deferred -- dispatch table and the initialization procedure have to be deferred
...@@ -8384,10 +8397,13 @@ package body Exp_Ch3 is ...@@ -8384,10 +8397,13 @@ package body Exp_Ch3 is
-- Normal case: No discriminants in the parent type -- Normal case: No discriminants in the parent type
else else
-- Don't need to set any value if this interface shares the -- Don't need to set any value if the offset-to-top field is
-- primary dispatch table. -- statically set or if this interface shares the primary
-- dispatch table.
if not Is_Ancestor (Iface, Typ, Use_Full_View => True) then if not Building_Static_Secondary_DT (Typ)
and then not Is_Ancestor (Iface, Typ, Use_Full_View => True)
then
Append_To (Stmts_List, Append_To (Stmts_List,
Build_Set_Static_Offset_To_Top (Loc, Build_Set_Static_Offset_To_Top (Loc,
Iface_Tag => New_Occurrence_Of (Iface_Tag, Loc), Iface_Tag => New_Occurrence_Of (Iface_Tag, Loc),
......
...@@ -5024,16 +5024,15 @@ package body Exp_Ch6 is ...@@ -5024,16 +5024,15 @@ package body Exp_Ch6 is
-- existing object for use as the return object. If the value -- existing object for use as the return object. If the value
-- is two, then the return object must be allocated on the -- is two, then the return object must be allocated on the
-- secondary stack. Otherwise, the object must be allocated in -- secondary stack. Otherwise, the object must be allocated in
-- a storage pool (currently only supported for the global -- a storage pool. We generate an if statement to test the
-- heap, user-defined storage pools TBD ???). We generate an -- implicit allocation formal and initialize a local access
-- if statement to test the implicit allocation formal and -- value appropriately, creating allocators in the secondary
-- initialize a local access value appropriately, creating -- stack and global heap cases. The special formal also exists
-- allocators in the secondary stack and global heap cases. -- and must be tested when the function has a tagged result,
-- The special formal also exists and must be tested when the -- even when the result subtype is constrained, because in
-- function has a tagged result, even when the result subtype -- general such functions can be called in dispatching contexts
-- is constrained, because in general such functions can be -- and must be handled similarly to functions with a class-wide
-- called in dispatching contexts and must be handled similarly -- result.
-- to functions with a class-wide result.
if not Is_Constrained (Ret_Typ) if not Is_Constrained (Ret_Typ)
or else Is_Tagged_Type (Underlying_Type (Ret_Typ)) or else Is_Tagged_Type (Underlying_Type (Ret_Typ))
...@@ -8192,7 +8191,28 @@ package body Exp_Ch6 is ...@@ -8192,7 +8191,28 @@ package body Exp_Ch6 is
(Obj_Decl : Node_Id; (Obj_Decl : Node_Id;
Function_Call : Node_Id) Function_Call : Node_Id)
is is
function Get_Function_Id (Func_Call : Node_Id) return Entity_Id;
-- Get the value of Function_Id, below
function Get_Function_Id (Func_Call : Node_Id) return Entity_Id is
begin
if Is_Entity_Name (Name (Func_Call)) then
return Entity (Name (Func_Call));
elsif Nkind (Name (Func_Call)) = N_Explicit_Dereference then
return Etype (Name (Func_Call));
else
raise Program_Error;
end if;
end Get_Function_Id;
Func_Call : constant Node_Id := Unqual_Conv (Function_Call);
Function_Id : constant Entity_Id := Get_Function_Id (Func_Call);
Result_Subt : constant Entity_Id := Etype (Function_Id);
Obj_Def_Id : constant Entity_Id := Defining_Identifier (Obj_Decl); Obj_Def_Id : constant Entity_Id := Defining_Identifier (Obj_Decl);
Obj_Typ : constant Entity_Id := Etype (Obj_Def_Id);
Encl_Func : constant Entity_Id := Enclosing_Subprogram (Obj_Def_Id); Encl_Func : constant Entity_Id := Enclosing_Subprogram (Obj_Def_Id);
Loc : constant Source_Ptr := Sloc (Function_Call); Loc : constant Source_Ptr := Sloc (Function_Call);
Obj_Loc : constant Source_Ptr := Sloc (Obj_Decl); Obj_Loc : constant Source_Ptr := Sloc (Obj_Decl);
...@@ -8201,15 +8221,21 @@ package body Exp_Ch6 is ...@@ -8201,15 +8221,21 @@ package body Exp_Ch6 is
Caller_Object : Node_Id; Caller_Object : Node_Id;
Def_Id : Entity_Id; Def_Id : Entity_Id;
Fmaster_Actual : Node_Id := Empty; Fmaster_Actual : Node_Id := Empty;
Func_Call : constant Node_Id := Unqual_Conv (Function_Call);
Function_Id : Entity_Id;
Pool_Actual : Node_Id; Pool_Actual : Node_Id;
Designated_Type : Entity_Id; Designated_Type : Entity_Id;
Ptr_Typ : Entity_Id; Ptr_Typ : Entity_Id;
Ptr_Typ_Decl : Node_Id; Ptr_Typ_Decl : Node_Id;
Pass_Caller_Acc : Boolean := False; Pass_Caller_Acc : Boolean := False;
Res_Decl : Node_Id; Res_Decl : Node_Id;
Result_Subt : Entity_Id;
Definite : constant Boolean :=
Caller_Known_Size (Func_Call, Result_Subt)
and then not Is_Class_Wide_Type (Obj_Typ);
-- In the case of "X : T'Class := F(...);", where F returns a
-- Caller_Known_Size (specific) tagged type, we treat it as
-- indefinite, because the code for the Definite case below sets the
-- initialization expression of the object to Empty, which would be
-- illegal Ada, and would cause gigi to mis-allocate X.
begin begin
-- Mark the call as processed as a build-in-place call -- Mark the call as processed as a build-in-place call
...@@ -8217,35 +8243,18 @@ package body Exp_Ch6 is ...@@ -8217,35 +8243,18 @@ package body Exp_Ch6 is
pragma Assert (not Is_Expanded_Build_In_Place_Call (Func_Call)); pragma Assert (not Is_Expanded_Build_In_Place_Call (Func_Call));
Set_Is_Expanded_Build_In_Place_Call (Func_Call); Set_Is_Expanded_Build_In_Place_Call (Func_Call);
if Is_Entity_Name (Name (Func_Call)) then
Function_Id := Entity (Name (Func_Call));
elsif Nkind (Name (Func_Call)) = N_Explicit_Dereference then
Function_Id := Etype (Name (Func_Call));
else
raise Program_Error;
end if;
Result_Subt := Etype (Function_Id);
declare
Definite : constant Boolean :=
Caller_Known_Size (Func_Call, Result_Subt);
begin
-- Create an access type designating the function's result subtype. -- Create an access type designating the function's result subtype.
-- We use the type of the original call because it may be a call to -- We use the type of the original call because it may be a call to an
-- an inherited operation, which the expansion has replaced with the -- inherited operation, which the expansion has replaced with the parent
-- parent operation that yields the parent type. Note that this -- operation that yields the parent type. Note that this access type
-- access type must be declared before we establish a transient -- must be declared before we establish a transient scope, so that it
-- scope, so that it receives the proper accessibility level. -- receives the proper accessibility level.
if Is_Class_Wide_Type (Etype (Defining_Identifier (Obj_Decl))) if Is_Class_Wide_Type (Obj_Typ)
and then not Is_Interface (Etype (Defining_Identifier (Obj_Decl))) and then not Is_Interface (Obj_Typ)
and then not Is_Class_Wide_Type (Etype (Function_Call)) and then not Is_Class_Wide_Type (Etype (Function_Call))
then then
Designated_Type := Etype (Defining_Identifier (Obj_Decl)); Designated_Type := Obj_Typ;
else else
Designated_Type := Etype (Function_Call); Designated_Type := Etype (Function_Call);
end if; end if;
...@@ -8261,17 +8270,17 @@ package body Exp_Ch6 is ...@@ -8261,17 +8270,17 @@ package body Exp_Ch6 is
New_Occurrence_Of (Designated_Type, Loc))); New_Occurrence_Of (Designated_Type, Loc)));
-- The access type and its accompanying object must be inserted after -- The access type and its accompanying object must be inserted after
-- the object declaration in the constrained case, so that the -- the object declaration in the constrained case, so that the function
-- function call can be passed access to the object. In the -- call can be passed access to the object. In the indefinite case, or
-- indefinite case, or if the object declaration is for a return -- if the object declaration is for a return object, the access type and
-- object, the access type and object must be inserted before the -- object must be inserted before the object, since the object
-- object, since the object declaration is rewritten to be a renaming -- declaration is rewritten to be a renaming of a dereference of the
-- of a dereference of the access object. Note: we need to freeze -- access object. Note: we need to freeze Ptr_Typ explicitly, because
-- Ptr_Typ explicitly, because the result object is in a different -- the result object is in a different (transient) scope, so won't cause
-- (transient) scope, so won't cause freezing. -- freezing.
if Definite if Definite
and then not Is_Return_Object (Defining_Identifier (Obj_Decl)) and then not Is_Return_Object (Obj_Def_Id)
then then
Insert_After_And_Analyze (Obj_Decl, Ptr_Typ_Decl); Insert_After_And_Analyze (Obj_Decl, Ptr_Typ_Decl);
else else
...@@ -8296,7 +8305,7 @@ package body Exp_Ch6 is ...@@ -8296,7 +8305,7 @@ package body Exp_Ch6 is
-- really be directly built in place in the aggregate and not in a -- really be directly built in place in the aggregate and not in a
-- temporary. ???) -- temporary. ???)
if Is_Return_Object (Defining_Identifier (Obj_Decl)) then if Is_Return_Object (Obj_Def_Id) then
Pass_Caller_Acc := True; Pass_Caller_Acc := True;
-- When the enclosing function has a BIP_Alloc_Form formal then we -- When the enclosing function has a BIP_Alloc_Form formal then we
...@@ -8339,9 +8348,8 @@ package body Exp_Ch6 is ...@@ -8339,9 +8348,8 @@ package body Exp_Ch6 is
(Encl_Func, BIP_Finalization_Master), Loc); (Encl_Func, BIP_Finalization_Master), Loc);
end if; end if;
-- Retrieve the BIPacc formal from the enclosing function and -- Retrieve the BIPacc formal from the enclosing function and convert
-- convert it to the access type of the callee's BIP_Object_Access -- it to the access type of the callee's BIP_Object_Access formal.
-- formal.
Caller_Object := Caller_Object :=
Make_Unchecked_Type_Conversion (Loc, Make_Unchecked_Type_Conversion (Loc,
...@@ -8357,10 +8365,9 @@ package body Exp_Ch6 is ...@@ -8357,10 +8365,9 @@ package body Exp_Ch6 is
Loc)); Loc));
-- In the definite case, add an implicit actual to the function call -- In the definite case, add an implicit actual to the function call
-- that provides access to the declared object. An unchecked -- that provides access to the declared object. An unchecked conversion
-- conversion to the (specific) result type of the function is -- to the (specific) result type of the function is inserted to handle
-- inserted to handle the case where the object is declared with a -- the case where the object is declared with a class-wide type.
-- class-wide type.
elsif Definite then elsif Definite then
Caller_Object := Caller_Object :=
...@@ -8369,30 +8376,29 @@ package body Exp_Ch6 is ...@@ -8369,30 +8376,29 @@ package body Exp_Ch6 is
Expression => New_Occurrence_Of (Obj_Def_Id, Loc)); Expression => New_Occurrence_Of (Obj_Def_Id, Loc));
-- When the function has a controlling result, an allocation-form -- When the function has a controlling result, an allocation-form
-- parameter must be passed indicating that the caller is -- parameter must be passed indicating that the caller is allocating
-- allocating the result object. This is needed because such a -- the result object. This is needed because such a function can be
-- function can be called as a dispatching operation and must be -- called as a dispatching operation and must be treated similarly to
-- treated similarly to functions with indefinite result subtypes. -- functions with indefinite result subtypes.
Add_Unconstrained_Actuals_To_Build_In_Place_Call Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation); (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
-- The allocation for indefinite library-level objects occurs on the -- The allocation for indefinite library-level objects occurs on the
-- heap as opposed to the secondary stack. This accommodates DLLs -- heap as opposed to the secondary stack. This accommodates DLLs where
-- where the secondary stack is destroyed after each library -- the secondary stack is destroyed after each library unload. This is a
-- unload. This is a hybrid mechanism where a stack-allocated object -- hybrid mechanism where a stack-allocated object lives on the heap.
-- lives on the heap.
elsif Is_Library_Level_Entity (Defining_Identifier (Obj_Decl)) elsif Is_Library_Level_Entity (Obj_Def_Id)
and then not Restriction_Active (No_Implicit_Heap_Allocations) and then not Restriction_Active (No_Implicit_Heap_Allocations)
then then
Add_Unconstrained_Actuals_To_Build_In_Place_Call Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Global_Heap); (Func_Call, Function_Id, Alloc_Form => Global_Heap);
Caller_Object := Empty; Caller_Object := Empty;
-- Create a finalization master for the access result type to -- Create a finalization master for the access result type to ensure
-- ensure that the heap allocation can properly chain the object -- that the heap allocation can properly chain the object and later
-- and later finalize it when the library unit goes out of scope. -- finalize it when the library unit goes out of scope.
if Needs_Finalization (Etype (Func_Call)) then if Needs_Finalization (Etype (Func_Call)) then
Build_Finalization_Master Build_Finalization_Master
...@@ -8407,11 +8413,10 @@ package body Exp_Ch6 is ...@@ -8407,11 +8413,10 @@ package body Exp_Ch6 is
Attribute_Name => Name_Unrestricted_Access); Attribute_Name => Name_Unrestricted_Access);
end if; end if;
-- In other indefinite cases, pass an indication to do the allocation -- In other indefinite cases, pass an indication to do the allocation on
-- on the secondary stack and set Caller_Object to Empty so that a -- the secondary stack and set Caller_Object to Empty so that a null
-- null value will be passed for the caller's object address. A -- value will be passed for the caller's object address. A transient
-- transient scope is established to ensure eventual cleanup of the -- scope is established to ensure eventual cleanup of the result.
-- result.
else else
Add_Unconstrained_Actuals_To_Build_In_Place_Call Add_Unconstrained_Actuals_To_Build_In_Place_Call
...@@ -8454,8 +8459,8 @@ package body Exp_Ch6 is ...@@ -8454,8 +8459,8 @@ package body Exp_Ch6 is
Is_Access => Pass_Caller_Acc); Is_Access => Pass_Caller_Acc);
-- Finally, create an access object initialized to a reference to the -- Finally, create an access object initialized to a reference to the
-- function call. We know this access value cannot be null, so mark -- function call. We know this access value cannot be null, so mark the
-- the entity accordingly to suppress the access check. -- entity accordingly to suppress the access check.
Def_Id := Make_Temporary (Loc, 'R', Func_Call); Def_Id := Make_Temporary (Loc, 'R', Func_Call);
Set_Etype (Def_Id, Ptr_Typ); Set_Etype (Def_Id, Ptr_Typ);
...@@ -8483,12 +8488,12 @@ package body Exp_Ch6 is ...@@ -8483,12 +8488,12 @@ package body Exp_Ch6 is
Insert_After_And_Analyze (Ptr_Typ_Decl, Res_Decl); Insert_After_And_Analyze (Ptr_Typ_Decl, Res_Decl);
-- If the result subtype of the called function is definite and is -- If the result subtype of the called function is definite and is not
-- not itself the return expression of an enclosing BIP function, -- itself the return expression of an enclosing BIP function, then mark
-- then mark the object as having no initialization. -- the object as having no initialization.
if Definite if Definite
and then not Is_Return_Object (Defining_Identifier (Obj_Decl)) and then not Is_Return_Object (Obj_Def_Id)
then then
-- The related object declaration is encased in a transient block -- The related object declaration is encased in a transient block
-- because the build-in-place function call contains at least one -- because the build-in-place function call contains at least one
...@@ -8498,9 +8503,9 @@ package body Exp_Ch6 is ...@@ -8498,9 +8503,9 @@ package body Exp_Ch6 is
-- Obj : ... := BIP_Func_Call (Ctrl_Func_Call); -- Obj : ... := BIP_Func_Call (Ctrl_Func_Call);
-- Since the build-in-place expansion decouples the call from the -- Since the build-in-place expansion decouples the call from the
-- object declaration, the finalization machinery lacks the -- object declaration, the finalization machinery lacks the context
-- context which prompted the generation of the transient -- which prompted the generation of the transient block. To resolve
-- block. To resolve this scenario, store the build-in-place call. -- this scenario, store the build-in-place call.
if Scope_Is_Transient and then Node_To_Be_Wrapped = Obj_Decl then if Scope_Is_Transient and then Node_To_Be_Wrapped = Obj_Decl then
Set_BIP_Initialization_Call (Obj_Def_Id, Res_Decl); Set_BIP_Initialization_Call (Obj_Def_Id, Res_Decl);
...@@ -8528,7 +8533,7 @@ package body Exp_Ch6 is ...@@ -8528,7 +8533,7 @@ package body Exp_Ch6 is
New_Occurrence_Of (Designated_Type, Obj_Loc), New_Occurrence_Of (Designated_Type, Obj_Loc),
Name => Call_Deref)); Name => Call_Deref));
Set_Renamed_Object (Defining_Identifier (Obj_Decl), Call_Deref); Set_Renamed_Object (Obj_Def_Id, Call_Deref);
-- If the original entity comes from source, then mark the new -- If the original entity comes from source, then mark the new
-- entity as needing debug information, even though it's defined -- entity as needing debug information, even though it's defined
...@@ -8537,26 +8542,13 @@ package body Exp_Ch6 is ...@@ -8537,26 +8542,13 @@ package body Exp_Ch6 is
-- Debug_Renaming_Declaration is called during analysis. -- Debug_Renaming_Declaration is called during analysis.
if Comes_From_Source (Obj_Def_Id) then if Comes_From_Source (Obj_Def_Id) then
Set_Debug_Info_Needed (Defining_Identifier (Obj_Decl)); Set_Debug_Info_Needed (Obj_Def_Id);
end if; end if;
Analyze (Obj_Decl); Analyze (Obj_Decl);
Replace_Renaming_Declaration_Id Replace_Renaming_Declaration_Id
(Obj_Decl, Original_Node (Obj_Decl)); (Obj_Decl, Original_Node (Obj_Decl));
end if; end if;
end;
-- If the object entity has a class-wide Etype, then we need to change
-- it to the result subtype of the function call, because otherwise the
-- object will be class-wide without an explicit initialization and
-- won't be allocated properly by the back end. It seems unclean to make
-- such a revision to the type at this point, and we should try to
-- improve this treatment when build-in-place functions with class-wide
-- results are implemented. ???
if Is_Class_Wide_Type (Etype (Defining_Identifier (Obj_Decl))) then
Set_Etype (Defining_Identifier (Obj_Decl), Result_Subt);
end if;
end Make_Build_In_Place_Call_In_Object_Declaration; end Make_Build_In_Place_Call_In_Object_Declaration;
------------------------------------------------- -------------------------------------------------
......
...@@ -29,6 +29,7 @@ with Debug; use Debug; ...@@ -29,6 +29,7 @@ with Debug; use Debug;
with Einfo; use Einfo; with Einfo; use Einfo;
with Elists; use Elists; with Elists; use Elists;
with Errout; use Errout; with Errout; use Errout;
with Expander; use Expander;
with Exp_Atag; use Exp_Atag; with Exp_Atag; use Exp_Atag;
with Exp_Ch6; use Exp_Ch6; with Exp_Ch6; use Exp_Ch6;
with Exp_CG; use Exp_CG; with Exp_CG; use Exp_CG;
...@@ -300,6 +301,32 @@ package body Exp_Disp is ...@@ -300,6 +301,32 @@ package body Exp_Disp is
end Building_Static_DT; end Building_Static_DT;
---------------------------------- ----------------------------------
-- Building_Static_Secondary_DT --
----------------------------------
function Building_Static_Secondary_DT (Typ : Entity_Id) return Boolean is
Full_Typ : Entity_Id := Typ;
Root_Typ : Entity_Id := Root_Type (Typ);
begin
-- Handle private types
if Present (Full_View (Typ)) then
Full_Typ := Full_View (Typ);
end if;
if Present (Full_View (Root_Typ)) then
Root_Typ := Full_View (Root_Typ);
end if;
return Building_Static_DT (Full_Typ)
and then not Is_Interface (Full_Typ)
and then Has_Interfaces (Full_Typ)
and then (Full_Typ = Root_Typ
or else not Is_Variable_Size_Record (Etype (Full_Typ)));
end Building_Static_Secondary_DT;
----------------------------------
-- Build_Static_Dispatch_Tables -- -- Build_Static_Dispatch_Tables --
---------------------------------- ----------------------------------
...@@ -1693,11 +1720,10 @@ package body Exp_Disp is ...@@ -1693,11 +1720,10 @@ package body Exp_Disp is
if From_Limited_With (Actual_Typ) then if From_Limited_With (Actual_Typ) then
-- If the type of the actual parameter comes from a -- If the type of the actual parameter comes from a limited
-- limited with-clause and the non-limited view is already -- with_clause and the nonlimited view is already available,
-- available, we replace the anonymous access type by -- we replace the anonymous access type by a duplicate
-- a duplicate declaration whose designated type is the -- declaration whose designated type is the nonlimited view.
-- non-limited view.
if Has_Non_Limited_View (Actual_DDT) then if Has_Non_Limited_View (Actual_DDT) then
Anon := New_Copy (Actual_Typ); Anon := New_Copy (Actual_Typ);
...@@ -3755,6 +3781,11 @@ package body Exp_Disp is ...@@ -3755,6 +3781,11 @@ package body Exp_Disp is
DT_Aggr : constant Elist_Id := New_Elmt_List; DT_Aggr : constant Elist_Id := New_Elmt_List;
-- Entities marked with attribute Is_Dispatch_Table_Entity -- Entities marked with attribute Is_Dispatch_Table_Entity
Dummy_Object : Entity_Id := Empty;
-- Extra nonexistent object of type Typ internally used to compute the
-- offset to the components that reference secondary dispatch tables.
-- Used to statically allocate secondary dispatch tables.
procedure Check_Premature_Freezing procedure Check_Premature_Freezing
(Subp : Entity_Id; (Subp : Entity_Id;
Tagged_Type : Entity_Id; Tagged_Type : Entity_Id;
...@@ -3783,6 +3814,7 @@ package body Exp_Disp is ...@@ -3783,6 +3814,7 @@ package body Exp_Disp is
procedure Make_Secondary_DT procedure Make_Secondary_DT
(Typ : Entity_Id; (Typ : Entity_Id;
Iface : Entity_Id; Iface : Entity_Id;
Iface_Comp : Node_Id;
Suffix_Index : Int; Suffix_Index : Int;
Num_Iface_Prims : Nat; Num_Iface_Prims : Nat;
Iface_DT_Ptr : Entity_Id; Iface_DT_Ptr : Entity_Id;
...@@ -3941,6 +3973,7 @@ package body Exp_Disp is ...@@ -3941,6 +3973,7 @@ package body Exp_Disp is
procedure Make_Secondary_DT procedure Make_Secondary_DT
(Typ : Entity_Id; (Typ : Entity_Id;
Iface : Entity_Id; Iface : Entity_Id;
Iface_Comp : Node_Id;
Suffix_Index : Int; Suffix_Index : Int;
Num_Iface_Prims : Nat; Num_Iface_Prims : Nat;
Iface_DT_Ptr : Entity_Id; Iface_DT_Ptr : Entity_Id;
...@@ -4179,11 +4212,26 @@ package body Exp_Disp is ...@@ -4179,11 +4212,26 @@ package body Exp_Disp is
Prefix => New_Occurrence_Of (Predef_Prims, Loc), Prefix => New_Occurrence_Of (Predef_Prims, Loc),
Attribute_Name => Name_Address)); Attribute_Name => Name_Address));
-- Note: The correct value of Offset_To_Top will be set by the init -- If the location of the component that references this secondary
-- subprogram -- dispatch table is variable then we have not declared the internal
-- dummy object; the value of Offset_To_Top will be set by the init
-- subprogram.
if No (Dummy_Object) then
Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0)); Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0));
else
Append_To (DT_Aggr_List,
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
Prefix =>
New_Occurrence_Of (Dummy_Object, Loc),
Selector_Name =>
New_Occurrence_Of (Iface_Comp, Loc)),
Attribute_Name => Name_Position));
end if;
-- Generate the Object Specific Data table required to dispatch calls -- Generate the Object Specific Data table required to dispatch calls
-- through synchronized interfaces. -- through synchronized interfaces.
...@@ -4407,15 +4455,16 @@ package body Exp_Disp is ...@@ -4407,15 +4455,16 @@ package body Exp_Disp is
Append_Elmt (New_Node, DT_Aggr); Append_Elmt (New_Node, DT_Aggr);
-- Note: Secondary dispatch tables cannot be declared constant -- Note: Secondary dispatch tables are declared constant only if
-- because the component Offset_To_Top is currently initialized -- we can compute their offset field by means of the extra dummy
-- by the IP routine. -- object; otherwise they cannot be declared constant and the
-- Offset_To_Top component is initialized by the IP routine.
Append_To (Result, Append_To (Result,
Make_Object_Declaration (Loc, Make_Object_Declaration (Loc,
Defining_Identifier => Iface_DT, Defining_Identifier => Iface_DT,
Aliased_Present => True, Aliased_Present => True,
Constant_Present => False, Constant_Present => Present (Dummy_Object),
Object_Definition => Object_Definition =>
Make_Subtype_Indication (Loc, Make_Subtype_Indication (Loc,
...@@ -4678,6 +4727,93 @@ package body Exp_Disp is ...@@ -4678,6 +4727,93 @@ package body Exp_Disp is
end; end;
end if; end if;
if Building_Static_Secondary_DT (Typ) then
declare
Cannot_Have_Null_Disc : Boolean := False;
Name_Dummy_Object : constant Name_Id :=
New_External_Name (Tname,
'P', Suffix_Index => -1);
begin
Dummy_Object := Make_Defining_Identifier (Loc, Name_Dummy_Object);
-- Define the extra object imported and constant to avoid linker
-- errors (since this object is never declared). Required because
-- we implement RM 13.3(19) for exported and imported (variable)
-- objects by making them volatile.
Set_Is_Imported (Dummy_Object);
Set_Ekind (Dummy_Object, E_Constant);
Set_Is_True_Constant (Dummy_Object);
Set_Related_Type (Dummy_Object, Typ);
-- The scope must be set now to call Get_External_Name
Set_Scope (Dummy_Object, Current_Scope);
Get_External_Name (Dummy_Object);
Set_Interface_Name (Dummy_Object,
Make_String_Literal (Loc, Strval => String_From_Name_Buffer));
-- Ensure proper Sprint output of this implicit importation
Set_Is_Internal (Dummy_Object);
if not Has_Discriminants (Typ) then
Append_To (Result,
Make_Object_Declaration (Loc,
Defining_Identifier => Dummy_Object,
Constant_Present => True,
Object_Definition => New_Occurrence_Of (Typ, Loc)));
else
declare
Constr_List : constant List_Id := New_List;
Discrim : Node_Id;
begin
Discrim := First_Discriminant (Typ);
while Present (Discrim) loop
if Is_Discrete_Type (Etype (Discrim)) then
Append_To (Constr_List,
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Etype (Discrim), Loc),
Attribute_Name => Name_First));
else
pragma Assert (Is_Access_Type (Etype (Discrim)));
Cannot_Have_Null_Disc :=
Cannot_Have_Null_Disc
or else Can_Never_Be_Null (Etype (Discrim));
Append_To (Constr_List, Make_Null (Loc));
end if;
Next_Discriminant (Discrim);
end loop;
Append_To (Result,
Make_Object_Declaration (Loc,
Defining_Identifier => Dummy_Object,
Constant_Present => True,
Object_Definition =>
Make_Subtype_Indication (Loc,
Subtype_Mark => New_Occurrence_Of (Typ, Loc),
Constraint =>
Make_Index_Or_Discriminant_Constraint (Loc,
Constraints => Constr_List))));
end;
end if;
-- Given that the dummy object will not be declared at run time,
-- analyze its declaration with expansion disabled and warnings
-- and error messages ignored.
Expander_Mode_Save_And_Set (False);
Ignore_Errors_Enable := Ignore_Errors_Enable + 1;
Analyze (Last (Result), Suppress => All_Checks);
Ignore_Errors_Enable := Ignore_Errors_Enable - 1;
Expander_Mode_Restore;
end;
end if;
-- Ada 2005 (AI-251): Build the secondary dispatch tables -- Ada 2005 (AI-251): Build the secondary dispatch tables
if Has_Interfaces (Typ) then if Has_Interfaces (Typ) then
...@@ -4704,6 +4840,7 @@ package body Exp_Disp is ...@@ -4704,6 +4840,7 @@ package body Exp_Disp is
(Typ => Typ, (Typ => Typ,
Iface => Base_Type Iface => Base_Type
(Related_Type (Node (AI_Tag_Comp))), (Related_Type (Node (AI_Tag_Comp))),
Iface_Comp => Node (AI_Tag_Comp),
Suffix_Index => Suffix_Index, Suffix_Index => Suffix_Index,
Num_Iface_Prims => UI_To_Int Num_Iface_Prims => UI_To_Int
(DT_Entry_Count (Node (AI_Tag_Comp))), (DT_Entry_Count (Node (AI_Tag_Comp))),
...@@ -4731,6 +4868,7 @@ package body Exp_Disp is ...@@ -4731,6 +4868,7 @@ package body Exp_Disp is
(Typ => Typ, (Typ => Typ,
Iface => Base_Type Iface => Base_Type
(Related_Type (Node (AI_Tag_Comp))), (Related_Type (Node (AI_Tag_Comp))),
Iface_Comp => Node (AI_Tag_Comp),
Suffix_Index => -1, Suffix_Index => -1,
Num_Iface_Prims => UI_To_Int Num_Iface_Prims => UI_To_Int
(DT_Entry_Count (Node (AI_Tag_Comp))), (DT_Entry_Count (Node (AI_Tag_Comp))),
......
...@@ -174,6 +174,11 @@ package Exp_Disp is ...@@ -174,6 +174,11 @@ package Exp_Disp is
pragma Inline (Building_Static_DT); pragma Inline (Building_Static_DT);
-- Returns true when building statically allocated dispatch tables -- Returns true when building statically allocated dispatch tables
function Building_Static_Secondary_DT (Typ : Entity_Id) return Boolean;
pragma Inline (Building_Static_Secondary_DT);
-- Returns true when building statically allocated secondary dispatch
-- tables
procedure Build_Static_Dispatch_Tables (N : Node_Id); procedure Build_Static_Dispatch_Tables (N : Node_Id);
-- N is a library level package declaration or package body. Build the -- N is a library level package declaration or package body. Build the
-- static dispatch table of the tagged types defined at library level. In -- static dispatch table of the tagged types defined at library level. In
......
...@@ -8860,7 +8860,7 @@ package body Sem_Ch4 is ...@@ -8860,7 +8860,7 @@ package body Sem_Ch4 is
while Present (Hom) loop while Present (Hom) loop
if Ekind_In (Hom, E_Procedure, E_Function) if Ekind_In (Hom, E_Procedure, E_Function)
and then (not Is_Hidden (Hom) or else In_Instance) and then (not Is_Hidden (Hom) or else In_Instance)
and then Scope (Hom) = Scope (Anc_Type) and then Scope (Hom) = Scope (Base_Type (Anc_Type))
and then Present (First_Formal (Hom)) and then Present (First_Formal (Hom))
and then and then
(Base_Type (Etype (First_Formal (Hom))) = Cls_Type (Base_Type (Etype (First_Formal (Hom))) = Cls_Type
...@@ -8921,8 +8921,13 @@ package body Sem_Ch4 is ...@@ -8921,8 +8921,13 @@ package body Sem_Ch4 is
Success => Success, Success => Success,
Skip_First => True); Skip_First => True);
-- The same operation may be encountered on two homonym
-- traversals, before and after looking at interfaces.
-- Check for this case before reporting a real ambiguity.
if Present (Valid_Candidate (Success, Call_Node, Hom)) if Present (Valid_Candidate (Success, Call_Node, Hom))
and then Nkind (Call_Node) /= N_Function_Call and then Nkind (Call_Node) /= N_Function_Call
and then Hom /= Matching_Op
then then
Error_Msg_NE ("ambiguous call to&", N, Hom); Error_Msg_NE ("ambiguous call to&", N, Hom);
Report_Ambiguity (Matching_Op); Report_Ambiguity (Matching_Op);
......
...@@ -20383,6 +20383,17 @@ package body Sem_Util is ...@@ -20383,6 +20383,17 @@ package body Sem_Util is
(Nearest_Dynamic_Scope (Nearest_Dynamic_Scope
(Defining_Entity (Node_Par))); (Defining_Entity (Node_Par)));
-- For a return statement within a function, return
-- the depth of the function itself. This is not just
-- a small optimization, but matters when analyzing
-- the expression in an expression function before
-- the body is created.
when N_Simple_Return_Statement =>
if Ekind (Current_Scope) = E_Function then
return Scope_Depth (Current_Scope);
end if;
when others => when others =>
null; null;
end case; end case;
......
with Ada.Text_IO; use Ada.Text_IO;
with Class_Wide3_Pkg; use Class_Wide3_Pkg;
procedure Class_Wide3 is
DC : Disc_Child := (N => 1, I => 3, J => 5);
begin
DC.Put_Line;
end Class_Wide3;
package Class_Wide3_Pkg is
type Iface is interface;
type Iface_Ptr is access all Iface'Class;
procedure Put_Line (I : Iface'Class);
type Root is tagged record
I : Integer;
end record;
type Disc_Child (N : Integer) is new Root and Iface with record
J : Integer;
end record;
end Class_Wide3_Pkg;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment