summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-10 12:35:07 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-10 12:35:07 +0000
commit4befb1a023b3eaa917101fe5eeb699d51f501762 (patch)
tree5033b93dc220ac16f90eeba1b770e74614c9d3e3
parentbe9124d0a1202dff2afe8d88f3511647f485e1ea (diff)
downloadppe42-gcc-4befb1a023b3eaa917101fe5eeb699d51f501762.tar.gz
ppe42-gcc-4befb1a023b3eaa917101fe5eeb699d51f501762.zip
2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
* aspects.adb: Add entries in table Canonical_Aspects for aspects Refined_Depends and Refined_Global. * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument, Aspect_Names, Aspect_Declay, Aspect_On_Body_Or_Stub_OK for aspects Refined_Depends and Refined_Global. * einfo.adb (Contract): Subprogram bodies are now valid owners of contracts. (Set_Contract): Subprogram bodies are now valid owners of contracts. (Write_Field24_Name): Output the contract attribute for subprogram bodies. * exp_ch6.adb (Expand_Subprogram_Contract): New routine. * exp_ch6.ads (Expand_Subprogram_Contract): New routine. * par-prag.adb: Pragmas Refined_Depends and Refined_Global do not require any special processing by the parser. * sem_ch3.adb (Adjust_D): Renamed to Adjust_Decl. (Analyze_Declarations): Code reformatting. Analyze the contract of a subprogram body at the end of the declarative region. * sem_ch6.adb (Analyze_Generic_Subprogram_Body): Subprogram bodies can now have contracts. Use Expand_Subprogram_Contract to handle the various contract assertions. (Analyze_Subprogram_Body_Contract): New null routine. (Analyze_Subprogram_Body_Helper): Subprogram bodies can now have contracts. Use Expand_Subprogram_Contract to handle the various contract assertions. (Analyze_Subprogram_Contract): Add local variable Nam. Update the call to Analyze_PPC_In_Decl_Part. Capture the pragma name in Nam. (Process_PPCs): Removed. * sem_ch6.ads (Analyze_Subprogram_Body_Contract): New routine. (Analyze_Subprogram_Contract): Update the comment on usage. * sem_ch13.adb (Analyze_Aspect_Specifications): Add null implementations for aspects Refined_Depends and Refined_Global. (Check_Aspect_At_Freeze_Point): Aspects Refined_Depends and Refined_Global do not need to be checked at the freeze point. * sem_prag.adb: Add entries in table Sig_Flags for pragmas Refined_Depends and Refined_Global. (Analyze_Contract_Cases_In_Decl_Part): Add local variable Restore. Use Restore to pop the scope. (Analyze_Depends_In_Decl_Part): Add local variable Restore. Use Restore to pop the scope. (Analyze_Global_In_Decl_List): Add local variable Restore. Use Restore to pop the scope. (Analyze_PPC_In_Decl_Part): Renamed to Analyze_Pre_Post_Condition_In_Decl_Part. (Analyze_Pragma): Add null implementations for pragmas Refined_Depends and Refined_Global. Refined_Pre and Refined_Post are now handled by routine Analyze_Refined_Pre_Post_Condition exclusively. (Analyze_Refined_Depends_In_Decl_Part): New null routine. (Analyze_Refined_Global_In_Decl_Part): New null routine. (Analyze_Refined_Pre_Post): Renamed to Analyze_Refined_Pre_Post_Condition. (Analyze_Refined_Pre_Post_Condition): Analyze the boolean expression. (Check_Precondition_Postcondition): Update the call to Analyze_PPC_In_Decl_Part. * sem_prag.ads: Add entries in table Pragma_On_Body_Or_Stub_OK for pragmas Refined_Depends and Refined_Global. (Analyze_PPC_In_Decl_Part): Renamed to Analyze_Pre_Post_Condition_In_Decl_Part. Update the comment on usage. (Analyze_Refined_Depends_In_Decl_Part): New routine. (Analyze_Refined_Global_In_Decl_Part): New routine. (Analyze_Test_Case_In_Decl_Part): Update the comment on usage. * sem_util.adb (Add_Contract_Item): Rename formal Item to Prag and update all occurrences. Subprogram body contracts can now contain pragmas Refined_Depends and Refined_Global. * sem_util.ads (Add_Contract_Item): Rename formal Item to Prag. Update the comment on usage. * sinfo.ads: Update the comment on structure and usage of N_Contract. * snames.ads-tmpl: Add new predefined names for Refined_Depends and Refined_Global. Add entries in table Pragma_Id for Refined_Depends and Refined_Global. 2013-10-10 Robert Dewar <dewar@adacore.com> * types.ads: Minor reformatting. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@203365 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/ChangeLog87
-rw-r--r--gcc/ada/aspects.adb2
-rw-r--r--gcc/ada/aspects.ads12
-rw-r--r--gcc/ada/einfo.adb9
-rw-r--r--gcc/ada/exp_ch6.adb1044
-rw-r--r--gcc/ada/exp_ch6.ads12
-rw-r--r--gcc/ada/par-prag.adb2
-rw-r--r--gcc/ada/sem_ch13.adb16
-rw-r--r--gcc/ada/sem_ch3.adb94
-rw-r--r--gcc/ada/sem_ch6.adb925
-rw-r--r--gcc/ada/sem_ch6.ads14
-rw-r--r--gcc/ada/sem_prag.adb485
-rw-r--r--gcc/ada/sem_prag.ads44
-rw-r--r--gcc/ada/sem_util.adb44
-rw-r--r--gcc/ada/sem_util.ads15
-rw-r--r--gcc/ada/sinfo.ads18
-rw-r--r--gcc/ada/snames.ads-tmpl4
-rw-r--r--gcc/ada/types.ads2
18 files changed, 1598 insertions, 1231 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 1526c73960e..ce65c67ceaa 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,90 @@
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add entries in table Canonical_Aspects for aspects
+ Refined_Depends and Refined_Global.
+ * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument,
+ Aspect_Names, Aspect_Declay, Aspect_On_Body_Or_Stub_OK for
+ aspects Refined_Depends and Refined_Global.
+ * einfo.adb (Contract): Subprogram bodies are now valid owners
+ of contracts.
+ (Set_Contract): Subprogram bodies are now valid
+ owners of contracts.
+ (Write_Field24_Name): Output the contract
+ attribute for subprogram bodies.
+ * exp_ch6.adb (Expand_Subprogram_Contract): New routine.
+ * exp_ch6.ads (Expand_Subprogram_Contract): New routine.
+ * par-prag.adb: Pragmas Refined_Depends and Refined_Global do
+ not require any special processing by the parser.
+ * sem_ch3.adb (Adjust_D): Renamed to Adjust_Decl.
+ (Analyze_Declarations): Code reformatting. Analyze the contract
+ of a subprogram body at the end of the declarative region.
+ * sem_ch6.adb (Analyze_Generic_Subprogram_Body):
+ Subprogram bodies can now have contracts. Use
+ Expand_Subprogram_Contract to handle the various contract
+ assertions.
+ (Analyze_Subprogram_Body_Contract): New null routine.
+ (Analyze_Subprogram_Body_Helper): Subprogram bodies can now have
+ contracts. Use Expand_Subprogram_Contract to handle the various
+ contract assertions.
+ (Analyze_Subprogram_Contract): Add local
+ variable Nam. Update the call to Analyze_PPC_In_Decl_Part. Capture
+ the pragma name in Nam.
+ (Process_PPCs): Removed.
+ * sem_ch6.ads (Analyze_Subprogram_Body_Contract): New routine.
+ (Analyze_Subprogram_Contract): Update the comment on usage.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add null
+ implementations for aspects Refined_Depends and Refined_Global.
+ (Check_Aspect_At_Freeze_Point): Aspects Refined_Depends and
+ Refined_Global do not need to be checked at the freeze point.
+ * sem_prag.adb: Add entries in table Sig_Flags
+ for pragmas Refined_Depends and Refined_Global.
+ (Analyze_Contract_Cases_In_Decl_Part): Add local
+ variable Restore. Use Restore to pop the scope.
+ (Analyze_Depends_In_Decl_Part): Add local variable Restore. Use
+ Restore to pop the scope.
+ (Analyze_Global_In_Decl_List): Add local variable Restore. Use Restore
+ to pop the scope.
+ (Analyze_PPC_In_Decl_Part): Renamed to
+ Analyze_Pre_Post_Condition_In_Decl_Part.
+ (Analyze_Pragma):
+ Add null implementations for pragmas Refined_Depends and
+ Refined_Global. Refined_Pre and Refined_Post are now
+ handled by routine Analyze_Refined_Pre_Post_Condition
+ exclusively.
+ (Analyze_Refined_Depends_In_Decl_Part): New
+ null routine.
+ (Analyze_Refined_Global_In_Decl_Part):
+ New null routine.
+ (Analyze_Refined_Pre_Post):
+ Renamed to Analyze_Refined_Pre_Post_Condition.
+ (Analyze_Refined_Pre_Post_Condition): Analyze the boolean
+ expression.
+ (Check_Precondition_Postcondition): Update the call
+ to Analyze_PPC_In_Decl_Part.
+ * sem_prag.ads: Add entries in table
+ Pragma_On_Body_Or_Stub_OK for pragmas Refined_Depends
+ and Refined_Global.
+ (Analyze_PPC_In_Decl_Part): Renamed
+ to Analyze_Pre_Post_Condition_In_Decl_Part. Update the
+ comment on usage.
+ (Analyze_Refined_Depends_In_Decl_Part): New routine.
+ (Analyze_Refined_Global_In_Decl_Part): New routine.
+ (Analyze_Test_Case_In_Decl_Part): Update the comment on usage.
+ * sem_util.adb (Add_Contract_Item): Rename formal Item to Prag
+ and update all occurrences. Subprogram body contracts can now
+ contain pragmas Refined_Depends and Refined_Global.
+ * sem_util.ads (Add_Contract_Item): Rename formal Item to
+ Prag. Update the comment on usage.
+ * sinfo.ads: Update the comment on structure and usage of
+ N_Contract.
+ * snames.ads-tmpl: Add new predefined names for Refined_Depends
+ and Refined_Global. Add entries in table Pragma_Id for
+ Refined_Depends and Refined_Global.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * types.ads: Minor reformatting.
+
2013-10-10 Thomas Quinot <quinot@adacore.com>
* s-taprop-posix.adb: Add missing comment.
diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index 638fdbedc29..0f21ad48b37 100644
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -466,6 +466,8 @@ package body Aspects is
Aspect_Pure_05 => Aspect_Pure_05,
Aspect_Pure_12 => Aspect_Pure_12,
Aspect_Pure_Function => Aspect_Pure_Function,
+ Aspect_Refined_Depends => Aspect_Refined_Depends,
+ Aspect_Refined_Global => Aspect_Refined_Global,
Aspect_Refined_Post => Aspect_Refined_Post,
Aspect_Refined_Pre => Aspect_Refined_Pre,
Aspect_Remote_Access_Type => Aspect_Remote_Access_Type,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index d2f5d6939a6..50ac1aa58cb 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -111,6 +111,8 @@ package Aspects is
Aspect_Predicate, -- GNAT
Aspect_Priority,
Aspect_Read,
+ Aspect_Refined_Depends, -- GNAT
+ Aspect_Refined_Global, -- GNAT
Aspect_Refined_Post, -- GNAT
Aspect_Refined_Pre, -- GNAT
Aspect_Relative_Deadline,
@@ -321,6 +323,8 @@ package Aspects is
Aspect_Predicate => Expression,
Aspect_Priority => Expression,
Aspect_Read => Name,
+ Aspect_Refined_Depends => Expression,
+ Aspect_Refined_Global => Expression,
Aspect_Refined_Post => Expression,
Aspect_Refined_Pre => Expression,
Aspect_Relative_Deadline => Expression,
@@ -419,6 +423,8 @@ package Aspects is
Aspect_Pure_12 => Name_Pure_12,
Aspect_Pure_Function => Name_Pure_Function,
Aspect_Read => Name_Read,
+ Aspect_Refined_Depends => Name_Refined_Depends,
+ Aspect_Refined_Global => Name_Refined_Global,
Aspect_Refined_Post => Name_Refined_Post,
Aspect_Refined_Pre => Name_Refined_Pre,
Aspect_Relative_Deadline => Name_Relative_Deadline,
@@ -612,6 +618,8 @@ package Aspects is
Aspect_Pure_12 => Always_Delay,
Aspect_Pure_Function => Always_Delay,
Aspect_Read => Always_Delay,
+ Aspect_Refined_Depends => Always_Delay,
+ Aspect_Refined_Global => Always_Delay,
Aspect_Relative_Deadline => Always_Delay,
Aspect_Remote_Access_Type => Always_Delay,
Aspect_Remote_Call_Interface => Always_Delay,
@@ -703,7 +711,9 @@ package Aspects is
-- Sem_Prag if the aspects below are implemented by a pragma.
Aspect_On_Body_Or_Stub_OK : constant array (Aspect_Id) of Boolean :=
- (Aspect_Refined_Post => True,
+ (Aspect_Refined_Depends => True,
+ Aspect_Refined_Global => True,
+ Aspect_Refined_Post => True,
Aspect_Refined_Pre => True,
Aspect_SPARK_Mode => True,
Aspect_Warnings => True,
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index da7fa2d6b3a..fb53f1bb841 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -1065,7 +1065,7 @@ package body Einfo is
function Contract (Id : E) return N is
begin
pragma Assert
- (Ekind_In (Id, E_Entry, E_Entry_Family)
+ (Ekind_In (Id, E_Entry, E_Entry_Family, E_Subprogram_Body)
or else Is_Subprogram (Id)
or else Is_Generic_Subprogram (Id));
return Node24 (Id);
@@ -3651,7 +3651,7 @@ package body Einfo is
procedure Set_Contract (Id : E; V : N) is
begin
pragma Assert
- (Ekind_In (Id, E_Entry, E_Entry_Family, E_Void)
+ (Ekind_In (Id, E_Entry, E_Entry_Family, E_Subprogram_Body, E_Void)
or else Is_Subprogram (Id)
or else Is_Generic_Subprogram (Id));
Set_Node24 (Id, V);
@@ -9012,10 +9012,15 @@ package body Einfo is
when E_Entry |
E_Entry_Family |
+ E_Subprogram_Body |
Subprogram_Kind |
Generic_Subprogram_Kind =>
Write_Str ("Contract");
+ -- The Subprogram_Kind and Generic_Subrpogram_Kind entries
+ -- here are odd, since the assertions for [Set_]Contract do not
+ -- allow these possibilities ???
+
when others =>
Write_Str ("Field24???");
end case;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index d48544fdada..be89e27dca6 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -8489,6 +8489,1050 @@ package body Exp_Ch6 is
end Expand_Simple_Function_Return;
--------------------------------
+ -- Expand_Subprogram_Contract --
+ --------------------------------
+
+ procedure Expand_Subprogram_Contract
+ (N : Node_Id;
+ Spec_Id : Entity_Id;
+ Body_Id : Entity_Id)
+ is
+ procedure Add_Invariant_And_Predicate_Checks
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id;
+ Result : out Node_Id);
+ -- Process the result of function Subp_Id (if applicable) and all its
+ -- formals. Add invariant and predicate checks where applicable. The
+ -- routine appends all the checks to list Stmts. If Subp_Id denotes a
+ -- function, Result contains the entity of parameter _Result, to be
+ -- used in the creation of procedure _Postconditions.
+
+ procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
+ -- Append a node to a list. If there is no list, create a new one. When
+ -- the item denotes a pragma, it is added to the list only when it is
+ -- enabled.
+
+ procedure Build_Postconditions_Procedure
+ (Subp_Id : Entity_Id;
+ Stmts : List_Id;
+ Result : Entity_Id);
+ -- Create the body of procedure _Postconditions which handles various
+ -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
+ -- of statements to be checked on exit. Parameter Result is the entity
+ -- of parameter _Result when Subp_Id denotes a function.
+
+ function Build_Pragma_Check_Equivalent
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id := Empty;
+ Inher_Id : Entity_Id := Empty) return Node_Id;
+ -- Transform a [refined] pre- or postcondition denoted by Prag into an
+ -- equivalent pragma Check. When the pre- or postcondition is inherited,
+ -- the routine corrects the references of all formals of Inher_Id to
+ -- point to the formals of Subp_Id.
+
+ procedure Collect_Body_Postconditions (Stmts : in out List_Id);
+ -- Process all postconditions found in the declarations of the body. The
+ -- routine appends the pragma Check equivalents to list Stmts.
+
+ procedure Collect_Spec_Postconditions
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id);
+ -- Process all [inherited] postconditions of subprogram spec Subp_Id.
+ -- The routine appends the pragma Check equivalents to list Stmts.
+
+ procedure Collect_Spec_Preconditions (Subp_Id : Entity_Id);
+ -- Process all [inherited] preconditions of subprogram spec Subp_Id. The
+ -- routine prepends the pragma Check equivalents to the declarations of
+ -- the body.
+
+ procedure Prepend_To_Declarations (Item : Node_Id);
+ -- Prepend a single item to the declarations of the subprogram body
+
+ procedure Process_Contract_Cases
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id);
+ -- Process pragma Contract_Cases of subprogram spec Subp_Id. The routine
+ -- appends the expanded code to list Stmts.
+
+ ----------------------------------------
+ -- Add_Invariant_And_Predicate_Checks --
+ ----------------------------------------
+
+ procedure Add_Invariant_And_Predicate_Checks
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id;
+ Result : out Node_Id)
+ is
+ procedure Add_Invariant_Access_Checks (Id : Entity_Id);
+ -- Id denotes the return value of a function or a formal parameter.
+ -- Add an invariant check if the type of Id is access to a type with
+ -- invariants. The routine appends the generated code to Stmts.
+
+ function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
+ -- Determine whether type Typ can benefit from invariant checks. To
+ -- qualify, the type must have a non-null invariant procedure and
+ -- subprogram Subp_Id must appear visible from the point of view of
+ -- the type.
+
+ function Predicate_Checks_OK (Typ : Entity_Id) return Boolean;
+ -- Determine whether type Typ can benefit from predicate checks. To
+ -- qualify, the type must have at least one checked predicate.
+
+ ---------------------------------
+ -- Add_Invariant_Access_Checks --
+ ---------------------------------
+
+ procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Ref : Node_Id;
+ Typ : Entity_Id;
+
+ begin
+ Typ := Etype (Id);
+
+ if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
+ Typ := Designated_Type (Typ);
+
+ if Invariant_Checks_OK (Typ) then
+ Ref :=
+ Make_Explicit_Dereference (Loc,
+ Prefix => New_Occurrence_Of (Id, Loc));
+ Set_Etype (Ref, Typ);
+
+ -- Generate:
+ -- if <Id> /= null then
+ -- <invariant_call (<Ref>)>
+ -- end if;
+
+ Append_Enabled_Item
+ (Item =>
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Occurrence_Of (Id, Loc),
+ Right_Opnd => Make_Null (Loc)),
+ Then_Statements => New_List (
+ Make_Invariant_Call (Ref))),
+ List => Stmts);
+ end if;
+ end if;
+ end Add_Invariant_Access_Checks;
+
+ -------------------------
+ -- Invariant_Checks_OK --
+ -------------------------
+
+ function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
+ function Has_Null_Body (Proc_Id : Entity_Id) return Boolean;
+ -- Determine whether the body of procedure Proc_Id contains a sole
+ -- null statement, possibly followed by an optional return.
+
+ function Has_Public_Visibility_Of_Subprogram return Boolean;
+ -- Determine whether type Typ has public visibility of subprogram
+ -- Subp_Id.
+
+ -------------------
+ -- Has_Null_Body --
+ -------------------
+
+ function Has_Null_Body (Proc_Id : Entity_Id) return Boolean is
+ Body_Id : Entity_Id;
+ Decl : Node_Id;
+ Spec : Node_Id;
+ Stmt1 : Node_Id;
+ Stmt2 : Node_Id;
+
+ begin
+ Spec := Parent (Proc_Id);
+ Decl := Parent (Spec);
+
+ -- Retrieve the entity of the invariant procedure body
+
+ if Nkind (Spec) = N_Procedure_Specification
+ and then Nkind (Decl) = N_Subprogram_Declaration
+ then
+ Body_Id := Corresponding_Body (Decl);
+
+ -- The body acts as a spec
+
+ else
+ Body_Id := Proc_Id;
+ end if;
+
+ -- The body will be generated later
+
+ if No (Body_Id) then
+ return False;
+ end if;
+
+ Spec := Parent (Body_Id);
+ Decl := Parent (Spec);
+
+ pragma Assert
+ (Nkind (Spec) = N_Procedure_Specification
+ and then Nkind (Decl) = N_Subprogram_Body);
+
+ Stmt1 := First (Statements (Handled_Statement_Sequence (Decl)));
+
+ -- Look for a null statement followed by an optional return
+ -- statement.
+
+ if Nkind (Stmt1) = N_Null_Statement then
+ Stmt2 := Next (Stmt1);
+
+ if Present (Stmt2) then
+ return Nkind (Stmt2) = N_Simple_Return_Statement;
+ else
+ return True;
+ end if;
+ end if;
+
+ return False;
+ end Has_Null_Body;
+
+ -----------------------------------------
+ -- Has_Public_Visibility_Of_Subprogram --
+ -----------------------------------------
+
+ function Has_Public_Visibility_Of_Subprogram return Boolean is
+ Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
+ Vis_Decls : constant List_Id :=
+ Visible_Declarations (Specification
+ (Unit_Declaration_Node (Scope (Typ))));
+ begin
+ -- An Initialization procedure must be considered visible even
+ -- though it is internally generated.
+
+ if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
+ return True;
+
+ -- Internally generated code is never publicly visible except
+ -- for a subprogram that is the implementation of an expression
+ -- function. In that case the visibility is determined by the
+ -- last check.
+
+ elsif not Comes_From_Source (Subp_Decl)
+ and then
+ (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
+ or else not
+ Comes_From_Source (Defining_Entity (Subp_Decl)))
+ then
+ return False;
+
+ -- Determine whether the subprogram is declared in the visible
+ -- declarations of the package containing the type.
+
+ else
+ return List_Containing (Subp_Decl) = Vis_Decls;
+ end if;
+ end Has_Public_Visibility_Of_Subprogram;
+
+ -- Start of processing for Invariant_Checks_OK
+
+ begin
+ return
+ Has_Invariants (Typ)
+ and then Present (Invariant_Procedure (Typ))
+ and then not Has_Null_Body (Invariant_Procedure (Typ))
+ and then Has_Public_Visibility_Of_Subprogram;
+ end Invariant_Checks_OK;
+
+ -------------------------
+ -- Predicate_Checks_OK --
+ -------------------------
+
+ function Predicate_Checks_OK (Typ : Entity_Id) return Boolean is
+ function Has_Checked_Predicate return Boolean;
+ -- Determine whether type Typ has or inherits at least one
+ -- predicate aspect or pragma, for which the applicable policy is
+ -- Checked.
+
+ ---------------------------
+ -- Has_Checked_Predicate --
+ ---------------------------
+
+ function Has_Checked_Predicate return Boolean is
+ Anc : Entity_Id;
+ Pred : Node_Id;
+
+ begin
+ -- Climb the ancestor type chain staring from the input. This
+ -- is done because the input type may lack aspect/pragma
+ -- predicate and simply inherit those from its ancestor.
+
+ -- Note that predicate pragmas include all three cases of
+ -- predicate aspects (Predicate, Dynamic_Predicate,
+ -- Static_Predicate), so this routine checks for all three
+ -- cases.
+
+ Anc := Typ;
+ while Present (Anc) loop
+ Pred := Get_Pragma (Anc, Pragma_Predicate);
+
+ if Present (Pred) and then not Is_Ignored (Pred) then
+ return True;
+ end if;
+
+ Anc := Nearest_Ancestor (Anc);
+ end loop;
+
+ return False;
+ end Has_Checked_Predicate;
+
+ -- Start of processing for Predicate_Checks_OK
+
+ begin
+ return
+ Has_Predicates (Typ)
+ and then Present (Predicate_Function (Typ))
+ and then Has_Checked_Predicate;
+ end Predicate_Checks_OK;
+
+ -- Local variables
+
+ Loc : constant Source_Ptr := Sloc (N);
+ Formal : Entity_Id;
+ Typ : Entity_Id;
+
+ -- Start of processing for Add_Invariant_And_Predicate_Checks
+
+ begin
+ Result := Empty;
+
+ -- Do not generate any checks if no code is being generated
+
+ if not Expander_Active then
+ return;
+ end if;
+
+ -- Process the result of a function
+
+ if Ekind_In (Subp_Id, E_Function, E_Generic_Function) then
+ Typ := Etype (Subp_Id);
+
+ -- Generate _Result which is used in procedure _Postconditions to
+ -- verify the return value.
+
+ Result := Make_Defining_Identifier (Loc, Name_uResult);
+ Set_Etype (Result, Typ);
+
+ -- Add an invariant check when the return type has invariants and
+ -- the related function is visible to the outside.
+
+ if Invariant_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
+ List => Stmts);
+ end if;
+
+ -- Add an invariant check when the return type is an access to a
+ -- type with invariants.
+
+ Add_Invariant_Access_Checks (Result);
+ end if;
+
+ -- Add invariant and predicates for all formals that qualify
+
+ Formal := First_Formal (Subp_Id);
+ while Present (Formal) loop
+ Typ := Etype (Formal);
+
+ if Ekind (Formal) /= E_In_Parameter
+ or else Is_Access_Type (Typ)
+ then
+ if Invariant_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
+ List => Stmts);
+ end if;
+
+ Add_Invariant_Access_Checks (Formal);
+
+ if Predicate_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Predicate_Check
+ (Typ, New_Reference_To (Formal, Loc)),
+ List => Stmts);
+ end if;
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+ end Add_Invariant_And_Predicate_Checks;
+
+ -------------------------
+ -- Append_Enabled_Item --
+ -------------------------
+
+ procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
+ begin
+ -- Do not chain ignored or disabled pragmas
+
+ if Nkind (Item) = N_Pragma
+ and then (Is_Ignored (Item) or else Is_Disabled (Item))
+ then
+ null;
+
+ -- Add the item
+
+ else
+ if No (List) then
+ List := New_List;
+ end if;
+
+ Append (Item, List);
+ end if;
+ end Append_Enabled_Item;
+
+ ------------------------------------
+ -- Build_Postconditions_Procedure --
+ ------------------------------------
+
+ procedure Build_Postconditions_Procedure
+ (Subp_Id : Entity_Id;
+ Stmts : List_Id;
+ Result : Entity_Id)
+ is
+ procedure Insert_After_Last_Declaration (Stmt : Node_Id);
+ -- Insert node Stmt after the last declaration of the subprogram body
+
+ -----------------------------------
+ -- Insert_After_Last_Declaration --
+ -----------------------------------
+
+ procedure Insert_After_Last_Declaration (Stmt : Node_Id) is
+ Decls : List_Id := Declarations (N);
+
+ begin
+ -- Ensure that the body has a declaration list
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (N, Decls);
+ end if;
+
+ Append_To (Decls, Stmt);
+ end Insert_After_Last_Declaration;
+
+ -- Local variables
+
+ Loc : constant Source_Ptr := Sloc (N);
+ Params : List_Id := No_List;
+ Proc_Id : Entity_Id;
+
+ -- Start of processing for Build_Postconditions_Procedure
+
+ begin
+ -- Do not create the routine if no code is being generated
+
+ if not Expander_Active then
+ return;
+
+ -- Nothing to do if there are no actions to check on exit
+
+ elsif No (Stmts) then
+ return;
+ end if;
+
+ Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
+
+ -- The related subprogram is a function, create the specification of
+ -- parameter _Result.
+
+ if Present (Result) then
+ Params := New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Result,
+ Parameter_Type =>
+ New_Reference_To (Etype (Result), Loc)));
+ end if;
+
+ -- Insert _Postconditions after the last declaration of the body.
+ -- This ensures that the body will not cause any premature freezing
+ -- as it may mention types:
+
+ -- procedure Proc (Obj : Array_Typ) is
+ -- procedure _postconditions is
+ -- begin
+ -- ... Obj ...
+ -- end _postconditions;
+
+ -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
+ -- begin
+
+ -- In the example above, Obj is of type T but the incorrect placement
+ -- of _Postconditions will cause a crash in gigi due to an out of
+ -- order reference. The body of _Postconditions must be placed after
+ -- the declaration of Temp to preserve correct visibility.
+
+ Insert_After_Last_Declaration (
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Proc_Id,
+ Parameter_Specifications => Params),
+
+ Declarations => Empty_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
+
+ -- Set the attributes of the related subprogram to capture the
+ -- generated procedure.
+
+ if Ekind_In (Subp_Id, E_Generic_Procedure, E_Procedure) then
+ Set_Postcondition_Proc (Subp_Id, Proc_Id);
+ end if;
+
+ Set_Has_Postconditions (Subp_Id);
+ end Build_Postconditions_Procedure;
+
+ -----------------------------------
+ -- Build_Pragma_Check_Equivalent --
+ -----------------------------------
+
+ function Build_Pragma_Check_Equivalent
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id := Empty;
+ Inher_Id : Entity_Id := Empty) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (Prag);
+ Prag_Nam : constant Name_Id := Pragma_Name (Prag);
+ Check_Prag : Node_Id;
+ Formals_Map : Elist_Id;
+ Inher_Formal : Entity_Id;
+ Msg_Arg : Node_Id;
+ Nam : Name_Id;
+ Subp_Formal : Entity_Id;
+
+ begin
+ Formals_Map := No_Elist;
+
+ -- When the pre- or postcondition is inherited, map the formals of
+ -- the inherited subprogram to those of the current subprogram.
+
+ if Present (Inher_Id) then
+ pragma Assert (Present (Subp_Id));
+
+ Formals_Map := New_Elmt_List;
+
+ -- Create a relation <inherited formal> => <subprogram formal>
+
+ Inher_Formal := First_Formal (Inher_Id);
+ Subp_Formal := First_Formal (Subp_Id);
+ while Present (Inher_Formal) and then Present (Subp_Formal) loop
+ Append_Elmt (Inher_Formal, Formals_Map);
+ Append_Elmt (Subp_Formal, Formals_Map);
+
+ Next_Formal (Inher_Formal);
+ Next_Formal (Subp_Formal);
+ end loop;
+ end if;
+
+ -- Copy the original pragma while performing substitutions (if
+ -- applicable).
+
+ Check_Prag :=
+ New_Copy_Tree
+ (Source => Prag,
+ Map => Formals_Map,
+ New_Scope => Current_Scope);
+
+ -- Mark the pragma as being internally generated and reset the
+ -- Analyzed flag.
+
+ Set_Comes_From_Source (Check_Prag, False);
+ Set_Analyzed (Check_Prag, False);
+
+ -- For a postcondition pragma within a generic, preserve the pragma
+ -- for later expansion. This is also used when an error was detected,
+ -- thus setting Expander_Active to False.
+
+ if Prag_Nam = Name_Postcondition and then not Expander_Active then
+ return Check_Prag;
+ end if;
+
+ if Present (Corresponding_Aspect (Prag)) then
+ Nam := Chars (Identifier (Corresponding_Aspect (Prag)));
+ else
+ Nam := Prag_Nam;
+ end if;
+
+ -- Convert the copy into pragma Check by correcting the name and
+ -- adding a check_kind argument.
+
+ Set_Pragma_Identifier
+ (Check_Prag, Make_Identifier (Loc, Name_Check));
+
+ Prepend_To (Pragma_Argument_Associations (Check_Prag),
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Nam)));
+
+ -- Update the error message when the pragma is inherited
+
+ if Present (Inher_Id) then
+ Msg_Arg := Last (Pragma_Argument_Associations (Check_Prag));
+
+ if Chars (Msg_Arg) = Name_Message then
+ String_To_Name_Buffer (Strval (Expression (Msg_Arg)));
+
+ -- Insert "inherited" to improve the error message
+
+ if Name_Buffer (1 .. 8) = "failed p" then
+ Insert_Str_In_Name_Buffer ("inherited ", 8);
+ Set_Strval (Expression (Msg_Arg), String_From_Name_Buffer);
+ end if;
+ end if;
+ end if;
+
+ return Check_Prag;
+ end Build_Pragma_Check_Equivalent;
+
+ ---------------------------------
+ -- Collect_Body_Postconditions --
+ ---------------------------------
+
+ procedure Collect_Body_Postconditions (Stmts : in out List_Id) is
+ procedure Collect_Body_Postconditions_Of_Kind (Post_Nam : Name_Id);
+ -- Process postconditions of a particular kind denoted by Post_Nam
+
+ -----------------------------------------
+ -- Collect_Body_Postconditions_Of_Kind --
+ -----------------------------------------
+
+ procedure Collect_Body_Postconditions_Of_Kind (Post_Nam : Name_Id) is
+ Check_Prag : Node_Id;
+ Decl : Node_Id;
+
+ begin
+ pragma Assert (Nam_In (Post_Nam, Name_Postcondition,
+ Name_Refined_Post));
+
+ -- Inspect the declarations of the subprogram body looking for a
+ -- pragma that matches the desired name.
+
+ Decl := First (Declarations (N));
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Pragma then
+ if Pragma_Name (Decl) = Post_Nam then
+ Analyze (Decl);
+ Check_Prag := Build_Pragma_Check_Equivalent (Decl);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for
+ -- later.
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Decl) then
+ null;
+
+ -- Postconditions in bodies are usually grouped at the top of
+ -- the declarations. There is no point in inspecting the whole
+ -- source list.
+
+ else
+ exit;
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Collect_Body_Postconditions_Of_Kind;
+
+ -- Start of processing for Collect_Body_Postconditions
+
+ begin
+ Collect_Body_Postconditions_Of_Kind (Name_Refined_Post);
+ Collect_Body_Postconditions_Of_Kind (Name_Postcondition);
+ end Collect_Body_Postconditions;
+
+ ---------------------------------
+ -- Collect_Spec_Postconditions --
+ ---------------------------------
+
+ procedure Collect_Spec_Postconditions
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id)
+ is
+ Inher_Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Check_Prag : Node_Id;
+ Prag : Node_Id;
+ Inher_Subp_Id : Entity_Id;
+
+ begin
+ -- Process the contract of the spec
+
+ Prag := Pre_Post_Conditions (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Postcondition then
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for later
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Process the contracts of all inherited subprograms, looking for
+ -- class-wide postconditions.
+
+ for Index in Inher_Subps'Range loop
+ Inher_Subp_Id := Inher_Subps (Index);
+
+ Prag := Pre_Post_Conditions (Contract (Inher_Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Postcondition
+ and then Class_Present (Prag)
+ then
+ Check_Prag :=
+ Build_Pragma_Check_Equivalent
+ (Prag => Prag,
+ Subp_Id => Subp_Id,
+ Inher_Id => Inher_Subp_Id);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for later
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end loop;
+ end Collect_Spec_Postconditions;
+
+ --------------------------------
+ -- Collect_Spec_Preconditions --
+ --------------------------------
+
+ procedure Collect_Spec_Preconditions (Subp_Id : Entity_Id) is
+ procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
+ -- Merge two class-wide preconditions by "or else"-ing them. The
+ -- changes are accumulated in parameter Into. Update the error
+ -- message of Into.
+
+ -------------------------
+ -- Merge_Preconditions --
+ -------------------------
+
+ procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
+ function Expression_Arg (Prag : Node_Id) return Node_Id;
+ -- Return the boolean expression argument of a precondition while
+ -- updating its parenteses count for the subsequent merge.
+
+ function Message_Arg (Prag : Node_Id) return Node_Id;
+ -- Return the message argument of a precondition
+
+ --------------------
+ -- Expression_Arg --
+ --------------------
+
+ function Expression_Arg (Prag : Node_Id) return Node_Id is
+ Args : constant List_Id := Pragma_Argument_Associations (Prag);
+ Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
+
+ begin
+ if Paren_Count (Arg) = 0 then
+ Set_Paren_Count (Arg, 1);
+ end if;
+
+ return Arg;
+ end Expression_Arg;
+
+ -----------------
+ -- Message_Arg --
+ -----------------
+
+ function Message_Arg (Prag : Node_Id) return Node_Id is
+ Args : constant List_Id := Pragma_Argument_Associations (Prag);
+ begin
+ return Get_Pragma_Arg (Last (Args));
+ end Message_Arg;
+
+ -- Local variables
+
+ From_Expr : constant Node_Id := Expression_Arg (From);
+ From_Msg : constant Node_Id := Message_Arg (From);
+ Into_Expr : constant Node_Id := Expression_Arg (Into);
+ Into_Msg : constant Node_Id := Message_Arg (Into);
+ Loc : constant Source_Ptr := Sloc (Into);
+
+ -- Start of processing for Merge_Preconditions
+
+ begin
+ -- Merge the two preconditions by "or else"-ing them
+
+ Rewrite (Into_Expr,
+ Make_Or_Else (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+
+ -- Merge the two error messages to produce a single message of the
+ -- form:
+
+ -- failed precondition from ...
+ -- also failed inherited precondition from ...
+
+ if not Exception_Locations_Suppressed then
+ Start_String (Strval (Into_Msg));
+ Store_String_Char (ASCII.LF);
+ Store_String_Chars (" also ");
+ Store_String_Chars (Strval (From_Msg));
+
+ Set_Strval (Into_Msg, End_String);
+ end if;
+ end Merge_Preconditions;
+
+ -- Local variables
+
+ Inher_Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Check_Prag : Node_Id;
+ Class_Pre : Node_Id := Empty;
+ Inher_Subp_Id : Entity_Id;
+ Prag : Node_Id;
+
+ -- Start of processing for Collect_Spec_Preconditions
+
+ begin
+ -- Process the contract of the spec
+
+ Prag := Pre_Post_Conditions (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Precondition then
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
+ -- Save the sole class-wide precondition (if any) for the next
+ -- step where it will be merged with inherited preconditions.
+
+ if Class_Present (Prag) then
+ Class_Pre := Check_Prag;
+
+ -- Accumulate the corresponding Check pragmas to the top of the
+ -- declarations. Prepending the items ensures that they will
+ -- be evaluated in their original order.
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Process the contracts of all inherited subprograms, looking for
+ -- class-wide preconditions.
+
+ for Index in Inher_Subps'Range loop
+ Inher_Subp_Id := Inher_Subps (Index);
+
+ Prag := Pre_Post_Conditions (Contract (Inher_Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Precondition
+ and then Class_Present (Prag)
+ then
+ Check_Prag :=
+ Build_Pragma_Check_Equivalent
+ (Prag => Prag,
+ Subp_Id => Subp_Id,
+ Inher_Id => Inher_Subp_Id);
+
+ -- The spec or an inherited subprogram already yielded a
+ -- class-wide precondition. Merge the existing precondition
+ -- with the current one using "or else".
+
+ if Present (Class_Pre) then
+ Merge_Preconditions (Check_Prag, Class_Pre);
+ else
+ Class_Pre := Check_Prag;
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end loop;
+
+ -- Add the merged class-wide preconditions (if any)
+
+ if Present (Class_Pre) then
+ Prepend_To_Declarations (Class_Pre);
+ end if;
+ end Collect_Spec_Preconditions;
+
+ -----------------------------
+ -- Prepend_To_Declarations --
+ -----------------------------
+
+ procedure Prepend_To_Declarations (Item : Node_Id) is
+ Decls : List_Id := Declarations (N);
+
+ begin
+ -- Ensure that the body has a declarative list
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Item);
+ end Prepend_To_Declarations;
+
+ ----------------------------
+ -- Process_Contract_Cases --
+ ----------------------------
+
+ procedure Process_Contract_Cases
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id)
+ is
+ Prag : Node_Id;
+
+ begin
+ -- Do not build the Contract_Cases circuitry if no code is being
+ -- generated.
+
+ if not Expander_Active then
+ null;
+ end if;
+
+ Prag := Contract_Test_Cases (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Contract_Cases then
+ Expand_Contract_Cases
+ (CCs => Prag,
+ Subp_Id => Subp_Id,
+ Decls => Declarations (N),
+ Stmts => Stmts);
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end Process_Contract_Cases;
+
+ -- Local variables
+
+ Post_Stmts : List_Id := No_List;
+ Result : Entity_Id;
+ Subp_Id : Entity_Id;
+
+ -- Start of processing for Expand_Subprogram_Contract
+
+ begin
+ if Present (Spec_Id) then
+ Subp_Id := Spec_Id;
+ else
+ Subp_Id := Body_Id;
+ end if;
+
+ -- Do not process a predicate function as its body will end up with a
+ -- recursive call to itself and blow up the stack.
+
+ if Ekind (Subp_Id) = E_Function
+ and then Is_Predicate_Function (Subp_Id)
+ then
+ return;
+
+ -- Do not process TSS subprograms
+
+ elsif Get_TSS_Name (Subp_Id) /= TSS_Null then
+ return;
+ end if;
+
+ -- The expansion of a subprogram contract involves the relocation of
+ -- various contract assertions to the declarations of the body in a
+ -- particular order. The order is as follows:
+
+ -- function Example (...) return ... is
+ -- procedure _Postconditions (...) is
+ -- begin
+ -- <refined postconditions from body>
+ -- <postconditions from body>
+ -- <postconditions from spec>
+ -- <inherited postconditions>
+ -- <contract cases>
+ -- <invariant check of function result (if applicable)>
+ -- <invariant and predicate checks of parameters>
+ -- end _Postconditions;
+
+ -- <inherited preconditions>
+ -- <preconditions from spec>
+ -- <preconditions from body>
+ -- <refined preconditions from body>
+
+ -- <source declarations>
+ -- begin
+ -- <source statements>
+
+ -- _Preconditions (Result);
+ -- return Result;
+ -- end Example;
+
+ -- Routine _Postconditions holds all contract assertions that must be
+ -- verified on exit from the related routine.
+
+ -- Collect all [inherited] preconditions from the spec, transform them
+ -- into Check pragmas and add them to the declarations of the body in
+ -- the order outlined above.
+
+ if Present (Spec_Id) then
+ Collect_Spec_Preconditions (Spec_Id);
+ end if;
+
+ -- Transform all [refined] postconditions of the body into Check
+ -- pragmas. The resulting pragmas are accumulated in list Post_Stmts.
+
+ Collect_Body_Postconditions (Post_Stmts);
+
+ -- Transform all [inherited] postconditions from the spec into Check
+ -- pragmas. The resulting pragmas are accumulated in list Post_Stmts.
+
+ if Present (Spec_Id) then
+ Collect_Spec_Postconditions (Spec_Id, Post_Stmts);
+
+ -- Transform pragma Contract_Cases from the spec into its circuitry
+
+ Process_Contract_Cases (Spec_Id, Post_Stmts);
+ end if;
+
+ -- Apply invariant and predicate checks on the result of a function (if
+ -- applicable) and all formals. The resulting checks are accumulated in
+ -- list Post_Stmts.
+
+ Add_Invariant_And_Predicate_Checks (Subp_Id, Post_Stmts, Result);
+
+ -- Construct procedure _Postconditions
+
+ Build_Postconditions_Procedure (Subp_Id, Post_Stmts, Result);
+ end Expand_Subprogram_Contract;
+
+ --------------------------------
-- Is_Build_In_Place_Function --
--------------------------------
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index f9829f52b34..02cca2401df 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -82,6 +82,18 @@ package Exp_Ch6 is
-- Subp_Id's body. All generated code is added to list Stmts. If Stmts is
-- empty, a new list is created.
+ procedure Expand_Subprogram_Contract
+ (N : Node_Id;
+ Spec_Id : Entity_Id;
+ Body_Id : Entity_Id);
+ -- Expand the contracts of a subprogram body and its correspoding spec (if
+ -- any). This routine processes all [refined] pre- and postconditions as
+ -- well as Contract_Cases, invariants and predicates. N is the body of the
+ -- subprogram. Spec_Id denotes the entity of its specification. Body_Id
+ -- denotes the entity of the subprogram body. This routine is not a "pure"
+ -- expansion mechanism as it is invoked during analysis and may perform
+ -- actions for generic subprograms or set up contract assertions for ASIS.
+
procedure Freeze_Subprogram (N : Node_Id);
-- generate the appropriate expansions related to Subprogram freeze
-- nodes (e.g. the filling of the corresponding Dispatch Table for
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 85ebe3bdeb7..e8bea1fced3 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1250,6 +1250,8 @@ begin
Pragma_Pure_12 |
Pragma_Pure_Function |
Pragma_Queuing_Policy |
+ Pragma_Refined_Depends |
+ Pragma_Refined_Global |
Pragma_Refined_Post |
Pragma_Refined_Pre |
Pragma_Relative_Deadline |
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index e307e87ec2c..30c5bc4adb8 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -1928,6 +1928,20 @@ package body Sem_Ch13 is
Expression => Relocate_Node (Expr))),
Pragma_Name => Name_SPARK_Mode);
+ -- Refined_Depends
+
+ -- ??? To be implemented
+
+ when Aspect_Refined_Depends =>
+ null;
+
+ -- Refined_Global
+
+ -- ??? To be implemented
+
+ when Aspect_Refined_Global =>
+ null;
+
-- Refined_Post
when Aspect_Refined_Post =>
@@ -7962,6 +7976,8 @@ package body Sem_Ch13 is
Aspect_Postcondition |
Aspect_Pre |
Aspect_Precondition |
+ Aspect_Refined_Depends |
+ Aspect_Refined_Global |
Aspect_Refined_Post |
Aspect_Refined_Pre |
Aspect_SPARK_Mode |
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index e900cfaa153..1e6abf24cec 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -2056,28 +2056,31 @@ package body Sem_Ch3 is
--------------------------
procedure Analyze_Declarations (L : List_Id) is
- D : Node_Id;
- Freeze_From : Entity_Id := Empty;
- Next_Node : Node_Id;
+ Decl : Node_Id;
- procedure Adjust_D;
- -- Adjust D not to include implicit label declarations, since these
+ procedure Adjust_Decl;
+ -- Adjust Decl not to include implicit label declarations, since these
-- have strange Sloc values that result in elaboration check problems.
-- (They have the sloc of the label as found in the source, and that
-- is ahead of the current declarative part).
- --------------
- -- Adjust_D --
- --------------
+ -----------------
+ -- Adjust_Decl --
+ -----------------
- procedure Adjust_D is
+ procedure Adjust_Decl is
begin
- while Present (Prev (D))
- and then Nkind (D) = N_Implicit_Label_Declaration
+ while Present (Prev (Decl))
+ and then Nkind (Decl) = N_Implicit_Label_Declaration
loop
- Prev (D);
+ Prev (Decl);
end loop;
- end Adjust_D;
+ end Adjust_Decl;
+
+ -- Local variables
+
+ Freeze_From : Entity_Id := Empty;
+ Next_Decl : Node_Id;
-- Start of processing for Analyze_Declarations
@@ -2086,23 +2089,23 @@ package body Sem_Ch3 is
Check_Later_Vs_Basic_Declarations (L, During_Parsing => False);
end if;
- D := First (L);
- while Present (D) loop
+ Decl := First (L);
+ while Present (Decl) loop
-- Package spec cannot contain a package declaration in SPARK
- if Nkind (D) = N_Package_Declaration
+ if Nkind (Decl) = N_Package_Declaration
and then Nkind (Parent (L)) = N_Package_Specification
then
Check_SPARK_Restriction
("package specification cannot contain a package declaration",
- D);
+ Decl);
end if;
-- Complete analysis of declaration
- Analyze (D);
- Next_Node := Next (D);
+ Analyze (Decl);
+ Next_Decl := Next (Decl);
if No (Freeze_From) then
Freeze_From := First_Entity (Current_Scope);
@@ -2124,7 +2127,7 @@ package body Sem_Ch3 is
-- be a freeze point once delayed freezing of bodies is implemented.
-- (This is needed in any case for early instantiations ???).
- if No (Next_Node) then
+ if No (Next_Decl) then
if Nkind_In (Parent (L), N_Component_List,
N_Task_Definition,
N_Protected_Definition)
@@ -2136,8 +2139,8 @@ package body Sem_Ch3 is
Freeze_From := First_Entity (Current_Scope);
end if;
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
elsif Scope (Current_Scope) /= Standard_Standard
@@ -2150,8 +2153,8 @@ package body Sem_Ch3 is
or else No (Private_Declarations (Parent (L)))
or else Is_Empty_List (Private_Declarations (Parent (L)))
then
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
end if;
@@ -2170,44 +2173,39 @@ package body Sem_Ch3 is
-- care to attach the bodies at a proper place in the tree so as to
-- not cause unwanted freezing at that point.
- elsif not Analyzed (Next_Node)
- and then (Nkind_In (Next_Node, N_Subprogram_Body,
+ elsif not Analyzed (Next_Decl)
+ and then (Nkind_In (Next_Decl, N_Subprogram_Body,
N_Entry_Body,
N_Package_Body,
N_Protected_Body,
N_Task_Body)
or else
- Nkind (Next_Node) in N_Body_Stub)
+ Nkind (Next_Decl) in N_Body_Stub)
then
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
end if;
- D := Next_Node;
+ Decl := Next_Decl;
end loop;
- -- One more thing to do, we need to scan the declarations to check for
- -- any precondition/postcondition pragmas (Pre/Post aspects have by this
- -- stage been converted into corresponding pragmas). It is at this point
- -- that we analyze the expressions in such pragmas, to implement the
- -- delayed visibility requirement.
+ -- Analyze the contracts of a subprogram declaration or a body now due
+ -- to delayed visibility requirements of aspects.
- declare
- Decl : Node_Id;
- Subp_Id : Entity_Id;
+ Decl := First (L);
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Subprogram_Body then
+ Analyze_Subprogram_Body_Contract
+ (Defining_Unit_Name (Specification (Decl)));
- begin
- Decl := First (L);
- while Present (Decl) loop
- if Nkind (Decl) = N_Subprogram_Declaration then
- Subp_Id := Defining_Unit_Name (Specification (Decl));
- Analyze_Subprogram_Contract (Subp_Id);
- end if;
+ elsif Nkind (Decl) = N_Subprogram_Declaration then
+ Analyze_Subprogram_Contract
+ (Defining_Unit_Name (Specification (Decl)));
+ end if;
- Next (Decl);
- end loop;
- end;
+ Next (Decl);
+ end loop;
end Analyze_Declarations;
-----------------------------------
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index e313f3518d8..462a7f1732f 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -212,17 +212,6 @@ package body Sem_Ch6 is
-- Create the declaration for an inequality operator that is implicitly
-- created by a user-defined equality operator that yields a boolean.
- procedure Process_PPCs
- (N : Node_Id;
- Spec_Id : Entity_Id;
- Body_Id : Entity_Id);
- -- Called from Analyze[_Generic]_Subprogram_Body to deal with scanning post
- -- conditions for the body and assembling and inserting the _postconditions
- -- procedure. N is the node for the subprogram body and Body_Id/Spec_Id are
- -- the entities for the body and separate spec (if there is no separate
- -- spec, Spec_Id is Empty). Note that invariants and predicates may also
- -- provide postconditions, and are also handled in this procedure.
-
procedure Set_Formal_Validity (Formal_Id : Entity_Id);
-- Formal_Id is an formal parameter entity. This procedure deals with
-- setting the proper validity status for this entity, which depends on
@@ -1120,7 +1109,7 @@ package body Sem_Ch6 is
-- Visible generic entity is callable within its own body
Set_Ekind (Gen_Id, Ekind (Body_Id));
- Set_Contract (Body_Id, Empty);
+ Set_Contract (Body_Id, Make_Contract (Sloc (Body_Id)));
Set_Ekind (Body_Id, E_Subprogram_Body);
Set_Convention (Body_Id, Convention (Gen_Id));
Set_Is_Obsolescent (Body_Id, Is_Obsolescent (Gen_Id));
@@ -1156,13 +1145,14 @@ package body Sem_Ch6 is
Set_Actual_Subtypes (N, Current_Scope);
- -- Deal with preconditions and postconditions. In formal verification
- -- mode, we keep pre- and postconditions attached to entities rather
- -- than inserted in the code, in order to facilitate a distinct
- -- treatment for them.
+ -- Deal with [refined] preconditions, postconditions, Contract_Cases,
+ -- invariants and predicates associated with the body and its spec.
+ -- Note that this is not pure expansion as Expand_Subprogram_Contract
+ -- prepares the contract assertions for generic subprograms or for
+ -- ASIS. Do not generate contract checks in SPARK mode.
if not SPARK_Mode then
- Process_PPCs (N, Gen_Id, Body_Id);
+ Expand_Subprogram_Contract (N, Gen_Id, Body_Id);
end if;
-- If the generic unit carries pre- or post-conditions, copy them
@@ -1981,6 +1971,18 @@ package body Sem_Ch6 is
end if;
end Analyze_Subprogram_Body;
+ --------------------------------------
+ -- Analyze_Subprogram_Body_Contract --
+ --------------------------------------
+
+ -- ??? To be implemented
+
+ procedure Analyze_Subprogram_Body_Contract (Subp : Entity_Id) is
+ pragma Unreferenced (Subp);
+ begin
+ null;
+ end Analyze_Subprogram_Body_Contract;
+
------------------------------------
-- Analyze_Subprogram_Body_Helper --
------------------------------------
@@ -2933,7 +2935,7 @@ package body Sem_Ch6 is
end if;
Set_Corresponding_Body (Unit_Declaration_Node (Spec_Id), Body_Id);
- Set_Contract (Body_Id, Empty);
+ Set_Contract (Body_Id, Make_Contract (Sloc (Body_Id)));
Set_Ekind (Body_Id, E_Subprogram_Body);
Set_Scope (Body_Id, Scope (Spec_Id));
Set_Is_Obsolescent (Body_Id, Is_Obsolescent (Spec_Id));
@@ -3117,13 +3119,14 @@ package body Sem_Ch6 is
HSS := Handled_Statement_Sequence (N);
Set_Actual_Subtypes (N, Current_Scope);
- -- Deal with preconditions and postconditions. In formal verification
- -- mode, we keep pre- and postconditions attached to entities rather
- -- than inserted in the code, in order to facilitate a distinct
- -- treatment for them.
+ -- Deal with [refined] preconditions, postconditions, Contract_Cases,
+ -- invariants and predicates associated with the body and its spec.
+ -- Note that this is not pure expansion as Expand_Subprogram_Contract
+ -- prepares the contract assertions for generic subprograms or for ASIS.
+ -- Do not generate contract checks in SPARK mode.
if not SPARK_Mode then
- Process_PPCs (N, Spec_Id, Body_Id);
+ Expand_Subprogram_Contract (N, Spec_Id, Body_Id);
end if;
-- Add a declaration for the Protection object, renaming declarations
@@ -3535,6 +3538,7 @@ package body Sem_Ch6 is
Items : constant Node_Id := Contract (Subp);
Error_CCase : Node_Id;
Error_Post : Node_Id;
+ Nam : Name_Id;
Prag : Node_Id;
-- Start of processing for Analyze_Subprogram_Contract
@@ -3549,7 +3553,7 @@ package body Sem_Ch6 is
Prag := Pre_Post_Conditions (Items);
while Present (Prag) loop
- Analyze_PPC_In_Decl_Part (Prag, Subp);
+ Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Subp);
-- Verify whether a postcondition mentions attribute 'Result and
-- its expression introduces a post-state.
@@ -3567,7 +3571,9 @@ package body Sem_Ch6 is
Prag := Contract_Test_Cases (Items);
while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Contract_Cases then
+ Nam := Pragma_Name (Prag);
+
+ if Nam = Name_Contract_Cases then
Analyze_Contract_Cases_In_Decl_Part (Prag);
-- Verify whether contract-cases mention attribute 'Result and
@@ -3581,7 +3587,7 @@ package body Sem_Ch6 is
end if;
else
- pragma Assert (Pragma_Name (Prag) = Name_Test_Case);
+ pragma Assert (Nam = Name_Test_Case);
Analyze_Test_Case_In_Decl_Part (Prag, Subp);
end if;
@@ -3592,10 +3598,12 @@ package body Sem_Ch6 is
Prag := Classifications (Contract (Subp));
while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Depends then
+ Nam := Pragma_Name (Prag);
+
+ if Nam = Name_Depends then
Analyze_Depends_In_Decl_Part (Prag);
else
- pragma Assert (Pragma_Name (Prag) = Name_Global);
+ pragma Assert (Nam = Name_Global);
Analyze_Global_In_Decl_Part (Prag);
end if;
@@ -11248,867 +11256,6 @@ package body Sem_Ch6 is
end if;
end Process_Formals;
- ------------------
- -- Process_PPCs --
- ------------------
-
- procedure Process_PPCs
- (N : Node_Id;
- Spec_Id : Entity_Id;
- Body_Id : Entity_Id)
- is
- Loc : constant Source_Ptr := Sloc (N);
- Prag : Node_Id;
- Parms : List_Id;
-
- Designator : Entity_Id;
- -- Subprogram designator, set from Spec_Id if present, else Body_Id
-
- Precond : Node_Id := Empty;
- -- Set non-Empty if we prepend precondition to the declarations. This
- -- is used to hook up inherited preconditions (adding the condition
- -- expression with OR ELSE, and adding the message).
-
- Inherited_Precond : Node_Id;
- -- Precondition inherited from parent subprogram
-
- Inherited : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
- -- List of subprograms inherited by this subprogram
-
- Plist : List_Id := No_List;
- -- List of generated postconditions
-
- procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
- -- Append a node to a list. If there is no list, create a new one. When
- -- the item denotes a pragma, it is added to the list only when it is
- -- enabled.
-
- procedure Check_Access_Invariants (E : Entity_Id);
- -- If the subprogram returns an access to a type with invariants, or
- -- has access parameters whose designated type has an invariant, then
- -- under the same visibility conditions as for other invariant checks,
- -- the type invariant must be applied to the returned value.
-
- procedure Collect_Body_Postconditions (Post_Nam : Name_Id);
- -- Examine the declarations of the body, looking for pragmas with name
- -- Post_Nam. Parameter Post_Nam must denote either Name_Postcondition or
- -- Name_Refined_Post. Chain any relevant postconditions to Plist.
-
- function Grab_PPC (Pspec : Entity_Id := Empty) return Node_Id;
- -- Prag contains an analyzed precondition or postcondition pragma. This
- -- function copies the pragma, changes it to the corresponding Check
- -- pragma and returns the Check pragma as the result. If Pspec is non-
- -- empty, this is the case of inheriting a PPC, where we must change
- -- references to parameters of the inherited subprogram to point to the
- -- corresponding parameters of the current subprogram.
-
- function Has_Checked_Predicate (Typ : Entity_Id) return Boolean;
- -- Determine whether type Typ has or inherits at least one predicate
- -- aspect or pragma, for which the applicable policy is Checked.
-
- function Has_Null_Body (Proc_Id : Entity_Id) return Boolean;
- -- Determine whether the body of procedure Proc_Id contains a sole null
- -- statement, possibly followed by an optional return.
-
- procedure Insert_After_Last_Declaration (Nod : Node_Id);
- -- Insert node Nod after the last declaration of the context
-
- function Is_Public_Subprogram_For (T : Entity_Id) return Boolean;
- -- T is the entity for a private type for which invariants are defined.
- -- This function returns True if the procedure corresponding to the
- -- value of Designator is a public procedure from the point of view of
- -- this type (i.e. its spec is in the visible part of the package that
- -- contains the declaration of the private type). A True value means
- -- that an invariant check is required (for an IN OUT parameter, or
- -- the returned value of a function.
-
- -------------------------
- -- Append_Enabled_Item --
- -------------------------
-
- procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
- begin
- -- Do not chain ignored or disabled pragmas
-
- if Nkind (Item) = N_Pragma
- and then (Is_Ignored (Item) or else Is_Disabled (Item))
- then
- null;
-
- -- Add the item
-
- else
- if No (List) then
- List := New_List;
- end if;
-
- Append (Item, List);
- end if;
- end Append_Enabled_Item;
-
- -----------------------------
- -- Check_Access_Invariants --
- -----------------------------
-
- procedure Check_Access_Invariants (E : Entity_Id) is
- Call : Node_Id;
- Obj : Node_Id;
- Typ : Entity_Id;
-
- begin
- if Is_Access_Type (Etype (E))
- and then not Is_Access_Constant (Etype (E))
- then
- Typ := Designated_Type (Etype (E));
-
- if Has_Invariants (Typ)
- and then Present (Invariant_Procedure (Typ))
- and then not Has_Null_Body (Invariant_Procedure (Typ))
- and then Is_Public_Subprogram_For (Typ)
- then
- Obj :=
- Make_Explicit_Dereference (Loc,
- Prefix => New_Occurrence_Of (E, Loc));
- Set_Etype (Obj, Typ);
-
- Call := Make_Invariant_Call (Obj);
-
- Append_Enabled_Item
- (Make_If_Statement (Loc,
- Condition =>
- Make_Op_Ne (Loc,
- Left_Opnd => Make_Null (Loc),
- Right_Opnd => New_Occurrence_Of (E, Loc)),
- Then_Statements => New_List (Call)),
- List => Plist);
- end if;
- end if;
- end Check_Access_Invariants;
-
- ---------------------------------
- -- Collect_Body_Postconditions --
- ---------------------------------
-
- procedure Collect_Body_Postconditions (Post_Nam : Name_Id) is
- Next_Prag : Node_Id;
-
- begin
- pragma Assert
- (Nam_In (Post_Nam, Name_Postcondition, Name_Refined_Post));
-
- Prag := First (Declarations (N));
- while Present (Prag) loop
- Next_Prag := Next (Prag);
-
- if Nkind (Prag) = N_Pragma then
-
- -- Capture postcondition pragmas
-
- if Pragma_Name (Prag) = Post_Nam then
- Analyze (Prag);
-
- -- All Refined_Post pragmas must be relocated to the body
- -- of the generated _Postconditions routine, otherwise they
- -- will be duplicated twice - once in the declarations of
- -- the body and once in _Postconditions.
-
- if Pragma_Name (Prag) = Name_Refined_Post then
- Remove (Prag);
- end if;
-
- -- If expansion is disabled, as in a generic unit, save
- -- pragma for later expansion.
-
- if not Expander_Active then
- Prepend (Grab_PPC, Declarations (N));
- else
- Append_Enabled_Item (Grab_PPC, Plist);
- end if;
- end if;
-
- -- Skip internally generated code
-
- elsif not Comes_From_Source (Prag) then
- null;
-
- else
- exit;
- end if;
-
- Prag := Next_Prag;
- end loop;
- end Collect_Body_Postconditions;
-
- --------------
- -- Grab_PPC --
- --------------
-
- function Grab_PPC (Pspec : Entity_Id := Empty) return Node_Id is
- Nam : constant Name_Id := Pragma_Name (Prag);
- Map : Elist_Id;
- CP : Node_Id;
-
- Ename : Name_Id;
- -- Effective name of pragma (maybe Pre/Post rather than Precondition/
- -- Postcodition if the pragma came from a Pre/Post aspect). We need
- -- the name right when we generate the Check pragma, since we want
- -- the right set of check policies to apply.
-
- begin
- -- Prepare map if this is the case where we have to map entities of
- -- arguments in the overridden subprogram to corresponding entities
- -- of the current subprogram.
-
- if No (Pspec) then
- Map := No_Elist;
-
- else
- declare
- PF : Entity_Id;
- CF : Entity_Id;
-
- begin
- Map := New_Elmt_List;
- PF := First_Formal (Pspec);
- CF := First_Formal (Designator);
- while Present (PF) loop
- Append_Elmt (PF, Map);
- Append_Elmt (CF, Map);
- Next_Formal (PF);
- Next_Formal (CF);
- end loop;
- end;
- end if;
-
- -- Now we can copy the tree, doing any required substitutions
-
- CP := New_Copy_Tree (Prag, Map => Map, New_Scope => Current_Scope);
-
- -- Set Analyzed to false, since we want to reanalyze the check
- -- procedure. Note that it is only at the outer level that we
- -- do this fiddling, for the spec cases, the already preanalyzed
- -- parameters are not affected.
-
- Set_Analyzed (CP, False);
-
- -- We also make sure Comes_From_Source is False for the copy
-
- Set_Comes_From_Source (CP, False);
-
- -- For a postcondition pragma within a generic, preserve the pragma
- -- for later expansion. This is also used when an error was detected,
- -- thus setting Expander_Active to False.
-
- if Nam = Name_Postcondition
- and then not Expander_Active
- then
- return CP;
- end if;
-
- -- Get effective name of aspect
-
- if Present (Corresponding_Aspect (Prag)) then
- Ename := Chars (Identifier (Corresponding_Aspect (Prag)));
- else
- Ename := Nam;
- end if;
-
- -- Change copy of pragma into corresponding pragma Check
-
- Prepend_To (Pragma_Argument_Associations (CP),
- Make_Pragma_Argument_Association (Sloc (Prag),
- Expression => Make_Identifier (Loc, Ename)));
- Set_Pragma_Identifier (CP, Make_Identifier (Sloc (Prag), Name_Check));
-
- -- If this is inherited case and the current message starts with
- -- "failed p", we change it to "failed inherited p...".
-
- if Present (Pspec) then
- declare
- Msg : constant Node_Id :=
- Last (Pragma_Argument_Associations (CP));
-
- begin
- if Chars (Msg) = Name_Message then
- String_To_Name_Buffer (Strval (Expression (Msg)));
-
- if Name_Buffer (1 .. 8) = "failed p" then
- Insert_Str_In_Name_Buffer ("inherited ", 8);
- Set_Strval
- (Expression (Last (Pragma_Argument_Associations (CP))),
- String_From_Name_Buffer);
- end if;
- end if;
- end;
- end if;
-
- -- Return the check pragma
-
- return CP;
- end Grab_PPC;
-
- ---------------------------
- -- Has_Checked_Predicate --
- ---------------------------
-
- function Has_Checked_Predicate (Typ : Entity_Id) return Boolean is
- Anc : Entity_Id;
- Pred : Node_Id;
-
- begin
- -- Climb the ancestor type chain staring from the input. This is done
- -- because the input type may lack aspect/pragma predicate and simply
- -- inherit those from its ancestor.
-
- -- Note that predicate pragmas include all three cases of predicate
- -- aspects (Predicate, Dynamic_Predicate, Static_Predicate), so this
- -- routine checks for all three cases.
-
- Anc := Typ;
- while Present (Anc) loop
- Pred := Get_Pragma (Anc, Pragma_Predicate);
-
- if Present (Pred) and then not Is_Ignored (Pred) then
- return True;
- end if;
-
- Anc := Nearest_Ancestor (Anc);
- end loop;
-
- return False;
- end Has_Checked_Predicate;
-
- -------------------
- -- Has_Null_Body --
- -------------------
-
- function Has_Null_Body (Proc_Id : Entity_Id) return Boolean is
- Body_Id : Entity_Id;
- Decl : Node_Id;
- Spec : Node_Id;
- Stmt1 : Node_Id;
- Stmt2 : Node_Id;
-
- begin
- Spec := Parent (Proc_Id);
- Decl := Parent (Spec);
-
- -- Retrieve the entity of the invariant procedure body
-
- if Nkind (Spec) = N_Procedure_Specification
- and then Nkind (Decl) = N_Subprogram_Declaration
- then
- Body_Id := Corresponding_Body (Decl);
-
- -- The body acts as a spec
-
- else
- Body_Id := Proc_Id;
- end if;
-
- -- The body will be generated later
-
- if No (Body_Id) then
- return False;
- end if;
-
- Spec := Parent (Body_Id);
- Decl := Parent (Spec);
-
- pragma Assert
- (Nkind (Spec) = N_Procedure_Specification
- and then Nkind (Decl) = N_Subprogram_Body);
-
- Stmt1 := First (Statements (Handled_Statement_Sequence (Decl)));
-
- -- Look for a null statement followed by an optional return statement
-
- if Nkind (Stmt1) = N_Null_Statement then
- Stmt2 := Next (Stmt1);
-
- if Present (Stmt2) then
- return Nkind (Stmt2) = N_Simple_Return_Statement;
- else
- return True;
- end if;
- end if;
-
- return False;
- end Has_Null_Body;
-
- -----------------------------------
- -- Insert_After_Last_Declaration --
- -----------------------------------
-
- procedure Insert_After_Last_Declaration (Nod : Node_Id) is
- Decls : constant List_Id := Declarations (N);
-
- begin
- if No (Decls) then
- Set_Declarations (N, New_List (Nod));
- else
- Append_To (Decls, Nod);
- end if;
- end Insert_After_Last_Declaration;
-
- ------------------------------
- -- Is_Public_Subprogram_For --
- ------------------------------
-
- -- The type T is a private type, its declaration is therefore in
- -- the list of public declarations of some package. The test for a
- -- public subprogram is that its declaration is in this same list
- -- of declarations for the same package (note that all the public
- -- declarations are in one list, and all the private declarations
- -- in another, so this deals with the public/private distinction).
-
- function Is_Public_Subprogram_For (T : Entity_Id) return Boolean is
- DD : constant Node_Id := Unit_Declaration_Node (Designator);
- -- The subprogram declaration for the subprogram in question
-
- TL : constant List_Id :=
- Visible_Declarations
- (Specification (Unit_Declaration_Node (Scope (T))));
- -- The list of declarations containing the private declaration of
- -- the type. We know it is a private type, so we know its scope is
- -- the package in question, and we know it must be in the visible
- -- declarations of this package.
-
- begin
- -- If the subprogram declaration is not a list member, it must be
- -- an Init_Proc, in which case we want to consider it to be a
- -- public subprogram, since we do get initializations to deal with.
- -- Other internally generated subprograms are not public.
-
- if not Is_List_Member (DD)
- and then Is_Init_Proc (Defining_Entity (DD))
- then
- return True;
-
- -- The declaration may have been generated for an expression function
- -- so check whether that function comes from source.
-
- elsif not Comes_From_Source (DD)
- and then
- (Nkind (Original_Node (DD)) /= N_Expression_Function
- or else not Comes_From_Source (Defining_Entity (DD)))
- then
- return False;
-
- -- Otherwise we test whether the subprogram is declared in the
- -- visible declarations of the package containing the type.
-
- else
- return TL = List_Containing (DD);
- end if;
- end Is_Public_Subprogram_For;
-
- -- Local variables
-
- Formal : Node_Id;
- Formal_Typ : Entity_Id;
- Func_Typ : Entity_Id;
- Post_Proc : Entity_Id;
- Result : Node_Id;
-
- -- Start of processing for Process_PPCs
-
- begin
- -- Capture designator from spec if present, else from body
-
- if Present (Spec_Id) then
- Designator := Spec_Id;
- else
- Designator := Body_Id;
- end if;
-
- -- Do not process a predicate function as its body will contain a
- -- recursive call to itself and blow up the stack.
-
- if Ekind (Designator) = E_Function
- and then Is_Predicate_Function (Designator)
- then
- return;
-
- -- Internally generated subprograms, such as type-specific functions,
- -- don't get assertion checks.
-
- elsif Get_TSS_Name (Designator) /= TSS_Null then
- return;
- end if;
-
- -- Grab preconditions from spec
-
- if Present (Spec_Id) then
-
- -- Loop through PPC pragmas from spec. Note that preconditions from
- -- the body will be analyzed and converted when we scan the body
- -- declarations below.
-
- Prag := Pre_Post_Conditions (Contract (Spec_Id));
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition then
-
- -- For Pre (or Precondition pragma), we simply prepend the
- -- pragma to the list of declarations right away so that it
- -- will be executed at the start of the procedure. Note that
- -- this processing reverses the order of the list, which is
- -- what we want since new entries were chained to the head of
- -- the list. There can be more than one precondition when we
- -- use pragma Precondition.
-
- if not Class_Present (Prag) then
- Prepend (Grab_PPC, Declarations (N));
-
- -- For Pre'Class there can only be one pragma, and we save
- -- it in Precond for now. We will add inherited Pre'Class
- -- stuff before inserting this pragma in the declarations.
- else
- Precond := Grab_PPC;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
-
- -- Now deal with inherited preconditions
-
- for J in Inherited'Range loop
- Prag := Pre_Post_Conditions (Contract (Inherited (J)));
-
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition
- and then Class_Present (Prag)
- then
- Inherited_Precond := Grab_PPC (Inherited (J));
-
- -- No precondition so far, so establish this as the first
-
- if No (Precond) then
- Precond := Inherited_Precond;
-
- -- Here we already have a precondition, add inherited one
-
- else
- -- Add new precondition to old one using OR ELSE
-
- declare
- New_Expr : constant Node_Id :=
- Get_Pragma_Arg
- (Next (First (Pragma_Argument_Associations
- (Inherited_Precond))));
- Old_Expr : constant Node_Id :=
- Get_Pragma_Arg
- (Next (First (Pragma_Argument_Associations
- (Precond))));
-
- begin
- if Paren_Count (Old_Expr) = 0 then
- Set_Paren_Count (Old_Expr, 1);
- end if;
-
- if Paren_Count (New_Expr) = 0 then
- Set_Paren_Count (New_Expr, 1);
- end if;
-
- Rewrite (Old_Expr,
- Make_Or_Else (Sloc (Old_Expr),
- Left_Opnd => Relocate_Node (Old_Expr),
- Right_Opnd => New_Expr));
- end;
-
- -- Add new message in the form:
-
- -- failed precondition from bla
- -- also failed inherited precondition from bla
- -- ...
-
- -- Skip this if exception locations are suppressed
-
- if not Exception_Locations_Suppressed then
- declare
- New_Msg : constant Node_Id :=
- Get_Pragma_Arg
- (Last
- (Pragma_Argument_Associations
- (Inherited_Precond)));
- Old_Msg : constant Node_Id :=
- Get_Pragma_Arg
- (Last
- (Pragma_Argument_Associations
- (Precond)));
- begin
- Start_String (Strval (Old_Msg));
- Store_String_Chars (ASCII.LF & " also ");
- Store_String_Chars (Strval (New_Msg));
- Set_Strval (Old_Msg, End_String);
- end;
- end if;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
- end loop;
-
- -- If we have built a precondition for Pre'Class (including any
- -- Pre'Class aspects inherited from parent subprograms), then we
- -- insert this composite precondition at this stage.
-
- if Present (Precond) then
- Prepend (Precond, Declarations (N));
- end if;
- end if;
-
- -- Build postconditions procedure if needed and prepend the following
- -- declaration to the start of the declarations for the subprogram.
-
- -- procedure _postconditions [(_Result : resulttype)] is
- -- begin
- -- pragma Check (Refined_Post, condition);
- -- pragma Check (Refined_Post, condition);
- -- pragma Check (Postcondition, condition [,message]);
- -- pragma Check (Postcondition, condition [,message]);
- -- ...
- -- Invariant_Procedure (_Result) ...
- -- Invariant_Procedure (Arg1)
- -- ...
- -- end;
-
- -- First we deal with the postconditions in the body
-
- Collect_Body_Postconditions (Name_Refined_Post);
- Collect_Body_Postconditions (Name_Postcondition);
-
- -- Now deal with any postconditions from the spec
-
- if Present (Spec_Id) then
- Spec_Postconditions : declare
- procedure Process_Contract_Cases (Spec : Node_Id);
- -- This processes the Contract_Test_Cases from Spec, processing
- -- any contract-cases from the list. The caller has checked that
- -- Contract_Test_Cases is non-Empty.
-
- procedure Process_Post_Conditions
- (Spec : Node_Id;
- Class : Boolean);
- -- This processes the Pre_Post_Conditions from Spec, processing
- -- any postconditions from the list. If Class is True, then only
- -- postconditions marked with Class_Present are considered. The
- -- caller has checked that Pre_Post_Conditions is non-Empty.
-
- ----------------------------
- -- Process_Contract_Cases --
- ----------------------------
-
- procedure Process_Contract_Cases (Spec : Node_Id) is
- begin
- -- Loop through Contract_Cases pragmas from spec
-
- Prag := Contract_Test_Cases (Contract (Spec));
- loop
- if Pragma_Name (Prag) = Name_Contract_Cases then
- Expand_Contract_Cases
- (CCs => Prag,
- Subp_Id => Spec_Id,
- Decls => Declarations (N),
- Stmts => Plist);
- end if;
-
- Prag := Next_Pragma (Prag);
- exit when No (Prag);
- end loop;
- end Process_Contract_Cases;
-
- -----------------------------
- -- Process_Post_Conditions --
- -----------------------------
-
- procedure Process_Post_Conditions
- (Spec : Node_Id;
- Class : Boolean)
- is
- Pspec : Node_Id;
-
- begin
- if Class then
- Pspec := Spec;
- else
- Pspec := Empty;
- end if;
-
- -- Loop through PPC pragmas from spec
-
- Prag := Pre_Post_Conditions (Contract (Spec));
- loop
- if Pragma_Name (Prag) = Name_Postcondition
- and then (not Class or else Class_Present (Prag))
- then
- if not Expander_Active then
- Prepend (Grab_PPC (Pspec), Declarations (N));
- else
- Append_Enabled_Item (Grab_PPC (Pspec), Plist);
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- exit when No (Prag);
- end loop;
- end Process_Post_Conditions;
-
- -- Start of processing for Spec_Postconditions
-
- begin
- -- Process postconditions expressed as contract-cases
-
- if Present (Contract_Test_Cases (Contract (Spec_Id))) then
- Process_Contract_Cases (Spec_Id);
- end if;
-
- -- Process spec postconditions
-
- if Present (Pre_Post_Conditions (Contract (Spec_Id))) then
- Process_Post_Conditions (Spec_Id, Class => False);
- end if;
-
- -- Process inherited postconditions
-
- for J in Inherited'Range loop
- if Present (Pre_Post_Conditions (Contract (Inherited (J)))) then
- Process_Post_Conditions (Inherited (J), Class => True);
- end if;
- end loop;
- end Spec_Postconditions;
- end if;
-
- -- Add an invariant call to check the result of a function
-
- if Ekind (Designator) /= E_Procedure and then Expander_Active then
- Func_Typ := Etype (Designator);
- Result := Make_Defining_Identifier (Loc, Name_uResult);
-
- Set_Etype (Result, Func_Typ);
-
- -- Add argument for return
-
- Parms := New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Result,
- Parameter_Type => New_Occurrence_Of (Func_Typ, Loc)));
-
- -- Add invariant call if returning type with invariants and this is a
- -- public function, i.e. a function declared in the visible part of
- -- the package defining the private type.
-
- if Has_Invariants (Func_Typ)
- and then Present (Invariant_Procedure (Func_Typ))
- and then not Has_Null_Body (Invariant_Procedure (Func_Typ))
- and then Is_Public_Subprogram_For (Func_Typ)
- then
- Append_Enabled_Item
- (Make_Invariant_Call (New_Occurrence_Of (Result, Loc)), Plist);
- end if;
-
- -- Same if return value is an access to type with invariants
-
- Check_Access_Invariants (Result);
-
- -- Procedure case
-
- else
- Parms := No_List;
- end if;
-
- -- Add invariant calls and predicate calls for parameters. Note that
- -- this is done for functions as well, since in Ada 2012 they can have
- -- IN OUT args.
-
- if Expander_Active then
- Formal := First_Formal (Designator);
- while Present (Formal) loop
- if Ekind (Formal) /= E_In_Parameter
- or else Is_Access_Type (Etype (Formal))
- then
- Formal_Typ := Etype (Formal);
-
- if Has_Invariants (Formal_Typ)
- and then Present (Invariant_Procedure (Formal_Typ))
- and then not Has_Null_Body (Invariant_Procedure (Formal_Typ))
- and then Is_Public_Subprogram_For (Formal_Typ)
- then
- Append_Enabled_Item
- (Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
- Plist);
- end if;
-
- Check_Access_Invariants (Formal);
-
- if Has_Predicates (Formal_Typ)
- and then Present (Predicate_Function (Formal_Typ))
- and then Has_Checked_Predicate (Formal_Typ)
- then
- Append_Enabled_Item
- (Make_Predicate_Check
- (Formal_Typ, New_Occurrence_Of (Formal, Loc)),
- Plist);
- end if;
- end if;
-
- Next_Formal (Formal);
- end loop;
- end if;
-
- -- Build and insert postcondition procedure
-
- if Expander_Active and then Present (Plist) then
- Post_Proc :=
- Make_Defining_Identifier (Loc, Chars => Name_uPostconditions);
-
- -- Insert the corresponding body of a post condition pragma after the
- -- last declaration of the context. This ensures that the body will
- -- not cause any premature freezing as it may mention types:
-
- -- procedure Proc (Obj : Array_Typ) is
- -- procedure _postconditions is
- -- begin
- -- ... Obj ...
- -- end _postconditions;
-
- -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
- -- begin
-
- -- In the example above, Obj is of type T but the incorrect placement
- -- of _postconditions will cause a crash in gigi due to an out of
- -- order reference. The body of _postconditions must be placed after
- -- the declaration of Temp to preserve correct visibility.
-
- Insert_After_Last_Declaration (
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name => Post_Proc,
- Parameter_Specifications => Parms),
-
- Declarations => Empty_List,
-
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Plist)));
-
- Set_Ekind (Post_Proc, E_Procedure);
-
- -- If this is a procedure, set the Postcondition_Proc attribute on
- -- the proper defining entity for the subprogram.
-
- if Ekind (Designator) = E_Procedure then
- Set_Postcondition_Proc (Designator, Post_Proc);
- end if;
-
- Set_Has_Postconditions (Designator);
- end if;
- end Process_PPCs;
-
----------------------------
-- Reference_Body_Formals --
----------------------------
diff --git a/gcc/ada/sem_ch6.ads b/gcc/ada/sem_ch6.ads
index d967c017ae0..bc901cc8fab 100644
--- a/gcc/ada/sem_ch6.ads
+++ b/gcc/ada/sem_ch6.ads
@@ -46,9 +46,21 @@ package Sem_Ch6 is
procedure Analyze_Subprogram_Declaration (N : Node_Id);
procedure Analyze_Subprogram_Body (N : Node_Id);
+ procedure Analyze_Subprogram_Body_Contract (Subp : Entity_Id);
+ -- Analyze all delayed aspects chained on the contract of subprogram body
+ -- Subp as if they appeared at the end of a declarative region. The aspects
+ -- in question are:
+ -- Refined_Depends
+ -- Refined_Global
+
procedure Analyze_Subprogram_Contract (Subp : Entity_Id);
-- Analyze all delayed aspects chained on the contract of subprogram Subp
- -- as if they appeared at the end of a declarative region.
+ -- as if they appeared at the end of a declarative region. The aspects in
+ -- question are:
+ -- Contract_Cases
+ -- Postcondition
+ -- Precondition
+ -- Test_Case
function Analyze_Subprogram_Specification (N : Node_Id) return Entity_Id;
-- Analyze subprogram specification in both subprogram declarations
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index ef8df47cdee..7b0f71f15b0 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -404,6 +404,7 @@ package body Sem_Prag is
Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
All_Cases : Node_Id;
CCase : Node_Id;
+ Restore : Boolean := False;
Subp_Decl : Node_Id;
Subp_Id : Entity_Id;
@@ -431,6 +432,7 @@ package body Sem_Prag is
-- for subprogram bodies because the formals are already visible.
if Requires_Profile_Installation (N, Subp_Decl) then
+ Restore := True;
Push_Scope (Subp_Id);
Install_Formals (Subp_Id);
end if;
@@ -441,7 +443,7 @@ package body Sem_Prag is
Next (CCase);
end loop;
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore then
End_Scope;
end if;
end if;
@@ -1234,6 +1236,9 @@ package body Sem_Prag is
Last_Clause : Node_Id;
Subp_Decl : Node_Id;
+ Restore_Scope : Boolean := False;
+ -- Gets set True if we do a Push_Scope needing a Pop_Scope on exit
+
-- Start of processing for Analyze_Depends_In_Decl_Part
begin
@@ -1287,6 +1292,7 @@ package body Sem_Prag is
-- bodies because the formals are already visible.
if Requires_Profile_Installation (N, Subp_Decl) then
+ Restore_Scope := True;
Push_Scope (Subp_Id);
Install_Formals (Subp_Id);
end if;
@@ -1317,7 +1323,7 @@ package body Sem_Prag is
Next (Clause);
end loop;
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore_Scope then
End_Scope;
end if;
@@ -1690,6 +1696,9 @@ package body Sem_Prag is
List : Node_Id;
Subp_Decl : Node_Id;
+ Restore_Scope : Boolean := False;
+ -- Set True if we do a Push_Scope requiring a Pop_Scope on exit
+
-- Start of processing for Analyze_Global_In_Decl_List
begin
@@ -1714,171 +1723,19 @@ package body Sem_Prag is
-- subprogram declarations.
if Requires_Profile_Installation (N, Subp_Decl) then
+ Restore_Scope := True;
Push_Scope (Subp_Id);
Install_Formals (Subp_Id);
end if;
Analyze_Global_List (List);
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore_Scope then
End_Scope;
end if;
end if;
end Analyze_Global_In_Decl_Part;
- ------------------------------
- -- Analyze_PPC_In_Decl_Part --
- ------------------------------
-
- procedure Analyze_PPC_In_Decl_Part (N : Node_Id; S : Entity_Id) is
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
-
- 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);
-
- -- Preanalyze the boolean expression, we treat this as a spec expression
- -- (i.e. similar to a default expression).
-
- -- In ASIS mode, for a pragma generated from a source aspect, analyze
- -- directly the the original aspect expression, which is shared with
- -- the generated pragma.
-
- if ASIS_Mode and then Present (Corresponding_Aspect (N)) then
- Preanalyze_Assert_Expression
- (Expression (Corresponding_Aspect (N)), Standard_Boolean);
- else
- Preanalyze_Assert_Expression
- (Get_Pragma_Arg (Arg1), Standard_Boolean);
- end if;
-
- -- For a class-wide condition, a reference to a controlling formal must
- -- be interpreted as having the class-wide type (or an access to such)
- -- so that the inherited condition can be properly applied to any
- -- overriding operation (see ARM12 6.6.1 (7)).
-
- if Class_Present (N) then
- Class_Wide_Condition : declare
- T : constant Entity_Id := Find_Dispatching_Type (S);
-
- ACW : Entity_Id := Empty;
- -- Access to T'class, created if there is a controlling formal
- -- that is an access parameter.
-
- function Get_ACW return Entity_Id;
- -- If the expression has a reference to an controlling access
- -- parameter, create an access to T'class for the necessary
- -- conversions if one does not exist.
-
- function Process (N : Node_Id) return Traverse_Result;
- -- ARM 6.1.1: Within the expression for a Pre'Class or Post'Class
- -- aspect for a primitive subprogram of a tagged type T, a name
- -- that denotes a formal parameter of type T is interpreted as
- -- having type T'Class. Similarly, a name that denotes a formal
- -- accessparameter of type access-to-T is interpreted as having
- -- type access-to-T'Class. This ensures the expression is well-
- -- defined for a primitive subprogram of a type descended from T.
- -- Note that this replacement is not done for selector names in
- -- parameter associations. These carry an entity for reference
- -- purposes, but semantically they are just identifiers.
-
- -------------
- -- Get_ACW --
- -------------
-
- function Get_ACW return Entity_Id is
- Loc : constant Source_Ptr := Sloc (N);
- Decl : Node_Id;
-
- begin
- if No (ACW) then
- Decl := Make_Full_Type_Declaration (Loc,
- Defining_Identifier => Make_Temporary (Loc, 'T'),
- Type_Definition =>
- Make_Access_To_Object_Definition (Loc,
- Subtype_Indication =>
- New_Occurrence_Of (Class_Wide_Type (T), Loc),
- All_Present => True));
-
- Insert_Before (Unit_Declaration_Node (S), Decl);
- Analyze (Decl);
- ACW := Defining_Identifier (Decl);
- Freeze_Before (Unit_Declaration_Node (S), ACW);
- end if;
-
- return ACW;
- end Get_ACW;
-
- -------------
- -- Process --
- -------------
-
- function Process (N : Node_Id) return Traverse_Result is
- Loc : constant Source_Ptr := Sloc (N);
- Typ : Entity_Id;
-
- begin
- if Is_Entity_Name (N)
- and then Present (Entity (N))
- and then Is_Formal (Entity (N))
- and then Nkind (Parent (N)) /= N_Type_Conversion
- and then
- (Nkind (Parent (N)) /= N_Parameter_Association
- or else N /= Selector_Name (Parent (N)))
- then
- if Etype (Entity (N)) = T then
- Typ := Class_Wide_Type (T);
-
- elsif Is_Access_Type (Etype (Entity (N)))
- and then Designated_Type (Etype (Entity (N))) = T
- then
- Typ := Get_ACW;
- else
- Typ := Empty;
- end if;
-
- if Present (Typ) then
- Rewrite (N,
- Make_Type_Conversion (Loc,
- Subtype_Mark =>
- New_Occurrence_Of (Typ, Loc),
- Expression => New_Occurrence_Of (Entity (N), Loc)));
- Set_Etype (N, Typ);
- end if;
- end if;
-
- return OK;
- end Process;
-
- procedure Replace_Type is new Traverse_Proc (Process);
-
- -- Start of processing for Class_Wide_Condition
-
- begin
- if not Present (T) then
- Error_Msg_Name_1 :=
- Chars (Identifier (Corresponding_Aspect (N)));
-
- 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));
- end if;
-
- Replace_Type (Get_Pragma_Arg (Arg1));
- end Class_Wide_Condition;
- end if;
-
- -- Remove the subprogram from the scope stack now that the pre-analysis
- -- of the precondition/postcondition is done.
-
- End_Scope;
- end Analyze_PPC_In_Decl_Part;
-
--------------------
-- Analyze_Pragma --
--------------------
@@ -1922,15 +1779,9 @@ 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 Analyze_Refined_Pre_Post
- (Body_Decl : out Node_Id;
- Spec_Id : out Entity_Id;
- Legal : out Boolean);
+ procedure Analyze_Refined_Pre_Post_Condition;
-- Subsidiary routine to the analysis of pragmas Refined_Pre and
- -- Refined_Post. Body_Decl is the declaration of the subprogram body
- -- [stub] subject to the pragma. Spec_Id is the corresponding spec of
- -- the subprogram body [stub]. Flag Legal denotes whether the pragma
- -- passes all legality rules.
+ -- Refined_Post.
procedure Check_Ada_83_Warning;
-- Issues a warning message for the current pragma if operating in Ada
@@ -2458,26 +2309,18 @@ package body Sem_Prag is
end if;
end Ada_2012_Pragma;
- ------------------------------
- -- Analyze_Refined_Pre_Post --
- ------------------------------
+ ----------------------------------------
+ -- Analyze_Refined_Pre_Post_Condition --
+ ----------------------------------------
- procedure Analyze_Refined_Pre_Post
- (Body_Decl : out Node_Id;
- Spec_Id : out Entity_Id;
- Legal : out Boolean)
- is
+ procedure Analyze_Refined_Pre_Post_Condition is
+ Body_Decl : Node_Id := Parent (N);
Pack_Spec : Node_Id;
Spec_Decl : Node_Id;
+ Spec_Id : Entity_Id;
Stmt : Node_Id;
begin
- -- Assume that the pragma is illegal
-
- Body_Decl := Parent (N);
- Spec_Id := Empty;
- Legal := False;
-
GNAT_Pragma;
Check_Arg_Count (1);
Check_No_Identifiers;
@@ -2576,10 +2419,10 @@ package body Sem_Prag is
return;
end if;
- -- If we get here, the placement and legality of the pragma is OK
+ -- Analyze the boolean expression as a "spec expression"
- Legal := True;
- end Analyze_Refined_Pre_Post;
+ Analyze_Pre_Post_Condition_In_Decl_Part (N, Spec_Id);
+ end Analyze_Refined_Pre_Post_Condition;
--------------------------
-- Check_Ada_83_Warning --
@@ -3791,7 +3634,7 @@ package body Sem_Prag is
-- analyzed.
if SPARK_Mode or else ASIS_Mode then
- Analyze_PPC_In_Decl_Part
+ Analyze_Pre_Post_Condition_In_Decl_Part
(N, Defining_Entity (Unit (Parent (PO))));
end if;
@@ -16092,32 +15935,35 @@ package body Sem_Prag is
when Pragma_Rational =>
Set_Rational_Profile;
- ------------------
- -- Refined_Post --
- ------------------
+ ---------------------
+ -- Refined_Depends --
+ ---------------------
- -- pragma Refined_Post (boolean_EXPRESSION);
+ -- ??? To be implemented
- when Pragma_Refined_Post => Refined_Post : declare
- Body_Decl : Node_Id;
- Legal : Boolean;
- Spec_Id : Entity_Id;
+ when Pragma_Refined_Depends =>
+ null;
- begin
- -- Verify the legal placement of the pragma. The pragma is left
- -- intentionally semi-analyzed. Process_PPCs does the remaining
- -- analysis of the expression when Refined_Post is converted into
- -- pragma Check.
+ --------------------
+ -- Refined_Global --
+ --------------------
- Analyze_Refined_Pre_Post (Body_Decl, Spec_Id, Legal);
+ -- ??? To be implemented
- -- Analyze the expression when code generation is disabled because
- -- the contract of the related subprogram will never be processed.
+ -- Would be better if these generated an error message saying that
+ -- the feature was not yet implemented ???
- if Legal and then not Expander_Active then
- Analyze_And_Resolve (Get_Pragma_Arg (Arg1), Standard_Boolean);
- end if;
- end Refined_Post;
+ when Pragma_Refined_Global =>
+ null;
+
+ ------------------
+ -- Refined_Post --
+ ------------------
+
+ -- pragma Refined_Post (boolean_EXPRESSION);
+
+ when Pragma_Refined_Post =>
+ Analyze_Refined_Pre_Post_Condition;
-----------------
-- Refined_Pre --
@@ -16125,48 +15971,8 @@ package body Sem_Prag is
-- pragma Refined_Pre (boolean_EXPRESSION);
- when Pragma_Refined_Pre => Refined_Pre : declare
- Body_Decl : Node_Id;
- Legal : Boolean;
- Restore : Boolean := False;
- Spec_Id : Entity_Id;
-
- begin
- Analyze_Refined_Pre_Post (Body_Decl, Spec_Id, Legal);
-
- if Legal then
- pragma Assert (Present (Body_Decl));
- pragma Assert (Present (Spec_Id));
-
- if Nkind (Body_Decl) = N_Subprogram_Body_Stub
- and then No (Library_Unit (Body_Decl))
- and then Current_Scope /= Spec_Id
- then
- Restore := True;
- Push_Scope (Spec_Id);
- Install_Formals (Spec_Id);
- end if;
-
- -- Convert pragma Refined_Pre into pragma Check. The analysis
- -- of the generated pragma will take care of the expression.
-
- Rewrite (N,
- Make_Pragma (Loc,
- Chars => Name_Check,
- Pragma_Argument_Associations => New_List (
- Make_Pragma_Argument_Association (Loc,
- Expression => Make_Identifier (Loc, Pname)),
-
- Make_Pragma_Argument_Association (Sloc (Arg1),
- Expression => Relocate_Node (Get_Pragma_Arg (Arg1))))));
-
- Analyze (N);
-
- if Restore then
- Pop_Scope;
- end if;
- end if;
- end Refined_Pre;
+ when Pragma_Refined_Pre =>
+ Analyze_Refined_Pre_Post_Condition;
-----------------------
-- Relative_Deadline --
@@ -18499,6 +18305,195 @@ package body Sem_Prag is
when Pragma_Exit => null;
end Analyze_Pragma;
+ ---------------------------------------------
+ -- Analyze_Pre_Post_Condition_In_Decl_Part --
+ ---------------------------------------------
+
+ procedure Analyze_Pre_Post_Condition_In_Decl_Part
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id)
+ is
+ Arg1 : constant Node_Id :=
+ First (Pragma_Argument_Associations (Prag));
+ Expr : Node_Id;
+ Restore : Boolean := False;
+
+ begin
+ -- Ensure that the subprogram and its formals are visible when analyzing
+ -- the expression of the pragma.
+
+ if Current_Scope /= Subp_Id then
+ Restore := True;
+ Push_Scope (Subp_Id);
+ Install_Formals (Subp_Id);
+ end if;
+
+ -- Preanalyze the boolean expression, we treat this as a spec expression
+ -- (i.e. similar to a default expression).
+
+ Expr := Get_Pragma_Arg (Arg1);
+
+ -- In ASIS mode, for a pragma generated from a source aspect, analyze
+ -- the original aspect expression, which is shared with the generated
+ -- pragma.
+
+ if ASIS_Mode and then Present (Corresponding_Aspect (Prag)) then
+ Expr := Expression (Corresponding_Aspect (Prag));
+ end if;
+
+ Preanalyze_Assert_Expression (Expr, Standard_Boolean);
+
+ -- For a class-wide condition, a reference to a controlling formal must
+ -- be interpreted as having the class-wide type (or an access to such)
+ -- so that the inherited condition can be properly applied to any
+ -- overriding operation (see ARM12 6.6.1 (7)).
+
+ if Class_Present (Prag) then
+ Class_Wide_Condition : declare
+ T : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
+ ACW : Entity_Id := Empty;
+ -- Access to T'class, created if there is a controlling formal
+ -- that is an access parameter.
+
+ function Get_ACW return Entity_Id;
+ -- If the expression has a reference to an controlling access
+ -- parameter, create an access to T'class for the necessary
+ -- conversions if one does not exist.
+
+ function Process (N : Node_Id) return Traverse_Result;
+ -- ARM 6.1.1: Within the expression for a Pre'Class or Post'Class
+ -- aspect for a primitive subprogram of a tagged type T, a name
+ -- that denotes a formal parameter of type T is interpreted as
+ -- having type T'Class. Similarly, a name that denotes a formal
+ -- accessparameter of type access-to-T is interpreted as having
+ -- type access-to-T'Class. This ensures the expression is well-
+ -- defined for a primitive subprogram of a type descended from T.
+ -- Note that this replacement is not done for selector names in
+ -- parameter associations. These carry an entity for reference
+ -- purposes, but semantically they are just identifiers.
+
+ -------------
+ -- Get_ACW --
+ -------------
+
+ function Get_ACW return Entity_Id is
+ Loc : constant Source_Ptr := Sloc (Prag);
+ Decl : Node_Id;
+
+ begin
+ if No (ACW) then
+ Decl :=
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Make_Temporary (Loc, 'T'),
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ Subtype_Indication =>
+ New_Occurrence_Of (Class_Wide_Type (T), Loc),
+ All_Present => True));
+
+ Insert_Before (Unit_Declaration_Node (Subp_Id), Decl);
+ Analyze (Decl);
+ ACW := Defining_Identifier (Decl);
+ Freeze_Before (Unit_Declaration_Node (Subp_Id), ACW);
+ end if;
+
+ return ACW;
+ end Get_ACW;
+
+ -------------
+ -- Process --
+ -------------
+
+ function Process (N : Node_Id) return Traverse_Result is
+ Loc : constant Source_Ptr := Sloc (N);
+ Typ : Entity_Id;
+
+ begin
+ if Is_Entity_Name (N)
+ and then Present (Entity (N))
+ and then Is_Formal (Entity (N))
+ and then Nkind (Parent (N)) /= N_Type_Conversion
+ and then
+ (Nkind (Parent (N)) /= N_Parameter_Association
+ or else N /= Selector_Name (Parent (N)))
+ then
+ if Etype (Entity (N)) = T then
+ Typ := Class_Wide_Type (T);
+
+ elsif Is_Access_Type (Etype (Entity (N)))
+ and then Designated_Type (Etype (Entity (N))) = T
+ then
+ Typ := Get_ACW;
+ else
+ Typ := Empty;
+ end if;
+
+ if Present (Typ) then
+ Rewrite (N,
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Typ, Loc),
+ Expression => New_Occurrence_Of (Entity (N), Loc)));
+ Set_Etype (N, Typ);
+ end if;
+ end if;
+
+ return OK;
+ end Process;
+
+ procedure Replace_Type is new Traverse_Proc (Process);
+
+ -- Start of processing for Class_Wide_Condition
+
+ begin
+ if not Present (T) then
+ Error_Msg_Name_1 :=
+ Chars (Identifier (Corresponding_Aspect (Prag)));
+
+ Error_Msg_Name_2 := Name_Class;
+
+ Error_Msg_N
+ ("aspect `%''%` can only be specified for a primitive "
+ & "operation of a tagged type", Corresponding_Aspect (Prag));
+ end if;
+
+ Replace_Type (Get_Pragma_Arg (Arg1));
+ end Class_Wide_Condition;
+ end if;
+
+ -- Remove the subprogram from the scope stack now that the pre-analysis
+ -- of the precondition/postcondition is done.
+
+ if Restore then
+ End_Scope;
+ end if;
+ end Analyze_Pre_Post_Condition_In_Decl_Part;
+
+ ------------------------------------------
+ -- Analyze_Refined_Depends_In_Decl_Part --
+ ------------------------------------------
+
+ -- ??? To be implemented
+
+ procedure Analyze_Refined_Depends_In_Decl_Part (N : Node_Id) is
+ pragma Unreferenced (N);
+ begin
+ null;
+ end Analyze_Refined_Depends_In_Decl_Part;
+
+ -----------------------------------------
+ -- Analyze_Refined_Global_In_Decl_Part --
+ -----------------------------------------
+
+ -- ??? To be implemented
+
+ procedure Analyze_Refined_Global_In_Decl_Part (N : Node_Id) is
+ pragma Unreferenced (N);
+ begin
+ null;
+ end Analyze_Refined_Global_In_Decl_Part;
+
------------------------------------
-- Analyze_Test_Case_In_Decl_Part --
------------------------------------
@@ -19251,6 +19246,8 @@ package body Sem_Prag is
Pragma_Queuing_Policy => -1,
Pragma_Rational => -1,
Pragma_Ravenscar => -1,
+ Pragma_Refined_Depends => -1,
+ Pragma_Refined_Global => -1,
Pragma_Refined_Post => -1,
Pragma_Refined_Pre => -1,
Pragma_Relative_Deadline => -1,
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
index 492eb9f779f..3b8114fef0d 100644
--- a/gcc/ada/sem_prag.ads
+++ b/gcc/ada/sem_prag.ads
@@ -38,11 +38,13 @@ package Sem_Prag is
-- the pragmas below implement an aspect.
Pragma_On_Body_Or_Stub_OK : constant array (Pragma_Id) of Boolean :=
- (Pragma_Refined_Post => True,
- Pragma_Refined_Pre => True,
- Pragma_SPARK_Mode => True,
- Pragma_Warnings => True,
- others => False);
+ (Pragma_Refined_Depends => True,
+ Pragma_Refined_Global => True,
+ Pragma_Refined_Post => True,
+ Pragma_Refined_Pre => True,
+ Pragma_SPARK_Mode => True,
+ Pragma_Warnings => True,
+ others => False);
-----------------
-- Subprograms --
@@ -60,21 +62,27 @@ package Sem_Prag is
procedure Analyze_Global_In_Decl_Part (N : Node_Id);
-- Perform full analysis of delayed pragma Global
- procedure Analyze_PPC_In_Decl_Part (N : Node_Id; S : Entity_Id);
- -- Special analyze routine for precondition/postcondition pragma that
- -- appears within a declarative part where the pragma is associated
- -- with a subprogram specification. N is the pragma node, and S is the
- -- entity for the related subprogram. This procedure does a preanalysis
- -- of the expressions in the pragma as "spec expressions" (see section
- -- in Sem "Handling of Default and Per-Object Expressions...").
+ procedure Analyze_Pre_Post_Condition_In_Decl_Part
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id);
+ -- Perform preanalysis of a [refined] precondition or postcondition that
+ -- appears on a subprogram declaration or body [stub]. Prag denotes the
+ -- pragma, Subp_Id is the entity of the related subprogram. The preanalysis
+ -- of the expression is done as "spec expression" (see section "Handling
+ -- of Default and Per-Object Expressions in Sem).
+
+ procedure Analyze_Refined_Depends_In_Decl_Part (N : Node_Id);
+ -- Preform full analysis of delayed pragma Refined_Depends
+
+ procedure Analyze_Refined_Global_In_Decl_Part (N : Node_Id);
+ -- Perform full analysis of delayed pragma Refined_Global
procedure Analyze_Test_Case_In_Decl_Part (N : Node_Id; S : Entity_Id);
- -- Special analyze routine for contract-case and test-case pragmas that
- -- appears within a declarative part where the pragma is associated with
- -- a subprogram specification. N is the pragma node, and S is the entity
- -- for the related subprogram. This procedure does a preanalysis of the
- -- expressions in the pragma as "spec expressions" (see section in Sem
- -- "Handling of Default and Per-Object Expressions...").
+ -- Perform preanalysis of pragma Test_Case that applies to a subprogram
+ -- declaration. Parameter N denotes the pragma, S is the entity of the
+ -- related subprogram. The preanalysis of the expression is done as "spec
+ -- expression" (see section "Handling of Default and Per-Object Expressions
+ -- in Sem).
procedure Check_Applicable_Policy (N : Node_Id);
-- N is either an N_Aspect or an N_Pragma node. There are two cases. If
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index d5681492233..6913c260884 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -212,25 +212,25 @@ package body Sem_Util is
-- Add_Contract_Item --
-----------------------
- procedure Add_Contract_Item (Item : Node_Id; Subp_Id : Entity_Id) is
+ procedure Add_Contract_Item (Prag : Node_Id; Subp_Id : Entity_Id) is
Items : constant Node_Id := Contract (Subp_Id);
Nam : Name_Id;
begin
- if Present (Items) and then Nkind (Item) = N_Pragma then
- Nam := Pragma_Name (Item);
+ -- The related subprogram [body] must have a contract and the item to be
+ -- added must be a pragma.
- if Nam_In (Nam, Name_Precondition, Name_Postcondition) then
- Set_Next_Pragma (Item, Pre_Post_Conditions (Items));
- Set_Pre_Post_Conditions (Items, Item);
+ pragma Assert (Present (Items));
+ pragma Assert (Nkind (Prag) = N_Pragma);
- elsif Nam_In (Nam, Name_Contract_Cases, Name_Test_Case) then
- Set_Next_Pragma (Item, Contract_Test_Cases (Items));
- Set_Contract_Test_Cases (Items, Item);
+ Nam := Pragma_Name (Prag);
- elsif Nam_In (Nam, Name_Depends, Name_Global) then
- Set_Next_Pragma (Item, Classifications (Items));
- Set_Classifications (Items, Item);
+ -- Contract items related to subprogram bodies
+
+ if Ekind (Subp_Id) = E_Subprogram_Body then
+ if Nam_In (Nam, Name_Refined_Depends, Name_Refined_Global) then
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
-- The pragma is not a proper contract item
@@ -238,10 +238,26 @@ package body Sem_Util is
raise Program_Error;
end if;
- -- The subprogram has not been properly decorated or the item is illegal
+ -- Contract items related to subprogram declarations
else
- raise Program_Error;
+ if Nam_In (Nam, Name_Precondition, Name_Postcondition) then
+ Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
+ Set_Pre_Post_Conditions (Items, Prag);
+
+ elsif Nam_In (Nam, Name_Contract_Cases, Name_Test_Case) then
+ Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
+ Set_Contract_Test_Cases (Items, Prag);
+
+ elsif Nam_In (Nam, Name_Depends, Name_Global) then
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
+
+ -- The pragma is not a proper contract item
+
+ else
+ raise Program_Error;
+ end if;
end if;
end Add_Contract_Item;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 7ea5657aa2b..3053bee8dcd 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -43,10 +43,17 @@ package Sem_Util is
-- Add A to the list of access types to process when expanding the
-- freeze node of E.
- procedure Add_Contract_Item (Item : Node_Id; Subp_Id : Entity_Id);
- -- Add a contract item (pragma Precondition, Postcondition, Test_Case,
- -- Contract_Cases, Global, Depends) to the contract of a subprogram. Item
- -- denotes a pragma and Subp_Id is the related subprogram.
+ procedure Add_Contract_Item (Prag : Node_Id; Subp_Id : Entity_Id);
+ -- Add one of the following contract item to the contract of a subprogram.
+ -- Prag denotes a pragma and Subp_Id is the related subprogram [body].
+ -- Contract_Cases
+ -- Depends
+ -- Global
+ -- Postcondition
+ -- Precondition
+ -- Refined_Depends
+ -- Refined_Global
+ -- Test_Case
procedure Add_Global_Declaration (N : Node_Id);
-- These procedures adds a declaration N at the library level, to be
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 149d4c411ce..83a1606cb38 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -7143,11 +7143,10 @@ package Sinfo is
--------------
-- This node is used to hold the various parts of an entry or subprogram
- -- contract, consisting in pre- and postconditions on the one hand, and
- -- test-cases on the other hand.
+ -- [body] contract, consisting of precondition, postconditions, contract
+ -- cases, test cases and global dependencies.
- -- It is referenced from an entry, a subprogram or a generic subprogram
- -- entity.
+ -- The node appears in an entry and [generic] subprogram [body] entity.
-- Sprint syntax: <none> as the node should not appear in the tree, but
-- only attached to an entry or [generic] subprogram
@@ -7160,9 +7159,10 @@ package Sinfo is
-- Classifications (Node3) (set to Empty if none)
-- Pre_Post_Conditions contains a collection of pragmas that correspond
- -- to pre- and postconditions associated with an entry or a subprogram.
- -- The pragmas can either come from source or be the byproduct of aspect
- -- expansion. The ordering in the list is in LIFO fashion.
+ -- to pre- and postconditions associated with an entry or a subprogram
+ -- [body or stub]. The pragmas can either come from source or be the
+ -- byproduct of aspect expansion. The ordering in the list is in LIFO
+ -- fashion.
-- Note that there might be multiple preconditions or postconditions
-- in this list, either because they come from separate pragmas in the
@@ -7175,8 +7175,8 @@ package Sinfo is
-- Classifications contains pragmas that either categorize subprogram
-- inputs and outputs or establish dependencies between them. Currently
- -- pragmas Depends and Global are stored in this list. The ordering is
- -- in LIFO fashion.
+ -- pragmas Depends, Global, Refined_Depends and Refined_Global are
+ -- stored in this list. The ordering is in LIFO fashion.
-------------------
-- Expanded_Name --
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index 9752d2b16f9..8aed6308bae 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -580,6 +580,8 @@ package Snames is
Name_Pure_05 : constant Name_Id := N + $; -- GNAT
Name_Pure_12 : constant Name_Id := N + $; -- GNAT
Name_Pure_Function : constant Name_Id := N + $; -- GNAT
+ Name_Refined_Depends : constant Name_Id := N + $; -- GNAT
+ Name_Refined_Global : constant Name_Id := N + $; -- GNAT
Name_Refined_Post : constant Name_Id := N + $; -- GNAT
Name_Refined_Pre : constant Name_Id := N + $; -- GNAT
Name_Relative_Deadline : constant Name_Id := N + $; -- Ada 05
@@ -1865,6 +1867,8 @@ package Snames is
Pragma_Pure_05,
Pragma_Pure_12,
Pragma_Pure_Function,
+ Pragma_Refined_Depends,
+ Pragma_Refined_Global,
Pragma_Refined_Post,
Pragma_Refined_Pre,
Pragma_Relative_Deadline,
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index 19e633ab209..4888d69e190 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -172,7 +172,7 @@ package Types is
for Physical_Line_Number'Size use 32;
-- Line number type, used for storing physical line numbers (i.e. line
-- numbers in the physical file being compiled, unaffected by the presence
- -- of source reference pragmas.
+ -- of source reference pragmas).
type Column_Number is range 0 .. 32767;
for Column_Number'Size use 16;
OpenPOWER on IntegriCloud