1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- C O N T R A C T S --
9 -- Copyright (C) 2015-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 -- This package contains routines that perform analysis and expansion of
29 with Types
; use Types
;
33 procedure Add_Contract_Item
(Prag
: Node_Id
; Id
: Entity_Id
);
34 -- Add pragma Prag to the contract of a constant, entry, entry family,
35 -- [generic] package, package body, protected unit, [generic] subprogram,
36 -- subprogram body, variable, task unit, or type denoted by Id.
37 -- The following are valid pragmas:
44 -- Constant_After_Elaboration
67 procedure Analyze_Contracts
(L
: List_Id
);
68 -- Analyze the contracts of all eligible constructs found in list L
70 procedure Analyze_Pragmas_In_Declarations
(Body_Id
: Entity_Id
);
71 -- Perform early analysis of pragmas at the top of a given subprogram's
74 -- The purpose of this is to analyze contract-related pragmas for later
75 -- processing, but also to handle other such pragmas before these
76 -- declarations get moved to an internal wrapper as part of contract
77 -- expansion. For example, pragmas Inline, Ghost, Volatile all need to
78 -- apply directly to the subprogram and not be moved to a wrapper.
80 procedure Analyze_Entry_Or_Subprogram_Body_Contract
(Body_Id
: Entity_Id
);
81 -- Analyze all delayed pragmas chained on the contract of entry or
82 -- subprogram body Body_Id as if they appeared at the end of a declarative
83 -- region. Pragmas in question are:
85 -- Always_Terminates (stand alone subprogram body)
86 -- Contract_Cases (stand alone subprogram body)
87 -- Depends (stand alone subprogram body)
88 -- Exceptional_Cases (stand alone subprogram body)
89 -- Global (stand alone subprogram body)
90 -- Postcondition (stand alone subprogram body)
91 -- Precondition (stand alone subprogram body)
95 -- Subprogram_Variant (stand alone subprogram body)
96 -- Test_Case (stand alone subprogram body)
98 procedure Analyze_Entry_Or_Subprogram_Contract
100 Freeze_Id
: Entity_Id
:= Empty
);
101 -- Analyze all delayed pragmas chained on the contract of entry or
102 -- subprogram Subp_Id as if they appeared at the end of a declarative
103 -- region. The pragmas in question are:
112 -- Subprogram_Variant
115 -- Freeze_Id is the entity of a [generic] package body or a [generic]
116 -- subprogram body which "freezes" the contract of Subp_Id.
118 procedure Analyze_Object_Contract
120 Freeze_Id
: Entity_Id
:= Empty
);
121 -- Analyze all delayed pragmas chained on the contract of object Obj_Id as
122 -- if they appeared at the end of the declarative region. The pragmas to be
127 -- Depends (single concurrent object)
130 -- Global (single concurrent object)
133 -- Freeze_Id is the entity of a [generic] package body or a [generic]
134 -- subprogram body which "freezes" the contract of Obj_Id.
136 procedure Analyze_Type_Contract
(Type_Id
: Entity_Id
);
137 -- Analyze all delayed pragmas chained on the contract of object Obj_Id as
138 -- if they appeared at the end of the declarative region. The pragmas to be
148 -- In the case of a protected or task type, there will also be
149 -- a call to Analyze_Protected_Contract or Analyze_Task_Contract.
151 procedure Analyze_Package_Body_Contract
152 (Body_Id
: Entity_Id
;
153 Freeze_Id
: Entity_Id
:= Empty
);
154 -- Analyze all delayed pragmas chained on the contract of package body
155 -- Body_Id as if they appeared at the end of a declarative region. The
156 -- pragmas that are considered are:
160 -- Freeze_Id is the entity of a [generic] package body or a [generic]
161 -- subprogram body which "freezes" the contract of Body_Id.
163 procedure Analyze_Package_Contract
(Pack_Id
: Entity_Id
);
164 -- Analyze all delayed pragmas chained on the contract of package Pack_Id
165 -- as if they appeared at the end of a declarative region. The pragmas
166 -- that are considered are:
171 procedure Analyze_Protected_Contract
(Prot_Id
: Entity_Id
);
172 -- Analyze all delayed pragmas chained on the contract of protected unit
173 -- Prot_Id if they appeared at the end of a declarative region. Currently
174 -- there are no such pragmas.
176 procedure Analyze_Subprogram_Body_Stub_Contract
(Stub_Id
: Entity_Id
);
177 -- Analyze all delayed pragmas chained on the contract of subprogram body
178 -- stub Stub_Id as if they appeared at the end of a declarative region. The
179 -- pragmas in question are:
191 -- Subprogram_Variant
194 procedure Analyze_Task_Contract
(Task_Id
: Entity_Id
);
195 -- Analyze all delayed pragmas chained on the contract of task unit Task_Id
196 -- as if they appeared at the end of a declarative region. The pragmas in
202 procedure Build_Entry_Contract_Wrapper
(E
: Entity_Id
; Decl
: Node_Id
);
203 -- Build the body of a wrapper procedure for an entry or entry family that
204 -- has contract cases, preconditions, or postconditions, and add it to the
205 -- freeze actions of the related synchronized type.
207 -- The body first verifies the preconditions and case guards of the
208 -- contract cases, then invokes the entry [family], and finally verifies
209 -- the postconditions and the consequences of the contract cases. E denotes
210 -- the entry family. Decl denotes the declaration of the enclosing
211 -- synchronized type.
213 procedure Create_Generic_Contract
(Unit
: Node_Id
);
214 -- Create a contract node for a generic package, generic subprogram, or a
215 -- generic body denoted by Unit by collecting all source contract-related
216 -- pragmas in the contract of the unit.
218 procedure Freeze_Previous_Contracts
(Body_Decl
: Node_Id
);
219 -- Freeze the contracts of all source constructs found in the declarative
220 -- list which contains entry, package, protected, subprogram, or task body
221 -- denoted by Body_Decl. In addition, freeze the contract of the nearest
222 -- enclosing package body.
224 procedure Inherit_Subprogram_Contract
226 From_Subp
: Entity_Id
);
227 -- Inherit relevant contract items from source subprogram From_Subp. Subp
228 -- denotes the destination subprogram. The inherited items are:
229 -- Extensions_Visible
230 -- ??? it would be nice if this routine handles Pre'Class and Post'Class
232 procedure Instantiate_Subprogram_Contract
(Templ
: Node_Id
; L
: List_Id
);
233 -- Instantiate all source pragmas found in the contract of the generic
234 -- subprogram declaration template denoted by Templ. The instantiated
235 -- pragmas are added to list L.
237 procedure Make_Class_Precondition_Subps
238 (Subp_Id
: Entity_Id
;
239 Late_Overriding
: Boolean := False);
240 -- Build helpers that at run time evaluate statically and dynamically the
241 -- class-wide preconditions of Subp_Id; build also the indirect-call
242 -- wrapper (ICW) required to check class-wide preconditions when the
243 -- subprogram is invoked through an access-to-subprogram, or when it
244 -- overrides an inherited class-wide precondition (see AI12-0195-1).
245 -- Late_Overriding enables special handling required for late-overriding
248 -- For example, if we have a subprogram with the following profile:
250 -- procedure Prim (Obj : TagTyp; <additional formals>)
251 -- with Pre'Class => F1 (Obj) and F2(Obj)
253 -- We build the following helper that evaluates statically the class-wide
256 -- function PrimSP (Obj : TagTyp) return Boolean is
258 -- return F1 (Obj) and F2(Obj);
261 -- ... and the following helper that evaluates dynamically the class-wide
264 -- function PrimDP (Obj : TagTyp'Class; ...) return Boolean is
266 -- return F1 (Obj) and F2(Obj);
269 -- ... and the following indirect-call wrapper (ICW) that is used by the
270 -- code generated by the compiler for indirect calls:
272 -- procedure PrimICW (Obj : TagTyp; <additional formals> is
274 -- if not PrimSP (Obj) then
275 -- $raise_assert_failure ("failed precondition in call at ...");
281 procedure Merge_Class_Conditions
(Spec_Id
: Entity_Id
);
282 -- Merge and preanalyze all class-wide conditions of Spec_Id (class-wide
283 -- preconditions merged with operator or-else; class-wide postconditions
284 -- merged with operator and-then). Ignored pre/postconditions are also
285 -- merged since, although they are not required to generate code, their
286 -- preanalysis is required to perform semantic checks. Resulting merged
287 -- expressions are later installed by the expander in helper subprograms
288 -- which are invoked from the caller side; they are also used to build
289 -- the dispatch-table wrapper (DTW), if required.
291 procedure Preanalyze_Class_Conditions
(Spec_Id
: Entity_Id
);
292 -- Preanalyze class-wide pre-/postconditions of the given subprogram
295 procedure Process_Class_Conditions_At_Freeze_Point
(Typ
: Entity_Id
);
296 -- Merge, preanalyze, and check class-wide pre/postconditions of Typ
299 procedure Save_Global_References_In_Contract
302 -- Save all global references found within the aspect specifications and
303 -- the contract-related source pragmas assocated with generic template
304 -- Templ. Gen_Id denotes the entity of the analyzed generic copy.