-- and ultimately rewritten as a renaming, so initialization activities
-- need to be deferred until after that is done.
+ Func_Id : constant Entity_Id :=
+ (if Special_Ret_Obj then Return_Applies_To (Scope (Def_Id)) else Empty);
+ -- The function if this is a special return object, otherwise Empty
+
function Build_Equivalent_Aggregate return Boolean;
-- If the object has a constrained discriminated type and no initial
-- value, it may be possible to build an equivalent aggregate instead,
function Build_Heap_Or_Pool_Allocator
(Temp_Id : Entity_Id;
Temp_Typ : Entity_Id;
- Func_Id : Entity_Id;
Ret_Typ : Entity_Id;
Alloc_Expr : Node_Id) return Node_Id;
-- Create the statements necessary to allocate a return object on the
function Build_Heap_Or_Pool_Allocator
(Temp_Id : Entity_Id;
Temp_Typ : Entity_Id;
- Func_Id : Entity_Id;
Ret_Typ : Entity_Id;
Alloc_Expr : Node_Id) return Node_Id
is
-------------------------------
function Make_Allocator_For_Return (Expr : Node_Id) return Node_Id is
- Func_Id : constant Entity_Id := Return_Applies_To (Scope (Def_Id));
-
Alloc : Node_Id;
begin
-- finalize it prematurely (see Expand_Simple_Function_Return
-- for the same test in the case of a simple return).
+ -- Moreover, in the case of a special return object, we also
+ -- need to make sure that the two functions return on the same
+ -- stack, otherwise we would create a dangling reference.
+
and then
((not Is_Library_Level_Entity (Def_Id)
and then Is_Captured_Function_Call (Expr_Q)
- and then (not Special_Ret_Obj
- or else Is_Related_To_Func_Return
- (Entity (Prefix (Expr_Q))))
- and then not Is_Class_Wide_Type (Typ))
+ and then
+ (not Special_Ret_Obj
+ or else
+ (Is_Related_To_Func_Return (Entity (Prefix (Expr_Q)))
+ and then Needs_Secondary_Stack (Etype (Expr_Q)) =
+ Needs_Secondary_Stack (Etype (Func_Id)))))
-- If the initializing expression is a variable with the
-- flag OK_To_Rename set, then transform:
if Is_Build_In_Place_Return_Object (Def_Id) then
declare
- Func_Id : constant Entity_Id := Return_Applies_To (Scope (Def_Id));
-
Init_Stmt : Node_Id;
Obj_Acc_Formal : Entity_Id;
Build_Heap_Or_Pool_Allocator
(Temp_Id => Alloc_Obj_Id,
Temp_Typ => Acc_Typ,
- Func_Id => Func_Id,
Ret_Typ => Desig_Typ,
Alloc_Expr => Heap_Allocator))),
Build_Heap_Or_Pool_Allocator
(Temp_Id => Alloc_Obj_Id,
Temp_Typ => Acc_Typ,
- Func_Id => Func_Id,
Ret_Typ => Desig_Typ,
Alloc_Expr => Pool_Allocator)))),
-- and that the tag is assigned in the case of any return object.
elsif Rewrite_As_Renaming then
- if Is_Secondary_Stack_Return_Object (Def_Id) then
+ if Special_Ret_Obj then
declare
- Func_Id : constant Entity_Id :=
- Return_Applies_To (Scope (Def_Id));
-
Desig_Typ : constant Entity_Id :=
(if Ekind (Typ) = E_Array_Subtype
then Etype (Func_Id) else Typ);
Set_Etype (Def_Id, Desig_Typ);
Set_Actual_Subtype (Def_Id, Typ);
end if;
- end;
- end if;
- if Special_Ret_Obj and then Present (Tag_Assign) then
- Insert_Action_After (Init_After, Tag_Assign);
+ if Present (Tag_Assign) then
+ Insert_Action_After (Init_After, Tag_Assign);
+ end if;
+
+ -- Ada 2005 (AI95-344): If the result type is class-wide,
+ -- insert a check that the level of the return expression's
+ -- underlying type is not deeper than the level of the master
+ -- enclosing the function.
+
+ -- AI12-043: The check is made immediately after the return
+ -- object is created.
+
+ if Is_Class_Wide_Type (Etype (Func_Id)) then
+ Apply_CW_Accessibility_Check (Expr_Q, Func_Id);
+ end if;
+ end;
end if;
-- If this is the return object of a function returning on the secondary
elsif Is_Secondary_Stack_Return_Object (Def_Id) then
declare
- Func_Id : constant Entity_Id :=
- Return_Applies_To (Scope (Def_Id));
-
Desig_Typ : constant Entity_Id :=
(if Ekind (Typ) = E_Array_Subtype
then Etype (Func_Id) else Typ);
-- type Equiv_T is record
-- _parent : T (List of discriminant constraints taken from Exp);
- -- Ext__50 : Storage_Array (1 .. (Exp'size - Typ'object_size)/8);
+ -- Cnn : Storage_Array (1 .. (Exp'size - Typ'object_size)/Storage_Unit);
-- end Equiv_T;
--
-- Note that this type does not guarantee same alignment as all derived
Range_Type : Entity_Id;
Str_Type : Entity_Id;
Constr_Root : Entity_Id;
- Sizexpr : Node_Id;
+ Size_Expr : Node_Id;
+ Size_Pref : Node_Id;
+
+ function Has_Tag_Of_Type (Exp : Node_Id) return Boolean;
+ -- Return True if expression Exp of a tagged type is known to statically
+ -- have the tag of this tagged type as specified by RM 3.9(19-25).
+
+ ---------------------
+ -- Has_Tag_Of_Type --
+ ---------------------
+
+ function Has_Tag_Of_Type (Exp : Node_Id) return Boolean is
+ Typ : constant Entity_Id := Etype (Exp);
+
+ begin
+ pragma Assert (Is_Tagged_Type (Typ));
+
+ -- The tag of an object of a class-wide type is that of its
+ -- initialization expression.
+
+ if Is_Class_Wide_Type (Typ) then
+ return False;
+ end if;
+
+ -- The tag of a stand-alone object of a specific tagged type T
+ -- identifies T.
+
+ if Is_Entity_Name (Exp)
+ and then Ekind (Entity (Exp)) in Constant_Or_Variable_Kind
+ then
+ return True;
+
+ else
+ case Nkind (E) is
+ -- The tag of a component or an aggregate of a specific tagged
+ -- type T identifies T.
+
+ when N_Indexed_Component
+ | N_Selected_Component
+ | N_Aggregate
+ =>
+ return True;
+
+ -- The tag of the result returned by a function whose result
+ -- type is a specific tagged type T identifies T.
+
+ when N_Function_Call =>
+ return True;
+
+ when N_Explicit_Dereference =>
+ return Is_Captured_Function_Call (Exp);
+
+ when others =>
+ return False;
+ end case;
+ end if;
+ end Has_Tag_Of_Type;
begin
-- If the root type is already constrained, there are no discriminants
Range_Type := Make_Temporary (Loc, 'G');
+ -- If the expression is known to have the tag of its type, then we can
+ -- use it directly for the prefix of the Size attribute; otherwise we
+ -- need to convert it first to the class-wide type to force a call to
+ -- the _Size primitive operation.
+
+ if Has_Tag_Of_Type (E) then
+ Size_Pref := Duplicate_Subexpr_No_Checks (E);
+ else
+ Size_Pref := OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E));
+ end if;
+
if not Is_Interface (Root_Typ) then
-- subtype rg__xx is
- -- Storage_Offset range 1 .. (Expr'size - typ'object_size)
+ -- Storage_Offset range 1 .. (Exp'size - Typ'object_size)
-- / Storage_Unit
- Sizexpr :=
+ Size_Expr :=
Make_Op_Subtract (Loc,
Left_Opnd =>
Make_Attribute_Reference (Loc,
- Prefix =>
- OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
+ Prefix => Size_Pref,
Attribute_Name => Name_Size),
Right_Opnd =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_Object_Size));
else
-- subtype rg__xx is
- -- Storage_Offset range 1 .. (Expr'size - Ada.Tags.Tag'object_size)
+ -- Storage_Offset range 1 .. (Exp'size - Ada.Tags.Tag'object_size)
-- / Storage_Unit
- Sizexpr :=
+ Size_Expr :=
Make_Op_Subtract (Loc,
Left_Opnd =>
Make_Attribute_Reference (Loc,
- Prefix =>
- OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
+ Prefix => Size_Pref,
Attribute_Name => Name_Size),
Right_Opnd =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_Object_Size));
end if;
- Set_Paren_Count (Sizexpr, 1);
+ Set_Paren_Count (Size_Expr, 1);
Append_To (List_Def,
Make_Subtype_Declaration (Loc,
Low_Bound => Make_Integer_Literal (Loc, 1),
High_Bound =>
Make_Op_Divide (Loc,
- Left_Opnd => Sizexpr,
+ Left_Opnd => Size_Expr,
Right_Opnd => Make_Integer_Literal (Loc,
Intval => System_Storage_Unit)))))));