]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/contracts.adb
[multiple changes]
[thirdparty/gcc.git] / gcc / ada / contracts.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- C O N T R A C T S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2015, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Aspects; use Aspects;
27 with Atree; use Atree;
28 with Einfo; use Einfo;
29 with Elists; use Elists;
30 with Errout; use Errout;
31 with Exp_Prag; use Exp_Prag;
32 with Exp_Tss; use Exp_Tss;
33 with Exp_Util; use Exp_Util;
34 with Namet; use Namet;
35 with Nlists; use Nlists;
36 with Nmake; use Nmake;
37 with Opt; use Opt;
38 with Sem; use Sem;
39 with Sem_Aux; use Sem_Aux;
40 with Sem_Ch6; use Sem_Ch6;
41 with Sem_Ch8; use Sem_Ch8;
42 with Sem_Ch12; use Sem_Ch12;
43 with Sem_Disp; use Sem_Disp;
44 with Sem_Prag; use Sem_Prag;
45 with Sem_Util; use Sem_Util;
46 with Sinfo; use Sinfo;
47 with Snames; use Snames;
48 with Stringt; use Stringt;
49 with Tbuild; use Tbuild;
50
51 package body Contracts is
52
53 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
54 -- Expand the contracts of a subprogram body and its correspoding spec (if
55 -- any). This routine processes all [refined] pre- and postconditions as
56 -- well as Contract_Cases, invariants and predicates. Body_Id denotes the
57 -- entity of the subprogram body.
58
59 -----------------------
60 -- Add_Contract_Item --
61 -----------------------
62
63 procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
64 Items : Node_Id := Contract (Id);
65
66 procedure Add_Classification;
67 -- Prepend Prag to the list of classifications
68
69 procedure Add_Contract_Test_Case;
70 -- Prepend Prag to the list of contract and test cases
71
72 procedure Add_Pre_Post_Condition;
73 -- Prepend Prag to the list of pre- and postconditions
74
75 ------------------------
76 -- Add_Classification --
77 ------------------------
78
79 procedure Add_Classification is
80 begin
81 Set_Next_Pragma (Prag, Classifications (Items));
82 Set_Classifications (Items, Prag);
83 end Add_Classification;
84
85 ----------------------------
86 -- Add_Contract_Test_Case --
87 ----------------------------
88
89 procedure Add_Contract_Test_Case is
90 begin
91 Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
92 Set_Contract_Test_Cases (Items, Prag);
93 end Add_Contract_Test_Case;
94
95 ----------------------------
96 -- Add_Pre_Post_Condition --
97 ----------------------------
98
99 procedure Add_Pre_Post_Condition is
100 begin
101 Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
102 Set_Pre_Post_Conditions (Items, Prag);
103 end Add_Pre_Post_Condition;
104
105 -- Local variables
106
107 Prag_Nam : Name_Id;
108
109 -- Start of processing for Add_Contract_Item
110
111 begin
112 -- A contract must contain only pragmas
113
114 pragma Assert (Nkind (Prag) = N_Pragma);
115 Prag_Nam := Pragma_Name (Prag);
116
117 -- Create a new contract when adding the first item
118
119 if No (Items) then
120 Items := Make_Contract (Sloc (Id));
121 Set_Contract (Id, Items);
122 end if;
123
124 -- Contract items related to constants. Applicable pragmas are:
125 -- Part_Of
126
127 if Ekind (Id) = E_Constant then
128 if Prag_Nam = Name_Part_Of then
129 Add_Classification;
130
131 -- The pragma is not a proper contract item
132
133 else
134 raise Program_Error;
135 end if;
136
137 -- Contract items related to [generic] packages or instantiations. The
138 -- applicable pragmas are:
139 -- Abstract_States
140 -- Initial_Condition
141 -- Initializes
142 -- Part_Of (instantiation only)
143
144 elsif Ekind_In (Id, E_Generic_Package, E_Package) then
145 if Nam_In (Prag_Nam, Name_Abstract_State,
146 Name_Initial_Condition,
147 Name_Initializes)
148 then
149 Add_Classification;
150
151 -- Indicator Part_Of must be associated with a package instantiation
152
153 elsif Prag_Nam = Name_Part_Of and then Is_Generic_Instance (Id) then
154 Add_Classification;
155
156 -- The pragma is not a proper contract item
157
158 else
159 raise Program_Error;
160 end if;
161
162 -- Contract items related to package bodies. The applicable pragmas are:
163 -- Refined_States
164
165 elsif Ekind (Id) = E_Package_Body then
166 if Prag_Nam = Name_Refined_State then
167 Add_Classification;
168
169 -- The pragma is not a proper contract item
170
171 else
172 raise Program_Error;
173 end if;
174
175 -- Contract items related to subprogram or entry declarations. The
176 -- applicable pragmas are:
177 -- Contract_Cases
178 -- Depends
179 -- Extensions_Visible
180 -- Global
181 -- Postcondition
182 -- Precondition
183 -- Test_Case
184 -- Volatile_Function
185
186 elsif Ekind_In (Id, E_Entry, E_Entry_Family)
187 or else Is_Generic_Subprogram (Id)
188 or else Is_Subprogram (Id)
189 then
190 if Nam_In (Prag_Nam, Name_Postcondition, Name_Precondition) then
191 Add_Pre_Post_Condition;
192
193 elsif Nam_In (Prag_Nam, Name_Contract_Cases, Name_Test_Case) then
194 Add_Contract_Test_Case;
195
196 elsif Nam_In (Prag_Nam, Name_Depends,
197 Name_Extensions_Visible,
198 Name_Global)
199 then
200 Add_Classification;
201
202 elsif Prag_Nam = Name_Volatile_Function
203 and then Ekind_In (Id, E_Function, E_Generic_Function)
204 then
205 Add_Classification;
206
207 -- The pragma is not a proper contract item
208
209 else
210 raise Program_Error;
211 end if;
212
213 -- Contract items related to subprogram bodies. Applicable pragmas are:
214 -- Postcondition
215 -- Precondition
216 -- Refined_Depends
217 -- Refined_Global
218 -- Refined_Post
219
220 elsif Ekind (Id) = E_Subprogram_Body then
221 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
222 Add_Classification;
223
224 elsif Nam_In (Prag_Nam, Name_Postcondition,
225 Name_Precondition,
226 Name_Refined_Post)
227 then
228 Add_Pre_Post_Condition;
229
230 -- The pragma is not a proper contract item
231
232 else
233 raise Program_Error;
234 end if;
235
236 -- Contract items related to variables. Applicable pragmas are:
237 -- Async_Readers
238 -- Async_Writers
239 -- Constant_After_Elaboration
240 -- Effective_Reads
241 -- Effective_Writes
242 -- Part_Of
243
244 elsif Ekind (Id) = E_Variable then
245 if Nam_In (Prag_Nam, Name_Async_Readers,
246 Name_Async_Writers,
247 Name_Constant_After_Elaboration,
248 Name_Effective_Reads,
249 Name_Effective_Writes,
250 Name_Part_Of)
251 then
252 Add_Classification;
253
254 -- The pragma is not a proper contract item
255
256 else
257 raise Program_Error;
258 end if;
259 end if;
260 end Add_Contract_Item;
261
262 ---------------------------------------------
263 -- Analyze_Enclosing_Package_Body_Contract --
264 ---------------------------------------------
265
266 procedure Analyze_Enclosing_Package_Body_Contract (Body_Decl : Node_Id) is
267 Par : Node_Id;
268
269 begin
270 -- Climb the parent chain looking for an enclosing body. Do not use the
271 -- scope stack, as a body uses the entity of its corresponding spec.
272
273 Par := Parent (Body_Decl);
274 while Present (Par) loop
275 if Nkind (Par) = N_Package_Body then
276 Analyze_Package_Body_Contract
277 (Body_Id => Defining_Entity (Par),
278 Freeze_Id => Defining_Entity (Body_Decl));
279
280 return;
281 end if;
282
283 Par := Parent (Par);
284 end loop;
285 end Analyze_Enclosing_Package_Body_Contract;
286
287 -----------------------------
288 -- Analyze_Object_Contract --
289 -----------------------------
290
291 procedure Analyze_Object_Contract (Obj_Id : Entity_Id) is
292 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
293 AR_Val : Boolean := False;
294 AW_Val : Boolean := False;
295 ER_Val : Boolean := False;
296 EW_Val : Boolean := False;
297 Items : Node_Id;
298 Prag : Node_Id;
299 Seen : Boolean := False;
300
301 begin
302 -- The loop parameter in an element iterator over a formal container
303 -- is declared with an object declaration, but no contracts apply.
304
305 if Ekind (Obj_Id) = E_Loop_Parameter then
306 return;
307 end if;
308
309 -- Do not analyze a contract multiple times
310
311 Items := Contract (Obj_Id);
312
313 if Present (Items) then
314 if Analyzed (Items) then
315 return;
316 else
317 Set_Analyzed (Items);
318 end if;
319 end if;
320
321 -- Constant-related checks
322
323 if Ekind (Obj_Id) = E_Constant then
324
325 -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
326 -- This check is relevant only when SPARK_Mode is on, as it is not
327 -- a standard Ada legality rule. Internally-generated constants that
328 -- map generic formals to actuals in instantiations are allowed to
329 -- be volatile.
330
331 if SPARK_Mode = On
332 and then Comes_From_Source (Obj_Id)
333 and then Is_Effectively_Volatile (Obj_Id)
334 and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
335 then
336 Error_Msg_N ("constant cannot be volatile", Obj_Id);
337 end if;
338
339 -- Variable-related checks
340
341 else pragma Assert (Ekind (Obj_Id) = E_Variable);
342
343 -- The following checks are relevant only when SPARK_Mode is on, as
344 -- they are not standard Ada legality rules. Internally generated
345 -- temporaries are ignored.
346
347 if SPARK_Mode = On and then Comes_From_Source (Obj_Id) then
348 if Is_Effectively_Volatile (Obj_Id) then
349
350 -- The declaration of an effectively volatile object must
351 -- appear at the library level (SPARK RM 7.1.3(3), C.6(6)).
352
353 if not Is_Library_Level_Entity (Obj_Id) then
354 Error_Msg_N
355 ("volatile variable & must be declared at library level",
356 Obj_Id);
357
358 -- An object of a discriminated type cannot be effectively
359 -- volatile except for protected objects (SPARK RM 7.1.3(5)).
360
361 elsif Has_Discriminants (Obj_Typ)
362 and then not Is_Protected_Type (Obj_Typ)
363 then
364 Error_Msg_N
365 ("discriminated object & cannot be volatile", Obj_Id);
366
367 -- An object of a tagged type cannot be effectively volatile
368 -- (SPARK RM C.6(5)).
369
370 elsif Is_Tagged_Type (Obj_Typ) then
371 Error_Msg_N ("tagged object & cannot be volatile", Obj_Id);
372 end if;
373
374 -- The object is not effectively volatile
375
376 else
377 -- A non-effectively volatile object cannot have effectively
378 -- volatile components (SPARK RM 7.1.3(6)).
379
380 if not Is_Effectively_Volatile (Obj_Id)
381 and then Has_Volatile_Component (Obj_Typ)
382 then
383 Error_Msg_N
384 ("non-volatile object & cannot have volatile components",
385 Obj_Id);
386 end if;
387 end if;
388 end if;
389
390 if Is_Ghost_Entity (Obj_Id) then
391
392 -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(8))
393
394 if Is_Effectively_Volatile (Obj_Id) then
395 Error_Msg_N ("ghost variable & cannot be volatile", Obj_Id);
396
397 -- A Ghost object cannot be imported or exported (SPARK RM 6.9(8))
398
399 elsif Is_Imported (Obj_Id) then
400 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
401
402 elsif Is_Exported (Obj_Id) then
403 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
404 end if;
405 end if;
406
407 -- Analyze all external properties
408
409 Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
410
411 if Present (Prag) then
412 Analyze_External_Property_In_Decl_Part (Prag, AR_Val);
413 Seen := True;
414 end if;
415
416 Prag := Get_Pragma (Obj_Id, Pragma_Async_Writers);
417
418 if Present (Prag) then
419 Analyze_External_Property_In_Decl_Part (Prag, AW_Val);
420 Seen := True;
421 end if;
422
423 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Reads);
424
425 if Present (Prag) then
426 Analyze_External_Property_In_Decl_Part (Prag, ER_Val);
427 Seen := True;
428 end if;
429
430 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Writes);
431
432 if Present (Prag) then
433 Analyze_External_Property_In_Decl_Part (Prag, EW_Val);
434 Seen := True;
435 end if;
436
437 -- Verify the mutual interaction of the various external properties
438
439 if Seen then
440 Check_External_Properties (Obj_Id, AR_Val, AW_Val, ER_Val, EW_Val);
441 end if;
442 end if;
443
444 -- Check whether the lack of indicator Part_Of agrees with the placement
445 -- of the object with respect to the state space.
446
447 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
448
449 if No (Prag) then
450 Check_Missing_Part_Of (Obj_Id);
451 end if;
452
453 -- A ghost object cannot be imported or exported (SPARK RM 6.9(8)). One
454 -- exception to this is the object that represents the dispatch table of
455 -- a Ghost tagged type, as the symbol needs to be exported.
456
457 if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
458 if Is_Exported (Obj_Id) then
459 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
460
461 elsif Is_Imported (Obj_Id) then
462 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
463 end if;
464 end if;
465 end Analyze_Object_Contract;
466
467 -----------------------------------
468 -- Analyze_Package_Body_Contract --
469 -----------------------------------
470
471 procedure Analyze_Package_Body_Contract
472 (Body_Id : Entity_Id;
473 Freeze_Id : Entity_Id := Empty)
474 is
475 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
476 Items : constant Node_Id := Contract (Body_Id);
477 Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
478 Mode : SPARK_Mode_Type;
479 Ref_State : Node_Id;
480
481 begin
482 -- Do not analyze a contract multiple times
483
484 if Present (Items) then
485 if Analyzed (Items) then
486 return;
487 else
488 Set_Analyzed (Items);
489 end if;
490 end if;
491
492 -- Due to the timing of contract analysis, delayed pragmas may be
493 -- subject to the wrong SPARK_Mode, usually that of the enclosing
494 -- context. To remedy this, restore the original SPARK_Mode of the
495 -- related package body.
496
497 Save_SPARK_Mode_And_Set (Body_Id, Mode);
498
499 Ref_State := Get_Pragma (Body_Id, Pragma_Refined_State);
500
501 -- The analysis of pragma Refined_State detects whether the spec has
502 -- abstract states available for refinement.
503
504 if Present (Ref_State) then
505 Analyze_Refined_State_In_Decl_Part (Ref_State, Freeze_Id);
506
507 -- State refinement is required when the package declaration defines at
508 -- least one abstract state. Null states are not considered. Refinement
509 -- is not enforced when SPARK checks are turned off.
510
511 elsif SPARK_Mode /= Off
512 and then Requires_State_Refinement (Spec_Id, Body_Id)
513 then
514 Error_Msg_N ("package & requires state refinement", Spec_Id);
515 end if;
516
517 -- Restore the SPARK_Mode of the enclosing context after all delayed
518 -- pragmas have been analyzed.
519
520 Restore_SPARK_Mode (Mode);
521
522 -- Capture all global references in a generic package body now that the
523 -- contract has been analyzed.
524
525 if Is_Generic_Declaration_Or_Body (Body_Decl) then
526 Save_Global_References_In_Contract
527 (Templ => Original_Node (Body_Decl),
528 Gen_Id => Spec_Id);
529 end if;
530 end Analyze_Package_Body_Contract;
531
532 ------------------------------
533 -- Analyze_Package_Contract --
534 ------------------------------
535
536 procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
537 Items : constant Node_Id := Contract (Pack_Id);
538 Pack_Decl : constant Node_Id := Unit_Declaration_Node (Pack_Id);
539 Init : Node_Id := Empty;
540 Init_Cond : Node_Id := Empty;
541 Mode : SPARK_Mode_Type;
542 Prag : Node_Id;
543 Prag_Nam : Name_Id;
544
545 begin
546 -- Do not analyze a contract multiple times
547
548 if Present (Items) then
549 if Analyzed (Items) then
550 return;
551 else
552 Set_Analyzed (Items);
553 end if;
554 end if;
555
556 -- Due to the timing of contract analysis, delayed pragmas may be
557 -- subject to the wrong SPARK_Mode, usually that of the enclosing
558 -- context. To remedy this, restore the original SPARK_Mode of the
559 -- related package.
560
561 Save_SPARK_Mode_And_Set (Pack_Id, Mode);
562
563 if Present (Items) then
564
565 -- Locate and store pragmas Initial_Condition and Initializes, since
566 -- their order of analysis matters.
567
568 Prag := Classifications (Items);
569 while Present (Prag) loop
570 Prag_Nam := Pragma_Name (Prag);
571
572 if Prag_Nam = Name_Initial_Condition then
573 Init_Cond := Prag;
574
575 elsif Prag_Nam = Name_Initializes then
576 Init := Prag;
577 end if;
578
579 Prag := Next_Pragma (Prag);
580 end loop;
581
582 -- Analyze the initialization-related pragmas. Initializes must come
583 -- before Initial_Condition due to item dependencies.
584
585 if Present (Init) then
586 Analyze_Initializes_In_Decl_Part (Init);
587 end if;
588
589 if Present (Init_Cond) then
590 Analyze_Initial_Condition_In_Decl_Part (Init_Cond);
591 end if;
592 end if;
593
594 -- Check whether the lack of indicator Part_Of agrees with the placement
595 -- of the package instantiation with respect to the state space.
596
597 if Is_Generic_Instance (Pack_Id) then
598 Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
599
600 if No (Prag) then
601 Check_Missing_Part_Of (Pack_Id);
602 end if;
603 end if;
604
605 -- Restore the SPARK_Mode of the enclosing context after all delayed
606 -- pragmas have been analyzed.
607
608 Restore_SPARK_Mode (Mode);
609
610 -- Capture all global references in a generic package now that the
611 -- contract has been analyzed.
612
613 if Is_Generic_Declaration_Or_Body (Pack_Decl) then
614 Save_Global_References_In_Contract
615 (Templ => Original_Node (Pack_Decl),
616 Gen_Id => Pack_Id);
617 end if;
618 end Analyze_Package_Contract;
619
620 --------------------------------------
621 -- Analyze_Subprogram_Body_Contract --
622 --------------------------------------
623
624 procedure Analyze_Subprogram_Body_Contract (Body_Id : Entity_Id) is
625 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
626 Items : constant Node_Id := Contract (Body_Id);
627 Spec_Id : constant Entity_Id := Corresponding_Spec_Of (Body_Decl);
628 Mode : SPARK_Mode_Type;
629 Prag : Node_Id;
630 Prag_Nam : Name_Id;
631 Ref_Depends : Node_Id := Empty;
632 Ref_Global : Node_Id := Empty;
633
634 begin
635 -- When a subprogram body declaration is illegal, its defining entity is
636 -- left unanalyzed. There is nothing left to do in this case because the
637 -- body lacks a contract, or even a proper Ekind.
638
639 if Ekind (Body_Id) = E_Void then
640 return;
641
642 -- Do not analyze a contract multiple times
643
644 elsif Present (Items) then
645 if Analyzed (Items) then
646 return;
647 else
648 Set_Analyzed (Items);
649 end if;
650 end if;
651
652 -- Due to the timing of contract analysis, delayed pragmas may be
653 -- subject to the wrong SPARK_Mode, usually that of the enclosing
654 -- context. To remedy this, restore the original SPARK_Mode of the
655 -- related subprogram body.
656
657 Save_SPARK_Mode_And_Set (Body_Id, Mode);
658
659 -- All subprograms carry a contract, but for some it is not significant
660 -- and should not be processed.
661
662 if not Has_Significant_Contract (Body_Id) then
663 null;
664
665 -- The subprogram body is a completion, analyze all delayed pragmas that
666 -- apply. Note that when the body is stand-alone, the pragmas are always
667 -- analyzed on the spot.
668
669 elsif Present (Items) then
670
671 -- Locate and store pragmas Refined_Depends and Refined_Global, since
672 -- their order of analysis matters.
673
674 Prag := Classifications (Items);
675 while Present (Prag) loop
676 Prag_Nam := Pragma_Name (Prag);
677
678 if Prag_Nam = Name_Refined_Depends then
679 Ref_Depends := Prag;
680
681 elsif Prag_Nam = Name_Refined_Global then
682 Ref_Global := Prag;
683 end if;
684
685 Prag := Next_Pragma (Prag);
686 end loop;
687
688 -- Analyze Refined_Global first, as Refined_Depends may mention items
689 -- classified in the global refinement.
690
691 if Present (Ref_Global) then
692 Analyze_Refined_Global_In_Decl_Part (Ref_Global);
693 end if;
694
695 -- Refined_Depends must be analyzed after Refined_Global in order to
696 -- see the modes of all global refinements.
697
698 if Present (Ref_Depends) then
699 Analyze_Refined_Depends_In_Decl_Part (Ref_Depends);
700 end if;
701 end if;
702
703 -- Ensure that the contract cases or postconditions mention 'Result or
704 -- define a post-state.
705
706 Check_Result_And_Post_State (Body_Id);
707
708 -- A stand-alone nonvolatile function body cannot have an effectively
709 -- volatile formal parameter or return type (SPARK RM 7.1.3(9)). This
710 -- check is relevant only when SPARK_Mode is on, as it is not a standard
711 -- legality rule. The check is performed here because Volatile_Function
712 -- is processed after the analysis of the related subprogram body.
713
714 if SPARK_Mode = On
715 and then Ekind_In (Body_Id, E_Function, E_Generic_Function)
716 and then not Is_Volatile_Function (Body_Id)
717 then
718 Check_Nonvolatile_Function_Profile (Body_Id);
719 end if;
720
721 -- Restore the SPARK_Mode of the enclosing context after all delayed
722 -- pragmas have been analyzed.
723
724 Restore_SPARK_Mode (Mode);
725
726 -- Capture all global references in a generic subprogram body now that
727 -- the contract has been analyzed.
728
729 if Is_Generic_Declaration_Or_Body (Body_Decl) then
730 Save_Global_References_In_Contract
731 (Templ => Original_Node (Body_Decl),
732 Gen_Id => Spec_Id);
733 end if;
734
735 -- Deal with preconditions, [refined] postconditions, Contract_Cases,
736 -- invariants and predicates associated with body and its spec. Do not
737 -- expand the contract of subprogram body stubs.
738
739 if Nkind (Body_Decl) = N_Subprogram_Body then
740 Expand_Subprogram_Contract (Body_Id);
741 end if;
742 end Analyze_Subprogram_Body_Contract;
743
744 ---------------------------------
745 -- Analyze_Subprogram_Contract --
746 ---------------------------------
747
748 procedure Analyze_Subprogram_Contract (Subp_Id : Entity_Id) is
749 Items : constant Node_Id := Contract (Subp_Id);
750 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
751 Depends : Node_Id := Empty;
752 Global : Node_Id := Empty;
753 Mode : SPARK_Mode_Type;
754 Prag : Node_Id;
755 Prag_Nam : Name_Id;
756
757 begin
758 -- Do not analyze a contract multiple times
759
760 if Present (Items) then
761 if Analyzed (Items) then
762 return;
763 else
764 Set_Analyzed (Items);
765 end if;
766 end if;
767
768 -- Due to the timing of contract analysis, delayed pragmas may be
769 -- subject to the wrong SPARK_Mode, usually that of the enclosing
770 -- context. To remedy this, restore the original SPARK_Mode of the
771 -- related subprogram body.
772
773 Save_SPARK_Mode_And_Set (Subp_Id, Mode);
774
775 -- All subprograms carry a contract, but for some it is not significant
776 -- and should not be processed.
777
778 if not Has_Significant_Contract (Subp_Id) then
779 null;
780
781 elsif Present (Items) then
782
783 -- Analyze pre- and postconditions
784
785 Prag := Pre_Post_Conditions (Items);
786 while Present (Prag) loop
787 Analyze_Pre_Post_Condition_In_Decl_Part (Prag);
788 Prag := Next_Pragma (Prag);
789 end loop;
790
791 -- Analyze contract-cases and test-cases
792
793 Prag := Contract_Test_Cases (Items);
794 while Present (Prag) loop
795 Prag_Nam := Pragma_Name (Prag);
796
797 if Prag_Nam = Name_Contract_Cases then
798 Analyze_Contract_Cases_In_Decl_Part (Prag);
799 else
800 pragma Assert (Prag_Nam = Name_Test_Case);
801 Analyze_Test_Case_In_Decl_Part (Prag);
802 end if;
803
804 Prag := Next_Pragma (Prag);
805 end loop;
806
807 -- Analyze classification pragmas
808
809 Prag := Classifications (Items);
810 while Present (Prag) loop
811 Prag_Nam := Pragma_Name (Prag);
812
813 if Prag_Nam = Name_Depends then
814 Depends := Prag;
815
816 elsif Prag_Nam = Name_Global then
817 Global := Prag;
818 end if;
819
820 Prag := Next_Pragma (Prag);
821 end loop;
822
823 -- Analyze Global first, as Depends may mention items classified in
824 -- the global categorization.
825
826 if Present (Global) then
827 Analyze_Global_In_Decl_Part (Global);
828 end if;
829
830 -- Depends must be analyzed after Global in order to see the modes of
831 -- all global items.
832
833 if Present (Depends) then
834 Analyze_Depends_In_Decl_Part (Depends);
835 end if;
836
837 -- Ensure that the contract cases or postconditions mention 'Result
838 -- or define a post-state.
839
840 Check_Result_And_Post_State (Subp_Id);
841 end if;
842
843 -- A nonvolatile function cannot have an effectively volatile formal
844 -- parameter or return type (SPARK RM 7.1.3(9)). This check is relevant
845 -- only when SPARK_Mode is on, as it is not a standard legality rule.
846 -- The check is performed here because pragma Volatile_Function is
847 -- processed after the analysis of the related subprogram declaration.
848
849 if SPARK_Mode = On
850 and then Ekind_In (Subp_Id, E_Function, E_Generic_Function)
851 and then not Is_Volatile_Function (Subp_Id)
852 then
853 Check_Nonvolatile_Function_Profile (Subp_Id);
854 end if;
855
856 -- Restore the SPARK_Mode of the enclosing context after all delayed
857 -- pragmas have been analyzed.
858
859 Restore_SPARK_Mode (Mode);
860
861 -- Capture all global references in a generic subprogram now that the
862 -- contract has been analyzed.
863
864 if Is_Generic_Declaration_Or_Body (Subp_Decl) then
865 Save_Global_References_In_Contract
866 (Templ => Original_Node (Subp_Decl),
867 Gen_Id => Subp_Id);
868 end if;
869 end Analyze_Subprogram_Contract;
870
871 -------------------------------------------
872 -- Analyze_Subprogram_Body_Stub_Contract --
873 -------------------------------------------
874
875 procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id) is
876 Stub_Decl : constant Node_Id := Parent (Parent (Stub_Id));
877 Spec_Id : constant Entity_Id := Corresponding_Spec_Of_Stub (Stub_Decl);
878
879 begin
880 -- A subprogram body stub may act as its own spec or as the completion
881 -- of a previous declaration. Depending on the context, the contract of
882 -- the stub may contain two sets of pragmas.
883
884 -- The stub is a completion, the applicable pragmas are:
885 -- Refined_Depends
886 -- Refined_Global
887
888 if Present (Spec_Id) then
889 Analyze_Subprogram_Body_Contract (Stub_Id);
890
891 -- The stub acts as its own spec, the applicable pragmas are:
892 -- Contract_Cases
893 -- Depends
894 -- Global
895 -- Postcondition
896 -- Precondition
897 -- Test_Case
898
899 else
900 Analyze_Subprogram_Contract (Stub_Id);
901 end if;
902 end Analyze_Subprogram_Body_Stub_Contract;
903
904 -----------------------------
905 -- Create_Generic_Contract --
906 -----------------------------
907
908 procedure Create_Generic_Contract (Unit : Node_Id) is
909 Templ : constant Node_Id := Original_Node (Unit);
910 Templ_Id : constant Entity_Id := Defining_Entity (Templ);
911
912 procedure Add_Generic_Contract_Pragma (Prag : Node_Id);
913 -- Add a single contract-related source pragma Prag to the contract of
914 -- generic template Templ_Id.
915
916 ---------------------------------
917 -- Add_Generic_Contract_Pragma --
918 ---------------------------------
919
920 procedure Add_Generic_Contract_Pragma (Prag : Node_Id) is
921 Prag_Templ : Node_Id;
922
923 begin
924 -- Mark the pragma to prevent the premature capture of global
925 -- references when capturing global references of the context
926 -- (see Save_References_In_Pragma).
927
928 Set_Is_Generic_Contract_Pragma (Prag);
929
930 -- Pragmas that apply to a generic subprogram declaration are not
931 -- part of the semantic structure of the generic template:
932
933 -- generic
934 -- procedure Example (Formal : Integer);
935 -- pragma Precondition (Formal > 0);
936
937 -- Create a generic template for such pragmas and link the template
938 -- of the pragma with the generic template.
939
940 if Nkind (Templ) = N_Generic_Subprogram_Declaration then
941 Rewrite
942 (Prag, Copy_Generic_Node (Prag, Empty, Instantiating => False));
943 Prag_Templ := Original_Node (Prag);
944
945 Set_Is_Generic_Contract_Pragma (Prag_Templ);
946 Add_Contract_Item (Prag_Templ, Templ_Id);
947
948 -- Otherwise link the pragma with the generic template
949
950 else
951 Add_Contract_Item (Prag, Templ_Id);
952 end if;
953 end Add_Generic_Contract_Pragma;
954
955 -- Local variables
956
957 Context : constant Node_Id := Parent (Unit);
958 Decl : Node_Id := Empty;
959
960 -- Start of processing for Create_Generic_Contract
961
962 begin
963 -- A generic package declaration carries contract-related source pragmas
964 -- in its visible declarations.
965
966 if Nkind (Templ) = N_Generic_Package_Declaration then
967 Set_Ekind (Templ_Id, E_Generic_Package);
968
969 if Present (Visible_Declarations (Specification (Templ))) then
970 Decl := First (Visible_Declarations (Specification (Templ)));
971 end if;
972
973 -- A generic package body carries contract-related source pragmas in its
974 -- declarations.
975
976 elsif Nkind (Templ) = N_Package_Body then
977 Set_Ekind (Templ_Id, E_Package_Body);
978
979 if Present (Declarations (Templ)) then
980 Decl := First (Declarations (Templ));
981 end if;
982
983 -- Generic subprogram declaration
984
985 elsif Nkind (Templ) = N_Generic_Subprogram_Declaration then
986 if Nkind (Specification (Templ)) = N_Function_Specification then
987 Set_Ekind (Templ_Id, E_Generic_Function);
988 else
989 Set_Ekind (Templ_Id, E_Generic_Procedure);
990 end if;
991
992 -- When the generic subprogram acts as a compilation unit, inspect
993 -- the Pragmas_After list for contract-related source pragmas.
994
995 if Nkind (Context) = N_Compilation_Unit then
996 if Present (Aux_Decls_Node (Context))
997 and then Present (Pragmas_After (Aux_Decls_Node (Context)))
998 then
999 Decl := First (Pragmas_After (Aux_Decls_Node (Context)));
1000 end if;
1001
1002 -- Otherwise inspect the successive declarations for contract-related
1003 -- source pragmas.
1004
1005 else
1006 Decl := Next (Unit);
1007 end if;
1008
1009 -- A generic subprogram body carries contract-related source pragmas in
1010 -- its declarations.
1011
1012 elsif Nkind (Templ) = N_Subprogram_Body then
1013 Set_Ekind (Templ_Id, E_Subprogram_Body);
1014
1015 if Present (Declarations (Templ)) then
1016 Decl := First (Declarations (Templ));
1017 end if;
1018 end if;
1019
1020 -- Inspect the relevant declarations looking for contract-related source
1021 -- pragmas and add them to the contract of the generic unit.
1022
1023 while Present (Decl) loop
1024 if Comes_From_Source (Decl) then
1025 if Nkind (Decl) = N_Pragma then
1026
1027 -- The source pragma is a contract annotation
1028
1029 if Is_Contract_Annotation (Decl) then
1030 Add_Generic_Contract_Pragma (Decl);
1031 end if;
1032
1033 -- The region where a contract-related source pragma may appear
1034 -- ends with the first source non-pragma declaration or statement.
1035
1036 else
1037 exit;
1038 end if;
1039 end if;
1040
1041 Next (Decl);
1042 end loop;
1043 end Create_Generic_Contract;
1044
1045 --------------------------------
1046 -- Expand_Subprogram_Contract --
1047 --------------------------------
1048
1049 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id) is
1050 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
1051 Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
1052
1053 procedure Add_Invariant_And_Predicate_Checks
1054 (Subp_Id : Entity_Id;
1055 Stmts : in out List_Id;
1056 Result : out Node_Id);
1057 -- Process the result of function Subp_Id (if applicable) and all its
1058 -- formals. Add invariant and predicate checks where applicable. The
1059 -- routine appends all the checks to list Stmts. If Subp_Id denotes a
1060 -- function, Result contains the entity of parameter _Result, to be
1061 -- used in the creation of procedure _Postconditions.
1062
1063 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
1064 -- Append a node to a list. If there is no list, create a new one. When
1065 -- the item denotes a pragma, it is added to the list only when it is
1066 -- enabled.
1067
1068 procedure Build_Postconditions_Procedure
1069 (Subp_Id : Entity_Id;
1070 Stmts : List_Id;
1071 Result : Entity_Id);
1072 -- Create the body of procedure _Postconditions which handles various
1073 -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
1074 -- of statements to be checked on exit. Parameter Result is the entity
1075 -- of parameter _Result when Subp_Id denotes a function.
1076
1077 function Build_Pragma_Check_Equivalent
1078 (Prag : Node_Id;
1079 Subp_Id : Entity_Id := Empty;
1080 Inher_Id : Entity_Id := Empty) return Node_Id;
1081 -- Transform a [refined] pre- or postcondition denoted by Prag into an
1082 -- equivalent pragma Check. When the pre- or postcondition is inherited,
1083 -- the routine corrects the references of all formals of Inher_Id to
1084 -- point to the formals of Subp_Id.
1085
1086 procedure Process_Contract_Cases (Stmts : in out List_Id);
1087 -- Process pragma Contract_Cases. This routine prepends items to the
1088 -- body declarations and appends items to list Stmts.
1089
1090 procedure Process_Postconditions (Stmts : in out List_Id);
1091 -- Collect all [inherited] spec and body postconditions and accumulate
1092 -- their pragma Check equivalents in list Stmts.
1093
1094 procedure Process_Preconditions;
1095 -- Collect all [inherited] spec and body preconditions and prepend their
1096 -- pragma Check equivalents to the declarations of the body.
1097
1098 ----------------------------------------
1099 -- Add_Invariant_And_Predicate_Checks --
1100 ----------------------------------------
1101
1102 procedure Add_Invariant_And_Predicate_Checks
1103 (Subp_Id : Entity_Id;
1104 Stmts : in out List_Id;
1105 Result : out Node_Id)
1106 is
1107 procedure Add_Invariant_Access_Checks (Id : Entity_Id);
1108 -- Id denotes the return value of a function or a formal parameter.
1109 -- Add an invariant check if the type of Id is access to a type with
1110 -- invariants. The routine appends the generated code to Stmts.
1111
1112 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
1113 -- Determine whether type Typ can benefit from invariant checks. To
1114 -- qualify, the type must have a non-null invariant procedure and
1115 -- subprogram Subp_Id must appear visible from the point of view of
1116 -- the type.
1117
1118 ---------------------------------
1119 -- Add_Invariant_Access_Checks --
1120 ---------------------------------
1121
1122 procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
1123 Loc : constant Source_Ptr := Sloc (Body_Decl);
1124 Ref : Node_Id;
1125 Typ : Entity_Id;
1126
1127 begin
1128 Typ := Etype (Id);
1129
1130 if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
1131 Typ := Designated_Type (Typ);
1132
1133 if Invariant_Checks_OK (Typ) then
1134 Ref :=
1135 Make_Explicit_Dereference (Loc,
1136 Prefix => New_Occurrence_Of (Id, Loc));
1137 Set_Etype (Ref, Typ);
1138
1139 -- Generate:
1140 -- if <Id> /= null then
1141 -- <invariant_call (<Ref>)>
1142 -- end if;
1143
1144 Append_Enabled_Item
1145 (Item =>
1146 Make_If_Statement (Loc,
1147 Condition =>
1148 Make_Op_Ne (Loc,
1149 Left_Opnd => New_Occurrence_Of (Id, Loc),
1150 Right_Opnd => Make_Null (Loc)),
1151 Then_Statements => New_List (
1152 Make_Invariant_Call (Ref))),
1153 List => Stmts);
1154 end if;
1155 end if;
1156 end Add_Invariant_Access_Checks;
1157
1158 -------------------------
1159 -- Invariant_Checks_OK --
1160 -------------------------
1161
1162 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
1163 function Has_Null_Body (Proc_Id : Entity_Id) return Boolean;
1164 -- Determine whether the body of procedure Proc_Id contains a sole
1165 -- null statement, possibly followed by an optional return.
1166
1167 function Has_Public_Visibility_Of_Subprogram return Boolean;
1168 -- Determine whether type Typ has public visibility of subprogram
1169 -- Subp_Id.
1170
1171 -------------------
1172 -- Has_Null_Body --
1173 -------------------
1174
1175 function Has_Null_Body (Proc_Id : Entity_Id) return Boolean is
1176 Body_Id : Entity_Id;
1177 Decl : Node_Id;
1178 Spec : Node_Id;
1179 Stmt1 : Node_Id;
1180 Stmt2 : Node_Id;
1181
1182 begin
1183 Spec := Parent (Proc_Id);
1184 Decl := Parent (Spec);
1185
1186 -- Retrieve the entity of the invariant procedure body
1187
1188 if Nkind (Spec) = N_Procedure_Specification
1189 and then Nkind (Decl) = N_Subprogram_Declaration
1190 then
1191 Body_Id := Corresponding_Body (Decl);
1192
1193 -- The body acts as a spec
1194
1195 else
1196 Body_Id := Proc_Id;
1197 end if;
1198
1199 -- The body will be generated later
1200
1201 if No (Body_Id) then
1202 return False;
1203 end if;
1204
1205 Spec := Parent (Body_Id);
1206 Decl := Parent (Spec);
1207
1208 pragma Assert
1209 (Nkind (Spec) = N_Procedure_Specification
1210 and then Nkind (Decl) = N_Subprogram_Body);
1211
1212 Stmt1 := First (Statements (Handled_Statement_Sequence (Decl)));
1213
1214 -- Look for a null statement followed by an optional return
1215 -- statement.
1216
1217 if Nkind (Stmt1) = N_Null_Statement then
1218 Stmt2 := Next (Stmt1);
1219
1220 if Present (Stmt2) then
1221 return Nkind (Stmt2) = N_Simple_Return_Statement;
1222 else
1223 return True;
1224 end if;
1225 end if;
1226
1227 return False;
1228 end Has_Null_Body;
1229
1230 -----------------------------------------
1231 -- Has_Public_Visibility_Of_Subprogram --
1232 -----------------------------------------
1233
1234 function Has_Public_Visibility_Of_Subprogram return Boolean is
1235 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
1236
1237 begin
1238 -- An Initialization procedure must be considered visible even
1239 -- though it is internally generated.
1240
1241 if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
1242 return True;
1243
1244 elsif Ekind (Scope (Typ)) /= E_Package then
1245 return False;
1246
1247 -- Internally generated code is never publicly visible except
1248 -- for a subprogram that is the implementation of an expression
1249 -- function. In that case the visibility is determined by the
1250 -- last check.
1251
1252 elsif not Comes_From_Source (Subp_Decl)
1253 and then
1254 (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
1255 or else not
1256 Comes_From_Source (Defining_Entity (Subp_Decl)))
1257 then
1258 return False;
1259
1260 -- Determine whether the subprogram is declared in the visible
1261 -- declarations of the package containing the type.
1262
1263 else
1264 return List_Containing (Subp_Decl) =
1265 Visible_Declarations
1266 (Specification (Unit_Declaration_Node (Scope (Typ))));
1267 end if;
1268 end Has_Public_Visibility_Of_Subprogram;
1269
1270 -- Start of processing for Invariant_Checks_OK
1271
1272 begin
1273 return
1274 Has_Invariants (Typ)
1275 and then Present (Invariant_Procedure (Typ))
1276 and then not Has_Null_Body (Invariant_Procedure (Typ))
1277 and then Has_Public_Visibility_Of_Subprogram;
1278 end Invariant_Checks_OK;
1279
1280 -- Local variables
1281
1282 Loc : constant Source_Ptr := Sloc (Body_Decl);
1283 -- Source location of subprogram body contract
1284
1285 Formal : Entity_Id;
1286 Typ : Entity_Id;
1287
1288 -- Start of processing for Add_Invariant_And_Predicate_Checks
1289
1290 begin
1291 Result := Empty;
1292
1293 -- Process the result of a function
1294
1295 if Ekind (Subp_Id) = E_Function then
1296 Typ := Etype (Subp_Id);
1297
1298 -- Generate _Result which is used in procedure _Postconditions to
1299 -- verify the return value.
1300
1301 Result := Make_Defining_Identifier (Loc, Name_uResult);
1302 Set_Etype (Result, Typ);
1303
1304 -- Add an invariant check when the return type has invariants and
1305 -- the related function is visible to the outside.
1306
1307 if Invariant_Checks_OK (Typ) then
1308 Append_Enabled_Item
1309 (Item =>
1310 Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
1311 List => Stmts);
1312 end if;
1313
1314 -- Add an invariant check when the return type is an access to a
1315 -- type with invariants.
1316
1317 Add_Invariant_Access_Checks (Result);
1318 end if;
1319
1320 -- Add invariant and predicates for all formals that qualify
1321
1322 Formal := First_Formal (Subp_Id);
1323 while Present (Formal) loop
1324 Typ := Etype (Formal);
1325
1326 if Ekind (Formal) /= E_In_Parameter
1327 or else Is_Access_Type (Typ)
1328 then
1329 if Invariant_Checks_OK (Typ) then
1330 Append_Enabled_Item
1331 (Item =>
1332 Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
1333 List => Stmts);
1334 end if;
1335
1336 Add_Invariant_Access_Checks (Formal);
1337
1338 -- Note: we used to add predicate checks for OUT and IN OUT
1339 -- formals here, but that was misguided, since such checks are
1340 -- performed on the caller side, based on the predicate of the
1341 -- actual, rather than the predicate of the formal.
1342
1343 end if;
1344
1345 Next_Formal (Formal);
1346 end loop;
1347 end Add_Invariant_And_Predicate_Checks;
1348
1349 -------------------------
1350 -- Append_Enabled_Item --
1351 -------------------------
1352
1353 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
1354 begin
1355 -- Do not chain ignored or disabled pragmas
1356
1357 if Nkind (Item) = N_Pragma
1358 and then (Is_Ignored (Item) or else Is_Disabled (Item))
1359 then
1360 null;
1361
1362 -- Otherwise, add the item
1363
1364 else
1365 if No (List) then
1366 List := New_List;
1367 end if;
1368
1369 -- If the pragma is a conjunct in a composite postcondition, it
1370 -- has been processed in reverse order. In the postcondition body
1371 -- it must appear before the others.
1372
1373 if Nkind (Item) = N_Pragma
1374 and then From_Aspect_Specification (Item)
1375 and then Split_PPC (Item)
1376 then
1377 Prepend (Item, List);
1378 else
1379 Append (Item, List);
1380 end if;
1381 end if;
1382 end Append_Enabled_Item;
1383
1384 ------------------------------------
1385 -- Build_Postconditions_Procedure --
1386 ------------------------------------
1387
1388 procedure Build_Postconditions_Procedure
1389 (Subp_Id : Entity_Id;
1390 Stmts : List_Id;
1391 Result : Entity_Id)
1392 is
1393 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id);
1394 -- Insert node Stmt before the first source declaration of the
1395 -- related subprogram's body. If no such declaration exists, Stmt
1396 -- becomes the last declaration.
1397
1398 --------------------------------------------
1399 -- Insert_Before_First_Source_Declaration --
1400 --------------------------------------------
1401
1402 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id) is
1403 Decls : constant List_Id := Declarations (Body_Decl);
1404 Decl : Node_Id;
1405
1406 begin
1407 -- Inspect the declarations of the related subprogram body looking
1408 -- for the first source declaration.
1409
1410 if Present (Decls) then
1411 Decl := First (Decls);
1412 while Present (Decl) loop
1413 if Comes_From_Source (Decl) then
1414 Insert_Before (Decl, Stmt);
1415 return;
1416 end if;
1417
1418 Next (Decl);
1419 end loop;
1420
1421 -- If we get there, then the subprogram body lacks any source
1422 -- declarations. The body of _Postconditions now acts as the
1423 -- last declaration.
1424
1425 Append (Stmt, Decls);
1426
1427 -- Ensure that the body has a declaration list
1428
1429 else
1430 Set_Declarations (Body_Decl, New_List (Stmt));
1431 end if;
1432 end Insert_Before_First_Source_Declaration;
1433
1434 -- Local variables
1435
1436 Loc : constant Source_Ptr := Sloc (Body_Decl);
1437 Params : List_Id := No_List;
1438 Proc_Bod : Node_Id;
1439 Proc_Id : Entity_Id;
1440
1441 -- Start of processing for Build_Postconditions_Procedure
1442
1443 begin
1444 -- Nothing to do if there are no actions to check on exit
1445
1446 if No (Stmts) then
1447 return;
1448 end if;
1449
1450 Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
1451 Set_Debug_Info_Needed (Proc_Id);
1452 Set_Postconditions_Proc (Subp_Id, Proc_Id);
1453
1454 -- The related subprogram is a function: create the specification of
1455 -- parameter _Result.
1456
1457 if Present (Result) then
1458 Params := New_List (
1459 Make_Parameter_Specification (Loc,
1460 Defining_Identifier => Result,
1461 Parameter_Type =>
1462 New_Occurrence_Of (Etype (Result), Loc)));
1463 end if;
1464
1465 -- Insert _Postconditions before the first source declaration of the
1466 -- body. This ensures that the body will not cause any premature
1467 -- freezing, as it may mention types:
1468
1469 -- procedure Proc (Obj : Array_Typ) is
1470 -- procedure _postconditions is
1471 -- begin
1472 -- ... Obj ...
1473 -- end _postconditions;
1474
1475 -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
1476 -- begin
1477
1478 -- In the example above, Obj is of type T but the incorrect placement
1479 -- of _Postconditions will cause a crash in gigi due to an out-of-
1480 -- order reference. The body of _Postconditions must be placed after
1481 -- the declaration of Temp to preserve correct visibility.
1482
1483 -- Set an explicit End_Label to override the sloc of the implicit
1484 -- RETURN statement, and prevent it from inheriting the sloc of one
1485 -- the postconditions: this would cause confusing debug info to be
1486 -- produced, interfering with coverage-analysis tools.
1487
1488 Proc_Bod :=
1489 Make_Subprogram_Body (Loc,
1490 Specification =>
1491 Make_Procedure_Specification (Loc,
1492 Defining_Unit_Name => Proc_Id,
1493 Parameter_Specifications => Params),
1494
1495 Declarations => Empty_List,
1496 Handled_Statement_Sequence =>
1497 Make_Handled_Sequence_Of_Statements (Loc,
1498 Statements => Stmts,
1499 End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
1500
1501 Insert_Before_First_Source_Declaration (Proc_Bod);
1502 Analyze (Proc_Bod);
1503 end Build_Postconditions_Procedure;
1504
1505 -----------------------------------
1506 -- Build_Pragma_Check_Equivalent --
1507 -----------------------------------
1508
1509 function Build_Pragma_Check_Equivalent
1510 (Prag : Node_Id;
1511 Subp_Id : Entity_Id := Empty;
1512 Inher_Id : Entity_Id := Empty) return Node_Id
1513 is
1514 function Suppress_Reference (N : Node_Id) return Traverse_Result;
1515 -- Detect whether node N references a formal parameter subject to
1516 -- pragma Unreferenced. If this is the case, set Comes_From_Source
1517 -- to False to suppress the generation of a reference when analyzing
1518 -- N later on.
1519
1520 ------------------------
1521 -- Suppress_Reference --
1522 ------------------------
1523
1524 function Suppress_Reference (N : Node_Id) return Traverse_Result is
1525 Formal : Entity_Id;
1526
1527 begin
1528 if Is_Entity_Name (N) and then Present (Entity (N)) then
1529 Formal := Entity (N);
1530
1531 -- The formal parameter is subject to pragma Unreferenced.
1532 -- Prevent the generation of a reference by resetting the
1533 -- Comes_From_Source flag.
1534
1535 if Is_Formal (Formal)
1536 and then Has_Pragma_Unreferenced (Formal)
1537 then
1538 Set_Comes_From_Source (N, False);
1539 end if;
1540 end if;
1541
1542 return OK;
1543 end Suppress_Reference;
1544
1545 procedure Suppress_References is
1546 new Traverse_Proc (Suppress_Reference);
1547
1548 -- Local variables
1549
1550 Loc : constant Source_Ptr := Sloc (Prag);
1551 Prag_Nam : constant Name_Id := Pragma_Name (Prag);
1552 Check_Prag : Node_Id;
1553 Formals_Map : Elist_Id;
1554 Inher_Formal : Entity_Id;
1555 Msg_Arg : Node_Id;
1556 Nam : Name_Id;
1557 Subp_Formal : Entity_Id;
1558
1559 -- Start of processing for Build_Pragma_Check_Equivalent
1560
1561 begin
1562 Formals_Map := No_Elist;
1563
1564 -- When the pre- or postcondition is inherited, map the formals of
1565 -- the inherited subprogram to those of the current subprogram.
1566
1567 if Present (Inher_Id) then
1568 pragma Assert (Present (Subp_Id));
1569
1570 Formals_Map := New_Elmt_List;
1571
1572 -- Create a relation <inherited formal> => <subprogram formal>
1573
1574 Inher_Formal := First_Formal (Inher_Id);
1575 Subp_Formal := First_Formal (Subp_Id);
1576 while Present (Inher_Formal) and then Present (Subp_Formal) loop
1577 Append_Elmt (Inher_Formal, Formals_Map);
1578 Append_Elmt (Subp_Formal, Formals_Map);
1579
1580 Next_Formal (Inher_Formal);
1581 Next_Formal (Subp_Formal);
1582 end loop;
1583 end if;
1584
1585 -- Copy the original pragma while performing substitutions (if
1586 -- applicable).
1587
1588 Check_Prag :=
1589 New_Copy_Tree
1590 (Source => Prag,
1591 Map => Formals_Map,
1592 New_Scope => Current_Scope);
1593
1594 -- Mark the pragma as being internally generated and reset the
1595 -- Analyzed flag.
1596
1597 Set_Analyzed (Check_Prag, False);
1598 Set_Comes_From_Source (Check_Prag, False);
1599
1600 -- The tree of the original pragma may contain references to the
1601 -- formal parameters of the related subprogram. At the same time
1602 -- the corresponding body may mark the formals as unreferenced:
1603
1604 -- procedure Proc (Formal : ...)
1605 -- with Pre => Formal ...;
1606
1607 -- procedure Proc (Formal : ...) is
1608 -- pragma Unreferenced (Formal);
1609 -- ...
1610
1611 -- This creates problems because all pragma Check equivalents are
1612 -- analyzed at the end of the body declarations. Since all source
1613 -- references have already been accounted for, reset any references
1614 -- to such formals in the generated pragma Check equivalent.
1615
1616 Suppress_References (Check_Prag);
1617
1618 if Present (Corresponding_Aspect (Prag)) then
1619 Nam := Chars (Identifier (Corresponding_Aspect (Prag)));
1620 else
1621 Nam := Prag_Nam;
1622 end if;
1623
1624 -- Convert the copy into pragma Check by correcting the name and
1625 -- adding a check_kind argument.
1626
1627 Set_Pragma_Identifier
1628 (Check_Prag, Make_Identifier (Loc, Name_Check));
1629
1630 Prepend_To (Pragma_Argument_Associations (Check_Prag),
1631 Make_Pragma_Argument_Association (Loc,
1632 Expression => Make_Identifier (Loc, Nam)));
1633
1634 -- Update the error message when the pragma is inherited
1635
1636 if Present (Inher_Id) then
1637 Msg_Arg := Last (Pragma_Argument_Associations (Check_Prag));
1638
1639 if Chars (Msg_Arg) = Name_Message then
1640 String_To_Name_Buffer (Strval (Expression (Msg_Arg)));
1641
1642 -- Insert "inherited" to improve the error message
1643
1644 if Name_Buffer (1 .. 8) = "failed p" then
1645 Insert_Str_In_Name_Buffer ("inherited ", 8);
1646 Set_Strval (Expression (Msg_Arg), String_From_Name_Buffer);
1647 end if;
1648 end if;
1649 end if;
1650
1651 return Check_Prag;
1652 end Build_Pragma_Check_Equivalent;
1653
1654 ----------------------------
1655 -- Process_Contract_Cases --
1656 ----------------------------
1657
1658 procedure Process_Contract_Cases (Stmts : in out List_Id) is
1659 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id);
1660 -- Process pragma Contract_Cases for subprogram Subp_Id
1661
1662 --------------------------------
1663 -- Process_Contract_Cases_For --
1664 --------------------------------
1665
1666 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id) is
1667 Items : constant Node_Id := Contract (Subp_Id);
1668 Prag : Node_Id;
1669
1670 begin
1671 if Present (Items) then
1672 Prag := Contract_Test_Cases (Items);
1673 while Present (Prag) loop
1674 if Pragma_Name (Prag) = Name_Contract_Cases then
1675 Expand_Pragma_Contract_Cases
1676 (CCs => Prag,
1677 Subp_Id => Subp_Id,
1678 Decls => Declarations (Body_Decl),
1679 Stmts => Stmts);
1680 end if;
1681
1682 Prag := Next_Pragma (Prag);
1683 end loop;
1684 end if;
1685 end Process_Contract_Cases_For;
1686
1687 -- Start of processing for Process_Contract_Cases
1688
1689 begin
1690 Process_Contract_Cases_For (Body_Id);
1691
1692 if Present (Spec_Id) then
1693 Process_Contract_Cases_For (Spec_Id);
1694 end if;
1695 end Process_Contract_Cases;
1696
1697 ----------------------------
1698 -- Process_Postconditions --
1699 ----------------------------
1700
1701 procedure Process_Postconditions (Stmts : in out List_Id) is
1702 procedure Process_Body_Postconditions (Post_Nam : Name_Id);
1703 -- Collect all [refined] postconditions of a specific kind denoted
1704 -- by Post_Nam that belong to the body, and generate pragma Check
1705 -- equivalents in list Stmts.
1706
1707 procedure Process_Spec_Postconditions;
1708 -- Collect all [inherited] postconditions of the spec, and generate
1709 -- pragma Check equivalents in list Stmts.
1710
1711 ---------------------------------
1712 -- Process_Body_Postconditions --
1713 ---------------------------------
1714
1715 procedure Process_Body_Postconditions (Post_Nam : Name_Id) is
1716 Items : constant Node_Id := Contract (Body_Id);
1717 Unit_Decl : constant Node_Id := Parent (Body_Decl);
1718 Decl : Node_Id;
1719 Prag : Node_Id;
1720
1721 begin
1722 -- Process the contract
1723
1724 if Present (Items) then
1725 Prag := Pre_Post_Conditions (Items);
1726 while Present (Prag) loop
1727 if Pragma_Name (Prag) = Post_Nam then
1728 Append_Enabled_Item
1729 (Item => Build_Pragma_Check_Equivalent (Prag),
1730 List => Stmts);
1731 end if;
1732
1733 Prag := Next_Pragma (Prag);
1734 end loop;
1735 end if;
1736
1737 -- The subprogram body being processed is actually the proper body
1738 -- of a stub with a corresponding spec. The subprogram stub may
1739 -- carry a postcondition pragma, in which case it must be taken
1740 -- into account. The pragma appears after the stub.
1741
1742 if Present (Spec_Id) and then Nkind (Unit_Decl) = N_Subunit then
1743 Decl := Next (Corresponding_Stub (Unit_Decl));
1744 while Present (Decl) loop
1745
1746 -- Note that non-matching pragmas are skipped
1747
1748 if Nkind (Decl) = N_Pragma then
1749 if Pragma_Name (Decl) = Post_Nam then
1750 Append_Enabled_Item
1751 (Item => Build_Pragma_Check_Equivalent (Decl),
1752 List => Stmts);
1753 end if;
1754
1755 -- Skip internally generated code
1756
1757 elsif not Comes_From_Source (Decl) then
1758 null;
1759
1760 -- Postcondition pragmas are usually grouped together. There
1761 -- is no need to inspect the whole declarative list.
1762
1763 else
1764 exit;
1765 end if;
1766
1767 Next (Decl);
1768 end loop;
1769 end if;
1770 end Process_Body_Postconditions;
1771
1772 ---------------------------------
1773 -- Process_Spec_Postconditions --
1774 ---------------------------------
1775
1776 procedure Process_Spec_Postconditions is
1777 Subps : constant Subprogram_List :=
1778 Inherited_Subprograms (Spec_Id);
1779 Items : Node_Id;
1780 Prag : Node_Id;
1781 Subp_Id : Entity_Id;
1782
1783 begin
1784 -- Process the contract
1785
1786 Items := Contract (Spec_Id);
1787
1788 if Present (Items) then
1789 Prag := Pre_Post_Conditions (Items);
1790 while Present (Prag) loop
1791 if Pragma_Name (Prag) = Name_Postcondition then
1792 Append_Enabled_Item
1793 (Item => Build_Pragma_Check_Equivalent (Prag),
1794 List => Stmts);
1795 end if;
1796
1797 Prag := Next_Pragma (Prag);
1798 end loop;
1799 end if;
1800
1801 -- Process the contracts of all inherited subprograms, looking for
1802 -- class-wide postconditions.
1803
1804 for Index in Subps'Range loop
1805 Subp_Id := Subps (Index);
1806 Items := Contract (Subp_Id);
1807
1808 if Present (Items) then
1809 Prag := Pre_Post_Conditions (Items);
1810 while Present (Prag) loop
1811 if Pragma_Name (Prag) = Name_Postcondition
1812 and then Class_Present (Prag)
1813 then
1814 Append_Enabled_Item
1815 (Item =>
1816 Build_Pragma_Check_Equivalent
1817 (Prag => Prag,
1818 Subp_Id => Spec_Id,
1819 Inher_Id => Subp_Id),
1820 List => Stmts);
1821 end if;
1822
1823 Prag := Next_Pragma (Prag);
1824 end loop;
1825 end if;
1826 end loop;
1827 end Process_Spec_Postconditions;
1828
1829 -- Start of processing for Process_Postconditions
1830
1831 begin
1832 -- The processing of postconditions is done in reverse order (body
1833 -- first) to ensure the following arrangement:
1834
1835 -- <refined postconditions from body>
1836 -- <postconditions from body>
1837 -- <postconditions from spec>
1838 -- <inherited postconditions>
1839
1840 Process_Body_Postconditions (Name_Refined_Post);
1841 Process_Body_Postconditions (Name_Postcondition);
1842
1843 if Present (Spec_Id) then
1844 Process_Spec_Postconditions;
1845 end if;
1846 end Process_Postconditions;
1847
1848 ---------------------------
1849 -- Process_Preconditions --
1850 ---------------------------
1851
1852 procedure Process_Preconditions is
1853 Class_Pre : Node_Id := Empty;
1854 -- The sole [inherited] class-wide precondition pragma that applies
1855 -- to the subprogram.
1856
1857 Insert_Node : Node_Id := Empty;
1858 -- The insertion node after which all pragma Check equivalents are
1859 -- inserted.
1860
1861 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
1862 -- Merge two class-wide preconditions by "or else"-ing them. The
1863 -- changes are accumulated in parameter Into. Update the error
1864 -- message of Into.
1865
1866 procedure Prepend_To_Decls (Item : Node_Id);
1867 -- Prepend a single item to the declarations of the subprogram body
1868
1869 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
1870 -- Save a class-wide precondition into Class_Pre, or prepend a normal
1871 -- precondition to the declarations of the body and analyze it.
1872
1873 procedure Process_Inherited_Preconditions;
1874 -- Collect all inherited class-wide preconditions and merge them into
1875 -- one big precondition to be evaluated as pragma Check.
1876
1877 procedure Process_Preconditions_For (Subp_Id : Entity_Id);
1878 -- Collect all preconditions of subprogram Subp_Id and prepend their
1879 -- pragma Check equivalents to the declarations of the body.
1880
1881 -------------------------
1882 -- Merge_Preconditions --
1883 -------------------------
1884
1885 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
1886 function Expression_Arg (Prag : Node_Id) return Node_Id;
1887 -- Return the boolean expression argument of a precondition while
1888 -- updating its parentheses count for the subsequent merge.
1889
1890 function Message_Arg (Prag : Node_Id) return Node_Id;
1891 -- Return the message argument of a precondition
1892
1893 --------------------
1894 -- Expression_Arg --
1895 --------------------
1896
1897 function Expression_Arg (Prag : Node_Id) return Node_Id is
1898 Args : constant List_Id := Pragma_Argument_Associations (Prag);
1899 Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
1900
1901 begin
1902 if Paren_Count (Arg) = 0 then
1903 Set_Paren_Count (Arg, 1);
1904 end if;
1905
1906 return Arg;
1907 end Expression_Arg;
1908
1909 -----------------
1910 -- Message_Arg --
1911 -----------------
1912
1913 function Message_Arg (Prag : Node_Id) return Node_Id is
1914 Args : constant List_Id := Pragma_Argument_Associations (Prag);
1915 begin
1916 return Get_Pragma_Arg (Last (Args));
1917 end Message_Arg;
1918
1919 -- Local variables
1920
1921 From_Expr : constant Node_Id := Expression_Arg (From);
1922 From_Msg : constant Node_Id := Message_Arg (From);
1923 Into_Expr : constant Node_Id := Expression_Arg (Into);
1924 Into_Msg : constant Node_Id := Message_Arg (Into);
1925 Loc : constant Source_Ptr := Sloc (Into);
1926
1927 -- Start of processing for Merge_Preconditions
1928
1929 begin
1930 -- Merge the two preconditions by "or else"-ing them
1931
1932 Rewrite (Into_Expr,
1933 Make_Or_Else (Loc,
1934 Right_Opnd => Relocate_Node (Into_Expr),
1935 Left_Opnd => From_Expr));
1936
1937 -- Merge the two error messages to produce a single message of the
1938 -- form:
1939
1940 -- failed precondition from ...
1941 -- also failed inherited precondition from ...
1942
1943 if not Exception_Locations_Suppressed then
1944 Start_String (Strval (Into_Msg));
1945 Store_String_Char (ASCII.LF);
1946 Store_String_Chars (" also ");
1947 Store_String_Chars (Strval (From_Msg));
1948
1949 Set_Strval (Into_Msg, End_String);
1950 end if;
1951 end Merge_Preconditions;
1952
1953 ----------------------
1954 -- Prepend_To_Decls --
1955 ----------------------
1956
1957 procedure Prepend_To_Decls (Item : Node_Id) is
1958 Decls : List_Id := Declarations (Body_Decl);
1959
1960 begin
1961 -- Ensure that the body has a declarative list
1962
1963 if No (Decls) then
1964 Decls := New_List;
1965 Set_Declarations (Body_Decl, Decls);
1966 end if;
1967
1968 Prepend_To (Decls, Item);
1969 end Prepend_To_Decls;
1970
1971 ------------------------------
1972 -- Prepend_To_Decls_Or_Save --
1973 ------------------------------
1974
1975 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
1976 Check_Prag : Node_Id;
1977
1978 begin
1979 Check_Prag := Build_Pragma_Check_Equivalent (Prag);
1980
1981 -- Save the sole class-wide precondition (if any) for the next
1982 -- step, where it will be merged with inherited preconditions.
1983
1984 if Class_Present (Prag) then
1985 pragma Assert (No (Class_Pre));
1986 Class_Pre := Check_Prag;
1987
1988 -- Accumulate the corresponding Check pragmas at the top of the
1989 -- declarations. Prepending the items ensures that they will be
1990 -- evaluated in their original order.
1991
1992 else
1993 if Present (Insert_Node) then
1994 Insert_After (Insert_Node, Check_Prag);
1995 else
1996 Prepend_To_Decls (Check_Prag);
1997 end if;
1998
1999 Analyze (Check_Prag);
2000 end if;
2001 end Prepend_To_Decls_Or_Save;
2002
2003 -------------------------------------
2004 -- Process_Inherited_Preconditions --
2005 -------------------------------------
2006
2007 procedure Process_Inherited_Preconditions is
2008 Subps : constant Subprogram_List :=
2009 Inherited_Subprograms (Spec_Id);
2010 Check_Prag : Node_Id;
2011 Items : Node_Id;
2012 Prag : Node_Id;
2013 Subp_Id : Entity_Id;
2014
2015 begin
2016 -- Process the contracts of all inherited subprograms, looking for
2017 -- class-wide preconditions.
2018
2019 for Index in Subps'Range loop
2020 Subp_Id := Subps (Index);
2021 Items := Contract (Subp_Id);
2022
2023 if Present (Items) then
2024 Prag := Pre_Post_Conditions (Items);
2025 while Present (Prag) loop
2026 if Pragma_Name (Prag) = Name_Precondition
2027 and then Class_Present (Prag)
2028 then
2029 Check_Prag :=
2030 Build_Pragma_Check_Equivalent
2031 (Prag => Prag,
2032 Subp_Id => Spec_Id,
2033 Inher_Id => Subp_Id);
2034
2035 -- The spec of an inherited subprogram already yielded
2036 -- a class-wide precondition. Merge the existing
2037 -- precondition with the current one using "or else".
2038
2039 if Present (Class_Pre) then
2040 Merge_Preconditions (Check_Prag, Class_Pre);
2041 else
2042 Class_Pre := Check_Prag;
2043 end if;
2044 end if;
2045
2046 Prag := Next_Pragma (Prag);
2047 end loop;
2048 end if;
2049 end loop;
2050
2051 -- Add the merged class-wide preconditions
2052
2053 if Present (Class_Pre) then
2054 Prepend_To_Decls (Class_Pre);
2055 Analyze (Class_Pre);
2056 end if;
2057 end Process_Inherited_Preconditions;
2058
2059 -------------------------------
2060 -- Process_Preconditions_For --
2061 -------------------------------
2062
2063 procedure Process_Preconditions_For (Subp_Id : Entity_Id) is
2064 Items : constant Node_Id := Contract (Subp_Id);
2065 Decl : Node_Id;
2066 Prag : Node_Id;
2067 Subp_Decl : Node_Id;
2068
2069 begin
2070 -- Process the contract
2071
2072 if Present (Items) then
2073 Prag := Pre_Post_Conditions (Items);
2074 while Present (Prag) loop
2075 if Pragma_Name (Prag) = Name_Precondition then
2076 Prepend_To_Decls_Or_Save (Prag);
2077 end if;
2078
2079 Prag := Next_Pragma (Prag);
2080 end loop;
2081 end if;
2082
2083 -- The subprogram declaration being processed is actually a body
2084 -- stub. The stub may carry a precondition pragma, in which case
2085 -- it must be taken into account. The pragma appears after the
2086 -- stub.
2087
2088 Subp_Decl := Unit_Declaration_Node (Subp_Id);
2089
2090 if Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
2091
2092 -- Inspect the declarations following the body stub
2093
2094 Decl := Next (Subp_Decl);
2095 while Present (Decl) loop
2096
2097 -- Note that non-matching pragmas are skipped
2098
2099 if Nkind (Decl) = N_Pragma then
2100 if Pragma_Name (Decl) = Name_Precondition then
2101 Prepend_To_Decls_Or_Save (Decl);
2102 end if;
2103
2104 -- Skip internally generated code
2105
2106 elsif not Comes_From_Source (Decl) then
2107 null;
2108
2109 -- Preconditions are usually grouped together. There is no
2110 -- need to inspect the whole declarative list.
2111
2112 else
2113 exit;
2114 end if;
2115
2116 Next (Decl);
2117 end loop;
2118 end if;
2119 end Process_Preconditions_For;
2120
2121 -- Local variables
2122
2123 Decls : constant List_Id := Declarations (Body_Decl);
2124 Decl : Node_Id;
2125
2126 -- Start of processing for Process_Preconditions
2127
2128 begin
2129 -- Find the last internally generated declaration, starting from the
2130 -- top of the body declarations. This ensures that discriminals and
2131 -- subtypes are properly visible to the pragma Check equivalents.
2132
2133 if Present (Decls) then
2134 Decl := First (Decls);
2135 while Present (Decl) loop
2136 exit when Comes_From_Source (Decl);
2137 Insert_Node := Decl;
2138 Next (Decl);
2139 end loop;
2140 end if;
2141
2142 -- The processing of preconditions is done in reverse order (body
2143 -- first), because each pragma Check equivalent is inserted at the
2144 -- top of the declarations. This ensures that the final order is
2145 -- consistent with following diagram:
2146
2147 -- <inherited preconditions>
2148 -- <preconditions from spec>
2149 -- <preconditions from body>
2150
2151 Process_Preconditions_For (Body_Id);
2152
2153 if Present (Spec_Id) then
2154 Process_Preconditions_For (Spec_Id);
2155 Process_Inherited_Preconditions;
2156 end if;
2157 end Process_Preconditions;
2158
2159 -- Local variables
2160
2161 Restore_Scope : Boolean := False;
2162 Result : Entity_Id;
2163 Stmts : List_Id := No_List;
2164 Subp_Id : Entity_Id;
2165
2166 -- Start of processing for Expand_Subprogram_Contract
2167
2168 begin
2169 -- Obtain the entity of the initial declaration
2170
2171 if Present (Spec_Id) then
2172 Subp_Id := Spec_Id;
2173 else
2174 Subp_Id := Body_Id;
2175 end if;
2176
2177 -- Do not perform expansion activity when it is not needed
2178
2179 if not Expander_Active then
2180 return;
2181
2182 -- ASIS requires an unaltered tree
2183
2184 elsif ASIS_Mode then
2185 return;
2186
2187 -- GNATprove does not need the executable semantics of a contract
2188
2189 elsif GNATprove_Mode then
2190 return;
2191
2192 -- The contract of a generic subprogram or one declared in a generic
2193 -- context is not expanded, as the corresponding instance will provide
2194 -- the executable semantics of the contract.
2195
2196 elsif Is_Generic_Subprogram (Subp_Id) or else Inside_A_Generic then
2197 return;
2198
2199 -- All subprograms carry a contract, but for some it is not significant
2200 -- and should not be processed. This is a small optimization.
2201
2202 elsif not Has_Significant_Contract (Subp_Id) then
2203 return;
2204
2205 -- The contract of an ignored Ghost subprogram does not need expansion,
2206 -- because the subprogram and all calls to it will be removed.
2207
2208 elsif Is_Ignored_Ghost_Entity (Subp_Id) then
2209 return;
2210 end if;
2211
2212 -- Do not re-expand the same contract. This scenario occurs when a
2213 -- construct is rewritten into something else during its analysis
2214 -- (expression functions for instance).
2215
2216 if Has_Expanded_Contract (Subp_Id) then
2217 return;
2218
2219 -- Otherwise mark the subprogram
2220
2221 else
2222 Set_Has_Expanded_Contract (Subp_Id);
2223 end if;
2224
2225 -- Ensure that the formal parameters are visible when expanding all
2226 -- contract items.
2227
2228 if not In_Open_Scopes (Subp_Id) then
2229 Restore_Scope := True;
2230 Push_Scope (Subp_Id);
2231
2232 if Is_Generic_Subprogram (Subp_Id) then
2233 Install_Generic_Formals (Subp_Id);
2234 else
2235 Install_Formals (Subp_Id);
2236 end if;
2237 end if;
2238
2239 -- The expansion of a subprogram contract involves the creation of Check
2240 -- pragmas to verify the contract assertions of the spec and body in a
2241 -- particular order. The order is as follows:
2242
2243 -- function Example (...) return ... is
2244 -- procedure _Postconditions (...) is
2245 -- begin
2246 -- <refined postconditions from body>
2247 -- <postconditions from body>
2248 -- <postconditions from spec>
2249 -- <inherited postconditions>
2250 -- <contract case consequences>
2251 -- <invariant check of function result>
2252 -- <invariant and predicate checks of parameters>
2253 -- end _Postconditions;
2254
2255 -- <inherited preconditions>
2256 -- <preconditions from spec>
2257 -- <preconditions from body>
2258 -- <contract case conditions>
2259
2260 -- <source declarations>
2261 -- begin
2262 -- <source statements>
2263
2264 -- _Preconditions (Result);
2265 -- return Result;
2266 -- end Example;
2267
2268 -- Routine _Postconditions holds all contract assertions that must be
2269 -- verified on exit from the related subprogram.
2270
2271 -- Step 1: Handle all preconditions. This action must come before the
2272 -- processing of pragma Contract_Cases because the pragma prepends items
2273 -- to the body declarations.
2274
2275 Process_Preconditions;
2276
2277 -- Step 2: Handle all postconditions. This action must come before the
2278 -- processing of pragma Contract_Cases because the pragma appends items
2279 -- to list Stmts.
2280
2281 Process_Postconditions (Stmts);
2282
2283 -- Step 3: Handle pragma Contract_Cases. This action must come before
2284 -- the processing of invariants and predicates because those append
2285 -- items to list Stmts.
2286
2287 Process_Contract_Cases (Stmts);
2288
2289 -- Step 4: Apply invariant and predicate checks on a function result and
2290 -- all formals. The resulting checks are accumulated in list Stmts.
2291
2292 Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
2293
2294 -- Step 5: Construct procedure _Postconditions
2295
2296 Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
2297
2298 if Restore_Scope then
2299 End_Scope;
2300 end if;
2301 end Expand_Subprogram_Contract;
2302
2303 ---------------------------------
2304 -- Inherit_Subprogram_Contract --
2305 ---------------------------------
2306
2307 procedure Inherit_Subprogram_Contract
2308 (Subp : Entity_Id;
2309 From_Subp : Entity_Id)
2310 is
2311 procedure Inherit_Pragma (Prag_Id : Pragma_Id);
2312 -- Propagate a pragma denoted by Prag_Id from From_Subp's contract to
2313 -- Subp's contract.
2314
2315 --------------------
2316 -- Inherit_Pragma --
2317 --------------------
2318
2319 procedure Inherit_Pragma (Prag_Id : Pragma_Id) is
2320 Prag : constant Node_Id := Get_Pragma (From_Subp, Prag_Id);
2321 New_Prag : Node_Id;
2322
2323 begin
2324 -- A pragma cannot be part of more than one First_Pragma/Next_Pragma
2325 -- chains, therefore the node must be replicated. The new pragma is
2326 -- flagged as inherited for distinction purposes.
2327
2328 if Present (Prag) then
2329 New_Prag := New_Copy_Tree (Prag);
2330 Set_Is_Inherited (New_Prag);
2331
2332 Add_Contract_Item (New_Prag, Subp);
2333 end if;
2334 end Inherit_Pragma;
2335
2336 -- Start of processing for Inherit_Subprogram_Contract
2337
2338 begin
2339 -- Inheritance is carried out only when both entities are subprograms
2340 -- with contracts.
2341
2342 if Is_Subprogram_Or_Generic_Subprogram (Subp)
2343 and then Is_Subprogram_Or_Generic_Subprogram (From_Subp)
2344 and then Present (Contract (From_Subp))
2345 then
2346 Inherit_Pragma (Pragma_Extensions_Visible);
2347 end if;
2348 end Inherit_Subprogram_Contract;
2349
2350 -------------------------------------
2351 -- Instantiate_Subprogram_Contract --
2352 -------------------------------------
2353
2354 procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id) is
2355 procedure Instantiate_Pragmas (First_Prag : Node_Id);
2356 -- Instantiate all contract-related source pragmas found in the list,
2357 -- starting with pragma First_Prag. Each instantiated pragma is added
2358 -- to list L.
2359
2360 -------------------------
2361 -- Instantiate_Pragmas --
2362 -------------------------
2363
2364 procedure Instantiate_Pragmas (First_Prag : Node_Id) is
2365 Inst_Prag : Node_Id;
2366 Prag : Node_Id;
2367
2368 begin
2369 Prag := First_Prag;
2370 while Present (Prag) loop
2371 if Is_Generic_Contract_Pragma (Prag) then
2372 Inst_Prag :=
2373 Copy_Generic_Node (Prag, Empty, Instantiating => True);
2374
2375 Set_Analyzed (Inst_Prag, False);
2376 Append_To (L, Inst_Prag);
2377 end if;
2378
2379 Prag := Next_Pragma (Prag);
2380 end loop;
2381 end Instantiate_Pragmas;
2382
2383 -- Local variables
2384
2385 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2386
2387 -- Start of processing for Instantiate_Subprogram_Contract
2388
2389 begin
2390 if Present (Items) then
2391 Instantiate_Pragmas (Pre_Post_Conditions (Items));
2392 Instantiate_Pragmas (Contract_Test_Cases (Items));
2393 Instantiate_Pragmas (Classifications (Items));
2394 end if;
2395 end Instantiate_Subprogram_Contract;
2396
2397 ----------------------------------------
2398 -- Save_Global_References_In_Contract --
2399 ----------------------------------------
2400
2401 procedure Save_Global_References_In_Contract
2402 (Templ : Node_Id;
2403 Gen_Id : Entity_Id)
2404 is
2405 procedure Save_Global_References_In_List (First_Prag : Node_Id);
2406 -- Save all global references in contract-related source pragmas found
2407 -- in the list, starting with pragma First_Prag.
2408
2409 ------------------------------------
2410 -- Save_Global_References_In_List --
2411 ------------------------------------
2412
2413 procedure Save_Global_References_In_List (First_Prag : Node_Id) is
2414 Prag : Node_Id;
2415
2416 begin
2417 Prag := First_Prag;
2418 while Present (Prag) loop
2419 if Is_Generic_Contract_Pragma (Prag) then
2420 Save_Global_References (Prag);
2421 end if;
2422
2423 Prag := Next_Pragma (Prag);
2424 end loop;
2425 end Save_Global_References_In_List;
2426
2427 -- Local variables
2428
2429 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2430
2431 -- Start of processing for Save_Global_References_In_Contract
2432
2433 begin
2434 -- The entity of the analyzed generic copy must be on the scope stack
2435 -- to ensure proper detection of global references.
2436
2437 Push_Scope (Gen_Id);
2438
2439 if Permits_Aspect_Specifications (Templ)
2440 and then Has_Aspects (Templ)
2441 then
2442 Save_Global_References_In_Aspects (Templ);
2443 end if;
2444
2445 if Present (Items) then
2446 Save_Global_References_In_List (Pre_Post_Conditions (Items));
2447 Save_Global_References_In_List (Contract_Test_Cases (Items));
2448 Save_Global_References_In_List (Classifications (Items));
2449 end if;
2450
2451 Pop_Scope;
2452 end Save_Global_References_In_Contract;
2453
2454 end Contracts;