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