annotate gcc/ada/contracts.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT COMPILER COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- C O N T R A C T S --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
9 -- Copyright (C) 2015-2019, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
kono
parents:
diff changeset
17 -- for more details. You should have received a copy of the GNU General --
kono
parents:
diff changeset
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
kono
parents:
diff changeset
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
kono
parents:
diff changeset
20 -- --
kono
parents:
diff changeset
21 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
23 -- --
kono
parents:
diff changeset
24 ------------------------------------------------------------------------------
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 with Aspects; use Aspects;
kono
parents:
diff changeset
27 with Atree; use Atree;
kono
parents:
diff changeset
28 with Einfo; use Einfo;
kono
parents:
diff changeset
29 with Elists; use Elists;
kono
parents:
diff changeset
30 with Errout; use Errout;
kono
parents:
diff changeset
31 with Exp_Prag; use Exp_Prag;
kono
parents:
diff changeset
32 with Exp_Tss; use Exp_Tss;
kono
parents:
diff changeset
33 with Exp_Util; use Exp_Util;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
34 with Freeze; use Freeze;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
35 with Lib; use Lib;
111
kono
parents:
diff changeset
36 with Namet; use Namet;
kono
parents:
diff changeset
37 with Nlists; use Nlists;
kono
parents:
diff changeset
38 with Nmake; use Nmake;
kono
parents:
diff changeset
39 with Opt; use Opt;
kono
parents:
diff changeset
40 with Sem; use Sem;
kono
parents:
diff changeset
41 with Sem_Aux; use Sem_Aux;
kono
parents:
diff changeset
42 with Sem_Ch6; use Sem_Ch6;
kono
parents:
diff changeset
43 with Sem_Ch8; use Sem_Ch8;
kono
parents:
diff changeset
44 with Sem_Ch12; use Sem_Ch12;
kono
parents:
diff changeset
45 with Sem_Ch13; use Sem_Ch13;
kono
parents:
diff changeset
46 with Sem_Disp; use Sem_Disp;
kono
parents:
diff changeset
47 with Sem_Prag; use Sem_Prag;
kono
parents:
diff changeset
48 with Sem_Util; use Sem_Util;
kono
parents:
diff changeset
49 with Sinfo; use Sinfo;
kono
parents:
diff changeset
50 with Snames; use Snames;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
51 with Stand; use Stand;
111
kono
parents:
diff changeset
52 with Stringt; use Stringt;
kono
parents:
diff changeset
53 with Tbuild; use Tbuild;
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 package body Contracts is
kono
parents:
diff changeset
56
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
57 procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
58 -- Analyze all delayed pragmas chained on the contract of package
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
59 -- instantiation Inst_Id as if they appear at the end of a declarative
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
60 -- region. The pragmas in question are:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
61 --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
62 -- Part_Of
111
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
kono
parents:
diff changeset
65 -- Expand the contracts of a subprogram body and its correspoding spec (if
kono
parents:
diff changeset
66 -- any). This routine processes all [refined] pre- and postconditions as
kono
parents:
diff changeset
67 -- well as Contract_Cases, invariants and predicates. Body_Id denotes the
kono
parents:
diff changeset
68 -- entity of the subprogram body.
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 -----------------------
kono
parents:
diff changeset
71 -- Add_Contract_Item --
kono
parents:
diff changeset
72 -----------------------
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
kono
parents:
diff changeset
75 Items : Node_Id := Contract (Id);
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 procedure Add_Classification;
kono
parents:
diff changeset
78 -- Prepend Prag to the list of classifications
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 procedure Add_Contract_Test_Case;
kono
parents:
diff changeset
81 -- Prepend Prag to the list of contract and test cases
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 procedure Add_Pre_Post_Condition;
kono
parents:
diff changeset
84 -- Prepend Prag to the list of pre- and postconditions
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 ------------------------
kono
parents:
diff changeset
87 -- Add_Classification --
kono
parents:
diff changeset
88 ------------------------
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 procedure Add_Classification is
kono
parents:
diff changeset
91 begin
kono
parents:
diff changeset
92 Set_Next_Pragma (Prag, Classifications (Items));
kono
parents:
diff changeset
93 Set_Classifications (Items, Prag);
kono
parents:
diff changeset
94 end Add_Classification;
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 ----------------------------
kono
parents:
diff changeset
97 -- Add_Contract_Test_Case --
kono
parents:
diff changeset
98 ----------------------------
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 procedure Add_Contract_Test_Case is
kono
parents:
diff changeset
101 begin
kono
parents:
diff changeset
102 Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
kono
parents:
diff changeset
103 Set_Contract_Test_Cases (Items, Prag);
kono
parents:
diff changeset
104 end Add_Contract_Test_Case;
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 ----------------------------
kono
parents:
diff changeset
107 -- Add_Pre_Post_Condition --
kono
parents:
diff changeset
108 ----------------------------
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 procedure Add_Pre_Post_Condition is
kono
parents:
diff changeset
111 begin
kono
parents:
diff changeset
112 Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
kono
parents:
diff changeset
113 Set_Pre_Post_Conditions (Items, Prag);
kono
parents:
diff changeset
114 end Add_Pre_Post_Condition;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 -- Local variables
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 -- A contract must contain only pragmas
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 pragma Assert (Nkind (Prag) = N_Pragma);
kono
parents:
diff changeset
121 Prag_Nam : constant Name_Id := Pragma_Name (Prag);
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 -- Start of processing for Add_Contract_Item
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 begin
kono
parents:
diff changeset
126 -- Create a new contract when adding the first item
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 if No (Items) then
kono
parents:
diff changeset
129 Items := Make_Contract (Sloc (Id));
kono
parents:
diff changeset
130 Set_Contract (Id, Items);
kono
parents:
diff changeset
131 end if;
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 -- Constants, the applicable pragmas are:
kono
parents:
diff changeset
134 -- Part_Of
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 if Ekind (Id) = E_Constant then
kono
parents:
diff changeset
137 if Prag_Nam = Name_Part_Of then
kono
parents:
diff changeset
138 Add_Classification;
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 -- The pragma is not a proper contract item
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 else
kono
parents:
diff changeset
143 raise Program_Error;
kono
parents:
diff changeset
144 end if;
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 -- Entry bodies, the applicable pragmas are:
kono
parents:
diff changeset
147 -- Refined_Depends
kono
parents:
diff changeset
148 -- Refined_Global
kono
parents:
diff changeset
149 -- Refined_Post
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 elsif Is_Entry_Body (Id) then
kono
parents:
diff changeset
152 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
kono
parents:
diff changeset
153 Add_Classification;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 elsif Prag_Nam = Name_Refined_Post then
kono
parents:
diff changeset
156 Add_Pre_Post_Condition;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 -- The pragma is not a proper contract item
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 else
kono
parents:
diff changeset
161 raise Program_Error;
kono
parents:
diff changeset
162 end if;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 -- Entry or subprogram declarations, the applicable pragmas are:
kono
parents:
diff changeset
165 -- Attach_Handler
kono
parents:
diff changeset
166 -- Contract_Cases
kono
parents:
diff changeset
167 -- Depends
kono
parents:
diff changeset
168 -- Extensions_Visible
kono
parents:
diff changeset
169 -- Global
kono
parents:
diff changeset
170 -- Interrupt_Handler
kono
parents:
diff changeset
171 -- Postcondition
kono
parents:
diff changeset
172 -- Precondition
kono
parents:
diff changeset
173 -- Test_Case
kono
parents:
diff changeset
174 -- Volatile_Function
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 elsif Is_Entry_Declaration (Id)
kono
parents:
diff changeset
177 or else Ekind_In (Id, E_Function,
kono
parents:
diff changeset
178 E_Generic_Function,
kono
parents:
diff changeset
179 E_Generic_Procedure,
kono
parents:
diff changeset
180 E_Procedure)
kono
parents:
diff changeset
181 then
kono
parents:
diff changeset
182 if Nam_In (Prag_Nam, Name_Attach_Handler, Name_Interrupt_Handler)
kono
parents:
diff changeset
183 and then Ekind_In (Id, E_Generic_Procedure, E_Procedure)
kono
parents:
diff changeset
184 then
kono
parents:
diff changeset
185 Add_Classification;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 elsif Nam_In (Prag_Nam, Name_Depends,
kono
parents:
diff changeset
188 Name_Extensions_Visible,
kono
parents:
diff changeset
189 Name_Global)
kono
parents:
diff changeset
190 then
kono
parents:
diff changeset
191 Add_Classification;
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 elsif Prag_Nam = Name_Volatile_Function
kono
parents:
diff changeset
194 and then Ekind_In (Id, E_Function, E_Generic_Function)
kono
parents:
diff changeset
195 then
kono
parents:
diff changeset
196 Add_Classification;
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 elsif Nam_In (Prag_Nam, Name_Contract_Cases, Name_Test_Case) then
kono
parents:
diff changeset
199 Add_Contract_Test_Case;
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 elsif Nam_In (Prag_Nam, Name_Postcondition, Name_Precondition) then
kono
parents:
diff changeset
202 Add_Pre_Post_Condition;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 -- The pragma is not a proper contract item
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 else
kono
parents:
diff changeset
207 raise Program_Error;
kono
parents:
diff changeset
208 end if;
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 -- Packages or instantiations, the applicable pragmas are:
kono
parents:
diff changeset
211 -- Abstract_States
kono
parents:
diff changeset
212 -- Initial_Condition
kono
parents:
diff changeset
213 -- Initializes
kono
parents:
diff changeset
214 -- Part_Of (instantiation only)
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 elsif Ekind_In (Id, E_Generic_Package, E_Package) then
kono
parents:
diff changeset
217 if Nam_In (Prag_Nam, Name_Abstract_State,
kono
parents:
diff changeset
218 Name_Initial_Condition,
kono
parents:
diff changeset
219 Name_Initializes)
kono
parents:
diff changeset
220 then
kono
parents:
diff changeset
221 Add_Classification;
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 -- Indicator Part_Of must be associated with a package instantiation
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 elsif Prag_Nam = Name_Part_Of and then Is_Generic_Instance (Id) then
kono
parents:
diff changeset
226 Add_Classification;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 -- The pragma is not a proper contract item
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 else
kono
parents:
diff changeset
231 raise Program_Error;
kono
parents:
diff changeset
232 end if;
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 -- Package bodies, the applicable pragmas are:
kono
parents:
diff changeset
235 -- Refined_States
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 elsif Ekind (Id) = E_Package_Body then
kono
parents:
diff changeset
238 if Prag_Nam = Name_Refined_State then
kono
parents:
diff changeset
239 Add_Classification;
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 -- The pragma is not a proper contract item
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 else
kono
parents:
diff changeset
244 raise Program_Error;
kono
parents:
diff changeset
245 end if;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 -- Protected units, the applicable pragmas are:
kono
parents:
diff changeset
248 -- Part_Of
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 elsif Ekind (Id) = E_Protected_Type then
kono
parents:
diff changeset
251 if Prag_Nam = Name_Part_Of then
kono
parents:
diff changeset
252 Add_Classification;
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 -- The pragma is not a proper contract item
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 else
kono
parents:
diff changeset
257 raise Program_Error;
kono
parents:
diff changeset
258 end if;
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 -- Subprogram bodies, the applicable pragmas are:
kono
parents:
diff changeset
261 -- Postcondition
kono
parents:
diff changeset
262 -- Precondition
kono
parents:
diff changeset
263 -- Refined_Depends
kono
parents:
diff changeset
264 -- Refined_Global
kono
parents:
diff changeset
265 -- Refined_Post
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 elsif Ekind (Id) = E_Subprogram_Body then
kono
parents:
diff changeset
268 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
kono
parents:
diff changeset
269 Add_Classification;
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 elsif Nam_In (Prag_Nam, Name_Postcondition,
kono
parents:
diff changeset
272 Name_Precondition,
kono
parents:
diff changeset
273 Name_Refined_Post)
kono
parents:
diff changeset
274 then
kono
parents:
diff changeset
275 Add_Pre_Post_Condition;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 -- The pragma is not a proper contract item
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 else
kono
parents:
diff changeset
280 raise Program_Error;
kono
parents:
diff changeset
281 end if;
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 -- Task bodies, the applicable pragmas are:
kono
parents:
diff changeset
284 -- Refined_Depends
kono
parents:
diff changeset
285 -- Refined_Global
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 elsif Ekind (Id) = E_Task_Body then
kono
parents:
diff changeset
288 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
kono
parents:
diff changeset
289 Add_Classification;
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 -- The pragma is not a proper contract item
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 else
kono
parents:
diff changeset
294 raise Program_Error;
kono
parents:
diff changeset
295 end if;
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 -- Task units, the applicable pragmas are:
kono
parents:
diff changeset
298 -- Depends
kono
parents:
diff changeset
299 -- Global
kono
parents:
diff changeset
300 -- Part_Of
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 elsif Ekind (Id) = E_Task_Type then
kono
parents:
diff changeset
303 if Nam_In (Prag_Nam, Name_Depends, Name_Global, Name_Part_Of) then
kono
parents:
diff changeset
304 Add_Classification;
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 -- The pragma is not a proper contract item
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 else
kono
parents:
diff changeset
309 raise Program_Error;
kono
parents:
diff changeset
310 end if;
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 -- Variables, the applicable pragmas are:
kono
parents:
diff changeset
313 -- Async_Readers
kono
parents:
diff changeset
314 -- Async_Writers
kono
parents:
diff changeset
315 -- Constant_After_Elaboration
kono
parents:
diff changeset
316 -- Depends
kono
parents:
diff changeset
317 -- Effective_Reads
kono
parents:
diff changeset
318 -- Effective_Writes
kono
parents:
diff changeset
319 -- Global
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
320 -- No_Caching
111
kono
parents:
diff changeset
321 -- Part_Of
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 elsif Ekind (Id) = E_Variable then
kono
parents:
diff changeset
324 if Nam_In (Prag_Nam, Name_Async_Readers,
kono
parents:
diff changeset
325 Name_Async_Writers,
kono
parents:
diff changeset
326 Name_Constant_After_Elaboration,
kono
parents:
diff changeset
327 Name_Depends,
kono
parents:
diff changeset
328 Name_Effective_Reads,
kono
parents:
diff changeset
329 Name_Effective_Writes,
kono
parents:
diff changeset
330 Name_Global,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
331 Name_No_Caching,
111
kono
parents:
diff changeset
332 Name_Part_Of)
kono
parents:
diff changeset
333 then
kono
parents:
diff changeset
334 Add_Classification;
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 -- The pragma is not a proper contract item
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 else
kono
parents:
diff changeset
339 raise Program_Error;
kono
parents:
diff changeset
340 end if;
kono
parents:
diff changeset
341 end if;
kono
parents:
diff changeset
342 end Add_Contract_Item;
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 -----------------------
kono
parents:
diff changeset
345 -- Analyze_Contracts --
kono
parents:
diff changeset
346 -----------------------
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 procedure Analyze_Contracts (L : List_Id) is
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
349 Decl : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
350
111
kono
parents:
diff changeset
351 begin
kono
parents:
diff changeset
352 Decl := First (L);
kono
parents:
diff changeset
353 while Present (Decl) loop
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 -- Entry or subprogram declarations
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
kono
parents:
diff changeset
358 N_Entry_Declaration,
kono
parents:
diff changeset
359 N_Generic_Subprogram_Declaration,
kono
parents:
diff changeset
360 N_Subprogram_Declaration)
kono
parents:
diff changeset
361 then
kono
parents:
diff changeset
362 declare
kono
parents:
diff changeset
363 Subp_Id : constant Entity_Id := Defining_Entity (Decl);
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365 begin
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
366 Analyze_Entry_Or_Subprogram_Contract (Subp_Id);
111
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 -- If analysis of a class-wide pre/postcondition indicates
kono
parents:
diff changeset
369 -- that a class-wide clone is needed, analyze its declaration
kono
parents:
diff changeset
370 -- now. Its body is created when the body of the original
kono
parents:
diff changeset
371 -- operation is analyzed (and rewritten).
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 if Is_Subprogram (Subp_Id)
kono
parents:
diff changeset
374 and then Present (Class_Wide_Clone (Subp_Id))
kono
parents:
diff changeset
375 then
kono
parents:
diff changeset
376 Analyze (Unit_Declaration_Node (Class_Wide_Clone (Subp_Id)));
kono
parents:
diff changeset
377 end if;
kono
parents:
diff changeset
378 end;
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 -- Entry or subprogram bodies
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 elsif Nkind_In (Decl, N_Entry_Body, N_Subprogram_Body) then
kono
parents:
diff changeset
383 Analyze_Entry_Or_Subprogram_Body_Contract (Defining_Entity (Decl));
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 -- Objects
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 elsif Nkind (Decl) = N_Object_Declaration then
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
388 Analyze_Object_Contract (Defining_Entity (Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
389
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
390 -- Package instantiation
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
391
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
392 elsif Nkind (Decl) = N_Package_Instantiation then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
393 Analyze_Package_Instantiation_Contract (Defining_Entity (Decl));
111
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 -- Protected units
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
kono
parents:
diff changeset
398 N_Single_Protected_Declaration)
kono
parents:
diff changeset
399 then
kono
parents:
diff changeset
400 Analyze_Protected_Contract (Defining_Entity (Decl));
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 -- Subprogram body stubs
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
kono
parents:
diff changeset
405 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 -- Task units
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 elsif Nkind_In (Decl, N_Single_Task_Declaration,
kono
parents:
diff changeset
410 N_Task_Type_Declaration)
kono
parents:
diff changeset
411 then
kono
parents:
diff changeset
412 Analyze_Task_Contract (Defining_Entity (Decl));
kono
parents:
diff changeset
413
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
414 -- For type declarations, we need to do the preanalysis of Iterable
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
415 -- aspect specifications.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
416
111
kono
parents:
diff changeset
417 -- Other type aspects need to be resolved here???
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 elsif Nkind (Decl) = N_Private_Type_Declaration
kono
parents:
diff changeset
420 and then Present (Aspect_Specifications (Decl))
kono
parents:
diff changeset
421 then
kono
parents:
diff changeset
422 declare
kono
parents:
diff changeset
423 E : constant Entity_Id := Defining_Identifier (Decl);
kono
parents:
diff changeset
424 It : constant Node_Id := Find_Aspect (E, Aspect_Iterable);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
425
111
kono
parents:
diff changeset
426 begin
kono
parents:
diff changeset
427 if Present (It) then
kono
parents:
diff changeset
428 Validate_Iterable_Aspect (E, It);
kono
parents:
diff changeset
429 end if;
kono
parents:
diff changeset
430 end;
kono
parents:
diff changeset
431 end if;
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 Next (Decl);
kono
parents:
diff changeset
434 end loop;
kono
parents:
diff changeset
435 end Analyze_Contracts;
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 -----------------------------------------------
kono
parents:
diff changeset
438 -- Analyze_Entry_Or_Subprogram_Body_Contract --
kono
parents:
diff changeset
439 -----------------------------------------------
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
442 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
443 -- SPARK mode.
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 procedure Analyze_Entry_Or_Subprogram_Body_Contract (Body_Id : Entity_Id) is
kono
parents:
diff changeset
446 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
kono
parents:
diff changeset
447 Items : constant Node_Id := Contract (Body_Id);
kono
parents:
diff changeset
448 Spec_Id : constant Entity_Id := Unique_Defining_Entity (Body_Decl);
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
451 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
452 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 begin
kono
parents:
diff changeset
455 -- When a subprogram body declaration is illegal, its defining entity is
kono
parents:
diff changeset
456 -- left unanalyzed. There is nothing left to do in this case because the
kono
parents:
diff changeset
457 -- body lacks a contract, or even a proper Ekind.
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 if Ekind (Body_Id) = E_Void then
kono
parents:
diff changeset
460 return;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 elsif Present (Items) then
kono
parents:
diff changeset
465 if Analyzed (Items) then
kono
parents:
diff changeset
466 return;
kono
parents:
diff changeset
467 else
kono
parents:
diff changeset
468 Set_Analyzed (Items);
kono
parents:
diff changeset
469 end if;
kono
parents:
diff changeset
470 end if;
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 -- Due to the timing of contract analysis, delayed pragmas may be
kono
parents:
diff changeset
473 -- subject to the wrong SPARK_Mode, usually that of the enclosing
kono
parents:
diff changeset
474 -- context. To remedy this, restore the original SPARK_Mode of the
kono
parents:
diff changeset
475 -- related subprogram body.
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 Set_SPARK_Mode (Body_Id);
kono
parents:
diff changeset
478
kono
parents:
diff changeset
479 -- Ensure that the contract cases or postconditions mention 'Result or
kono
parents:
diff changeset
480 -- define a post-state.
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 Check_Result_And_Post_State (Body_Id);
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 -- A stand-alone nonvolatile function body cannot have an effectively
kono
parents:
diff changeset
485 -- volatile formal parameter or return type (SPARK RM 7.1.3(9)). This
kono
parents:
diff changeset
486 -- check is relevant only when SPARK_Mode is on, as it is not a standard
kono
parents:
diff changeset
487 -- legality rule. The check is performed here because Volatile_Function
kono
parents:
diff changeset
488 -- is processed after the analysis of the related subprogram body. The
kono
parents:
diff changeset
489 -- check only applies to source subprograms and not to generated TSS
kono
parents:
diff changeset
490 -- subprograms.
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 if SPARK_Mode = On
kono
parents:
diff changeset
493 and then Ekind_In (Body_Id, E_Function, E_Generic_Function)
kono
parents:
diff changeset
494 and then Comes_From_Source (Spec_Id)
kono
parents:
diff changeset
495 and then not Is_Volatile_Function (Body_Id)
kono
parents:
diff changeset
496 then
kono
parents:
diff changeset
497 Check_Nonvolatile_Function_Profile (Body_Id);
kono
parents:
diff changeset
498 end if;
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
501 -- pragmas have been analyzed.
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 -- Capture all global references in a generic subprogram body now that
kono
parents:
diff changeset
506 -- the contract has been analyzed.
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 if Is_Generic_Declaration_Or_Body (Body_Decl) then
kono
parents:
diff changeset
509 Save_Global_References_In_Contract
kono
parents:
diff changeset
510 (Templ => Original_Node (Body_Decl),
kono
parents:
diff changeset
511 Gen_Id => Spec_Id);
kono
parents:
diff changeset
512 end if;
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 -- Deal with preconditions, [refined] postconditions, Contract_Cases,
kono
parents:
diff changeset
515 -- invariants and predicates associated with body and its spec. Do not
kono
parents:
diff changeset
516 -- expand the contract of subprogram body stubs.
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 if Nkind (Body_Decl) = N_Subprogram_Body then
kono
parents:
diff changeset
519 Expand_Subprogram_Contract (Body_Id);
kono
parents:
diff changeset
520 end if;
kono
parents:
diff changeset
521 end Analyze_Entry_Or_Subprogram_Body_Contract;
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 ------------------------------------------
kono
parents:
diff changeset
524 -- Analyze_Entry_Or_Subprogram_Contract --
kono
parents:
diff changeset
525 ------------------------------------------
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
528 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
529 -- SPARK mode.
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 procedure Analyze_Entry_Or_Subprogram_Contract
kono
parents:
diff changeset
532 (Subp_Id : Entity_Id;
kono
parents:
diff changeset
533 Freeze_Id : Entity_Id := Empty)
kono
parents:
diff changeset
534 is
kono
parents:
diff changeset
535 Items : constant Node_Id := Contract (Subp_Id);
kono
parents:
diff changeset
536 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
539 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
540 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542 Skip_Assert_Exprs : constant Boolean :=
kono
parents:
diff changeset
543 Ekind_In (Subp_Id, E_Entry, E_Entry_Family)
kono
parents:
diff changeset
544 and then not ASIS_Mode
kono
parents:
diff changeset
545 and then not GNATprove_Mode;
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 Depends : Node_Id := Empty;
kono
parents:
diff changeset
548 Global : Node_Id := Empty;
kono
parents:
diff changeset
549 Prag : Node_Id;
kono
parents:
diff changeset
550 Prag_Nam : Name_Id;
kono
parents:
diff changeset
551
kono
parents:
diff changeset
552 begin
kono
parents:
diff changeset
553 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 if Present (Items) then
kono
parents:
diff changeset
556 if Analyzed (Items) then
kono
parents:
diff changeset
557 return;
kono
parents:
diff changeset
558 else
kono
parents:
diff changeset
559 Set_Analyzed (Items);
kono
parents:
diff changeset
560 end if;
kono
parents:
diff changeset
561 end if;
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 -- Due to the timing of contract analysis, delayed pragmas may be
kono
parents:
diff changeset
564 -- subject to the wrong SPARK_Mode, usually that of the enclosing
kono
parents:
diff changeset
565 -- context. To remedy this, restore the original SPARK_Mode of the
kono
parents:
diff changeset
566 -- related subprogram body.
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 Set_SPARK_Mode (Subp_Id);
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 -- All subprograms carry a contract, but for some it is not significant
kono
parents:
diff changeset
571 -- and should not be processed.
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 if not Has_Significant_Contract (Subp_Id) then
kono
parents:
diff changeset
574 null;
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 elsif Present (Items) then
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 -- Do not analyze the pre/postconditions of an entry declaration
kono
parents:
diff changeset
579 -- unless annotating the original tree for ASIS or GNATprove. The
kono
parents:
diff changeset
580 -- real analysis occurs when the pre/postconditons are relocated to
kono
parents:
diff changeset
581 -- the contract wrapper procedure (see Build_Contract_Wrapper).
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 if Skip_Assert_Exprs then
kono
parents:
diff changeset
584 null;
kono
parents:
diff changeset
585
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
586 -- Otherwise analyze the pre/postconditions.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
587 -- If these come from an aspect specification, their expressions
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
588 -- might include references to types that are not frozen yet, in the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
589 -- case where the body is a rewritten expression function that is a
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
590 -- completion, so freeze all types within before constructing the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
591 -- contract code.
111
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
594 declare
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
595 Bod : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
596 Freeze_Types : Boolean := False;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
597
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
598 begin
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
599 if Present (Freeze_Id) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
600 Bod := Unit_Declaration_Node (Freeze_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
601
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
602 if Nkind (Bod) = N_Subprogram_Body
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
603 and then Was_Expression_Function (Bod)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
604 and then Ekind (Subp_Id) = E_Function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
605 and then Chars (Subp_Id) = Chars (Freeze_Id)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
606 and then Subp_Id /= Freeze_Id
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
607 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
608 Freeze_Types := True;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
609 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
610 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
611
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
612 Prag := Pre_Post_Conditions (Items);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
613 while Present (Prag) loop
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
614 if Freeze_Types
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
615 and then Present (Corresponding_Aspect (Prag))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
616 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
617 Freeze_Expr_Types
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
618 (Def_Id => Subp_Id,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
619 Typ => Standard_Boolean,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
620 Expr => Expression (Corresponding_Aspect (Prag)),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
621 N => Bod);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
622 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
623
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
624 Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
625 Prag := Next_Pragma (Prag);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
626 end loop;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
627 end;
111
kono
parents:
diff changeset
628 end if;
kono
parents:
diff changeset
629
kono
parents:
diff changeset
630 -- Analyze contract-cases and test-cases
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 Prag := Contract_Test_Cases (Items);
kono
parents:
diff changeset
633 while Present (Prag) loop
kono
parents:
diff changeset
634 Prag_Nam := Pragma_Name (Prag);
kono
parents:
diff changeset
635
kono
parents:
diff changeset
636 if Prag_Nam = Name_Contract_Cases then
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 -- Do not analyze the contract cases of an entry declaration
kono
parents:
diff changeset
639 -- unless annotating the original tree for ASIS or GNATprove.
kono
parents:
diff changeset
640 -- The real analysis occurs when the contract cases are moved
kono
parents:
diff changeset
641 -- to the contract wrapper procedure (Build_Contract_Wrapper).
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 if Skip_Assert_Exprs then
kono
parents:
diff changeset
644 null;
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 -- Otherwise analyze the contract cases
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 else
kono
parents:
diff changeset
649 Analyze_Contract_Cases_In_Decl_Part (Prag, Freeze_Id);
kono
parents:
diff changeset
650 end if;
kono
parents:
diff changeset
651 else
kono
parents:
diff changeset
652 pragma Assert (Prag_Nam = Name_Test_Case);
kono
parents:
diff changeset
653 Analyze_Test_Case_In_Decl_Part (Prag);
kono
parents:
diff changeset
654 end if;
kono
parents:
diff changeset
655
kono
parents:
diff changeset
656 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
657 end loop;
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 -- Analyze classification pragmas
kono
parents:
diff changeset
660
kono
parents:
diff changeset
661 Prag := Classifications (Items);
kono
parents:
diff changeset
662 while Present (Prag) loop
kono
parents:
diff changeset
663 Prag_Nam := Pragma_Name (Prag);
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 if Prag_Nam = Name_Depends then
kono
parents:
diff changeset
666 Depends := Prag;
kono
parents:
diff changeset
667
kono
parents:
diff changeset
668 elsif Prag_Nam = Name_Global then
kono
parents:
diff changeset
669 Global := Prag;
kono
parents:
diff changeset
670 end if;
kono
parents:
diff changeset
671
kono
parents:
diff changeset
672 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
673 end loop;
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 -- Analyze Global first, as Depends may mention items classified in
kono
parents:
diff changeset
676 -- the global categorization.
kono
parents:
diff changeset
677
kono
parents:
diff changeset
678 if Present (Global) then
kono
parents:
diff changeset
679 Analyze_Global_In_Decl_Part (Global);
kono
parents:
diff changeset
680 end if;
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 -- Depends must be analyzed after Global in order to see the modes of
kono
parents:
diff changeset
683 -- all global items.
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 if Present (Depends) then
kono
parents:
diff changeset
686 Analyze_Depends_In_Decl_Part (Depends);
kono
parents:
diff changeset
687 end if;
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 -- Ensure that the contract cases or postconditions mention 'Result
kono
parents:
diff changeset
690 -- or define a post-state.
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 Check_Result_And_Post_State (Subp_Id);
kono
parents:
diff changeset
693 end if;
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 -- A nonvolatile function cannot have an effectively volatile formal
kono
parents:
diff changeset
696 -- parameter or return type (SPARK RM 7.1.3(9)). This check is relevant
kono
parents:
diff changeset
697 -- only when SPARK_Mode is on, as it is not a standard legality rule.
kono
parents:
diff changeset
698 -- The check is performed here because pragma Volatile_Function is
kono
parents:
diff changeset
699 -- processed after the analysis of the related subprogram declaration.
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 if SPARK_Mode = On
kono
parents:
diff changeset
702 and then Ekind_In (Subp_Id, E_Function, E_Generic_Function)
kono
parents:
diff changeset
703 and then Comes_From_Source (Subp_Id)
kono
parents:
diff changeset
704 and then not Is_Volatile_Function (Subp_Id)
kono
parents:
diff changeset
705 then
kono
parents:
diff changeset
706 Check_Nonvolatile_Function_Profile (Subp_Id);
kono
parents:
diff changeset
707 end if;
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
710 -- pragmas have been analyzed.
kono
parents:
diff changeset
711
kono
parents:
diff changeset
712 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 -- Capture all global references in a generic subprogram now that the
kono
parents:
diff changeset
715 -- contract has been analyzed.
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 if Is_Generic_Declaration_Or_Body (Subp_Decl) then
kono
parents:
diff changeset
718 Save_Global_References_In_Contract
kono
parents:
diff changeset
719 (Templ => Original_Node (Subp_Decl),
kono
parents:
diff changeset
720 Gen_Id => Subp_Id);
kono
parents:
diff changeset
721 end if;
kono
parents:
diff changeset
722 end Analyze_Entry_Or_Subprogram_Contract;
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 -----------------------------
kono
parents:
diff changeset
725 -- Analyze_Object_Contract --
kono
parents:
diff changeset
726 -----------------------------
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
729 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
730 -- SPARK mode.
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 procedure Analyze_Object_Contract
kono
parents:
diff changeset
733 (Obj_Id : Entity_Id;
kono
parents:
diff changeset
734 Freeze_Id : Entity_Id := Empty)
kono
parents:
diff changeset
735 is
kono
parents:
diff changeset
736 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
739 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
740 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 AR_Val : Boolean := False;
kono
parents:
diff changeset
743 AW_Val : Boolean := False;
kono
parents:
diff changeset
744 ER_Val : Boolean := False;
kono
parents:
diff changeset
745 EW_Val : Boolean := False;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
746 NC_Val : Boolean := False;
111
kono
parents:
diff changeset
747 Items : Node_Id;
kono
parents:
diff changeset
748 Prag : Node_Id;
kono
parents:
diff changeset
749 Ref_Elmt : Elmt_Id;
kono
parents:
diff changeset
750 Seen : Boolean := False;
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 begin
kono
parents:
diff changeset
753 -- The loop parameter in an element iterator over a formal container
kono
parents:
diff changeset
754 -- is declared with an object declaration, but no contracts apply.
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 if Ekind (Obj_Id) = E_Loop_Parameter then
kono
parents:
diff changeset
757 return;
kono
parents:
diff changeset
758 end if;
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
761
kono
parents:
diff changeset
762 Items := Contract (Obj_Id);
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 if Present (Items) then
kono
parents:
diff changeset
765 if Analyzed (Items) then
kono
parents:
diff changeset
766 return;
kono
parents:
diff changeset
767 else
kono
parents:
diff changeset
768 Set_Analyzed (Items);
kono
parents:
diff changeset
769 end if;
kono
parents:
diff changeset
770 end if;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 -- The anonymous object created for a single concurrent type inherits
kono
parents:
diff changeset
773 -- the SPARK_Mode from the type. Due to the timing of contract analysis,
kono
parents:
diff changeset
774 -- delayed pragmas may be subject to the wrong SPARK_Mode, usually that
kono
parents:
diff changeset
775 -- of the enclosing context. To remedy this, restore the original mode
kono
parents:
diff changeset
776 -- of the related anonymous object.
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 if Is_Single_Concurrent_Object (Obj_Id)
kono
parents:
diff changeset
779 and then Present (SPARK_Pragma (Obj_Id))
kono
parents:
diff changeset
780 then
kono
parents:
diff changeset
781 Set_SPARK_Mode (Obj_Id);
kono
parents:
diff changeset
782 end if;
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 -- Constant-related checks
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 if Ekind (Obj_Id) = E_Constant then
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 -- Analyze indicator Part_Of
kono
parents:
diff changeset
789
kono
parents:
diff changeset
790 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 -- Check whether the lack of indicator Part_Of agrees with the
kono
parents:
diff changeset
793 -- placement of the constant with respect to the state space.
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 if No (Prag) then
kono
parents:
diff changeset
796 Check_Missing_Part_Of (Obj_Id);
kono
parents:
diff changeset
797 end if;
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
kono
parents:
diff changeset
800 -- This check is relevant only when SPARK_Mode is on, as it is not
kono
parents:
diff changeset
801 -- a standard Ada legality rule. Internally-generated constants that
kono
parents:
diff changeset
802 -- map generic formals to actuals in instantiations are allowed to
kono
parents:
diff changeset
803 -- be volatile.
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 if SPARK_Mode = On
kono
parents:
diff changeset
806 and then Comes_From_Source (Obj_Id)
kono
parents:
diff changeset
807 and then Is_Effectively_Volatile (Obj_Id)
kono
parents:
diff changeset
808 and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
kono
parents:
diff changeset
809 then
kono
parents:
diff changeset
810 Error_Msg_N ("constant cannot be volatile", Obj_Id);
kono
parents:
diff changeset
811 end if;
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 -- Variable-related checks
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 else pragma Assert (Ekind (Obj_Id) = E_Variable);
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 -- Analyze all external properties
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 if Present (Prag) then
kono
parents:
diff changeset
822 Analyze_External_Property_In_Decl_Part (Prag, AR_Val);
kono
parents:
diff changeset
823 Seen := True;
kono
parents:
diff changeset
824 end if;
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 Prag := Get_Pragma (Obj_Id, Pragma_Async_Writers);
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 if Present (Prag) then
kono
parents:
diff changeset
829 Analyze_External_Property_In_Decl_Part (Prag, AW_Val);
kono
parents:
diff changeset
830 Seen := True;
kono
parents:
diff changeset
831 end if;
kono
parents:
diff changeset
832
kono
parents:
diff changeset
833 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Reads);
kono
parents:
diff changeset
834
kono
parents:
diff changeset
835 if Present (Prag) then
kono
parents:
diff changeset
836 Analyze_External_Property_In_Decl_Part (Prag, ER_Val);
kono
parents:
diff changeset
837 Seen := True;
kono
parents:
diff changeset
838 end if;
kono
parents:
diff changeset
839
kono
parents:
diff changeset
840 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Writes);
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 if Present (Prag) then
kono
parents:
diff changeset
843 Analyze_External_Property_In_Decl_Part (Prag, EW_Val);
kono
parents:
diff changeset
844 Seen := True;
kono
parents:
diff changeset
845 end if;
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 -- Verify the mutual interaction of the various external properties
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 if Seen then
kono
parents:
diff changeset
850 Check_External_Properties (Obj_Id, AR_Val, AW_Val, ER_Val, EW_Val);
kono
parents:
diff changeset
851 end if;
kono
parents:
diff changeset
852
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
853 -- Analyze the non-external volatility property No_Caching
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
854
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
855 Prag := Get_Pragma (Obj_Id, Pragma_No_Caching);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
856
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
857 if Present (Prag) then
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
858 Analyze_External_Property_In_Decl_Part (Prag, NC_Val);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
859 end if;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
860
111
kono
parents:
diff changeset
861 -- The anonymous object created for a single concurrent type carries
kono
parents:
diff changeset
862 -- pragmas Depends and Globat of the type.
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 if Is_Single_Concurrent_Object (Obj_Id) then
kono
parents:
diff changeset
865
kono
parents:
diff changeset
866 -- Analyze Global first, as Depends may mention items classified
kono
parents:
diff changeset
867 -- in the global categorization.
kono
parents:
diff changeset
868
kono
parents:
diff changeset
869 Prag := Get_Pragma (Obj_Id, Pragma_Global);
kono
parents:
diff changeset
870
kono
parents:
diff changeset
871 if Present (Prag) then
kono
parents:
diff changeset
872 Analyze_Global_In_Decl_Part (Prag);
kono
parents:
diff changeset
873 end if;
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875 -- Depends must be analyzed after Global in order to see the modes
kono
parents:
diff changeset
876 -- of all global items.
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 Prag := Get_Pragma (Obj_Id, Pragma_Depends);
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 if Present (Prag) then
kono
parents:
diff changeset
881 Analyze_Depends_In_Decl_Part (Prag);
kono
parents:
diff changeset
882 end if;
kono
parents:
diff changeset
883 end if;
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
kono
parents:
diff changeset
886
kono
parents:
diff changeset
887 -- Analyze indicator Part_Of
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 if Present (Prag) then
kono
parents:
diff changeset
890 Analyze_Part_Of_In_Decl_Part (Prag, Freeze_Id);
kono
parents:
diff changeset
891
kono
parents:
diff changeset
892 -- The variable is a constituent of a single protected/task type
kono
parents:
diff changeset
893 -- and behaves as a component of the type. Verify that references
kono
parents:
diff changeset
894 -- to the variable occur within the definition or body of the type
kono
parents:
diff changeset
895 -- (SPARK RM 9.3).
kono
parents:
diff changeset
896
kono
parents:
diff changeset
897 if Present (Encapsulating_State (Obj_Id))
kono
parents:
diff changeset
898 and then Is_Single_Concurrent_Object
kono
parents:
diff changeset
899 (Encapsulating_State (Obj_Id))
kono
parents:
diff changeset
900 and then Present (Part_Of_References (Obj_Id))
kono
parents:
diff changeset
901 then
kono
parents:
diff changeset
902 Ref_Elmt := First_Elmt (Part_Of_References (Obj_Id));
kono
parents:
diff changeset
903 while Present (Ref_Elmt) loop
kono
parents:
diff changeset
904 Check_Part_Of_Reference (Obj_Id, Node (Ref_Elmt));
kono
parents:
diff changeset
905 Next_Elmt (Ref_Elmt);
kono
parents:
diff changeset
906 end loop;
kono
parents:
diff changeset
907 end if;
kono
parents:
diff changeset
908
kono
parents:
diff changeset
909 -- Otherwise check whether the lack of indicator Part_Of agrees with
kono
parents:
diff changeset
910 -- the placement of the variable with respect to the state space.
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 else
kono
parents:
diff changeset
913 Check_Missing_Part_Of (Obj_Id);
kono
parents:
diff changeset
914 end if;
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 -- The following checks are relevant only when SPARK_Mode is on, as
kono
parents:
diff changeset
917 -- they are not standard Ada legality rules. Internally generated
kono
parents:
diff changeset
918 -- temporaries are ignored.
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 if SPARK_Mode = On and then Comes_From_Source (Obj_Id) then
kono
parents:
diff changeset
921 if Is_Effectively_Volatile (Obj_Id) then
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 -- The declaration of an effectively volatile object must
kono
parents:
diff changeset
924 -- appear at the library level (SPARK RM 7.1.3(3), C.6(6)).
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 if not Is_Library_Level_Entity (Obj_Id) then
kono
parents:
diff changeset
927 Error_Msg_N
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
928 ("volatile variable & must be declared at library level "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
929 & "(SPARK RM 7.1.3(3))", Obj_Id);
111
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 -- An object of a discriminated type cannot be effectively
kono
parents:
diff changeset
932 -- volatile except for protected objects (SPARK RM 7.1.3(5)).
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934 elsif Has_Discriminants (Obj_Typ)
kono
parents:
diff changeset
935 and then not Is_Protected_Type (Obj_Typ)
kono
parents:
diff changeset
936 then
kono
parents:
diff changeset
937 Error_Msg_N
kono
parents:
diff changeset
938 ("discriminated object & cannot be volatile", Obj_Id);
kono
parents:
diff changeset
939 end if;
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 -- The object is not effectively volatile
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943 else
kono
parents:
diff changeset
944 -- A non-effectively volatile object cannot have effectively
kono
parents:
diff changeset
945 -- volatile components (SPARK RM 7.1.3(6)).
kono
parents:
diff changeset
946
kono
parents:
diff changeset
947 if not Is_Effectively_Volatile (Obj_Id)
kono
parents:
diff changeset
948 and then Has_Volatile_Component (Obj_Typ)
kono
parents:
diff changeset
949 then
kono
parents:
diff changeset
950 Error_Msg_N
kono
parents:
diff changeset
951 ("non-volatile object & cannot have volatile components",
kono
parents:
diff changeset
952 Obj_Id);
kono
parents:
diff changeset
953 end if;
kono
parents:
diff changeset
954 end if;
kono
parents:
diff changeset
955 end if;
kono
parents:
diff changeset
956 end if;
kono
parents:
diff changeset
957
kono
parents:
diff changeset
958 -- Common checks
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 -- A Ghost object cannot be of a type that yields a synchronized
kono
parents:
diff changeset
963 -- object (SPARK RM 6.9(19)).
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 if Yields_Synchronized_Object (Obj_Typ) then
kono
parents:
diff changeset
966 Error_Msg_N ("ghost object & cannot be synchronized", Obj_Id);
kono
parents:
diff changeset
967
kono
parents:
diff changeset
968 -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and
kono
parents:
diff changeset
969 -- SPARK RM 6.9(19)).
kono
parents:
diff changeset
970
kono
parents:
diff changeset
971 elsif Is_Effectively_Volatile (Obj_Id) then
kono
parents:
diff changeset
972 Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
kono
parents:
diff changeset
973
kono
parents:
diff changeset
974 -- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)).
kono
parents:
diff changeset
975 -- One exception to this is the object that represents the dispatch
kono
parents:
diff changeset
976 -- table of a Ghost tagged type, as the symbol needs to be exported.
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 elsif Is_Exported (Obj_Id) then
kono
parents:
diff changeset
979 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
kono
parents:
diff changeset
980
kono
parents:
diff changeset
981 elsif Is_Imported (Obj_Id) then
kono
parents:
diff changeset
982 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
kono
parents:
diff changeset
983 end if;
kono
parents:
diff changeset
984 end if;
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
987 -- pragmas have been analyzed.
kono
parents:
diff changeset
988
kono
parents:
diff changeset
989 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
990 end Analyze_Object_Contract;
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 -----------------------------------
kono
parents:
diff changeset
993 -- Analyze_Package_Body_Contract --
kono
parents:
diff changeset
994 -----------------------------------
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
997 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
998 -- SPARK mode.
kono
parents:
diff changeset
999
kono
parents:
diff changeset
1000 procedure Analyze_Package_Body_Contract
kono
parents:
diff changeset
1001 (Body_Id : Entity_Id;
kono
parents:
diff changeset
1002 Freeze_Id : Entity_Id := Empty)
kono
parents:
diff changeset
1003 is
kono
parents:
diff changeset
1004 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
kono
parents:
diff changeset
1005 Items : constant Node_Id := Contract (Body_Id);
kono
parents:
diff changeset
1006 Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
kono
parents:
diff changeset
1007
kono
parents:
diff changeset
1008 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
1009 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
1010 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
1011
kono
parents:
diff changeset
1012 Ref_State : Node_Id;
kono
parents:
diff changeset
1013
kono
parents:
diff changeset
1014 begin
kono
parents:
diff changeset
1015 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
1016
kono
parents:
diff changeset
1017 if Present (Items) then
kono
parents:
diff changeset
1018 if Analyzed (Items) then
kono
parents:
diff changeset
1019 return;
kono
parents:
diff changeset
1020 else
kono
parents:
diff changeset
1021 Set_Analyzed (Items);
kono
parents:
diff changeset
1022 end if;
kono
parents:
diff changeset
1023 end if;
kono
parents:
diff changeset
1024
kono
parents:
diff changeset
1025 -- Due to the timing of contract analysis, delayed pragmas may be
kono
parents:
diff changeset
1026 -- subject to the wrong SPARK_Mode, usually that of the enclosing
kono
parents:
diff changeset
1027 -- context. To remedy this, restore the original SPARK_Mode of the
kono
parents:
diff changeset
1028 -- related package body.
kono
parents:
diff changeset
1029
kono
parents:
diff changeset
1030 Set_SPARK_Mode (Body_Id);
kono
parents:
diff changeset
1031
kono
parents:
diff changeset
1032 Ref_State := Get_Pragma (Body_Id, Pragma_Refined_State);
kono
parents:
diff changeset
1033
kono
parents:
diff changeset
1034 -- The analysis of pragma Refined_State detects whether the spec has
kono
parents:
diff changeset
1035 -- abstract states available for refinement.
kono
parents:
diff changeset
1036
kono
parents:
diff changeset
1037 if Present (Ref_State) then
kono
parents:
diff changeset
1038 Analyze_Refined_State_In_Decl_Part (Ref_State, Freeze_Id);
kono
parents:
diff changeset
1039 end if;
kono
parents:
diff changeset
1040
kono
parents:
diff changeset
1041 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
1042 -- pragmas have been analyzed.
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 -- Capture all global references in a generic package body now that the
kono
parents:
diff changeset
1047 -- contract has been analyzed.
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 if Is_Generic_Declaration_Or_Body (Body_Decl) then
kono
parents:
diff changeset
1050 Save_Global_References_In_Contract
kono
parents:
diff changeset
1051 (Templ => Original_Node (Body_Decl),
kono
parents:
diff changeset
1052 Gen_Id => Spec_Id);
kono
parents:
diff changeset
1053 end if;
kono
parents:
diff changeset
1054 end Analyze_Package_Body_Contract;
kono
parents:
diff changeset
1055
kono
parents:
diff changeset
1056 ------------------------------
kono
parents:
diff changeset
1057 -- Analyze_Package_Contract --
kono
parents:
diff changeset
1058 ------------------------------
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
1061 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
1062 -- SPARK mode.
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064 procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
kono
parents:
diff changeset
1065 Items : constant Node_Id := Contract (Pack_Id);
kono
parents:
diff changeset
1066 Pack_Decl : constant Node_Id := Unit_Declaration_Node (Pack_Id);
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
1069 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
1070 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
1071
kono
parents:
diff changeset
1072 Init : Node_Id := Empty;
kono
parents:
diff changeset
1073 Init_Cond : Node_Id := Empty;
kono
parents:
diff changeset
1074 Prag : Node_Id;
kono
parents:
diff changeset
1075 Prag_Nam : Name_Id;
kono
parents:
diff changeset
1076
kono
parents:
diff changeset
1077 begin
kono
parents:
diff changeset
1078 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 if Present (Items) then
kono
parents:
diff changeset
1081 if Analyzed (Items) then
kono
parents:
diff changeset
1082 return;
kono
parents:
diff changeset
1083 else
kono
parents:
diff changeset
1084 Set_Analyzed (Items);
kono
parents:
diff changeset
1085 end if;
kono
parents:
diff changeset
1086 end if;
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 -- Due to the timing of contract analysis, delayed pragmas may be
kono
parents:
diff changeset
1089 -- subject to the wrong SPARK_Mode, usually that of the enclosing
kono
parents:
diff changeset
1090 -- context. To remedy this, restore the original SPARK_Mode of the
kono
parents:
diff changeset
1091 -- related package.
kono
parents:
diff changeset
1092
kono
parents:
diff changeset
1093 Set_SPARK_Mode (Pack_Id);
kono
parents:
diff changeset
1094
kono
parents:
diff changeset
1095 if Present (Items) then
kono
parents:
diff changeset
1096
kono
parents:
diff changeset
1097 -- Locate and store pragmas Initial_Condition and Initializes, since
kono
parents:
diff changeset
1098 -- their order of analysis matters.
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 Prag := Classifications (Items);
kono
parents:
diff changeset
1101 while Present (Prag) loop
kono
parents:
diff changeset
1102 Prag_Nam := Pragma_Name (Prag);
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 if Prag_Nam = Name_Initial_Condition then
kono
parents:
diff changeset
1105 Init_Cond := Prag;
kono
parents:
diff changeset
1106
kono
parents:
diff changeset
1107 elsif Prag_Nam = Name_Initializes then
kono
parents:
diff changeset
1108 Init := Prag;
kono
parents:
diff changeset
1109 end if;
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
1112 end loop;
kono
parents:
diff changeset
1113
kono
parents:
diff changeset
1114 -- Analyze the initialization-related pragmas. Initializes must come
kono
parents:
diff changeset
1115 -- before Initial_Condition due to item dependencies.
kono
parents:
diff changeset
1116
kono
parents:
diff changeset
1117 if Present (Init) then
kono
parents:
diff changeset
1118 Analyze_Initializes_In_Decl_Part (Init);
kono
parents:
diff changeset
1119 end if;
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 if Present (Init_Cond) then
kono
parents:
diff changeset
1122 Analyze_Initial_Condition_In_Decl_Part (Init_Cond);
kono
parents:
diff changeset
1123 end if;
kono
parents:
diff changeset
1124 end if;
kono
parents:
diff changeset
1125
kono
parents:
diff changeset
1126 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
1127 -- pragmas have been analyzed.
kono
parents:
diff changeset
1128
kono
parents:
diff changeset
1129 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
1130
kono
parents:
diff changeset
1131 -- Capture all global references in a generic package now that the
kono
parents:
diff changeset
1132 -- contract has been analyzed.
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 if Is_Generic_Declaration_Or_Body (Pack_Decl) then
kono
parents:
diff changeset
1135 Save_Global_References_In_Contract
kono
parents:
diff changeset
1136 (Templ => Original_Node (Pack_Decl),
kono
parents:
diff changeset
1137 Gen_Id => Pack_Id);
kono
parents:
diff changeset
1138 end if;
kono
parents:
diff changeset
1139 end Analyze_Package_Contract;
kono
parents:
diff changeset
1140
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1141 --------------------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1142 -- Analyze_Package_Instantiation_Contract --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1143 --------------------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1144
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1145 -- WARNING: This routine manages SPARK regions. Return statements must be
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1146 -- replaced by gotos which jump to the end of the routine and restore the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1147 -- SPARK mode.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1148
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1149 procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id) is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1150 Inst_Spec : constant Node_Id :=
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1151 Instance_Spec (Unit_Declaration_Node (Inst_Id));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1152
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1153 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1154 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1155 -- Save the SPARK_Mode-related data to restore on exit
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1156
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1157 Pack_Id : Entity_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1158 Prag : Node_Id;
111
kono
parents:
diff changeset
1159
kono
parents:
diff changeset
1160 begin
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1161 -- Nothing to do when the package instantiation is erroneous or left
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1162 -- partially decorated.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1163
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1164 if No (Inst_Spec) then
111
kono
parents:
diff changeset
1165 return;
kono
parents:
diff changeset
1166 end if;
kono
parents:
diff changeset
1167
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1168 Pack_Id := Defining_Entity (Inst_Spec);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1169 Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1170
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1171 -- Due to the timing of contract analysis, delayed pragmas may be
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1172 -- subject to the wrong SPARK_Mode, usually that of the enclosing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1173 -- context. To remedy this, restore the original SPARK_Mode of the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1174 -- related package.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1175
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1176 Set_SPARK_Mode (Pack_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1177
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1178 -- Check whether the lack of indicator Part_Of agrees with the placement
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1179 -- of the package instantiation with respect to the state space. Nested
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1180 -- package instantiations do not need to be checked because they inherit
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1181 -- Part_Of indicator of the outermost package instantiation (see routine
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1182 -- Propagate_Part_Of in Sem_Prag).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1183
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1184 if In_Instance then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1185 null;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1186
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1187 elsif No (Prag) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1188 Check_Missing_Part_Of (Pack_Id);
111
kono
parents:
diff changeset
1189 end if;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1190
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1191 -- Restore the SPARK_Mode of the enclosing context after all delayed
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1192 -- pragmas have been analyzed.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1193
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1194 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1195 end Analyze_Package_Instantiation_Contract;
111
kono
parents:
diff changeset
1196
kono
parents:
diff changeset
1197 --------------------------------
kono
parents:
diff changeset
1198 -- Analyze_Protected_Contract --
kono
parents:
diff changeset
1199 --------------------------------
kono
parents:
diff changeset
1200
kono
parents:
diff changeset
1201 procedure Analyze_Protected_Contract (Prot_Id : Entity_Id) is
kono
parents:
diff changeset
1202 Items : constant Node_Id := Contract (Prot_Id);
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 begin
kono
parents:
diff changeset
1205 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
1206
kono
parents:
diff changeset
1207 if Present (Items) then
kono
parents:
diff changeset
1208 if Analyzed (Items) then
kono
parents:
diff changeset
1209 return;
kono
parents:
diff changeset
1210 else
kono
parents:
diff changeset
1211 Set_Analyzed (Items);
kono
parents:
diff changeset
1212 end if;
kono
parents:
diff changeset
1213 end if;
kono
parents:
diff changeset
1214 end Analyze_Protected_Contract;
kono
parents:
diff changeset
1215
kono
parents:
diff changeset
1216 -------------------------------------------
kono
parents:
diff changeset
1217 -- Analyze_Subprogram_Body_Stub_Contract --
kono
parents:
diff changeset
1218 -------------------------------------------
kono
parents:
diff changeset
1219
kono
parents:
diff changeset
1220 procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id) is
kono
parents:
diff changeset
1221 Stub_Decl : constant Node_Id := Parent (Parent (Stub_Id));
kono
parents:
diff changeset
1222 Spec_Id : constant Entity_Id := Corresponding_Spec_Of_Stub (Stub_Decl);
kono
parents:
diff changeset
1223
kono
parents:
diff changeset
1224 begin
kono
parents:
diff changeset
1225 -- A subprogram body stub may act as its own spec or as the completion
kono
parents:
diff changeset
1226 -- of a previous declaration. Depending on the context, the contract of
kono
parents:
diff changeset
1227 -- the stub may contain two sets of pragmas.
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 -- The stub is a completion, the applicable pragmas are:
kono
parents:
diff changeset
1230 -- Refined_Depends
kono
parents:
diff changeset
1231 -- Refined_Global
kono
parents:
diff changeset
1232
kono
parents:
diff changeset
1233 if Present (Spec_Id) then
kono
parents:
diff changeset
1234 Analyze_Entry_Or_Subprogram_Body_Contract (Stub_Id);
kono
parents:
diff changeset
1235
kono
parents:
diff changeset
1236 -- The stub acts as its own spec, the applicable pragmas are:
kono
parents:
diff changeset
1237 -- Contract_Cases
kono
parents:
diff changeset
1238 -- Depends
kono
parents:
diff changeset
1239 -- Global
kono
parents:
diff changeset
1240 -- Postcondition
kono
parents:
diff changeset
1241 -- Precondition
kono
parents:
diff changeset
1242 -- Test_Case
kono
parents:
diff changeset
1243
kono
parents:
diff changeset
1244 else
kono
parents:
diff changeset
1245 Analyze_Entry_Or_Subprogram_Contract (Stub_Id);
kono
parents:
diff changeset
1246 end if;
kono
parents:
diff changeset
1247 end Analyze_Subprogram_Body_Stub_Contract;
kono
parents:
diff changeset
1248
kono
parents:
diff changeset
1249 ---------------------------
kono
parents:
diff changeset
1250 -- Analyze_Task_Contract --
kono
parents:
diff changeset
1251 ---------------------------
kono
parents:
diff changeset
1252
kono
parents:
diff changeset
1253 -- WARNING: This routine manages SPARK regions. Return statements must be
kono
parents:
diff changeset
1254 -- replaced by gotos which jump to the end of the routine and restore the
kono
parents:
diff changeset
1255 -- SPARK mode.
kono
parents:
diff changeset
1256
kono
parents:
diff changeset
1257 procedure Analyze_Task_Contract (Task_Id : Entity_Id) is
kono
parents:
diff changeset
1258 Items : constant Node_Id := Contract (Task_Id);
kono
parents:
diff changeset
1259
kono
parents:
diff changeset
1260 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
kono
parents:
diff changeset
1261 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
kono
parents:
diff changeset
1262 -- Save the SPARK_Mode-related data to restore on exit
kono
parents:
diff changeset
1263
kono
parents:
diff changeset
1264 Prag : Node_Id;
kono
parents:
diff changeset
1265
kono
parents:
diff changeset
1266 begin
kono
parents:
diff changeset
1267 -- Do not analyze a contract multiple times
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 if Present (Items) then
kono
parents:
diff changeset
1270 if Analyzed (Items) then
kono
parents:
diff changeset
1271 return;
kono
parents:
diff changeset
1272 else
kono
parents:
diff changeset
1273 Set_Analyzed (Items);
kono
parents:
diff changeset
1274 end if;
kono
parents:
diff changeset
1275 end if;
kono
parents:
diff changeset
1276
kono
parents:
diff changeset
1277 -- Due to the timing of contract analysis, delayed pragmas may be
kono
parents:
diff changeset
1278 -- subject to the wrong SPARK_Mode, usually that of the enclosing
kono
parents:
diff changeset
1279 -- context. To remedy this, restore the original SPARK_Mode of the
kono
parents:
diff changeset
1280 -- related task unit.
kono
parents:
diff changeset
1281
kono
parents:
diff changeset
1282 Set_SPARK_Mode (Task_Id);
kono
parents:
diff changeset
1283
kono
parents:
diff changeset
1284 -- Analyze Global first, as Depends may mention items classified in the
kono
parents:
diff changeset
1285 -- global categorization.
kono
parents:
diff changeset
1286
kono
parents:
diff changeset
1287 Prag := Get_Pragma (Task_Id, Pragma_Global);
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 if Present (Prag) then
kono
parents:
diff changeset
1290 Analyze_Global_In_Decl_Part (Prag);
kono
parents:
diff changeset
1291 end if;
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 -- Depends must be analyzed after Global in order to see the modes of
kono
parents:
diff changeset
1294 -- all global items.
kono
parents:
diff changeset
1295
kono
parents:
diff changeset
1296 Prag := Get_Pragma (Task_Id, Pragma_Depends);
kono
parents:
diff changeset
1297
kono
parents:
diff changeset
1298 if Present (Prag) then
kono
parents:
diff changeset
1299 Analyze_Depends_In_Decl_Part (Prag);
kono
parents:
diff changeset
1300 end if;
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 -- Restore the SPARK_Mode of the enclosing context after all delayed
kono
parents:
diff changeset
1303 -- pragmas have been analyzed.
kono
parents:
diff changeset
1304
kono
parents:
diff changeset
1305 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
kono
parents:
diff changeset
1306 end Analyze_Task_Contract;
kono
parents:
diff changeset
1307
kono
parents:
diff changeset
1308 -----------------------------
kono
parents:
diff changeset
1309 -- Create_Generic_Contract --
kono
parents:
diff changeset
1310 -----------------------------
kono
parents:
diff changeset
1311
kono
parents:
diff changeset
1312 procedure Create_Generic_Contract (Unit : Node_Id) is
kono
parents:
diff changeset
1313 Templ : constant Node_Id := Original_Node (Unit);
kono
parents:
diff changeset
1314 Templ_Id : constant Entity_Id := Defining_Entity (Templ);
kono
parents:
diff changeset
1315
kono
parents:
diff changeset
1316 procedure Add_Generic_Contract_Pragma (Prag : Node_Id);
kono
parents:
diff changeset
1317 -- Add a single contract-related source pragma Prag to the contract of
kono
parents:
diff changeset
1318 -- generic template Templ_Id.
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 ---------------------------------
kono
parents:
diff changeset
1321 -- Add_Generic_Contract_Pragma --
kono
parents:
diff changeset
1322 ---------------------------------
kono
parents:
diff changeset
1323
kono
parents:
diff changeset
1324 procedure Add_Generic_Contract_Pragma (Prag : Node_Id) is
kono
parents:
diff changeset
1325 Prag_Templ : Node_Id;
kono
parents:
diff changeset
1326
kono
parents:
diff changeset
1327 begin
kono
parents:
diff changeset
1328 -- Mark the pragma to prevent the premature capture of global
kono
parents:
diff changeset
1329 -- references when capturing global references of the context
kono
parents:
diff changeset
1330 -- (see Save_References_In_Pragma).
kono
parents:
diff changeset
1331
kono
parents:
diff changeset
1332 Set_Is_Generic_Contract_Pragma (Prag);
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 -- Pragmas that apply to a generic subprogram declaration are not
kono
parents:
diff changeset
1335 -- part of the semantic structure of the generic template:
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 -- generic
kono
parents:
diff changeset
1338 -- procedure Example (Formal : Integer);
kono
parents:
diff changeset
1339 -- pragma Precondition (Formal > 0);
kono
parents:
diff changeset
1340
kono
parents:
diff changeset
1341 -- Create a generic template for such pragmas and link the template
kono
parents:
diff changeset
1342 -- of the pragma with the generic template.
kono
parents:
diff changeset
1343
kono
parents:
diff changeset
1344 if Nkind (Templ) = N_Generic_Subprogram_Declaration then
kono
parents:
diff changeset
1345 Rewrite
kono
parents:
diff changeset
1346 (Prag, Copy_Generic_Node (Prag, Empty, Instantiating => False));
kono
parents:
diff changeset
1347 Prag_Templ := Original_Node (Prag);
kono
parents:
diff changeset
1348
kono
parents:
diff changeset
1349 Set_Is_Generic_Contract_Pragma (Prag_Templ);
kono
parents:
diff changeset
1350 Add_Contract_Item (Prag_Templ, Templ_Id);
kono
parents:
diff changeset
1351
kono
parents:
diff changeset
1352 -- Otherwise link the pragma with the generic template
kono
parents:
diff changeset
1353
kono
parents:
diff changeset
1354 else
kono
parents:
diff changeset
1355 Add_Contract_Item (Prag, Templ_Id);
kono
parents:
diff changeset
1356 end if;
kono
parents:
diff changeset
1357 end Add_Generic_Contract_Pragma;
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 -- Local variables
kono
parents:
diff changeset
1360
kono
parents:
diff changeset
1361 Context : constant Node_Id := Parent (Unit);
kono
parents:
diff changeset
1362 Decl : Node_Id := Empty;
kono
parents:
diff changeset
1363
kono
parents:
diff changeset
1364 -- Start of processing for Create_Generic_Contract
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 begin
kono
parents:
diff changeset
1367 -- A generic package declaration carries contract-related source pragmas
kono
parents:
diff changeset
1368 -- in its visible declarations.
kono
parents:
diff changeset
1369
kono
parents:
diff changeset
1370 if Nkind (Templ) = N_Generic_Package_Declaration then
kono
parents:
diff changeset
1371 Set_Ekind (Templ_Id, E_Generic_Package);
kono
parents:
diff changeset
1372
kono
parents:
diff changeset
1373 if Present (Visible_Declarations (Specification (Templ))) then
kono
parents:
diff changeset
1374 Decl := First (Visible_Declarations (Specification (Templ)));
kono
parents:
diff changeset
1375 end if;
kono
parents:
diff changeset
1376
kono
parents:
diff changeset
1377 -- A generic package body carries contract-related source pragmas in its
kono
parents:
diff changeset
1378 -- declarations.
kono
parents:
diff changeset
1379
kono
parents:
diff changeset
1380 elsif Nkind (Templ) = N_Package_Body then
kono
parents:
diff changeset
1381 Set_Ekind (Templ_Id, E_Package_Body);
kono
parents:
diff changeset
1382
kono
parents:
diff changeset
1383 if Present (Declarations (Templ)) then
kono
parents:
diff changeset
1384 Decl := First (Declarations (Templ));
kono
parents:
diff changeset
1385 end if;
kono
parents:
diff changeset
1386
kono
parents:
diff changeset
1387 -- Generic subprogram declaration
kono
parents:
diff changeset
1388
kono
parents:
diff changeset
1389 elsif Nkind (Templ) = N_Generic_Subprogram_Declaration then
kono
parents:
diff changeset
1390 if Nkind (Specification (Templ)) = N_Function_Specification then
kono
parents:
diff changeset
1391 Set_Ekind (Templ_Id, E_Generic_Function);
kono
parents:
diff changeset
1392 else
kono
parents:
diff changeset
1393 Set_Ekind (Templ_Id, E_Generic_Procedure);
kono
parents:
diff changeset
1394 end if;
kono
parents:
diff changeset
1395
kono
parents:
diff changeset
1396 -- When the generic subprogram acts as a compilation unit, inspect
kono
parents:
diff changeset
1397 -- the Pragmas_After list for contract-related source pragmas.
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 if Nkind (Context) = N_Compilation_Unit then
kono
parents:
diff changeset
1400 if Present (Aux_Decls_Node (Context))
kono
parents:
diff changeset
1401 and then Present (Pragmas_After (Aux_Decls_Node (Context)))
kono
parents:
diff changeset
1402 then
kono
parents:
diff changeset
1403 Decl := First (Pragmas_After (Aux_Decls_Node (Context)));
kono
parents:
diff changeset
1404 end if;
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 -- Otherwise inspect the successive declarations for contract-related
kono
parents:
diff changeset
1407 -- source pragmas.
kono
parents:
diff changeset
1408
kono
parents:
diff changeset
1409 else
kono
parents:
diff changeset
1410 Decl := Next (Unit);
kono
parents:
diff changeset
1411 end if;
kono
parents:
diff changeset
1412
kono
parents:
diff changeset
1413 -- A generic subprogram body carries contract-related source pragmas in
kono
parents:
diff changeset
1414 -- its declarations.
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 elsif Nkind (Templ) = N_Subprogram_Body then
kono
parents:
diff changeset
1417 Set_Ekind (Templ_Id, E_Subprogram_Body);
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 if Present (Declarations (Templ)) then
kono
parents:
diff changeset
1420 Decl := First (Declarations (Templ));
kono
parents:
diff changeset
1421 end if;
kono
parents:
diff changeset
1422 end if;
kono
parents:
diff changeset
1423
kono
parents:
diff changeset
1424 -- Inspect the relevant declarations looking for contract-related source
kono
parents:
diff changeset
1425 -- pragmas and add them to the contract of the generic unit.
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 while Present (Decl) loop
kono
parents:
diff changeset
1428 if Comes_From_Source (Decl) then
kono
parents:
diff changeset
1429 if Nkind (Decl) = N_Pragma then
kono
parents:
diff changeset
1430
kono
parents:
diff changeset
1431 -- The source pragma is a contract annotation
kono
parents:
diff changeset
1432
kono
parents:
diff changeset
1433 if Is_Contract_Annotation (Decl) then
kono
parents:
diff changeset
1434 Add_Generic_Contract_Pragma (Decl);
kono
parents:
diff changeset
1435 end if;
kono
parents:
diff changeset
1436
kono
parents:
diff changeset
1437 -- The region where a contract-related source pragma may appear
kono
parents:
diff changeset
1438 -- ends with the first source non-pragma declaration or statement.
kono
parents:
diff changeset
1439
kono
parents:
diff changeset
1440 else
kono
parents:
diff changeset
1441 exit;
kono
parents:
diff changeset
1442 end if;
kono
parents:
diff changeset
1443 end if;
kono
parents:
diff changeset
1444
kono
parents:
diff changeset
1445 Next (Decl);
kono
parents:
diff changeset
1446 end loop;
kono
parents:
diff changeset
1447 end Create_Generic_Contract;
kono
parents:
diff changeset
1448
kono
parents:
diff changeset
1449 --------------------------------
kono
parents:
diff changeset
1450 -- Expand_Subprogram_Contract --
kono
parents:
diff changeset
1451 --------------------------------
kono
parents:
diff changeset
1452
kono
parents:
diff changeset
1453 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id) is
kono
parents:
diff changeset
1454 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
kono
parents:
diff changeset
1455 Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
kono
parents:
diff changeset
1456
kono
parents:
diff changeset
1457 procedure Add_Invariant_And_Predicate_Checks
kono
parents:
diff changeset
1458 (Subp_Id : Entity_Id;
kono
parents:
diff changeset
1459 Stmts : in out List_Id;
kono
parents:
diff changeset
1460 Result : out Node_Id);
kono
parents:
diff changeset
1461 -- Process the result of function Subp_Id (if applicable) and all its
kono
parents:
diff changeset
1462 -- formals. Add invariant and predicate checks where applicable. The
kono
parents:
diff changeset
1463 -- routine appends all the checks to list Stmts. If Subp_Id denotes a
kono
parents:
diff changeset
1464 -- function, Result contains the entity of parameter _Result, to be
kono
parents:
diff changeset
1465 -- used in the creation of procedure _Postconditions.
kono
parents:
diff changeset
1466
kono
parents:
diff changeset
1467 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
kono
parents:
diff changeset
1468 -- Append a node to a list. If there is no list, create a new one. When
kono
parents:
diff changeset
1469 -- the item denotes a pragma, it is added to the list only when it is
kono
parents:
diff changeset
1470 -- enabled.
kono
parents:
diff changeset
1471
kono
parents:
diff changeset
1472 procedure Build_Postconditions_Procedure
kono
parents:
diff changeset
1473 (Subp_Id : Entity_Id;
kono
parents:
diff changeset
1474 Stmts : List_Id;
kono
parents:
diff changeset
1475 Result : Entity_Id);
kono
parents:
diff changeset
1476 -- Create the body of procedure _Postconditions which handles various
kono
parents:
diff changeset
1477 -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
kono
parents:
diff changeset
1478 -- of statements to be checked on exit. Parameter Result is the entity
kono
parents:
diff changeset
1479 -- of parameter _Result when Subp_Id denotes a function.
kono
parents:
diff changeset
1480
kono
parents:
diff changeset
1481 procedure Process_Contract_Cases (Stmts : in out List_Id);
kono
parents:
diff changeset
1482 -- Process pragma Contract_Cases. This routine prepends items to the
kono
parents:
diff changeset
1483 -- body declarations and appends items to list Stmts.
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 procedure Process_Postconditions (Stmts : in out List_Id);
kono
parents:
diff changeset
1486 -- Collect all [inherited] spec and body postconditions and accumulate
kono
parents:
diff changeset
1487 -- their pragma Check equivalents in list Stmts.
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 procedure Process_Preconditions;
kono
parents:
diff changeset
1490 -- Collect all [inherited] spec and body preconditions and prepend their
kono
parents:
diff changeset
1491 -- pragma Check equivalents to the declarations of the body.
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493 ----------------------------------------
kono
parents:
diff changeset
1494 -- Add_Invariant_And_Predicate_Checks --
kono
parents:
diff changeset
1495 ----------------------------------------
kono
parents:
diff changeset
1496
kono
parents:
diff changeset
1497 procedure Add_Invariant_And_Predicate_Checks
kono
parents:
diff changeset
1498 (Subp_Id : Entity_Id;
kono
parents:
diff changeset
1499 Stmts : in out List_Id;
kono
parents:
diff changeset
1500 Result : out Node_Id)
kono
parents:
diff changeset
1501 is
kono
parents:
diff changeset
1502 procedure Add_Invariant_Access_Checks (Id : Entity_Id);
kono
parents:
diff changeset
1503 -- Id denotes the return value of a function or a formal parameter.
kono
parents:
diff changeset
1504 -- Add an invariant check if the type of Id is access to a type with
kono
parents:
diff changeset
1505 -- invariants. The routine appends the generated code to Stmts.
kono
parents:
diff changeset
1506
kono
parents:
diff changeset
1507 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
kono
parents:
diff changeset
1508 -- Determine whether type Typ can benefit from invariant checks. To
kono
parents:
diff changeset
1509 -- qualify, the type must have a non-null invariant procedure and
kono
parents:
diff changeset
1510 -- subprogram Subp_Id must appear visible from the point of view of
kono
parents:
diff changeset
1511 -- the type.
kono
parents:
diff changeset
1512
kono
parents:
diff changeset
1513 ---------------------------------
kono
parents:
diff changeset
1514 -- Add_Invariant_Access_Checks --
kono
parents:
diff changeset
1515 ---------------------------------
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
kono
parents:
diff changeset
1518 Loc : constant Source_Ptr := Sloc (Body_Decl);
kono
parents:
diff changeset
1519 Ref : Node_Id;
kono
parents:
diff changeset
1520 Typ : Entity_Id;
kono
parents:
diff changeset
1521
kono
parents:
diff changeset
1522 begin
kono
parents:
diff changeset
1523 Typ := Etype (Id);
kono
parents:
diff changeset
1524
kono
parents:
diff changeset
1525 if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
kono
parents:
diff changeset
1526 Typ := Designated_Type (Typ);
kono
parents:
diff changeset
1527
kono
parents:
diff changeset
1528 if Invariant_Checks_OK (Typ) then
kono
parents:
diff changeset
1529 Ref :=
kono
parents:
diff changeset
1530 Make_Explicit_Dereference (Loc,
kono
parents:
diff changeset
1531 Prefix => New_Occurrence_Of (Id, Loc));
kono
parents:
diff changeset
1532 Set_Etype (Ref, Typ);
kono
parents:
diff changeset
1533
kono
parents:
diff changeset
1534 -- Generate:
kono
parents:
diff changeset
1535 -- if <Id> /= null then
kono
parents:
diff changeset
1536 -- <invariant_call (<Ref>)>
kono
parents:
diff changeset
1537 -- end if;
kono
parents:
diff changeset
1538
kono
parents:
diff changeset
1539 Append_Enabled_Item
kono
parents:
diff changeset
1540 (Item =>
kono
parents:
diff changeset
1541 Make_If_Statement (Loc,
kono
parents:
diff changeset
1542 Condition =>
kono
parents:
diff changeset
1543 Make_Op_Ne (Loc,
kono
parents:
diff changeset
1544 Left_Opnd => New_Occurrence_Of (Id, Loc),
kono
parents:
diff changeset
1545 Right_Opnd => Make_Null (Loc)),
kono
parents:
diff changeset
1546 Then_Statements => New_List (
kono
parents:
diff changeset
1547 Make_Invariant_Call (Ref))),
kono
parents:
diff changeset
1548 List => Stmts);
kono
parents:
diff changeset
1549 end if;
kono
parents:
diff changeset
1550 end if;
kono
parents:
diff changeset
1551 end Add_Invariant_Access_Checks;
kono
parents:
diff changeset
1552
kono
parents:
diff changeset
1553 -------------------------
kono
parents:
diff changeset
1554 -- Invariant_Checks_OK --
kono
parents:
diff changeset
1555 -------------------------
kono
parents:
diff changeset
1556
kono
parents:
diff changeset
1557 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
kono
parents:
diff changeset
1558 function Has_Public_Visibility_Of_Subprogram return Boolean;
kono
parents:
diff changeset
1559 -- Determine whether type Typ has public visibility of subprogram
kono
parents:
diff changeset
1560 -- Subp_Id.
kono
parents:
diff changeset
1561
kono
parents:
diff changeset
1562 -----------------------------------------
kono
parents:
diff changeset
1563 -- Has_Public_Visibility_Of_Subprogram --
kono
parents:
diff changeset
1564 -----------------------------------------
kono
parents:
diff changeset
1565
kono
parents:
diff changeset
1566 function Has_Public_Visibility_Of_Subprogram return Boolean is
kono
parents:
diff changeset
1567 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
kono
parents:
diff changeset
1568
kono
parents:
diff changeset
1569 begin
kono
parents:
diff changeset
1570 -- An Initialization procedure must be considered visible even
kono
parents:
diff changeset
1571 -- though it is internally generated.
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
kono
parents:
diff changeset
1574 return True;
kono
parents:
diff changeset
1575
kono
parents:
diff changeset
1576 elsif Ekind (Scope (Typ)) /= E_Package then
kono
parents:
diff changeset
1577 return False;
kono
parents:
diff changeset
1578
kono
parents:
diff changeset
1579 -- Internally generated code is never publicly visible except
kono
parents:
diff changeset
1580 -- for a subprogram that is the implementation of an expression
kono
parents:
diff changeset
1581 -- function. In that case the visibility is determined by the
kono
parents:
diff changeset
1582 -- last check.
kono
parents:
diff changeset
1583
kono
parents:
diff changeset
1584 elsif not Comes_From_Source (Subp_Decl)
kono
parents:
diff changeset
1585 and then
kono
parents:
diff changeset
1586 (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
kono
parents:
diff changeset
1587 or else not
kono
parents:
diff changeset
1588 Comes_From_Source (Defining_Entity (Subp_Decl)))
kono
parents:
diff changeset
1589 then
kono
parents:
diff changeset
1590 return False;
kono
parents:
diff changeset
1591
kono
parents:
diff changeset
1592 -- Determine whether the subprogram is declared in the visible
kono
parents:
diff changeset
1593 -- declarations of the package containing the type, or in the
kono
parents:
diff changeset
1594 -- visible declaration of a child unit of that package.
kono
parents:
diff changeset
1595
kono
parents:
diff changeset
1596 else
kono
parents:
diff changeset
1597 declare
kono
parents:
diff changeset
1598 Decls : constant List_Id :=
kono
parents:
diff changeset
1599 List_Containing (Subp_Decl);
kono
parents:
diff changeset
1600 Subp_Scope : constant Entity_Id :=
kono
parents:
diff changeset
1601 Scope (Defining_Entity (Subp_Decl));
kono
parents:
diff changeset
1602 Typ_Scope : constant Entity_Id := Scope (Typ);
kono
parents:
diff changeset
1603
kono
parents:
diff changeset
1604 begin
kono
parents:
diff changeset
1605 return
kono
parents:
diff changeset
1606 Decls = Visible_Declarations
kono
parents:
diff changeset
1607 (Specification (Unit_Declaration_Node (Typ_Scope)))
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 or else
kono
parents:
diff changeset
1610 (Ekind (Subp_Scope) = E_Package
kono
parents:
diff changeset
1611 and then Typ_Scope /= Subp_Scope
kono
parents:
diff changeset
1612 and then Is_Child_Unit (Subp_Scope)
kono
parents:
diff changeset
1613 and then
kono
parents:
diff changeset
1614 Is_Ancestor_Package (Typ_Scope, Subp_Scope)
kono
parents:
diff changeset
1615 and then
kono
parents:
diff changeset
1616 Decls = Visible_Declarations
kono
parents:
diff changeset
1617 (Specification
kono
parents:
diff changeset
1618 (Unit_Declaration_Node (Subp_Scope))));
kono
parents:
diff changeset
1619 end;
kono
parents:
diff changeset
1620 end if;
kono
parents:
diff changeset
1621 end Has_Public_Visibility_Of_Subprogram;
kono
parents:
diff changeset
1622
kono
parents:
diff changeset
1623 -- Start of processing for Invariant_Checks_OK
kono
parents:
diff changeset
1624
kono
parents:
diff changeset
1625 begin
kono
parents:
diff changeset
1626 return
kono
parents:
diff changeset
1627 Has_Invariants (Typ)
kono
parents:
diff changeset
1628 and then Present (Invariant_Procedure (Typ))
kono
parents:
diff changeset
1629 and then not Has_Null_Body (Invariant_Procedure (Typ))
kono
parents:
diff changeset
1630 and then Has_Public_Visibility_Of_Subprogram;
kono
parents:
diff changeset
1631 end Invariant_Checks_OK;
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 -- Local variables
kono
parents:
diff changeset
1634
kono
parents:
diff changeset
1635 Loc : constant Source_Ptr := Sloc (Body_Decl);
kono
parents:
diff changeset
1636 -- Source location of subprogram body contract
kono
parents:
diff changeset
1637
kono
parents:
diff changeset
1638 Formal : Entity_Id;
kono
parents:
diff changeset
1639 Typ : Entity_Id;
kono
parents:
diff changeset
1640
kono
parents:
diff changeset
1641 -- Start of processing for Add_Invariant_And_Predicate_Checks
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 begin
kono
parents:
diff changeset
1644 Result := Empty;
kono
parents:
diff changeset
1645
kono
parents:
diff changeset
1646 -- Process the result of a function
kono
parents:
diff changeset
1647
kono
parents:
diff changeset
1648 if Ekind (Subp_Id) = E_Function then
kono
parents:
diff changeset
1649 Typ := Etype (Subp_Id);
kono
parents:
diff changeset
1650
kono
parents:
diff changeset
1651 -- Generate _Result which is used in procedure _Postconditions to
kono
parents:
diff changeset
1652 -- verify the return value.
kono
parents:
diff changeset
1653
kono
parents:
diff changeset
1654 Result := Make_Defining_Identifier (Loc, Name_uResult);
kono
parents:
diff changeset
1655 Set_Etype (Result, Typ);
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 -- Add an invariant check when the return type has invariants and
kono
parents:
diff changeset
1658 -- the related function is visible to the outside.
kono
parents:
diff changeset
1659
kono
parents:
diff changeset
1660 if Invariant_Checks_OK (Typ) then
kono
parents:
diff changeset
1661 Append_Enabled_Item
kono
parents:
diff changeset
1662 (Item =>
kono
parents:
diff changeset
1663 Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
kono
parents:
diff changeset
1664 List => Stmts);
kono
parents:
diff changeset
1665 end if;
kono
parents:
diff changeset
1666
kono
parents:
diff changeset
1667 -- Add an invariant check when the return type is an access to a
kono
parents:
diff changeset
1668 -- type with invariants.
kono
parents:
diff changeset
1669
kono
parents:
diff changeset
1670 Add_Invariant_Access_Checks (Result);
kono
parents:
diff changeset
1671 end if;
kono
parents:
diff changeset
1672
kono
parents:
diff changeset
1673 -- Add invariant and predicates for all formals that qualify
kono
parents:
diff changeset
1674
kono
parents:
diff changeset
1675 Formal := First_Formal (Subp_Id);
kono
parents:
diff changeset
1676 while Present (Formal) loop
kono
parents:
diff changeset
1677 Typ := Etype (Formal);
kono
parents:
diff changeset
1678
kono
parents:
diff changeset
1679 if Ekind (Formal) /= E_In_Parameter
kono
parents:
diff changeset
1680 or else Is_Access_Type (Typ)
kono
parents:
diff changeset
1681 then
kono
parents:
diff changeset
1682 if Invariant_Checks_OK (Typ) then
kono
parents:
diff changeset
1683 Append_Enabled_Item
kono
parents:
diff changeset
1684 (Item =>
kono
parents:
diff changeset
1685 Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
kono
parents:
diff changeset
1686 List => Stmts);
kono
parents:
diff changeset
1687 end if;
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689 Add_Invariant_Access_Checks (Formal);
kono
parents:
diff changeset
1690
kono
parents:
diff changeset
1691 -- Note: we used to add predicate checks for OUT and IN OUT
kono
parents:
diff changeset
1692 -- formals here, but that was misguided, since such checks are
kono
parents:
diff changeset
1693 -- performed on the caller side, based on the predicate of the
kono
parents:
diff changeset
1694 -- actual, rather than the predicate of the formal.
kono
parents:
diff changeset
1695
kono
parents:
diff changeset
1696 end if;
kono
parents:
diff changeset
1697
kono
parents:
diff changeset
1698 Next_Formal (Formal);
kono
parents:
diff changeset
1699 end loop;
kono
parents:
diff changeset
1700 end Add_Invariant_And_Predicate_Checks;
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 -------------------------
kono
parents:
diff changeset
1703 -- Append_Enabled_Item --
kono
parents:
diff changeset
1704 -------------------------
kono
parents:
diff changeset
1705
kono
parents:
diff changeset
1706 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
kono
parents:
diff changeset
1707 begin
kono
parents:
diff changeset
1708 -- Do not chain ignored or disabled pragmas
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 if Nkind (Item) = N_Pragma
kono
parents:
diff changeset
1711 and then (Is_Ignored (Item) or else Is_Disabled (Item))
kono
parents:
diff changeset
1712 then
kono
parents:
diff changeset
1713 null;
kono
parents:
diff changeset
1714
kono
parents:
diff changeset
1715 -- Otherwise, add the item
kono
parents:
diff changeset
1716
kono
parents:
diff changeset
1717 else
kono
parents:
diff changeset
1718 if No (List) then
kono
parents:
diff changeset
1719 List := New_List;
kono
parents:
diff changeset
1720 end if;
kono
parents:
diff changeset
1721
kono
parents:
diff changeset
1722 -- If the pragma is a conjunct in a composite postcondition, it
kono
parents:
diff changeset
1723 -- has been processed in reverse order. In the postcondition body
kono
parents:
diff changeset
1724 -- it must appear before the others.
kono
parents:
diff changeset
1725
kono
parents:
diff changeset
1726 if Nkind (Item) = N_Pragma
kono
parents:
diff changeset
1727 and then From_Aspect_Specification (Item)
kono
parents:
diff changeset
1728 and then Split_PPC (Item)
kono
parents:
diff changeset
1729 then
kono
parents:
diff changeset
1730 Prepend (Item, List);
kono
parents:
diff changeset
1731 else
kono
parents:
diff changeset
1732 Append (Item, List);
kono
parents:
diff changeset
1733 end if;
kono
parents:
diff changeset
1734 end if;
kono
parents:
diff changeset
1735 end Append_Enabled_Item;
kono
parents:
diff changeset
1736
kono
parents:
diff changeset
1737 ------------------------------------
kono
parents:
diff changeset
1738 -- Build_Postconditions_Procedure --
kono
parents:
diff changeset
1739 ------------------------------------
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 procedure Build_Postconditions_Procedure
kono
parents:
diff changeset
1742 (Subp_Id : Entity_Id;
kono
parents:
diff changeset
1743 Stmts : List_Id;
kono
parents:
diff changeset
1744 Result : Entity_Id)
kono
parents:
diff changeset
1745 is
kono
parents:
diff changeset
1746 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id);
kono
parents:
diff changeset
1747 -- Insert node Stmt before the first source declaration of the
kono
parents:
diff changeset
1748 -- related subprogram's body. If no such declaration exists, Stmt
kono
parents:
diff changeset
1749 -- becomes the last declaration.
kono
parents:
diff changeset
1750
kono
parents:
diff changeset
1751 --------------------------------------------
kono
parents:
diff changeset
1752 -- Insert_Before_First_Source_Declaration --
kono
parents:
diff changeset
1753 --------------------------------------------
kono
parents:
diff changeset
1754
kono
parents:
diff changeset
1755 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id) is
kono
parents:
diff changeset
1756 Decls : constant List_Id := Declarations (Body_Decl);
kono
parents:
diff changeset
1757 Decl : Node_Id;
kono
parents:
diff changeset
1758
kono
parents:
diff changeset
1759 begin
kono
parents:
diff changeset
1760 -- Inspect the declarations of the related subprogram body looking
kono
parents:
diff changeset
1761 -- for the first source declaration.
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 if Present (Decls) then
kono
parents:
diff changeset
1764 Decl := First (Decls);
kono
parents:
diff changeset
1765 while Present (Decl) loop
kono
parents:
diff changeset
1766 if Comes_From_Source (Decl) then
kono
parents:
diff changeset
1767 Insert_Before (Decl, Stmt);
kono
parents:
diff changeset
1768 return;
kono
parents:
diff changeset
1769 end if;
kono
parents:
diff changeset
1770
kono
parents:
diff changeset
1771 Next (Decl);
kono
parents:
diff changeset
1772 end loop;
kono
parents:
diff changeset
1773
kono
parents:
diff changeset
1774 -- If we get there, then the subprogram body lacks any source
kono
parents:
diff changeset
1775 -- declarations. The body of _Postconditions now acts as the
kono
parents:
diff changeset
1776 -- last declaration.
kono
parents:
diff changeset
1777
kono
parents:
diff changeset
1778 Append (Stmt, Decls);
kono
parents:
diff changeset
1779
kono
parents:
diff changeset
1780 -- Ensure that the body has a declaration list
kono
parents:
diff changeset
1781
kono
parents:
diff changeset
1782 else
kono
parents:
diff changeset
1783 Set_Declarations (Body_Decl, New_List (Stmt));
kono
parents:
diff changeset
1784 end if;
kono
parents:
diff changeset
1785 end Insert_Before_First_Source_Declaration;
kono
parents:
diff changeset
1786
kono
parents:
diff changeset
1787 -- Local variables
kono
parents:
diff changeset
1788
kono
parents:
diff changeset
1789 Loc : constant Source_Ptr := Sloc (Body_Decl);
kono
parents:
diff changeset
1790 Params : List_Id := No_List;
kono
parents:
diff changeset
1791 Proc_Bod : Node_Id;
kono
parents:
diff changeset
1792 Proc_Decl : Node_Id;
kono
parents:
diff changeset
1793 Proc_Id : Entity_Id;
kono
parents:
diff changeset
1794 Proc_Spec : Node_Id;
kono
parents:
diff changeset
1795
kono
parents:
diff changeset
1796 -- Start of processing for Build_Postconditions_Procedure
kono
parents:
diff changeset
1797
kono
parents:
diff changeset
1798 begin
kono
parents:
diff changeset
1799 -- Nothing to do if there are no actions to check on exit
kono
parents:
diff changeset
1800
kono
parents:
diff changeset
1801 if No (Stmts) then
kono
parents:
diff changeset
1802 return;
kono
parents:
diff changeset
1803 end if;
kono
parents:
diff changeset
1804
kono
parents:
diff changeset
1805 Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
kono
parents:
diff changeset
1806 Set_Debug_Info_Needed (Proc_Id);
kono
parents:
diff changeset
1807 Set_Postconditions_Proc (Subp_Id, Proc_Id);
kono
parents:
diff changeset
1808
kono
parents:
diff changeset
1809 -- Force the front-end inlining of _Postconditions when generating C
kono
parents:
diff changeset
1810 -- code, since its body may have references to itypes defined in the
kono
parents:
diff changeset
1811 -- enclosing subprogram, which would cause problems for unnesting
kono
parents:
diff changeset
1812 -- routines in the absence of inlining.
kono
parents:
diff changeset
1813
kono
parents:
diff changeset
1814 if Modify_Tree_For_C then
kono
parents:
diff changeset
1815 Set_Has_Pragma_Inline (Proc_Id);
kono
parents:
diff changeset
1816 Set_Has_Pragma_Inline_Always (Proc_Id);
kono
parents:
diff changeset
1817 Set_Is_Inlined (Proc_Id);
kono
parents:
diff changeset
1818 end if;
kono
parents:
diff changeset
1819
kono
parents:
diff changeset
1820 -- The related subprogram is a function: create the specification of
kono
parents:
diff changeset
1821 -- parameter _Result.
kono
parents:
diff changeset
1822
kono
parents:
diff changeset
1823 if Present (Result) then
kono
parents:
diff changeset
1824 Params := New_List (
kono
parents:
diff changeset
1825 Make_Parameter_Specification (Loc,
kono
parents:
diff changeset
1826 Defining_Identifier => Result,
kono
parents:
diff changeset
1827 Parameter_Type =>
kono
parents:
diff changeset
1828 New_Occurrence_Of (Etype (Result), Loc)));
kono
parents:
diff changeset
1829 end if;
kono
parents:
diff changeset
1830
kono
parents:
diff changeset
1831 Proc_Spec :=
kono
parents:
diff changeset
1832 Make_Procedure_Specification (Loc,
kono
parents:
diff changeset
1833 Defining_Unit_Name => Proc_Id,
kono
parents:
diff changeset
1834 Parameter_Specifications => Params);
kono
parents:
diff changeset
1835
kono
parents:
diff changeset
1836 Proc_Decl := Make_Subprogram_Declaration (Loc, Proc_Spec);
kono
parents:
diff changeset
1837
kono
parents:
diff changeset
1838 -- Insert _Postconditions before the first source declaration of the
kono
parents:
diff changeset
1839 -- body. This ensures that the body will not cause any premature
kono
parents:
diff changeset
1840 -- freezing, as it may mention types:
kono
parents:
diff changeset
1841
kono
parents:
diff changeset
1842 -- procedure Proc (Obj : Array_Typ) is
kono
parents:
diff changeset
1843 -- procedure _postconditions is
kono
parents:
diff changeset
1844 -- begin
kono
parents:
diff changeset
1845 -- ... Obj ...
kono
parents:
diff changeset
1846 -- end _postconditions;
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
kono
parents:
diff changeset
1849 -- begin
kono
parents:
diff changeset
1850
kono
parents:
diff changeset
1851 -- In the example above, Obj is of type T but the incorrect placement
kono
parents:
diff changeset
1852 -- of _Postconditions will cause a crash in gigi due to an out-of-
kono
parents:
diff changeset
1853 -- order reference. The body of _Postconditions must be placed after
kono
parents:
diff changeset
1854 -- the declaration of Temp to preserve correct visibility.
kono
parents:
diff changeset
1855
kono
parents:
diff changeset
1856 Insert_Before_First_Source_Declaration (Proc_Decl);
kono
parents:
diff changeset
1857 Analyze (Proc_Decl);
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 -- Set an explicit End_Label to override the sloc of the implicit
kono
parents:
diff changeset
1860 -- RETURN statement, and prevent it from inheriting the sloc of one
kono
parents:
diff changeset
1861 -- the postconditions: this would cause confusing debug info to be
kono
parents:
diff changeset
1862 -- produced, interfering with coverage-analysis tools.
kono
parents:
diff changeset
1863
kono
parents:
diff changeset
1864 Proc_Bod :=
kono
parents:
diff changeset
1865 Make_Subprogram_Body (Loc,
kono
parents:
diff changeset
1866 Specification =>
kono
parents:
diff changeset
1867 Copy_Subprogram_Spec (Proc_Spec),
kono
parents:
diff changeset
1868 Declarations => Empty_List,
kono
parents:
diff changeset
1869 Handled_Statement_Sequence =>
kono
parents:
diff changeset
1870 Make_Handled_Sequence_Of_Statements (Loc,
kono
parents:
diff changeset
1871 Statements => Stmts,
kono
parents:
diff changeset
1872 End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
kono
parents:
diff changeset
1873
kono
parents:
diff changeset
1874 Insert_After_And_Analyze (Proc_Decl, Proc_Bod);
kono
parents:
diff changeset
1875 end Build_Postconditions_Procedure;
kono
parents:
diff changeset
1876
kono
parents:
diff changeset
1877 ----------------------------
kono
parents:
diff changeset
1878 -- Process_Contract_Cases --
kono
parents:
diff changeset
1879 ----------------------------
kono
parents:
diff changeset
1880
kono
parents:
diff changeset
1881 procedure Process_Contract_Cases (Stmts : in out List_Id) is
kono
parents:
diff changeset
1882 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id);
kono
parents:
diff changeset
1883 -- Process pragma Contract_Cases for subprogram Subp_Id
kono
parents:
diff changeset
1884
kono
parents:
diff changeset
1885 --------------------------------
kono
parents:
diff changeset
1886 -- Process_Contract_Cases_For --
kono
parents:
diff changeset
1887 --------------------------------
kono
parents:
diff changeset
1888
kono
parents:
diff changeset
1889 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id) is
kono
parents:
diff changeset
1890 Items : constant Node_Id := Contract (Subp_Id);
kono
parents:
diff changeset
1891 Prag : Node_Id;
kono
parents:
diff changeset
1892
kono
parents:
diff changeset
1893 begin
kono
parents:
diff changeset
1894 if Present (Items) then
kono
parents:
diff changeset
1895 Prag := Contract_Test_Cases (Items);
kono
parents:
diff changeset
1896 while Present (Prag) loop
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1897 if Pragma_Name (Prag) = Name_Contract_Cases
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1898 and then Is_Checked (Prag)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1899 then
111
kono
parents:
diff changeset
1900 Expand_Pragma_Contract_Cases
kono
parents:
diff changeset
1901 (CCs => Prag,
kono
parents:
diff changeset
1902 Subp_Id => Subp_Id,
kono
parents:
diff changeset
1903 Decls => Declarations (Body_Decl),
kono
parents:
diff changeset
1904 Stmts => Stmts);
kono
parents:
diff changeset
1905 end if;
kono
parents:
diff changeset
1906
kono
parents:
diff changeset
1907 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
1908 end loop;
kono
parents:
diff changeset
1909 end if;
kono
parents:
diff changeset
1910 end Process_Contract_Cases_For;
kono
parents:
diff changeset
1911
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1912 pragma Unmodified (Stmts);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1913 -- Stmts is passed as IN OUT to signal that the list can be updated,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1914 -- even if the corresponding integer value representing the list does
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1915 -- not change.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1916
111
kono
parents:
diff changeset
1917 -- Start of processing for Process_Contract_Cases
kono
parents:
diff changeset
1918
kono
parents:
diff changeset
1919 begin
kono
parents:
diff changeset
1920 Process_Contract_Cases_For (Body_Id);
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 if Present (Spec_Id) then
kono
parents:
diff changeset
1923 Process_Contract_Cases_For (Spec_Id);
kono
parents:
diff changeset
1924 end if;
kono
parents:
diff changeset
1925 end Process_Contract_Cases;
kono
parents:
diff changeset
1926
kono
parents:
diff changeset
1927 ----------------------------
kono
parents:
diff changeset
1928 -- Process_Postconditions --
kono
parents:
diff changeset
1929 ----------------------------
kono
parents:
diff changeset
1930
kono
parents:
diff changeset
1931 procedure Process_Postconditions (Stmts : in out List_Id) is
kono
parents:
diff changeset
1932 procedure Process_Body_Postconditions (Post_Nam : Name_Id);
kono
parents:
diff changeset
1933 -- Collect all [refined] postconditions of a specific kind denoted
kono
parents:
diff changeset
1934 -- by Post_Nam that belong to the body, and generate pragma Check
kono
parents:
diff changeset
1935 -- equivalents in list Stmts.
kono
parents:
diff changeset
1936
kono
parents:
diff changeset
1937 procedure Process_Spec_Postconditions;
kono
parents:
diff changeset
1938 -- Collect all [inherited] postconditions of the spec, and generate
kono
parents:
diff changeset
1939 -- pragma Check equivalents in list Stmts.
kono
parents:
diff changeset
1940
kono
parents:
diff changeset
1941 ---------------------------------
kono
parents:
diff changeset
1942 -- Process_Body_Postconditions --
kono
parents:
diff changeset
1943 ---------------------------------
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 procedure Process_Body_Postconditions (Post_Nam : Name_Id) is
kono
parents:
diff changeset
1946 Items : constant Node_Id := Contract (Body_Id);
kono
parents:
diff changeset
1947 Unit_Decl : constant Node_Id := Parent (Body_Decl);
kono
parents:
diff changeset
1948 Decl : Node_Id;
kono
parents:
diff changeset
1949 Prag : Node_Id;
kono
parents:
diff changeset
1950
kono
parents:
diff changeset
1951 begin
kono
parents:
diff changeset
1952 -- Process the contract
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 if Present (Items) then
kono
parents:
diff changeset
1955 Prag := Pre_Post_Conditions (Items);
kono
parents:
diff changeset
1956 while Present (Prag) loop
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1957 if Pragma_Name (Prag) = Post_Nam
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1958 and then Is_Checked (Prag)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1959 then
111
kono
parents:
diff changeset
1960 Append_Enabled_Item
kono
parents:
diff changeset
1961 (Item => Build_Pragma_Check_Equivalent (Prag),
kono
parents:
diff changeset
1962 List => Stmts);
kono
parents:
diff changeset
1963 end if;
kono
parents:
diff changeset
1964
kono
parents:
diff changeset
1965 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
1966 end loop;
kono
parents:
diff changeset
1967 end if;
kono
parents:
diff changeset
1968
kono
parents:
diff changeset
1969 -- The subprogram body being processed is actually the proper body
kono
parents:
diff changeset
1970 -- of a stub with a corresponding spec. The subprogram stub may
kono
parents:
diff changeset
1971 -- carry a postcondition pragma, in which case it must be taken
kono
parents:
diff changeset
1972 -- into account. The pragma appears after the stub.
kono
parents:
diff changeset
1973
kono
parents:
diff changeset
1974 if Present (Spec_Id) and then Nkind (Unit_Decl) = N_Subunit then
kono
parents:
diff changeset
1975 Decl := Next (Corresponding_Stub (Unit_Decl));
kono
parents:
diff changeset
1976 while Present (Decl) loop
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 -- Note that non-matching pragmas are skipped
kono
parents:
diff changeset
1979
kono
parents:
diff changeset
1980 if Nkind (Decl) = N_Pragma then
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1981 if Pragma_Name (Decl) = Post_Nam
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1982 and then Is_Checked (Decl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1983 then
111
kono
parents:
diff changeset
1984 Append_Enabled_Item
kono
parents:
diff changeset
1985 (Item => Build_Pragma_Check_Equivalent (Decl),
kono
parents:
diff changeset
1986 List => Stmts);
kono
parents:
diff changeset
1987 end if;
kono
parents:
diff changeset
1988
kono
parents:
diff changeset
1989 -- Skip internally generated code
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 elsif not Comes_From_Source (Decl) then
kono
parents:
diff changeset
1992 null;
kono
parents:
diff changeset
1993
kono
parents:
diff changeset
1994 -- Postcondition pragmas are usually grouped together. There
kono
parents:
diff changeset
1995 -- is no need to inspect the whole declarative list.
kono
parents:
diff changeset
1996
kono
parents:
diff changeset
1997 else
kono
parents:
diff changeset
1998 exit;
kono
parents:
diff changeset
1999 end if;
kono
parents:
diff changeset
2000
kono
parents:
diff changeset
2001 Next (Decl);
kono
parents:
diff changeset
2002 end loop;
kono
parents:
diff changeset
2003 end if;
kono
parents:
diff changeset
2004 end Process_Body_Postconditions;
kono
parents:
diff changeset
2005
kono
parents:
diff changeset
2006 ---------------------------------
kono
parents:
diff changeset
2007 -- Process_Spec_Postconditions --
kono
parents:
diff changeset
2008 ---------------------------------
kono
parents:
diff changeset
2009
kono
parents:
diff changeset
2010 procedure Process_Spec_Postconditions is
kono
parents:
diff changeset
2011 Subps : constant Subprogram_List :=
kono
parents:
diff changeset
2012 Inherited_Subprograms (Spec_Id);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2013 Item : Node_Id;
111
kono
parents:
diff changeset
2014 Items : Node_Id;
kono
parents:
diff changeset
2015 Prag : Node_Id;
kono
parents:
diff changeset
2016 Subp_Id : Entity_Id;
kono
parents:
diff changeset
2017
kono
parents:
diff changeset
2018 begin
kono
parents:
diff changeset
2019 -- Process the contract
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 Items := Contract (Spec_Id);
kono
parents:
diff changeset
2022
kono
parents:
diff changeset
2023 if Present (Items) then
kono
parents:
diff changeset
2024 Prag := Pre_Post_Conditions (Items);
kono
parents:
diff changeset
2025 while Present (Prag) loop
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2026 if Pragma_Name (Prag) = Name_Postcondition
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2027 and then Is_Checked (Prag)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2028 then
111
kono
parents:
diff changeset
2029 Append_Enabled_Item
kono
parents:
diff changeset
2030 (Item => Build_Pragma_Check_Equivalent (Prag),
kono
parents:
diff changeset
2031 List => Stmts);
kono
parents:
diff changeset
2032 end if;
kono
parents:
diff changeset
2033
kono
parents:
diff changeset
2034 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2035 end loop;
kono
parents:
diff changeset
2036 end if;
kono
parents:
diff changeset
2037
kono
parents:
diff changeset
2038 -- Process the contracts of all inherited subprograms, looking for
kono
parents:
diff changeset
2039 -- class-wide postconditions.
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 for Index in Subps'Range loop
kono
parents:
diff changeset
2042 Subp_Id := Subps (Index);
kono
parents:
diff changeset
2043 Items := Contract (Subp_Id);
kono
parents:
diff changeset
2044
kono
parents:
diff changeset
2045 if Present (Items) then
kono
parents:
diff changeset
2046 Prag := Pre_Post_Conditions (Items);
kono
parents:
diff changeset
2047 while Present (Prag) loop
kono
parents:
diff changeset
2048 if Pragma_Name (Prag) = Name_Postcondition
kono
parents:
diff changeset
2049 and then Class_Present (Prag)
kono
parents:
diff changeset
2050 then
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2051 Item :=
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2052 Build_Pragma_Check_Equivalent
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2053 (Prag => Prag,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2054 Subp_Id => Spec_Id,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2055 Inher_Id => Subp_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2056
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2057 -- The pragma Check equivalent of the class-wide
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2058 -- postcondition is still created even though the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2059 -- pragma may be ignored because the equivalent
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2060 -- performs semantic checks.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2061
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2062 if Is_Checked (Prag) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2063 Append_Enabled_Item (Item, Stmts);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2064 end if;
111
kono
parents:
diff changeset
2065 end if;
kono
parents:
diff changeset
2066
kono
parents:
diff changeset
2067 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2068 end loop;
kono
parents:
diff changeset
2069 end if;
kono
parents:
diff changeset
2070 end loop;
kono
parents:
diff changeset
2071 end Process_Spec_Postconditions;
kono
parents:
diff changeset
2072
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2073 pragma Unmodified (Stmts);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2074 -- Stmts is passed as IN OUT to signal that the list can be updated,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2075 -- even if the corresponding integer value representing the list does
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2076 -- not change.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2077
111
kono
parents:
diff changeset
2078 -- Start of processing for Process_Postconditions
kono
parents:
diff changeset
2079
kono
parents:
diff changeset
2080 begin
kono
parents:
diff changeset
2081 -- The processing of postconditions is done in reverse order (body
kono
parents:
diff changeset
2082 -- first) to ensure the following arrangement:
kono
parents:
diff changeset
2083
kono
parents:
diff changeset
2084 -- <refined postconditions from body>
kono
parents:
diff changeset
2085 -- <postconditions from body>
kono
parents:
diff changeset
2086 -- <postconditions from spec>
kono
parents:
diff changeset
2087 -- <inherited postconditions>
kono
parents:
diff changeset
2088
kono
parents:
diff changeset
2089 Process_Body_Postconditions (Name_Refined_Post);
kono
parents:
diff changeset
2090 Process_Body_Postconditions (Name_Postcondition);
kono
parents:
diff changeset
2091
kono
parents:
diff changeset
2092 if Present (Spec_Id) then
kono
parents:
diff changeset
2093 Process_Spec_Postconditions;
kono
parents:
diff changeset
2094 end if;
kono
parents:
diff changeset
2095 end Process_Postconditions;
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 ---------------------------
kono
parents:
diff changeset
2098 -- Process_Preconditions --
kono
parents:
diff changeset
2099 ---------------------------
kono
parents:
diff changeset
2100
kono
parents:
diff changeset
2101 procedure Process_Preconditions is
kono
parents:
diff changeset
2102 Class_Pre : Node_Id := Empty;
kono
parents:
diff changeset
2103 -- The sole [inherited] class-wide precondition pragma that applies
kono
parents:
diff changeset
2104 -- to the subprogram.
kono
parents:
diff changeset
2105
kono
parents:
diff changeset
2106 Insert_Node : Node_Id := Empty;
kono
parents:
diff changeset
2107 -- The insertion node after which all pragma Check equivalents are
kono
parents:
diff changeset
2108 -- inserted.
kono
parents:
diff changeset
2109
kono
parents:
diff changeset
2110 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean;
kono
parents:
diff changeset
2111 -- Determine whether arbitrary declaration Decl denotes a renaming of
kono
parents:
diff changeset
2112 -- a discriminant or protection field _object.
kono
parents:
diff changeset
2113
kono
parents:
diff changeset
2114 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
kono
parents:
diff changeset
2115 -- Merge two class-wide preconditions by "or else"-ing them. The
kono
parents:
diff changeset
2116 -- changes are accumulated in parameter Into. Update the error
kono
parents:
diff changeset
2117 -- message of Into.
kono
parents:
diff changeset
2118
kono
parents:
diff changeset
2119 procedure Prepend_To_Decls (Item : Node_Id);
kono
parents:
diff changeset
2120 -- Prepend a single item to the declarations of the subprogram body
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
kono
parents:
diff changeset
2123 -- Save a class-wide precondition into Class_Pre, or prepend a normal
kono
parents:
diff changeset
2124 -- precondition to the declarations of the body and analyze it.
kono
parents:
diff changeset
2125
kono
parents:
diff changeset
2126 procedure Process_Inherited_Preconditions;
kono
parents:
diff changeset
2127 -- Collect all inherited class-wide preconditions and merge them into
kono
parents:
diff changeset
2128 -- one big precondition to be evaluated as pragma Check.
kono
parents:
diff changeset
2129
kono
parents:
diff changeset
2130 procedure Process_Preconditions_For (Subp_Id : Entity_Id);
kono
parents:
diff changeset
2131 -- Collect all preconditions of subprogram Subp_Id and prepend their
kono
parents:
diff changeset
2132 -- pragma Check equivalents to the declarations of the body.
kono
parents:
diff changeset
2133
kono
parents:
diff changeset
2134 --------------------------
kono
parents:
diff changeset
2135 -- Is_Prologue_Renaming --
kono
parents:
diff changeset
2136 --------------------------
kono
parents:
diff changeset
2137
kono
parents:
diff changeset
2138 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean is
kono
parents:
diff changeset
2139 Nam : Node_Id;
kono
parents:
diff changeset
2140 Obj : Entity_Id;
kono
parents:
diff changeset
2141 Pref : Node_Id;
kono
parents:
diff changeset
2142 Sel : Node_Id;
kono
parents:
diff changeset
2143
kono
parents:
diff changeset
2144 begin
kono
parents:
diff changeset
2145 if Nkind (Decl) = N_Object_Renaming_Declaration then
kono
parents:
diff changeset
2146 Obj := Defining_Entity (Decl);
kono
parents:
diff changeset
2147 Nam := Name (Decl);
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 if Nkind (Nam) = N_Selected_Component then
kono
parents:
diff changeset
2150 Pref := Prefix (Nam);
kono
parents:
diff changeset
2151 Sel := Selector_Name (Nam);
kono
parents:
diff changeset
2152
kono
parents:
diff changeset
2153 -- A discriminant renaming appears as
kono
parents:
diff changeset
2154 -- Discr : constant ... := Prefix.Discr;
kono
parents:
diff changeset
2155
kono
parents:
diff changeset
2156 if Ekind (Obj) = E_Constant
kono
parents:
diff changeset
2157 and then Is_Entity_Name (Sel)
kono
parents:
diff changeset
2158 and then Present (Entity (Sel))
kono
parents:
diff changeset
2159 and then Ekind (Entity (Sel)) = E_Discriminant
kono
parents:
diff changeset
2160 then
kono
parents:
diff changeset
2161 return True;
kono
parents:
diff changeset
2162
kono
parents:
diff changeset
2163 -- A protection field renaming appears as
kono
parents:
diff changeset
2164 -- Prot : ... := _object._object;
kono
parents:
diff changeset
2165
kono
parents:
diff changeset
2166 -- A renamed private component is just a component of
kono
parents:
diff changeset
2167 -- _object, with an arbitrary name.
kono
parents:
diff changeset
2168
kono
parents:
diff changeset
2169 elsif Ekind (Obj) = E_Variable
kono
parents:
diff changeset
2170 and then Nkind (Pref) = N_Identifier
kono
parents:
diff changeset
2171 and then Chars (Pref) = Name_uObject
kono
parents:
diff changeset
2172 and then Nkind (Sel) = N_Identifier
kono
parents:
diff changeset
2173 then
kono
parents:
diff changeset
2174 return True;
kono
parents:
diff changeset
2175 end if;
kono
parents:
diff changeset
2176 end if;
kono
parents:
diff changeset
2177 end if;
kono
parents:
diff changeset
2178
kono
parents:
diff changeset
2179 return False;
kono
parents:
diff changeset
2180 end Is_Prologue_Renaming;
kono
parents:
diff changeset
2181
kono
parents:
diff changeset
2182 -------------------------
kono
parents:
diff changeset
2183 -- Merge_Preconditions --
kono
parents:
diff changeset
2184 -------------------------
kono
parents:
diff changeset
2185
kono
parents:
diff changeset
2186 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
kono
parents:
diff changeset
2187 function Expression_Arg (Prag : Node_Id) return Node_Id;
kono
parents:
diff changeset
2188 -- Return the boolean expression argument of a precondition while
kono
parents:
diff changeset
2189 -- updating its parentheses count for the subsequent merge.
kono
parents:
diff changeset
2190
kono
parents:
diff changeset
2191 function Message_Arg (Prag : Node_Id) return Node_Id;
kono
parents:
diff changeset
2192 -- Return the message argument of a precondition
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 --------------------
kono
parents:
diff changeset
2195 -- Expression_Arg --
kono
parents:
diff changeset
2196 --------------------
kono
parents:
diff changeset
2197
kono
parents:
diff changeset
2198 function Expression_Arg (Prag : Node_Id) return Node_Id is
kono
parents:
diff changeset
2199 Args : constant List_Id := Pragma_Argument_Associations (Prag);
kono
parents:
diff changeset
2200 Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
kono
parents:
diff changeset
2201
kono
parents:
diff changeset
2202 begin
kono
parents:
diff changeset
2203 if Paren_Count (Arg) = 0 then
kono
parents:
diff changeset
2204 Set_Paren_Count (Arg, 1);
kono
parents:
diff changeset
2205 end if;
kono
parents:
diff changeset
2206
kono
parents:
diff changeset
2207 return Arg;
kono
parents:
diff changeset
2208 end Expression_Arg;
kono
parents:
diff changeset
2209
kono
parents:
diff changeset
2210 -----------------
kono
parents:
diff changeset
2211 -- Message_Arg --
kono
parents:
diff changeset
2212 -----------------
kono
parents:
diff changeset
2213
kono
parents:
diff changeset
2214 function Message_Arg (Prag : Node_Id) return Node_Id is
kono
parents:
diff changeset
2215 Args : constant List_Id := Pragma_Argument_Associations (Prag);
kono
parents:
diff changeset
2216 begin
kono
parents:
diff changeset
2217 return Get_Pragma_Arg (Last (Args));
kono
parents:
diff changeset
2218 end Message_Arg;
kono
parents:
diff changeset
2219
kono
parents:
diff changeset
2220 -- Local variables
kono
parents:
diff changeset
2221
kono
parents:
diff changeset
2222 From_Expr : constant Node_Id := Expression_Arg (From);
kono
parents:
diff changeset
2223 From_Msg : constant Node_Id := Message_Arg (From);
kono
parents:
diff changeset
2224 Into_Expr : constant Node_Id := Expression_Arg (Into);
kono
parents:
diff changeset
2225 Into_Msg : constant Node_Id := Message_Arg (Into);
kono
parents:
diff changeset
2226 Loc : constant Source_Ptr := Sloc (Into);
kono
parents:
diff changeset
2227
kono
parents:
diff changeset
2228 -- Start of processing for Merge_Preconditions
kono
parents:
diff changeset
2229
kono
parents:
diff changeset
2230 begin
kono
parents:
diff changeset
2231 -- Merge the two preconditions by "or else"-ing them
kono
parents:
diff changeset
2232
kono
parents:
diff changeset
2233 Rewrite (Into_Expr,
kono
parents:
diff changeset
2234 Make_Or_Else (Loc,
kono
parents:
diff changeset
2235 Right_Opnd => Relocate_Node (Into_Expr),
kono
parents:
diff changeset
2236 Left_Opnd => From_Expr));
kono
parents:
diff changeset
2237
kono
parents:
diff changeset
2238 -- Merge the two error messages to produce a single message of the
kono
parents:
diff changeset
2239 -- form:
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 -- failed precondition from ...
kono
parents:
diff changeset
2242 -- also failed inherited precondition from ...
kono
parents:
diff changeset
2243
kono
parents:
diff changeset
2244 if not Exception_Locations_Suppressed then
kono
parents:
diff changeset
2245 Start_String (Strval (Into_Msg));
kono
parents:
diff changeset
2246 Store_String_Char (ASCII.LF);
kono
parents:
diff changeset
2247 Store_String_Chars (" also ");
kono
parents:
diff changeset
2248 Store_String_Chars (Strval (From_Msg));
kono
parents:
diff changeset
2249
kono
parents:
diff changeset
2250 Set_Strval (Into_Msg, End_String);
kono
parents:
diff changeset
2251 end if;
kono
parents:
diff changeset
2252 end Merge_Preconditions;
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 ----------------------
kono
parents:
diff changeset
2255 -- Prepend_To_Decls --
kono
parents:
diff changeset
2256 ----------------------
kono
parents:
diff changeset
2257
kono
parents:
diff changeset
2258 procedure Prepend_To_Decls (Item : Node_Id) is
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2259 Decls : List_Id;
111
kono
parents:
diff changeset
2260
kono
parents:
diff changeset
2261 begin
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2262 Decls := Declarations (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2263
111
kono
parents:
diff changeset
2264 -- Ensure that the body has a declarative list
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 if No (Decls) then
kono
parents:
diff changeset
2267 Decls := New_List;
kono
parents:
diff changeset
2268 Set_Declarations (Body_Decl, Decls);
kono
parents:
diff changeset
2269 end if;
kono
parents:
diff changeset
2270
kono
parents:
diff changeset
2271 Prepend_To (Decls, Item);
kono
parents:
diff changeset
2272 end Prepend_To_Decls;
kono
parents:
diff changeset
2273
kono
parents:
diff changeset
2274 ------------------------------
kono
parents:
diff changeset
2275 -- Prepend_To_Decls_Or_Save --
kono
parents:
diff changeset
2276 ------------------------------
kono
parents:
diff changeset
2277
kono
parents:
diff changeset
2278 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
kono
parents:
diff changeset
2279 Check_Prag : Node_Id;
kono
parents:
diff changeset
2280
kono
parents:
diff changeset
2281 begin
kono
parents:
diff changeset
2282 Check_Prag := Build_Pragma_Check_Equivalent (Prag);
kono
parents:
diff changeset
2283
kono
parents:
diff changeset
2284 -- Save the sole class-wide precondition (if any) for the next
kono
parents:
diff changeset
2285 -- step, where it will be merged with inherited preconditions.
kono
parents:
diff changeset
2286
kono
parents:
diff changeset
2287 if Class_Present (Prag) then
kono
parents:
diff changeset
2288 pragma Assert (No (Class_Pre));
kono
parents:
diff changeset
2289 Class_Pre := Check_Prag;
kono
parents:
diff changeset
2290
kono
parents:
diff changeset
2291 -- Accumulate the corresponding Check pragmas at the top of the
kono
parents:
diff changeset
2292 -- declarations. Prepending the items ensures that they will be
kono
parents:
diff changeset
2293 -- evaluated in their original order.
kono
parents:
diff changeset
2294
kono
parents:
diff changeset
2295 else
kono
parents:
diff changeset
2296 if Present (Insert_Node) then
kono
parents:
diff changeset
2297 Insert_After (Insert_Node, Check_Prag);
kono
parents:
diff changeset
2298 else
kono
parents:
diff changeset
2299 Prepend_To_Decls (Check_Prag);
kono
parents:
diff changeset
2300 end if;
kono
parents:
diff changeset
2301
kono
parents:
diff changeset
2302 Analyze (Check_Prag);
kono
parents:
diff changeset
2303 end if;
kono
parents:
diff changeset
2304 end Prepend_To_Decls_Or_Save;
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 -------------------------------------
kono
parents:
diff changeset
2307 -- Process_Inherited_Preconditions --
kono
parents:
diff changeset
2308 -------------------------------------
kono
parents:
diff changeset
2309
kono
parents:
diff changeset
2310 procedure Process_Inherited_Preconditions is
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2311 Subps : constant Subprogram_List :=
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2312 Inherited_Subprograms (Spec_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2313
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2314 Item : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2315 Items : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2316 Prag : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2317 Subp_Id : Entity_Id;
111
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 begin
kono
parents:
diff changeset
2320 -- Process the contracts of all inherited subprograms, looking for
kono
parents:
diff changeset
2321 -- class-wide preconditions.
kono
parents:
diff changeset
2322
kono
parents:
diff changeset
2323 for Index in Subps'Range loop
kono
parents:
diff changeset
2324 Subp_Id := Subps (Index);
kono
parents:
diff changeset
2325 Items := Contract (Subp_Id);
kono
parents:
diff changeset
2326
kono
parents:
diff changeset
2327 if Present (Items) then
kono
parents:
diff changeset
2328 Prag := Pre_Post_Conditions (Items);
kono
parents:
diff changeset
2329 while Present (Prag) loop
kono
parents:
diff changeset
2330 if Pragma_Name (Prag) = Name_Precondition
kono
parents:
diff changeset
2331 and then Class_Present (Prag)
kono
parents:
diff changeset
2332 then
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2333 Item :=
111
kono
parents:
diff changeset
2334 Build_Pragma_Check_Equivalent
kono
parents:
diff changeset
2335 (Prag => Prag,
kono
parents:
diff changeset
2336 Subp_Id => Spec_Id,
kono
parents:
diff changeset
2337 Inher_Id => Subp_Id);
kono
parents:
diff changeset
2338
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2339 -- The pragma Check equivalent of the class-wide
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2340 -- precondition is still created even though the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2341 -- pragma may be ignored because the equivalent
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2342 -- performs semantic checks.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2343
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2344 if Is_Checked (Prag) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2345
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2346 -- The spec of an inherited subprogram already
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2347 -- yielded a class-wide precondition. Merge the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2348 -- existing precondition with the current one
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2349 -- using "or else".
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2350
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2351 if Present (Class_Pre) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2352 Merge_Preconditions (Item, Class_Pre);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2353 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2354 Class_Pre := Item;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2355 end if;
111
kono
parents:
diff changeset
2356 end if;
kono
parents:
diff changeset
2357 end if;
kono
parents:
diff changeset
2358
kono
parents:
diff changeset
2359 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2360 end loop;
kono
parents:
diff changeset
2361 end if;
kono
parents:
diff changeset
2362 end loop;
kono
parents:
diff changeset
2363
kono
parents:
diff changeset
2364 -- Add the merged class-wide preconditions
kono
parents:
diff changeset
2365
kono
parents:
diff changeset
2366 if Present (Class_Pre) then
kono
parents:
diff changeset
2367 Prepend_To_Decls (Class_Pre);
kono
parents:
diff changeset
2368 Analyze (Class_Pre);
kono
parents:
diff changeset
2369 end if;
kono
parents:
diff changeset
2370 end Process_Inherited_Preconditions;
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 -------------------------------
kono
parents:
diff changeset
2373 -- Process_Preconditions_For --
kono
parents:
diff changeset
2374 -------------------------------
kono
parents:
diff changeset
2375
kono
parents:
diff changeset
2376 procedure Process_Preconditions_For (Subp_Id : Entity_Id) is
kono
parents:
diff changeset
2377 Items : constant Node_Id := Contract (Subp_Id);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2378 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
111
kono
parents:
diff changeset
2379 Decl : Node_Id;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2380 Freeze_T : Boolean;
111
kono
parents:
diff changeset
2381 Prag : Node_Id;
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 begin
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2384 -- Process the contract. If the body is an expression function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2385 -- that is a completion, freeze types within, because this may
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2386 -- not have been done yet, when the subprogram declaration and
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2387 -- its completion by an expression function appear in distinct
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2388 -- declarative lists of the same unit (visible and private).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2389
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2390 Freeze_T :=
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2391 Was_Expression_Function (Body_Decl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2392 and then Sloc (Body_Id) /= Sloc (Subp_Id)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2393 and then In_Same_Source_Unit (Body_Id, Subp_Id)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2394 and then List_Containing (Body_Decl) /=
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2395 List_Containing (Subp_Decl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2396 and then not In_Instance;
111
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 if Present (Items) then
kono
parents:
diff changeset
2399 Prag := Pre_Post_Conditions (Items);
kono
parents:
diff changeset
2400 while Present (Prag) loop
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2401 if Pragma_Name (Prag) = Name_Precondition
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2402 and then Is_Checked (Prag)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2403 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2404 if Freeze_T
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2405 and then Present (Corresponding_Aspect (Prag))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2406 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2407 Freeze_Expr_Types
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2408 (Def_Id => Subp_Id,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2409 Typ => Standard_Boolean,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2410 Expr => Expression (Corresponding_Aspect (Prag)),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2411 N => Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2412 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2413
111
kono
parents:
diff changeset
2414 Prepend_To_Decls_Or_Save (Prag);
kono
parents:
diff changeset
2415 end if;
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2418 end loop;
kono
parents:
diff changeset
2419 end if;
kono
parents:
diff changeset
2420
kono
parents:
diff changeset
2421 -- The subprogram declaration being processed is actually a body
kono
parents:
diff changeset
2422 -- stub. The stub may carry a precondition pragma, in which case
kono
parents:
diff changeset
2423 -- it must be taken into account. The pragma appears after the
kono
parents:
diff changeset
2424 -- stub.
kono
parents:
diff changeset
2425
kono
parents:
diff changeset
2426 if Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
kono
parents:
diff changeset
2427
kono
parents:
diff changeset
2428 -- Inspect the declarations following the body stub
kono
parents:
diff changeset
2429
kono
parents:
diff changeset
2430 Decl := Next (Subp_Decl);
kono
parents:
diff changeset
2431 while Present (Decl) loop
kono
parents:
diff changeset
2432
kono
parents:
diff changeset
2433 -- Note that non-matching pragmas are skipped
kono
parents:
diff changeset
2434
kono
parents:
diff changeset
2435 if Nkind (Decl) = N_Pragma then
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2436 if Pragma_Name (Decl) = Name_Precondition
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2437 and then Is_Checked (Decl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2438 then
111
kono
parents:
diff changeset
2439 Prepend_To_Decls_Or_Save (Decl);
kono
parents:
diff changeset
2440 end if;
kono
parents:
diff changeset
2441
kono
parents:
diff changeset
2442 -- Skip internally generated code
kono
parents:
diff changeset
2443
kono
parents:
diff changeset
2444 elsif not Comes_From_Source (Decl) then
kono
parents:
diff changeset
2445 null;
kono
parents:
diff changeset
2446
kono
parents:
diff changeset
2447 -- Preconditions are usually grouped together. There is no
kono
parents:
diff changeset
2448 -- need to inspect the whole declarative list.
kono
parents:
diff changeset
2449
kono
parents:
diff changeset
2450 else
kono
parents:
diff changeset
2451 exit;
kono
parents:
diff changeset
2452 end if;
kono
parents:
diff changeset
2453
kono
parents:
diff changeset
2454 Next (Decl);
kono
parents:
diff changeset
2455 end loop;
kono
parents:
diff changeset
2456 end if;
kono
parents:
diff changeset
2457 end Process_Preconditions_For;
kono
parents:
diff changeset
2458
kono
parents:
diff changeset
2459 -- Local variables
kono
parents:
diff changeset
2460
kono
parents:
diff changeset
2461 Decls : constant List_Id := Declarations (Body_Decl);
kono
parents:
diff changeset
2462 Decl : Node_Id;
kono
parents:
diff changeset
2463
kono
parents:
diff changeset
2464 -- Start of processing for Process_Preconditions
kono
parents:
diff changeset
2465
kono
parents:
diff changeset
2466 begin
kono
parents:
diff changeset
2467 -- Find the proper insertion point for all pragma Check equivalents
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 if Present (Decls) then
kono
parents:
diff changeset
2470 Decl := First (Decls);
kono
parents:
diff changeset
2471 while Present (Decl) loop
kono
parents:
diff changeset
2472
kono
parents:
diff changeset
2473 -- First source declaration terminates the search, because all
kono
parents:
diff changeset
2474 -- preconditions must be evaluated prior to it, by definition.
kono
parents:
diff changeset
2475
kono
parents:
diff changeset
2476 if Comes_From_Source (Decl) then
kono
parents:
diff changeset
2477 exit;
kono
parents:
diff changeset
2478
kono
parents:
diff changeset
2479 -- Certain internally generated object renamings such as those
kono
parents:
diff changeset
2480 -- for discriminants and protection fields must be elaborated
kono
parents:
diff changeset
2481 -- before the preconditions are evaluated, as their expressions
kono
parents:
diff changeset
2482 -- may mention the discriminants. The renamings include those
kono
parents:
diff changeset
2483 -- for private components so we need to find the last such.
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 elsif Is_Prologue_Renaming (Decl) then
kono
parents:
diff changeset
2486 while Present (Next (Decl))
kono
parents:
diff changeset
2487 and then Is_Prologue_Renaming (Next (Decl))
kono
parents:
diff changeset
2488 loop
kono
parents:
diff changeset
2489 Next (Decl);
kono
parents:
diff changeset
2490 end loop;
kono
parents:
diff changeset
2491
kono
parents:
diff changeset
2492 Insert_Node := Decl;
kono
parents:
diff changeset
2493
kono
parents:
diff changeset
2494 -- Otherwise the declaration does not come from source. This
kono
parents:
diff changeset
2495 -- also terminates the search, because internal code may raise
kono
parents:
diff changeset
2496 -- exceptions which should not preempt the preconditions.
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 else
kono
parents:
diff changeset
2499 exit;
kono
parents:
diff changeset
2500 end if;
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 Next (Decl);
kono
parents:
diff changeset
2503 end loop;
kono
parents:
diff changeset
2504 end if;
kono
parents:
diff changeset
2505
kono
parents:
diff changeset
2506 -- The processing of preconditions is done in reverse order (body
kono
parents:
diff changeset
2507 -- first), because each pragma Check equivalent is inserted at the
kono
parents:
diff changeset
2508 -- top of the declarations. This ensures that the final order is
kono
parents:
diff changeset
2509 -- consistent with following diagram:
kono
parents:
diff changeset
2510
kono
parents:
diff changeset
2511 -- <inherited preconditions>
kono
parents:
diff changeset
2512 -- <preconditions from spec>
kono
parents:
diff changeset
2513 -- <preconditions from body>
kono
parents:
diff changeset
2514
kono
parents:
diff changeset
2515 Process_Preconditions_For (Body_Id);
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 if Present (Spec_Id) then
kono
parents:
diff changeset
2518 Process_Preconditions_For (Spec_Id);
kono
parents:
diff changeset
2519 Process_Inherited_Preconditions;
kono
parents:
diff changeset
2520 end if;
kono
parents:
diff changeset
2521 end Process_Preconditions;
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 -- Local variables
kono
parents:
diff changeset
2524
kono
parents:
diff changeset
2525 Restore_Scope : Boolean := False;
kono
parents:
diff changeset
2526 Result : Entity_Id;
kono
parents:
diff changeset
2527 Stmts : List_Id := No_List;
kono
parents:
diff changeset
2528 Subp_Id : Entity_Id;
kono
parents:
diff changeset
2529
kono
parents:
diff changeset
2530 -- Start of processing for Expand_Subprogram_Contract
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 begin
kono
parents:
diff changeset
2533 -- Obtain the entity of the initial declaration
kono
parents:
diff changeset
2534
kono
parents:
diff changeset
2535 if Present (Spec_Id) then
kono
parents:
diff changeset
2536 Subp_Id := Spec_Id;
kono
parents:
diff changeset
2537 else
kono
parents:
diff changeset
2538 Subp_Id := Body_Id;
kono
parents:
diff changeset
2539 end if;
kono
parents:
diff changeset
2540
kono
parents:
diff changeset
2541 -- Do not perform expansion activity when it is not needed
kono
parents:
diff changeset
2542
kono
parents:
diff changeset
2543 if not Expander_Active then
kono
parents:
diff changeset
2544 return;
kono
parents:
diff changeset
2545
kono
parents:
diff changeset
2546 -- ASIS requires an unaltered tree
kono
parents:
diff changeset
2547
kono
parents:
diff changeset
2548 elsif ASIS_Mode then
kono
parents:
diff changeset
2549 return;
kono
parents:
diff changeset
2550
kono
parents:
diff changeset
2551 -- GNATprove does not need the executable semantics of a contract
kono
parents:
diff changeset
2552
kono
parents:
diff changeset
2553 elsif GNATprove_Mode then
kono
parents:
diff changeset
2554 return;
kono
parents:
diff changeset
2555
kono
parents:
diff changeset
2556 -- The contract of a generic subprogram or one declared in a generic
kono
parents:
diff changeset
2557 -- context is not expanded, as the corresponding instance will provide
kono
parents:
diff changeset
2558 -- the executable semantics of the contract.
kono
parents:
diff changeset
2559
kono
parents:
diff changeset
2560 elsif Is_Generic_Subprogram (Subp_Id) or else Inside_A_Generic then
kono
parents:
diff changeset
2561 return;
kono
parents:
diff changeset
2562
kono
parents:
diff changeset
2563 -- All subprograms carry a contract, but for some it is not significant
kono
parents:
diff changeset
2564 -- and should not be processed. This is a small optimization.
kono
parents:
diff changeset
2565
kono
parents:
diff changeset
2566 elsif not Has_Significant_Contract (Subp_Id) then
kono
parents:
diff changeset
2567 return;
kono
parents:
diff changeset
2568
kono
parents:
diff changeset
2569 -- The contract of an ignored Ghost subprogram does not need expansion,
kono
parents:
diff changeset
2570 -- because the subprogram and all calls to it will be removed.
kono
parents:
diff changeset
2571
kono
parents:
diff changeset
2572 elsif Is_Ignored_Ghost_Entity (Subp_Id) then
kono
parents:
diff changeset
2573 return;
kono
parents:
diff changeset
2574
kono
parents:
diff changeset
2575 -- Do not re-expand the same contract. This scenario occurs when a
kono
parents:
diff changeset
2576 -- construct is rewritten into something else during its analysis
kono
parents:
diff changeset
2577 -- (expression functions for instance).
kono
parents:
diff changeset
2578
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2579 elsif Has_Expanded_Contract (Subp_Id) then
111
kono
parents:
diff changeset
2580 return;
kono
parents:
diff changeset
2581 end if;
kono
parents:
diff changeset
2582
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2583 -- Prevent multiple expansion attempts of the same contract
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2584
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2585 Set_Has_Expanded_Contract (Subp_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2586
111
kono
parents:
diff changeset
2587 -- Ensure that the formal parameters are visible when expanding all
kono
parents:
diff changeset
2588 -- contract items.
kono
parents:
diff changeset
2589
kono
parents:
diff changeset
2590 if not In_Open_Scopes (Subp_Id) then
kono
parents:
diff changeset
2591 Restore_Scope := True;
kono
parents:
diff changeset
2592 Push_Scope (Subp_Id);
kono
parents:
diff changeset
2593
kono
parents:
diff changeset
2594 if Is_Generic_Subprogram (Subp_Id) then
kono
parents:
diff changeset
2595 Install_Generic_Formals (Subp_Id);
kono
parents:
diff changeset
2596 else
kono
parents:
diff changeset
2597 Install_Formals (Subp_Id);
kono
parents:
diff changeset
2598 end if;
kono
parents:
diff changeset
2599 end if;
kono
parents:
diff changeset
2600
kono
parents:
diff changeset
2601 -- The expansion of a subprogram contract involves the creation of Check
kono
parents:
diff changeset
2602 -- pragmas to verify the contract assertions of the spec and body in a
kono
parents:
diff changeset
2603 -- particular order. The order is as follows:
kono
parents:
diff changeset
2604
kono
parents:
diff changeset
2605 -- function Example (...) return ... is
kono
parents:
diff changeset
2606 -- procedure _Postconditions (...) is
kono
parents:
diff changeset
2607 -- begin
kono
parents:
diff changeset
2608 -- <refined postconditions from body>
kono
parents:
diff changeset
2609 -- <postconditions from body>
kono
parents:
diff changeset
2610 -- <postconditions from spec>
kono
parents:
diff changeset
2611 -- <inherited postconditions>
kono
parents:
diff changeset
2612 -- <contract case consequences>
kono
parents:
diff changeset
2613 -- <invariant check of function result>
kono
parents:
diff changeset
2614 -- <invariant and predicate checks of parameters>
kono
parents:
diff changeset
2615 -- end _Postconditions;
kono
parents:
diff changeset
2616
kono
parents:
diff changeset
2617 -- <inherited preconditions>
kono
parents:
diff changeset
2618 -- <preconditions from spec>
kono
parents:
diff changeset
2619 -- <preconditions from body>
kono
parents:
diff changeset
2620 -- <contract case conditions>
kono
parents:
diff changeset
2621
kono
parents:
diff changeset
2622 -- <source declarations>
kono
parents:
diff changeset
2623 -- begin
kono
parents:
diff changeset
2624 -- <source statements>
kono
parents:
diff changeset
2625
kono
parents:
diff changeset
2626 -- _Preconditions (Result);
kono
parents:
diff changeset
2627 -- return Result;
kono
parents:
diff changeset
2628 -- end Example;
kono
parents:
diff changeset
2629
kono
parents:
diff changeset
2630 -- Routine _Postconditions holds all contract assertions that must be
kono
parents:
diff changeset
2631 -- verified on exit from the related subprogram.
kono
parents:
diff changeset
2632
kono
parents:
diff changeset
2633 -- Step 1: Handle all preconditions. This action must come before the
kono
parents:
diff changeset
2634 -- processing of pragma Contract_Cases because the pragma prepends items
kono
parents:
diff changeset
2635 -- to the body declarations.
kono
parents:
diff changeset
2636
kono
parents:
diff changeset
2637 Process_Preconditions;
kono
parents:
diff changeset
2638
kono
parents:
diff changeset
2639 -- Step 2: Handle all postconditions. This action must come before the
kono
parents:
diff changeset
2640 -- processing of pragma Contract_Cases because the pragma appends items
kono
parents:
diff changeset
2641 -- to list Stmts.
kono
parents:
diff changeset
2642
kono
parents:
diff changeset
2643 Process_Postconditions (Stmts);
kono
parents:
diff changeset
2644
kono
parents:
diff changeset
2645 -- Step 3: Handle pragma Contract_Cases. This action must come before
kono
parents:
diff changeset
2646 -- the processing of invariants and predicates because those append
kono
parents:
diff changeset
2647 -- items to list Stmts.
kono
parents:
diff changeset
2648
kono
parents:
diff changeset
2649 Process_Contract_Cases (Stmts);
kono
parents:
diff changeset
2650
kono
parents:
diff changeset
2651 -- Step 4: Apply invariant and predicate checks on a function result and
kono
parents:
diff changeset
2652 -- all formals. The resulting checks are accumulated in list Stmts.
kono
parents:
diff changeset
2653
kono
parents:
diff changeset
2654 Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
kono
parents:
diff changeset
2655
kono
parents:
diff changeset
2656 -- Step 5: Construct procedure _Postconditions
kono
parents:
diff changeset
2657
kono
parents:
diff changeset
2658 Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
kono
parents:
diff changeset
2659
kono
parents:
diff changeset
2660 if Restore_Scope then
kono
parents:
diff changeset
2661 End_Scope;
kono
parents:
diff changeset
2662 end if;
kono
parents:
diff changeset
2663 end Expand_Subprogram_Contract;
kono
parents:
diff changeset
2664
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2665 -------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2666 -- Freeze_Previous_Contracts --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2667 -------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2668
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2669 procedure Freeze_Previous_Contracts (Body_Decl : Node_Id) is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2670 function Causes_Contract_Freezing (N : Node_Id) return Boolean;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2671 pragma Inline (Causes_Contract_Freezing);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2672 -- Determine whether arbitrary node N causes contract freezing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2673
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2674 procedure Freeze_Contracts;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2675 pragma Inline (Freeze_Contracts);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2676 -- Freeze the contracts of all eligible constructs which precede body
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2677 -- Body_Decl.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2678
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2679 procedure Freeze_Enclosing_Package_Body;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2680 pragma Inline (Freeze_Enclosing_Package_Body);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2681 -- Freeze the contract of the nearest package body (if any) which
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2682 -- encloses body Body_Decl.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2683
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2684 ------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2685 -- Causes_Contract_Freezing --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2686 ------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2687
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2688 function Causes_Contract_Freezing (N : Node_Id) return Boolean is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2689 begin
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2690 return Nkind_In (N, N_Entry_Body,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2691 N_Package_Body,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2692 N_Protected_Body,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2693 N_Subprogram_Body,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2694 N_Subprogram_Body_Stub,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2695 N_Task_Body);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2696 end Causes_Contract_Freezing;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2697
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2698 ----------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2699 -- Freeze_Contracts --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2700 ----------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2701
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2702 procedure Freeze_Contracts is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2703 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2704 Decl : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2705
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2706 begin
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2707 -- Nothing to do when the body which causes freezing does not appear
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2708 -- in a declarative list because there cannot possibly be constructs
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2709 -- with contracts.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2710
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2711 if not Is_List_Member (Body_Decl) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2712 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2713 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2714
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2715 -- Inspect the declarations preceding the body, and freeze individual
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2716 -- contracts of eligible constructs.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2717
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2718 Decl := Prev (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2719 while Present (Decl) loop
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2720
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2721 -- Stop the traversal when a preceding construct that causes
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2722 -- freezing is encountered as there is no point in refreezing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2723 -- the already frozen constructs.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2724
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2725 if Causes_Contract_Freezing (Decl) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2726 exit;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2727
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2728 -- Entry or subprogram declarations
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2729
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2730 elsif Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2731 N_Entry_Declaration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2732 N_Generic_Subprogram_Declaration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2733 N_Subprogram_Declaration)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2734 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2735 Analyze_Entry_Or_Subprogram_Contract
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2736 (Subp_Id => Defining_Entity (Decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2737 Freeze_Id => Body_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2738
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2739 -- Objects
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2740
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2741 elsif Nkind (Decl) = N_Object_Declaration then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2742 Analyze_Object_Contract
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2743 (Obj_Id => Defining_Entity (Decl),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2744 Freeze_Id => Body_Id);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2745
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2746 -- Protected units
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2747
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2748 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2749 N_Single_Protected_Declaration)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2750 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2751 Analyze_Protected_Contract (Defining_Entity (Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2752
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2753 -- Subprogram body stubs
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2754
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2755 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2756 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2757
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2758 -- Task units
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2759
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2760 elsif Nkind_In (Decl, N_Single_Task_Declaration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2761 N_Task_Type_Declaration)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2762 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2763 Analyze_Task_Contract (Defining_Entity (Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2764 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2765
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2766 Prev (Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2767 end loop;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2768 end Freeze_Contracts;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2769
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2770 -----------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2771 -- Freeze_Enclosing_Package_Body --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2772 -----------------------------------
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2773
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2774 procedure Freeze_Enclosing_Package_Body is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2775 Orig_Decl : constant Node_Id := Original_Node (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2776 Par : Node_Id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2777
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2778 begin
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2779 -- Climb the parent chain looking for an enclosing package body. Do
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2780 -- not use the scope stack, because a body utilizes the entity of its
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2781 -- corresponding spec.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2782
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2783 Par := Parent (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2784 while Present (Par) loop
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2785 if Nkind (Par) = N_Package_Body then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2786 Analyze_Package_Body_Contract
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2787 (Body_Id => Defining_Entity (Par),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2788 Freeze_Id => Defining_Entity (Body_Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2789
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2790 exit;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2791
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2792 -- Do not look for an enclosing package body when the construct
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2793 -- which causes freezing is a body generated for an expression
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2794 -- function and it appears within a package spec. This ensures
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2795 -- that the traversal will not reach too far up the parent chain
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2796 -- and attempt to freeze a package body which must not be frozen.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2797
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2798 -- package body Enclosing_Body
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2799 -- with Refined_State => (State => Var)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2800 -- is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2801 -- package Nested is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2802 -- type Some_Type is ...;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2803 -- function Cause_Freezing return ...;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2804 -- private
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2805 -- function Cause_Freezing is (...);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2806 -- end Nested;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2807 --
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2808 -- Var : Nested.Some_Type;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2809
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2810 elsif Nkind (Par) = N_Package_Declaration
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2811 and then Nkind (Orig_Decl) = N_Expression_Function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2812 then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2813 exit;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2814
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2815 -- Prevent the search from going too far
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2816
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2817 elsif Is_Body_Or_Package_Declaration (Par) then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2818 exit;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2819 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2820
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2821 Par := Parent (Par);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2822 end loop;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2823 end Freeze_Enclosing_Package_Body;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2824
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2825 -- Local variables
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2826
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2827 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2828
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2829 -- Start of processing for Freeze_Previous_Contracts
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2830
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2831 begin
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2832 pragma Assert (Causes_Contract_Freezing (Body_Decl));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2833
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2834 -- A body that is in the process of being inlined appears from source,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2835 -- but carries name _parent. Such a body does not cause freezing of
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2836 -- contracts.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2837
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2838 if Chars (Body_Id) = Name_uParent then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2839 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2840 end if;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2841
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2842 Freeze_Enclosing_Package_Body;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2843 Freeze_Contracts;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2844 end Freeze_Previous_Contracts;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2845
111
kono
parents:
diff changeset
2846 ---------------------------------
kono
parents:
diff changeset
2847 -- Inherit_Subprogram_Contract --
kono
parents:
diff changeset
2848 ---------------------------------
kono
parents:
diff changeset
2849
kono
parents:
diff changeset
2850 procedure Inherit_Subprogram_Contract
kono
parents:
diff changeset
2851 (Subp : Entity_Id;
kono
parents:
diff changeset
2852 From_Subp : Entity_Id)
kono
parents:
diff changeset
2853 is
kono
parents:
diff changeset
2854 procedure Inherit_Pragma (Prag_Id : Pragma_Id);
kono
parents:
diff changeset
2855 -- Propagate a pragma denoted by Prag_Id from From_Subp's contract to
kono
parents:
diff changeset
2856 -- Subp's contract.
kono
parents:
diff changeset
2857
kono
parents:
diff changeset
2858 --------------------
kono
parents:
diff changeset
2859 -- Inherit_Pragma --
kono
parents:
diff changeset
2860 --------------------
kono
parents:
diff changeset
2861
kono
parents:
diff changeset
2862 procedure Inherit_Pragma (Prag_Id : Pragma_Id) is
kono
parents:
diff changeset
2863 Prag : constant Node_Id := Get_Pragma (From_Subp, Prag_Id);
kono
parents:
diff changeset
2864 New_Prag : Node_Id;
kono
parents:
diff changeset
2865
kono
parents:
diff changeset
2866 begin
kono
parents:
diff changeset
2867 -- A pragma cannot be part of more than one First_Pragma/Next_Pragma
kono
parents:
diff changeset
2868 -- chains, therefore the node must be replicated. The new pragma is
kono
parents:
diff changeset
2869 -- flagged as inherited for distinction purposes.
kono
parents:
diff changeset
2870
kono
parents:
diff changeset
2871 if Present (Prag) then
kono
parents:
diff changeset
2872 New_Prag := New_Copy_Tree (Prag);
kono
parents:
diff changeset
2873 Set_Is_Inherited_Pragma (New_Prag);
kono
parents:
diff changeset
2874
kono
parents:
diff changeset
2875 Add_Contract_Item (New_Prag, Subp);
kono
parents:
diff changeset
2876 end if;
kono
parents:
diff changeset
2877 end Inherit_Pragma;
kono
parents:
diff changeset
2878
kono
parents:
diff changeset
2879 -- Start of processing for Inherit_Subprogram_Contract
kono
parents:
diff changeset
2880
kono
parents:
diff changeset
2881 begin
kono
parents:
diff changeset
2882 -- Inheritance is carried out only when both entities are subprograms
kono
parents:
diff changeset
2883 -- with contracts.
kono
parents:
diff changeset
2884
kono
parents:
diff changeset
2885 if Is_Subprogram_Or_Generic_Subprogram (Subp)
kono
parents:
diff changeset
2886 and then Is_Subprogram_Or_Generic_Subprogram (From_Subp)
kono
parents:
diff changeset
2887 and then Present (Contract (From_Subp))
kono
parents:
diff changeset
2888 then
kono
parents:
diff changeset
2889 Inherit_Pragma (Pragma_Extensions_Visible);
kono
parents:
diff changeset
2890 end if;
kono
parents:
diff changeset
2891 end Inherit_Subprogram_Contract;
kono
parents:
diff changeset
2892
kono
parents:
diff changeset
2893 -------------------------------------
kono
parents:
diff changeset
2894 -- Instantiate_Subprogram_Contract --
kono
parents:
diff changeset
2895 -------------------------------------
kono
parents:
diff changeset
2896
kono
parents:
diff changeset
2897 procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id) is
kono
parents:
diff changeset
2898 procedure Instantiate_Pragmas (First_Prag : Node_Id);
kono
parents:
diff changeset
2899 -- Instantiate all contract-related source pragmas found in the list,
kono
parents:
diff changeset
2900 -- starting with pragma First_Prag. Each instantiated pragma is added
kono
parents:
diff changeset
2901 -- to list L.
kono
parents:
diff changeset
2902
kono
parents:
diff changeset
2903 -------------------------
kono
parents:
diff changeset
2904 -- Instantiate_Pragmas --
kono
parents:
diff changeset
2905 -------------------------
kono
parents:
diff changeset
2906
kono
parents:
diff changeset
2907 procedure Instantiate_Pragmas (First_Prag : Node_Id) is
kono
parents:
diff changeset
2908 Inst_Prag : Node_Id;
kono
parents:
diff changeset
2909 Prag : Node_Id;
kono
parents:
diff changeset
2910
kono
parents:
diff changeset
2911 begin
kono
parents:
diff changeset
2912 Prag := First_Prag;
kono
parents:
diff changeset
2913 while Present (Prag) loop
kono
parents:
diff changeset
2914 if Is_Generic_Contract_Pragma (Prag) then
kono
parents:
diff changeset
2915 Inst_Prag :=
kono
parents:
diff changeset
2916 Copy_Generic_Node (Prag, Empty, Instantiating => True);
kono
parents:
diff changeset
2917
kono
parents:
diff changeset
2918 Set_Analyzed (Inst_Prag, False);
kono
parents:
diff changeset
2919 Append_To (L, Inst_Prag);
kono
parents:
diff changeset
2920 end if;
kono
parents:
diff changeset
2921
kono
parents:
diff changeset
2922 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2923 end loop;
kono
parents:
diff changeset
2924 end Instantiate_Pragmas;
kono
parents:
diff changeset
2925
kono
parents:
diff changeset
2926 -- Local variables
kono
parents:
diff changeset
2927
kono
parents:
diff changeset
2928 Items : constant Node_Id := Contract (Defining_Entity (Templ));
kono
parents:
diff changeset
2929
kono
parents:
diff changeset
2930 -- Start of processing for Instantiate_Subprogram_Contract
kono
parents:
diff changeset
2931
kono
parents:
diff changeset
2932 begin
kono
parents:
diff changeset
2933 if Present (Items) then
kono
parents:
diff changeset
2934 Instantiate_Pragmas (Pre_Post_Conditions (Items));
kono
parents:
diff changeset
2935 Instantiate_Pragmas (Contract_Test_Cases (Items));
kono
parents:
diff changeset
2936 Instantiate_Pragmas (Classifications (Items));
kono
parents:
diff changeset
2937 end if;
kono
parents:
diff changeset
2938 end Instantiate_Subprogram_Contract;
kono
parents:
diff changeset
2939
kono
parents:
diff changeset
2940 ----------------------------------------
kono
parents:
diff changeset
2941 -- Save_Global_References_In_Contract --
kono
parents:
diff changeset
2942 ----------------------------------------
kono
parents:
diff changeset
2943
kono
parents:
diff changeset
2944 procedure Save_Global_References_In_Contract
kono
parents:
diff changeset
2945 (Templ : Node_Id;
kono
parents:
diff changeset
2946 Gen_Id : Entity_Id)
kono
parents:
diff changeset
2947 is
kono
parents:
diff changeset
2948 procedure Save_Global_References_In_List (First_Prag : Node_Id);
kono
parents:
diff changeset
2949 -- Save all global references in contract-related source pragmas found
kono
parents:
diff changeset
2950 -- in the list, starting with pragma First_Prag.
kono
parents:
diff changeset
2951
kono
parents:
diff changeset
2952 ------------------------------------
kono
parents:
diff changeset
2953 -- Save_Global_References_In_List --
kono
parents:
diff changeset
2954 ------------------------------------
kono
parents:
diff changeset
2955
kono
parents:
diff changeset
2956 procedure Save_Global_References_In_List (First_Prag : Node_Id) is
kono
parents:
diff changeset
2957 Prag : Node_Id;
kono
parents:
diff changeset
2958
kono
parents:
diff changeset
2959 begin
kono
parents:
diff changeset
2960 Prag := First_Prag;
kono
parents:
diff changeset
2961 while Present (Prag) loop
kono
parents:
diff changeset
2962 if Is_Generic_Contract_Pragma (Prag) then
kono
parents:
diff changeset
2963 Save_Global_References (Prag);
kono
parents:
diff changeset
2964 end if;
kono
parents:
diff changeset
2965
kono
parents:
diff changeset
2966 Prag := Next_Pragma (Prag);
kono
parents:
diff changeset
2967 end loop;
kono
parents:
diff changeset
2968 end Save_Global_References_In_List;
kono
parents:
diff changeset
2969
kono
parents:
diff changeset
2970 -- Local variables
kono
parents:
diff changeset
2971
kono
parents:
diff changeset
2972 Items : constant Node_Id := Contract (Defining_Entity (Templ));
kono
parents:
diff changeset
2973
kono
parents:
diff changeset
2974 -- Start of processing for Save_Global_References_In_Contract
kono
parents:
diff changeset
2975
kono
parents:
diff changeset
2976 begin
kono
parents:
diff changeset
2977 -- The entity of the analyzed generic copy must be on the scope stack
kono
parents:
diff changeset
2978 -- to ensure proper detection of global references.
kono
parents:
diff changeset
2979
kono
parents:
diff changeset
2980 Push_Scope (Gen_Id);
kono
parents:
diff changeset
2981
kono
parents:
diff changeset
2982 if Permits_Aspect_Specifications (Templ)
kono
parents:
diff changeset
2983 and then Has_Aspects (Templ)
kono
parents:
diff changeset
2984 then
kono
parents:
diff changeset
2985 Save_Global_References_In_Aspects (Templ);
kono
parents:
diff changeset
2986 end if;
kono
parents:
diff changeset
2987
kono
parents:
diff changeset
2988 if Present (Items) then
kono
parents:
diff changeset
2989 Save_Global_References_In_List (Pre_Post_Conditions (Items));
kono
parents:
diff changeset
2990 Save_Global_References_In_List (Contract_Test_Cases (Items));
kono
parents:
diff changeset
2991 Save_Global_References_In_List (Classifications (Items));
kono
parents:
diff changeset
2992 end if;
kono
parents:
diff changeset
2993
kono
parents:
diff changeset
2994 Pop_Scope;
kono
parents:
diff changeset
2995 end Save_Global_References_In_Contract;
kono
parents:
diff changeset
2996
kono
parents:
diff changeset
2997 end Contracts;