exp_ch4.adb (Expand_N_Allocator_Expression): Minor code reorganization and cleanup.
2012-10-03 Javier Miranda <miranda@adacore.com> * exp_ch4.adb (Expand_N_Allocator_Expression): Minor code reorganization and cleanup. Done to ensure proper management of the C++ constructor covering tagged and untagged types and also non-default constructors. * exp_ch6.ads, exp_ch6.adb (Make_CPP_Constructor_Call_In_Allocator): New subprogram. From-SVN: r192028
This commit is contained in:
parent
71fb4dc8c8
commit
3bfb3c03da
4 changed files with 118 additions and 52 deletions
|
@ -1,3 +1,12 @@
|
|||
2012-10-03 Javier Miranda <miranda@adacore.com>
|
||||
|
||||
* exp_ch4.adb (Expand_N_Allocator_Expression): Minor code
|
||||
reorganization and cleanup. Done to ensure proper management of
|
||||
the C++ constructor covering tagged and untagged types and also
|
||||
non-default constructors.
|
||||
* exp_ch6.ads, exp_ch6.adb (Make_CPP_Constructor_Call_In_Allocator):
|
||||
New subprogram.
|
||||
|
||||
2012-10-03 Gary Dismukes <dismukes@adacore.com>
|
||||
|
||||
* sem_ch6.adb: Minor typo fix.
|
||||
|
|
|
@ -867,6 +867,15 @@ package body Exp_Ch4 is
|
|||
-- Start of processing for Expand_Allocator_Expression
|
||||
|
||||
begin
|
||||
-- Handle call to C++ constructor
|
||||
|
||||
if Is_CPP_Constructor_Call (Exp) then
|
||||
Make_CPP_Constructor_Call_In_Allocator
|
||||
(Allocator => N,
|
||||
Function_Call => Exp);
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- In the case of an Ada 2012 allocator whose initial value comes from a
|
||||
-- function call, pass "the accessibility level determined by the point
|
||||
-- of call" (AI05-0234) to the function. Conceptually, this belongs in
|
||||
|
@ -899,58 +908,6 @@ package body Exp_Ch4 is
|
|||
-- Case of tagged type or type requiring finalization
|
||||
|
||||
if Is_Tagged_Type (T) or else Needs_Finalization (T) then
|
||||
if Is_CPP_Constructor_Call (Exp) then
|
||||
|
||||
-- Generate:
|
||||
-- Pnnn : constant ptr_T := new (T);
|
||||
-- Init (Pnnn.all,...);
|
||||
|
||||
-- Allocate the object without an expression
|
||||
|
||||
Node := Relocate_Node (N);
|
||||
Set_Expression (Node, New_Reference_To (Etype (Exp), Loc));
|
||||
|
||||
-- Avoid its expansion to avoid generating a call to the default
|
||||
-- C++ constructor.
|
||||
|
||||
Set_Analyzed (Node);
|
||||
|
||||
Temp := Make_Temporary (Loc, 'P', N);
|
||||
|
||||
Temp_Decl :=
|
||||
Make_Object_Declaration (Loc,
|
||||
Defining_Identifier => Temp,
|
||||
Constant_Present => True,
|
||||
Object_Definition => New_Reference_To (PtrT, Loc),
|
||||
Expression => Node);
|
||||
Insert_Action (N, Temp_Decl);
|
||||
|
||||
Apply_Accessibility_Check (Temp);
|
||||
|
||||
-- Locate the enclosing list and insert the C++ constructor call
|
||||
|
||||
declare
|
||||
P : Node_Id;
|
||||
|
||||
begin
|
||||
P := Parent (Node);
|
||||
while not Is_List_Member (P) loop
|
||||
P := Parent (P);
|
||||
end loop;
|
||||
|
||||
Insert_List_After_And_Analyze (P,
|
||||
Build_Initialization_Call (Loc,
|
||||
Id_Ref =>
|
||||
Make_Explicit_Dereference (Loc,
|
||||
Prefix => New_Reference_To (Temp, Loc)),
|
||||
Typ => Etype (Exp),
|
||||
Constructor_Ref => Exp));
|
||||
end;
|
||||
|
||||
Rewrite (N, New_Reference_To (Temp, Loc));
|
||||
Analyze_And_Resolve (N, PtrT);
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Ada 2005 (AI-318-02): If the initialization expression is a call
|
||||
-- to a build-in-place function, then access to the allocated object
|
||||
|
|
|
@ -9121,6 +9121,96 @@ package body Exp_Ch6 is
|
|||
end if;
|
||||
end Make_Build_In_Place_Call_In_Object_Declaration;
|
||||
|
||||
--------------------------------------------
|
||||
-- Make_CPP_Constructor_Call_In_Allocator --
|
||||
--------------------------------------------
|
||||
|
||||
procedure Make_CPP_Constructor_Call_In_Allocator
|
||||
(Allocator : Node_Id;
|
||||
Function_Call : Node_Id)
|
||||
is
|
||||
Loc : constant Source_Ptr := Sloc (Function_Call);
|
||||
Acc_Type : constant Entity_Id := Etype (Allocator);
|
||||
Function_Id : constant Entity_Id := Entity (Name (Function_Call));
|
||||
Result_Subt : constant Entity_Id := Available_View (Etype (Function_Id));
|
||||
|
||||
New_Allocator : Node_Id;
|
||||
Return_Obj_Access : Entity_Id;
|
||||
Tmp_Obj : Node_Id;
|
||||
|
||||
begin
|
||||
pragma Assert (Nkind (Allocator) = N_Allocator
|
||||
and then Nkind (Function_Call) = N_Function_Call);
|
||||
pragma Assert (Convention (Function_Id) = Convention_CPP
|
||||
and then Is_Constructor (Function_Id));
|
||||
pragma Assert (Is_Constrained (Underlying_Type (Result_Subt)));
|
||||
|
||||
-- Replace the initialized allocator of form "new T'(Func (...))" with
|
||||
-- an uninitialized allocator of form "new T", where T is the result
|
||||
-- subtype of the called function. The call to the function is handled
|
||||
-- separately further below.
|
||||
|
||||
New_Allocator :=
|
||||
Make_Allocator (Loc,
|
||||
Expression => New_Reference_To (Result_Subt, Loc));
|
||||
Set_No_Initialization (New_Allocator);
|
||||
|
||||
-- Copy attributes to new allocator. Note that the new allocator
|
||||
-- logically comes from source if the original one did, so copy the
|
||||
-- relevant flag. This ensures proper treatment of the restriction
|
||||
-- No_Implicit_Heap_Allocations in this case.
|
||||
|
||||
Set_Storage_Pool (New_Allocator, Storage_Pool (Allocator));
|
||||
Set_Procedure_To_Call (New_Allocator, Procedure_To_Call (Allocator));
|
||||
Set_Comes_From_Source (New_Allocator, Comes_From_Source (Allocator));
|
||||
|
||||
Rewrite (Allocator, New_Allocator);
|
||||
|
||||
-- Create a new access object and initialize it to the result of the
|
||||
-- new uninitialized allocator. Note: we do not use Allocator as the
|
||||
-- Related_Node of Return_Obj_Access in call to Make_Temporary below
|
||||
-- as this would create a sort of infinite "recursion".
|
||||
|
||||
Return_Obj_Access := Make_Temporary (Loc, 'R');
|
||||
Set_Etype (Return_Obj_Access, Acc_Type);
|
||||
|
||||
-- Generate:
|
||||
-- Rnnn : constant ptr_T := new (T);
|
||||
-- Init (Rnn.all,...);
|
||||
|
||||
Tmp_Obj :=
|
||||
Make_Object_Declaration (Loc,
|
||||
Defining_Identifier => Return_Obj_Access,
|
||||
Constant_Present => True,
|
||||
Object_Definition => New_Reference_To (Acc_Type, Loc),
|
||||
Expression => Relocate_Node (Allocator));
|
||||
Insert_Action (Allocator, Tmp_Obj);
|
||||
|
||||
Insert_List_After_And_Analyze (Tmp_Obj,
|
||||
Build_Initialization_Call (Loc,
|
||||
Id_Ref =>
|
||||
Make_Explicit_Dereference (Loc,
|
||||
Prefix => New_Reference_To (Return_Obj_Access, Loc)),
|
||||
Typ => Etype (Function_Id),
|
||||
Constructor_Ref => Function_Call));
|
||||
|
||||
-- Finally, replace the allocator node with a reference to the result of
|
||||
-- the function call itself (which will effectively be an access to the
|
||||
-- object created by the allocator).
|
||||
|
||||
Rewrite (Allocator, New_Reference_To (Return_Obj_Access, Loc));
|
||||
|
||||
-- Ada 2005 (AI-251): If the type of the allocator is an interface then
|
||||
-- generate an implicit conversion to force displacement of the "this"
|
||||
-- pointer.
|
||||
|
||||
if Is_Interface (Designated_Type (Acc_Type)) then
|
||||
Rewrite (Allocator, Convert_To (Acc_Type, Relocate_Node (Allocator)));
|
||||
end if;
|
||||
|
||||
Analyze_And_Resolve (Allocator, Acc_Type);
|
||||
end Make_CPP_Constructor_Call_In_Allocator;
|
||||
|
||||
-----------------------------------
|
||||
-- Needs_BIP_Finalization_Master --
|
||||
-----------------------------------
|
||||
|
|
|
@ -205,6 +205,16 @@ package Exp_Ch6 is
|
|||
-- for which Is_Build_In_Place_Call is True, or an N_Qualified_Expression
|
||||
-- node applied to such a function call.
|
||||
|
||||
procedure Make_CPP_Constructor_Call_In_Allocator
|
||||
(Allocator : Node_Id;
|
||||
Function_Call : Node_Id);
|
||||
-- Handle a call to a CPP constructor that occurs as the expression that
|
||||
-- initializes an allocator, by passing access to the allocated object as
|
||||
-- an additional parameter of the constructor call. A new access object is
|
||||
-- declared that is initialized to the result of the allocator, passed to
|
||||
-- the constructor, and the allocator is rewritten to refer to that access
|
||||
-- object. Function_Call must denote a call to a CPP_Constructor function.
|
||||
|
||||
function Needs_BIP_Alloc_Form (Func_Id : Entity_Id) return Boolean;
|
||||
-- Ada 2005 (AI-318-02): Return True if the function needs an implicit
|
||||
-- BIP_Alloc_Form parameter (see type BIP_Formal_Kind).
|
||||
|
|
Loading…
Add table
Reference in a new issue