Typ => Base_Typ);
end if;
+ -- Renaming an expression of the object's type is immediate
+
+ elsif Rewrite_As_Renaming
+ and then Base_Type (Etype (Expr_Q)) = Base_Type (Typ)
+ then
+ null;
+
elsif Tagged_Type_Expansion then
declare
Iface : constant Entity_Id := Root_Type (Typ);
-- recursion and inappropriate call to Initialize.
-- We don't want to remove side effects when the expression must be
- -- built in place. In the case of a build-in-place function call,
- -- that could lead to a duplication of the call, which was already
- -- substituted for the allocator.
+ -- built in place and we don't need it when there is no storage pool
+ -- or this is a return/secondary stack allocation.
- if not Aggr_In_Place then
+ if not Aggr_In_Place
+ and then Present (Storage_Pool (N))
+ and then not Is_RTE (Storage_Pool (N), RE_RS_Pool)
+ and then not Is_RTE (Storage_Pool (N), RE_SS_Pool)
+ then
Remove_Side_Effects (Exp);
end if;
-- Processing for allocators returning non-interface types
- if not Is_Interface (Directly_Designated_Type (PtrT)) then
+ if not Is_Interface (DesigT) then
if Aggr_In_Place then
Temp_Decl :=
Make_Object_Declaration (Loc,
if Needs_Finalization (DesigT)
and then Needs_Finalization (T)
- and then not Aggr_In_Place
and then not Is_Limited_View (T)
+ and then not Aggr_In_Place
+ and then Nkind (Exp) /= N_Function_Call
and then not For_Special_Return_Object (N)
then
-- An unchecked conversion is needed in the classwide case because
-- component containing the secondary dispatch table of the interface
-- type.
- if Is_Interface (Directly_Designated_Type (PtrT)) then
+ if Is_Interface (DesigT) then
Displace_Allocator_Pointer (N);
end if;
-- Another optimization: if the returned value is used to initialize an
-- object, then no need to copy/readjust/finalize, we can initialize it
- -- in place. However, if the call returns on the secondary stack or this
- -- is a special return object, then we need the expansion because we'll
- -- be renaming the temporary as the (permanent) object.
+ -- in place. However, if the call returns on the secondary stack, then
+ -- we need the expansion because we'll be renaming the temporary as the
+ -- (permanent) object.
- if Nkind (Par) = N_Object_Declaration
- and then not Use_Sec_Stack
- and then not Is_Special_Return_Object (Defining_Entity (Par))
- then
+ if Nkind (Par) = N_Object_Declaration and then not Use_Sec_Stack then
return;
end if;
null;
-- Optimize the case where the result is a function call that also
- -- returns on the secondary stack. In this case the result is already
+ -- returns on the secondary stack; in this case the result is already
-- on the secondary stack and no further processing is required.
elsif Exp_Is_Function_Call
-- gigi is not able to properly allocate class-wide types.
-- But optimize the case where the result is a function call that
- -- also needs finalization. In this case the result can directly be
+ -- also needs finalization; in this case the result can directly be
-- allocated on the secondary stack and no further processing is
- -- required.
+ -- required, unless the returned object is an interface.
elsif CW_Or_Needs_Finalization (Utyp)
- and then not (Exp_Is_Function_Call
- and then Needs_Finalization (Exp_Typ))
+ and then (Is_Interface (R_Type)
+ or else not (Exp_Is_Function_Call
+ and then Needs_Finalization (Exp_Typ)))
then
declare
Acc_Typ : constant Entity_Id := Make_Temporary (Loc, 'A');
-- discriminants.
else
- Remove_Side_Effects (Exp);
Rewrite (Subtype_Indic,
Make_Subtype_From_Expr (Exp, Underlying_Record_View (Unc_Type)));
end if;
end if;
else
- Remove_Side_Effects (Exp);
Rewrite (Subtype_Indic,
Make_Subtype_From_Expr (Exp, Unc_Type, Related_Id));
end if;
Root_Utyp : constant Entity_Id := Underlying_Type (Root_Typ);
List_Def : constant List_Id := Empty_List;
Comp_List : constant List_Id := New_List;
+
Equiv_Type : Entity_Id;
Range_Type : Entity_Id;
Str_Type : Entity_Id;
Constr_Root : Entity_Id;
+ Size_Attr : 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
-- the _Size primitive operation.
if Has_Tag_Of_Type (E) then
- Size_Pref := Duplicate_Subexpr_No_Checks (E);
+ if not Has_Discriminants (Etype (E))
+ or else Is_Constrained (Etype (E))
+ then
+ Size_Attr :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Etype (E), Loc),
+ Attribute_Name => Name_Object_Size);
+
+ else
+ Size_Attr :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr_No_Checks (E),
+ Attribute_Name => Name_Size);
+ end if;
+
else
- Size_Pref := OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E));
+ Size_Attr :=
+ Make_Attribute_Reference (Loc,
+ Prefix => OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
+ Attribute_Name => Name_Size);
end if;
if not Is_Interface (Root_Typ) then
Size_Expr :=
Make_Op_Subtract (Loc,
- Left_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix => Size_Pref,
- Attribute_Name => Name_Size),
+ Left_Opnd => Size_Attr,
Right_Opnd =>
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (Constr_Root, Loc),
Size_Expr :=
Make_Op_Subtract (Loc,
- Left_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix => Size_Pref,
- Attribute_Name => Name_Size),
+ Left_Opnd => Size_Attr,
Right_Opnd =>
Make_Attribute_Reference (Loc,
Prefix => New_Occurrence_Of (RTE (RE_Tag), Loc),