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