aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_prag.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_prag.adb')
-rw-r--r--gcc/ada/sem_prag.adb513
1 files changed, 407 insertions, 106 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 621edc7..2fc3698 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -216,10 +216,10 @@ package body Sem_Prag is
(Prag : Node_Id;
Spec_Id : Entity_Id);
-- Subsidiary to the analysis of pragmas Contract_Cases, Postcondition,
- -- Precondition, Refined_Post, Subprogram_Variant, and Test_Case. Emit a
- -- warning when pragma Prag is associated with subprogram Spec_Id subject
- -- to Inline_Always, assertions are enabled and inling is done in the
- -- frontend.
+ -- Precondition, Program_Exit, Refined_Post, Subprogram_Variant, and
+ -- Test_Case. Emit a warning when pragma Prag is associated with subprogram
+ -- Spec_Id subject to Inline_Always, assertions are enabled and inling is
+ -- done in the frontend.
procedure Check_State_And_Constituent_Use
(States : Elist_Id;
@@ -234,9 +234,10 @@ package body Sem_Prag is
(Contract_Id : Entity_Id;
Freeze_Id : Entity_Id);
-- Subsidiary to the analysis of pragmas Contract_Cases, Exceptional_Cases,
- -- Part_Of, Post, Pre and Subprogram_Variant. Emit a freezing-related error
- -- message where Freeze_Id is the entity of a body which caused contract
- -- freezing and Contract_Id denotes the entity of the affected contstruct.
+ -- Part_Of, Post, Pre, Program_Exit and Subprogram_Variant. Emit a
+ -- freezing-related error message where Freeze_Id is the entity of a body
+ -- which caused contract freezing and Contract_Id denotes the entity of the
+ -- affected contstruct.
procedure Duplication_Error (Prag : Node_Id; Prev : Node_Id);
-- Subsidiary to all Find_Related_xxx routines. Emit an error on pragma
@@ -474,7 +475,8 @@ package body Sem_Prag is
end if;
Errors := Serious_Errors_Detected;
- Preanalyze_Assert_Expression (Expression (Arg1), Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression
+ (Expression (Arg1), Standard_Boolean);
-- Emit a clarification message when the expression contains at least
-- one undefined reference, possibly due to contract freezing.
@@ -564,7 +566,8 @@ package body Sem_Prag is
if Nkind (Case_Guard) /= N_Others_Choice then
Errors := Serious_Errors_Detected;
- Preanalyze_Assert_Expression (Case_Guard, Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression
+ (Case_Guard, Standard_Boolean);
-- Emit a clarification message when the case guard contains
-- at least one undefined reference, possibly due to contract
@@ -579,7 +582,8 @@ package body Sem_Prag is
end if;
Errors := Serious_Errors_Detected;
- Preanalyze_Assert_Expression (Conseq, Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression
+ (Conseq, Standard_Boolean);
-- Emit a clarification message when the consequence contains
-- at least one undefined reference, possibly due to contract
@@ -2391,9 +2395,10 @@ package body Sem_Prag is
Errors := Serious_Errors_Detected;
- -- Preanalyze_Assert_Expression enforcing the expression type
+ -- Preanalyze_And_Resolve_Assert_Expression enforcing the expression
+ -- type.
- Preanalyze_Assert_Expression (Consequence, Any_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression (Consequence, Any_Boolean);
Check_Params (Consequence);
@@ -2621,7 +2626,8 @@ package body Sem_Prag is
if Nkind (Case_Guard) /= N_Others_Choice then
Errors := Serious_Errors_Detected;
- Preanalyze_Assert_Expression (Case_Guard, Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression
+ (Case_Guard, Standard_Boolean);
-- Emit a clarification message when the case guard contains
-- at least one undefined reference, possibly due to contract
@@ -2636,14 +2642,16 @@ package body Sem_Prag is
end if;
-- Check the exit kind. It shall be either an exception or the
- -- identifiers Normal_Return or Any_Exception.
+ -- identifiers Normal_Return, Exception_Raised, or Program_Exit.
if Nkind (Exit_Kind) = N_Identifier then
if Chars (Exit_Kind) not in Name_Normal_Return
| Name_Exception_Raised
+ | Name_Program_Exit
then
Error_Msg_N
- ("exit kind should be Normal_Return or Exception_Raised",
+ ("exit kind should be Normal_Return, Exception_Raised, " &
+ "or Program_Exit",
Exit_Kind);
end if;
@@ -5112,10 +5120,6 @@ package body Sem_Prag is
-- Determines if the placement of the current pragma is appropriate
-- for a configuration pragma.
- function Is_In_Context_Clause return Boolean;
- -- Returns True if pragma appears within the context clause of a unit,
- -- and False for any other placement (does not generate any messages).
-
function Is_Static_String_Expression (Arg : Node_Id) return Boolean;
-- Analyzes the argument, and determines if it is a static string
-- expression, returns True if so, False if non-static or not String.
@@ -5585,7 +5589,7 @@ package body Sem_Prag is
if Present (Arg2) then
Check_Optional_Identifier (Arg2, Name_Message);
- Preanalyze_Assert_Expression
+ Preanalyze_And_Resolve_Assert_Expression
(Get_Pragma_Arg (Arg2), Standard_String);
end if;
end if;
@@ -6009,7 +6013,7 @@ package body Sem_Prag is
-- Check case of appearing within context clause
- if not Is_Unused and then Is_In_Context_Clause then
+ if not Is_Unused and then Is_In_Context_Clause (N) then
-- The arguments must all be units mentioned in a with clause in
-- the same context clause. Note that Par.Prag already checked
@@ -8083,10 +8087,26 @@ package body Sem_Prag is
-- the test below also permits use in a configuration pragma file.
function Is_Configuration_Pragma return Boolean is
+ function Is_Pragma_Node (Prg : Node_Id) return Boolean is
+ (Nkind (Prg) = N_Pragma
+ or else
+ (Present (Original_Node (Prg))
+ and then Nkind (Original_Node (Prg)) = N_Pragma));
+ -- Returns true whether the node is a pragma or was originally a
+ -- pragma.
+ --
+ -- Note that some pragmas like Assertion_Policy are rewritten as
+ -- Null_Statment nodes but we still need to make sure here that the
+ -- original node was a pragma node.
+
+ -- Local variables
+
Lis : List_Id;
Par : constant Node_Id := Parent (N);
Prg : Node_Id;
+ -- Start of processing for Is_Configuration_Pragma
+
begin
-- Don't evaluate List_Containing (N) if Parent (N) could be
-- an N_Aspect_Specification node.
@@ -8115,7 +8135,7 @@ package body Sem_Prag is
loop
if Prg = N then
return True;
- elsif Nkind (Prg) /= N_Pragma then
+ elsif not Is_Pragma_Node (Prg) then
return False;
end if;
@@ -8127,27 +8147,6 @@ package body Sem_Prag is
end if;
end Is_Configuration_Pragma;
- --------------------------
- -- Is_In_Context_Clause --
- --------------------------
-
- function Is_In_Context_Clause return Boolean is
- Plist : List_Id;
- Parent_Node : Node_Id;
-
- begin
- if Is_List_Member (N) then
- Plist := List_Containing (N);
- Parent_Node := Parent (Plist);
-
- return Present (Parent_Node)
- and then Nkind (Parent_Node) = N_Compilation_Unit
- and then Context_Items (Parent_Node) = Plist;
- end if;
-
- return False;
- end Is_In_Context_Clause;
-
---------------------------------
-- Is_Static_String_Expression --
---------------------------------
@@ -10049,7 +10048,6 @@ package body Sem_Prag is
end if;
Def_Id := Entity (Def_Id);
- Kill_Size_Check_Code (Def_Id);
if Ekind (Def_Id) /= E_Constant then
Note_Possible_Modification
(Get_Pragma_Arg (Arg1), Sure => False);
@@ -10062,7 +10060,6 @@ package body Sem_Prag is
-- purposes of legality checks and removal of ignored Ghost code.
Mark_Ghost_Pragma (N, Def_Id);
- Kill_Size_Check_Code (Def_Id);
if Ekind (Def_Id) /= E_Constant then
Note_Possible_Modification
(Get_Pragma_Arg (Arg2), Sure => False);
@@ -14065,7 +14062,7 @@ package body Sem_Prag is
-- Perform preanalysis to deal with embedded Loop_Entry
-- attributes.
- Preanalyze_Assert_Expression (Expr, Any_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression (Expr, Any_Boolean);
end if;
-- Implement Assert[_And_Cut]/Assume/Loop_Invariant by generating
@@ -14696,19 +14693,18 @@ package body Sem_Prag is
D := Declaration_Node (E);
- if (Nkind (D) = N_Full_Type_Declaration and then Is_Array_Type (E))
+ if (Nkind (D) in N_Full_Type_Declaration
+ | N_Formal_Type_Declaration
+ and then Is_Array_Type (E))
or else
(Nkind (D) = N_Object_Declaration
and then Ekind (E) in E_Constant | E_Variable
and then Nkind (Object_Definition (D)) =
N_Constrained_Array_Definition)
- or else
- (Ada_Version >= Ada_2022
- and then Nkind (D) = N_Formal_Type_Declaration)
then
-- The flag is set on the base type, or on the object
- if Nkind (D) = N_Full_Type_Declaration then
+ if Is_Array_Type (E) then
E := Base_Type (E);
end if;
@@ -16166,7 +16162,8 @@ package body Sem_Prag is
-- described in "Handling of Default and Per-Object
-- Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_CPU_Range));
+ Preanalyze_And_Resolve_Spec_Expression
+ (Arg, RTE (RE_CPU_Range));
-- See comment in Sem_Ch13 about the following restrictions
@@ -16212,7 +16209,7 @@ package body Sem_Prag is
-- The expression must be analyzed in the special manner described
-- in "Handling of Default and Per-Object Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_Time_Span));
+ Preanalyze_And_Resolve_Spec_Expression (Arg, RTE (RE_Time_Span));
-- Only protected types allowed
@@ -16841,7 +16838,8 @@ package body Sem_Prag is
-- described in "Handling of Default and Per-Object
-- Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_Dispatching_Domain));
+ Preanalyze_And_Resolve_Spec_Expression
+ (Arg, RTE (RE_Dispatching_Domain));
-- Check duplicate pragma before we chain the pragma in the Rep
-- Item chain of Ent.
@@ -16869,7 +16867,7 @@ package body Sem_Prag is
begin
-- Pragma must be in context items list of a compilation unit
- if not Is_In_Context_Clause then
+ if not Is_In_Context_Clause (N) then
Pragma_Misplaced;
end if;
@@ -16965,7 +16963,7 @@ package body Sem_Prag is
-- Pragma must be in context items list of a compilation unit
- if not Is_In_Context_Clause then
+ if not Is_In_Context_Clause (N) then
Pragma_Misplaced;
end if;
@@ -17457,6 +17455,7 @@ package body Sem_Prag is
--
-- EXIT_KIND ::=
-- Normal_Return
+ -- | Program_Exit
-- | Exception_Raised
-- | (Exception_Raised => exception_name)
--
@@ -19964,7 +19963,6 @@ package body Sem_Prag is
-- object to be imported.
if Ekind (Def_Id) = E_Variable then
- Kill_Size_Check_Code (Def_Id);
Note_Possible_Modification (Id, Sure => False);
-- Initialization is not allowed for imported variable
@@ -20074,7 +20072,8 @@ package body Sem_Prag is
-- described in "Handling of Default and Per-Object
-- Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_Interrupt_Priority));
+ Preanalyze_And_Resolve_Spec_Expression
+ (Arg, RTE (RE_Interrupt_Priority));
end if;
if Nkind (P) not in N_Task_Definition | N_Protected_Definition then
@@ -20979,10 +20978,10 @@ package body Sem_Prag is
("Structural variant shall be the only variant", Variant);
end if;
- -- Preanalyze_Assert_Expression, but without enforcing any of
- -- the two acceptable types.
+ -- Preanalyze_And_Resolve_Assert_Expression, but without
+ -- enforcing any of the two acceptable types.
- Preanalyze_Assert_Expression (Expression (Variant));
+ Preanalyze_And_Resolve_Assert_Expression (Expression (Variant));
-- Expression of a discrete type is allowed. Nothing to
-- check for structural variants.
@@ -20992,7 +20991,7 @@ package body Sem_Prag is
then
null;
- -- Expression of a Big_Integer type (or its ghost variant) is
+ -- Expression of a Big_Integer type (or its SPARK variant) is
-- only allowed in Decreases clause.
elsif
@@ -21000,9 +20999,6 @@ package body Sem_Prag is
RE_Big_Integer)
or else
Is_RTE (Base_Type (Etype (Expression (Variant))),
- RO_GH_Big_Integer)
- or else
- Is_RTE (Base_Type (Etype (Expression (Variant))),
RO_SP_Big_Integer)
then
if Chars (Variant) = Name_Increases then
@@ -23410,7 +23406,8 @@ package body Sem_Prag is
-- described in "Handling of Default and Per-Object
-- Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_Any_Priority));
+ Preanalyze_And_Resolve_Spec_Expression
+ (Arg, RTE (RE_Any_Priority));
if not Is_OK_Static_Expression (Arg) then
Check_Restriction (Static_Priorities, Arg);
@@ -23615,6 +23612,132 @@ package body Sem_Prag is
end if;
end;
+ ------------------
+ -- Program_Exit --
+ ------------------
+
+ -- pragma Program_Exit (Boolean_EXPRESSION);
+
+ -- Characteristics:
+
+ -- * Analysis - The annotation undergoes initial checks to verify
+ -- the legal placement and context. Secondary checks preanalyze the
+ -- expression in:
+
+ -- Analyze_Program_Exit_In_Decl_Part
+
+ -- * Expansion - The annotation is expanded during the expansion of
+ -- the related subprogram [body] contract as performed in:
+
+ -- Expand_Subprogram_Contract
+
+ -- * Template - The annotation utilizes the generic template of the
+ -- related subprogram [body] when it is:
+
+ -- aspect on subprogram declaration
+ -- aspect on stand-alone subprogram body
+ -- pragma on stand-alone subprogram body
+
+ -- The annotation must prepare its own template when it is:
+
+ -- pragma on subprogram declaration
+
+ -- * Globals - Capture of global references must occur after full
+ -- analysis.
+
+ -- * Instance - The annotation is instantiated automatically when
+ -- the related generic subprogram [body] is instantiated except for
+ -- the "pragma on subprogram declaration" case. In that scenario
+ -- the annotation must instantiate itself.
+
+ when Pragma_Program_Exit => Program_Exit : declare
+ Spec_Id : Entity_Id;
+ Subp_Decl : Node_Id;
+ Subp_Spec : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_At_Most_N_Arguments (1);
+
+ -- Ensure the proper placement of the pragma. Program_Exit must be
+ -- associated with a subprogram declaration or a body that acts as
+ -- a spec.
+
+ Subp_Decl :=
+ Find_Related_Declaration_Or_Body (N, Do_Checks => True);
+
+ -- Generic subprogram
+
+ if Nkind (Subp_Decl) = N_Generic_Subprogram_Declaration then
+ null;
+
+ -- Body acts as spec
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body
+ and then No (Corresponding_Spec (Subp_Decl))
+ then
+ null;
+
+ -- Body stub acts as spec
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body_Stub
+ and then No (Corresponding_Spec_Of_Stub (Subp_Decl))
+ then
+ null;
+
+ -- Subprogram
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Declaration then
+ Subp_Spec := Specification (Subp_Decl);
+
+ -- Pragma Program_Exit is forbidden on null procedures, as this
+ -- may lead to potential ambiguities in behavior when interface
+ -- null procedures are involved. Also, it just wouldn't make
+ -- sense, because null procedure always exits.
+
+ if Nkind (Subp_Spec) = N_Procedure_Specification
+ and then Null_Present (Subp_Spec)
+ then
+ Error_Msg_N (Fix_Error
+ ("pragma % cannot apply to null procedure"), N);
+ return;
+ end if;
+
+ else
+ Pragma_Misplaced;
+ end if;
+
+ Spec_Id := Unique_Defining_Entity (Subp_Decl);
+
+ -- A pragma that applies to a Ghost entity becomes Ghost for the
+ -- purposes of legality checks and removal of ignored Ghost code.
+
+ Mark_Ghost_Pragma (N, Spec_Id);
+
+ -- Chain the pragma on the contract for further processing by
+ -- Analyze_Program_Exit.
+
+ Add_Contract_Item (N, Defining_Entity (Subp_Decl));
+
+ -- Fully analyze the pragma when it appears inside a subprogram
+ -- body because it cannot benefit from forward references.
+
+ if Nkind (Subp_Decl) in N_Subprogram_Body
+ | N_Subprogram_Body_Stub
+ then
+ -- The legality checks of pragma Program_Exit are affected by
+ -- the SPARK mode in effect and the volatility of the context.
+ -- Analyze all pragmas in a specific order.
+
+ Analyze_If_Present (Pragma_SPARK_Mode);
+ Analyze_If_Present (Pragma_Volatile_Function);
+ Analyze_If_Present (Pragma_Global);
+ Analyze_If_Present (Pragma_Depends);
+ Analyze_Program_Exit_In_Decl_Part (N);
+ end if;
+ end Program_Exit;
+
----------------------
-- Profile_Warnings --
----------------------
@@ -23982,7 +24105,7 @@ package body Sem_Prag is
Analyze_If_Present (Pragma_Side_Effects);
-- A function with side effects shall not have a Pure_Function
- -- aspect or pragma (SPARK RM 6.1.11(5)).
+ -- aspect or pragma (SPARK RM 6.1.12(5)).
if Is_Function_With_Side_Effects (E) then
Error_Pragma
@@ -24397,7 +24520,7 @@ package body Sem_Prag is
-- The expression must be analyzed in the special manner described
-- in "Handling of Default and Per-Object Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, RTE (RE_Time_Span));
+ Preanalyze_And_Resolve_Spec_Expression (Arg, RTE (RE_Time_Span));
-- Subprogram case
@@ -24657,7 +24780,7 @@ package body Sem_Prag is
-- The expression must be analyzed in the special manner
-- described in "Handling of Default Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, Any_Integer);
+ Preanalyze_And_Resolve_Spec_Expression (Arg, Any_Integer);
-- The pragma cannot appear if the No_Secondary_Stack
-- restriction is in effect.
@@ -25815,7 +25938,7 @@ package body Sem_Prag is
-- in "Handling of Default Expressions" in sem.ads.
Arg := Get_Pragma_Arg (Arg1);
- Preanalyze_Spec_Expression (Arg, Any_Integer);
+ Preanalyze_And_Resolve_Spec_Expression (Arg, Any_Integer);
if not Is_OK_Static_Expression (Arg) then
Check_Restriction (Static_Storage_Size, Arg);
@@ -26845,7 +26968,7 @@ package body Sem_Prag is
Opt.Time_Slice_Set := True;
Val := Expr_Value_R (Get_Pragma_Arg (Arg1));
- if Val <= Ureal_0 then
+ if not UR_Is_Positive (Val) then
Opt.Time_Slice_Value := 0;
elsif Val > UR_From_Uint (UI_From_Int (1000)) then
@@ -28241,7 +28364,7 @@ package body Sem_Prag is
end if;
Errors := Serious_Errors_Detected;
- Preanalyze_Assert_Expression (Expr, Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression (Expr, Standard_Boolean);
-- Emit a clarification message when the expression contains at least
-- one undefined reference, possibly due to contract freezing.
@@ -28296,6 +28419,153 @@ package body Sem_Prag is
Restore_Ghost_Region (Saved_GM, Saved_IGR);
end Analyze_Pre_Post_Condition_In_Decl_Part;
+ ---------------------------------------
+ -- Analyze_Program_Exit_In_Decl_Part --
+ ---------------------------------------
+
+ -- WARNING: This routine manages Ghost regions. Return statements must be
+ -- replaced by gotos which jump to the end of the routine and restore the
+ -- Ghost mode.
+
+ procedure Analyze_Program_Exit_In_Decl_Part
+ (N : Node_Id;
+ Freeze_Id : Entity_Id := Empty)
+ is
+ Subp_Decl : constant Node_Id := Find_Related_Declaration_Or_Body (N);
+ Spec_Id : constant Entity_Id := Unique_Defining_Entity (Subp_Decl);
+ Arg1 : constant Node_Id :=
+ First (Pragma_Argument_Associations (N));
+
+ Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
+ Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ -- Save the Ghost-related attributes to restore on exit
+
+ Errors : Nat;
+ Restore_Scope : Boolean := False;
+ Unused : Boolean;
+
+ Subp_Inputs, Subp_Outputs : Elist_Id := No_Elist;
+ -- Inputs and outputs of the subprogram
+
+ function Check_Reference (N : Node_Id) return Traverse_Result;
+ -- Check references to objects within the Program_Exit expression
+
+ ---------------------
+ -- Check_Reference --
+ ---------------------
+
+ function Check_Reference (N : Node_Id) return Traverse_Result is
+ begin
+ -- If an output of a subprogram with side effects is mentioned
+ -- in the boolean expression of its aspect Program_Exit, then it
+ -- shall either occur inside the prefix of a reference to the Old
+ -- attribute or be a stand-alone object.
+
+ if Is_Attribute_Old (N) then
+ return Skip;
+ end if;
+
+ if Is_Entity_Name (N) then
+ declare
+ E : constant Entity_Id := Entity (N);
+ begin
+ if Appears_In (Subp_Outputs, E)
+ and then Ekind (E) not in E_Constant | E_Variable
+ then
+ Error_Msg_NE
+ ("reference to subprogram output & in Program_Exit", N, E);
+ end if;
+ end;
+ end if;
+
+ return OK;
+ end Check_Reference;
+
+ procedure Check_Exit_References is new Traverse_Proc (Check_Reference);
+
+ -- Start of processing for Analyze_Pre_Post_Condition_In_Decl_Part
+
+ begin
+ -- Do not analyze the pragma multiple times
+
+ if Is_Analyzed_Pragma (N) then
+ return;
+ end if;
+
+ if Ekind (Spec_Id) in E_Function | E_Generic_Function
+ and then not Is_Function_With_Side_Effects (Spec_Id)
+ then
+ Error_Msg_N
+ ("aspect Program_Exit is only allowed " &
+ "for subprograms with side effects", N);
+ end if;
+
+ if Present (Arg1) then
+
+ -- Set the Ghost mode in effect from the pragma. Due to the delayed
+ -- analysis of the pragma, the Ghost mode at point of declaration and
+ -- point of analysis may not necessarily be the same. Use the mode in
+ -- effect at the point of declaration.
+
+ Set_Ghost_Mode (N);
+
+ -- Ensure that the subprogram and its formals are visible when
+ -- analyzing the expression of the pragma.
+
+ if not In_Open_Scopes (Spec_Id) then
+ Restore_Scope := True;
+
+ if Is_Generic_Subprogram (Spec_Id) then
+ Push_Scope (Spec_Id);
+ Install_Generic_Formals (Spec_Id);
+ else
+ Push_Scope (Spec_Id);
+ Install_Formals (Spec_Id);
+ end if;
+ end if;
+
+ Errors := Serious_Errors_Detected;
+
+ -- Preanalyze_And_Resolve_Assert_Expression enforcing the expression
+ -- type.
+
+ Preanalyze_And_Resolve_Assert_Expression
+ (Expression (Arg1), Any_Boolean);
+
+ Collect_Subprogram_Inputs_Outputs
+ (Spec_Id,
+ Synthesize => True,
+ Subp_Inputs => Subp_Inputs,
+ Subp_Outputs => Subp_Outputs,
+ Global_Seen => Unused);
+
+ Check_Exit_References (Expression (Arg1));
+
+ -- Emit a clarification message when the expression contains at least
+ -- one undefined reference, possibly due to contract freezing.
+
+ if Errors /= Serious_Errors_Detected
+ and then Present (Freeze_Id)
+ and then Has_Undefined_Reference (Expression (Arg1))
+ then
+ Contract_Freeze_Error (Spec_Id, Freeze_Id);
+ end if;
+
+ if Restore_Scope then
+ End_Scope;
+ end if;
+
+ -- Currently it is not possible to inline pre/postconditions on a
+ -- subprogram subject to pragma Inline_Always.
+
+ Check_Postcondition_Use_In_Inlined_Subprogram (N, Spec_Id);
+
+ Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ end if;
+
+ Set_Is_Analyzed_Pragma (N);
+ end Analyze_Program_Exit_In_Decl_Part;
+
------------------------------------------
-- Analyze_Refined_Depends_In_Decl_Part --
------------------------------------------
@@ -30956,34 +31226,67 @@ package body Sem_Prag is
-- end Pack;
if Constit_Id = Any_Id then
- SPARK_Msg_NE ("& is undefined", Constit, Constit_Id);
+ -- A "Foo is undefined" message has already been
+ -- generated for this constituent. Emit an additional
+ -- message in the special case where the named
+ -- would-be constituent was declared too late in the
+ -- declaration list (as opposed to, for example, not
+ -- being declared at all).
+
+ -- Look for named constituent after freezing point
+ if Present (Freeze_Id) then
+ declare
+ Decl : Node_Id;
+ begin
+ Decl := Enclosing_Declaration (Freeze_Id);
- -- Emit a specialized info message when the contract of
- -- the related package body was "frozen" by another body.
- -- Note that it is not possible to precisely identify why
- -- the constituent is undefined because it is not visible
- -- when pragma Refined_State is analyzed. This message is
- -- a reasonable approximation.
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Object_Declaration
+ and then Same_Name (Defining_Identifier (Decl),
+ Constit)
+ and then not Constant_Present (Decl)
+ then
+ Error_Msg_Node_1 := Constit;
+ Error_Msg_Sloc :=
+ Sloc (Defining_Identifier (Decl));
- if Present (Freeze_Id) and then not Freeze_Posted then
- Freeze_Posted := True;
+ SPARK_Msg_NE
+ ("abstract state constituent & declared"
+ & " too late #!", Constit, Constit);
- Error_Msg_Name_1 := Chars (Body_Id);
- Error_Msg_Sloc := Sloc (Freeze_Id);
- SPARK_Msg_NE
- ("body & declared # freezes the contract of %",
- N, Freeze_Id);
- SPARK_Msg_N
- ("\all constituents must be declared before body #",
- N);
+ exit;
+ end if;
+ Next (Decl);
+ end loop;
+ end;
+
+ -- Emit a specialized info message when the contract
+ -- of the related package body was "frozen" by
+ -- another body. If a "declared too late" message
+ -- is generated, this will clarify what is meant by
+ -- "too late".
+
+ if not Freeze_Posted then
+ Freeze_Posted := True;
- -- A misplaced constituent is a critical error because
- -- pragma Refined_Depends or Refined_Global depends on
- -- the proper link between a state and a constituent.
- -- Stop the compilation, as this leads to a multitude
- -- of misleading cascaded errors.
+ Error_Msg_Name_1 := Chars (Body_Id);
+ Error_Msg_Sloc := Sloc (Freeze_Id);
+ SPARK_Msg_NE
+ ("body & declared # freezes the contract of %",
+ N, Freeze_Id);
+ SPARK_Msg_N
+ ("\all constituents must be declared" &
+ " before body #", N);
- raise Unrecoverable_Error;
+ -- A misplaced constituent is a critical error
+ -- because pragma Refined_Depends or
+ -- Refined_Global depends on the proper link
+ -- between a state and a constituent. Stop the
+ -- compilation, as this leads to a multitude of
+ -- misleading cascaded errors.
+
+ raise Unrecoverable_Error;
+ end if;
end if;
-- The constituent is a valid state or object
@@ -31452,10 +31755,10 @@ package body Sem_Prag is
Errors := Serious_Errors_Detected;
- -- Preanalyze_Assert_Expression, but without enforcing any of the
- -- acceptable types.
+ -- Preanalyze_And_Resolve_Assert_Expression, but without enforcing
+ -- any of the acceptable types.
- Preanalyze_Assert_Expression (Expr);
+ Preanalyze_And_Resolve_Assert_Expression (Expr);
-- Expression of a discrete type is allowed. Nothing more to check
-- for structural variants.
@@ -31468,12 +31771,8 @@ package body Sem_Prag is
-- Expression of a Big_Integer type (or its ghost variant) is only
-- allowed in Decreases clause.
- elsif
- Is_RTE (Base_Type (Etype (Expr)), RE_Big_Integer)
- or else
- Is_RTE (Base_Type (Etype (Expr)), RO_GH_Big_Integer)
- or else
- Is_RTE (Base_Type (Etype (Expr)), RO_SP_Big_Integer)
+ elsif Is_RTE (Base_Type (Etype (Expr)), RE_Big_Integer)
+ or else Is_RTE (Base_Type (Etype (Expr)), RO_SP_Big_Integer)
then
if Chars (Direction) = Name_Increases then
Error_Msg_N
@@ -31633,7 +31932,7 @@ package body Sem_Prag is
From_Aspect => True);
if Present (Arg) then
- Preanalyze_Assert_Expression
+ Preanalyze_And_Resolve_Assert_Expression
(Expression (Arg), Standard_Boolean);
end if;
end if;
@@ -31641,7 +31940,8 @@ package body Sem_Prag is
Arg := Test_Case_Arg (N, Arg_Nam);
if Present (Arg) then
- Preanalyze_Assert_Expression (Expression (Arg), Standard_Boolean);
+ Preanalyze_And_Resolve_Assert_Expression
+ (Expression (Arg), Standard_Boolean);
end if;
end Preanalyze_Test_Case_Arg;
@@ -33640,6 +33940,7 @@ package body Sem_Prag is
Pragma_Profile => 0,
Pragma_Profile_Warnings => 0,
Pragma_Propagate_Exceptions => 0,
+ Pragma_Program_Exit => -1,
Pragma_Provide_Shift_Operators => 0,
Pragma_Psect_Object => 0,
Pragma_Pure => 0,