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.adb276
1 files changed, 134 insertions, 142 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 399753a365e..937ca4bcfc2 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -18056,116 +18056,58 @@ package body Sem_Prag is
-- 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_Spark_Mode_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 is the desired new 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.
+ Body_Id : Entity_Id;
+ Context : Node_Id;
+ Mode : Name_Id;
+ Mode_Id : SPARK_Mode_Type;
+ Spec_Id : Entity_Id;
+ Stmt : Node_Id;
+
+ procedure Check_Pragma_Conformance (Old_Pragma : Node_Id);
+ -- Verify the monotonicity of SPARK modes between the new pragma
+ -- N, and the old pragma, Old_Pragma, that was inherited. If
+ -- Old_Pragma is Empty, the call has no effect, otherwise we
+ -- verify that the new mode is less restrictive than the old mode.
+ -- For example, if the old mode is ON, then the new mode can be
+ -- anything. But if the old mode is OFF, then the only allowed
+ -- new mode is also OFF. If there is no error, this routine also
+ -- sets SPARK_Mode_Pragma to N, and SPARK_Mode to Mode_Id.
function Get_SPARK_Mode_Name (Id : SPARK_Mode_Type) return Name_Id;
-- Convert a value of type SPARK_Mode_Type to corresponding name
- ------------------
- -- Chain_Pragma --
- ------------------
-
- procedure Chain_Pragma (Context : Entity_Id; Prag : Node_Id) is
- Existing_Prag : constant Node_Id :=
- SPARK_Mode_Pragmas (Context);
-
- begin
- -- Chain existing pragmas to this one, checking consistency
-
- if Present (Existing_Prag) then
- Check_Pragma_Conformance
- (Governing_Mode => Existing_Prag,
- New_Mode => Prag);
-
- Set_Next_Pragma (Prag, Existing_Prag);
- end if;
-
- Set_SPARK_Mode_Pragmas (Context, Prag);
- end Chain_Pragma;
-
- ----------------------------------
- -- Check_Spark_Mode_Conformance --
- ----------------------------------
-
- procedure Check_Spark_Mode_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_Spark_Mode_Conformance;
-
------------------------------
-- Check_Pragma_Conformance --
------------------------------
- procedure Check_Pragma_Conformance
- (Governing_Mode : Node_Id;
- New_Mode : Node_Id)
- is
- Gov_M : constant SPARK_Mode_Type :=
- Get_SPARK_Mode_From_Pragma (Governing_Mode);
- New_M : constant SPARK_Mode_Type :=
- Get_SPARK_Mode_From_Pragma (New_Mode);
-
+ procedure Check_Pragma_Conformance (Old_Pragma : Node_Id) is
begin
- -- The new mode is less restrictive than the established mode
+ if Present (Old_Pragma) then
+ pragma Assert (Nkind (Old_Pragma) = N_Pragma);
- 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);
+ declare
+ Gov_M : constant SPARK_Mode_Type :=
+ Get_SPARK_Mode_From_Pragma (Old_Pragma);
- 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);
+ begin
+ -- New mode less restrictive than the established mode
+
+ if Gov_M < Mode_Id then
+ Error_Msg_Name_1 := Mode;
+ Error_Msg_N ("cannot define 'S'P'A'R'K mode %", Arg1);
+
+ Error_Msg_Name_1 := Get_SPARK_Mode_Name (SPARK_Mode);
+ Error_Msg_Sloc := Sloc (SPARK_Mode_Pragma);
+ Error_Msg_N
+ ("\mode is less restrictive than mode "
+ & "% defined #", Arg1);
+ raise Pragma_Exit;
+ end if;
+ end;
end if;
+
+ SPARK_Mode_Pragma := N;
+ SPARK_Mode := Mode_Id;
end Check_Pragma_Conformance;
-------------------------
@@ -18190,15 +18132,6 @@ package body Sem_Prag is
end if;
end Get_SPARK_Mode_Name;
- -- Local variables
-
- Body_Id : Entity_Id;
- Context : Node_Id;
- Mode : Name_Id;
- Mode_Id : SPARK_Mode_Type;
- Spec_Id : Entity_Id;
- Stmt : Node_Id;
-
-- Start of processing for SPARK_Mod
begin
@@ -18217,19 +18150,29 @@ package body Sem_Prag is
Mode_Id := Get_SPARK_Mode_Type (Mode);
Context := Parent (N);
- SPARK_Mode := Mode_Id;
- -- The pragma appears in a configuration file
+ -- The pragma appears in a configuration pragmas file
if No (Context) then
Check_Valid_Configuration_Pragma;
+ if Present (SPARK_Mode_Pragma) then
+ Error_Msg_Sloc := Sloc (SPARK_Mode_Pragma);
+ Error_Msg_N ("pragma% duplicates pragma declared#", N);
+ raise Pragma_Exit;
+ end if;
+
+ SPARK_Mode_Pragma := N;
+ 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);
+
+ SPARK_Mode_Pragma := N;
+ SPARK_Mode := Mode_Id;
-- The pragma applies to a [library unit] subprogram or package
@@ -18238,8 +18181,8 @@ package body Sem_Prag is
if Mode_Id = Auto then
Error_Pragma_Arg
- ("mode `Auto` can only apply to the configuration variant "
- & "of pragma %", Arg1);
+ ("mode `Auto` is only allowed when pragma % appears as "
+ & "a configuration pragma", Arg1);
end if;
-- Verify the placement of the pragma with respect to package
@@ -18255,6 +18198,7 @@ package body Sem_Prag is
Error_Msg_Name_1 := Pname;
Error_Msg_Sloc := Sloc (Stmt);
Error_Msg_N ("pragma% duplicates pragma declared#", N);
+ raise Pragma_Exit;
end if;
-- Skip internally generated code
@@ -18262,15 +18206,31 @@ package body Sem_Prag is
elsif not Comes_From_Source (Stmt) then
null;
- -- The pragma applies to a package or subprogram declaration
+ -- The pragma applies to a package declaration
elsif Nkind_In (Stmt, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration,
- N_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Spec_Id := Defining_Unit_Name (Specification (Stmt));
+ Check_Pragma_Conformance (SPARK_Pragma (Spec_Id));
+
+ Set_SPARK_Pragma (Spec_Id, N);
+ Set_SPARK_Pragma_Inherited (Spec_Id, False);
+ Set_SPARK_Aux_Pragma (Spec_Id, N);
+ Set_SPARK_Aux_Pragma_Inherited (Spec_Id, True);
+
+ return;
+
+ -- The pragma applies to a subprogram declaration
+
+ elsif Nkind_In (Stmt, N_Generic_Subprogram_Declaration,
N_Subprogram_Declaration)
then
Spec_Id := Defining_Unit_Name (Specification (Stmt));
- Chain_Pragma (Spec_Id, N);
+ Check_Pragma_Conformance (SPARK_Pragma (Spec_Id));
+
+ Set_SPARK_Pragma (Spec_Id, N);
+ Set_SPARK_Pragma_Inherited (Spec_Id, False);
return;
-- The pragma does not apply to a legal construct, issue an
@@ -18304,48 +18264,79 @@ package body Sem_Prag is
end if;
end if;
- -- The pragma is at the top level of a package spec or appears
- -- as an aspect on a subprogram.
-
- -- function F ... with SPARK_Mode => ...;
+ -- The pragma is at the top level of a package spec
-- package P is
-- pragma SPARK_Mode;
- if Nkind_In (Context, N_Function_Specification,
- N_Package_Specification,
- N_Procedure_Specification)
+ -- or
+
+ -- package P is
+ -- ...
+ -- private
+ -- pragma SPARK_Mode;
+
+ if Nkind (Context) = N_Package_Specification then
+ Spec_Id := Defining_Unit_Name (Context);
+
+ -- Pragma applies to private part
+
+ if List_Containing (N) = Private_Declarations (Context) then
+ Check_Pragma_Conformance (SPARK_Aux_Pragma (Spec_Id));
+ Set_SPARK_Aux_Pragma (Spec_Id, N);
+ Set_SPARK_Aux_Pragma_Inherited (Spec_Id, False);
+
+ -- Pragma applies to public part
+
+ else
+ Check_Pragma_Conformance (SPARK_Pragma (Spec_Id));
+ Set_SPARK_Pragma (Spec_Id, N);
+ Set_SPARK_Pragma_Inherited (Spec_Id, False);
+ Set_SPARK_Aux_Pragma (Spec_Id, N);
+ Set_SPARK_Aux_Pragma_Inherited (Spec_Id, True);
+ end if;
+
+ -- The pragma appears as an aspect on a subprogram.
+
+ -- function F ... with SPARK_Mode => ...;
+
+ elsif Nkind_In (Context, N_Function_Specification,
+ N_Procedure_Specification)
then
Spec_Id := Defining_Unit_Name (Context);
- Chain_Pragma (Spec_Id, N);
+ Check_Pragma_Conformance (SPARK_Pragma (Spec_Id));
- -- Pragma is immediately within a package or subprogram body
+ Set_SPARK_Pragma (Spec_Id, N);
+ Set_SPARK_Pragma_Inherited (Spec_Id, False);
- -- function F ... is
- -- pragma SPARK_Mode;
+ -- Pragma is immediately within a package body
-- package body P is
-- pragma SPARK_Mode;
- elsif Nkind_In (Context, N_Package_Body,
- N_Subprogram_Body)
- then
+ elsif Nkind (Context) = N_Package_Body then
Spec_Id := Corresponding_Spec (Context);
+ Body_Id := Defining_Entity (Context);
+ Check_Pragma_Conformance (SPARK_Pragma (Body_Id));
- if Nkind (Context) = N_Subprogram_Body then
- Context := Specification (Context);
- end if;
+ Set_SPARK_Pragma (Body_Id, N);
+ Set_SPARK_Pragma_Inherited (Body_Id, False);
+ Set_SPARK_Aux_Pragma (Body_Id, N);
+ Set_SPARK_Aux_Pragma_Inherited (Body_Id, True);
- Body_Id := Defining_Entity (Context);
+ -- Pragma is immediately within a subprogram body
- Chain_Pragma (Body_Id, N);
+ -- function F ... is
+ -- pragma SPARK_Mode;
- -- Verify that the SPARK modes are consistent between
- -- body and spec, if any.
+ elsif Nkind (Context) = N_Subprogram_Body then
+ Spec_Id := Corresponding_Spec (Context);
+ Context := Specification (Context);
+ Body_Id := Defining_Entity (Context);
+ Check_Pragma_Conformance (SPARK_Pragma (Body_Id));
- if Present (Spec_Id) then
- Check_Spark_Mode_Conformance (Spec_Id, Body_Id);
- end if;
+ Set_SPARK_Pragma (Body_Id, N);
+ Set_SPARK_Pragma_Inherited (Body_Id, False);
-- The pragma applies to the statements of a package body
@@ -18359,9 +18350,10 @@ package body Sem_Prag is
Context := Parent (Context);
Spec_Id := Corresponding_Spec (Context);
Body_Id := Defining_Unit_Name (Context);
+ Check_Pragma_Conformance (SPARK_Aux_Pragma (Body_Id));
- Chain_Pragma (Body_Id, N);
- Check_Spark_Mode_Conformance (Spec_Id, Body_Id);
+ Set_SPARK_Aux_Pragma (Body_Id, N);
+ Set_SPARK_Aux_Pragma_Inherited (Body_Id, False);
-- The pragma does not apply to a legal construct, issue error