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.adb2377
1 files changed, 1994 insertions, 383 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 32b5130f797..0636b8e272b 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -181,11 +181,24 @@ package body Sem_Prag is
-- original one, following the renaming chain) is returned. Otherwise the
-- entity is returned unchanged. Should be in Einfo???
+ function Is_Valid_Assertion_Kind (Nam : Name_Id) return Boolean;
+ -- Returns True if Nam is one of the names recognized as a valid assertion
+ -- kind by the Assertion_Policy pragma. Note that the 'Class cases are
+ -- represented by the corresponding special names Name_uPre, Name_uPost,
+ -- Name_uInviarnat, and Name_uType_Invariant (_Pre, _Post, _Invariant,
+ -- and _Type_Invariant).
+
procedure Preanalyze_CTC_Args (N, Arg_Req, Arg_Ens : Node_Id);
-- Preanalyze the boolean expressions in the Requires and Ensures arguments
-- of a Contract_Case or Test_Case pragma if present (possibly Empty). We
-- treat these as spec expressions (i.e. similar to a default expression).
+ procedure Rewrite_Assertion_Kind (N : Node_Id);
+ -- If N is Pre'Class, Post'Class, Invariant'Class, or Type_Invariant'Class,
+ -- then it is rewritten as an identifier with the corresponding special
+ -- name _Pre, _Post, _Invariant, or _Type_Invariant. Used by pragmas
+ -- Check, Check_Policy.
+
procedure rv;
-- This is a dummy function called by the processing for pragma Reviewable.
-- It is there for assisting front end debugging. By placing a Reviewable
@@ -248,20 +261,68 @@ package body Sem_Prag is
------------------------------
procedure Analyze_CTC_In_Decl_Part (N : Node_Id; S : Entity_Id) is
+
+ procedure Analyze_Contract_Cases (Aggr : Node_Id);
+ -- Pre-analyze the guard and consequence expressions of a Contract_Cases
+ -- pragma/aspect aggregate expression.
+
+ ----------------------------
+ -- Analyze_Contract_Cases --
+ ----------------------------
+
+ procedure Analyze_Contract_Cases (Aggr : Node_Id) is
+ Case_Guard : Node_Id;
+ Conseq : Node_Id;
+ Post_Case : Node_Id;
+
+ begin
+ Post_Case := First (Component_Associations (Aggr));
+ while Present (Post_Case) loop
+ Case_Guard := First (Choices (Post_Case));
+ Conseq := Expression (Post_Case);
+
+ -- Preanalyze the boolean expression, we treat this as a spec
+ -- expression (i.e. similar to a default expression).
+
+ if Nkind (Case_Guard) /= N_Others_Choice then
+ Preanalyze_Assert_Expression (Case_Guard, Standard_Boolean);
+ end if;
+
+ Preanalyze_Assert_Expression (Conseq, Standard_Boolean);
+
+ Next (Post_Case);
+ end loop;
+ end Analyze_Contract_Cases;
+
+ -- Start of processing for Analyze_CTC_In_Decl_Part
+
begin
-- Install formals and push subprogram spec onto scope stack so that we
-- can see the formals from the pragma.
- Install_Formals (S);
Push_Scope (S);
+ Install_Formals (S);
-- Preanalyze the boolean expressions, we treat these as spec
-- expressions (i.e. similar to a default expression).
- Preanalyze_CTC_Args
- (N,
- Get_Requires_From_CTC_Pragma (N),
- Get_Ensures_From_CTC_Pragma (N));
+ if Nam_In (Pragma_Name (N), Name_Test_Case, Name_Contract_Case) then
+ Preanalyze_CTC_Args
+ (N,
+ Get_Requires_From_CTC_Pragma (N),
+ Get_Ensures_From_CTC_Pragma (N));
+
+ elsif Pragma_Name (N) = Name_Contract_Cases then
+ Analyze_Contract_Cases
+ (Expression (First (Pragma_Argument_Associations (N))));
+
+ -- In ASIS mode, for a pragma generated from a source aspect, also
+ -- analyze the original aspect expression.
+
+ if ASIS_Mode and then Present (Corresponding_Aspect (N)) then
+ Analyze_Contract_Cases (Expression (Corresponding_Aspect (N)));
+ end if;
+ end if;
-- Remove the subprogram from the scope stack now that the pre-analysis
-- of the expressions in the contract case or test case is done.
@@ -401,9 +462,8 @@ package body Sem_Prag is
Error_Msg_Name_2 := Name_Class;
Error_Msg_N
- ("aspect `%''%` can only be specified for a primitive " &
- "operation of a tagged type",
- Corresponding_Aspect (N));
+ ("aspect `%''%` can only be specified for a primitive "
+ & "operation of a tagged type", Corresponding_Aspect (N));
end if;
Replace_Type (Get_Pragma_Arg (Arg1));
@@ -459,6 +519,11 @@ package body Sem_Prag is
-- In Ada 95 or 05 mode, these are implementation defined pragmas, so
-- should be caught by the No_Implementation_Pragmas restriction.
+ procedure Add_Item (Item : Entity_Id; To_List : in out Elist_Id);
+ -- Subsidiary routine to the analysis of pragmas Depends and Global.
+ -- Append an input or output item to a list. If the list is empty, a
+ -- new one is created.
+
procedure Check_Ada_83_Warning;
-- Issues a warning message for the current pragma if operating in Ada
-- 83 mode (used for language pragmas that are not a standard part of
@@ -984,6 +1049,19 @@ package body Sem_Prag is
end if;
end Ada_2012_Pragma;
+ --------------
+ -- Add_Item --
+ --------------
+
+ procedure Add_Item (Item : Entity_Id; To_List : in out Elist_Id) is
+ begin
+ if No (To_List) then
+ To_List := New_Elmt_List;
+ end if;
+
+ Append_Unique_Elmt (Item, To_List);
+ end Add_Item;
+
--------------------------
-- Check_Ada_83_Warning --
--------------------------
@@ -1143,6 +1221,7 @@ package body Sem_Prag is
OK : Boolean;
Ent : constant Entity_Id := Entity (Argx);
Scop : constant Entity_Id := Scope (Ent);
+
begin
-- Case of a pragma applied to a compilation unit: pragma must
-- occur immediately after the program unit in the compilation.
@@ -1239,7 +1318,7 @@ package body Sem_Prag is
begin
Check_Arg_Is_Identifier (Argx);
- if Chars (Argx) /= N1 and then Chars (Argx) /= N2 then
+ if not Nam_In (Chars (Argx), N1, N2) then
Error_Msg_Name_2 := N1;
Error_Msg_Name_3 := N2;
Error_Pragma_Arg ("argument for pragma% must be% or%", Argx);
@@ -1255,10 +1334,7 @@ package body Sem_Prag is
begin
Check_Arg_Is_Identifier (Argx);
- if Chars (Argx) /= N1
- and then Chars (Argx) /= N2
- and then Chars (Argx) /= N3
- then
+ if not Nam_In (Chars (Argx), N1, N2, N3) then
Error_Pragma_Arg ("invalid argument for pragma%", Argx);
end if;
end Check_Arg_Is_One_Of;
@@ -1272,11 +1348,7 @@ package body Sem_Prag is
begin
Check_Arg_Is_Identifier (Argx);
- if Chars (Argx) /= N1
- and then Chars (Argx) /= N2
- and then Chars (Argx) /= N3
- and then Chars (Argx) /= N4
- then
+ if not Nam_In (Chars (Argx), N1, N2, N3, N4) then
Error_Pragma_Arg ("invalid argument for pragma%", Argx);
end if;
end Check_Arg_Is_One_Of;
@@ -1290,12 +1362,7 @@ package body Sem_Prag is
begin
Check_Arg_Is_Identifier (Argx);
- if Chars (Argx) /= N1
- and then Chars (Argx) /= N2
- and then Chars (Argx) /= N3
- and then Chars (Argx) /= N4
- and then Chars (Argx) /= N5
- then
+ if not Nam_In (Chars (Argx), N1, N2, N3, N4, N5) then
Error_Pragma_Arg ("invalid argument for pragma%", Argx);
end if;
end Check_Arg_Is_One_Of;
@@ -1430,8 +1497,8 @@ package body Sem_Prag is
and then not Is_Unchecked_Union (Etype (Subtype_Mark (Sindic)))
then
Error_Msg_N
- ("component subtype subject to per-object constraint " &
- "must be an Unchecked_Union", Comp);
+ ("component subtype subject to per-object constraint "
+ & "must be an Unchecked_Union", Comp);
-- Ada 2012 (AI05-0026): For an unchecked union type declared within
-- the body of a generic unit, or within the body of any of its
@@ -1914,13 +1981,15 @@ package body Sem_Prag is
-- instance can be in a nested scope. The check that protected type
-- is itself a library-level declaration is done elsewhere.
- -- Note: we omit this check in Codepeer mode to properly handle code
- -- prior to AI-0033 (pragmas don't matter to codepeer in any case).
+ -- Note: we omit this check in Relaxed_RM_Semantics mode to properly
+ -- handle code prior to AI-0033. Analysis tools typically are not
+ -- interested in this pragma in any case, so no need to worry too
+ -- much about its placement.
if Inside_A_Generic then
if Ekind (Scope (Current_Scope)) = E_Generic_Package
and then In_Package_Body (Scope (Current_Scope))
- and then not CodePeer_Mode
+ and then not Relaxed_RM_Semantics
then
Error_Pragma ("pragma% cannot be used inside a generic");
end if;
@@ -1946,12 +2015,12 @@ package body Sem_Prag is
begin
if Nkind (Constr) = N_Pragma then
Error_Pragma
- ("pragma % must appear immediately within the statements " &
- "of a loop");
+ ("pragma % must appear immediately within the statements "
+ & "of a loop");
else
Error_Pragma_Arg
- ("block containing pragma % must appear immediately within " &
- "the statements of a loop", Constr);
+ ("block containing pragma % must appear immediately within "
+ & "the statements of a loop", Constr);
end if;
end Placement_Error;
@@ -2095,9 +2164,7 @@ package body Sem_Prag is
procedure Check_No_Link_Name is
begin
- if Present (Arg3)
- and then Chars (Arg3) = Name_Link_Name
- then
+ if Present (Arg3) and then Chars (Arg3) = Name_Link_Name then
Arg4 := Arg3;
end if;
@@ -2185,13 +2252,18 @@ package body Sem_Prag is
("aspect % requires ''Class for null procedure");
-- Pre/postconditions are legal on a subprogram body if it is not
- -- a completion of a declaration.
+ -- a completion of a declaration. They are also legal on a stub
+ -- with no previous declarations (this is checked when processing
+ -- the corresponding aspects).
elsif Nkind (PO) = N_Subprogram_Body
and then Acts_As_Spec (PO)
then
null;
+ elsif Nkind (PO) = N_Subprogram_Body_Stub then
+ null;
+
elsif not Nkind_In (PO, N_Subprogram_Declaration,
N_Expression_Function,
N_Generic_Subprogram_Declaration,
@@ -2248,12 +2320,12 @@ package body Sem_Prag is
-- For a pragma PPC in the extended main source unit, record enabled
-- status in SCO.
- -- This may seem redundant with the call to Check_Enabled occurring
- -- later on when the pragma is rewritten into a pragma Check but
- -- is actually required in the case of a postcondition within a
+ -- This may seem redundant with the call to Check_Kind test that
+ -- occurs later on when the pragma is rewritten into a pragma Check
+ -- but is actually required in the case of a postcondition within a
-- generic.
- if Check_Enabled (Pname) and then not Split_PPC (N) then
+ if Check_Kind (Pname) = Name_Check and then not Split_PPC (N) then
Set_SCO_Pragma_Enabled (Loc);
end if;
@@ -3410,19 +3482,16 @@ package body Sem_Prag is
then
-- Give error if same as our pragma or Export/Convention
- if Pragma_Name (Decl) = Name_Export
- or else
- Pragma_Name (Decl) = Name_Convention
- or else
- Pragma_Name (Decl) = Pragma_Name (N)
+ if Nam_In (Pragma_Name (Decl), Name_Export,
+ Name_Convention,
+ Pragma_Name (N))
then
exit;
-- Case of Import/Interface or the other way round
- elsif Pragma_Name (Decl) = Name_Interface
- or else
- Pragma_Name (Decl) = Name_Import
+ elsif Nam_In (Pragma_Name (Decl), Name_Interface,
+ Name_Import)
then
-- Here we know that we have Import and Interface. It
-- doesn't matter which way round they are. See if
@@ -3450,8 +3519,12 @@ package body Sem_Prag is
end if;
-- Give message if needed if we fall through those tests
+ -- except on Relaxed_RM_Semantics where we let go: either this
+ -- is a case accepted/ignored by other Ada compilers (e.g.
+ -- a mix of Convention and Import), or another error will be
+ -- generated later (e.g. using both Import and Export).
- if Err then
+ if Err and not Relaxed_RM_Semantics then
Error_Pragma_Arg
("at most one Convention/Export/Import pragma is allowed",
Arg2);
@@ -3475,9 +3548,8 @@ package body Sem_Prag is
and then C /= Convention (Overridden_Operation (E))
then
Error_Pragma_Arg
- ("cannot change convention for " &
- "overridden dispatching operation",
- Arg1);
+ ("cannot change convention for overridden dispatching "
+ & "operation", Arg1);
end if;
-- Set the convention
@@ -3648,9 +3720,12 @@ package body Sem_Prag is
end if;
-- Check that we are not applying this to a specless body
+ -- Relax this check if Relaxed_RM_Semantics to accomodate other Ada
+ -- compilers.
if Is_Subprogram (E)
and then Nkind (Parent (Declaration_Node (E))) = N_Subprogram_Body
+ and then not Relaxed_RM_Semantics
then
Error_Pragma
("pragma% requires separate spec and must come before body");
@@ -4192,9 +4267,7 @@ package body Sem_Prag is
elsif Etype (Def_Id) /= Standard_Void_Type
and then
- (Pname = Name_Export_Procedure
- or else
- Pname = Name_Import_Procedure)
+ Nam_In (Pname, Name_Export_Procedure, Name_Import_Procedure)
then
Match := False;
@@ -4786,8 +4859,8 @@ package body Sem_Prag is
then
Error_Msg_Sloc := Sloc (Def_Id);
Error_Msg_NE
- ("cannot import&, renaming already provided for " &
- "declaration #", N, Def_Id);
+ ("cannot import&, renaming already provided for "
+ & "declaration #", N, Def_Id);
end if;
end;
@@ -5256,7 +5329,7 @@ package body Sem_Prag is
elsif not Effective
and then Warn_On_Redundant_Constructs
- and then not (Status = Suppressed or Suppress_All_Inlining)
+ and then not (Status = Suppressed or else Suppress_All_Inlining)
then
if Inlining_Not_Possible (Subp) then
Error_Msg_NE
@@ -5729,6 +5802,26 @@ package body Sem_Prag is
end if;
end;
+ elsif Id = Name_No_Use_Of_Attribute then
+ if Nkind (Expr) /= N_Identifier
+ or else not Is_Attribute_Name (Chars (Expr))
+ then
+ Error_Msg_N ("unknown attribute name?", Expr);
+
+ else
+ Set_Restriction_No_Use_Of_Attribute (Expr, Warn);
+ end if;
+
+ elsif Id = Name_No_Use_Of_Pragma then
+ if Nkind (Expr) /= N_Identifier
+ or else not Is_Pragma_Name (Chars (Expr))
+ then
+ Error_Msg_N ("unknown pragma name?", Expr);
+
+ else
+ Set_Restriction_No_Use_Of_Pragma (Expr, Warn);
+ end if;
+
-- All other cases of restriction identifier present
else
@@ -5996,7 +6089,9 @@ package body Sem_Prag is
Error_Pragma_Arg
("cannot export entity& that was previously imported", Arg);
- elsif Present (Address_Clause (E)) and then not CodePeer_Mode then
+ elsif Present (Address_Clause (E))
+ and then not Relaxed_RM_Semantics
+ then
Error_Pragma_Arg
("cannot export entity& that has an address clause", Arg);
end if;
@@ -6152,6 +6247,12 @@ package body Sem_Prag is
if Is_Exported (E) then
Error_Msg_NE ("entity& was previously exported", N, E);
+ -- Ignore error in CodePeer mode where we treat all imported
+ -- subprograms as unknown.
+
+ elsif CodePeer_Mode then
+ goto OK;
+
-- OK if Import/Interface case
elsif Import_Interface_Present (N) then
@@ -6286,9 +6387,10 @@ package body Sem_Prag is
Class := First (Expressions (Mech_Name));
if Nkind (Prefix (Mech_Name)) /= N_Identifier
- or else not (Chars (Prefix (Mech_Name)) = Name_Descriptor or else
- Chars (Prefix (Mech_Name)) = Name_Short_Descriptor)
- or else Present (Next (Class))
+ or else
+ not Nam_In (Chars (Prefix (Mech_Name)), Name_Descriptor,
+ Name_Short_Descriptor)
+ or else Present (Next (Class))
then
Bad_Mechanism;
else
@@ -6313,8 +6415,9 @@ package body Sem_Prag is
Param := First (Parameter_Associations (Mech_Name));
if Nkind (Name (Mech_Name)) /= N_Identifier
- or else not (Chars (Name (Mech_Name)) = Name_Descriptor or else
- Chars (Name (Mech_Name)) = Name_Short_Descriptor)
+ or else
+ not Nam_In (Chars (Name (Mech_Name)), Name_Descriptor,
+ Name_Short_Descriptor)
or else Present (Next (Param))
or else No (Selector_Name (Param))
or else Chars (Selector_Name (Param)) /= Name_Class
@@ -6658,6 +6761,16 @@ package body Sem_Prag is
Pname := Chars (Identifier (Corresponding_Aspect (N)));
end if;
+ Check_Applicable_Policy (N);
+
+ -- If pragma is disable, rewrite as Null statement and skip analysis
+
+ if Is_Disabled (N) then
+ Rewrite (N, Make_Null_Statement (Loc));
+ Analyze (N);
+ raise Pragma_Exit;
+ end if;
+
-- Preset arguments
Arg_Count := 0;
@@ -6683,6 +6796,8 @@ package body Sem_Prag is
end if;
end if;
+ Check_Restriction_No_Use_Of_Pragma (N);
+
-- An enumeration type defines the pragmas that are supported by the
-- implementation. Get_Pragma_Id (in package Prag) transforms a name
-- into the corresponding enumeration value for the following case.
@@ -6715,20 +6830,21 @@ package body Sem_Prag is
-- pragma Abstract_State (ABSTRACT_STATE_LIST)
- -- ABSTRACT_STATE_LIST ::=
+ -- ABSTRACT_STATE_LIST ::=
-- null
- -- | STATE_NAME_WITH_PROPERTIES {, STATE_NAME_WITH_PROPERTIES}
+ -- | STATE_NAME_WITH_PROPERTIES {, STATE_NAME_WITH_PROPERTIES}
-- STATE_NAME_WITH_PROPERTIES ::=
-- STATE_NAME
- -- | (STATE_NAME with PROPERTY_LIST)
+ -- | (STATE_NAME with PROPERTY_LIST)
- -- PROPERTY_LIST ::= PROPERTY {, PROPERTY}
- -- PROPERTY ::= SIMPLE_PROPERTY
- -- | NAME_VALUE_PROPERTY
- -- SIMPLE_PROPERTY ::= IDENTIFIER
- -- NAME_VALUE_PROPERTY ::= IDENTIFIER => EXPRESSION
- -- STATE_NAME ::= DEFINING_IDENTIFIER
+ -- PROPERTY_LIST ::= PROPERTY {, PROPERTY}
+ -- PROPERTY ::= SIMPLE_PROPERTY | NAME_VALUE_PROPERTY
+
+ -- SIMPLE_PROPERTY ::= IDENTIFIER
+ -- NAME_VALUE_PROPERTY ::= IDENTIFIER => EXPRESSION
+
+ -- STATE_NAME ::= DEFINING_IDENTIFIER
when Pragma_Abstract_State => Abstract_State : declare
Pack_Id : Entity_Id;
@@ -6796,8 +6912,8 @@ package body Sem_Prag is
-- declare additional states.
if Null_Seen then
- Error_Msg_Name_1 := Chars (Pack_Id);
- Error_Msg_N ("package % has null abstract state", State);
+ Error_Msg_NE
+ ("package & has null abstract state", State, Pack_Id);
-- Null states appear as internally generated entities
@@ -6810,9 +6926,9 @@ package body Sem_Prag is
-- non-null states.
if Non_Null_Seen then
- Error_Msg_Name_1 := Chars (Pack_Id);
- Error_Msg_N
- ("package % has non-null abstract state", State);
+ Error_Msg_NE
+ ("package & has non-null abstract state",
+ State, Pack_Id);
end if;
-- Simple state declaration
@@ -6865,8 +6981,8 @@ package body Sem_Prag is
(not Input_Seen and then not Output_Seen)) -- none
then
Error_Msg_N
- ("property Volatile requires exactly one Input or " &
- "Output", State);
+ ("property Volatile requires exactly one Input or "
+ & "Output", State);
end if;
-- Either Input or Output require Volatile
@@ -6979,7 +7095,7 @@ package body Sem_Prag is
return;
end if;
- Pack_Id := Defining_Unit_Name (Specification (Par));
+ Pack_Id := Defining_Entity (Par);
State := Expression (Arg1);
-- Multiple abstract states appear as an aggregate
@@ -7333,41 +7449,175 @@ package body Sem_Prag is
-- Assertion_Policy --
----------------------
- -- pragma Assertion_Policy (Check | Disable | Ignore)
+ -- pragma Assertion_Policy (POLICY_IDENTIFIER);
+
+ -- The following form is Ada 2012 only, but we allow it in all modes
+
+ -- Pragma Assertion_Policy (
+ -- ASSERTION_KIND => POLICY_IDENTIFIER
+ -- {, ASSERTION_KIND => POLICY_IDENTIFIER});
+
+ -- ASSERTION_KIND ::= RM_ASSERTION_KIND | ID_ASSERTION_KIND
+
+ -- RM_ASSERTION_KIND ::= Assert |
+ -- Static_Predicate |
+ -- Dynamic_Predicate |
+ -- Pre |
+ -- Pre'Class |
+ -- Post |
+ -- Post'Class |
+ -- Type_Invariant |
+ -- Type_Invariant'Class
+
+ -- ID_ASSERTION_KIND ::= Assert_And_Cut }
+ -- Assume |
+ -- Contract_Cases |
+ -- Debug |
+ -- Loop_Invariant |
+ -- Loop_Variant |
+ -- Postcondition |
+ -- Precondition |
+ -- Predicate
+ --
+ -- Note: The RM_ASSERTION_KIND list is language-defined, and the
+ -- ID_ASSERTION_KIND list contains implementation-defined additions
+ -- recognized by GNAT. The effect is to control the behavior of
+ -- identically named aspects and pragmas, depending on the specified
+ -- policy identifier:
+
+ -- POLICY_IDENTIFIER ::= Check | Disable | Ignore
+
+ -- Note: Check and Ignore are language-defined. Disable is a GNAT
+ -- implementation defined addition that results in totally ignoring
+ -- the corresponding assertion. If Disable is specified, then the
+ -- argument of the assertion is not even analyzed. This is useful
+ -- when the aspect/pragma argument references entities in a with'ed
+ -- packaqe that is replaced by a dummy package in the final build.
+
+ -- Note: the attribute forms Pre'Class, Post'Class, Invariant'Class,
+ -- and Type_Invariant'Class were recognized by the parser and
+ -- transformed into referencea to the special internal identifiers
+ -- _Pre, _Post, _Invariant, and _Type_Invariant, so no special
+ -- processing is required here.
when Pragma_Assertion_Policy => Assertion_Policy : declare
+ LocP : Source_Ptr;
Policy : Node_Id;
+ Arg : Node_Id;
+ Kind : Name_Id;
+ Prag : Node_Id;
begin
Ada_2005_Pragma;
- Check_Valid_Configuration_Pragma;
- Check_Arg_Count (1);
- Check_No_Identifiers;
- Check_Arg_Is_One_Of (Arg1, Name_Check, Name_Disable, Name_Ignore);
- -- We treat pragma Assertion_Policy as equivalent to:
+ -- This can always appear as a configuration pragma
- -- pragma Check_Policy (Assertion, policy)
+ if Is_Configuration_Pragma then
+ null;
- -- So rewrite the pragma in that manner and link on to the chain
- -- of Check_Policy pragmas, marking the pragma as analyzed.
+ -- It can also appear in a declaration or package spec in Ada
+ -- 2012 mode. We allow this in other modes, but in that case
+ -- we consider that we have an Ada 2012 pragma on our hands.
- Policy := Get_Pragma_Arg (Arg1);
+ else
+ Check_Is_In_Decl_Part_Or_Package_Spec;
+ Ada_2012_Pragma;
+ end if;
- Rewrite (N,
- Make_Pragma (Loc,
- Chars => Name_Check_Policy,
- Pragma_Argument_Associations => New_List (
- Make_Pragma_Argument_Association (Loc,
- Expression => Make_Identifier (Loc, Name_Assertion)),
+ -- One argument case with no identifier (first form above)
- Make_Pragma_Argument_Association (Loc,
- Expression =>
- Make_Identifier (Sloc (Policy), Chars (Policy))))));
+ if Arg_Count = 1
+ and then (Nkind (Arg1) /= N_Pragma_Argument_Association
+ or else Chars (Arg1) = No_Name)
+ then
+ Check_Arg_Is_One_Of
+ (Arg1, Name_Check, Name_Disable, Name_Ignore);
+
+ -- Treat one argument Assertion_Policy as equivalent to:
+
+ -- pragma Check_Policy (Assertion, policy)
- Set_Analyzed (N);
- Set_Next_Pragma (N, Opt.Check_Policy_List);
- Opt.Check_Policy_List := N;
+ -- So rewrite pragma in that manner and link on to the chain
+ -- of Check_Policy pragmas, marking the pragma as analyzed.
+
+ Policy := Get_Pragma_Arg (Arg1);
+
+ Rewrite (N,
+ Make_Pragma (Loc,
+ Chars => Name_Check_Policy,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Name_Assertion)),
+
+ Make_Pragma_Argument_Association (Loc,
+ Expression =>
+ Make_Identifier (Sloc (Policy), Chars (Policy))))));
+
+ Set_Analyzed (N);
+ Set_Next_Pragma (N, Opt.Check_Policy_List);
+ Opt.Check_Policy_List := N;
+
+ -- Here if we have two or more arguments
+
+ else
+ Check_At_Least_N_Arguments (1);
+ Ada_2012_Pragma;
+
+ -- Loop through arguments
+
+ Arg := Arg1;
+ while Present (Arg) loop
+ LocP := Sloc (Arg);
+
+ -- Kind must be specified
+
+ if Nkind (Arg) /= N_Pragma_Argument_Association
+ or else Chars (Arg) = No_Name
+ then
+ Error_Pragma_Arg
+ ("missing assertion kind for pragma%", Arg);
+ end if;
+
+ -- Check Kind and Policy have allowed forms
+
+ Kind := Chars (Arg);
+
+ if not Is_Valid_Assertion_Kind (Kind) then
+ Error_Pragma_Arg
+ ("invalid assertion kind for pragma%", Arg);
+ end if;
+
+ Check_Arg_Is_One_Of
+ (Arg, Name_Check, Name_Disable, Name_Ignore);
+
+ -- We rewrite the Assertion_Policy pragma as a series of
+ -- Check_Policy pragmas:
+
+ -- Check_Policy (Kind, Policy);
+
+ Prag :=
+ Make_Pragma (LocP,
+ Chars => Name_Check_Policy,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (LocP,
+ Expression => Make_Identifier (LocP, Kind)),
+ Make_Pragma_Argument_Association (LocP,
+ Expression => Get_Pragma_Arg (Arg))));
+
+ Set_Analyzed (Prag);
+ Set_Next_Pragma (Prag, Opt.Check_Policy_List);
+ Opt.Check_Policy_List := Prag;
+ Insert_Action (N, Prag);
+
+ Arg := Next (Arg);
+ end loop;
+
+ -- Rewrite the Assertion_Policy pragma as null since we have
+ -- now inserted all the equivalent Check pragmas.
+
+ Rewrite (N, Make_Null_Statement (Loc));
+ Analyze (N);
+ end if;
end Assertion_Policy;
------------
@@ -7593,8 +7843,7 @@ package body Sem_Prag is
-- unit (RM E.4.1(4)).
Error_Pragma
- ("pragma% not in Remote_Call_Interface or " &
- "Remote_Types unit");
+ ("pragma% not in Remote_Call_Interface or Remote_Types unit");
end if;
if Ekind (Nm) = E_Procedure
@@ -7818,14 +8067,21 @@ package body Sem_Prag is
-- Check --
-----------
- -- pragma Check ([Name =>] IDENTIFIER,
+ -- pragma Check ([Name =>] CHECK_KIND,
-- [Check =>] Boolean_EXPRESSION
-- [,[Message =>] String_EXPRESSION]);
+ -- CHECK_KIND ::= IDENTIFIER |
+ -- Pre'Class |
+ -- Post'Class |
+ -- Invariant'Class |
+ -- Type_Invariant'Class
+
when Pragma_Check => Check : declare
Expr : Node_Id;
Eloc : Source_Ptr;
Cname : Name_Id;
+ Str : Node_Id;
Check_On : Boolean;
-- Set True if category of assertions referenced by Name enabled
@@ -7839,21 +8095,41 @@ package body Sem_Prag is
if Arg_Count = 3 then
Check_Optional_Identifier (Arg3, Name_Message);
- Analyze_And_Resolve (Get_Pragma_Arg (Arg3), Standard_String);
+ Str := Get_Pragma_Arg (Arg3);
end if;
+ Rewrite_Assertion_Kind (Get_Pragma_Arg (Arg1));
Check_Arg_Is_Identifier (Arg1);
+ Cname := Chars (Get_Pragma_Arg (Arg1));
- -- Completely ignore if disabled
+ -- Set Check_On to indicate check status
- if Check_Disabled (Chars (Get_Pragma_Arg (Arg1))) then
- Rewrite (N, Make_Null_Statement (Loc));
- Analyze (N);
- return;
- end if;
+ case Check_Kind (Cname) is
+ when Name_Ignore =>
+ Check_On := False;
- Cname := Chars (Get_Pragma_Arg (Arg1));
- Check_On := Check_Enabled (Cname);
+ when Name_Check =>
+ Check_On := True;
+
+ -- For disable, rewrite pragma as null statement and skip
+ -- rest of the analysis of the pragma.
+
+ when Name_Disable =>
+ Rewrite (N, Make_Null_Statement (Loc));
+ Analyze (N);
+ raise Pragma_Exit;
+
+ -- No other possibilities
+
+ when others =>
+ raise Program_Error;
+ end case;
+
+ -- If check kind was not Disable, then continue pragma analysis
+
+ Expr := Get_Pragma_Arg (Arg2);
+
+ -- Deal with SCO generation
case Cname is
when Name_Predicate |
@@ -7875,28 +8151,51 @@ package body Sem_Prag is
end if;
end case;
- -- If expansion is active and the check is not enabled then we
- -- rewrite the Check as:
+ -- Deal with analyzing the string argument.
+
+ if Arg_Count = 3 then
+
+ -- If checks are not on we don't want any expansion (since
+ -- such expansion would not get properly deleted) but
+ -- we do want to analyze (to get proper references).
+ -- The Preanalyze_And_Resolve routine does just what we want
+
+ if not Check_On then
+ Preanalyze_And_Resolve (Str, Standard_String);
+
+ -- Otherwise we need a proper analysis and expansion
+
+ else
+ Analyze_And_Resolve (Str, Standard_String);
+ end if;
+ end if;
+
+ -- Now you might think we could just do the same with the Boolean
+ -- expression if checks are off (and expansion is on) and then
+ -- rewrite the check as a null statement. This would work but we
+ -- would lose the useful warnings about an assertion being bound
+ -- to fail even if assertions are turned off.
+
+ -- So instead we wrap the boolean expression in an if statement
+ -- that looks like:
-- if False and then condition then
-- null;
-- end if;
- -- The reason we do this rewriting during semantic analysis rather
- -- than as part of normal expansion is that we cannot analyze and
- -- expand the code for the boolean expression directly, or it may
- -- cause insertion of actions that would escape the attempt to
- -- suppress the check code.
+ -- The reason we do this rewriting during semantic analysis
+ -- rather than as part of normal expansion is that we cannot
+ -- analyze and expand the code for the boolean expression
+ -- directly, or it may cause insertion of actions that would
+ -- escape the attempt to suppress the check code.
-- Note that the Sloc for the if statement corresponds to the
- -- argument condition, not the pragma itself. The reason for this
- -- is that we may generate a warning if the condition is False at
- -- compile time, and we do not want to delete this warning when we
- -- delete the if statement.
+ -- argument condition, not the pragma itself. The reason for
+ -- this is that we may generate a warning if the condition is
+ -- False at compile time, and we do not want to delete this
+ -- warning when we delete the if statement.
- Expr := Get_Pragma_Arg (Arg2);
-
- if Expander_Active and then not Check_On then
+ if Expander_Active and not Check_On then
Eloc := Sloc (Expr);
Rewrite (N,
@@ -7908,9 +8207,12 @@ package body Sem_Prag is
Then_Statements => New_List (
Make_Null_Statement (Eloc))));
+ In_Assertion_Expr := In_Assertion_Expr + 1;
Analyze (N);
+ In_Assertion_Expr := In_Assertion_Expr - 1;
- -- Check is active
+ -- Check is active or expansion not active. In these cases we can
+ -- just go ahead and analyze the boolean with no worries.
else
In_Assertion_Expr := In_Assertion_Expr + 1;
@@ -7961,22 +8263,36 @@ package body Sem_Prag is
-- Check_Policy --
------------------
- -- pragma Check_Policy (
- -- [Name =>] IDENTIFIER,
- -- [Policy =>] POLICY_IDENTIFIER);
+ -- This is the old style syntax, which is still allowed in all modes:
+
+ -- pragma Check_Policy ([Name =>] CHECK_KIND
+ -- [Policy =>] POLICY_IDENTIFIER);
+
+ -- POLICY_IDENTIFIER ::= On | Off | Check | Disable | Ignore
- -- POLICY_IDENTIFIER ::= ON | OFF | CHECK | DISABLE | IGNORE
+ -- CHECK_KIND ::= IDENTIFIER |
+ -- Pre'Class |
+ -- Post'Class |
+ -- Type_Invariant'Class |
+ -- Invariant'Class
- -- Note: this is a configuration pragma, but it is allowed to appear
- -- anywhere else.
+ -- This is the new style syntax, compatible with Assertion_Policy
+ -- and also allowed in all modes.
- when Pragma_Check_Policy =>
+ -- Pragma Check_Policy (
+ -- CHECK_KIND => POLICY_IDENTIFIER
+ -- {, CHECK_KIND => POLICY_IDENTIFIER});
+
+ -- Note: the identifiers Name and Policy are not allowed as
+ -- Check_Kind values. This avoids ambiguities between the old and
+ -- new form syntax.
+
+ when Pragma_Check_Policy => Check_Policy : declare
+ Kind : Node_Id;
+
+ begin
GNAT_Pragma;
- Check_Arg_Count (2);
- Check_Optional_Identifier (Arg1, Name_Name);
- Check_Optional_Identifier (Arg2, Name_Policy);
- Check_Arg_Is_One_Of
- (Arg2, Name_On, Name_Off, Name_Check, Name_Disable, Name_Ignore);
+ Check_At_Least_N_Arguments (1);
-- A Check_Policy pragma can appear either as a configuration
-- pragma, or in a declarative part or a package spec (see RM
@@ -7987,8 +8303,91 @@ package body Sem_Prag is
Check_Is_In_Decl_Part_Or_Package_Spec;
end if;
- Set_Next_Pragma (N, Opt.Check_Policy_List);
- Opt.Check_Policy_List := N;
+ -- Figure out if we have the old or new syntax. We have the
+ -- old syntax if the first argument has no identifier, or the
+ -- identifier is Name.
+
+ if Nkind (Arg1) /= N_Pragma_Argument_Association
+ or else Nam_In (Chars (Arg1), No_Name, Name_Name)
+ then
+ -- Old syntax
+
+ Check_Arg_Count (2);
+ Check_Optional_Identifier (Arg1, Name_Name);
+ Kind := Get_Pragma_Arg (Arg1);
+ Rewrite_Assertion_Kind (Kind);
+ Check_Arg_Is_Identifier (Arg1);
+
+ -- Check forbidden check kind
+
+ if Nam_In (Chars (Kind), Name_Name, Name_Policy) then
+ Error_Msg_Name_2 := Chars (Kind);
+ Error_Pragma_Arg
+ ("pragma% does not allow% as check name", Arg1);
+ end if;
+
+ -- Check policy
+
+ Check_Optional_Identifier (Arg2, Name_Policy);
+ Check_Arg_Is_One_Of
+ (Arg2,
+ Name_On, Name_Off, Name_Check, Name_Disable, Name_Ignore);
+
+ -- And chain pragma on the Check_Policy_List for search
+
+ Set_Next_Pragma (N, Opt.Check_Policy_List);
+ Opt.Check_Policy_List := N;
+
+ -- For the new syntax, what we do is to convert each argument to
+ -- an old syntax equivalent. We do that because we want to chain
+ -- old style Check_Pragmas for the search (we don't wnat to have
+ -- to deal with multiple arguments in the search)
+
+ else
+ declare
+ Arg : Node_Id;
+ Argx : Node_Id;
+ LocP : Source_Ptr;
+
+ begin
+ Arg := Arg1;
+ while Present (Arg) loop
+ LocP := Sloc (Arg);
+ Argx := Get_Pragma_Arg (Arg);
+
+ -- Kind must be specified
+
+ if Nkind (Arg) /= N_Pragma_Argument_Association
+ or else Chars (Arg) = No_Name
+ then
+ Error_Pragma_Arg
+ ("missing assertion kind for pragma%", Arg);
+ end if;
+
+ -- Construct equivalent old form syntax Check_Policy
+ -- pragma and insert it to get remaining checks.
+
+ Insert_Action (N,
+ Make_Pragma (LocP,
+ Chars => Name_Check_Policy,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (LocP,
+ Expression =>
+ Make_Identifier (LocP, Chars (Arg))),
+ Make_Pragma_Argument_Association (Sloc (Argx),
+ Expression => Argx))));
+
+ Arg := Next (Arg);
+ end loop;
+
+ -- Rewrite original Check_Policy pragma to null, since we
+ -- have converted it into a series of old syntax pragmas.
+
+ Rewrite (N, Make_Null_Statement (Loc));
+ Analyze (N);
+ end;
+ end if;
+ end Check_Policy;
---------------------
-- CIL_Constructor --
@@ -8204,8 +8603,8 @@ package body Sem_Prag is
and then not Is_Array_Type (Typ)
then
Error_Pragma_Arg
- ("Name parameter of pragma% must identify record or " &
- "array type", Name);
+ ("Name parameter of pragma% must identify record or "
+ & "array type", Name);
end if;
-- An explicit Component_Alignment pragma overrides an
@@ -8305,9 +8704,9 @@ package body Sem_Prag is
S14_Pragma;
Check_Arg_Count (1);
- -- Completely ignore if disabled
+ -- Completely ignore if not enabled
- if Check_Disabled (Pname) then
+ if Is_Ignored (N) then
Rewrite (N, Make_Null_Statement (Loc));
Analyze (N);
return;
@@ -8491,10 +8890,9 @@ package body Sem_Prag is
GNAT_Pragma;
if Warn_On_Obsolescent_Feature then
- -- Following message is obsolete ???
Error_Msg_N
- ("'G'N'A'T pragma cpp'_class is now obsolete and has no " &
- "effect; replace it by pragma import?j?", N);
+ ("'G'N'A'T pragma cpp'_class is now obsolete and has no "
+ & "effect; replace it by pragma import?j?", N);
end if;
Check_Arg_Count (1);
@@ -8557,8 +8955,8 @@ package body Sem_Prag is
then
if Scope (Def_Id) /= Scope (Etype (Def_Id)) then
Error_Msg_N
- ("'C'P'P constructor must be defined in the scope of " &
- "its returned type", Arg1);
+ ("'C'P'P constructor must be defined in the scope of "
+ & "its returned type", Arg1);
end if;
if Arg_Count >= 2 then
@@ -8618,8 +9016,8 @@ 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 effect?j?", N);
+ ("'G'N'A'T pragma cpp'_virtual is now obsolete and has no "
+ & "effect?j?", N);
end if;
end CPP_Virtual;
@@ -8633,8 +9031,8 @@ 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 effect?j?", N);
+ ("'G'N'A'T pragma cpp'_vtable is now obsolete and has no "
+ & "effect?j?", N);
end if;
end CPP_Vtable;
@@ -8741,20 +9139,16 @@ package body Sem_Prag is
begin
GNAT_Pragma;
- -- Skip analysis if disabled
-
- if Debug_Pragmas_Disabled then
- Rewrite (N, Make_Null_Statement (Loc));
- Analyze (N);
- return;
- end if;
+ -- The condition for executing the call is that the expander
+ -- is active and that we are not ignoring this debug pragma.
Cond :=
New_Occurrence_Of
- (Boolean_Literals (Debug_Pragmas_Enabled and Expander_Active),
+ (Boolean_Literals
+ (Expander_Active and then not Is_Ignored (N)),
Loc);
- if Debug_Pragmas_Enabled then
+ if not Is_Ignored (N) then
Set_SCO_Pragma_Enabled (Loc);
end if;
@@ -8833,16 +9227,1085 @@ package body Sem_Prag is
-- Debug_Policy --
------------------
- -- pragma Debug_Policy (Check | Ignore)
+ -- pragma Debug_Policy (On | Off | Check | Disable | Ignore)
when Pragma_Debug_Policy =>
GNAT_Pragma;
Check_Arg_Count (1);
- Check_Arg_Is_One_Of (Arg1, Name_Check, Name_Disable, Name_Ignore);
- Debug_Pragmas_Enabled :=
- Chars (Get_Pragma_Arg (Arg1)) = Name_Check;
- Debug_Pragmas_Disabled :=
- Chars (Get_Pragma_Arg (Arg1)) = Name_Disable;
+ Check_No_Identifiers;
+ Check_Arg_Is_Identifier (Arg1);
+
+ -- Exactly equivalent to pragma Check_Policy (Debug, arg), so
+ -- rewrite it that way, and let the rest of the checking come
+ -- from analyzing the rewritten pragma.
+
+ Rewrite (N,
+ Make_Pragma (Loc,
+ Chars => Name_Check_Policy,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Name_Debug)),
+
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Get_Pragma_Arg (Arg1)))));
+
+ Analyze (N);
+
+ -------------
+ -- Depends --
+ -------------
+
+ -- pragma Depends (DEPENDENCY_RELATION);
+
+ -- DEPENDENCY_RELATION ::=
+ -- null
+ -- | DEPENDENCY_CLAUSE {, DEPENDENCY_CLAUSE}
+
+ -- DEPENDENCY_CLAUSE ::=
+ -- OUTPUT_LIST =>[+] INPUT_LIST
+ -- | NULL_DEPENDENCY_CLAUSE
+
+ -- NULL_DEPENDENCY_CLAUSE ::= null => INPUT_LIST
+
+ -- OUTPUT_LIST ::= OUTPUT | (OUTPUT {, OUTPUT})
+
+ -- INPUT_LIST ::= null | INPUT | (INPUT {, INPUT})
+
+ -- OUTPUT ::= NAME | FUNCTION_RESULT
+ -- INPUT ::= NAME
+
+ -- where FUNCTION_RESULT is a function Result attribute_reference
+
+ when Pragma_Depends => Depends : declare
+ All_Inputs_Seen : Elist_Id := No_Elist;
+ -- A list containing the entities of all the inputs processed so
+ -- far. This Elist is populated with unique entities because the
+ -- same input may appear in multiple input lists.
+
+ Global_Seen : Boolean := False;
+ -- A flag set when pragma Global has been processed
+
+ Outputs_Seen : Elist_Id := No_Elist;
+ -- A list containing the entities of all the outputs processed so
+ -- far. The elements of this list may come from different output
+ -- lists.
+
+ Null_Output_Seen : Boolean := False;
+ -- A flag used to track the legality of a null output
+
+ Result_Seen : Boolean := False;
+ -- A flag set when Subp_Id'Result is processed
+
+ Subp_Id : Entity_Id;
+ -- The entity of the subprogram subject to pragma Depends
+
+ Subp_Inputs : Elist_Id := No_Elist;
+ Subp_Outputs : Elist_Id := No_Elist;
+ -- Two lists containing the full set of inputs and output of the
+ -- related subprograms. Note that these lists contain both nodes
+ -- and entities.
+
+ procedure Analyze_Dependency_Clause
+ (Clause : Node_Id;
+ Is_Last : Boolean);
+ -- Verify the legality of a single dependency clause. Flag Is_Last
+ -- denotes whether Clause is the last clause in the relation.
+
+ function Appears_In
+ (List : Elist_Id;
+ Item_Id : Entity_Id) return Boolean;
+ -- Determine whether a particular item appears in a mixed list of
+ -- nodes and entities.
+
+ procedure Check_Function_Return;
+ -- Verify that Funtion'Result appears as one of the outputs
+
+ procedure Check_Mode
+ (Item : Node_Id;
+ Item_Id : Entity_Id;
+ Is_Input : Boolean);
+ -- Ensure that an item has a proper "in", "in out" or "out" mode
+ -- depending on its function. If this is not the case, emit an
+ -- error.
+
+ procedure Check_Usage
+ (Subp_List : Elist_Id;
+ Item_List : Elist_Id;
+ Is_Input : Boolean);
+ -- Verify that all items from list Subp_List appear in Item_List.
+ -- Emit an error if this is not the case.
+
+ procedure Collect_Subprogram_Inputs_Outputs;
+ -- Gather all inputs and outputs of the subprogram. These are the
+ -- formal parameters and entities classified in pragma Global.
+
+ procedure Normalize_Clause (Clause : Node_Id);
+ -- Remove a self-dependency "+" from the input list of a clause.
+ -- Depending on the contents of the relation, either split the
+ -- the clause into multiple smaller clauses or perform the
+ -- normalization in place.
+
+ -------------------------------
+ -- Analyze_Dependency_Clause --
+ -------------------------------
+
+ procedure Analyze_Dependency_Clause
+ (Clause : Node_Id;
+ Is_Last : Boolean)
+ is
+ procedure Analyze_Input_List (Inputs : Node_Id);
+ -- Verify the legality of a single input list
+
+ procedure Analyze_Input_Output
+ (Item : Node_Id;
+ Is_Input : Boolean;
+ Top_Level : Boolean;
+ Seen : in out Elist_Id;
+ Null_Seen : in out Boolean);
+ -- Verify the legality of a single input or output item. Flag
+ -- Is_Input should be set whenever Item is an input, False when
+ -- it denotes an output. Flag Top_Level should be set whenever
+ -- Item appears immediately within an input or output list.
+ -- Seen is a collection of all abstract states, variables and
+ -- formals processed so far. Flag Null_Seen denotes whether a
+ -- null input or output has been encountered.
+
+ ------------------------
+ -- Analyze_Input_List --
+ ------------------------
+
+ procedure Analyze_Input_List (Inputs : Node_Id) is
+ Inputs_Seen : Elist_Id := No_Elist;
+ -- A list containing the entities of all inputs that appear
+ -- in the current input list.
+
+ Null_Input_Seen : Boolean := False;
+ -- A flag used to track the legality of a null input
+
+ Input : Node_Id;
+
+ begin
+ -- Multiple inputs appear as an aggregate
+
+ if Nkind (Inputs) = N_Aggregate then
+ if Present (Component_Associations (Inputs)) then
+ Error_Msg_N
+ ("nested dependency relations not allowed", Inputs);
+
+ elsif Present (Expressions (Inputs)) then
+ Input := First (Expressions (Inputs));
+ while Present (Input) loop
+ Analyze_Input_Output
+ (Item => Input,
+ Is_Input => True,
+ Top_Level => False,
+ Seen => Inputs_Seen,
+ Null_Seen => Null_Input_Seen);
+
+ Next (Input);
+ end loop;
+
+ else
+ Error_Msg_N
+ ("malformed input dependency list", Inputs);
+ end if;
+
+ -- Process a solitary input
+
+ else
+ Analyze_Input_Output
+ (Item => Inputs,
+ Is_Input => True,
+ Top_Level => False,
+ Seen => Inputs_Seen,
+ Null_Seen => Null_Input_Seen);
+ end if;
+
+ -- Detect an illegal dependency clause of the form
+
+ -- (null =>[+] null)
+
+ if Null_Output_Seen and then Null_Input_Seen then
+ Error_Msg_N
+ ("null dependency clause cannot have a null input list",
+ Inputs);
+ end if;
+ end Analyze_Input_List;
+
+ --------------------------
+ -- Analyze_Input_Output --
+ --------------------------
+
+ procedure Analyze_Input_Output
+ (Item : Node_Id;
+ Is_Input : Boolean;
+ Top_Level : Boolean;
+ Seen : in out Elist_Id;
+ Null_Seen : in out Boolean)
+ is
+ Is_Output : constant Boolean := not Is_Input;
+ Grouped : Node_Id;
+ Item_Id : Entity_Id;
+
+ begin
+ -- Multiple input or output items appear as an aggregate
+
+ if Nkind (Item) = N_Aggregate then
+ if not Top_Level then
+ Error_Msg_N
+ ("nested grouping of items not allowed", Item);
+
+ elsif Present (Component_Associations (Item)) then
+ Error_Msg_N
+ ("nested dependency relations not allowed", Item);
+
+ -- Recursively analyze the grouped items
+
+ elsif Present (Expressions (Item)) then
+ Grouped := First (Expressions (Item));
+ while Present (Grouped) loop
+ Analyze_Input_Output
+ (Item => Grouped,
+ Is_Input => Is_Input,
+ Top_Level => False,
+ Seen => Seen,
+ Null_Seen => Null_Seen);
+
+ Next (Grouped);
+ end loop;
+
+ else
+ Error_Msg_N ("malformed dependency list", Item);
+ end if;
+
+ -- Process Function'Result in the context of a dependency
+ -- clause.
+
+ elsif Nkind (Item) = N_Attribute_Reference
+ and then Attribute_Name (Item) = Name_Result
+ then
+ -- It is sufficent to analyze the prefix of 'Result in
+ -- order to establish legality of the attribute.
+
+ Analyze (Prefix (Item));
+
+ -- The prefix of 'Result must denote the function for
+ -- which aspect/pragma Depends applies.
+
+ if not Is_Entity_Name (Prefix (Item))
+ or else Ekind (Subp_Id) /= E_Function
+ or else Entity (Prefix (Item)) /= Subp_Id
+ then
+ Error_Msg_Name_1 := Name_Result;
+ Error_Msg_N
+ ("prefix of attribute % must denote the enclosing "
+ & "function", Item);
+
+ -- Function'Result is allowed to appear on the output
+ -- side of a dependency clause.
+
+ elsif Is_Input then
+ Error_Msg_N
+ ("function result cannot act as input", Item);
+
+ else
+ Result_Seen := True;
+ end if;
+
+ -- Detect multiple uses of null in a single dependency list
+ -- or throughout the whole relation. Verify the placement of
+ -- a null output list relative to the other clauses.
+
+ elsif Nkind (Item) = N_Null then
+ if Null_Seen then
+ Error_Msg_N
+ ("multiple null dependency relations not allowed",
+ Item);
+ else
+ Null_Seen := True;
+
+ if Is_Output and then not Is_Last then
+ Error_Msg_N
+ ("null output list must be the last clause in "
+ & "a dependency relation", Item);
+ end if;
+ end if;
+
+ -- Default case
+
+ else
+ Analyze (Item);
+
+ -- Find the entity of the item. If this is a renaming,
+ -- climb the renaming chain to reach the root object.
+ -- Renamings of non-entire objects do not yield an
+ -- entity (Empty).
+
+ Item_Id := Entity_Of (Item);
+
+ if Present (Item_Id) then
+ if Ekind_In (Item_Id, E_Abstract_State,
+ E_In_Parameter,
+ E_In_Out_Parameter,
+ E_Out_Parameter,
+ E_Variable)
+ then
+ -- Ensure that the item is of the correct mode
+ -- depending on its function.
+
+ Check_Mode (Item, Item_Id, Is_Input);
+
+ -- Detect multiple uses of the same state, variable
+ -- or formal parameter. If this is not the case,
+ -- add the item to the list of processed relations.
+
+ if Contains (Seen, Item_Id) then
+ Error_Msg_N ("duplicate use of item", Item);
+ else
+ Add_Item (Item_Id, Seen);
+ end if;
+
+ -- Detect an illegal use of an input related to a
+ -- null output. Such input items cannot appear in
+ -- other input lists.
+
+ if Null_Output_Seen
+ and then Contains (All_Inputs_Seen, Item_Id)
+ then
+ Error_Msg_N
+ ("input of a null output list appears in "
+ & "multiple input lists", Item);
+ else
+ Add_Item (Item_Id, All_Inputs_Seen);
+ end if;
+
+ -- When the item renames an entire object, replace
+ -- the item with a reference to the object.
+
+ if Present (Renamed_Object (Entity (Item))) then
+ Rewrite (Item,
+ New_Reference_To (Item_Id, Sloc (Item)));
+ Analyze (Item);
+ end if;
+
+ -- All other input/output items are illegal
+
+ else
+ Error_Msg_N
+ ("item must denote variable, state or formal "
+ & "parameter", Item);
+ end if;
+
+ -- All other input/output items are illegal
+
+ else
+ Error_Msg_N
+ ("item must denote variable, state or formal "
+ & "parameter", Item);
+ end if;
+ end if;
+ end Analyze_Input_Output;
+
+ -- Local variables
+
+ Inputs : Node_Id;
+ Output : Node_Id;
+
+ -- Start of processing for Analyze_Dependency_Clause
+
+ begin
+ -- Process the output_list of a dependency_clause
+
+ Output := First (Choices (Clause));
+ while Present (Output) loop
+ Analyze_Input_Output
+ (Item => Output,
+ Is_Input => False,
+ Top_Level => True,
+ Seen => Outputs_Seen,
+ Null_Seen => Null_Output_Seen);
+
+ Next (Output);
+ end loop;
+
+ -- Process the input_list of a dependency_clause
+
+ Inputs := Expression (Clause);
+
+ -- An input list with a self-dependency appears as operator "+"
+ -- where the actuals inputs are the right operand.
+
+ if Nkind (Inputs) = N_Op_Plus then
+ Inputs := Right_Opnd (Inputs);
+ end if;
+
+ Analyze_Input_List (Inputs);
+ end Analyze_Dependency_Clause;
+
+ ----------------
+ -- Appears_In --
+ ----------------
+
+ function Appears_In
+ (List : Elist_Id;
+ Item_Id : Entity_Id) return Boolean
+ is
+ Elmt : Elmt_Id;
+ Id : Entity_Id;
+
+ begin
+ if Present (List) then
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ if Nkind (Node (Elmt)) = N_Defining_Identifier then
+ Id := Node (Elmt);
+ else
+ Id := Entity (Node (Elmt));
+ end if;
+
+ if Id = Item_Id then
+ return True;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+
+ return False;
+ end Appears_In;
+
+ ----------------------------
+ -- Check_Function_Return --
+ ----------------------------
+
+ procedure Check_Function_Return is
+ begin
+ if Ekind (Subp_Id) = E_Function and then not Result_Seen then
+ Error_Msg_NE
+ ("result of & must appear in exactly one output list",
+ N, Subp_Id);
+ end if;
+ end Check_Function_Return;
+
+ ----------------
+ -- Check_Mode --
+ ----------------
+
+ procedure Check_Mode
+ (Item : Node_Id;
+ Item_Id : Entity_Id;
+ Is_Input : Boolean)
+ is
+ begin
+ if Is_Input then
+ if Ekind (Item_Id) = E_Out_Parameter
+ or else (Global_Seen
+ and then not Appears_In (Subp_Inputs, Item_Id))
+ then
+ Error_Msg_NE
+ ("item & must have mode in or in out", Item, Item_Id);
+ end if;
+
+ -- Output
+
+ else
+ if Ekind (Item_Id) = E_In_Parameter
+ or else
+ (Global_Seen
+ and then not Appears_In (Subp_Outputs, Item_Id))
+ then
+ Error_Msg_NE
+ ("item & must have mode out or in out", Item, Item_Id);
+ end if;
+ end if;
+ end Check_Mode;
+
+ -----------------
+ -- Check_Usage --
+ -----------------
+
+ procedure Check_Usage
+ (Subp_List : Elist_Id;
+ Item_List : Elist_Id;
+ Is_Input : Boolean)
+ is
+ procedure Usage_Error (Item : Node_Id; Item_Id : Entity_Id);
+ -- Emit an error concerning the erroneous usage of an item
+
+ -----------------
+ -- Usage_Error --
+ -----------------
+
+ procedure Usage_Error (Item : Node_Id; Item_Id : Entity_Id) is
+ begin
+ if Is_Input then
+ Error_Msg_NE
+ ("item & must appear in at least one input list of "
+ & "aspect Depends", Item, Item_Id);
+ else
+ Error_Msg_NE
+ ("item & must appear in exactly one output list of "
+ & "aspect Depends", Item, Item_Id);
+ end if;
+ end Usage_Error;
+
+ -- Local variables
+
+ Elmt : Elmt_Id;
+ Item : Node_Id;
+ Item_Id : Entity_Id;
+
+ -- Start of processing for Check_Usage
+
+ begin
+ if No (Subp_List) then
+ return;
+ end if;
+
+ -- Each input or output of the subprogram must appear in a
+ -- dependency relation.
+
+ Elmt := First_Elmt (Subp_List);
+ while Present (Elmt) loop
+ Item := Node (Elmt);
+
+ if Nkind (Item) = N_Defining_Identifier then
+ Item_Id := Item;
+ else
+ Item_Id := Entity (Item);
+ end if;
+
+ -- The item does not appear in a dependency
+
+ if not Contains (Item_List, Item_Id) then
+ if Is_Formal (Item_Id) then
+ Usage_Error (Item, Item_Id);
+
+ -- States and global variables are not used properly only
+ -- when the subprogram is subject to pragma Global.
+
+ elsif Global_Seen then
+ Usage_Error (Item, Item_Id);
+ end if;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end Check_Usage;
+
+ ---------------------------------------
+ -- Collect_Subprogram_Inputs_Outputs --
+ ---------------------------------------
+
+ procedure Collect_Subprogram_Inputs_Outputs is
+ procedure Collect_Global_List
+ (List : Node_Id;
+ Mode : Name_Id := Name_Input);
+ -- Collect all relevant items from a global list
+
+ -------------------------
+ -- Collect_Global_List --
+ -------------------------
+
+ procedure Collect_Global_List
+ (List : Node_Id;
+ Mode : Name_Id := Name_Input)
+ is
+ procedure Collect_Global_Item
+ (Item : Node_Id;
+ Mode : Name_Id);
+ -- Add an item to the proper subprogram input or output
+ -- collection.
+
+ -------------------------
+ -- Collect_Global_Item --
+ -------------------------
+
+ procedure Collect_Global_Item
+ (Item : Node_Id;
+ Mode : Name_Id)
+ is
+ begin
+ if Nam_In (Mode, Name_In_Out, Name_Input) then
+ Add_Item (Item, Subp_Inputs);
+ end if;
+
+ if Nam_In (Mode, Name_In_Out, Name_Output) then
+ Add_Item (Item, Subp_Outputs);
+ end if;
+ end Collect_Global_Item;
+
+ -- Local variables
+
+ Assoc : Node_Id;
+ Item : Node_Id;
+
+ -- Start of processing for Collect_Global_List
+
+ begin
+ -- Single global item declaration
+
+ if Nkind_In (List, N_Identifier, N_Selected_Component) then
+ Collect_Global_Item (List, Mode);
+
+ -- Simple global list or moded global list declaration
+
+ else
+ if Present (Expressions (List)) then
+ Item := First (Expressions (List));
+ while Present (Item) loop
+ Collect_Global_Item (Item, Mode);
+
+ Next (Item);
+ end loop;
+
+ else
+ Assoc := First (Component_Associations (List));
+ while Present (Assoc) loop
+ Collect_Global_List
+ (List => Expression (Assoc),
+ Mode => Chars (First (Choices (Assoc))));
+
+ Next (Assoc);
+ end loop;
+ end if;
+ end if;
+ end Collect_Global_List;
+
+ -- Local variables
+
+ Formal : Entity_Id;
+ Global : Node_Id;
+ List : Node_Id;
+
+ -- Start of processing for Collect_Subprogram_Inputs_Outputs
+
+ begin
+ -- Process all formal parameters
+
+ Formal := First_Formal (Subp_Id);
+ while Present (Formal) loop
+ if Ekind_In (Formal, E_In_Out_Parameter,
+ E_In_Parameter)
+ then
+ Add_Item (Formal, Subp_Inputs);
+ end if;
+
+ if Ekind_In (Formal, E_In_Out_Parameter,
+ E_Out_Parameter)
+ then
+ Add_Item (Formal, Subp_Outputs);
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+
+ -- If the subprogram is subject to pragma Global, traverse all
+ -- global lists and gather the relevant items.
+
+ Global := Find_Aspect (Subp_Id, Aspect_Global);
+ if Present (Global) then
+ Global_Seen := True;
+
+ -- Retrieve the pragma as it contains the analyzed lists
+
+ Global := Aspect_Rep_Item (Global);
+
+ -- The pragma may not have been analyzed because of the
+ -- arbitrary declaration order of aspects. Make sure that
+ -- it is analyzed for the purposes of item extraction.
+
+ if not Analyzed (Global) then
+ Analyze (Global);
+ end if;
+
+ List :=
+ Expression (First (Pragma_Argument_Associations (Global)));
+
+ -- Nothing to be done for a null global list
+
+ if Nkind (List) /= N_Null then
+ Collect_Global_List (List);
+ end if;
+ end if;
+ end Collect_Subprogram_Inputs_Outputs;
+
+ ----------------------
+ -- Normalize_Clause --
+ ----------------------
+
+ procedure Normalize_Clause (Clause : Node_Id) is
+ procedure Create_Or_Modify_Clause
+ (Output : Node_Id;
+ Outputs : Node_Id;
+ Inputs : Node_Id;
+ After : Node_Id;
+ In_Place : Boolean;
+ Multiple : Boolean);
+ -- Create a brand new clause to represent the self-reference
+ -- or modify the input and/or output lists of an existing
+ -- clause. Output denotes a self-referencial output. Outputs
+ -- is the output list of a clause. Inputs is the input list
+ -- of a clause. After denotes the clause after which the new
+ -- clause is to be inserted. Flag In_Place should be set when
+ -- normalizing the last output of an output list. Flag Multiple
+ -- should be set when Output comes from a list with multiple
+ -- items.
+
+ -----------------------------
+ -- Create_Or_Modify_Clause --
+ -----------------------------
+
+ procedure Create_Or_Modify_Clause
+ (Output : Node_Id;
+ Outputs : Node_Id;
+ Inputs : Node_Id;
+ After : Node_Id;
+ In_Place : Boolean;
+ Multiple : Boolean)
+ is
+ procedure Propagate_Output
+ (Output : Node_Id;
+ Inputs : Node_Id);
+ -- Handle the various cases of output propagation to the
+ -- input list. Output denotes a self-referencial output
+ -- item. Inputs is the input list of a clause.
+
+ ----------------------
+ -- Propagate_Output --
+ ----------------------
+
+ procedure Propagate_Output
+ (Output : Node_Id;
+ Inputs : Node_Id)
+ is
+ function In_Input_List
+ (Item : Entity_Id;
+ Inputs : List_Id) return Boolean;
+ -- Determine whether a particulat item appears in the
+ -- input list of a clause.
+
+ -------------------
+ -- In_Input_List --
+ -------------------
+
+ function In_Input_List
+ (Item : Entity_Id;
+ Inputs : List_Id) return Boolean
+ is
+ Elmt : Node_Id;
+
+ begin
+ Elmt := First (Inputs);
+ while Present (Elmt) loop
+ if Entity_Of (Elmt) = Item then
+ return True;
+ end if;
+
+ Next (Elmt);
+ end loop;
+
+ return False;
+ end In_Input_List;
+
+ -- Local variables
+
+ Output_Id : constant Entity_Id := Entity_Of (Output);
+ Grouped : List_Id;
+
+ -- Start of processing for Propagate_Output
+
+ begin
+ -- The clause is of the form:
+
+ -- (Output =>+ null)
+
+ -- Remove the null input and replace it with a copy of
+ -- the output:
+
+ -- (Output => Output)
+
+ if Nkind (Inputs) = N_Null then
+ Rewrite (Inputs, New_Copy_Tree (Output));
+
+ -- The clause is of the form:
+
+ -- (Output =>+ (Input1, ..., InputN))
+
+ -- Determine whether the output is not already mentioned
+ -- in the input list and if not, add it to the list of
+ -- inputs:
+
+ -- (Output => (Output, Input1, ..., InputN))
+
+ elsif Nkind (Inputs) = N_Aggregate then
+ Grouped := Expressions (Inputs);
+
+ if not In_Input_List
+ (Item => Output_Id,
+ Inputs => Grouped)
+ then
+ Prepend_To (Grouped, New_Copy_Tree (Output));
+ end if;
+
+ -- The clause is of the form:
+
+ -- (Output =>+ Input)
+
+ -- If the input does not mention the output, group the
+ -- two together:
+
+ -- (Output => (Output, Input))
+
+ elsif Entity_Of (Inputs) /= Output_Id then
+ Rewrite (Inputs,
+ Make_Aggregate (Loc,
+ Expressions => New_List (
+ New_Copy_Tree (Output),
+ New_Copy_Tree (Inputs))));
+ end if;
+ end Propagate_Output;
+
+ -- Local variables
+
+ Loc : constant Source_Ptr := Sloc (Output);
+ Clause : Node_Id;
+
+ -- Start of processing for Create_Or_Modify_Clause
+
+ begin
+ -- A function result cannot depend on itself because it
+ -- cannot appear in the input list of a relation.
+
+ if Nkind (Output) = N_Attribute_Reference
+ and then Attribute_Name (Output) = Name_Result
+ then
+ Error_Msg_N
+ ("function result cannot depend on itself", Output);
+ return;
+
+ -- A null output depending on itself does not require any
+ -- normalization.
+
+ elsif Nkind (Output) = N_Null then
+ return;
+ end if;
+
+ -- When performing the transformation in place, simply add
+ -- the output to the list of inputs (if not already there).
+ -- This case arises when dealing with the last output of an
+ -- output list - we perform the normalization in place to
+ -- avoid generating a malformed tree.
+
+ if In_Place then
+ Propagate_Output (Output, Inputs);
+
+ -- A list with multiple outputs is slowly trimmed until
+ -- only one element remains. When this happens, replace
+ -- the aggregate with the element itself.
+
+ if Multiple then
+ Remove (Output);
+ Rewrite (Outputs, Output);
+ end if;
+
+ -- Default case
+
+ else
+ -- Unchain the output from its output list as it will
+ -- appear in a new clause. Note that we cannot simply
+ -- rewrite the output as null because this will violate
+ -- the semantics of aspect/pragma Depends.
+
+ Remove (Output);
+
+ -- Create a new clause of the form:
+
+ -- (Output => Inputs)
+
+ Clause :=
+ Make_Component_Association (Loc,
+ Choices => New_List (Output),
+ Expression => New_Copy_Tree (Inputs));
+
+ -- The new clause contains replicated content that has
+ -- already been analyzed. There is not need to reanalyze
+ -- it or renormalize it again.
+
+ Set_Analyzed (Clause);
+
+ Propagate_Output
+ (Output => First (Choices (Clause)),
+ Inputs => Expression (Clause));
+
+ Insert_After (After, Clause);
+ end if;
+ end Create_Or_Modify_Clause;
+
+ -- Local variables
+
+ Outputs : constant Node_Id := First (Choices (Clause));
+ Inputs : Node_Id;
+ Last_Output : Node_Id;
+ Next_Output : Node_Id;
+ Output : Node_Id;
+
+ -- Start of processing for Normalize_Clause
+
+ begin
+ -- A self-dependency appears as operator "+". Remove the "+"
+ -- from the tree by moving the real inputs to their proper
+ -- place.
+
+ if Nkind (Expression (Clause)) = N_Op_Plus then
+ Rewrite
+ (Expression (Clause), Right_Opnd (Expression (Clause)));
+ Inputs := Expression (Clause);
+
+ -- Multiple outputs appear as an aggregate
+
+ if Nkind (Outputs) = N_Aggregate then
+ Last_Output := Last (Expressions (Outputs));
+
+ Output := First (Expressions (Outputs));
+ while Present (Output) loop
+
+ -- Normalization may remove an output from its list,
+ -- preserve the subsequent output now.
+
+ Next_Output := Next (Output);
+
+ Create_Or_Modify_Clause
+ (Output => Output,
+ Outputs => Outputs,
+ Inputs => Inputs,
+ After => Clause,
+ In_Place => Output = Last_Output,
+ Multiple => True);
+
+ Output := Next_Output;
+ end loop;
+
+ -- Solitary output
+
+ else
+ Create_Or_Modify_Clause
+ (Output => Outputs,
+ Outputs => Empty,
+ Inputs => Inputs,
+ After => Empty,
+ In_Place => True,
+ Multiple => False);
+ end if;
+ end if;
+ end Normalize_Clause;
+
+ -- Local variables
+
+ Clause : Node_Id;
+ Errors : Nat;
+ Last_Clause : Node_Id;
+ Subp_Decl : Node_Id;
+
+ -- Start of processing for Depends
+
+ begin
+ GNAT_Pragma;
+ S14_Pragma;
+ Check_Arg_Count (1);
+
+ -- Ensure the proper placement of the pragma. Depends must be
+ -- associated with a subprogram declaration.
+
+ Subp_Decl := Parent (Corresponding_Aspect (N));
+
+ if Nkind (Subp_Decl) /= N_Subprogram_Declaration then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
+ Clause := Expression (Arg1);
+
+ -- Empty dependency list
+
+ if Nkind (Clause) = N_Null then
+
+ -- Gather all states, variables and formal parameters that the
+ -- subprogram may depend on. These items are obtained from the
+ -- parameter profile or pragma Global (if available).
+
+ Collect_Subprogram_Inputs_Outputs;
+
+ -- Verify that every input or output of the subprogram appear
+ -- in a dependency.
+
+ Check_Usage (Subp_Inputs, All_Inputs_Seen, True);
+ Check_Usage (Subp_Outputs, Outputs_Seen, False);
+ Check_Function_Return;
+
+ -- Dependency clauses appear as component associations of an
+ -- aggregate.
+
+ elsif Nkind (Clause) = N_Aggregate
+ and then Present (Component_Associations (Clause))
+ then
+ Last_Clause := Last (Component_Associations (Clause));
+
+ -- Gather all states, variables and formal parameters that the
+ -- subprogram may depend on. These items are obtained from the
+ -- parameter profile or pragma Global (if available).
+
+ Collect_Subprogram_Inputs_Outputs;
+
+ -- Ensure that the formal parameters are visible when analyzing
+ -- all clauses. This falls out of the general rule of aspects
+ -- pertaining to subprogram declarations.
+
+ Push_Scope (Subp_Id);
+ Install_Formals (Subp_Id);
+
+ Clause := First (Component_Associations (Clause));
+ while Present (Clause) loop
+ Errors := Serious_Errors_Detected;
+
+ -- Normalization may create extra clauses that contain
+ -- replicated input and output names. There is no need
+ -- to reanalyze or renormalize these extra clauses.
+
+ if not Analyzed (Clause) then
+ Set_Analyzed (Clause);
+
+ Analyze_Dependency_Clause
+ (Clause => Clause,
+ Is_Last => Clause = Last_Clause);
+
+ -- Do not normalize an erroneous clause because the
+ -- inputs or outputs may denote illegal items.
+
+ if Errors = Serious_Errors_Detected then
+ Normalize_Clause (Clause);
+ end if;
+ end if;
+
+ Next (Clause);
+ end loop;
+
+ End_Scope;
+
+ -- Verify that every input or output of the subprogram appear
+ -- in a dependency.
+
+ Check_Usage (Subp_Inputs, All_Inputs_Seen, True);
+ Check_Usage (Subp_Outputs, Outputs_Seen, False);
+ Check_Function_Return;
+
+ -- The top level dependency relation is malformed
+
+ else
+ Error_Msg_N ("malformed dependency relation", Clause);
+ end if;
+ end Depends;
---------------------
-- Detect_Blocking --
@@ -9325,8 +10788,8 @@ package body Sem_Prag is
Present (Source_Location)
then
Error_Pragma
- ("parameter profile and source location cannot " &
- "be used together in pragma%");
+ ("parameter profile and source location cannot be used "
+ & "together in pragma%");
end if;
Process_Eliminate_Pragma
@@ -10030,20 +11493,55 @@ package body Sem_Prag is
end if;
end Float_Representation;
+ -----------
+ -- Ghost --
+ -----------
+
+ -- pragma GHOST (function_LOCAL_NAME);
+
+ when Pragma_Ghost => Ghost : declare
+ Subp : Node_Id;
+ Subp_Id : Entity_Id;
+
+ begin
+ GNAT_Pragma;
+ S14_Pragma;
+ Check_Arg_Count (1);
+ Check_Arg_Is_Local_Name (Arg1);
+
+ -- Ensure the proper placement of the pragma. Ghost must be
+ -- associated with a subprogram declaration.
+
+ Subp := Parent (Corresponding_Aspect (N));
+
+ if Nkind (Subp) /= N_Subprogram_Declaration then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Subp_Id := Defining_Unit_Name (Specification (Subp));
+
+ if Ekind (Subp_Id) /= E_Function then
+ Error_Pragma ("pragma % must be applied to a function");
+ end if;
+ end Ghost;
+
------------
-- Global --
------------
-- pragma Global (GLOBAL_SPECIFICATION)
- -- GLOBAL_SPECIFICATION ::= MODED_GLOBAL_LIST {, MODED_GLOBAL_LIST}
- -- | GLOBAL_LIST
- -- | null
- -- MODED_GLOBAL_LIST ::= MODE_SELECTOR => GLOBAL_LIST
- -- MODE_SELECTOR ::= Input | Output | In_Out | Contract_In
- -- GLOBAL_LIST ::= GLOBAL_ITEM
- -- | (GLOBAL_ITEM {, GLOBAL_ITEM})
- -- GLOBAL_ITEM ::= NAME
+ -- GLOBAL_SPECIFICATION ::=
+ -- null
+ -- | GLOBAL_LIST
+ -- | MODED_GLOBAL_LIST {, MODED_GLOBAL_LIST}
+
+ -- MODED_GLOBAL_LIST ::= MODE_SELECTOR => GLOBAL_LIST
+
+ -- MODE_SELECTOR ::= Input | Output | In_Out | Contract_In
+ -- GLOBAL_LIST ::= GLOBAL_ITEM | (GLOBAL_ITEM {, GLOBAL_ITEM})
+ -- GLOBAL_ITEM ::= NAME
when Pragma_Global => Global : declare
Subp_Id : Entity_Id;
@@ -10052,12 +11550,11 @@ package body Sem_Prag is
-- A list containing the entities of all the items processed so
-- far. It plays a role in detecting distinct entities.
- -- Flags used to verify the consistency of modes
-
Contract_Seen : Boolean := False;
In_Out_Seen : Boolean := False;
Input_Seen : Boolean := False;
Output_Seen : Boolean := False;
+ -- Flags used to verify the consistency of modes
procedure Analyze_Global_List
(List : Node_Id;
@@ -10099,36 +11596,7 @@ package body Sem_Prag is
(Item : Node_Id;
Global_Mode : Name_Id)
is
- function Is_Duplicate_Item (Id : Entity_Id) return Boolean;
- -- Determine whether Id has already been processed
-
- -----------------------
- -- Is_Duplicate_Item --
- -----------------------
-
- function Is_Duplicate_Item (Id : Entity_Id) return Boolean is
- Item_Elmt : Elmt_Id;
-
- begin
- if Present (Seen) then
- Item_Elmt := First_Elmt (Seen);
- while Present (Item_Elmt) loop
- if Node (Item_Elmt) = Id then
- return True;
- end if;
-
- Next_Elmt (Item_Elmt);
- end loop;
- end if;
-
- return False;
- end Is_Duplicate_Item;
-
- -- Local declarations
-
- Id : Entity_Id;
-
- -- Start of processing for Analyze_Global_Item
+ Item_Id : Entity_Id;
begin
-- Detect one of the following cases
@@ -10145,13 +11613,18 @@ package body Sem_Prag is
Analyze (Item);
- if Is_Entity_Name (Item) then
- Id := Entity (Item);
+ -- Find the entity of the item. If this is a renaming, climb
+ -- the renaming chain to reach the root object. Renamings of
+ -- non-entire objects do not yield an entity (Empty).
+
+ Item_Id := Entity_Of (Item);
+
+ if Present (Item_Id) then
-- A global item cannot reference a formal parameter. Do
-- this check first to provide a better error diagnostic.
- if Is_Formal (Id) then
+ if Is_Formal (Item_Id) then
Error_Msg_N
("global item cannot reference formal parameter",
Item);
@@ -10160,14 +11633,23 @@ package body Sem_Prag is
-- The only legal references are those to abstract states
-- and variables.
- elsif not Ekind_In (Entity (Item), E_Abstract_State,
- E_Variable)
+ elsif not Ekind_In (Item_Id, E_Abstract_State,
+ E_Variable)
then
Error_Msg_N
("global item must denote variable or state", Item);
return;
end if;
+ -- When the item renames an entire object, replace the
+ -- item with a reference to the object.
+
+ if Present (Renamed_Object (Entity (Item))) then
+ Rewrite (Item,
+ New_Reference_To (Item_Id, Sloc (Item)));
+ Analyze (Item);
+ end if;
+
-- Some form of illegal construct masquerading as a name
else
@@ -10179,42 +11661,34 @@ package body Sem_Prag is
-- The same entity might be referenced through various way.
-- Check the entity of the item rather than the item itself.
- if Is_Duplicate_Item (Id) then
+ if Contains (Seen, Item_Id) then
Error_Msg_N ("duplicate global item", Item);
-- Add the entity of the current item to the list of
-- processed items.
else
- if No (Seen) then
- Seen := New_Elmt_List;
- end if;
-
- Append_Elmt (Id, Seen);
+ Add_Item (Item_Id, Seen);
end if;
- if Ekind (Id) = E_Abstract_State
- and then Is_Volatile_State (Id)
+ if Ekind (Item_Id) = E_Abstract_State
+ and then Is_Volatile_State (Item_Id)
then
-- A global item of mode In_Out or Output cannot denote a
-- volatile Input state.
- if Is_Input_State (Id)
- and then (Global_Mode = Name_In_Out
- or else
- Global_Mode = Name_Output)
+ if Is_Input_State (Item_Id)
+ and then Nam_In (Global_Mode, Name_In_Out, Name_Output)
then
Error_Msg_N
- ("global item of mode In_Out or Output cannot " &
- "reference Volatile Input state", Item);
+ ("global item of mode In_Out or Output cannot "
+ & "reference Volatile Input state", Item);
-- A global item of mode In_Out or Input cannot reference
-- a volatile Output state.
- elsif Is_Output_State (Id)
- and then (Global_Mode = Name_In_Out
- or else
- Global_Mode = Name_Input)
+ elsif Is_Output_State (Item_Id)
+ and then Nam_In (Global_Mode, Name_In_Out, Name_Input)
then
Error_Msg_N
("global item of mode In_Out or Input cannot "
@@ -10246,9 +11720,8 @@ package body Sem_Prag is
procedure Check_Mode_Restriction_In_Function (Mode : Node_Id) is
begin
if Ekind (Subp_Id) = E_Function then
- Error_Msg_Name_1 := Chars (Mode);
Error_Msg_N
- ("global mode % not applicable to functions", Mode);
+ ("global mode & not applicable to functions", Mode);
end if;
end Check_Mode_Restriction_In_Function;
@@ -10300,22 +11773,22 @@ package body Sem_Prag is
Assoc := First (Component_Associations (List));
while Present (Assoc) loop
- Mode := First (Choices (Assoc));
+ Mode := First (Choices (Assoc));
if Nkind (Mode) = N_Identifier then
if Chars (Mode) = Name_Contract_In then
- Check_Duplicate_Mode (Mode, Contract_Seen);
+ Check_Duplicate_Mode (Mode, Contract_Seen);
elsif Chars (Mode) = Name_In_Out then
Check_Duplicate_Mode (Mode, In_Out_Seen);
- Check_Mode_Restriction_In_Function (Mode);
+ Check_Mode_Restriction_In_Function (Mode);
elsif Chars (Mode) = Name_Input then
- Check_Duplicate_Mode (Mode, Input_Seen);
+ Check_Duplicate_Mode (Mode, Input_Seen);
elsif Chars (Mode) = Name_Output then
Check_Duplicate_Mode (Mode, Output_Seen);
- Check_Mode_Restriction_In_Function (Mode);
+ Check_Mode_Restriction_In_Function (Mode);
else
Error_Msg_N ("invalid mode selector", Mode);
@@ -10393,7 +11866,7 @@ package body Sem_Prag is
Analyze_Global_List (List);
- Pop_Scope;
+ End_Scope;
end if;
end Global;
@@ -10608,8 +12081,8 @@ package body Sem_Prag is
null;
else
Error_Pragma_Arg
- ("controlling formal must be of synchronized " &
- "tagged type", Arg1);
+ ("controlling formal must be of synchronized tagged type",
+ Arg1);
return;
end if;
@@ -10637,8 +12110,8 @@ package body Sem_Prag is
and then Is_Task_Interface (Typ)
then
Error_Pragma_Arg
- ("implementation kind By_Protected_Procedure cannot be " &
- "applied to a task interface primitive", Arg2);
+ ("implementation kind By_Protected_Procedure cannot be "
+ & "applied to a task interface primitive", Arg2);
return;
end if;
@@ -11460,8 +12933,8 @@ package body Sem_Prag is
Int_Val > Expr_Value (Type_High_Bound (Int_Id))
then
Error_Pragma_Arg
- ("value not in range of type " &
- """Ada.Interrupts.Interrupt_'I'D""", Arg1);
+ ("value not in range of type "
+ & """Ada.Interrupts.Interrupt_'I'D""", Arg1);
end if;
end if;
@@ -11567,8 +13040,8 @@ package body Sem_Prag is
elsif In_Private_Part (Current_Scope) then
Error_Pragma_Arg
- ("pragma% only allowed for private type " &
- "declared in visible part", Arg1);
+ ("pragma% only allowed for private type declared in "
+ & "visible part", Arg1);
else
Error_Pragma_Arg
@@ -11576,10 +13049,10 @@ package body Sem_Prag is
end if;
-- Note that the type has at least one invariant, and also that
- -- it has inheritable invariants if we have Invariant'Class.
- -- Build the corresponding invariant procedure declaration, so
- -- that calls to it can be generated before the body is built
- -- (for example wihin an expression function).
+ -- it has inheritable invariants if we have Invariant'Class
+ -- or Type_Invariant'Class. Build the corresponding invariant
+ -- procedure declaration, so that calls to it can be generated
+ -- before the body is built (e.g. within an expression function).
PDecl := Build_Invariant_Procedure_Declaration (Typ);
Insert_After (N, PDecl);
@@ -11661,12 +13134,12 @@ package body Sem_Prag is
if Ekind (Def_Id) /= E_Function then
if VM_Target = JVM_Target then
Error_Pragma_Arg
- ("pragma% requires function returning a " &
- "'Java access type", Def_Id);
+ ("pragma% requires function returning a 'Java access "
+ & "type", Def_Id);
else
Error_Pragma_Arg
- ("pragma% requires function returning a " &
- "'C'I'L access type", Def_Id);
+ ("pragma% requires function returning a 'C'I'L access "
+ & "type", Def_Id);
end if;
end if;
@@ -11762,8 +13235,8 @@ package body Sem_Prag is
then
Error_Msg_Name_1 := Pname;
Error_Msg_N
- ("first formal of % function must be a named access" &
- " to subprogram type",
+ ("first formal of % function must be a named access "
+ & "to subprogram type",
Parameter_Type (Parent (This_Formal)));
-- Warning: We should reject anonymous access types because
@@ -11779,9 +13252,8 @@ package body Sem_Prag is
then
Error_Msg_Name_1 := Pname;
Error_Msg_N
- ("first formal of % function must be a named access" &
- " type",
- Parameter_Type (Parent (This_Formal)));
+ ("first formal of % function must be a named access "
+ & "type", Parameter_Type (Parent (This_Formal)));
elsif Atree.Convention
(Designated_Type (Etype (This_Formal))) /= Convention
@@ -11790,14 +13262,12 @@ package body Sem_Prag is
if Convention = Convention_Java then
Error_Msg_N
- ("pragma% requires convention 'Cil in designated" &
- " type",
- Parameter_Type (Parent (This_Formal)));
+ ("pragma% requires convention 'Cil in designated "
+ & "type", Parameter_Type (Parent (This_Formal)));
else
Error_Msg_N
- ("pragma% requires convention 'Java in designated" &
- " type",
- Parameter_Type (Parent (This_Formal)));
+ ("pragma% requires convention 'Java in designated "
+ & "type", Parameter_Type (Parent (This_Formal)));
end if;
elsif No (Expression (Parent (This_Formal)))
@@ -11826,13 +13296,13 @@ package body Sem_Prag is
if Atree.Convention (Etype (Def_Id)) /= Convention then
if Convention = Convention_Java then
Error_Pragma_Arg
- ("pragma% requires function returning a " &
- "'Java access type", Arg1);
+ ("pragma% requires function returning a 'Java "
+ & "access type", Arg1);
else
pragma Assert (Convention = Convention_CIL);
Error_Pragma_Arg
- ("pragma% requires function returning a " &
- "'C'I'L access type", Arg1);
+ ("pragma% requires function returning a 'C'I'L "
+ & "access type", Arg1);
end if;
end if;
@@ -11847,12 +13317,12 @@ package body Sem_Prag is
if Convention = Convention_Java then
Error_Pragma_Arg
- ("pragma% requires function returning a named" &
- "'Java access type", Arg1);
+ ("pragma% requires function returning a named "
+ & "'Java access type", Arg1);
else
Error_Pragma_Arg
- ("pragma% requires function returning a named" &
- "'C'I'L access type", Arg1);
+ ("pragma% requires function returning a named "
+ & "'C'I'L access type", Arg1);
end if;
end if;
end if;
@@ -12392,22 +13862,20 @@ package body Sem_Prag is
Check_Arg_Count (1);
Check_Loop_Pragma_Placement;
- -- Completely ignore if disabled
+ -- Completely ignore if not enabled
- if Check_Disabled (Pname) then
+ if Is_Ignored (N) then
Rewrite (N, Make_Null_Statement (Loc));
Analyze (N);
return;
end if;
- Preanalyze_And_Resolve (Expression (Arg1), Any_Boolean);
+ Preanalyze_Assert_Expression (Expression (Arg1), Any_Boolean);
-- Transform pragma Loop_Invariant into equivalent pragma Check
-- Generate:
-- pragma Check (Loop_Invaraint, Arg1);
- -- Seems completely wrong to hijack pragma Check this way ???
-
Rewrite (N,
Make_Pragma (Loc,
Chars => Name_Check,
@@ -12434,12 +13902,14 @@ package body Sem_Prag is
GNAT_Pragma;
Check_At_Least_N_Arguments (1);
Check_No_Identifiers;
+
Hint := First (Pragma_Argument_Associations (N));
while Present (Hint) loop
Check_Arg_Is_One_Of (Hint,
Name_No_Unroll, Name_Unroll, Name_No_Vector, Name_Vector);
Next (Hint);
end loop;
+
Check_Loop_Pragma_Placement;
end Loop_Optimize;
@@ -12463,9 +13933,9 @@ package body Sem_Prag is
Check_At_Least_N_Arguments (1);
Check_Loop_Pragma_Placement;
- -- Completely ignore if disabled
+ -- Completely ignore if not enabled
- if Check_Disabled (Pname) then
+ if Is_Ignored (N) then
Rewrite (N, Make_Null_Statement (Loc));
Analyze (N);
return;
@@ -12475,13 +13945,14 @@ package body Sem_Prag is
Variant := First (Pragma_Argument_Associations (N));
while Present (Variant) loop
- if Chars (Variant) /= Name_Decreases
- and then Chars (Variant) /= Name_Increases
+ if not Nam_In (Chars (Variant), Name_Decreases,
+ Name_Increases)
then
Error_Pragma_Arg ("wrong change modifier", Variant);
end if;
- Preanalyze_And_Resolve (Expression (Variant), Any_Discrete);
+ Preanalyze_Assert_Expression
+ (Expression (Variant), Any_Discrete);
Next (Variant);
end loop;
@@ -12875,8 +14346,8 @@ package body Sem_Prag is
loop
if No (Ent) then
Error_Pragma
- ("pragma % entity name does not match any " &
- "enumeration literal");
+ ("pragma % entity name does not match any "
+ & "enumeration literal");
elsif Chars (Ent) = Chars (Ename) then
Set_Entity (Ename, Ent);
@@ -13414,12 +14885,22 @@ package body Sem_Prag is
Check_First_Subtype (Arg1);
Ent := Entity (Get_Pragma_Arg (Arg1));
- if not (Is_Private_Type (Ent)
- or else
- Is_Protected_Type (Ent)
- or else
- (Is_Generic_Type (Ent) and then Is_Derived_Type (Ent)))
+ -- The pragma may come from an aspect on a private declaration,
+ -- even if the freeze point at which this is analyzed in the
+ -- private part after the full view.
+
+ if Has_Private_Declaration (Ent)
+ and then From_Aspect_Specification (N)
+ then
+ null;
+
+ elsif Is_Private_Type (Ent)
+ or else Is_Protected_Type (Ent)
+ or else (Is_Generic_Type (Ent) and then Is_Derived_Type (Ent))
then
+ null;
+
+ else
Error_Pragma_Arg
("pragma % can only be applied to private, formal derived or "
& "protected type",
@@ -13434,8 +14915,8 @@ package body Sem_Prag is
and then not Has_Preelaborable_Initialization (Ent)
then
Error_Msg_N
- ("protected type & does not have preelaborable " &
- "initialization", Ent);
+ ("protected type & does not have preelaborable "
+ & "initialization", Ent);
-- Otherwise mark the type as definitely having preelaborable
-- initialization.
@@ -13552,7 +15033,7 @@ package body Sem_Prag is
Check_Precondition_Postcondition (In_Body);
- -- When the pragma is a source contruct and appears inside a body,
+ -- When the pragma is a source construct appearing inside a body,
-- preanalyze the boolean_expression to detect illegal forward
-- references:
@@ -13583,10 +15064,20 @@ package body Sem_Prag is
Check_Precondition_Postcondition (In_Body);
-- If in spec, nothing more to do. If in body, then we convert the
- -- pragma to pragma Check (Precondition, cond [, msg]). Note we do
- -- this whether or not precondition checks are enabled. That works
- -- fine since pragma Check will do this check, and will also
- -- analyze the condition itself in the proper context.
+ -- pragma to an equivalent pragam Check. Note we do this whether
+ -- or not precondition checks are enabled. That works fine since
+ -- pragma Check will do this check, and will also analyze the
+ -- condition itself in the proper context.
+
+ -- The form of the pragma Check is either:
+
+ -- pragma Check (Precondition, cond [, msg])
+ -- or
+ -- pragma Check (Pre, cond [, msg])
+
+ -- We use the Pre form if this pragma derived from a Pre aspect.
+ -- This is needed to make sure that the right set of Policy
+ -- pragmas are checked.
if In_Body then
Rewrite (N,
@@ -13594,7 +15085,7 @@ package body Sem_Prag is
Chars => Name_Check,
Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Loc,
- Expression => Make_Identifier (Loc, Name_Precondition)),
+ Expression => Make_Identifier (Loc, Pname)),
Make_Pragma_Argument_Association (Sloc (Arg1),
Expression => Relocate_Node (Get_Pragma_Arg (Arg1))))));
@@ -13808,7 +15299,7 @@ package body Sem_Prag is
-- described in "Handling of Default and Per-Object
-- Expressions" in sem.ads.
- Preanalyze_Spec_Expression (Arg, Standard_Integer);
+ Preanalyze_Spec_Expression (Arg, RTE (RE_Any_Priority));
if not Is_Static_Expression (Arg) then
Check_Restriction (Static_Priorities, Arg);
@@ -13894,8 +15385,8 @@ package body Sem_Prag is
elsif Lower_Val > Upper_Val then
Error_Pragma
- ("last_priority_expression must be greater than" &
- " or equal to first_priority_expression");
+ ("last_priority_expression must be greater than or equal to "
+ & "first_priority_expression");
-- Store the new policy, but always preserve System_Location since
-- we like the error message with the run-time name.
@@ -14737,8 +16228,8 @@ package body Sem_Prag is
or else In_Package_Body (Current_Scope)
then
Error_Pragma
- ("pragma% can only apply to type declared immediately " &
- "within a package declaration");
+ ("pragma% can only apply to type declared immediately "
+ & "within a package declaration");
end if;
-- A simple storage pool type must be an immutably limited record
@@ -14976,8 +16467,8 @@ package body Sem_Prag is
or else Present (Next_Formal (First_Formal (Ent)))
then
Error_Pragma_Arg
- ("argument for pragma% must be" &
- " function of one argument", Arg);
+ ("argument for pragma% must be function of one argument",
+ Arg);
end if;
end Check_OK_Stream_Convert_Function;
@@ -16100,10 +17591,7 @@ package body Sem_Prag is
-- On/Off one argument case was processed by parser
if Nkind (Argx) = N_Identifier
- and then
- (Chars (Argx) = Name_On
- or else
- Chars (Argx) = Name_Off)
+ and then Nam_In (Chars (Argx), Name_On, Name_Off)
then
null;
@@ -16111,8 +17599,8 @@ package body Sem_Prag is
elsif not Is_Static_String_Expression (Arg1) then
Error_Pragma_Arg
- ("argument of pragma% must be On/Off or " &
- "static string expression", Arg1);
+ ("argument of pragma% must be On/Off or static string "
+ & "expression", Arg1);
-- One argument string expression case
@@ -16156,8 +17644,8 @@ package body Sem_Prag is
if not Set_Dot_Warning_Switch (Chr) then
Error_Pragma_Arg
- ("invalid warning switch character " &
- '.' & Chr, Arg1);
+ ("invalid warning switch character "
+ & '.' & Chr, Arg1);
end if;
-- Non-Dot case
@@ -16250,8 +17738,8 @@ package body Sem_Prag is
elsif not Is_Static_String_Expression (Arg2) then
Error_Pragma_Arg
- ("second argument of pragma% must be entity " &
- "name or static string expression", Arg2);
+ ("second argument of pragma% must be entity name "
+ & "or static string expression", Arg2);
-- String literal case
@@ -16290,9 +17778,8 @@ package body Sem_Prag is
if Err then
Error_Msg
- ("??pragma Warnings On with no " &
- "matching Warnings Off",
- Loc);
+ ("??pragma Warnings On with no matching "
+ & "Warnings Off", Loc);
end if;
end if;
end if;
@@ -16371,84 +17858,140 @@ package body Sem_Prag is
when Pragma_Exit => null;
end Analyze_Pragma;
- --------------------
- -- Check_Disabled --
- --------------------
+ ----------------
+ -- Check_Kind --
+ ----------------
- function Check_Disabled (Nam : Name_Id) return Boolean is
+ function Check_Kind (Nam : Name_Id) return Name_Id is
PP : Node_Id;
begin
-- Loop through entries in check policy list
PP := Opt.Check_Policy_List;
- loop
- -- If there are no specific entries that matched, then nothing is
- -- disabled, so return False.
+ while Present (PP) loop
+ declare
+ PPA : constant List_Id := Pragma_Argument_Associations (PP);
+ Pnm : constant Name_Id := Chars (Get_Pragma_Arg (First (PPA)));
- if No (PP) then
- return False;
+ begin
+ if Nam = Pnm
+ or else (Is_Valid_Assertion_Kind (Nam)
+ and then Pnm = Name_Assertion)
+ then
+ case (Chars (Get_Pragma_Arg (Last (PPA)))) is
+ when Name_On | Name_Check =>
+ return Name_Check;
+ when Name_Off | Name_Ignore =>
+ return Name_Ignore;
+ when Name_Disable =>
+ return Name_Disable;
+ when others =>
+ raise Program_Error;
+ end case;
- -- Here we have an entry see if it matches
+ else
+ PP := Next_Pragma (PP);
+ end if;
+ end;
+ end loop;
+
+ -- If there are no specific entries that matched, then we let the
+ -- setting of assertions govern. Note that this provides the needed
+ -- compatibility with the RM for the cases of assertion, invariant,
+ -- precondition, predicate, and postcondition.
+
+ if Assertions_Enabled then
+ return Name_Check;
+ else
+ return Name_Ignore;
+ end if;
+ end Check_Kind;
+
+ -----------------------------
+ -- Check_Applicable_Policy --
+ -----------------------------
+
+ procedure Check_Applicable_Policy (N : Node_Id) is
+ PP : Node_Id;
+ Policy : Name_Id;
+ Ename : Name_Id;
+ -- Effective name of aspect or pragma, this is simply the name of
+ -- the aspect or pragma, except in the case of a pragma derived from
+ -- an aspect, in which case it is the name of the aspect (which may be
+ -- different, e.g. Pre aspect generating Precondition pragma). It also
+ -- deals with the 'Class cases for an aspect.
+
+ begin
+ if Nkind (N) = N_Pragma then
+ if Present (Corresponding_Aspect (N)) then
+ Ename := Chars (Identifier (Corresponding_Aspect (N)));
else
- declare
- PPA : constant List_Id := Pragma_Argument_Associations (PP);
- begin
- if Nam = Chars (Get_Pragma_Arg (First (PPA))) then
- return Chars (Get_Pragma_Arg (Last (PPA))) = Name_Disable;
- else
- PP := Next_Pragma (PP);
- end if;
- end;
+ Ename := Chars (Pragma_Identifier (N));
end if;
- end loop;
- end Check_Disabled;
- -------------------
- -- Check_Enabled --
- -------------------
+ else
+ pragma Assert (Nkind (N) = N_Aspect_Specification);
+ Ename := Chars (Identifier (N));
+
+ if Class_Present (N) then
+ case Ename is
+ when Name_Invariant => Ename := Name_uInvariant;
+ when Name_Pre => Ename := Name_uPre;
+ when Name_Post => Ename := Name_uPost;
+ when Name_Type_Invariant => Ename := Name_uType_Invariant;
+ when others => raise Program_Error;
+ end case;
+ end if;
+ end if;
- function Check_Enabled (Nam : Name_Id) return Boolean is
- PP : Node_Id;
+ -- No effect if not valid assertion kind name
+
+ if not Is_Valid_Assertion_Kind (Ename) then
+ return;
+ end if;
- begin
-- Loop through entries in check policy list
PP := Opt.Check_Policy_List;
- loop
- -- If there are no specific entries that matched, then we let the
- -- setting of assertions govern. Note that this provides the needed
- -- compatibility with the RM for the cases of assertion, invariant,
- -- precondition, predicate, and postcondition.
+ while Present (PP) loop
+ declare
+ PPA : constant List_Id := Pragma_Argument_Associations (PP);
+ Pnm : constant Name_Id := Chars (Get_Pragma_Arg (First (PPA)));
- if No (PP) then
- return Assertions_Enabled;
+ begin
+ if Ename = Pnm or else Pnm = Name_Assertion then
+ Policy := Chars (Get_Pragma_Arg (Last (PPA)));
- -- Here we have an entry see if it matches
+ case Policy is
+ when Name_Off | Name_Ignore =>
+ Set_Is_Ignored (N, True);
- else
- declare
- PPA : constant List_Id := Pragma_Argument_Associations (PP);
+ when Name_Disable =>
+ Set_Is_Ignored (N, True);
+ Set_Is_Disabled (N, True);
- begin
- if Nam = Chars (Get_Pragma_Arg (First (PPA))) then
- case (Chars (Get_Pragma_Arg (Last (PPA)))) is
- when Name_On | Name_Check =>
- return True;
- when Name_Off | Name_Ignore =>
- return False;
- when others =>
- raise Program_Error;
- end case;
+ when others =>
+ null;
+ end case;
- else
- PP := Next_Pragma (PP);
- end if;
- end;
- end if;
+ return;
+ end if;
+
+ PP := Next_Pragma (PP);
+ end;
end loop;
- end Check_Enabled;
+
+ -- If there are no specific entries that matched, then we let the
+ -- setting of assertions govern. Note that this provides the needed
+ -- compatibility with the RM for the cases of assertion, invariant,
+ -- precondition, predicate, and postcondition.
+
+ if not Assertions_Enabled then
+ Set_Is_Ignored (N);
+ end if;
+ end Check_Applicable_Policy;
---------------------------------
-- Delay_Config_Pragma_Analyze --
@@ -16456,9 +17999,8 @@ package body Sem_Prag is
function Delay_Config_Pragma_Analyze (N : Node_Id) return Boolean is
begin
- return Pragma_Name (N) = Name_Interrupt_State
- or else
- Pragma_Name (N) = Name_Priority_Specific_Dispatching;
+ return Nam_In (Pragma_Name (N), Name_Interrupt_State,
+ Name_Priority_Specific_Dispatching);
end Delay_Config_Pragma_Analyze;
-------------------------
@@ -16618,6 +18160,7 @@ package body Sem_Prag is
Pragma_Debug_Policy => 0,
Pragma_Detect_Blocking => -1,
Pragma_Default_Storage_Pool => -1,
+ Pragma_Depends => -1,
Pragma_Disable_Atomic_Synchronization => -1,
Pragma_Discard_Names => 0,
Pragma_Dispatching_Domain => -1,
@@ -16642,6 +18185,7 @@ package body Sem_Prag is
Pragma_Fast_Math => -1,
Pragma_Finalize_Storage_Only => 0,
Pragma_Float_Representation => 0,
+ Pragma_Ghost => 0,
Pragma_Global => -1,
Pragma_Ident => -1,
Pragma_Implementation_Defined => -1,
@@ -16899,6 +18443,44 @@ package body Sem_Prag is
end if;
end Is_Pragma_String_Literal;
+ -----------------------------
+ -- Is_Valid_Assertion_Kind --
+ -----------------------------
+
+ function Is_Valid_Assertion_Kind (Nam : Name_Id) return Boolean is
+ begin
+ case Nam is
+ when
+ -- RM defined
+
+ Name_Assert |
+ Name_Static_Predicate |
+ Name_Dynamic_Predicate |
+ Name_Pre |
+ Name_uPre |
+ Name_Post |
+ Name_uPost |
+ Name_Type_Invariant |
+ Name_uType_Invariant |
+
+ -- Impl defined
+
+ Name_Assert_And_Cut |
+ Name_Assume |
+ Name_Contract_Cases |
+ Name_Debug |
+ Name_Invariant |
+ Name_uInvariant |
+ Name_Loop_Invariant |
+ Name_Loop_Variant |
+ Name_Postcondition |
+ Name_Precondition |
+ Name_Predicate => return True;
+
+ when others => return False;
+ end case;
+ end Is_Valid_Assertion_Kind;
+
-----------------------------------------
-- Make_Aspect_For_PPC_In_Gen_Sub_Decl --
-----------------------------------------
@@ -17038,6 +18620,35 @@ package body Sem_Prag is
end Process_Compilation_Unit_Pragmas;
+ ----------------------------
+ -- Rewrite_Assertion_Kind --
+ ----------------------------
+
+ procedure Rewrite_Assertion_Kind (N : Node_Id) is
+ Nam : Name_Id;
+
+ begin
+ if Nkind (N) = N_Attribute_Reference
+ and then Attribute_Name (N) = Name_Class
+ and then Nkind (Prefix (N)) = N_Identifier
+ then
+ case Chars (Prefix (N)) is
+ when Name_Pre =>
+ Nam := Name_uPre;
+ when Name_Post =>
+ Nam := Name_uPost;
+ when Name_Type_Invariant =>
+ Nam := Name_uType_Invariant;
+ when Name_Invariant =>
+ Nam := Name_uInvariant;
+ when others =>
+ return;
+ end case;
+
+ Rewrite (N, Make_Identifier (Sloc (N), Chars => Nam));
+ end if;
+ end Rewrite_Assertion_Kind;
+
--------
-- rv --
--------