contracts.adb (Analyze_Contracts): For a type declaration, analyze an iterable aspect...
[official-gcc.git] / gcc / ada / contracts.adb
blobe26b28d832c8b8e0ff6ea2408449c9b29df68463
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 ------------------------------------------------------------------------------
26 with Aspects; use Aspects;
27 with Atree; use Atree;
28 with Einfo; use Einfo;
29 with Elists; use Elists;
30 with Errout; use Errout;
31 with Exp_Prag; use Exp_Prag;
32 with Exp_Tss; use Exp_Tss;
33 with Exp_Util; use Exp_Util;
34 with Namet; use Namet;
35 with Nlists; use Nlists;
36 with Nmake; use Nmake;
37 with Opt; use Opt;
38 with Sem; use Sem;
39 with Sem_Aux; use Sem_Aux;
40 with Sem_Ch6; use Sem_Ch6;
41 with Sem_Ch8; use Sem_Ch8;
42 with Sem_Ch12; use Sem_Ch12;
43 with Sem_Ch13; use Sem_Ch13;
44 with Sem_Disp; use Sem_Disp;
45 with Sem_Prag; use Sem_Prag;
46 with Sem_Util; use Sem_Util;
47 with Sinfo; use Sinfo;
48 with Snames; use Snames;
49 with Stringt; use Stringt;
50 with Tbuild; use Tbuild;
52 package body Contracts is
54 procedure Analyze_Contracts
55 (L : List_Id;
56 Freeze_Nod : Node_Id;
57 Freeze_Id : Entity_Id);
58 -- Subsidiary to the one parameter version of Analyze_Contracts and routine
59 -- Analyze_Previous_Constracts. Analyze the contracts of all constructs in
60 -- the list L. If Freeze_Nod is set, then the analysis stops when the node
61 -- is reached. Freeze_Id is the entity of some related context which caused
62 -- freezing up to node Freeze_Nod.
64 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
65 -- Expand the contracts of a subprogram body and its correspoding spec (if
66 -- any). This routine processes all [refined] pre- and postconditions as
67 -- well as Contract_Cases, invariants and predicates. Body_Id denotes the
68 -- entity of the subprogram body.
70 -----------------------
71 -- Add_Contract_Item --
72 -----------------------
74 procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
75 Items : Node_Id := Contract (Id);
77 procedure Add_Classification;
78 -- Prepend Prag to the list of classifications
80 procedure Add_Contract_Test_Case;
81 -- Prepend Prag to the list of contract and test cases
83 procedure Add_Pre_Post_Condition;
84 -- Prepend Prag to the list of pre- and postconditions
86 ------------------------
87 -- Add_Classification --
88 ------------------------
90 procedure Add_Classification is
91 begin
92 Set_Next_Pragma (Prag, Classifications (Items));
93 Set_Classifications (Items, Prag);
94 end Add_Classification;
96 ----------------------------
97 -- Add_Contract_Test_Case --
98 ----------------------------
100 procedure Add_Contract_Test_Case is
101 begin
102 Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
103 Set_Contract_Test_Cases (Items, Prag);
104 end Add_Contract_Test_Case;
106 ----------------------------
107 -- Add_Pre_Post_Condition --
108 ----------------------------
110 procedure Add_Pre_Post_Condition is
111 begin
112 Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
113 Set_Pre_Post_Conditions (Items, Prag);
114 end Add_Pre_Post_Condition;
116 -- Local variables
118 Prag_Nam : Name_Id;
120 -- Start of processing for Add_Contract_Item
122 begin
123 -- A contract must contain only pragmas
125 pragma Assert (Nkind (Prag) = N_Pragma);
126 Prag_Nam := Pragma_Name (Prag);
128 -- Create a new contract when adding the first item
130 if No (Items) then
131 Items := Make_Contract (Sloc (Id));
132 Set_Contract (Id, Items);
133 end if;
135 -- Constants, the applicable pragmas are:
136 -- Part_Of
138 if Ekind (Id) = E_Constant then
139 if Prag_Nam = Name_Part_Of then
140 Add_Classification;
142 -- The pragma is not a proper contract item
144 else
145 raise Program_Error;
146 end if;
148 -- Entry bodies, the applicable pragmas are:
149 -- Refined_Depends
150 -- Refined_Global
151 -- Refined_Post
153 elsif Is_Entry_Body (Id) then
154 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
155 Add_Classification;
157 elsif Prag_Nam = Name_Refined_Post then
158 Add_Pre_Post_Condition;
160 -- The pragma is not a proper contract item
162 else
163 raise Program_Error;
164 end if;
166 -- Entry or subprogram declarations, the applicable pragmas are:
167 -- Attach_Handler
168 -- Contract_Cases
169 -- Depends
170 -- Extensions_Visible
171 -- Global
172 -- Interrupt_Handler
173 -- Postcondition
174 -- Precondition
175 -- Test_Case
176 -- Volatile_Function
178 elsif Is_Entry_Declaration (Id)
179 or else Ekind_In (Id, E_Function,
180 E_Generic_Function,
181 E_Generic_Procedure,
182 E_Procedure)
183 then
184 if Nam_In (Prag_Nam, Name_Attach_Handler, Name_Interrupt_Handler)
185 and then Ekind_In (Id, E_Generic_Procedure, E_Procedure)
186 then
187 Add_Classification;
189 elsif Nam_In (Prag_Nam, Name_Depends,
190 Name_Extensions_Visible,
191 Name_Global)
192 then
193 Add_Classification;
195 elsif Prag_Nam = Name_Volatile_Function
196 and then Ekind_In (Id, E_Function, E_Generic_Function)
197 then
198 Add_Classification;
200 elsif Nam_In (Prag_Nam, Name_Contract_Cases, Name_Test_Case) then
201 Add_Contract_Test_Case;
203 elsif Nam_In (Prag_Nam, Name_Postcondition, Name_Precondition) then
204 Add_Pre_Post_Condition;
206 -- The pragma is not a proper contract item
208 else
209 raise Program_Error;
210 end if;
212 -- Packages or instantiations, the applicable pragmas are:
213 -- Abstract_States
214 -- Initial_Condition
215 -- Initializes
216 -- Part_Of (instantiation only)
218 elsif Ekind_In (Id, E_Generic_Package, E_Package) then
219 if Nam_In (Prag_Nam, Name_Abstract_State,
220 Name_Initial_Condition,
221 Name_Initializes)
222 then
223 Add_Classification;
225 -- Indicator Part_Of must be associated with a package instantiation
227 elsif Prag_Nam = Name_Part_Of and then Is_Generic_Instance (Id) then
228 Add_Classification;
230 -- The pragma is not a proper contract item
232 else
233 raise Program_Error;
234 end if;
236 -- Package bodies, the applicable pragmas are:
237 -- Refined_States
239 elsif Ekind (Id) = E_Package_Body then
240 if Prag_Nam = Name_Refined_State then
241 Add_Classification;
243 -- The pragma is not a proper contract item
245 else
246 raise Program_Error;
247 end if;
249 -- Protected units, the applicable pragmas are:
250 -- Part_Of
252 elsif Ekind (Id) = E_Protected_Type then
253 if Prag_Nam = Name_Part_Of then
254 Add_Classification;
256 -- The pragma is not a proper contract item
258 else
259 raise Program_Error;
260 end if;
262 -- Subprogram bodies, the applicable pragmas are:
263 -- Postcondition
264 -- Precondition
265 -- Refined_Depends
266 -- Refined_Global
267 -- Refined_Post
269 elsif Ekind (Id) = E_Subprogram_Body then
270 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
271 Add_Classification;
273 elsif Nam_In (Prag_Nam, Name_Postcondition,
274 Name_Precondition,
275 Name_Refined_Post)
276 then
277 Add_Pre_Post_Condition;
279 -- The pragma is not a proper contract item
281 else
282 raise Program_Error;
283 end if;
285 -- Task bodies, the applicable pragmas are:
286 -- Refined_Depends
287 -- Refined_Global
289 elsif Ekind (Id) = E_Task_Body then
290 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
291 Add_Classification;
293 -- The pragma is not a proper contract item
295 else
296 raise Program_Error;
297 end if;
299 -- Task units, the applicable pragmas are:
300 -- Depends
301 -- Global
302 -- Part_Of
304 elsif Ekind (Id) = E_Task_Type then
305 if Nam_In (Prag_Nam, Name_Depends, Name_Global, Name_Part_Of) then
306 Add_Classification;
308 -- The pragma is not a proper contract item
310 else
311 raise Program_Error;
312 end if;
314 -- Variables, the applicable pragmas are:
315 -- Async_Readers
316 -- Async_Writers
317 -- Constant_After_Elaboration
318 -- Depends
319 -- Effective_Reads
320 -- Effective_Writes
321 -- Global
322 -- Part_Of
324 elsif Ekind (Id) = E_Variable then
325 if Nam_In (Prag_Nam, Name_Async_Readers,
326 Name_Async_Writers,
327 Name_Constant_After_Elaboration,
328 Name_Depends,
329 Name_Effective_Reads,
330 Name_Effective_Writes,
331 Name_Global,
332 Name_Part_Of)
333 then
334 Add_Classification;
336 -- The pragma is not a proper contract item
338 else
339 raise Program_Error;
340 end if;
341 end if;
342 end Add_Contract_Item;
344 -----------------------
345 -- Analyze_Contracts --
346 -----------------------
348 procedure Analyze_Contracts (L : List_Id) is
349 begin
350 Analyze_Contracts (L, Freeze_Nod => Empty, Freeze_Id => Empty);
351 end Analyze_Contracts;
353 procedure Analyze_Contracts
354 (L : List_Id;
355 Freeze_Nod : Node_Id;
356 Freeze_Id : Entity_Id)
358 Decl : Node_Id;
360 begin
361 Decl := First (L);
362 while Present (Decl) loop
364 -- The caller requests that the traversal stops at a particular node
365 -- that causes contract "freezing".
367 if Present (Freeze_Nod) and then Decl = Freeze_Nod then
368 exit;
369 end if;
371 -- Entry or subprogram declarations
373 if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
374 N_Entry_Declaration,
375 N_Generic_Subprogram_Declaration,
376 N_Subprogram_Declaration)
377 then
378 Analyze_Entry_Or_Subprogram_Contract
379 (Subp_Id => Defining_Entity (Decl),
380 Freeze_Id => Freeze_Id);
382 -- Entry or subprogram bodies
384 elsif Nkind_In (Decl, N_Entry_Body, N_Subprogram_Body) then
385 Analyze_Entry_Or_Subprogram_Body_Contract (Defining_Entity (Decl));
387 -- Objects
389 elsif Nkind (Decl) = N_Object_Declaration then
390 Analyze_Object_Contract
391 (Obj_Id => Defining_Entity (Decl),
392 Freeze_Id => Freeze_Id);
394 -- Protected untis
396 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
397 N_Single_Protected_Declaration)
398 then
399 Analyze_Protected_Contract (Defining_Entity (Decl));
401 -- Subprogram body stubs
403 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
404 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
406 -- Task units
408 elsif Nkind_In (Decl, N_Single_Task_Declaration,
409 N_Task_Type_Declaration)
410 then
411 Analyze_Task_Contract (Defining_Entity (Decl));
413 -- For type declarations, we need to do the pre-analysis of
414 -- Iterable aspect specifications.
415 -- Other type aspects need to be resolved here???
417 elsif Nkind (Decl) = N_Private_Type_Declaration
418 and then Present (Aspect_Specifications (Decl))
419 then
420 declare
421 E : constant Entity_Id := Defining_Identifier (Decl);
422 It : constant Node_Id := Find_Aspect (E, Aspect_Iterable);
423 begin
424 if Present (It) then
425 Validate_Iterable_Aspect (E, It);
426 end if;
427 end;
428 end if;
430 Next (Decl);
431 end loop;
432 end Analyze_Contracts;
434 -----------------------------------------------
435 -- Analyze_Entry_Or_Subprogram_Body_Contract --
436 -----------------------------------------------
438 procedure Analyze_Entry_Or_Subprogram_Body_Contract (Body_Id : Entity_Id) is
439 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
440 Items : constant Node_Id := Contract (Body_Id);
441 Spec_Id : constant Entity_Id := Unique_Defining_Entity (Body_Decl);
442 Mode : SPARK_Mode_Type;
444 begin
445 -- When a subprogram body declaration is illegal, its defining entity is
446 -- left unanalyzed. There is nothing left to do in this case because the
447 -- body lacks a contract, or even a proper Ekind.
449 if Ekind (Body_Id) = E_Void then
450 return;
452 -- Do not analyze a contract multiple times
454 elsif Present (Items) then
455 if Analyzed (Items) then
456 return;
457 else
458 Set_Analyzed (Items);
459 end if;
460 end if;
462 -- Due to the timing of contract analysis, delayed pragmas may be
463 -- subject to the wrong SPARK_Mode, usually that of the enclosing
464 -- context. To remedy this, restore the original SPARK_Mode of the
465 -- related subprogram body.
467 Save_SPARK_Mode_And_Set (Body_Id, Mode);
469 -- Ensure that the contract cases or postconditions mention 'Result or
470 -- define a post-state.
472 Check_Result_And_Post_State (Body_Id);
474 -- A stand-alone nonvolatile function body cannot have an effectively
475 -- volatile formal parameter or return type (SPARK RM 7.1.3(9)). This
476 -- check is relevant only when SPARK_Mode is on, as it is not a standard
477 -- legality rule. The check is performed here because Volatile_Function
478 -- is processed after the analysis of the related subprogram body.
480 if SPARK_Mode = On
481 and then Ekind_In (Body_Id, E_Function, E_Generic_Function)
482 and then not Is_Volatile_Function (Body_Id)
483 then
484 Check_Nonvolatile_Function_Profile (Body_Id);
485 end if;
487 -- Restore the SPARK_Mode of the enclosing context after all delayed
488 -- pragmas have been analyzed.
490 Restore_SPARK_Mode (Mode);
492 -- Capture all global references in a generic subprogram body now that
493 -- the contract has been analyzed.
495 if Is_Generic_Declaration_Or_Body (Body_Decl) then
496 Save_Global_References_In_Contract
497 (Templ => Original_Node (Body_Decl),
498 Gen_Id => Spec_Id);
499 end if;
501 -- Deal with preconditions, [refined] postconditions, Contract_Cases,
502 -- invariants and predicates associated with body and its spec. Do not
503 -- expand the contract of subprogram body stubs.
505 if Nkind (Body_Decl) = N_Subprogram_Body then
506 Expand_Subprogram_Contract (Body_Id);
507 end if;
508 end Analyze_Entry_Or_Subprogram_Body_Contract;
510 ------------------------------------------
511 -- Analyze_Entry_Or_Subprogram_Contract --
512 ------------------------------------------
514 procedure Analyze_Entry_Or_Subprogram_Contract
515 (Subp_Id : Entity_Id;
516 Freeze_Id : Entity_Id := Empty)
518 Items : constant Node_Id := Contract (Subp_Id);
519 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
521 Skip_Assert_Exprs : constant Boolean :=
522 Ekind_In (Subp_Id, E_Entry, E_Entry_Family)
523 and then not ASIS_Mode
524 and then not GNATprove_Mode;
526 Depends : Node_Id := Empty;
527 Global : Node_Id := Empty;
528 Mode : SPARK_Mode_Type;
529 Prag : Node_Id;
530 Prag_Nam : Name_Id;
532 begin
533 -- Do not analyze a contract multiple times
535 if Present (Items) then
536 if Analyzed (Items) then
537 return;
538 else
539 Set_Analyzed (Items);
540 end if;
541 end if;
543 -- Due to the timing of contract analysis, delayed pragmas may be
544 -- subject to the wrong SPARK_Mode, usually that of the enclosing
545 -- context. To remedy this, restore the original SPARK_Mode of the
546 -- related subprogram body.
548 Save_SPARK_Mode_And_Set (Subp_Id, Mode);
550 -- All subprograms carry a contract, but for some it is not significant
551 -- and should not be processed.
553 if not Has_Significant_Contract (Subp_Id) then
554 null;
556 elsif Present (Items) then
558 -- Do not analyze the pre/postconditions of an entry declaration
559 -- unless annotating the original tree for ASIS or GNATprove. The
560 -- real analysis occurs when the pre/postconditons are relocated to
561 -- the contract wrapper procedure (see Build_Contract_Wrapper).
563 if Skip_Assert_Exprs then
564 null;
566 -- Otherwise analyze the pre/postconditions
568 else
569 Prag := Pre_Post_Conditions (Items);
570 while Present (Prag) loop
571 Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
572 Prag := Next_Pragma (Prag);
573 end loop;
574 end if;
576 -- Analyze contract-cases and test-cases
578 Prag := Contract_Test_Cases (Items);
579 while Present (Prag) loop
580 Prag_Nam := Pragma_Name (Prag);
582 if Prag_Nam = Name_Contract_Cases then
584 -- Do not analyze the contract cases of an entry declaration
585 -- unless annotating the original tree for ASIS or GNATprove.
586 -- The real analysis occurs when the contract cases are moved
587 -- to the contract wrapper procedure (Build_Contract_Wrapper).
589 if Skip_Assert_Exprs then
590 null;
592 -- Otherwise analyze the contract cases
594 else
595 Analyze_Contract_Cases_In_Decl_Part (Prag, Freeze_Id);
596 end if;
597 else
598 pragma Assert (Prag_Nam = Name_Test_Case);
599 Analyze_Test_Case_In_Decl_Part (Prag);
600 end if;
602 Prag := Next_Pragma (Prag);
603 end loop;
605 -- Analyze classification pragmas
607 Prag := Classifications (Items);
608 while Present (Prag) loop
609 Prag_Nam := Pragma_Name (Prag);
611 if Prag_Nam = Name_Depends then
612 Depends := Prag;
614 elsif Prag_Nam = Name_Global then
615 Global := Prag;
616 end if;
618 Prag := Next_Pragma (Prag);
619 end loop;
621 -- Analyze Global first, as Depends may mention items classified in
622 -- the global categorization.
624 if Present (Global) then
625 Analyze_Global_In_Decl_Part (Global);
626 end if;
628 -- Depends must be analyzed after Global in order to see the modes of
629 -- all global items.
631 if Present (Depends) then
632 Analyze_Depends_In_Decl_Part (Depends);
633 end if;
635 -- Ensure that the contract cases or postconditions mention 'Result
636 -- or define a post-state.
638 Check_Result_And_Post_State (Subp_Id);
639 end if;
641 -- A nonvolatile function cannot have an effectively volatile formal
642 -- parameter or return type (SPARK RM 7.1.3(9)). This check is relevant
643 -- only when SPARK_Mode is on, as it is not a standard legality rule.
644 -- The check is performed here because pragma Volatile_Function is
645 -- processed after the analysis of the related subprogram declaration.
647 if SPARK_Mode = On
648 and then Ekind_In (Subp_Id, E_Function, E_Generic_Function)
649 and then not Is_Volatile_Function (Subp_Id)
650 then
651 Check_Nonvolatile_Function_Profile (Subp_Id);
652 end if;
654 -- Restore the SPARK_Mode of the enclosing context after all delayed
655 -- pragmas have been analyzed.
657 Restore_SPARK_Mode (Mode);
659 -- Capture all global references in a generic subprogram now that the
660 -- contract has been analyzed.
662 if Is_Generic_Declaration_Or_Body (Subp_Decl) then
663 Save_Global_References_In_Contract
664 (Templ => Original_Node (Subp_Decl),
665 Gen_Id => Subp_Id);
666 end if;
667 end Analyze_Entry_Or_Subprogram_Contract;
669 -----------------------------
670 -- Analyze_Object_Contract --
671 -----------------------------
673 procedure Analyze_Object_Contract
674 (Obj_Id : Entity_Id;
675 Freeze_Id : Entity_Id := Empty)
677 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
678 AR_Val : Boolean := False;
679 AW_Val : Boolean := False;
680 ER_Val : Boolean := False;
681 EW_Val : Boolean := False;
682 Items : Node_Id;
683 Mode : SPARK_Mode_Type;
684 Prag : Node_Id;
685 Ref_Elmt : Elmt_Id;
686 Restore_Mode : Boolean := False;
687 Seen : Boolean := False;
689 begin
690 -- The loop parameter in an element iterator over a formal container
691 -- is declared with an object declaration, but no contracts apply.
693 if Ekind (Obj_Id) = E_Loop_Parameter then
694 return;
695 end if;
697 -- Do not analyze a contract multiple times
699 Items := Contract (Obj_Id);
701 if Present (Items) then
702 if Analyzed (Items) then
703 return;
704 else
705 Set_Analyzed (Items);
706 end if;
707 end if;
709 -- The anonymous object created for a single concurrent type inherits
710 -- the SPARK_Mode from the type. Due to the timing of contract analysis,
711 -- delayed pragmas may be subject to the wrong SPARK_Mode, usually that
712 -- of the enclosing context. To remedy this, restore the original mode
713 -- of the related anonymous object.
715 if Is_Single_Concurrent_Object (Obj_Id)
716 and then Present (SPARK_Pragma (Obj_Id))
717 then
718 Restore_Mode := True;
719 Save_SPARK_Mode_And_Set (Obj_Id, Mode);
720 end if;
722 -- Constant-related checks
724 if Ekind (Obj_Id) = E_Constant then
726 -- Analyze indicator Part_Of
728 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
730 -- Check whether the lack of indicator Part_Of agrees with the
731 -- placement of the constant with respect to the state space.
733 if No (Prag) then
734 Check_Missing_Part_Of (Obj_Id);
735 end if;
737 -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
738 -- This check is relevant only when SPARK_Mode is on, as it is not
739 -- a standard Ada legality rule. Internally-generated constants that
740 -- map generic formals to actuals in instantiations are allowed to
741 -- be volatile.
743 if SPARK_Mode = On
744 and then Comes_From_Source (Obj_Id)
745 and then Is_Effectively_Volatile (Obj_Id)
746 and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
747 then
748 Error_Msg_N ("constant cannot be volatile", Obj_Id);
749 end if;
751 -- Variable-related checks
753 else pragma Assert (Ekind (Obj_Id) = E_Variable);
755 -- Analyze all external properties
757 Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
759 if Present (Prag) then
760 Analyze_External_Property_In_Decl_Part (Prag, AR_Val);
761 Seen := True;
762 end if;
764 Prag := Get_Pragma (Obj_Id, Pragma_Async_Writers);
766 if Present (Prag) then
767 Analyze_External_Property_In_Decl_Part (Prag, AW_Val);
768 Seen := True;
769 end if;
771 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Reads);
773 if Present (Prag) then
774 Analyze_External_Property_In_Decl_Part (Prag, ER_Val);
775 Seen := True;
776 end if;
778 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Writes);
780 if Present (Prag) then
781 Analyze_External_Property_In_Decl_Part (Prag, EW_Val);
782 Seen := True;
783 end if;
785 -- Verify the mutual interaction of the various external properties
787 if Seen then
788 Check_External_Properties (Obj_Id, AR_Val, AW_Val, ER_Val, EW_Val);
789 end if;
791 -- The anonymous object created for a single concurrent type carries
792 -- pragmas Depends and Globat of the type.
794 if Is_Single_Concurrent_Object (Obj_Id) then
796 -- Analyze Global first, as Depends may mention items classified
797 -- in the global categorization.
799 Prag := Get_Pragma (Obj_Id, Pragma_Global);
801 if Present (Prag) then
802 Analyze_Global_In_Decl_Part (Prag);
803 end if;
805 -- Depends must be analyzed after Global in order to see the modes
806 -- of all global items.
808 Prag := Get_Pragma (Obj_Id, Pragma_Depends);
810 if Present (Prag) then
811 Analyze_Depends_In_Decl_Part (Prag);
812 end if;
813 end if;
815 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
817 -- Analyze indicator Part_Of
819 if Present (Prag) then
820 Analyze_Part_Of_In_Decl_Part (Prag, Freeze_Id);
822 -- The variable is a constituent of a single protected/task type
823 -- and behaves as a component of the type. Verify that references
824 -- to the variable occur within the definition or body of the type
825 -- (SPARK RM 9.3).
827 if Present (Encapsulating_State (Obj_Id))
828 and then Is_Single_Concurrent_Object
829 (Encapsulating_State (Obj_Id))
830 and then Present (Part_Of_References (Obj_Id))
831 then
832 Ref_Elmt := First_Elmt (Part_Of_References (Obj_Id));
833 while Present (Ref_Elmt) loop
834 Check_Part_Of_Reference (Obj_Id, Node (Ref_Elmt));
835 Next_Elmt (Ref_Elmt);
836 end loop;
837 end if;
839 -- Otherwise check whether the lack of indicator Part_Of agrees with
840 -- the placement of the variable with respect to the state space.
842 else
843 Check_Missing_Part_Of (Obj_Id);
844 end if;
846 -- The following checks are relevant only when SPARK_Mode is on, as
847 -- they are not standard Ada legality rules. Internally generated
848 -- temporaries are ignored.
850 if SPARK_Mode = On and then Comes_From_Source (Obj_Id) then
851 if Is_Effectively_Volatile (Obj_Id) then
853 -- The declaration of an effectively volatile object must
854 -- appear at the library level (SPARK RM 7.1.3(3), C.6(6)).
856 if not Is_Library_Level_Entity (Obj_Id) then
857 Error_Msg_N
858 ("volatile variable & must be declared at library level",
859 Obj_Id);
861 -- An object of a discriminated type cannot be effectively
862 -- volatile except for protected objects (SPARK RM 7.1.3(5)).
864 elsif Has_Discriminants (Obj_Typ)
865 and then not Is_Protected_Type (Obj_Typ)
866 then
867 Error_Msg_N
868 ("discriminated object & cannot be volatile", Obj_Id);
870 -- An object of a tagged type cannot be effectively volatile
871 -- (SPARK RM C.6(5)).
873 elsif Is_Tagged_Type (Obj_Typ) then
874 Error_Msg_N ("tagged object & cannot be volatile", Obj_Id);
875 end if;
877 -- The object is not effectively volatile
879 else
880 -- A non-effectively volatile object cannot have effectively
881 -- volatile components (SPARK RM 7.1.3(6)).
883 if not Is_Effectively_Volatile (Obj_Id)
884 and then Has_Volatile_Component (Obj_Typ)
885 then
886 Error_Msg_N
887 ("non-volatile object & cannot have volatile components",
888 Obj_Id);
889 end if;
890 end if;
891 end if;
892 end if;
894 -- Common checks
896 if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
898 -- A Ghost object cannot be of a type that yields a synchronized
899 -- object (SPARK RM 6.9(19)).
901 if Yields_Synchronized_Object (Obj_Typ) then
902 Error_Msg_N ("ghost object & cannot be synchronized", Obj_Id);
904 -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and
905 -- SPARK RM 6.9(19)).
907 elsif Is_Effectively_Volatile (Obj_Id) then
908 Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
910 -- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)).
911 -- One exception to this is the object that represents the dispatch
912 -- table of a Ghost tagged type, as the symbol needs to be exported.
914 elsif Is_Exported (Obj_Id) then
915 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
917 elsif Is_Imported (Obj_Id) then
918 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
919 end if;
920 end if;
922 -- Restore the SPARK_Mode of the enclosing context after all delayed
923 -- pragmas have been analyzed.
925 if Restore_Mode then
926 Restore_SPARK_Mode (Mode);
927 end if;
928 end Analyze_Object_Contract;
930 -----------------------------------
931 -- Analyze_Package_Body_Contract --
932 -----------------------------------
934 procedure Analyze_Package_Body_Contract
935 (Body_Id : Entity_Id;
936 Freeze_Id : Entity_Id := Empty)
938 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
939 Items : constant Node_Id := Contract (Body_Id);
940 Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
941 Mode : SPARK_Mode_Type;
942 Ref_State : Node_Id;
944 begin
945 -- Do not analyze a contract multiple times
947 if Present (Items) then
948 if Analyzed (Items) then
949 return;
950 else
951 Set_Analyzed (Items);
952 end if;
953 end if;
955 -- Due to the timing of contract analysis, delayed pragmas may be
956 -- subject to the wrong SPARK_Mode, usually that of the enclosing
957 -- context. To remedy this, restore the original SPARK_Mode of the
958 -- related package body.
960 Save_SPARK_Mode_And_Set (Body_Id, Mode);
962 Ref_State := Get_Pragma (Body_Id, Pragma_Refined_State);
964 -- The analysis of pragma Refined_State detects whether the spec has
965 -- abstract states available for refinement.
967 if Present (Ref_State) then
968 Analyze_Refined_State_In_Decl_Part (Ref_State, Freeze_Id);
969 end if;
971 -- Restore the SPARK_Mode of the enclosing context after all delayed
972 -- pragmas have been analyzed.
974 Restore_SPARK_Mode (Mode);
976 -- Capture all global references in a generic package body now that the
977 -- contract has been analyzed.
979 if Is_Generic_Declaration_Or_Body (Body_Decl) then
980 Save_Global_References_In_Contract
981 (Templ => Original_Node (Body_Decl),
982 Gen_Id => Spec_Id);
983 end if;
984 end Analyze_Package_Body_Contract;
986 ------------------------------
987 -- Analyze_Package_Contract --
988 ------------------------------
990 procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
991 Items : constant Node_Id := Contract (Pack_Id);
992 Pack_Decl : constant Node_Id := Unit_Declaration_Node (Pack_Id);
993 Init : Node_Id := Empty;
994 Init_Cond : Node_Id := Empty;
995 Mode : SPARK_Mode_Type;
996 Prag : Node_Id;
997 Prag_Nam : Name_Id;
999 begin
1000 -- Do not analyze a contract multiple times
1002 if Present (Items) then
1003 if Analyzed (Items) then
1004 return;
1005 else
1006 Set_Analyzed (Items);
1007 end if;
1008 end if;
1010 -- Due to the timing of contract analysis, delayed pragmas may be
1011 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1012 -- context. To remedy this, restore the original SPARK_Mode of the
1013 -- related package.
1015 Save_SPARK_Mode_And_Set (Pack_Id, Mode);
1017 if Present (Items) then
1019 -- Locate and store pragmas Initial_Condition and Initializes, since
1020 -- their order of analysis matters.
1022 Prag := Classifications (Items);
1023 while Present (Prag) loop
1024 Prag_Nam := Pragma_Name (Prag);
1026 if Prag_Nam = Name_Initial_Condition then
1027 Init_Cond := Prag;
1029 elsif Prag_Nam = Name_Initializes then
1030 Init := Prag;
1031 end if;
1033 Prag := Next_Pragma (Prag);
1034 end loop;
1036 -- Analyze the initialization-related pragmas. Initializes must come
1037 -- before Initial_Condition due to item dependencies.
1039 if Present (Init) then
1040 Analyze_Initializes_In_Decl_Part (Init);
1041 end if;
1043 if Present (Init_Cond) then
1044 Analyze_Initial_Condition_In_Decl_Part (Init_Cond);
1045 end if;
1046 end if;
1048 -- Check whether the lack of indicator Part_Of agrees with the placement
1049 -- of the package instantiation with respect to the state space.
1051 if Is_Generic_Instance (Pack_Id) then
1052 Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
1054 if No (Prag) then
1055 Check_Missing_Part_Of (Pack_Id);
1056 end if;
1057 end if;
1059 -- Restore the SPARK_Mode of the enclosing context after all delayed
1060 -- pragmas have been analyzed.
1062 Restore_SPARK_Mode (Mode);
1064 -- Capture all global references in a generic package now that the
1065 -- contract has been analyzed.
1067 if Is_Generic_Declaration_Or_Body (Pack_Decl) then
1068 Save_Global_References_In_Contract
1069 (Templ => Original_Node (Pack_Decl),
1070 Gen_Id => Pack_Id);
1071 end if;
1072 end Analyze_Package_Contract;
1074 --------------------------------
1075 -- Analyze_Previous_Contracts --
1076 --------------------------------
1078 procedure Analyze_Previous_Contracts (Body_Decl : Node_Id) is
1079 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
1080 Par : Node_Id;
1082 begin
1083 -- A body that is in the process of being inlined appears from source,
1084 -- but carries name _parent. Such a body does not cause "freezing" of
1085 -- contracts.
1087 if Chars (Body_Id) = Name_uParent then
1088 return;
1089 end if;
1091 -- Climb the parent chain looking for an enclosing package body. Do not
1092 -- use the scope stack, as a body uses the entity of its corresponding
1093 -- spec.
1095 Par := Parent (Body_Decl);
1096 while Present (Par) loop
1097 if Nkind (Par) = N_Package_Body then
1098 Analyze_Package_Body_Contract
1099 (Body_Id => Defining_Entity (Par),
1100 Freeze_Id => Defining_Entity (Body_Decl));
1102 exit;
1103 end if;
1105 Par := Parent (Par);
1106 end loop;
1108 -- Analyze the contracts of all eligible construct up to the body which
1109 -- caused the "freezing".
1111 if Is_List_Member (Body_Decl) then
1112 Analyze_Contracts
1113 (L => List_Containing (Body_Decl),
1114 Freeze_Nod => Body_Decl,
1115 Freeze_Id => Body_Id);
1116 end if;
1117 end Analyze_Previous_Contracts;
1119 --------------------------------
1120 -- Analyze_Protected_Contract --
1121 --------------------------------
1123 procedure Analyze_Protected_Contract (Prot_Id : Entity_Id) is
1124 Items : constant Node_Id := Contract (Prot_Id);
1126 begin
1127 -- Do not analyze a contract multiple times
1129 if Present (Items) then
1130 if Analyzed (Items) then
1131 return;
1132 else
1133 Set_Analyzed (Items);
1134 end if;
1135 end if;
1136 end Analyze_Protected_Contract;
1138 -------------------------------------------
1139 -- Analyze_Subprogram_Body_Stub_Contract --
1140 -------------------------------------------
1142 procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id) is
1143 Stub_Decl : constant Node_Id := Parent (Parent (Stub_Id));
1144 Spec_Id : constant Entity_Id := Corresponding_Spec_Of_Stub (Stub_Decl);
1146 begin
1147 -- A subprogram body stub may act as its own spec or as the completion
1148 -- of a previous declaration. Depending on the context, the contract of
1149 -- the stub may contain two sets of pragmas.
1151 -- The stub is a completion, the applicable pragmas are:
1152 -- Refined_Depends
1153 -- Refined_Global
1155 if Present (Spec_Id) then
1156 Analyze_Entry_Or_Subprogram_Body_Contract (Stub_Id);
1158 -- The stub acts as its own spec, the applicable pragmas are:
1159 -- Contract_Cases
1160 -- Depends
1161 -- Global
1162 -- Postcondition
1163 -- Precondition
1164 -- Test_Case
1166 else
1167 Analyze_Entry_Or_Subprogram_Contract (Stub_Id);
1168 end if;
1169 end Analyze_Subprogram_Body_Stub_Contract;
1171 ---------------------------
1172 -- Analyze_Task_Contract --
1173 ---------------------------
1175 procedure Analyze_Task_Contract (Task_Id : Entity_Id) is
1176 Items : constant Node_Id := Contract (Task_Id);
1177 Mode : SPARK_Mode_Type;
1178 Prag : Node_Id;
1180 begin
1181 -- Do not analyze a contract multiple times
1183 if Present (Items) then
1184 if Analyzed (Items) then
1185 return;
1186 else
1187 Set_Analyzed (Items);
1188 end if;
1189 end if;
1191 -- Due to the timing of contract analysis, delayed pragmas may be
1192 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1193 -- context. To remedy this, restore the original SPARK_Mode of the
1194 -- related task unit.
1196 Save_SPARK_Mode_And_Set (Task_Id, Mode);
1198 -- Analyze Global first, as Depends may mention items classified in the
1199 -- global categorization.
1201 Prag := Get_Pragma (Task_Id, Pragma_Global);
1203 if Present (Prag) then
1204 Analyze_Global_In_Decl_Part (Prag);
1205 end if;
1207 -- Depends must be analyzed after Global in order to see the modes of
1208 -- all global items.
1210 Prag := Get_Pragma (Task_Id, Pragma_Depends);
1212 if Present (Prag) then
1213 Analyze_Depends_In_Decl_Part (Prag);
1214 end if;
1216 -- Restore the SPARK_Mode of the enclosing context after all delayed
1217 -- pragmas have been analyzed.
1219 Restore_SPARK_Mode (Mode);
1220 end Analyze_Task_Contract;
1222 -----------------------------
1223 -- Create_Generic_Contract --
1224 -----------------------------
1226 procedure Create_Generic_Contract (Unit : Node_Id) is
1227 Templ : constant Node_Id := Original_Node (Unit);
1228 Templ_Id : constant Entity_Id := Defining_Entity (Templ);
1230 procedure Add_Generic_Contract_Pragma (Prag : Node_Id);
1231 -- Add a single contract-related source pragma Prag to the contract of
1232 -- generic template Templ_Id.
1234 ---------------------------------
1235 -- Add_Generic_Contract_Pragma --
1236 ---------------------------------
1238 procedure Add_Generic_Contract_Pragma (Prag : Node_Id) is
1239 Prag_Templ : Node_Id;
1241 begin
1242 -- Mark the pragma to prevent the premature capture of global
1243 -- references when capturing global references of the context
1244 -- (see Save_References_In_Pragma).
1246 Set_Is_Generic_Contract_Pragma (Prag);
1248 -- Pragmas that apply to a generic subprogram declaration are not
1249 -- part of the semantic structure of the generic template:
1251 -- generic
1252 -- procedure Example (Formal : Integer);
1253 -- pragma Precondition (Formal > 0);
1255 -- Create a generic template for such pragmas and link the template
1256 -- of the pragma with the generic template.
1258 if Nkind (Templ) = N_Generic_Subprogram_Declaration then
1259 Rewrite
1260 (Prag, Copy_Generic_Node (Prag, Empty, Instantiating => False));
1261 Prag_Templ := Original_Node (Prag);
1263 Set_Is_Generic_Contract_Pragma (Prag_Templ);
1264 Add_Contract_Item (Prag_Templ, Templ_Id);
1266 -- Otherwise link the pragma with the generic template
1268 else
1269 Add_Contract_Item (Prag, Templ_Id);
1270 end if;
1271 end Add_Generic_Contract_Pragma;
1273 -- Local variables
1275 Context : constant Node_Id := Parent (Unit);
1276 Decl : Node_Id := Empty;
1278 -- Start of processing for Create_Generic_Contract
1280 begin
1281 -- A generic package declaration carries contract-related source pragmas
1282 -- in its visible declarations.
1284 if Nkind (Templ) = N_Generic_Package_Declaration then
1285 Set_Ekind (Templ_Id, E_Generic_Package);
1287 if Present (Visible_Declarations (Specification (Templ))) then
1288 Decl := First (Visible_Declarations (Specification (Templ)));
1289 end if;
1291 -- A generic package body carries contract-related source pragmas in its
1292 -- declarations.
1294 elsif Nkind (Templ) = N_Package_Body then
1295 Set_Ekind (Templ_Id, E_Package_Body);
1297 if Present (Declarations (Templ)) then
1298 Decl := First (Declarations (Templ));
1299 end if;
1301 -- Generic subprogram declaration
1303 elsif Nkind (Templ) = N_Generic_Subprogram_Declaration then
1304 if Nkind (Specification (Templ)) = N_Function_Specification then
1305 Set_Ekind (Templ_Id, E_Generic_Function);
1306 else
1307 Set_Ekind (Templ_Id, E_Generic_Procedure);
1308 end if;
1310 -- When the generic subprogram acts as a compilation unit, inspect
1311 -- the Pragmas_After list for contract-related source pragmas.
1313 if Nkind (Context) = N_Compilation_Unit then
1314 if Present (Aux_Decls_Node (Context))
1315 and then Present (Pragmas_After (Aux_Decls_Node (Context)))
1316 then
1317 Decl := First (Pragmas_After (Aux_Decls_Node (Context)));
1318 end if;
1320 -- Otherwise inspect the successive declarations for contract-related
1321 -- source pragmas.
1323 else
1324 Decl := Next (Unit);
1325 end if;
1327 -- A generic subprogram body carries contract-related source pragmas in
1328 -- its declarations.
1330 elsif Nkind (Templ) = N_Subprogram_Body then
1331 Set_Ekind (Templ_Id, E_Subprogram_Body);
1333 if Present (Declarations (Templ)) then
1334 Decl := First (Declarations (Templ));
1335 end if;
1336 end if;
1338 -- Inspect the relevant declarations looking for contract-related source
1339 -- pragmas and add them to the contract of the generic unit.
1341 while Present (Decl) loop
1342 if Comes_From_Source (Decl) then
1343 if Nkind (Decl) = N_Pragma then
1345 -- The source pragma is a contract annotation
1347 if Is_Contract_Annotation (Decl) then
1348 Add_Generic_Contract_Pragma (Decl);
1349 end if;
1351 -- The region where a contract-related source pragma may appear
1352 -- ends with the first source non-pragma declaration or statement.
1354 else
1355 exit;
1356 end if;
1357 end if;
1359 Next (Decl);
1360 end loop;
1361 end Create_Generic_Contract;
1363 --------------------------------
1364 -- Expand_Subprogram_Contract --
1365 --------------------------------
1367 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id) is
1368 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
1369 Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
1371 procedure Add_Invariant_And_Predicate_Checks
1372 (Subp_Id : Entity_Id;
1373 Stmts : in out List_Id;
1374 Result : out Node_Id);
1375 -- Process the result of function Subp_Id (if applicable) and all its
1376 -- formals. Add invariant and predicate checks where applicable. The
1377 -- routine appends all the checks to list Stmts. If Subp_Id denotes a
1378 -- function, Result contains the entity of parameter _Result, to be
1379 -- used in the creation of procedure _Postconditions.
1381 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
1382 -- Append a node to a list. If there is no list, create a new one. When
1383 -- the item denotes a pragma, it is added to the list only when it is
1384 -- enabled.
1386 procedure Build_Postconditions_Procedure
1387 (Subp_Id : Entity_Id;
1388 Stmts : List_Id;
1389 Result : Entity_Id);
1390 -- Create the body of procedure _Postconditions which handles various
1391 -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
1392 -- of statements to be checked on exit. Parameter Result is the entity
1393 -- of parameter _Result when Subp_Id denotes a function.
1395 procedure Process_Contract_Cases (Stmts : in out List_Id);
1396 -- Process pragma Contract_Cases. This routine prepends items to the
1397 -- body declarations and appends items to list Stmts.
1399 procedure Process_Postconditions (Stmts : in out List_Id);
1400 -- Collect all [inherited] spec and body postconditions and accumulate
1401 -- their pragma Check equivalents in list Stmts.
1403 procedure Process_Preconditions;
1404 -- Collect all [inherited] spec and body preconditions and prepend their
1405 -- pragma Check equivalents to the declarations of the body.
1407 ----------------------------------------
1408 -- Add_Invariant_And_Predicate_Checks --
1409 ----------------------------------------
1411 procedure Add_Invariant_And_Predicate_Checks
1412 (Subp_Id : Entity_Id;
1413 Stmts : in out List_Id;
1414 Result : out Node_Id)
1416 procedure Add_Invariant_Access_Checks (Id : Entity_Id);
1417 -- Id denotes the return value of a function or a formal parameter.
1418 -- Add an invariant check if the type of Id is access to a type with
1419 -- invariants. The routine appends the generated code to Stmts.
1421 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
1422 -- Determine whether type Typ can benefit from invariant checks. To
1423 -- qualify, the type must have a non-null invariant procedure and
1424 -- subprogram Subp_Id must appear visible from the point of view of
1425 -- the type.
1427 ---------------------------------
1428 -- Add_Invariant_Access_Checks --
1429 ---------------------------------
1431 procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
1432 Loc : constant Source_Ptr := Sloc (Body_Decl);
1433 Ref : Node_Id;
1434 Typ : Entity_Id;
1436 begin
1437 Typ := Etype (Id);
1439 if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
1440 Typ := Designated_Type (Typ);
1442 if Invariant_Checks_OK (Typ) then
1443 Ref :=
1444 Make_Explicit_Dereference (Loc,
1445 Prefix => New_Occurrence_Of (Id, Loc));
1446 Set_Etype (Ref, Typ);
1448 -- Generate:
1449 -- if <Id> /= null then
1450 -- <invariant_call (<Ref>)>
1451 -- end if;
1453 Append_Enabled_Item
1454 (Item =>
1455 Make_If_Statement (Loc,
1456 Condition =>
1457 Make_Op_Ne (Loc,
1458 Left_Opnd => New_Occurrence_Of (Id, Loc),
1459 Right_Opnd => Make_Null (Loc)),
1460 Then_Statements => New_List (
1461 Make_Invariant_Call (Ref))),
1462 List => Stmts);
1463 end if;
1464 end if;
1465 end Add_Invariant_Access_Checks;
1467 -------------------------
1468 -- Invariant_Checks_OK --
1469 -------------------------
1471 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
1472 function Has_Public_Visibility_Of_Subprogram return Boolean;
1473 -- Determine whether type Typ has public visibility of subprogram
1474 -- Subp_Id.
1476 -----------------------------------------
1477 -- Has_Public_Visibility_Of_Subprogram --
1478 -----------------------------------------
1480 function Has_Public_Visibility_Of_Subprogram return Boolean is
1481 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
1483 begin
1484 -- An Initialization procedure must be considered visible even
1485 -- though it is internally generated.
1487 if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
1488 return True;
1490 elsif Ekind (Scope (Typ)) /= E_Package then
1491 return False;
1493 -- Internally generated code is never publicly visible except
1494 -- for a subprogram that is the implementation of an expression
1495 -- function. In that case the visibility is determined by the
1496 -- last check.
1498 elsif not Comes_From_Source (Subp_Decl)
1499 and then
1500 (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
1501 or else not
1502 Comes_From_Source (Defining_Entity (Subp_Decl)))
1503 then
1504 return False;
1506 -- Determine whether the subprogram is declared in the visible
1507 -- declarations of the package containing the type.
1509 else
1510 return List_Containing (Subp_Decl) =
1511 Visible_Declarations
1512 (Specification (Unit_Declaration_Node (Scope (Typ))));
1513 end if;
1514 end Has_Public_Visibility_Of_Subprogram;
1516 -- Start of processing for Invariant_Checks_OK
1518 begin
1519 return
1520 Has_Invariants (Typ)
1521 and then Present (Invariant_Procedure (Typ))
1522 and then not Has_Null_Body (Invariant_Procedure (Typ))
1523 and then Has_Public_Visibility_Of_Subprogram;
1524 end Invariant_Checks_OK;
1526 -- Local variables
1528 Loc : constant Source_Ptr := Sloc (Body_Decl);
1529 -- Source location of subprogram body contract
1531 Formal : Entity_Id;
1532 Typ : Entity_Id;
1534 -- Start of processing for Add_Invariant_And_Predicate_Checks
1536 begin
1537 Result := Empty;
1539 -- Process the result of a function
1541 if Ekind (Subp_Id) = E_Function then
1542 Typ := Etype (Subp_Id);
1544 -- Generate _Result which is used in procedure _Postconditions to
1545 -- verify the return value.
1547 Result := Make_Defining_Identifier (Loc, Name_uResult);
1548 Set_Etype (Result, Typ);
1550 -- Add an invariant check when the return type has invariants and
1551 -- the related function is visible to the outside.
1553 if Invariant_Checks_OK (Typ) then
1554 Append_Enabled_Item
1555 (Item =>
1556 Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
1557 List => Stmts);
1558 end if;
1560 -- Add an invariant check when the return type is an access to a
1561 -- type with invariants.
1563 Add_Invariant_Access_Checks (Result);
1564 end if;
1566 -- Add invariant and predicates for all formals that qualify
1568 Formal := First_Formal (Subp_Id);
1569 while Present (Formal) loop
1570 Typ := Etype (Formal);
1572 if Ekind (Formal) /= E_In_Parameter
1573 or else Is_Access_Type (Typ)
1574 then
1575 if Invariant_Checks_OK (Typ) then
1576 Append_Enabled_Item
1577 (Item =>
1578 Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
1579 List => Stmts);
1580 end if;
1582 Add_Invariant_Access_Checks (Formal);
1584 -- Note: we used to add predicate checks for OUT and IN OUT
1585 -- formals here, but that was misguided, since such checks are
1586 -- performed on the caller side, based on the predicate of the
1587 -- actual, rather than the predicate of the formal.
1589 end if;
1591 Next_Formal (Formal);
1592 end loop;
1593 end Add_Invariant_And_Predicate_Checks;
1595 -------------------------
1596 -- Append_Enabled_Item --
1597 -------------------------
1599 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
1600 begin
1601 -- Do not chain ignored or disabled pragmas
1603 if Nkind (Item) = N_Pragma
1604 and then (Is_Ignored (Item) or else Is_Disabled (Item))
1605 then
1606 null;
1608 -- Otherwise, add the item
1610 else
1611 if No (List) then
1612 List := New_List;
1613 end if;
1615 -- If the pragma is a conjunct in a composite postcondition, it
1616 -- has been processed in reverse order. In the postcondition body
1617 -- it must appear before the others.
1619 if Nkind (Item) = N_Pragma
1620 and then From_Aspect_Specification (Item)
1621 and then Split_PPC (Item)
1622 then
1623 Prepend (Item, List);
1624 else
1625 Append (Item, List);
1626 end if;
1627 end if;
1628 end Append_Enabled_Item;
1630 ------------------------------------
1631 -- Build_Postconditions_Procedure --
1632 ------------------------------------
1634 procedure Build_Postconditions_Procedure
1635 (Subp_Id : Entity_Id;
1636 Stmts : List_Id;
1637 Result : Entity_Id)
1639 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id);
1640 -- Insert node Stmt before the first source declaration of the
1641 -- related subprogram's body. If no such declaration exists, Stmt
1642 -- becomes the last declaration.
1644 --------------------------------------------
1645 -- Insert_Before_First_Source_Declaration --
1646 --------------------------------------------
1648 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id) is
1649 Decls : constant List_Id := Declarations (Body_Decl);
1650 Decl : Node_Id;
1652 begin
1653 -- Inspect the declarations of the related subprogram body looking
1654 -- for the first source declaration.
1656 if Present (Decls) then
1657 Decl := First (Decls);
1658 while Present (Decl) loop
1659 if Comes_From_Source (Decl) then
1660 Insert_Before (Decl, Stmt);
1661 return;
1662 end if;
1664 Next (Decl);
1665 end loop;
1667 -- If we get there, then the subprogram body lacks any source
1668 -- declarations. The body of _Postconditions now acts as the
1669 -- last declaration.
1671 Append (Stmt, Decls);
1673 -- Ensure that the body has a declaration list
1675 else
1676 Set_Declarations (Body_Decl, New_List (Stmt));
1677 end if;
1678 end Insert_Before_First_Source_Declaration;
1680 -- Local variables
1682 Loc : constant Source_Ptr := Sloc (Body_Decl);
1683 Params : List_Id := No_List;
1684 Proc_Bod : Node_Id;
1685 Proc_Decl : Node_Id;
1686 Proc_Id : Entity_Id;
1687 Proc_Spec : Node_Id;
1689 -- Start of processing for Build_Postconditions_Procedure
1691 begin
1692 -- Nothing to do if there are no actions to check on exit
1694 if No (Stmts) then
1695 return;
1696 end if;
1698 Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
1699 Set_Debug_Info_Needed (Proc_Id);
1700 Set_Postconditions_Proc (Subp_Id, Proc_Id);
1702 -- Force the front-end inlining of _Postconditions when generating C
1703 -- code, since its body may have references to itypes defined in the
1704 -- enclosing subprogram, which would cause problems for unnesting
1705 -- routines in the absence of inlining.
1707 if Generate_C_Code then
1708 Set_Has_Pragma_Inline (Proc_Id);
1709 Set_Has_Pragma_Inline_Always (Proc_Id);
1710 Set_Is_Inlined (Proc_Id);
1711 end if;
1713 -- The related subprogram is a function: create the specification of
1714 -- parameter _Result.
1716 if Present (Result) then
1717 Params := New_List (
1718 Make_Parameter_Specification (Loc,
1719 Defining_Identifier => Result,
1720 Parameter_Type =>
1721 New_Occurrence_Of (Etype (Result), Loc)));
1722 end if;
1724 Proc_Spec :=
1725 Make_Procedure_Specification (Loc,
1726 Defining_Unit_Name => Proc_Id,
1727 Parameter_Specifications => Params);
1729 Proc_Decl := Make_Subprogram_Declaration (Loc, Proc_Spec);
1731 -- Insert _Postconditions before the first source declaration of the
1732 -- body. This ensures that the body will not cause any premature
1733 -- freezing, as it may mention types:
1735 -- procedure Proc (Obj : Array_Typ) is
1736 -- procedure _postconditions is
1737 -- begin
1738 -- ... Obj ...
1739 -- end _postconditions;
1741 -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
1742 -- begin
1744 -- In the example above, Obj is of type T but the incorrect placement
1745 -- of _Postconditions will cause a crash in gigi due to an out-of-
1746 -- order reference. The body of _Postconditions must be placed after
1747 -- the declaration of Temp to preserve correct visibility.
1749 Insert_Before_First_Source_Declaration (Proc_Decl);
1750 Analyze (Proc_Decl);
1752 -- Set an explicit End_Label to override the sloc of the implicit
1753 -- RETURN statement, and prevent it from inheriting the sloc of one
1754 -- the postconditions: this would cause confusing debug info to be
1755 -- produced, interfering with coverage-analysis tools.
1757 Proc_Bod :=
1758 Make_Subprogram_Body (Loc,
1759 Specification =>
1760 Copy_Subprogram_Spec (Proc_Spec),
1761 Declarations => Empty_List,
1762 Handled_Statement_Sequence =>
1763 Make_Handled_Sequence_Of_Statements (Loc,
1764 Statements => Stmts,
1765 End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
1767 Insert_After_And_Analyze (Proc_Decl, Proc_Bod);
1768 end Build_Postconditions_Procedure;
1770 ----------------------------
1771 -- Process_Contract_Cases --
1772 ----------------------------
1774 procedure Process_Contract_Cases (Stmts : in out List_Id) is
1775 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id);
1776 -- Process pragma Contract_Cases for subprogram Subp_Id
1778 --------------------------------
1779 -- Process_Contract_Cases_For --
1780 --------------------------------
1782 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id) is
1783 Items : constant Node_Id := Contract (Subp_Id);
1784 Prag : Node_Id;
1786 begin
1787 if Present (Items) then
1788 Prag := Contract_Test_Cases (Items);
1789 while Present (Prag) loop
1790 if Pragma_Name (Prag) = Name_Contract_Cases then
1791 Expand_Pragma_Contract_Cases
1792 (CCs => Prag,
1793 Subp_Id => Subp_Id,
1794 Decls => Declarations (Body_Decl),
1795 Stmts => Stmts);
1796 end if;
1798 Prag := Next_Pragma (Prag);
1799 end loop;
1800 end if;
1801 end Process_Contract_Cases_For;
1803 -- Start of processing for Process_Contract_Cases
1805 begin
1806 Process_Contract_Cases_For (Body_Id);
1808 if Present (Spec_Id) then
1809 Process_Contract_Cases_For (Spec_Id);
1810 end if;
1811 end Process_Contract_Cases;
1813 ----------------------------
1814 -- Process_Postconditions --
1815 ----------------------------
1817 procedure Process_Postconditions (Stmts : in out List_Id) is
1818 procedure Process_Body_Postconditions (Post_Nam : Name_Id);
1819 -- Collect all [refined] postconditions of a specific kind denoted
1820 -- by Post_Nam that belong to the body, and generate pragma Check
1821 -- equivalents in list Stmts.
1823 procedure Process_Spec_Postconditions;
1824 -- Collect all [inherited] postconditions of the spec, and generate
1825 -- pragma Check equivalents in list Stmts.
1827 ---------------------------------
1828 -- Process_Body_Postconditions --
1829 ---------------------------------
1831 procedure Process_Body_Postconditions (Post_Nam : Name_Id) is
1832 Items : constant Node_Id := Contract (Body_Id);
1833 Unit_Decl : constant Node_Id := Parent (Body_Decl);
1834 Decl : Node_Id;
1835 Prag : Node_Id;
1837 begin
1838 -- Process the contract
1840 if Present (Items) then
1841 Prag := Pre_Post_Conditions (Items);
1842 while Present (Prag) loop
1843 if Pragma_Name (Prag) = Post_Nam then
1844 Append_Enabled_Item
1845 (Item => Build_Pragma_Check_Equivalent (Prag),
1846 List => Stmts);
1847 end if;
1849 Prag := Next_Pragma (Prag);
1850 end loop;
1851 end if;
1853 -- The subprogram body being processed is actually the proper body
1854 -- of a stub with a corresponding spec. The subprogram stub may
1855 -- carry a postcondition pragma, in which case it must be taken
1856 -- into account. The pragma appears after the stub.
1858 if Present (Spec_Id) and then Nkind (Unit_Decl) = N_Subunit then
1859 Decl := Next (Corresponding_Stub (Unit_Decl));
1860 while Present (Decl) loop
1862 -- Note that non-matching pragmas are skipped
1864 if Nkind (Decl) = N_Pragma then
1865 if Pragma_Name (Decl) = Post_Nam then
1866 Append_Enabled_Item
1867 (Item => Build_Pragma_Check_Equivalent (Decl),
1868 List => Stmts);
1869 end if;
1871 -- Skip internally generated code
1873 elsif not Comes_From_Source (Decl) then
1874 null;
1876 -- Postcondition pragmas are usually grouped together. There
1877 -- is no need to inspect the whole declarative list.
1879 else
1880 exit;
1881 end if;
1883 Next (Decl);
1884 end loop;
1885 end if;
1886 end Process_Body_Postconditions;
1888 ---------------------------------
1889 -- Process_Spec_Postconditions --
1890 ---------------------------------
1892 procedure Process_Spec_Postconditions is
1893 Subps : constant Subprogram_List :=
1894 Inherited_Subprograms (Spec_Id);
1895 Items : Node_Id;
1896 Prag : Node_Id;
1897 Subp_Id : Entity_Id;
1899 begin
1900 -- Process the contract
1902 Items := Contract (Spec_Id);
1904 if Present (Items) then
1905 Prag := Pre_Post_Conditions (Items);
1906 while Present (Prag) loop
1907 if Pragma_Name (Prag) = Name_Postcondition then
1908 Append_Enabled_Item
1909 (Item => Build_Pragma_Check_Equivalent (Prag),
1910 List => Stmts);
1911 end if;
1913 Prag := Next_Pragma (Prag);
1914 end loop;
1915 end if;
1917 -- Process the contracts of all inherited subprograms, looking for
1918 -- class-wide postconditions.
1920 for Index in Subps'Range loop
1921 Subp_Id := Subps (Index);
1922 Items := Contract (Subp_Id);
1924 if Present (Items) then
1925 Prag := Pre_Post_Conditions (Items);
1926 while Present (Prag) loop
1927 if Pragma_Name (Prag) = Name_Postcondition
1928 and then Class_Present (Prag)
1929 then
1930 Append_Enabled_Item
1931 (Item =>
1932 Build_Pragma_Check_Equivalent
1933 (Prag => Prag,
1934 Subp_Id => Spec_Id,
1935 Inher_Id => Subp_Id),
1936 List => Stmts);
1937 end if;
1939 Prag := Next_Pragma (Prag);
1940 end loop;
1941 end if;
1942 end loop;
1943 end Process_Spec_Postconditions;
1945 -- Start of processing for Process_Postconditions
1947 begin
1948 -- The processing of postconditions is done in reverse order (body
1949 -- first) to ensure the following arrangement:
1951 -- <refined postconditions from body>
1952 -- <postconditions from body>
1953 -- <postconditions from spec>
1954 -- <inherited postconditions>
1956 Process_Body_Postconditions (Name_Refined_Post);
1957 Process_Body_Postconditions (Name_Postcondition);
1959 if Present (Spec_Id) then
1960 Process_Spec_Postconditions;
1961 end if;
1962 end Process_Postconditions;
1964 ---------------------------
1965 -- Process_Preconditions --
1966 ---------------------------
1968 procedure Process_Preconditions is
1969 Class_Pre : Node_Id := Empty;
1970 -- The sole [inherited] class-wide precondition pragma that applies
1971 -- to the subprogram.
1973 Insert_Node : Node_Id := Empty;
1974 -- The insertion node after which all pragma Check equivalents are
1975 -- inserted.
1977 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean;
1978 -- Determine whether arbitrary declaration Decl denotes a renaming of
1979 -- a discriminant or protection field _object.
1981 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
1982 -- Merge two class-wide preconditions by "or else"-ing them. The
1983 -- changes are accumulated in parameter Into. Update the error
1984 -- message of Into.
1986 procedure Prepend_To_Decls (Item : Node_Id);
1987 -- Prepend a single item to the declarations of the subprogram body
1989 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
1990 -- Save a class-wide precondition into Class_Pre, or prepend a normal
1991 -- precondition to the declarations of the body and analyze it.
1993 procedure Process_Inherited_Preconditions;
1994 -- Collect all inherited class-wide preconditions and merge them into
1995 -- one big precondition to be evaluated as pragma Check.
1997 procedure Process_Preconditions_For (Subp_Id : Entity_Id);
1998 -- Collect all preconditions of subprogram Subp_Id and prepend their
1999 -- pragma Check equivalents to the declarations of the body.
2001 --------------------------
2002 -- Is_Prologue_Renaming --
2003 --------------------------
2005 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean is
2006 Nam : Node_Id;
2007 Obj : Entity_Id;
2008 Pref : Node_Id;
2009 Sel : Node_Id;
2011 begin
2012 if Nkind (Decl) = N_Object_Renaming_Declaration then
2013 Obj := Defining_Entity (Decl);
2014 Nam := Name (Decl);
2016 if Nkind (Nam) = N_Selected_Component then
2017 Pref := Prefix (Nam);
2018 Sel := Selector_Name (Nam);
2020 -- A discriminant renaming appears as
2021 -- Discr : constant ... := Prefix.Discr;
2023 if Ekind (Obj) = E_Constant
2024 and then Is_Entity_Name (Sel)
2025 and then Present (Entity (Sel))
2026 and then Ekind (Entity (Sel)) = E_Discriminant
2027 then
2028 return True;
2030 -- A protection field renaming appears as
2031 -- Prot : ... := _object._object;
2033 elsif Ekind (Obj) = E_Variable
2034 and then Nkind (Pref) = N_Identifier
2035 and then Chars (Pref) = Name_uObject
2036 and then Nkind (Sel) = N_Identifier
2037 and then Chars (Sel) = Name_uObject
2038 then
2039 return True;
2040 end if;
2041 end if;
2042 end if;
2044 return False;
2045 end Is_Prologue_Renaming;
2047 -------------------------
2048 -- Merge_Preconditions --
2049 -------------------------
2051 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
2052 function Expression_Arg (Prag : Node_Id) return Node_Id;
2053 -- Return the boolean expression argument of a precondition while
2054 -- updating its parentheses count for the subsequent merge.
2056 function Message_Arg (Prag : Node_Id) return Node_Id;
2057 -- Return the message argument of a precondition
2059 --------------------
2060 -- Expression_Arg --
2061 --------------------
2063 function Expression_Arg (Prag : Node_Id) return Node_Id is
2064 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2065 Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
2067 begin
2068 if Paren_Count (Arg) = 0 then
2069 Set_Paren_Count (Arg, 1);
2070 end if;
2072 return Arg;
2073 end Expression_Arg;
2075 -----------------
2076 -- Message_Arg --
2077 -----------------
2079 function Message_Arg (Prag : Node_Id) return Node_Id is
2080 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2081 begin
2082 return Get_Pragma_Arg (Last (Args));
2083 end Message_Arg;
2085 -- Local variables
2087 From_Expr : constant Node_Id := Expression_Arg (From);
2088 From_Msg : constant Node_Id := Message_Arg (From);
2089 Into_Expr : constant Node_Id := Expression_Arg (Into);
2090 Into_Msg : constant Node_Id := Message_Arg (Into);
2091 Loc : constant Source_Ptr := Sloc (Into);
2093 -- Start of processing for Merge_Preconditions
2095 begin
2096 -- Merge the two preconditions by "or else"-ing them
2098 Rewrite (Into_Expr,
2099 Make_Or_Else (Loc,
2100 Right_Opnd => Relocate_Node (Into_Expr),
2101 Left_Opnd => From_Expr));
2103 -- Merge the two error messages to produce a single message of the
2104 -- form:
2106 -- failed precondition from ...
2107 -- also failed inherited precondition from ...
2109 if not Exception_Locations_Suppressed then
2110 Start_String (Strval (Into_Msg));
2111 Store_String_Char (ASCII.LF);
2112 Store_String_Chars (" also ");
2113 Store_String_Chars (Strval (From_Msg));
2115 Set_Strval (Into_Msg, End_String);
2116 end if;
2117 end Merge_Preconditions;
2119 ----------------------
2120 -- Prepend_To_Decls --
2121 ----------------------
2123 procedure Prepend_To_Decls (Item : Node_Id) is
2124 Decls : List_Id := Declarations (Body_Decl);
2126 begin
2127 -- Ensure that the body has a declarative list
2129 if No (Decls) then
2130 Decls := New_List;
2131 Set_Declarations (Body_Decl, Decls);
2132 end if;
2134 Prepend_To (Decls, Item);
2135 end Prepend_To_Decls;
2137 ------------------------------
2138 -- Prepend_To_Decls_Or_Save --
2139 ------------------------------
2141 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
2142 Check_Prag : Node_Id;
2144 begin
2145 Check_Prag := Build_Pragma_Check_Equivalent (Prag);
2147 -- Save the sole class-wide precondition (if any) for the next
2148 -- step, where it will be merged with inherited preconditions.
2150 if Class_Present (Prag) then
2151 pragma Assert (No (Class_Pre));
2152 Class_Pre := Check_Prag;
2154 -- Accumulate the corresponding Check pragmas at the top of the
2155 -- declarations. Prepending the items ensures that they will be
2156 -- evaluated in their original order.
2158 else
2159 if Present (Insert_Node) then
2160 Insert_After (Insert_Node, Check_Prag);
2161 else
2162 Prepend_To_Decls (Check_Prag);
2163 end if;
2165 Analyze (Check_Prag);
2166 end if;
2167 end Prepend_To_Decls_Or_Save;
2169 -------------------------------------
2170 -- Process_Inherited_Preconditions --
2171 -------------------------------------
2173 procedure Process_Inherited_Preconditions is
2174 Subps : constant Subprogram_List :=
2175 Inherited_Subprograms (Spec_Id);
2176 Check_Prag : Node_Id;
2177 Items : Node_Id;
2178 Prag : Node_Id;
2179 Subp_Id : Entity_Id;
2181 begin
2182 -- Process the contracts of all inherited subprograms, looking for
2183 -- class-wide preconditions.
2185 for Index in Subps'Range loop
2186 Subp_Id := Subps (Index);
2187 Items := Contract (Subp_Id);
2189 if Present (Items) then
2190 Prag := Pre_Post_Conditions (Items);
2191 while Present (Prag) loop
2192 if Pragma_Name (Prag) = Name_Precondition
2193 and then Class_Present (Prag)
2194 then
2195 Check_Prag :=
2196 Build_Pragma_Check_Equivalent
2197 (Prag => Prag,
2198 Subp_Id => Spec_Id,
2199 Inher_Id => Subp_Id);
2201 -- The spec of an inherited subprogram already yielded
2202 -- a class-wide precondition. Merge the existing
2203 -- precondition with the current one using "or else".
2205 if Present (Class_Pre) then
2206 Merge_Preconditions (Check_Prag, Class_Pre);
2207 else
2208 Class_Pre := Check_Prag;
2209 end if;
2210 end if;
2212 Prag := Next_Pragma (Prag);
2213 end loop;
2214 end if;
2215 end loop;
2217 -- Add the merged class-wide preconditions
2219 if Present (Class_Pre) then
2220 Prepend_To_Decls (Class_Pre);
2221 Analyze (Class_Pre);
2222 end if;
2223 end Process_Inherited_Preconditions;
2225 -------------------------------
2226 -- Process_Preconditions_For --
2227 -------------------------------
2229 procedure Process_Preconditions_For (Subp_Id : Entity_Id) is
2230 Items : constant Node_Id := Contract (Subp_Id);
2231 Decl : Node_Id;
2232 Prag : Node_Id;
2233 Subp_Decl : Node_Id;
2235 begin
2236 -- Process the contract
2238 if Present (Items) then
2239 Prag := Pre_Post_Conditions (Items);
2240 while Present (Prag) loop
2241 if Pragma_Name (Prag) = Name_Precondition then
2242 Prepend_To_Decls_Or_Save (Prag);
2243 end if;
2245 Prag := Next_Pragma (Prag);
2246 end loop;
2247 end if;
2249 -- The subprogram declaration being processed is actually a body
2250 -- stub. The stub may carry a precondition pragma, in which case
2251 -- it must be taken into account. The pragma appears after the
2252 -- stub.
2254 Subp_Decl := Unit_Declaration_Node (Subp_Id);
2256 if Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
2258 -- Inspect the declarations following the body stub
2260 Decl := Next (Subp_Decl);
2261 while Present (Decl) loop
2263 -- Note that non-matching pragmas are skipped
2265 if Nkind (Decl) = N_Pragma then
2266 if Pragma_Name (Decl) = Name_Precondition then
2267 Prepend_To_Decls_Or_Save (Decl);
2268 end if;
2270 -- Skip internally generated code
2272 elsif not Comes_From_Source (Decl) then
2273 null;
2275 -- Preconditions are usually grouped together. There is no
2276 -- need to inspect the whole declarative list.
2278 else
2279 exit;
2280 end if;
2282 Next (Decl);
2283 end loop;
2284 end if;
2285 end Process_Preconditions_For;
2287 -- Local variables
2289 Decls : constant List_Id := Declarations (Body_Decl);
2290 Decl : Node_Id;
2292 -- Start of processing for Process_Preconditions
2294 begin
2295 -- Find the proper insertion point for all pragma Check equivalents
2297 if Present (Decls) then
2298 Decl := First (Decls);
2299 while Present (Decl) loop
2301 -- First source declaration terminates the search, because all
2302 -- preconditions must be evaluated prior to it, by definition.
2304 if Comes_From_Source (Decl) then
2305 exit;
2307 -- Certain internally generated object renamings such as those
2308 -- for discriminants and protection fields must be elaborated
2309 -- before the preconditions are evaluated, as their expressions
2310 -- may mention the discriminants.
2312 elsif Is_Prologue_Renaming (Decl) then
2313 Insert_Node := Decl;
2315 -- Otherwise the declaration does not come from source. This
2316 -- also terminates the search, because internal code may raise
2317 -- exceptions which should not preempt the preconditions.
2319 else
2320 exit;
2321 end if;
2323 Next (Decl);
2324 end loop;
2325 end if;
2327 -- The processing of preconditions is done in reverse order (body
2328 -- first), because each pragma Check equivalent is inserted at the
2329 -- top of the declarations. This ensures that the final order is
2330 -- consistent with following diagram:
2332 -- <inherited preconditions>
2333 -- <preconditions from spec>
2334 -- <preconditions from body>
2336 Process_Preconditions_For (Body_Id);
2338 if Present (Spec_Id) then
2339 Process_Preconditions_For (Spec_Id);
2340 Process_Inherited_Preconditions;
2341 end if;
2342 end Process_Preconditions;
2344 -- Local variables
2346 Restore_Scope : Boolean := False;
2347 Result : Entity_Id;
2348 Stmts : List_Id := No_List;
2349 Subp_Id : Entity_Id;
2351 -- Start of processing for Expand_Subprogram_Contract
2353 begin
2354 -- Obtain the entity of the initial declaration
2356 if Present (Spec_Id) then
2357 Subp_Id := Spec_Id;
2358 else
2359 Subp_Id := Body_Id;
2360 end if;
2362 -- Do not perform expansion activity when it is not needed
2364 if not Expander_Active then
2365 return;
2367 -- ASIS requires an unaltered tree
2369 elsif ASIS_Mode then
2370 return;
2372 -- GNATprove does not need the executable semantics of a contract
2374 elsif GNATprove_Mode then
2375 return;
2377 -- The contract of a generic subprogram or one declared in a generic
2378 -- context is not expanded, as the corresponding instance will provide
2379 -- the executable semantics of the contract.
2381 elsif Is_Generic_Subprogram (Subp_Id) or else Inside_A_Generic then
2382 return;
2384 -- All subprograms carry a contract, but for some it is not significant
2385 -- and should not be processed. This is a small optimization.
2387 elsif not Has_Significant_Contract (Subp_Id) then
2388 return;
2390 -- The contract of an ignored Ghost subprogram does not need expansion,
2391 -- because the subprogram and all calls to it will be removed.
2393 elsif Is_Ignored_Ghost_Entity (Subp_Id) then
2394 return;
2395 end if;
2397 -- Do not re-expand the same contract. This scenario occurs when a
2398 -- construct is rewritten into something else during its analysis
2399 -- (expression functions for instance).
2401 if Has_Expanded_Contract (Subp_Id) then
2402 return;
2404 -- Otherwise mark the subprogram
2406 else
2407 Set_Has_Expanded_Contract (Subp_Id);
2408 end if;
2410 -- Ensure that the formal parameters are visible when expanding all
2411 -- contract items.
2413 if not In_Open_Scopes (Subp_Id) then
2414 Restore_Scope := True;
2415 Push_Scope (Subp_Id);
2417 if Is_Generic_Subprogram (Subp_Id) then
2418 Install_Generic_Formals (Subp_Id);
2419 else
2420 Install_Formals (Subp_Id);
2421 end if;
2422 end if;
2424 -- The expansion of a subprogram contract involves the creation of Check
2425 -- pragmas to verify the contract assertions of the spec and body in a
2426 -- particular order. The order is as follows:
2428 -- function Example (...) return ... is
2429 -- procedure _Postconditions (...) is
2430 -- begin
2431 -- <refined postconditions from body>
2432 -- <postconditions from body>
2433 -- <postconditions from spec>
2434 -- <inherited postconditions>
2435 -- <contract case consequences>
2436 -- <invariant check of function result>
2437 -- <invariant and predicate checks of parameters>
2438 -- end _Postconditions;
2440 -- <inherited preconditions>
2441 -- <preconditions from spec>
2442 -- <preconditions from body>
2443 -- <contract case conditions>
2445 -- <source declarations>
2446 -- begin
2447 -- <source statements>
2449 -- _Preconditions (Result);
2450 -- return Result;
2451 -- end Example;
2453 -- Routine _Postconditions holds all contract assertions that must be
2454 -- verified on exit from the related subprogram.
2456 -- Step 1: Handle all preconditions. This action must come before the
2457 -- processing of pragma Contract_Cases because the pragma prepends items
2458 -- to the body declarations.
2460 Process_Preconditions;
2462 -- Step 2: Handle all postconditions. This action must come before the
2463 -- processing of pragma Contract_Cases because the pragma appends items
2464 -- to list Stmts.
2466 Process_Postconditions (Stmts);
2468 -- Step 3: Handle pragma Contract_Cases. This action must come before
2469 -- the processing of invariants and predicates because those append
2470 -- items to list Stmts.
2472 Process_Contract_Cases (Stmts);
2474 -- Step 4: Apply invariant and predicate checks on a function result and
2475 -- all formals. The resulting checks are accumulated in list Stmts.
2477 Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
2479 -- Step 5: Construct procedure _Postconditions
2481 Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
2483 if Restore_Scope then
2484 End_Scope;
2485 end if;
2486 end Expand_Subprogram_Contract;
2488 ---------------------------------
2489 -- Inherit_Subprogram_Contract --
2490 ---------------------------------
2492 procedure Inherit_Subprogram_Contract
2493 (Subp : Entity_Id;
2494 From_Subp : Entity_Id)
2496 procedure Inherit_Pragma (Prag_Id : Pragma_Id);
2497 -- Propagate a pragma denoted by Prag_Id from From_Subp's contract to
2498 -- Subp's contract.
2500 --------------------
2501 -- Inherit_Pragma --
2502 --------------------
2504 procedure Inherit_Pragma (Prag_Id : Pragma_Id) is
2505 Prag : constant Node_Id := Get_Pragma (From_Subp, Prag_Id);
2506 New_Prag : Node_Id;
2508 begin
2509 -- A pragma cannot be part of more than one First_Pragma/Next_Pragma
2510 -- chains, therefore the node must be replicated. The new pragma is
2511 -- flagged as inherited for distinction purposes.
2513 if Present (Prag) then
2514 New_Prag := New_Copy_Tree (Prag);
2515 Set_Is_Inherited_Pragma (New_Prag);
2517 Add_Contract_Item (New_Prag, Subp);
2518 end if;
2519 end Inherit_Pragma;
2521 -- Start of processing for Inherit_Subprogram_Contract
2523 begin
2524 -- Inheritance is carried out only when both entities are subprograms
2525 -- with contracts.
2527 if Is_Subprogram_Or_Generic_Subprogram (Subp)
2528 and then Is_Subprogram_Or_Generic_Subprogram (From_Subp)
2529 and then Present (Contract (From_Subp))
2530 then
2531 Inherit_Pragma (Pragma_Extensions_Visible);
2532 end if;
2533 end Inherit_Subprogram_Contract;
2535 -------------------------------------
2536 -- Instantiate_Subprogram_Contract --
2537 -------------------------------------
2539 procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id) is
2540 procedure Instantiate_Pragmas (First_Prag : Node_Id);
2541 -- Instantiate all contract-related source pragmas found in the list,
2542 -- starting with pragma First_Prag. Each instantiated pragma is added
2543 -- to list L.
2545 -------------------------
2546 -- Instantiate_Pragmas --
2547 -------------------------
2549 procedure Instantiate_Pragmas (First_Prag : Node_Id) is
2550 Inst_Prag : Node_Id;
2551 Prag : Node_Id;
2553 begin
2554 Prag := First_Prag;
2555 while Present (Prag) loop
2556 if Is_Generic_Contract_Pragma (Prag) then
2557 Inst_Prag :=
2558 Copy_Generic_Node (Prag, Empty, Instantiating => True);
2560 Set_Analyzed (Inst_Prag, False);
2561 Append_To (L, Inst_Prag);
2562 end if;
2564 Prag := Next_Pragma (Prag);
2565 end loop;
2566 end Instantiate_Pragmas;
2568 -- Local variables
2570 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2572 -- Start of processing for Instantiate_Subprogram_Contract
2574 begin
2575 if Present (Items) then
2576 Instantiate_Pragmas (Pre_Post_Conditions (Items));
2577 Instantiate_Pragmas (Contract_Test_Cases (Items));
2578 Instantiate_Pragmas (Classifications (Items));
2579 end if;
2580 end Instantiate_Subprogram_Contract;
2582 ----------------------------------------
2583 -- Save_Global_References_In_Contract --
2584 ----------------------------------------
2586 procedure Save_Global_References_In_Contract
2587 (Templ : Node_Id;
2588 Gen_Id : Entity_Id)
2590 procedure Save_Global_References_In_List (First_Prag : Node_Id);
2591 -- Save all global references in contract-related source pragmas found
2592 -- in the list, starting with pragma First_Prag.
2594 ------------------------------------
2595 -- Save_Global_References_In_List --
2596 ------------------------------------
2598 procedure Save_Global_References_In_List (First_Prag : Node_Id) is
2599 Prag : Node_Id;
2601 begin
2602 Prag := First_Prag;
2603 while Present (Prag) loop
2604 if Is_Generic_Contract_Pragma (Prag) then
2605 Save_Global_References (Prag);
2606 end if;
2608 Prag := Next_Pragma (Prag);
2609 end loop;
2610 end Save_Global_References_In_List;
2612 -- Local variables
2614 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2616 -- Start of processing for Save_Global_References_In_Contract
2618 begin
2619 -- The entity of the analyzed generic copy must be on the scope stack
2620 -- to ensure proper detection of global references.
2622 Push_Scope (Gen_Id);
2624 if Permits_Aspect_Specifications (Templ)
2625 and then Has_Aspects (Templ)
2626 then
2627 Save_Global_References_In_Aspects (Templ);
2628 end if;
2630 if Present (Items) then
2631 Save_Global_References_In_List (Pre_Post_Conditions (Items));
2632 Save_Global_References_In_List (Contract_Test_Cases (Items));
2633 Save_Global_References_In_List (Classifications (Items));
2634 end if;
2636 Pop_Scope;
2637 end Save_Global_References_In_Contract;
2639 end Contracts;