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:
Javier Miranda 2012-10-03 08:09:15 +00:00 committed by Arnaud Charlet
parent 71fb4dc8c8
commit 3bfb3c03da
4 changed files with 118 additions and 52 deletions

View File

@ -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.

View File

@ -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

View File

@ -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 --
-----------------------------------

View File

@ -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).