-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-----------------------
procedure Analyze_Return_Statement (N : Node_Id);
- -- Common processing for simple_ and extended_return_statements
+ -- Common processing for simple and extended return statements
procedure Analyze_Function_Return (N : Node_Id);
-- Subsidiary to Analyze_Return_Statement. Called when the return statement
procedure Analyze_Return_Type (N : Node_Id);
-- Subsidiary to Process_Formals: analyze subtype mark in function
- -- specification, in a context where the formals are visible and hide
+ -- specification in a context where the formals are visible and hide
-- outer homographs.
procedure Analyze_Subprogram_Body_Helper (N : Node_Id);
- -- Does all the real work of Analyze_Subprogram_Body
+ -- Does all the real work of Analyze_Subprogram_Body. This is split out so
+ -- that we can use RETURN but not skip the debug output at the end.
procedure Analyze_Generic_Subprogram_Body (N : Node_Id; Gen_Id : Entity_Id);
-- Analyze a generic subprogram body. N is the body to be analyzed, and
-- True otherwise. Proc is the entity for the procedure case and is used
-- in posting the warning message.
+ procedure Check_Untagged_Equality (Eq_Op : Entity_Id);
+ -- In Ada 2012, a primitive equality operator on an untagged record type
+ -- must appear before the type is frozen, and have the same visibility as
+ -- that of the type. This procedure checks that this rule is met, and
+ -- otherwise emits an error on the subprogram declaration and a warning
+ -- on the earlier freeze point if it is easy to locate.
+
procedure Enter_Overloaded_Entity (S : Entity_Id);
-- This procedure makes S, a new overloaded entity, into the first visible
-- entity with that name.
-------------------------------------
procedure Check_Return_Subtype_Indication (Obj_Decl : Node_Id) is
- Return_Obj : constant Node_Id := Defining_Identifier (Obj_Decl);
- R_Stm_Type : constant Entity_Id := Etype (Return_Obj);
- -- Subtype given in the extended return statement;
- -- this must match R_Type.
+ Return_Obj : constant Node_Id := Defining_Identifier (Obj_Decl);
+
+ R_Stm_Type : constant Entity_Id := Etype (Return_Obj);
+ -- Subtype given in the extended return statement (must match R_Type)
Subtype_Ind : constant Node_Id :=
Object_Definition (Original_Node (Obj_Decl));
-- True if type of the return object is an anonymous access type
begin
- -- First, avoid cascade errors:
+ -- First, avoid cascaded errors
if Error_Posted (Obj_Decl) or else Error_Posted (Subtype_Ind) then
return;
Subtype_Ind);
end if;
- if Is_Constrained (R_Type) then
+ -- AI05-103: for elementary types, subtypes must statically match
+
+ if Is_Constrained (R_Type)
+ or else Is_Access_Type (R_Type)
+ then
if not Subtypes_Statically_Match (R_Stm_Type, R_Type) then
Error_Msg_N
("subtype must statically match function result subtype",
& "null-excluding return?",
Reason => CE_Null_Not_Allowed);
end if;
+
+ -- Apply checks suggested by AI05-0144 (dangerous order dependence)
+ -- (Disabled for now)
+
+ -- Check_Order_Dependence;
end if;
end Analyze_Function_Return;
if Style_Check then
Style.Check_Identifier (Body_Id, Gen_Id);
end if;
+
End_Generic;
end Analyze_Generic_Subprogram_Body;
Analyze (Explicit_Actual_Parameter (N));
end Analyze_Parameter_Association;
+ --------------------------------------
+ -- Analyze_Parameterized_Expression --
+ --------------------------------------
+
+ procedure Analyze_Parameterized_Expression (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ LocX : constant Source_Ptr := Sloc (Expression (N));
+
+ begin
+ -- This is one of the occasions on which we write things during semantic
+ -- analysis. Transform the parameterized expression into an equivalent
+ -- subprogram body, and then analyze that.
+
+ Rewrite (N,
+ Make_Subprogram_Body (Loc,
+ Specification => Specification (N),
+ Declarations => Empty_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (LocX,
+ Statements => New_List (
+ Make_Simple_Return_Statement (LocX,
+ Expression => Expression (N))))));
+ Analyze (N);
+ end Analyze_Parameterized_Expression;
+
----------------------------
-- Analyze_Procedure_Call --
----------------------------
procedure Analyze_Call_And_Resolve;
-- Do Analyze and Resolve calls for procedure call
+ -- At end, check illegal order dependence.
------------------------------
-- Analyze_Call_And_Resolve --
if Nkind (N) = N_Procedure_Call_Statement then
Analyze_Call (N);
Resolve (N, Standard_Void_Type);
+
+ -- Apply checks suggested by AI05-0144 (Disabled for now)
+
+ -- Check_Order_Dependence;
+
else
Analyze (N);
end if;
return;
end if;
- -- If error analyzing prefix, then set Any_Type as result and return
+ -- If there is an error analyzing the name (which may have been
+ -- rewritten if the original call was in prefix notation) then error
+ -- has been emitted already, mark node and return.
- if Etype (P) = Any_Type then
+ if Error_Posted (N)
+ or else Etype (Name (N)) = Any_Type
+ then
Set_Etype (N, Any_Type);
return;
end if;
Prev_Id : constant Entity_Id := Current_Entity_In_Scope (Body_Id);
Conformant : Boolean;
HSS : Node_Id;
- Missing_Ret : Boolean;
P_Ent : Entity_Id;
Prot_Typ : Entity_Id := Empty;
Spec_Id : Entity_Id;
-- If pragma does not appear after the body, check whether there is
-- an inline pragma before any local declarations.
+ procedure Check_Missing_Return;
+ -- Checks for a function with a no return statements, and also performs
+ -- the warning checks implemented by Check_Returns.
+
function Disambiguate_Spec return Entity_Id;
-- When a primitive is declared between the private view and the full
-- view of a concurrent type which implements an interface, a special
if Present (Prag) then
if Present (Spec_Id) then
- if List_Containing (N) =
- List_Containing (Unit_Declaration_Node (Spec_Id))
- then
+ if In_Same_List (N, Unit_Declaration_Node (Spec_Id)) then
Analyze (Prag);
end if;
declare
Subp : constant Entity_Id :=
- Make_Defining_Identifier (Loc, Chars (Body_Id));
+ Make_Defining_Identifier (Loc, Chars (Body_Id));
Decl : constant Node_Id :=
- Make_Subprogram_Declaration (Loc,
- Specification => New_Copy_Tree (Specification (N)));
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ New_Copy_Tree (Specification (N)));
+
begin
Set_Defining_Unit_Name (Specification (Decl), Subp);
end if;
end Check_Inline_Pragma;
+ --------------------------
+ -- Check_Missing_Return --
+ --------------------------
+
+ procedure Check_Missing_Return is
+ Id : Entity_Id;
+ Missing_Ret : Boolean;
+
+ begin
+ if Nkind (Body_Spec) = N_Function_Specification then
+ if Present (Spec_Id) then
+ Id := Spec_Id;
+ else
+ Id := Body_Id;
+ end if;
+
+ if Return_Present (Id) then
+ Check_Returns (HSS, 'F', Missing_Ret);
+
+ if Missing_Ret then
+ Set_Has_Missing_Return (Id);
+ end if;
+
+ elsif (Is_Generic_Subprogram (Id)
+ or else not Is_Machine_Code_Subprogram (Id))
+ and then not Body_Deleted
+ then
+ Error_Msg_N ("missing RETURN statement in function body", N);
+ end if;
+
+ -- If procedure with No_Return, check returns
+
+ elsif Nkind (Body_Spec) = N_Procedure_Specification
+ and then Present (Spec_Id)
+ and then No_Return (Spec_Id)
+ then
+ Check_Returns (HSS, 'P', Missing_Ret, Spec_Id);
+ end if;
+ end Check_Missing_Return;
+
-----------------------
-- Disambiguate_Spec --
-----------------------
elsif not Is_Primitive (Spec_Id)
and then Ekind (Scope (Spec_Id)) /= E_Protected_Type
then
- Error_Msg_N ("overriding indicator only allowed " &
- "if subprogram is primitive",
- Body_Spec);
+ Error_Msg_N
+ ("overriding indicator only allowed " &
+ "if subprogram is primitive",
+ Body_Spec);
end if;
elsif Style_Check -- ??? incorrect use of Style_Check!
Set_Is_Child_Unit (Body_Id, Is_Child_Unit (Spec_Id));
Analyze_Generic_Subprogram_Body (N, Spec_Id);
+
+ if Nkind (N) = N_Subprogram_Body then
+ HSS := Handled_Statement_Sequence (N);
+ Check_Missing_Return;
+ end if;
+
return;
else
and then Comes_From_Source (N)
and then Is_Protected_Type (Current_Scope)
then
- declare
- Decl : Node_Id;
- Plist : List_Id;
- Formal : Entity_Id;
- New_Spec : Node_Id;
-
- begin
- Formal := First_Formal (Body_Id);
-
- -- The protected operation always has at least one formal, namely
- -- the object itself, but it is only placed in the parameter list
- -- if expansion is enabled.
-
- if Present (Formal)
- or else Expander_Active
- then
- Plist := Copy_Parameter_List (Body_Id);
- else
- Plist := No_List;
- end if;
-
- if Nkind (Body_Spec) = N_Procedure_Specification then
- New_Spec :=
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name =>
- Make_Defining_Identifier (Sloc (Body_Id),
- Chars => Chars (Body_Id)),
- Parameter_Specifications => Plist);
- else
- New_Spec :=
- Make_Function_Specification (Loc,
- Defining_Unit_Name =>
- Make_Defining_Identifier (Sloc (Body_Id),
- Chars => Chars (Body_Id)),
- Parameter_Specifications => Plist,
- Result_Definition =>
- New_Occurrence_Of (Etype (Body_Id), Loc));
- end if;
-
- Decl :=
- Make_Subprogram_Declaration (Loc,
- Specification => New_Spec);
- Insert_Before (N, Decl);
- Spec_Id := Defining_Unit_Name (New_Spec);
-
- -- Indicate that the entity comes from source, to ensure that
- -- cross-reference information is properly generated. The body
- -- itself is rewritten during expansion, and the body entity will
- -- not appear in calls to the operation.
-
- Set_Comes_From_Source (Spec_Id, True);
- Analyze (Decl);
- Set_Has_Completion (Spec_Id);
- Set_Convention (Spec_Id, Convention_Protected);
- end;
+ Spec_Id := Build_Private_Protected_Declaration (N);
end if;
-- If a separate spec is present, then deal with freezing issues
end if;
end if;
- -- Mark presence of postcondition proc in current scope
+ -- Mark presence of postcondition procedure in current scope and mark
+ -- the procedure itself as needing debug info. The latter is important
+ -- when analyzing decision coverage (for example, for MC/DC coverage).
if Chars (Body_Id) = Name_uPostconditions then
Set_Has_Postconditions (Current_Scope);
+ Set_Debug_Info_Needed (Body_Id);
end if;
-- Place subprogram on scope stack, and make formals visible. If there
then
Conformant := True;
+ -- Conversely, the spec may have been generated for specless body
+ -- with an inline pragma.
+
+ elsif Comes_From_Source (N)
+ and then not Comes_From_Source (Spec_Id)
+ and then Has_Pragma_Inline (Spec_Id)
+ then
+ Conformant := True;
+
else
Check_Conformance
(Body_Id, Spec_Id,
end if;
end if;
- -- If function, check return statements
-
- if Nkind (Body_Spec) = N_Function_Specification then
- declare
- Id : Entity_Id;
-
- begin
- if Present (Spec_Id) then
- Id := Spec_Id;
- else
- Id := Body_Id;
- end if;
-
- if Return_Present (Id) then
- Check_Returns (HSS, 'F', Missing_Ret);
-
- if Missing_Ret then
- Set_Has_Missing_Return (Id);
- end if;
-
- elsif not Is_Machine_Code_Subprogram (Id)
- and then not Body_Deleted
- then
- Error_Msg_N ("missing RETURN statement in function body", N);
- end if;
- end;
-
- -- If procedure with No_Return, check returns
-
- elsif Nkind (Body_Spec) = N_Procedure_Specification
- and then Present (Spec_Id)
- and then No_Return (Spec_Id)
- then
- Check_Returns (HSS, 'P', Missing_Ret, Spec_Id);
- end if;
+ Check_Missing_Return;
-- Now we are going to check for variables that are never modified in
-- the body of the procedure. But first we deal with a special case
end loop;
if Is_Protected_Type (Current_Scope) then
- Error_Msg_N
- ("protected operation cannot be a null procedure", N);
+ Error_Msg_N ("protected operation cannot be a null procedure", N);
end if;
end if;
-- If the type of the first formal of the current subprogram is a
-- nongeneric tagged private type, mark the subprogram as being a
-- private primitive. Ditto if this is a function with controlling
- -- result, and the return type is currently private.
+ -- result, and the return type is currently private. In both cases,
+ -- the type of the controlling argument or result must be in the
+ -- current scope for the operation to be primitive.
if Has_Controlling_Result (Designator)
and then Is_Private_Type (Etype (Designator))
+ and then Scope (Etype (Designator)) = Current_Scope
and then not Is_Generic_Actual_Type (Etype (Designator))
then
Set_Is_Private_Primitive (Designator);
begin
Set_Is_Private_Primitive (Designator,
Is_Tagged_Type (Formal_Typ)
+ and then Scope (Formal_Typ) = Current_Scope
and then Is_Private_Type (Formal_Typ)
and then not Is_Generic_Actual_Type (Formal_Typ));
end;
-- Ada 2005 (AI-251): If the return type is abstract, verify that
-- the subprogram is abstract also. This does not apply to renaming
-- declarations, where abstractness is inherited.
+
-- In case of primitives associated with abstract interface types
-- the check is applied later (see Analyze_Subprogram_Declaration).
- if Is_Abstract_Type (Etype (Designator))
- and then not Is_Interface (Etype (Designator))
- and then Nkind (Parent (N)) /= N_Subprogram_Renaming_Declaration
- and then Nkind (Parent (N)) /=
- N_Abstract_Subprogram_Declaration
- and then
- (Nkind (Parent (N))) /= N_Formal_Abstract_Subprogram_Declaration
+ if not Nkind_In (Parent (N), N_Subprogram_Renaming_Declaration,
+ N_Abstract_Subprogram_Declaration,
+ N_Formal_Abstract_Subprogram_Declaration)
then
- Error_Msg_N
- ("function that returns abstract type must be abstract", N);
+ if Is_Abstract_Type (Etype (Designator))
+ and then not Is_Interface (Etype (Designator))
+ then
+ Error_Msg_N
+ ("function that returns abstract type must be abstract", N);
+
+ -- Ada 2012 (AI-0073): extend this test to subprograms with an
+ -- access result whose designated type is abstract.
+
+ elsif Nkind (Result_Definition (N)) = N_Access_Definition
+ and then
+ not Is_Class_Wide_Type (Designated_Type (Etype (Designator)))
+ and then Is_Abstract_Type (Designated_Type (Etype (Designator)))
+ and then Ada_Version >= Ada_12
+ then
+ Error_Msg_N ("function whose access result designates "
+ & "abstract type must be abstract", N);
+ end if;
end if;
end if;
and then Has_Excluded_Statement (Statements (S))
then
return True;
+
+ elsif Nkind (S) = N_Extended_Return_Statement then
+ if Has_Excluded_Statement
+ (Statements (Handled_Statement_Sequence (S)))
+ or else Present
+ (Exception_Handlers (Handled_Statement_Sequence (S)))
+ then
+ return True;
+ end if;
end if;
Next (S);
or else Is_Child_Unit (S)
then
return False;
+
elsif Ekind (S) = E_Package
and then Has_Forward_Instantiation (S)
then
return Abandon;
end if;
+ -- A return statement within an extended return is a noop
+ -- after inlining.
+
+ elsif No (Expression (N))
+ and then Nkind (Parent (Parent (N))) =
+ N_Extended_Return_Statement
+ then
+ return OK;
+
else
-- Expression has wrong form
return Abandon;
end if;
+ -- We can only inline a build-in-place function if
+ -- it has a single extended return.
+
+ elsif Nkind (N) = N_Extended_Return_Statement then
+ if No (Return_Statement) then
+ Return_Statement := N;
+ return OK;
+
+ else
+ return Abandon;
+ end if;
+
else
return OK;
end if;
-- Start of processing for Has_Single_Return
begin
- return Check_All_Returns (N) = OK
- and then Present (Declarations (N))
- and then Present (First (Declarations (N)))
- and then Chars (Expression (Return_Statement)) =
- Chars (Defining_Identifier (First (Declarations (N))));
+ if Check_All_Returns (N) /= OK then
+ return False;
+
+ elsif Nkind (Return_Statement) = N_Extended_Return_Statement then
+ return True;
+
+ else
+ return Present (Declarations (N))
+ and then Present (First (Declarations (N)))
+ and then Chars (Expression (Return_Statement)) =
+ Chars (Defining_Identifier (First (Declarations (N))));
+ end if;
end Has_Single_Return;
--------------------
procedure Cannot_Inline (Msg : String; N : Node_Id; Subp : Entity_Id) is
begin
- -- Do not emit warning if this is a predefined unit which is not
- -- the main unit. With validity checks enabled, some predefined
- -- subprograms may contain nested subprograms and become ineligible
- -- for inlining.
+ -- Do not emit warning if this is a predefined unit which is not the
+ -- main unit. With validity checks enabled, some predefined subprograms
+ -- may contain nested subprograms and become ineligible for inlining.
if Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (Subp)))
and then not In_Extended_Main_Source_Unit (Subp)
when Mode_Conformant =>
if Nkind (Parent (Old_Id)) = N_Full_Type_Declaration then
- Error_Msg_N -- CODEFIX???
+ Error_Msg_N
("not mode conformant with operation inherited#!",
Enode);
else
- Error_Msg_N -- CODEFIX???
+ Error_Msg_N
("not mode conformant with declaration#!", Enode);
end if;
when Subtype_Conformant =>
if Nkind (Parent (Old_Id)) = N_Full_Type_Declaration then
- Error_Msg_N -- CODEFIX???
+ Error_Msg_N
("not subtype conformant with operation inherited#!",
Enode);
else
- Error_Msg_N -- CODEFIX???
+ Error_Msg_N
("not subtype conformant with declaration#!", Enode);
end if;
Error_Msg_Name_1 := Chars (New_Id);
Error_Msg_Name_2 :=
Name_Ada + Convention_Id'Pos (Convention (New_Id));
-
Conformance_Error ("\prior declaration for% has convention %!");
else
Set_Error_Posted (New_Formal);
return;
end if;
+
+ -- Null exclusion must match
+
+ if Null_Exclusion_Present (Parent (Old_Formal))
+ /=
+ Null_Exclusion_Present (Parent (New_Formal))
+ then
+ -- Only give error if both come from source. This should be
+ -- investigated some time, since it should not be needed ???
+
+ if Comes_From_Source (Old_Formal)
+ and then
+ Comes_From_Source (New_Formal)
+ then
+ Conformance_Error
+ ("\null exclusion for & does not match", New_Formal);
+
+ -- Mark error posted on the new formal to avoid duplicated
+ -- complaint about types not matching.
+
+ Set_Error_Posted (New_Formal);
+ end if;
+ end if;
end if;
-- Ada 2005 (AI-423): Possible access [sub]type and itype match. This
or else
Is_Access_Constant (Etype (Old_Formal)) /=
Is_Access_Constant (Etype (New_Formal)))
+
+ -- Do not complain if error already posted on New_Formal. This
+ -- avoids some redundant error messages.
+
+ and then not Error_Posted (New_Formal)
then
-- It is allowed to omit the null-exclusion in case of stream
-- attribute subprograms. We recognize stream subprograms
Error_Msg_Name_2 := Get_Convention_Name (Convention (Op));
Error_Msg_Sloc := Sloc (Op);
- if Comes_From_Source (Op) then
+ if Comes_From_Source (Op) or else No (Alias (Op)) then
if not Is_Overriding_Operation (Op) then
Error_Msg_N ("\\primitive % defined #", Typ);
else
- Error_Msg_N ("\\overriding operation % with " &
- "convention % defined #", Typ);
+ Error_Msg_N
+ ("\\overriding operation % with " &
+ "convention % defined #", Typ);
end if;
else pragma Assert (Present (Alias (Op)));
Error_Msg_Sloc := Sloc (Alias (Op));
- Error_Msg_N ("\\inherited operation % with " &
- "convention % defined #", Typ);
+ Error_Msg_N
+ ("\\inherited operation % with " &
+ "convention % defined #", Typ);
end if;
Error_Msg_Name_1 := Chars (Op);
Error_Msg_Name_2 :=
Get_Convention_Name (Convention (Iface_Prim));
Error_Msg_Sloc := Sloc (Iface_Prim);
- Error_Msg_N ("\\overridden operation % with " &
- "convention % defined #", Typ);
+ Error_Msg_N
+ ("\\overridden operation % with " &
+ "convention % defined #", Typ);
-- Avoid cascading errors
then
Error_Msg_Node_2 := Alias (Overridden_Subp);
Error_Msg_Sloc := Sloc (Error_Msg_Node_2);
- Error_Msg_NE ("& does not match corresponding formal of&#",
+ Error_Msg_NE
+ ("& does not match corresponding formal of&#",
Form1, Form1);
exit;
end if;
end;
end if;
- if Present (Overridden_Subp) then
+ -- If there is an overridden subprogram, then check that there is no
+ -- "not overriding" indicator, and mark the subprogram as overriding.
+ -- This is not done if the overridden subprogram is marked as hidden,
+ -- which can occur for the case of inherited controlled operations
+ -- (see Derive_Subprogram), unless the inherited subprogram's parent
+ -- subprogram is not itself hidden. (Note: This condition could probably
+ -- be simplified, leaving out the testing for the specific controlled
+ -- cases, but it seems safer and clearer this way, and echoes similar
+ -- special-case tests of this kind in other places.)
+
+ if Present (Overridden_Subp)
+ and then (not Is_Hidden (Overridden_Subp)
+ or else
+ ((Chars (Overridden_Subp) = Name_Initialize
+ or else Chars (Overridden_Subp) = Name_Adjust
+ or else Chars (Overridden_Subp) = Name_Finalize)
+ and then Present (Alias (Overridden_Subp))
+ and then not Is_Hidden (Alias (Overridden_Subp))))
+ then
if Must_Not_Override (Spec) then
Error_Msg_Sloc := Sloc (Overridden_Subp);
-- If Subp is an operator, it may override a predefined operation, if
-- it is defined in the same scope as the type to which it applies.
- -- In that case overridden_subp is empty because of our implicit
+ -- In that case Overridden_Subp is empty because of our implicit
-- representation for predefined operators. We have to check whether the
-- signature of Subp matches that of a predefined operator. Note that
-- first argument provides the name of the operator, and the second
elsif Nkind (Subp) = N_Defining_Operator_Symbol then
declare
Typ : constant Entity_Id :=
- Base_Type (Etype (First_Formal (Subp)));
+ Base_Type (Etype (First_Formal (Subp)));
Can_Override : constant Boolean :=
Operator_Matches_Spec (Subp, Subp)
elsif Can_Override then
Error_Msg_NE
- ("subprogram & overrides predefined operator ",
- Spec, Subp);
+ ("subprogram& overrides predefined operator ", Spec, Subp);
end if;
elsif Must_Override (Spec) then
if Is_Overriding_Operation (Subp) then
- Set_Is_Overriding_Operation (Subp);
+ null;
elsif not Can_Override then
Error_Msg_NE ("subprogram & is not overriding", Spec, Subp);
-- and also returned as the result. These formals are always of mode IN.
-- The new formal has the type Typ, is declared in Scope, and its name
-- is given by a concatenation of the name of Assoc_Entity and Suffix.
+ -- The following suffixes are currently used. They should not be changed
+ -- without coordinating with CodePeer, which makes use of these to
+ -- provide better messages.
+
+ -- O denotes the Constrained bit.
+ -- L denotes the accessibility level.
+ -- BIP_xxx denotes an extra formal for a build-in-place function. See
+ -- the full list in exp_ch6.BIP_Formal_Kind.
----------------------
-- Add_Extra_Formal --
-- generated stream attributes do get passed through because extra
-- build-in-place formals are needed in some cases (limited 'Input).
- if Is_Predefined_Dispatching_Operation (E) then
+ if Is_Predefined_Internal_Operation (E) then
goto Test_For_BIP_Extras;
end if;
and then not Is_Indefinite_Subtype (Formal_Type)
then
Set_Extra_Constrained
- (Formal, Add_Extra_Formal (Formal, Standard_Boolean, E, "F"));
+ (Formal, Add_Extra_Formal (Formal, Standard_Boolean, E, "O"));
end if;
end if;
or else Present (Extra_Accessibility (P_Formal)))
then
Set_Extra_Accessibility
- (Formal, Add_Extra_Formal (Formal, Standard_Natural, E, "F"));
+ (Formal, Add_Extra_Formal (Formal, Standard_Natural, E, "L"));
end if;
-- This label is required when skipping extra formal generation for
begin
-- In the case of functions with unconstrained result subtypes,
- -- add a 3-state formal indicating whether the return object is
- -- allocated by the caller (0), or should be allocated by the
- -- callee on the secondary stack (1) or in the global heap (2).
- -- For the moment we just use Natural for the type of this formal.
- -- Note that this formal isn't usually needed in the case where
- -- the result subtype is constrained, but it is needed when the
- -- function has a tagged result, because generally such functions
- -- can be called in a dispatching context and such calls must be
- -- handled like calls to a class-wide function.
+ -- add a 4-state formal indicating whether the return object is
+ -- allocated by the caller (1), or should be allocated by the
+ -- callee on the secondary stack (2), in the global heap (3), or
+ -- in a user-defined storage pool (4). For the moment we just use
+ -- Natural for the type of this formal. Note that this formal
+ -- isn't usually needed in the case where the result subtype is
+ -- constrained, but it is needed when the function has a tagged
+ -- result, because generally such functions can be called in a
+ -- dispatching context and such calls must be handled like calls
+ -- to a class-wide function.
if not Is_Constrained (Underlying_Type (Result_Subt))
or else Is_Tagged_Type (Underlying_Type (Result_Subt))
E, BIP_Formal_Suffix (BIP_Alloc_Form));
end if;
- -- In the case of functions whose result type has controlled
- -- parts, we have an extra formal of type
- -- System.Finalization_Implementation.Finalizable_Ptr_Ptr. That
- -- is, we are passing a pointer to a finalization list (which is
- -- itself a pointer). This extra formal is then passed along to
- -- Move_Final_List in case of successful completion of a return
- -- statement. We cannot pass an 'in out' parameter, because we
- -- need to update the finalization list during an abort-deferred
- -- region, rather than using copy-back after the function
- -- returns. This is true even if we are able to get away with
- -- having 'in out' parameters, which are normally illegal for
- -- functions. This formal is also needed when the function has
- -- a tagged result.
+ -- For functions whose result type has controlled parts, we have
+ -- an extra formal of type System.Finalization_Implementation.
+ -- Finalizable_Ptr_Ptr. That is, we are passing a pointer to a
+ -- finalization list (which is itself a pointer). This extra
+ -- formal is then passed along to Move_Final_List in case of
+ -- successful completion of a return statement. We cannot pass an
+ -- 'in out' parameter, because we need to update the finalization
+ -- list during an abort-deferred region, rather than using
+ -- copy-back after the function returns. This is true even if we
+ -- are able to get away with having 'in out' parameters, which are
+ -- normally illegal for functions. This formal is also needed when
+ -- the function has a tagged result.
if Needs_BIP_Final_List (E) then
Discard :=
end Enter_Overloaded_Entity;
-----------------------------
+ -- Check_Untagged_Equality --
+ -----------------------------
+
+ procedure Check_Untagged_Equality (Eq_Op : Entity_Id) is
+ Typ : constant Entity_Id := Etype (First_Formal (Eq_Op));
+ Decl : constant Node_Id := Unit_Declaration_Node (Eq_Op);
+ Obj_Decl : Node_Id;
+
+ begin
+ if Nkind (Decl) = N_Subprogram_Declaration
+ and then Is_Record_Type (Typ)
+ and then not Is_Tagged_Type (Typ)
+ then
+ if Is_Frozen (Typ) then
+ Error_Msg_NE
+ ("equality operator must be declared "
+ & "before type& is frozen", Eq_Op, Typ);
+
+ Obj_Decl := Next (Parent (Typ));
+ while Present (Obj_Decl)
+ and then Obj_Decl /= Decl
+ loop
+ if Nkind (Obj_Decl) = N_Object_Declaration
+ and then Etype (Defining_Identifier (Obj_Decl)) = Typ
+ then
+ Error_Msg_NE ("type& is frozen by declaration?",
+ Obj_Decl, Typ);
+ Error_Msg_N
+ ("\an equality operator cannot be declared after this "
+ & "point ('R'M 4.5.2 (9.8)) (Ada 2012))?", Obj_Decl);
+ exit;
+ end if;
+
+ Next (Obj_Decl);
+ end loop;
+
+ elsif not In_Same_List (Parent (Typ), Decl)
+ and then not Is_Limited_Type (Typ)
+ then
+ Error_Msg_N ("equality operator appears too late", Eq_Op);
+ end if;
+ end if;
+ end Check_Untagged_Equality;
+
+ -----------------------------
-- Find_Corresponding_Spec --
-----------------------------
-- that was created for an operation inherited by a null
-- extension, it may be overridden by a body without a previous
-- spec (one more reason why these should be shunned). In that
- -- case remove the generated body, because the current one is
- -- the explicit overriding.
+ -- case remove the generated body if present, because the
+ -- current one is the explicit overriding.
elsif Ekind (E) = E_Function
and then Ada_Version >= Ada_05
then
Set_Has_Completion (E, False);
- if Expander_Active then
+ if Expander_Active
+ and then Nkind (Parent (E)) = N_Function_Specification
+ then
Remove
(Unit_Declaration_Node
- (Corresponding_Body (Unit_Declaration_Node (E))));
+ (Corresponding_Body (Unit_Declaration_Node (E))));
+
return E;
- -- If expansion is disabled, the wrapper function has not
- -- been generated, and this is the standard case of a late
- -- body overriding an inherited operation.
+ -- If expansion is disabled, or if the wrapper function has
+ -- not been generated yet, this a late body overriding an
+ -- inherited operation, or it is an overriding by some other
+ -- declaration before the controlling result is frozen. In
+ -- either case this is a declaration of a new entity.
else
return Empty;
when N_Aggregate =>
return
FCL (Expressions (E1), Expressions (E2))
- and then FCL (Component_Associations (E1),
- Component_Associations (E2));
+ and then
+ FCL (Component_Associations (E1),
+ Component_Associations (E2));
when N_Allocator =>
if Nkind (Expression (E1)) = N_Qualified_Expression
and then
FCE (Right_Opnd (E1), Right_Opnd (E2));
+ when N_Case_Expression =>
+ declare
+ Alt1 : Node_Id;
+ Alt2 : Node_Id;
+
+ begin
+ if not FCE (Expression (E1), Expression (E2)) then
+ return False;
+
+ else
+ Alt1 := First (Alternatives (E1));
+ Alt2 := First (Alternatives (E2));
+ loop
+ if Present (Alt1) /= Present (Alt2) then
+ return False;
+ elsif No (Alt1) then
+ return True;
+ end if;
+
+ if not FCE (Expression (Alt1), Expression (Alt2))
+ or else not FCL (Discrete_Choices (Alt1),
+ Discrete_Choices (Alt2))
+ then
+ return False;
+ end if;
+
+ Next (Alt1);
+ Next (Alt2);
+ end loop;
+ end if;
+ end;
+
when N_Character_Literal =>
return
Char_Literal_Value (E1) = Char_Literal_Value (E2);
when N_Component_Association =>
return
FCL (Choices (E1), Choices (E2))
- and then FCE (Expression (E1), Expression (E2));
+ and then
+ FCE (Expression (E1), Expression (E2));
when N_Conditional_Expression =>
return
when N_Function_Call =>
return
FCE (Name (E1), Name (E2))
- and then FCL (Parameter_Associations (E1),
- Parameter_Associations (E2));
+ and then
+ FCL (Parameter_Associations (E1),
+ Parameter_Associations (E2));
when N_Indexed_Component =>
return
FCE (Prefix (E1), Prefix (E2))
- and then FCL (Expressions (E1), Expressions (E2));
+ and then
+ FCL (Expressions (E1), Expressions (E2));
when N_Integer_Literal =>
return (Intval (E1) = Intval (E2));
when N_Qualified_Expression =>
return
FCE (Subtype_Mark (E1), Subtype_Mark (E2))
- and then FCE (Expression (E1), Expression (E2));
+ and then
+ FCE (Expression (E1), Expression (E2));
when N_Range =>
return
FCE (Low_Bound (E1), Low_Bound (E2))
- and then FCE (High_Bound (E1), High_Bound (E2));
+ and then
+ FCE (High_Bound (E1), High_Bound (E2));
when N_Real_Literal =>
return (Realval (E1) = Realval (E2));
when N_Selected_Component =>
return
FCE (Prefix (E1), Prefix (E2))
- and then FCE (Selector_Name (E1), Selector_Name (E2));
+ and then
+ FCE (Selector_Name (E1), Selector_Name (E2));
when N_Slice =>
return
FCE (Prefix (E1), Prefix (E2))
- and then FCE (Discrete_Range (E1), Discrete_Range (E2));
+ and then
+ FCE (Discrete_Range (E1), Discrete_Range (E2));
when N_String_Literal =>
declare
when N_Type_Conversion =>
return
FCE (Subtype_Mark (E1), Subtype_Mark (E2))
- and then FCE (Expression (E1), Expression (E2));
+ and then
+ FCE (Expression (E1), Expression (E2));
when N_Unary_Op =>
return
Entity (E1) = Entity (E2)
- and then FCE (Right_Opnd (E1), Right_Opnd (E2));
+ and then
+ FCE (Right_Opnd (E1), Right_Opnd (E2));
when N_Unchecked_Type_Conversion =>
return
FCE (Subtype_Mark (E1), Subtype_Mark (E2))
- and then FCE (Expression (E1), Expression (E2));
+ and then
+ FCE (Expression (E1), Expression (E2));
-- All other node types cannot appear in this context. Strictly
-- we should raise a fatal internal error. Instead we just ignore
or else Etype (Prim) = Etype (Iface_Prim)
or else not Has_Controlling_Result (Prim)
then
- return Type_Conformant (Prim, Iface_Prim,
- Skip_Controlling_Formals => True);
+ return Type_Conformant
+ (Iface_Prim, Prim, Skip_Controlling_Formals => True);
-- Case of a function returning an interface, or an access to one.
-- Check that the return types correspond.
-- instance of) a generic type.
Formal := First_Formal (Prev_E);
-
while Present (Formal) loop
F_Typ := Base_Type (Etype (Formal));
and then (not Is_Overriding
or else not Is_Abstract_Subprogram (E))
then
- Error_Msg_N ("abstract subprograms must be visible "
- & "(RM 3.9.3(10))!", S);
+ Error_Msg_N
+ ("abstract subprograms must be visible "
+ & "(RM 3.9.3(10))!", S);
elsif Ekind (S) = E_Function
- and then Is_Tagged_Type (T)
- and then T = Base_Type (Etype (S))
and then not Is_Overriding
then
- Error_Msg_N
- ("private function with tagged result must"
- & " override visible-part function", S);
- Error_Msg_N
- ("\move subprogram to the visible part"
- & " (RM 3.9.3(10))", S);
+ if Is_Tagged_Type (T)
+ and then T = Base_Type (Etype (S))
+ then
+ Error_Msg_N
+ ("private function with tagged result must"
+ & " override visible-part function", S);
+ Error_Msg_N
+ ("\move subprogram to the visible part"
+ & " (RM 3.9.3(10))", S);
+
+ -- AI05-0073: extend this test to the case of a function
+ -- with a controlling access result.
+
+ elsif Ekind (Etype (S)) = E_Anonymous_Access_Type
+ and then Is_Tagged_Type (Designated_Type (Etype (S)))
+ and then
+ not Is_Class_Wide_Type (Designated_Type (Etype (S)))
+ and then Ada_Version >= Ada_12
+ then
+ Error_Msg_N
+ ("private function with controlling access result "
+ & "must override visible-part function", S);
+ Error_Msg_N
+ ("\move subprogram to the visible part"
+ & " (RM 3.9.3(10))", S);
+ end if;
end if;
end if;
end Check_Private_Overriding;
E := Current_Entity_In_Scope (S);
+ -- Ada 2005 (AI-251): Derivation of abstract interface primitives.
+ -- They are directly added to the list of primitive operations of
+ -- Derived_Type, unless this is a rederivation in the private part
+ -- of an operation that was already derived in the visible part of
+ -- the current package.
+
+ if Ada_Version >= Ada_05
+ and then Present (Derived_Type)
+ and then Present (Alias (S))
+ and then Is_Dispatching_Operation (Alias (S))
+ and then Present (Find_Dispatching_Type (Alias (S)))
+ and then Is_Interface (Find_Dispatching_Type (Alias (S)))
+ then
+ -- For private types, when the full-view is processed we propagate to
+ -- the full view the non-overridden entities whose attribute "alias"
+ -- references an interface primitive. These entities were added by
+ -- Derive_Subprograms to ensure that interface primitives are
+ -- covered.
+
+ -- Inside_Freeze_Actions is non zero when S corresponds with an
+ -- internal entity that links an interface primitive with its
+ -- covering primitive through attribute Interface_Alias (see
+ -- Add_Internal_Interface_Entities)
+
+ if Inside_Freezing_Actions = 0
+ and then Is_Package_Or_Generic_Package (Current_Scope)
+ and then In_Private_Part (Current_Scope)
+ and then Nkind (Parent (E)) = N_Private_Extension_Declaration
+ and then Nkind (Parent (S)) = N_Full_Type_Declaration
+ and then Full_View (Defining_Identifier (Parent (E)))
+ = Defining_Identifier (Parent (S))
+ and then Alias (E) = Alias (S)
+ then
+ Check_Operation_From_Private_View (S, E);
+ Set_Is_Dispatching_Operation (S);
+
+ -- Common case
+
+ else
+ Enter_Overloaded_Entity (S);
+ Check_Dispatching_Operation (S, Empty);
+ Check_For_Primitive_Subprogram (Is_Primitive_Subp);
+ end if;
+
+ return;
+ end if;
+
-- If there is no homonym then this is definitely not overriding
if No (E) then
-- E exists and is overloadable
else
- -- Ada 2005 (AI-251): Derivation of abstract interface primitives
- -- need no check against the homonym chain. They are directly added
- -- to the list of primitive operations of Derived_Type.
-
- if Ada_Version >= Ada_05
- and then Present (Derived_Type)
- and then Is_Dispatching_Operation (Alias (S))
- and then Present (Find_Dispatching_Type (Alias (S)))
- and then Is_Interface (Find_Dispatching_Type (Alias (S)))
- then
- goto Add_New_Entity;
- end if;
-
Check_Synchronized_Overriding (S, Overridden_Subp);
-- Loop through E and its homonyms to determine if any of them is
E := Homonym (E);
end loop;
- <<Add_New_Entity>>
-
-- On exit, we know that S is a new entity
Enter_Overloaded_Entity (S);
and then not Is_Dispatching_Operation (S)
then
Make_Inequality_Operator (S);
+
+ if Ada_Version >= Ada_12 then
+ Check_Untagged_Equality (S);
+ end if;
end if;
end New_Overloaded_Entity;
Prag := Spec_PPC_List (Spec_Id);
while Present (Prag) loop
if Pragma_Name (Prag) = Name_Precondition
- and then PPC_Enabled (Prag)
+ and then Pragma_Enabled (Prag)
then
-- Add pragma Check at the start of the declarations of N.
-- Note that this processing reverses the order of the list,
Prag := Spec_PPC_List (Spec_Id);
while Present (Prag) loop
if Pragma_Name (Prag) = Name_Postcondition
- and then PPC_Enabled (Prag)
+ and then Pragma_Enabled (Prag)
then
if Plist = No_List then
Plist := Empty_List;
Make_Handled_Sequence_Of_Statements (Loc,
Statements => Plist)));
- -- If this is a procedure, set the Postcondition_Proc attribute
+ -- If this is a procedure, set the Postcondition_Proc attribute on
+ -- the proper defining entity for the subprogram.
if Etype (Subp) = Standard_Void_Type then
- Set_Postcondition_Proc (Spec_Id, Post_Proc);
+ if Present (Spec_Id) then
+ Set_Postcondition_Proc (Spec_Id, Post_Proc);
+ else
+ Set_Postcondition_Proc (Body_Id, Post_Proc);
+ end if;
end if;
end;