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