summaryrefslogtreecommitdiff
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.adb646
1 files changed, 539 insertions, 107 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index e148d05bbf2..4fe6c57a5bd 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -213,6 +213,11 @@ package body Sem_Prag is
-- original one, following the renaming chain) is returned. Otherwise the
-- entity is returned unchanged. Should be in Einfo???
+ function Get_SPARK_Mode_Id (N : Name_Id) return SPARK_Mode_Id;
+ -- Subsidiary to the analysis of pragma SPARK_Mode as well as subprogram
+ -- Get_SPARK_Mode_Id. Convert a name into a corresponding value of type
+ -- SPARK_Mode_Id.
+
function Original_Name (N : Node_Id) return Name_Id;
-- N is a pragma node or aspect specification node. This function returns
-- the name of the pragma or aspect in original source form, taking into
@@ -1713,14 +1718,16 @@ package body Sem_Prag is
-- Preanalyze the boolean expression, we treat this as a spec expression
-- (i.e. similar to a default expression).
- Preanalyze_Assert_Expression (Get_Pragma_Arg (Arg1), Standard_Boolean);
-
- -- In ASIS mode, for a pragma generated from a source aspect, also
- -- analyze the original aspect expression.
+ -- In ASIS mode, for a pragma generated from a source aspect, analyze
+ -- directly the the original aspect expression, which is shared with
+ -- the generated pragma.
if ASIS_Mode and then Present (Corresponding_Aspect (N)) then
Preanalyze_Assert_Expression
(Expression (Corresponding_Aspect (N)), Standard_Boolean);
+ else
+ Preanalyze_Assert_Expression
+ (Get_Pragma_Arg (Arg1), Standard_Boolean);
end if;
-- For a class-wide condition, a reference to a controlling formal must
@@ -1749,6 +1756,9 @@ package body Sem_Prag is
-- accessparameter of type access-to-T is interpreted as having
-- type access-to-T'Class. This ensures the expression is well-
-- defined for a primitive subprogram of a type descended from T.
+ -- Note that this replacement is not done for selector names in
+ -- parameter associations. These carry an entity for reference
+ -- purposes, but semantically they are just identifiers.
-------------
-- Get_ACW --
@@ -1790,6 +1800,9 @@ package body Sem_Prag is
and then Present (Entity (N))
and then Is_Formal (Entity (N))
and then Nkind (Parent (N)) /= N_Type_Conversion
+ and then
+ (Nkind (Parent (N)) /= N_Parameter_Association
+ or else N /= Selector_Name (Parent (N)))
then
if Etype (Entity (N)) = T then
Typ := Class_Wide_Type (T);
@@ -3552,12 +3565,13 @@ package body Sem_Prag is
-- If we fall through loop, pragma is at start of list, so see if it
-- is at the start of declarations of a subprogram body.
- if Nkind (Parent (N)) = N_Subprogram_Body
- and then List_Containing (N) = Declarations (Parent (N))
+ PO := Parent (N);
+
+ if Nkind (PO) = N_Subprogram_Body
+ and then List_Containing (N) = Declarations (PO)
then
- if Operating_Mode /= Generate_Code
- or else Inside_A_Generic
- then
+ if Operating_Mode /= Generate_Code or else Inside_A_Generic then
+
-- Analyze pragma expression for correctness and for ASIS use
Preanalyze_Assert_Expression
@@ -3572,22 +3586,56 @@ package body Sem_Prag is
end if;
end if;
+ -- Retain a copy of the pre- or postcondition pragma for formal
+ -- verification purposes. The copy is needed because the pragma is
+ -- expanded into other constructs which are not acceptable in the
+ -- N_Contract node.
+
+ if Acts_As_Spec (PO)
+ and then (SPARK_Mode or else Formal_Extensions)
+ then
+ declare
+ Prag : constant Node_Id := New_Copy_Tree (N);
+
+ begin
+ -- Preanalyze the pragma
+
+ Preanalyze_Assert_Expression
+ (Get_Pragma_Arg
+ (First (Pragma_Argument_Associations (Prag))),
+ Standard_Boolean);
+
+ -- Preanalyze the corresponding aspect (if any)
+
+ if Present (Corresponding_Aspect (Prag)) then
+ Preanalyze_Assert_Expression
+ (Expression (Corresponding_Aspect (Prag)),
+ Standard_Boolean);
+ end if;
+
+ -- Chain the copy on the contract of the body
+
+ Add_Contract_Item
+ (Prag, Defining_Unit_Name (Specification (PO)));
+ end;
+ end if;
+
In_Body := True;
return;
-- See if it is in the pragmas after a library level subprogram
- elsif Nkind (Parent (N)) = N_Compilation_Unit_Aux then
+ elsif Nkind (PO) = N_Compilation_Unit_Aux then
-- In formal verification mode, analyze pragma expression for
-- correctness, as it is not expanded later.
if SPARK_Mode then
Analyze_PPC_In_Decl_Part
- (N, Defining_Entity (Unit (Parent (Parent (N)))));
+ (N, Defining_Entity (Unit (Parent (PO))));
end if;
- Chain_PPC (Unit (Parent (Parent (N))));
+ Chain_PPC (Unit (Parent (PO)));
return;
end if;
@@ -3740,7 +3788,6 @@ package body Sem_Prag is
begin
-- First check pragma arguments
- GNAT_Pragma;
Check_At_Least_N_Arguments (2);
Check_At_Most_N_Arguments (4);
Check_Arg_Order
@@ -4617,7 +4664,7 @@ package body Sem_Prag is
and then
Is_Spec_Name (Unit_Name (Current_Sem_Unit))
and then (Ekind (Cent) /= E_Package
- or else not In_Private_Part (Cent));
+ or else not In_Private_Part (Cent));
-- Set True if this is the warning case, and we are in the
-- visible part of a package spec, or in a subprogram spec,
-- in which case we want to force the client to see the
@@ -5289,7 +5336,6 @@ package body Sem_Prag is
procedure Process_Disable_Enable_Atomic_Sync (Nam : Name_Id) is
begin
- GNAT_Pragma;
Check_No_Identifiers;
Check_At_Most_N_Arguments (1);
@@ -5993,6 +6039,8 @@ package body Sem_Prag is
Check_No_Identifiers;
Check_At_Least_N_Arguments (1);
+ -- Check all arguments are names of generic units or instances
+
Arg := Arg1;
while Present (Arg) loop
Exp := Get_Pragma_Arg (Arg);
@@ -6977,33 +7025,8 @@ package body Sem_Prag is
Expr : Node_Id;
Val : Uint;
- procedure Check_Unit_Name (N : Node_Id);
- -- Checks unit name parameter for No_Dependence. Returns if it has
- -- an appropriate form, otherwise raises pragma argument error.
-
- ---------------------
- -- Check_Unit_Name --
- ---------------------
-
- procedure Check_Unit_Name (N : Node_Id) is
- begin
- if Nkind (N) = N_Selected_Component then
- Check_Unit_Name (Prefix (N));
- Check_Unit_Name (Selector_Name (N));
-
- elsif Nkind (N) = N_Identifier then
- return;
-
- else
- Error_Pragma_Arg
- ("wrong form for unit name for No_Dependence", N);
- end if;
- end Check_Unit_Name;
-
- -- Start of processing for Process_Restrictions_Or_Restriction_Warnings
-
begin
- -- Ignore all Restrictions pragma in CodePeer mode
+ -- Ignore all Restrictions pragmas in CodePeer mode
if CodePeer_Mode then
return;
@@ -7161,7 +7184,9 @@ package body Sem_Prag is
-- already made the necessary entry in the No_Dependence table.
elsif Id = Name_No_Dependence then
- Check_Unit_Name (Expr);
+ if not OK_No_Dependence_Unit_Name (Expr) then
+ raise Pragma_Exit;
+ end if;
-- Case of No_Specification_Of_Aspect => Identifier.
@@ -9650,8 +9675,8 @@ package body Sem_Prag is
-- pragma Check_Name (check_IDENTIFIER);
when Pragma_Check_Name =>
- Check_No_Identifiers;
GNAT_Pragma;
+ Check_No_Identifiers;
Check_Valid_Configuration_Pragma;
Check_Arg_Count (1);
Check_Arg_Is_Identifier (Arg1);
@@ -10076,11 +10101,19 @@ package body Sem_Prag is
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Contract_Cases_In_Decl_Part (N);
- -- Chain the pragma on the contract for further processing
+ -- When Contract_Cases applies to a subprogram compilation unit,
+ -- the corresponding pragma is placed after the unit's declaration
+ -- node and needs to be analyzed immediately.
- else
- Add_Contract_Item (N, Subp_Id);
+ elsif Nkind (Subp_Decl) = N_Subprogram_Declaration
+ and then Nkind (Parent (Subp_Decl)) = N_Compilation_Unit
+ then
+ Analyze_Contract_Cases_In_Decl_Part (N);
end if;
+
+ -- Chain the pragma on the contract for further processing
+
+ Add_Contract_Item (N, Subp_Id);
end Contract_Cases;
----------------
@@ -10294,7 +10327,7 @@ package body Sem_Prag is
if Warn_On_Obsolescent_Feature then
Error_Msg_N
- ("'G'N'A'T pragma cpp'_virtual is now obsolete and has no "
+ ("'G'N'A'T pragma Cpp'_Virtual is now obsolete and has no "
& "effect?j?", N);
end if;
end CPP_Virtual;
@@ -10309,7 +10342,7 @@ package body Sem_Prag is
if Warn_On_Obsolescent_Feature then
Error_Msg_N
- ("'G'N'A'T pragma cpp'_vtable is now obsolete and has no "
+ ("'G'N'A'T pragma Cpp'_Vtable is now obsolete and has no "
& "effect?j?", N);
end if;
end CPP_Vtable;
@@ -10584,11 +10617,19 @@ package body Sem_Prag is
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Depends_In_Decl_Part (N);
- -- Chain the pragma on the contract for further processing
+ -- When Depends applies to a subprogram compilation unit, the
+ -- corresponding pragma is placed after the unit's declaration
+ -- node and needs to be analyzed immediately.
- else
- Add_Contract_Item (N, Subp_Id);
+ elsif Nkind (Subp_Decl) = N_Subprogram_Declaration
+ and then Nkind (Parent (Subp_Decl)) = N_Compilation_Unit
+ then
+ Analyze_Depends_In_Decl_Part (N);
end if;
+
+ -- Chain the pragma on the contract for further processing
+
+ Add_Contract_Item (N, Subp_Id);
end Depends;
---------------------
@@ -10661,6 +10702,7 @@ package body Sem_Prag is
-- pragma Disable_Atomic_Synchronization [(Entity)];
when Pragma_Disable_Atomic_Synchronization =>
+ GNAT_Pragma;
Process_Disable_Enable_Atomic_Sync (Name_Suppress);
-------------------
@@ -11092,6 +11134,7 @@ package body Sem_Prag is
-- pragma Enable_Atomic_Synchronization [(Entity)];
when Pragma_Enable_Atomic_Synchronization =>
+ GNAT_Pragma;
Process_Disable_Enable_Atomic_Sync (Name_Unsuppress);
------------
@@ -11592,6 +11635,18 @@ package body Sem_Prag is
end case;
end External_Name_Casing;
+ ---------------
+ -- Fast_Math --
+ ---------------
+
+ -- pragma Fast_Math;
+
+ when Pragma_Fast_Math =>
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_Valid_Configuration_Pragma;
+ Fast_Math := True;
+
--------------------------
-- Favor_Top_Level --
--------------------------
@@ -11623,18 +11678,6 @@ package body Sem_Prag is
end if;
end Favor_Top_Level;
- ---------------
- -- Fast_Math --
- ---------------
-
- -- pragma Fast_Math;
-
- when Pragma_Fast_Math =>
- GNAT_Pragma;
- Check_No_Identifiers;
- Check_Valid_Configuration_Pragma;
- Fast_Math := True;
-
---------------------------
-- Finalize_Storage_Only --
---------------------------
@@ -11825,11 +11868,19 @@ package body Sem_Prag is
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Global_In_Decl_Part (N);
- -- Chain the pragma on the contract for further processing
+ -- When Global applies to a subprogram compilation unit, the
+ -- corresponding pragma is placed after the unit's declaration
+ -- node and needs to be analyzed immediately.
- else
- Add_Contract_Item (N, Subp_Id);
+ elsif Nkind (Subp_Decl) = N_Subprogram_Declaration
+ and then Nkind (Parent (Subp_Decl)) = N_Compilation_Unit
+ then
+ Analyze_Global_In_Decl_Part (N);
end if;
+
+ -- Chain the pragma on the contract for further processing
+
+ Add_Contract_Item (N, Subp_Id);
end Global;
-----------
@@ -11959,6 +12010,7 @@ package body Sem_Prag is
Ent : Entity_Id;
begin
+ GNAT_Pragma;
Check_No_Identifiers;
-- Form with no arguments
@@ -13339,8 +13391,8 @@ package body Sem_Prag is
-- abstract. ???
if not Is_Tagged_Type (Typ) or else not Is_Abstract_Type (Typ) then
- Error_Pragma_Arg ("pragma% requires an abstract "
- & "tagged type", Arg1);
+ Error_Pragma_Arg
+ ("pragma% requires an abstract tagged type", Arg1);
elsif not Has_Discriminants (Typ)
or else Ekind (Etype (First_Discriminant (Typ)))
@@ -14471,6 +14523,41 @@ package body Sem_Prag is
Optimize_Alignment_Local := True;
end Optimize_Alignment;
+ -------------
+ -- Ordered --
+ -------------
+
+ -- pragma Ordered (first_enumeration_subtype_LOCAL_NAME);
+
+ when Pragma_Ordered => Ordered : declare
+ Assoc : constant Node_Id := Arg1;
+ Type_Id : Node_Id;
+ Typ : Entity_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_Arg_Count (1);
+ Check_Arg_Is_Local_Name (Arg1);
+
+ Type_Id := Get_Pragma_Arg (Assoc);
+ Find_Type (Type_Id);
+ Typ := Entity (Type_Id);
+
+ if Typ = Any_Type then
+ return;
+ else
+ Typ := Underlying_Type (Typ);
+ end if;
+
+ if not Is_Enumeration_Type (Typ) then
+ Error_Pragma ("pragma% must specify enumeration type");
+ end if;
+
+ Check_First_Subtype (Arg1);
+ Set_Has_Pragma_Ordered (Base_Type (Typ));
+ end Ordered;
+
-------------------
-- Overflow_Mode --
-------------------
@@ -14551,43 +14638,17 @@ package body Sem_Prag is
end if;
end Overflow_Mode;
- when Pragma_Overriding_Renamings =>
- Overriding_Renamings := True;
-
- -------------
- -- Ordered --
- -------------
-
- -- pragma Ordered (first_enumeration_subtype_LOCAL_NAME);
+ --------------------------
+ -- Overriding Renamings --
+ --------------------------
- when Pragma_Ordered => Ordered : declare
- Assoc : constant Node_Id := Arg1;
- Type_Id : Node_Id;
- Typ : Entity_Id;
+ -- pragma Overriding_Renamings;
- begin
+ when Pragma_Overriding_Renamings =>
GNAT_Pragma;
- Check_No_Identifiers;
- Check_Arg_Count (1);
- Check_Arg_Is_Local_Name (Arg1);
-
- Type_Id := Get_Pragma_Arg (Assoc);
- Find_Type (Type_Id);
- Typ := Entity (Type_Id);
-
- if Typ = Any_Type then
- return;
- else
- Typ := Underlying_Type (Typ);
- end if;
-
- if not Is_Enumeration_Type (Typ) then
- Error_Pragma ("pragma% must specify enumeration type");
- end if;
-
- Check_First_Subtype (Arg1);
- Set_Has_Pragma_Ordered (Base_Type (Typ));
- end Ordered;
+ Check_Arg_Count (0);
+ Check_Valid_Configuration_Pragma;
+ Overriding_Renamings := True;
----------
-- Pack --
@@ -15022,7 +15083,7 @@ package body Sem_Prag is
-- pragma Predicate
-- ([Entity =>] type_LOCAL_NAME,
- -- [Check =>] EXPRESSION);
+ -- [Check =>] boolean_EXPRESSION);
when Pragma_Predicate => Predicate : declare
Type_Id : Node_Id;
@@ -15452,8 +15513,10 @@ package body Sem_Prag is
GNAT_Pragma;
Check_Arg_Count (0);
- if In_Extended_Main_Source_Unit (N) then
- Propagate_Exceptions := True;
+ if Warn_On_Obsolescent_Feature then
+ Error_Msg_N
+ ("'G'N'A'T pragma Propagate'_Exceptions is now obsolete " &
+ "and has no effect?j?", N);
end if;
------------------
@@ -16042,6 +16105,8 @@ package body Sem_Prag is
-- Short_Circuit_And_Or --
--------------------------
+ -- pragma Short_Circuit_And_Or;
+
when Pragma_Short_Circuit_And_Or =>
GNAT_Pragma;
Check_Arg_Count (0);
@@ -16052,7 +16117,9 @@ package body Sem_Prag is
-- Share_Generic --
-------------------
- -- pragma Share_Generic (NAME {, NAME});
+ -- pragma Share_Generic (GNAME {, GNAME});
+
+ -- GNAME ::= generic_unit_NAME | generic_instance_NAME
when Pragma_Share_Generic =>
GNAT_Pragma;
@@ -16267,6 +16334,290 @@ package body Sem_Prag is
when Pragma_Source_Reference =>
GNAT_Pragma;
+ ----------------
+ -- SPARK_Mode --
+ ----------------
+
+ -- pragma SPARK_Mode (On | Off | Auto);
+
+ when Pragma_SPARK_Mode => SPARK_Mod : declare
+ procedure Chain_Pragma (Context : Entity_Id; Prag : Node_Id);
+ -- Associate a SPARK_Mode pragma with the context where it lives.
+ -- If the context is a package spec or a body, the routine checks
+ -- the consistency between modes of visible/private declarations
+ -- and body declarations/statements.
+
+ procedure Check_Conformance
+ (Governing_Id : Entity_Id;
+ New_Id : Entity_Id);
+ -- Verify the "monotonicity" of SPARK modes between two entities.
+ -- The order of modes is Off < Auto < On. Governing_Id establishes
+ -- the mode of the context. New_Id attempts to redefine the known
+ -- mode.
+
+ procedure Check_Pragma_Conformance
+ (Governing_Mode : Node_Id;
+ New_Mode : Node_Id);
+ -- Verify the "monotonicity" of two SPARK_Mode pragmas. The order
+ -- of modes is Off < Auto < On. Governing_Mode is the established
+ -- mode dictated by the context. New_Mode attempts to redefine the
+ -- governing mode.
+
+ function Get_SPARK_Mode_Name (Id : SPARK_Mode_Id) return Name_Id;
+ -- Convert a value of type SPARK_Mode_Id into a corresponding name
+
+ ------------------
+ -- Chain_Pragma --
+ ------------------
+
+ procedure Chain_Pragma (Context : Entity_Id; Prag : Node_Id) is
+ Existing_Prag : constant Node_Id :=
+ SPARK_Mode_Pragmas (Context);
+ begin
+ -- The context does not have a prior mode defined
+
+ if No (Existing_Prag) then
+ Set_SPARK_Mode_Pragmas (Context, Prag);
+
+ -- Chain the new mode on the list of SPARK_Mode pragmas. Verify
+ -- the consistency between the existing mode and the new one.
+
+ else
+ Set_Next_Pragma (Existing_Prag, Prag);
+
+ Check_Pragma_Conformance
+ (Governing_Mode => Existing_Prag,
+ New_Mode => Prag);
+ end if;
+ end Chain_Pragma;
+
+ -----------------------
+ -- Check_Conformance --
+ -----------------------
+
+ procedure Check_Conformance
+ (Governing_Id : Entity_Id;
+ New_Id : Entity_Id)
+ is
+ Gov_Prag : constant Node_Id :=
+ SPARK_Mode_Pragmas (Governing_Id);
+ New_Prag : constant Node_Id := SPARK_Mode_Pragmas (New_Id);
+
+ begin
+ -- Nothing to do when one or both entities lack a mode
+
+ if No (Gov_Prag) or else No (New_Prag) then
+ return;
+ end if;
+
+ -- Do not compare the modes of a package spec and body when the
+ -- spec mode appears in the private part. In this case the spec
+ -- mode does not affect the body.
+
+ if Ekind_In (Governing_Id, E_Generic_Package, E_Package)
+ and then Ekind (New_Id) = E_Package_Body
+ and then Is_Private_SPARK_Mode (Gov_Prag)
+ then
+ null;
+
+ -- Test the pragmas
+
+ else
+ Check_Pragma_Conformance
+ (Governing_Mode => Gov_Prag,
+ New_Mode => New_Prag);
+ end if;
+ end Check_Conformance;
+
+ ------------------------------
+ -- Check_Pragma_Conformance --
+ ------------------------------
+
+ procedure Check_Pragma_Conformance
+ (Governing_Mode : Node_Id;
+ New_Mode : Node_Id)
+ is
+ Gov_M : constant SPARK_Mode_Id :=
+ Get_SPARK_Mode_Id (Governing_Mode);
+ New_M : constant SPARK_Mode_Id := Get_SPARK_Mode_Id (New_Mode);
+
+ begin
+ -- The new mode is less restrictive than the established mode
+
+ if Gov_M < New_M then
+ Error_Msg_Name_1 := Get_SPARK_Mode_Name (New_M);
+ Error_Msg_N ("cannot define 'S'P'A'R'K mode %", New_Mode);
+
+ Error_Msg_Name_1 := Get_SPARK_Mode_Name (Gov_M);
+ Error_Msg_Sloc := Sloc (Governing_Mode);
+ Error_Msg_N
+ ("\mode is less restrictive than mode % defined #",
+ New_Mode);
+ end if;
+ end Check_Pragma_Conformance;
+
+ -------------------------
+ -- Get_SPARK_Mode_Name --
+ -------------------------
+
+ function Get_SPARK_Mode_Name (Id : SPARK_Mode_Id) return Name_Id is
+ begin
+ if Id = SPARK_On then
+ return Name_On;
+ elsif Id = SPARK_Off then
+ return Name_Off;
+ elsif Id = SPARK_Auto then
+ return Name_Auto;
+
+ -- Mode "None" should never be used in error message generation
+
+ else
+ raise Program_Error;
+ end if;
+ end Get_SPARK_Mode_Name;
+
+ -- Local variables
+
+ Body_Id : Entity_Id;
+ Context : Node_Id;
+ Mode : Name_Id;
+ Mode_Id : SPARK_Mode_Id;
+ Spec_Id : Entity_Id;
+ Stmt : Node_Id;
+
+ -- Start of processing for SPARK_Mode
+
+ begin
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_At_Most_N_Arguments (1);
+
+ -- Check the legality of the mode
+
+ if Arg_Count = 1 then
+ Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off, Name_Auto);
+ Mode := Chars (Get_Pragma_Arg (Arg1));
+
+ -- A SPARK_Mode without an argument defaults to "On"
+
+ else
+ Mode := Name_On;
+ end if;
+
+ Mode_Id := Get_SPARK_Mode_Id (Mode);
+ Context := Parent (N);
+
+ -- The pragma appears in a configuration file
+
+ if No (Context) then
+ Check_Valid_Configuration_Pragma;
+ Global_SPARK_Mode := Mode_Id;
+
+ -- When the pragma is placed before the declaration of a unit, it
+ -- configures the whole unit.
+
+ elsif Nkind (Context) = N_Compilation_Unit then
+ Check_Valid_Configuration_Pragma;
+ Set_SPARK_Mode_Pragma (Current_Sem_Unit, N);
+
+ -- The pragma applies to a [library unit] subprogram or package
+
+ else
+ -- Mode "Auto" cannot be used in nested subprograms or packages
+
+ if Mode_Id = SPARK_Auto then
+ Error_Pragma_Arg
+ ("mode `Auto` can only apply to the configuration variant "
+ & "of pragma %", Arg1);
+ end if;
+
+ -- Verify the placement of the pragma with respect to package
+ -- or subprogram declarations and detect duplicates.
+
+ Stmt := Prev (N);
+ while Present (Stmt) loop
+
+ -- Skip prior pragmas, but check for duplicates
+
+ if Nkind (Stmt) = N_Pragma then
+ if Pragma_Name (Stmt) = Pname then
+ Error_Msg_Name_1 := Pname;
+ Error_Msg_Sloc := Sloc (Stmt);
+ Error_Msg_N
+ ("pragma % duplicates pragma declared #", N);
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Stmt) then
+ null;
+
+ -- The pragma applies to a package or subprogram declaration
+
+ elsif Nkind_In (Stmt, N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Package_Declaration,
+ N_Subprogram_Declaration)
+ then
+ Spec_Id := Defining_Unit_Name (Specification (Stmt));
+ Chain_Pragma (Spec_Id, N);
+ return;
+
+ -- The pragma does not apply to a legal construct, issue an
+ -- error and stop the analysis.
+
+ else
+ Pragma_Misplaced;
+ exit;
+ end if;
+
+ Stmt := Prev (Stmt);
+ end loop;
+
+ -- If we get here, then we ran out of preceding statements. The
+ -- pragma is immediately within a body.
+
+ if Nkind_In (Context, N_Package_Body,
+ N_Subprogram_Body)
+ then
+ Spec_Id := Corresponding_Spec (Context);
+
+ if Nkind (Context) = N_Subprogram_Body then
+ Context := Specification (Context);
+ end if;
+
+ Body_Id := Defining_Unit_Name (Context);
+
+ Chain_Pragma (Body_Id, N);
+ Check_Conformance (Spec_Id, Body_Id);
+
+ -- The pragma is at the top level of a package spec
+
+ elsif Nkind (Context) = N_Package_Specification then
+ Spec_Id := Defining_Unit_Name (Context);
+ Chain_Pragma (Spec_Id, N);
+
+ -- The pragma applies to the statements of a package body
+
+ elsif Nkind (Context) = N_Handled_Sequence_Of_Statements
+ and then Nkind (Parent (Context)) = N_Package_Body
+ then
+ Context := Parent (Context);
+ Spec_Id := Corresponding_Spec (Context);
+ Body_Id := Defining_Unit_Name (Context);
+
+ Chain_Pragma (Body_Id, N);
+ Check_Conformance (Spec_Id, Body_Id);
+
+ -- The pragma does not apply to a legal construct, issue an
+ -- error.
+
+ else
+ Pragma_Misplaced;
+ end if;
+ end if;
+ end SPARK_Mod;
+
--------------------------------
-- Static_Elaboration_Desired --
--------------------------------
@@ -16890,6 +17241,7 @@ package body Sem_Prag is
-- MODE_TYPE ::= Nominal | Robustness
when Pragma_Test_Case =>
+ GNAT_Pragma;
Check_Test_Case;
--------------------------
@@ -18219,6 +18571,43 @@ package body Sem_Prag is
return Result;
end Get_Base_Subprogram;
+ -----------------------
+ -- Get_SPARK_Mode_Id --
+ -----------------------
+
+ function Get_SPARK_Mode_Id (N : Name_Id) return SPARK_Mode_Id is
+ begin
+ if N = Name_On then
+ return SPARK_On;
+ elsif N = Name_Off then
+ return SPARK_Off;
+ elsif N = Name_Auto then
+ return SPARK_Auto;
+
+ -- Any other argument is erroneous
+
+ else
+ raise Program_Error;
+ end if;
+ end Get_SPARK_Mode_Id;
+
+ -----------------------
+ -- Get_SPARK_Mode_Id --
+ -----------------------
+
+ function Get_SPARK_Mode_Id (N : Node_Id) return SPARK_Mode_Id is
+ Mode : Node_Id;
+
+ begin
+ pragma Assert
+ (Nkind (N) = N_Pragma
+ and then Present (Pragma_Argument_Associations (N)));
+
+ Mode := First (Pragma_Argument_Associations (N));
+
+ return Get_SPARK_Mode_Id (Chars (Get_Pragma_Arg (Mode)));
+ end Get_SPARK_Mode_Id;
+
----------------
-- Initialize --
----------------
@@ -18283,11 +18672,33 @@ package body Sem_Prag is
-- Start of processing for Is_Config_Static_String
begin
-
Name_Len := 0;
+
return Add_Config_Static_String (Arg);
end Is_Config_Static_String;
+ -------------------------------
+ -- Is_Elaboration_SPARK_Mode --
+ -------------------------------
+
+ function Is_Elaboration_SPARK_Mode (N : Node_Id) return Boolean is
+ begin
+ pragma Assert
+ (Nkind (N) = N_Pragma
+ and then Pragma_Name (N) = Name_SPARK_Mode
+ and then Is_List_Member (N));
+
+ -- Pragma SPARK_Mode affects the elaboration of a package body when it
+ -- appears in the statement part of the body.
+
+ return
+ Present (Parent (N))
+ and then Nkind (Parent (N)) = N_Handled_Sequence_Of_Statements
+ and then List_Containing (N) = Statements (Parent (N))
+ and then Present (Parent (Parent (N)))
+ and then Nkind (Parent (Parent (N))) = N_Package_Body;
+ end Is_Elaboration_SPARK_Mode;
+
-----------------------------------------
-- Is_Non_Significant_Pragma_Reference --
-----------------------------------------
@@ -18475,6 +18886,7 @@ package body Sem_Prag is
Pragma_Source_File_Name => -1,
Pragma_Source_File_Name_Project => -1,
Pragma_Source_Reference => -1,
+ Pragma_SPARK_Mode => 0,
Pragma_Storage_Size => -1,
Pragma_Storage_Unit => -1,
Pragma_Static_Elaboration_Desired => -1,
@@ -18633,6 +19045,26 @@ package body Sem_Prag is
end if;
end Is_Pragma_String_Literal;
+ ---------------------------
+ -- Is_Private_SPARK_Mode --
+ ---------------------------
+
+ function Is_Private_SPARK_Mode (N : Node_Id) return Boolean is
+ begin
+ pragma Assert
+ (Nkind (N) = N_Pragma
+ and then Pragma_Name (N) = Name_SPARK_Mode
+ and then Is_List_Member (N));
+
+ -- For pragma SPARK_Mode to be private, it has to appear in the private
+ -- declarations of a package.
+
+ return
+ Present (Parent (N))
+ and then Nkind (Parent (N)) = N_Package_Specification
+ and then List_Containing (N) = Private_Declarations (Parent (N));
+ end Is_Private_SPARK_Mode;
+
-----------------------------
-- Is_Valid_Assertion_Kind --
-----------------------------