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,345 +8243,311 @@ package body Exp_Ch6 is ...@@ -8217,345 +8243,311 @@ 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 -- Create an access type designating the function's result subtype.
Function_Id := Entity (Name (Func_Call)); -- We use the type of the original call because it may be a call to an
-- inherited operation, which the expansion has replaced with the parent
-- operation that yields the parent type. Note that this access type
-- must be declared before we establish a transient scope, so that it
-- receives the proper accessibility level.
elsif Nkind (Name (Func_Call)) = N_Explicit_Dereference then if Is_Class_Wide_Type (Obj_Typ)
Function_Id := Etype (Name (Func_Call)); and then not Is_Interface (Obj_Typ)
and then not Is_Class_Wide_Type (Etype (Function_Call))
then
Designated_Type := Obj_Typ;
else
Designated_Type := Etype (Function_Call);
end if;
Ptr_Typ := Make_Temporary (Loc, 'A');
Ptr_Typ_Decl :=
Make_Full_Type_Declaration (Loc,
Defining_Identifier => Ptr_Typ,
Type_Definition =>
Make_Access_To_Object_Definition (Loc,
All_Present => True,
Subtype_Indication =>
New_Occurrence_Of (Designated_Type, Loc)));
-- The access type and its accompanying object must be inserted after
-- the object declaration in the constrained case, so that the function
-- call can be passed access to the object. In the indefinite case, or
-- if the object declaration is for a return object, the access type and
-- object must be inserted before the object, since the object
-- declaration is rewritten to be a renaming of a dereference of the
-- access object. Note: we need to freeze Ptr_Typ explicitly, because
-- the result object is in a different (transient) scope, so won't cause
-- freezing.
if Definite
and then not Is_Return_Object (Obj_Def_Id)
then
Insert_After_And_Analyze (Obj_Decl, Ptr_Typ_Decl);
else else
raise Program_Error; Insert_Action (Obj_Decl, Ptr_Typ_Decl);
end if; end if;
Result_Subt := Etype (Function_Id); -- Force immediate freezing of Ptr_Typ because Res_Decl will be
-- elaborated in an inner (transient) scope and thus won't cause
-- freezing by itself. It's not an itype, but it needs to be frozen
-- inside the current subprogram (see Freeze_Outside in freeze.adb).
Freeze_Itype (Ptr_Typ, Ptr_Typ_Decl);
-- If the object is a return object of an enclosing build-in-place
-- function, then the implicit build-in-place parameters of the
-- enclosing function are simply passed along to the called function.
-- (Unfortunately, this won't cover the case of extension aggregates
-- where the ancestor part is a build-in-place indefinite function
-- call that should be passed along the caller's parameters.
-- Currently those get mishandled by reassigning the result of the
-- call to the aggregate return object, when the call result should
-- really be directly built in place in the aggregate and not in a
-- temporary. ???)
if Is_Return_Object (Obj_Def_Id) then
Pass_Caller_Acc := True;
-- When the enclosing function has a BIP_Alloc_Form formal then we
-- pass it along to the callee (such as when the enclosing
-- function has an unconstrained or tagged result type).
if Needs_BIP_Alloc_Form (Encl_Func) then
if RTE_Available (RE_Root_Storage_Pool_Ptr) then
Pool_Actual :=
New_Occurrence_Of
(Build_In_Place_Formal
(Encl_Func, BIP_Storage_Pool), Loc);
declare -- The build-in-place pool formal is not built on e.g. ZFP
Definite : constant Boolean :=
Caller_Known_Size (Func_Call, Result_Subt);
begin else
-- Create an access type designating the function's result subtype. Pool_Actual := Empty;
-- We use the type of the original call because it may be a call to end if;
-- an inherited operation, which the expansion has replaced with the
-- parent operation that yields the parent type. Note that this Add_Unconstrained_Actuals_To_Build_In_Place_Call
-- access type must be declared before we establish a transient (Function_Call => Func_Call,
-- scope, so that it receives the proper accessibility level. Function_Id => Function_Id,
Alloc_Form_Exp =>
if Is_Class_Wide_Type (Etype (Defining_Identifier (Obj_Decl))) New_Occurrence_Of
and then not Is_Interface (Etype (Defining_Identifier (Obj_Decl))) (Build_In_Place_Formal (Encl_Func, BIP_Alloc_Form), Loc),
and then not Is_Class_Wide_Type (Etype (Function_Call)) Pool_Actual => Pool_Actual);
then
Designated_Type := Etype (Defining_Identifier (Obj_Decl)); -- Otherwise, if enclosing function has a definite result subtype,
else -- then caller allocation will be used.
Designated_Type := Etype (Function_Call);
end if;
Ptr_Typ := Make_Temporary (Loc, 'A');
Ptr_Typ_Decl :=
Make_Full_Type_Declaration (Loc,
Defining_Identifier => Ptr_Typ,
Type_Definition =>
Make_Access_To_Object_Definition (Loc,
All_Present => True,
Subtype_Indication =>
New_Occurrence_Of (Designated_Type, Loc)));
-- The access type and its accompanying object must be inserted after
-- the object declaration in the constrained case, so that the
-- function call can be passed access to the object. In the
-- indefinite case, or if the object declaration is for a return
-- object, the access type and object must be inserted before the
-- object, since the object declaration is rewritten to be a renaming
-- of a dereference of the access object. Note: we need to freeze
-- Ptr_Typ explicitly, because the result object is in a different
-- (transient) scope, so won't cause freezing.
if Definite
and then not Is_Return_Object (Defining_Identifier (Obj_Decl))
then
Insert_After_And_Analyze (Obj_Decl, Ptr_Typ_Decl);
else else
Insert_Action (Obj_Decl, Ptr_Typ_Decl); Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
end if; end if;
-- Force immediate freezing of Ptr_Typ because Res_Decl will be if Needs_BIP_Finalization_Master (Encl_Func) then
-- elaborated in an inner (transient) scope and thus won't cause Fmaster_Actual :=
-- freezing by itself. It's not an itype, but it needs to be frozen New_Occurrence_Of
-- inside the current subprogram (see Freeze_Outside in freeze.adb). (Build_In_Place_Formal
(Encl_Func, BIP_Finalization_Master), Loc);
Freeze_Itype (Ptr_Typ, Ptr_Typ_Decl); end if;
-- If the object is a return object of an enclosing build-in-place -- Retrieve the BIPacc formal from the enclosing function and convert
-- function, then the implicit build-in-place parameters of the -- it to the access type of the callee's BIP_Object_Access formal.
-- enclosing function are simply passed along to the called function.
-- (Unfortunately, this won't cover the case of extension aggregates
-- where the ancestor part is a build-in-place indefinite function
-- call that should be passed along the caller's parameters.
-- Currently those get mishandled by reassigning the result of the
-- call to the aggregate return object, when the call result should
-- really be directly built in place in the aggregate and not in a
-- temporary. ???)
if Is_Return_Object (Defining_Identifier (Obj_Decl)) then Caller_Object :=
Pass_Caller_Acc := True; Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark =>
New_Occurrence_Of
(Etype
(Build_In_Place_Formal
(Function_Id, BIP_Object_Access)),
Loc),
Expression =>
New_Occurrence_Of
(Build_In_Place_Formal (Encl_Func, BIP_Object_Access),
Loc));
-- When the enclosing function has a BIP_Alloc_Form formal then we -- In the definite case, add an implicit actual to the function call
-- pass it along to the callee (such as when the enclosing -- that provides access to the declared object. An unchecked conversion
-- function has an unconstrained or tagged result type). -- to the (specific) result type of the function is inserted to handle
-- the case where the object is declared with a class-wide type.
if Needs_BIP_Alloc_Form (Encl_Func) then elsif Definite then
if RTE_Available (RE_Root_Storage_Pool_Ptr) then Caller_Object :=
Pool_Actual := Make_Unchecked_Type_Conversion (Loc,
New_Occurrence_Of Subtype_Mark => New_Occurrence_Of (Result_Subt, Loc),
(Build_In_Place_Formal Expression => New_Occurrence_Of (Obj_Def_Id, Loc));
(Encl_Func, BIP_Storage_Pool), Loc);
-- The build-in-place pool formal is not built on e.g. ZFP -- When the function has a controlling result, an allocation-form
-- parameter must be passed indicating that the caller is allocating
-- the result object. This is needed because such a function can be
-- called as a dispatching operation and must be treated similarly to
-- functions with indefinite result subtypes.
else Add_Unconstrained_Actuals_To_Build_In_Place_Call
Pool_Actual := Empty; (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
end if;
Add_Unconstrained_Actuals_To_Build_In_Place_Call -- The allocation for indefinite library-level objects occurs on the
(Function_Call => Func_Call, -- heap as opposed to the secondary stack. This accommodates DLLs where
Function_Id => Function_Id, -- the secondary stack is destroyed after each library unload. This is a
Alloc_Form_Exp => -- hybrid mechanism where a stack-allocated object lives on the heap.
New_Occurrence_Of
(Build_In_Place_Formal (Encl_Func, BIP_Alloc_Form), Loc),
Pool_Actual => Pool_Actual);
-- Otherwise, if enclosing function has a definite result subtype, elsif Is_Library_Level_Entity (Obj_Def_Id)
-- then caller allocation will be used. and then not Restriction_Active (No_Implicit_Heap_Allocations)
then
Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Global_Heap);
Caller_Object := Empty;
else -- Create a finalization master for the access result type to ensure
Add_Unconstrained_Actuals_To_Build_In_Place_Call -- that the heap allocation can properly chain the object and later
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation); -- finalize it when the library unit goes out of scope.
end if;
if Needs_BIP_Finalization_Master (Encl_Func) then if Needs_Finalization (Etype (Func_Call)) then
Fmaster_Actual := Build_Finalization_Master
New_Occurrence_Of (Typ => Ptr_Typ,
(Build_In_Place_Formal For_Lib_Level => True,
(Encl_Func, BIP_Finalization_Master), Loc); Insertion_Node => Ptr_Typ_Decl);
end if;
-- Retrieve the BIPacc formal from the enclosing function and Fmaster_Actual :=
-- convert it to the access type of the callee's BIP_Object_Access Make_Attribute_Reference (Loc,
-- formal. Prefix =>
New_Occurrence_Of (Finalization_Master (Ptr_Typ), Loc),
Caller_Object := Attribute_Name => Name_Unrestricted_Access);
Make_Unchecked_Type_Conversion (Loc, end if;
Subtype_Mark =>
New_Occurrence_Of
(Etype
(Build_In_Place_Formal
(Function_Id, BIP_Object_Access)),
Loc),
Expression =>
New_Occurrence_Of
(Build_In_Place_Formal (Encl_Func, BIP_Object_Access),
Loc));
-- In the definite case, add an implicit actual to the function call
-- that provides access to the declared object. An unchecked
-- conversion to the (specific) result type of the function is
-- inserted to handle the case where the object is declared with a
-- class-wide type.
elsif Definite then
Caller_Object :=
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark => New_Occurrence_Of (Result_Subt, Loc),
Expression => New_Occurrence_Of (Obj_Def_Id, Loc));
-- When the function has a controlling result, an allocation-form
-- parameter must be passed indicating that the caller is
-- allocating the result object. This is needed because such a
-- function can be called as a dispatching operation and must be
-- treated similarly to functions with indefinite result subtypes.
Add_Unconstrained_Actuals_To_Build_In_Place_Call -- In other indefinite cases, pass an indication to do the allocation on
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation); -- the secondary stack and set Caller_Object to Empty so that a null
-- value will be passed for the caller's object address. A transient
-- scope is established to ensure eventual cleanup of the result.
-- The allocation for indefinite library-level objects occurs on the else
-- heap as opposed to the secondary stack. This accommodates DLLs Add_Unconstrained_Actuals_To_Build_In_Place_Call
-- where the secondary stack is destroyed after each library (Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
-- unload. This is a hybrid mechanism where a stack-allocated object Caller_Object := Empty;
-- lives on the heap.
elsif Is_Library_Level_Entity (Defining_Identifier (Obj_Decl)) Establish_Transient_Scope (Obj_Decl, Sec_Stack => True);
and then not Restriction_Active (No_Implicit_Heap_Allocations) end if;
then
Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Global_Heap);
Caller_Object := Empty;
-- Create a finalization master for the access result type to -- Pass along any finalization master actual, which is needed in the
-- ensure that the heap allocation can properly chain the object -- case where the called function initializes a return object of an
-- and later finalize it when the library unit goes out of scope. -- enclosing build-in-place function.
if Needs_Finalization (Etype (Func_Call)) then Add_Finalization_Master_Actual_To_Build_In_Place_Call
Build_Finalization_Master (Func_Call => Func_Call,
(Typ => Ptr_Typ, Func_Id => Function_Id,
For_Lib_Level => True, Master_Exp => Fmaster_Actual);
Insertion_Node => Ptr_Typ_Decl);
Fmaster_Actual := if Nkind (Parent (Obj_Decl)) = N_Extended_Return_Statement
Make_Attribute_Reference (Loc, and then Has_Task (Result_Subt)
Prefix => then
New_Occurrence_Of (Finalization_Master (Ptr_Typ), Loc), -- Here we're passing along the master that was passed in to this
Attribute_Name => Name_Unrestricted_Access); -- function.
end if;
-- In other indefinite cases, pass an indication to do the allocation Add_Task_Actuals_To_Build_In_Place_Call
-- on the secondary stack and set Caller_Object to Empty so that a (Func_Call, Function_Id,
-- null value will be passed for the caller's object address. A Master_Actual =>
-- transient scope is established to ensure eventual cleanup of the New_Occurrence_Of
-- result. (Build_In_Place_Formal (Encl_Func, BIP_Task_Master), Loc));
else else
Add_Unconstrained_Actuals_To_Build_In_Place_Call Add_Task_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Secondary_Stack); (Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster));
Caller_Object := Empty; end if;
Establish_Transient_Scope (Obj_Decl, Sec_Stack => True); Add_Access_Actual_To_Build_In_Place_Call
end if; (Func_Call,
Function_Id,
Caller_Object,
Is_Access => Pass_Caller_Acc);
-- Pass along any finalization master actual, which is needed in the -- Finally, create an access object initialized to a reference to the
-- case where the called function initializes a return object of an -- function call. We know this access value cannot be null, so mark the
-- enclosing build-in-place function. -- entity accordingly to suppress the access check.
Add_Finalization_Master_Actual_To_Build_In_Place_Call Def_Id := Make_Temporary (Loc, 'R', Func_Call);
(Func_Call => Func_Call, Set_Etype (Def_Id, Ptr_Typ);
Func_Id => Function_Id, Set_Is_Known_Non_Null (Def_Id);
Master_Exp => Fmaster_Actual);
if Nkind (Parent (Obj_Decl)) = N_Extended_Return_Statement if Nkind (Function_Call) = N_Type_Conversion then
and then Has_Task (Result_Subt) Res_Decl :=
then Make_Object_Declaration (Loc,
-- Here we're passing along the master that was passed in to this Defining_Identifier => Def_Id,
-- function. Constant_Present => True,
Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc),
Expression =>
Make_Unchecked_Type_Conversion (Loc,
New_Occurrence_Of (Ptr_Typ, Loc),
Make_Reference (Loc, Relocate_Node (Func_Call))));
else
Res_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Def_Id,
Constant_Present => True,
Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc),
Expression =>
Make_Reference (Loc, Relocate_Node (Func_Call)));
end if;
Add_Task_Actuals_To_Build_In_Place_Call Insert_After_And_Analyze (Ptr_Typ_Decl, Res_Decl);
(Func_Call, Function_Id,
Master_Actual =>
New_Occurrence_Of
(Build_In_Place_Formal (Encl_Func, BIP_Task_Master), Loc));
else -- If the result subtype of the called function is definite and is not
Add_Task_Actuals_To_Build_In_Place_Call -- itself the return expression of an enclosing BIP function, then mark
(Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster)); -- the object as having no initialization.
end if;
Add_Access_Actual_To_Build_In_Place_Call if Definite
(Func_Call, and then not Is_Return_Object (Obj_Def_Id)
Function_Id, then
Caller_Object, -- The related object declaration is encased in a transient block
Is_Access => Pass_Caller_Acc); -- because the build-in-place function call contains at least one
-- nested function call that produces a controlled transient
-- temporary:
-- Finally, create an access object initialized to a reference to the -- Obj : ... := BIP_Func_Call (Ctrl_Func_Call);
-- function call. We know this access value cannot be null, so mark
-- the entity accordingly to suppress the access check.
Def_Id := Make_Temporary (Loc, 'R', Func_Call); -- Since the build-in-place expansion decouples the call from the
Set_Etype (Def_Id, Ptr_Typ); -- object declaration, the finalization machinery lacks the context
Set_Is_Known_Non_Null (Def_Id); -- which prompted the generation of the transient block. To resolve
-- this scenario, store the build-in-place call.
if Nkind (Function_Call) = N_Type_Conversion then if Scope_Is_Transient and then Node_To_Be_Wrapped = Obj_Decl then
Res_Decl := Set_BIP_Initialization_Call (Obj_Def_Id, Res_Decl);
Make_Object_Declaration (Loc,
Defining_Identifier => Def_Id,
Constant_Present => True,
Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc),
Expression =>
Make_Unchecked_Type_Conversion (Loc,
New_Occurrence_Of (Ptr_Typ, Loc),
Make_Reference (Loc, Relocate_Node (Func_Call))));
else
Res_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Def_Id,
Constant_Present => True,
Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc),
Expression =>
Make_Reference (Loc, Relocate_Node (Func_Call)));
end if; end if;
Insert_After_And_Analyze (Ptr_Typ_Decl, Res_Decl); Set_Expression (Obj_Decl, Empty);
Set_No_Initialization (Obj_Decl);
-- If the result subtype of the called function is definite and is
-- not itself the return expression of an enclosing BIP function,
-- then mark the object as having no initialization.
if Definite
and then not Is_Return_Object (Defining_Identifier (Obj_Decl))
then
-- The related object declaration is encased in a transient block
-- because the build-in-place function call contains at least one
-- nested function call that produces a controlled transient
-- temporary:
-- Obj : ... := BIP_Func_Call (Ctrl_Func_Call);
-- Since the build-in-place expansion decouples the call from the
-- object declaration, the finalization machinery lacks the
-- context which prompted the generation of the transient
-- block. To resolve this scenario, store the build-in-place call.
if Scope_Is_Transient and then Node_To_Be_Wrapped = Obj_Decl then
Set_BIP_Initialization_Call (Obj_Def_Id, Res_Decl);
end if;
Set_Expression (Obj_Decl, Empty);
Set_No_Initialization (Obj_Decl);
-- In case of an indefinite result subtype, or if the call is the
-- return expression of an enclosing BIP function, rewrite the object
-- declaration as an object renaming where the renamed object is a
-- dereference of <function_Call>'reference:
--
-- Obj : Subt renames <function_call>'Ref.all;
else -- In case of an indefinite result subtype, or if the call is the
Call_Deref := -- return expression of an enclosing BIP function, rewrite the object
Make_Explicit_Dereference (Obj_Loc, -- declaration as an object renaming where the renamed object is a
Prefix => New_Occurrence_Of (Def_Id, Obj_Loc)); -- dereference of <function_Call>'reference:
--
Rewrite (Obj_Decl, -- Obj : Subt renames <function_call>'Ref.all;
Make_Object_Renaming_Declaration (Obj_Loc,
Defining_Identifier => Make_Temporary (Obj_Loc, 'D'),
Subtype_Mark =>
New_Occurrence_Of (Designated_Type, Obj_Loc),
Name => Call_Deref));
Set_Renamed_Object (Defining_Identifier (Obj_Decl), Call_Deref);
-- If the original entity comes from source, then mark the new
-- entity as needing debug information, even though it's defined
-- by a generated renaming that does not come from source, so that
-- the Materialize_Entity flag will be set on the entity when
-- Debug_Renaming_Declaration is called during analysis.
if Comes_From_Source (Obj_Def_Id) then
Set_Debug_Info_Needed (Defining_Identifier (Obj_Decl));
end if;
Analyze (Obj_Decl); else
Replace_Renaming_Declaration_Id Call_Deref :=
(Obj_Decl, Original_Node (Obj_Decl)); Make_Explicit_Dereference (Obj_Loc,
Prefix => New_Occurrence_Of (Def_Id, Obj_Loc));
Rewrite (Obj_Decl,
Make_Object_Renaming_Declaration (Obj_Loc,
Defining_Identifier => Make_Temporary (Obj_Loc, 'D'),
Subtype_Mark =>
New_Occurrence_Of (Designated_Type, Obj_Loc),
Name => Call_Deref));
Set_Renamed_Object (Obj_Def_Id, Call_Deref);
-- If the original entity comes from source, then mark the new
-- entity as needing debug information, even though it's defined
-- by a generated renaming that does not come from source, so that
-- the Materialize_Entity flag will be set on the entity when
-- Debug_Renaming_Declaration is called during analysis.
if Comes_From_Source (Obj_Def_Id) then
Set_Debug_Info_Needed (Obj_Def_Id);
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 Analyze (Obj_Decl);
Set_Etype (Defining_Identifier (Obj_Decl), Result_Subt); Replace_Renaming_Declaration_Id
(Obj_Decl, Original_Node (Obj_Decl));
end if; 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,10 +4212,25 @@ package body Exp_Disp is ...@@ -4179,10 +4212,25 @@ 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.
Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0)); if No (Dummy_Object) then
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