summaryrefslogtreecommitdiff
path: root/gcc/ada/contracts.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/contracts.adb')
-rw-r--r--gcc/ada/contracts.adb303
1 files changed, 199 insertions, 104 deletions
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 8a35b82f55e..1bd13bd91d3 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -53,16 +53,6 @@ with Tbuild; use Tbuild;
package body Contracts is
- procedure Analyze_Contracts
- (L : List_Id;
- Freeze_Nod : Node_Id;
- Freeze_Id : Entity_Id);
- -- Subsidiary to the one parameter version of Analyze_Contracts and routine
- -- Analyze_Previous_Constracts. Analyze the contracts of all constructs in
- -- the list L. If Freeze_Nod is set, then the analysis stops when the node
- -- is reached. Freeze_Id is the entity of some related context which caused
- -- freezing up to node Freeze_Nod.
-
procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id);
-- (CodePeer): Subsidiary procedure to Analyze_Contracts which builds the
-- contract-only subprogram body of eligible subprograms found in L, adds
@@ -351,32 +341,16 @@ package body Contracts is
-----------------------
procedure Analyze_Contracts (L : List_Id) is
+ Decl : Node_Id;
+
begin
if CodePeer_Mode and then Debug_Flag_Dot_KK then
Build_And_Analyze_Contract_Only_Subprograms (L);
end if;
- Analyze_Contracts (L, Freeze_Nod => Empty, Freeze_Id => Empty);
- end Analyze_Contracts;
-
- procedure Analyze_Contracts
- (L : List_Id;
- Freeze_Nod : Node_Id;
- Freeze_Id : Entity_Id)
- is
- Decl : Node_Id;
-
- begin
Decl := First (L);
while Present (Decl) loop
- -- The caller requests that the traversal stops at a particular node
- -- that causes contract "freezing".
-
- if Present (Freeze_Nod) and then Decl = Freeze_Nod then
- exit;
- end if;
-
-- Entry or subprogram declarations
if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
@@ -388,7 +362,7 @@ package body Contracts is
Subp_Id : constant Entity_Id := Defining_Entity (Decl);
begin
- Analyze_Entry_Or_Subprogram_Contract (Subp_Id, Freeze_Id);
+ Analyze_Entry_Or_Subprogram_Contract (Subp_Id);
-- If analysis of a class-wide pre/postcondition indicates
-- that a class-wide clone is needed, analyze its declaration
@@ -410,9 +384,7 @@ package body Contracts is
-- Objects
elsif Nkind (Decl) = N_Object_Declaration then
- Analyze_Object_Contract
- (Obj_Id => Defining_Entity (Decl),
- Freeze_Id => Freeze_Id);
+ Analyze_Object_Contract (Defining_Entity (Decl));
-- Protected units
@@ -433,8 +405,9 @@ package body Contracts is
then
Analyze_Task_Contract (Defining_Entity (Decl));
- -- For type declarations, we need to do the pre-analysis of
- -- Iterable aspect specifications.
+ -- For type declarations, we need to do the pre-analysis of Iterable
+ -- aspect specifications.
+
-- Other type aspects need to be resolved here???
elsif Nkind (Decl) = N_Private_Type_Declaration
@@ -443,6 +416,7 @@ package body Contracts is
declare
E : constant Entity_Id := Defining_Identifier (Decl);
It : constant Node_Id := Find_Aspect (E, Aspect_Iterable);
+
begin
if Present (It) then
Validate_Iterable_Aspect (E, It);
@@ -1127,76 +1101,6 @@ package body Contracts is
end Analyze_Package_Contract;
--------------------------------
- -- Analyze_Previous_Contracts --
- --------------------------------
-
- procedure Analyze_Previous_Contracts (Body_Decl : Node_Id) is
- Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
- Orig_Decl : constant Node_Id := Original_Node (Body_Decl);
-
- Par : Node_Id;
-
- begin
- -- A body that is in the process of being inlined appears from source,
- -- but carries name _parent. Such a body does not cause "freezing" of
- -- contracts.
-
- if Chars (Body_Id) = Name_uParent then
- return;
- end if;
-
- -- Climb the parent chain looking for an enclosing package body. Do not
- -- use the scope stack, as a body uses the entity of its corresponding
- -- spec.
-
- Par := Parent (Body_Decl);
- while Present (Par) loop
- if Nkind (Par) = N_Package_Body then
- Analyze_Package_Body_Contract
- (Body_Id => Defining_Entity (Par),
- Freeze_Id => Defining_Entity (Body_Decl));
-
- exit;
-
- -- Do not look for an enclosing package body when the construct which
- -- causes freezing is a body generated for an expression function and
- -- it appears within a package spec. This ensures that the traversal
- -- will not reach too far up the parent chain and attempt to freeze a
- -- package body which should not be frozen.
-
- -- package body Enclosing_Body
- -- with Refined_State => (State => Var)
- -- is
- -- package Nested is
- -- type Some_Type is ...;
- -- function Cause_Freezing return ...;
- -- private
- -- function Cause_Freezing is (...);
- -- end Nested;
- --
- -- Var : Nested.Some_Type;
-
- elsif Nkind (Par) = N_Package_Declaration
- and then Nkind (Orig_Decl) = N_Expression_Function
- then
- exit;
- end if;
-
- Par := Parent (Par);
- end loop;
-
- -- Analyze the contracts of all eligible construct up to the body which
- -- caused the "freezing".
-
- if Is_List_Member (Body_Decl) then
- Analyze_Contracts
- (L => List_Containing (Body_Decl),
- Freeze_Nod => Body_Decl,
- Freeze_Id => Body_Id);
- end if;
- end Analyze_Previous_Contracts;
-
- --------------------------------
-- Analyze_Protected_Contract --
--------------------------------
@@ -2393,6 +2297,11 @@ package body Contracts is
end if;
end Process_Contract_Cases_For;
+ pragma Unmodified (Stmts);
+ -- Stmts is passed as IN OUT to signal that the list can be updated,
+ -- even if the corresponding integer value representing the list does
+ -- not change.
+
-- Start of processing for Process_Contract_Cases
begin
@@ -2535,6 +2444,11 @@ package body Contracts is
end loop;
end Process_Spec_Postconditions;
+ pragma Unmodified (Stmts);
+ -- Stmts is passed as IN OUT to signal that the list can be updated,
+ -- even if the corresponding integer value representing the list does
+ -- not change.
+
-- Start of processing for Process_Postconditions
begin
@@ -3087,6 +3001,187 @@ package body Contracts is
end if;
end Expand_Subprogram_Contract;
+ -------------------------------
+ -- Freeze_Previous_Contracts --
+ -------------------------------
+
+ procedure Freeze_Previous_Contracts (Body_Decl : Node_Id) is
+ function Causes_Contract_Freezing (N : Node_Id) return Boolean;
+ pragma Inline (Causes_Contract_Freezing);
+ -- Determine whether arbitrary node N causes contract freezing
+
+ procedure Freeze_Contracts;
+ pragma Inline (Freeze_Contracts);
+ -- Freeze the contracts of all eligible constructs which precede body
+ -- Body_Decl.
+
+ procedure Freeze_Enclosing_Package_Body;
+ pragma Inline (Freeze_Enclosing_Package_Body);
+ -- Freeze the contract of the nearest package body (if any) which
+ -- encloses body Body_Decl.
+
+ ------------------------------
+ -- Causes_Contract_Freezing --
+ ------------------------------
+
+ function Causes_Contract_Freezing (N : Node_Id) return Boolean is
+ begin
+ return Nkind_In (N, N_Entry_Body,
+ N_Package_Body,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Subprogram_Body_Stub,
+ N_Task_Body);
+ end Causes_Contract_Freezing;
+
+ ----------------------
+ -- Freeze_Contracts --
+ ----------------------
+
+ procedure Freeze_Contracts is
+ Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
+ Decl : Node_Id;
+
+ begin
+ -- Nothing to do when the body which causes freezing does not appear
+ -- in a declarative list because there cannot possibly be constructs
+ -- with contracts.
+
+ if not Is_List_Member (Body_Decl) then
+ return;
+ end if;
+
+ -- Inspect the declarations preceding the body, and freeze individual
+ -- contracts of eligible constructs.
+
+ Decl := Prev (Body_Decl);
+ while Present (Decl) loop
+
+ -- Stop the traversal when a preceding construct that causes
+ -- freezing is encountered as there is no point in refreezing
+ -- the already frozen constructs.
+
+ if Causes_Contract_Freezing (Decl) then
+ exit;
+
+ -- Entry or subprogram declarations
+
+ elsif Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
+ N_Entry_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Subprogram_Declaration)
+ then
+ Analyze_Entry_Or_Subprogram_Contract
+ (Subp_Id => Defining_Entity (Decl),
+ Freeze_Id => Body_Id);
+
+ -- Objects
+
+ elsif Nkind (Decl) = N_Object_Declaration then
+ Analyze_Object_Contract
+ (Obj_Id => Defining_Entity (Decl),
+ Freeze_Id => Body_Id);
+
+ -- Protected units
+
+ elsif Nkind_In (Decl, N_Protected_Type_Declaration,
+ N_Single_Protected_Declaration)
+ then
+ Analyze_Protected_Contract (Defining_Entity (Decl));
+
+ -- Subprogram body stubs
+
+ elsif Nkind (Decl) = N_Subprogram_Body_Stub then
+ Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
+
+ -- Task units
+
+ elsif Nkind_In (Decl, N_Single_Task_Declaration,
+ N_Task_Type_Declaration)
+ then
+ Analyze_Task_Contract (Defining_Entity (Decl));
+ end if;
+
+ Prev (Decl);
+ end loop;
+ end Freeze_Contracts;
+
+ -----------------------------------
+ -- Freeze_Enclosing_Package_Body --
+ -----------------------------------
+
+ procedure Freeze_Enclosing_Package_Body is
+ Orig_Decl : constant Node_Id := Original_Node (Body_Decl);
+ Par : Node_Id;
+
+ begin
+ -- Climb the parent chain looking for an enclosing package body. Do
+ -- not use the scope stack, because a body utilizes the entity of its
+ -- corresponding spec.
+
+ Par := Parent (Body_Decl);
+ while Present (Par) loop
+ if Nkind (Par) = N_Package_Body then
+ Analyze_Package_Body_Contract
+ (Body_Id => Defining_Entity (Par),
+ Freeze_Id => Defining_Entity (Body_Decl));
+
+ exit;
+
+ -- Do not look for an enclosing package body when the construct
+ -- which causes freezing is a body generated for an expression
+ -- function and it appears within a package spec. This ensures
+ -- that the traversal will not reach too far up the parent chain
+ -- and attempt to freeze a package body which must not be frozen.
+
+ -- package body Enclosing_Body
+ -- with Refined_State => (State => Var)
+ -- is
+ -- package Nested is
+ -- type Some_Type is ...;
+ -- function Cause_Freezing return ...;
+ -- private
+ -- function Cause_Freezing is (...);
+ -- end Nested;
+ --
+ -- Var : Nested.Some_Type;
+
+ elsif Nkind (Par) = N_Package_Declaration
+ and then Nkind (Orig_Decl) = N_Expression_Function
+ then
+ exit;
+
+ -- Prevent the search from going too far
+
+ elsif Is_Body_Or_Package_Declaration (Par) then
+ exit;
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+ end Freeze_Enclosing_Package_Body;
+
+ -- Local variables
+
+ Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
+
+ -- Start of processing for Freeze_Previous_Contracts
+
+ begin
+ pragma Assert (Causes_Contract_Freezing (Body_Decl));
+
+ -- A body that is in the process of being inlined appears from source,
+ -- but carries name _parent. Such a body does not cause freezing of
+ -- contracts.
+
+ if Chars (Body_Id) = Name_uParent then
+ return;
+ end if;
+
+ Freeze_Enclosing_Package_Body;
+ Freeze_Contracts;
+ end Freeze_Previous_Contracts;
+
---------------------------------
-- Inherit_Subprogram_Contract --
---------------------------------