-- the activation Chain. Note: Master_Actual can be Empty, but only if
-- there are no tasks.
+ procedure Apply_CW_Accessibility_Check (Exp : Node_Id; Func : Entity_Id);
+ -- 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. Always generate the
+ -- check when the type of the return expression is class-wide, when it's a
+ -- type conversion, or when it's a formal parameter. Otherwise suppress the
+ -- check in the case where the return expression has a specific type whose
+ -- level is known not to be statically deeper than the result type of the
+ -- function.
+
function Caller_Known_Size
(Func_Call : Node_Id;
Result_Subt : Entity_Id) return Boolean;
Add_Extra_Actual_To_Call (Function_Call, Chain_Formal, Chain_Actual);
end Add_Task_Actuals_To_Build_In_Place_Call;
+ ----------------------------------
+ -- Apply_CW_Accessibility_Check --
+ ----------------------------------
+
+ procedure Apply_CW_Accessibility_Check (Exp : Node_Id; Func : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Exp);
+
+ begin
+ if Ada_Version >= Ada_2005
+ and then Tagged_Type_Expansion
+ and then not Scope_Suppress.Suppress (Accessibility_Check)
+ and then
+ (Is_Class_Wide_Type (Etype (Exp))
+ or else Nkind_In (Exp, N_Type_Conversion,
+ N_Unchecked_Type_Conversion)
+ or else (Is_Entity_Name (Exp)
+ and then Is_Formal (Entity (Exp)))
+ or else Scope_Depth (Enclosing_Dynamic_Scope (Etype (Exp))) >
+ Scope_Depth (Enclosing_Dynamic_Scope (Func)))
+ then
+ declare
+ Tag_Node : Node_Id;
+
+ begin
+ -- Ada 2005 (AI-251): In class-wide interface objects we displace
+ -- "this" to reference the base of the object. This is required to
+ -- get access to the TSD of the object.
+
+ if Is_Class_Wide_Type (Etype (Exp))
+ and then Is_Interface (Etype (Exp))
+ then
+ -- If the expression is an explicit dereference then we can
+ -- directly displace the pointer to reference the base of
+ -- the object.
+
+ if Nkind (Exp) = N_Explicit_Dereference then
+ Tag_Node :=
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Unchecked_Convert_To (RTE (RE_Tag_Ptr),
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Base_Address), Loc),
+ Parameter_Associations => New_List (
+ Unchecked_Convert_To (RTE (RE_Address),
+ Duplicate_Subexpr (Prefix (Exp)))))));
+
+ -- Similar case to the previous one but the expression is a
+ -- renaming of an explicit dereference.
+
+ elsif Nkind (Exp) = N_Identifier
+ and then Present (Renamed_Object (Entity (Exp)))
+ and then Nkind (Renamed_Object (Entity (Exp)))
+ = N_Explicit_Dereference
+ then
+ Tag_Node :=
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Unchecked_Convert_To (RTE (RE_Tag_Ptr),
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Base_Address), Loc),
+ Parameter_Associations => New_List (
+ Unchecked_Convert_To (RTE (RE_Address),
+ Duplicate_Subexpr
+ (Prefix
+ (Renamed_Object (Entity (Exp)))))))));
+
+ -- Common case: obtain the address of the actual object and
+ -- displace the pointer to reference the base of the object.
+
+ else
+ Tag_Node :=
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Unchecked_Convert_To (RTE (RE_Tag_Ptr),
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Base_Address), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr (Exp),
+ Attribute_Name => Name_Address)))));
+ end if;
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr (Exp),
+ Attribute_Name => Name_Tag);
+ end if;
+
+ -- CodePeer does not do anything useful with
+ -- Ada.Tags.Type_Specific_Data components.
+
+ if not CodePeer_Mode then
+ Insert_Action (Exp,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd => Build_Get_Access_Level (Loc, Tag_Node),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ Scope_Depth (Enclosing_Dynamic_Scope (Func)))),
+ Reason => PE_Accessibility_Check_Failed));
+ end if;
+ end;
+ end if;
+ end Apply_CW_Accessibility_Check;
+
-----------------------
-- BIP_Formal_Suffix --
-----------------------
Is_Build_In_Place_Function_Call (Exp));
null;
end if;
+
+ -- Ada 2005 (AI95-344): If the result type is class-wide, then 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 Present (Exp) and then Is_Class_Wide_Type (Ret_Typ) then
+ Apply_CW_Accessibility_Check (Exp, Func_Id);
+ end if;
else
Exp := Empty;
end if;
Set_Comes_From_Extended_Return_Statement (Return_Stmt);
Rewrite (N, Result);
- Analyze (N, Suppress => All_Checks);
+
+ -- AI12-043: The checks of 6.5(8.1/3) and 6.5(21/3) are made immediately
+ -- before an object is returned. A predicate that applies to the return
+ -- subtype is checked immediately before an object is returned.
+
+ -- Suppress access checks to avoid generating extra checks for b-i-p.
+
+ Analyze (N, Suppress => Access_Check);
end Expand_N_Extended_Return_Statement;
----------------------------
Exp : Node_Id := Expression (N);
pragma Assert (Present (Exp));
- Exptyp : constant Entity_Id := Etype (Exp);
+ Exp_Typ : constant Entity_Id := Etype (Exp);
-- The type of the expression (not necessarily the same as R_Type)
Subtype_Ind : Node_Id;
end Check_Against_Result_Level;
-- Start of processing for Expand_Simple_Function_Return
+
begin
if Is_Class_Wide_Type (R_Type)
- and then not Is_Class_Wide_Type (Exptyp)
+ and then not Is_Class_Wide_Type (Exp_Typ)
and then Nkind (Exp) /= N_Type_Conversion
then
- Subtype_Ind := New_Occurrence_Of (Exptyp, Loc);
+ Subtype_Ind := New_Occurrence_Of (Exp_Typ, Loc);
else
Subtype_Ind := New_Occurrence_Of (R_Type, Loc);
-- altogether to prevent tag overwriting.
if Is_Class_Wide_Type (R_Type)
- and then not Is_Class_Wide_Type (Exptyp)
+ and then not Is_Class_Wide_Type (Exp_Typ)
and then Nkind (Exp) = N_Type_Conversion
then
Exp := Expression (Exp);
-- handled by means of simple return statements. This leaves their
-- expansion simple and clean.
- and then not Is_Thunk (Current_Scope)
+ and then not Is_Thunk (Scope_Id)
then
declare
Return_Object_Entity : constant Entity_Id :=
-- barrier functions for protected types, which turn the condition into
-- a return statement.
- if Is_Boolean_Type (Exptyp)
- and then Nonzero_Is_True (Exptyp)
- then
+ if Is_Boolean_Type (Exp_Typ) and then Nonzero_Is_True (Exp_Typ) then
Adjust_Condition (Exp);
- Adjust_Result_Type (Exp, Exptyp);
+ Adjust_Result_Type (Exp, Exp_Typ);
end if;
-- Do validity check if enabled for returns
- if Validity_Checks_On
- and then Validity_Check_Returns
- then
+ if Validity_Checks_On and then Validity_Check_Returns then
Ensure_Valid (Exp);
end if;
-- only done for scalars.
-- ???
- if Is_Scalar_Type (Exptyp) then
+ if Is_Scalar_Type (Exp_Typ) then
Rewrite (Exp, Convert_To (R_Type, Exp));
-- The expression is resolved to ensure that the conversion gets
-- it requires a cleanup scope for the secondary stack case).
if Is_Build_In_Place_Function (Scope_Id)
- or else Is_Limited_Interface (Exptyp)
+ or else Is_Limited_Interface (Exp_Typ)
then
null;
-- the object is returned by reference and the maximum functionality
-- required is just to displace the pointer.
- elsif Is_Thunk (Current_Scope) and then Is_Interface (Exptyp) then
+ elsif Is_Thunk (Scope_Id) and then Is_Interface (Exp_Typ) then
null;
-- If the call is within a thunk and the type is a limited view, the
-- backend will eventually see the non-limited view of the type.
- elsif Is_Thunk (Current_Scope) and then Is_Incomplete_Type (Exptyp) then
+ elsif Is_Thunk (Scope_Id) and then Is_Incomplete_Type (Exp_Typ) then
return;
-- A return statement from an ignored Ghost function does not use the
-- cause a temporary with maximum size to be created.
declare
- Ubt : constant Entity_Id := Underlying_Type (Base_Type (Exptyp));
+ Ubt : constant Entity_Id := Underlying_Type (Base_Type (Exp_Typ));
Decl : Node_Id;
Ent : Entity_Id;
begin
-- for array types if the constrained status of the target type is
-- different from that of the expression.
- if Requires_Transient_Scope (Exptyp)
+ if Requires_Transient_Scope (Exp_Typ)
and then
- (not Is_Array_Type (Exptyp)
- or else Is_Constrained (Exptyp) = Is_Constrained (R_Type)
+ (not Is_Array_Type (Exp_Typ)
+ or else Is_Constrained (Exp_Typ) = Is_Constrained (R_Type)
or else CW_Or_Has_Controlled_Part (Utyp))
and then Nkind (Exp) = N_Function_Call
then
end;
end if;
- -- Ada 2005 (AI-344): If the result type is class-wide, then insert
+ -- Ada 2005 (AI95-344): If the result type is class-wide, then 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.
- -- Always generate the check when the type of the return expression
- -- is class-wide, when it's a type conversion, or when it's a formal
- -- parameter. Otherwise, suppress the check in the case where the
- -- return expression has a specific type whose level is known not to
- -- be statically deeper than the function's result type.
+
+ -- AI12-043: The check is made immediately after the return object is
+ -- created. This means that we do not apply it to the simple return
+ -- generated by the expansion of an extended return statement.
-- No runtime check needed in interface thunks since it is performed
-- by the target primitive associated with the thunk.
- -- Note: accessibility check is skipped in the VM case, since there
- -- does not seem to be any practical way to implement this check.
-
- elsif Ada_Version >= Ada_2005
- and then Tagged_Type_Expansion
- and then Is_Class_Wide_Type (R_Type)
- and then not Is_Thunk (Current_Scope)
- and then not Scope_Suppress.Suppress (Accessibility_Check)
- and then
- (Is_Class_Wide_Type (Etype (Exp))
- or else Nkind_In (Exp, N_Type_Conversion,
- N_Unchecked_Type_Conversion)
- or else (Is_Entity_Name (Exp)
- and then Is_Formal (Entity (Exp)))
- or else Scope_Depth (Enclosing_Dynamic_Scope (Etype (Exp))) >
- Scope_Depth (Enclosing_Dynamic_Scope (Scope_Id)))
+ elsif Is_Class_Wide_Type (R_Type)
+ and then not Comes_From_Extended_Return_Statement (N)
+ and then not Is_Thunk (Scope_Id)
then
- declare
- Tag_Node : Node_Id;
+ Apply_CW_Accessibility_Check (Exp, Scope_Id);
- begin
- -- Ada 2005 (AI-251): In class-wide interface objects we displace
- -- "this" to reference the base of the object. This is required to
- -- get access to the TSD of the object.
-
- if Is_Class_Wide_Type (Etype (Exp))
- and then Is_Interface (Etype (Exp))
- then
- -- If the expression is an explicit dereference then we can
- -- directly displace the pointer to reference the base of
- -- the object.
-
- if Nkind (Exp) = N_Explicit_Dereference then
- Tag_Node :=
- Make_Explicit_Dereference (Loc,
- Prefix =>
- Unchecked_Convert_To (RTE (RE_Tag_Ptr),
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Base_Address), Loc),
- Parameter_Associations => New_List (
- Unchecked_Convert_To (RTE (RE_Address),
- Duplicate_Subexpr (Prefix (Exp)))))));
-
- -- Similar case to the previous one but the expression is a
- -- renaming of an explicit dereference.
-
- elsif Nkind (Exp) = N_Identifier
- and then Present (Renamed_Object (Entity (Exp)))
- and then Nkind (Renamed_Object (Entity (Exp)))
- = N_Explicit_Dereference
- then
- Tag_Node :=
- Make_Explicit_Dereference (Loc,
- Prefix =>
- Unchecked_Convert_To (RTE (RE_Tag_Ptr),
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Base_Address), Loc),
- Parameter_Associations => New_List (
- Unchecked_Convert_To (RTE (RE_Address),
- Duplicate_Subexpr
- (Prefix
- (Renamed_Object (Entity (Exp)))))))));
-
- -- Common case: obtain the address of the actual object and
- -- displace the pointer to reference the base of the object.
-
- else
- Tag_Node :=
- Make_Explicit_Dereference (Loc,
- Prefix =>
- Unchecked_Convert_To (RTE (RE_Tag_Ptr),
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Base_Address), Loc),
- Parameter_Associations => New_List (
- Make_Attribute_Reference (Loc,
- Prefix => Duplicate_Subexpr (Exp),
- Attribute_Name => Name_Address)))));
- end if;
- else
- Tag_Node :=
- Make_Attribute_Reference (Loc,
- Prefix => Duplicate_Subexpr (Exp),
- Attribute_Name => Name_Tag);
- end if;
-
- -- CodePeer does not do anything useful with
- -- Ada.Tags.Type_Specific_Data components.
-
- if not CodePeer_Mode then
- Insert_Action (Exp,
- Make_Raise_Program_Error (Loc,
- Condition =>
- Make_Op_Gt (Loc,
- Left_Opnd => Build_Get_Access_Level (Loc, Tag_Node),
- Right_Opnd =>
- Make_Integer_Literal (Loc,
- Scope_Depth (Enclosing_Dynamic_Scope (Scope_Id)))),
- Reason => PE_Accessibility_Check_Failed));
- end if;
- end;
-
- -- AI05-0073: If function has a controlling access result, check that
- -- the tag of the return value, if it is not null, matches designated
- -- type of return type.
+ -- Ada 2012 (AI05-0073): If the result subtype of the function is
+ -- defined by an access_definition designating a specific tagged
+ -- type T, a check is made that the result value is null or the tag
+ -- of the object designated by the result value identifies T.
-- The return expression is referenced twice in the code below, so it
-- must be made free of side effects. Given that different compilers
-- perform a copy.
elsif Ekind (R_Type) = E_Anonymous_Access_Type
- and then Has_Controlling_Result (Scope_Id)
+ and then Is_Tagged_Type (Designated_Type (R_Type))
+ and then not Is_Class_Wide_Type (Designated_Type (R_Type))
+ and then Nkind (Original_Node (Exp)) /= N_Null
+ and then not Tag_Checks_Suppressed (Designated_Type (R_Type))
then
+ -- Generate:
+ -- [Constraint_Error
+ -- when Exp /= null
+ -- and then Exp.all not in Designated_Type]
+
Insert_Action (N,
Make_Raise_Constraint_Error (Loc,
Condition =>
Left_Opnd => Duplicate_Subexpr (Exp),
Right_Opnd => Make_Null (Loc)),
- Right_Opnd => Make_Op_Ne (Loc,
- Left_Opnd =>
- Make_Selected_Component (Loc,
- Prefix => Duplicate_Subexpr (Exp),
- Selector_Name => Make_Identifier (Loc, Name_uTag)),
-
- Right_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix =>
- New_Occurrence_Of (Designated_Type (R_Type), Loc),
- Attribute_Name => Name_Tag))),
+ Right_Opnd =>
+ Make_Not_In (Loc,
+ Left_Opnd =>
+ Make_Explicit_Dereference (Loc,
+ Prefix => Duplicate_Subexpr (Exp)),
+ Right_Opnd =>
+ New_Occurrence_Of (Designated_Type (R_Type), Loc))),
Reason => CE_Tag_Check_Failed),
Suppress => All_Checks);
Object_Access_Level (Entity (Ultimate_Prefix (Prefix (Exp))))));
end if;
- -- AI05-0234: RM 6.5(21/3). Check access discriminants to
- -- ensure that the function result does not outlive an
- -- object designated by one of it discriminants.
+ -- AI05-0234: Check unconstrained access discriminants to ensure
+ -- that the result does not outlive an object designated by one
+ -- of its discriminants (RM 6.5(21/3)).
if Present (Extra_Accessibility_Of_Result (Scope_Id))
and then Has_Unconstrained_Access_Discriminants (R_Type)
and then Comes_From_Extended_Return_Statement (N)
and then Nkind (Expression (N)) = N_Identifier
and then Is_Interface (Utyp)
- and then Utyp /= Underlying_Type (Exptyp)
+ and then Utyp /= Underlying_Type (Exp_Typ)
then
Rewrite (Exp, Convert_To (Utyp, Relocate_Node (Exp)));
Analyze_And_Resolve (Exp);