PR middle-end/66867
[official-gcc.git] / gcc / ada / contracts.adb
blobc85b650d66b19584bd1bfbacb3bb0fd5fa43fb8c
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_Disp; use Sem_Disp;
44 with Sem_Prag; use Sem_Prag;
45 with Sem_Util; use Sem_Util;
46 with Sinfo; use Sinfo;
47 with Snames; use Snames;
48 with Stringt; use Stringt;
49 with Tbuild; use Tbuild;
51 package body Contracts is
53 procedure Analyze_Contracts
54 (L : List_Id;
55 Freeze_Nod : Node_Id;
56 Freeze_Id : Entity_Id);
57 -- Subsidiary to the one parameter version of Analyze_Contracts and routine
58 -- Analyze_Previous_Constracts. Analyze the contracts of all constructs in
59 -- the list L. If Freeze_Nod is set, then the analysis stops when the node
60 -- is reached. Freeze_Id is the entity of some related context which caused
61 -- freezing up to node Freeze_Nod.
63 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
64 -- Expand the contracts of a subprogram body and its correspoding spec (if
65 -- any). This routine processes all [refined] pre- and postconditions as
66 -- well as Contract_Cases, invariants and predicates. Body_Id denotes the
67 -- entity of the subprogram body.
69 -----------------------
70 -- Add_Contract_Item --
71 -----------------------
73 procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
74 Items : Node_Id := Contract (Id);
76 procedure Add_Classification;
77 -- Prepend Prag to the list of classifications
79 procedure Add_Contract_Test_Case;
80 -- Prepend Prag to the list of contract and test cases
82 procedure Add_Pre_Post_Condition;
83 -- Prepend Prag to the list of pre- and postconditions
85 ------------------------
86 -- Add_Classification --
87 ------------------------
89 procedure Add_Classification is
90 begin
91 Set_Next_Pragma (Prag, Classifications (Items));
92 Set_Classifications (Items, Prag);
93 end Add_Classification;
95 ----------------------------
96 -- Add_Contract_Test_Case --
97 ----------------------------
99 procedure Add_Contract_Test_Case is
100 begin
101 Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
102 Set_Contract_Test_Cases (Items, Prag);
103 end Add_Contract_Test_Case;
105 ----------------------------
106 -- Add_Pre_Post_Condition --
107 ----------------------------
109 procedure Add_Pre_Post_Condition is
110 begin
111 Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
112 Set_Pre_Post_Conditions (Items, Prag);
113 end Add_Pre_Post_Condition;
115 -- Local variables
117 Prag_Nam : Name_Id;
119 -- Start of processing for Add_Contract_Item
121 begin
122 -- A contract must contain only pragmas
124 pragma Assert (Nkind (Prag) = N_Pragma);
125 Prag_Nam := Pragma_Name (Prag);
127 -- Create a new contract when adding the first item
129 if No (Items) then
130 Items := Make_Contract (Sloc (Id));
131 Set_Contract (Id, Items);
132 end if;
134 -- Constants, the applicable pragmas are:
135 -- Part_Of
137 if Ekind (Id) = E_Constant then
138 if Prag_Nam = Name_Part_Of then
139 Add_Classification;
141 -- The pragma is not a proper contract item
143 else
144 raise Program_Error;
145 end if;
147 -- Entry bodies, the applicable pragmas are:
148 -- Refined_Depends
149 -- Refined_Global
150 -- Refined_Post
152 elsif Is_Entry_Body (Id) then
153 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
154 Add_Classification;
156 elsif Prag_Nam = Name_Refined_Post then
157 Add_Pre_Post_Condition;
159 -- The pragma is not a proper contract item
161 else
162 raise Program_Error;
163 end if;
165 -- Entry or subprogram declarations, the applicable pragmas are:
166 -- Attach_Handler
167 -- Contract_Cases
168 -- Depends
169 -- Extensions_Visible
170 -- Global
171 -- Interrupt_Handler
172 -- Postcondition
173 -- Precondition
174 -- Test_Case
175 -- Volatile_Function
177 elsif Is_Entry_Declaration (Id)
178 or else Ekind_In (Id, E_Function,
179 E_Generic_Function,
180 E_Generic_Procedure,
181 E_Procedure)
182 then
183 if Nam_In (Prag_Nam, Name_Attach_Handler, Name_Interrupt_Handler)
184 and then Ekind_In (Id, E_Generic_Procedure, E_Procedure)
185 then
186 Add_Classification;
188 elsif Nam_In (Prag_Nam, Name_Depends,
189 Name_Extensions_Visible,
190 Name_Global)
191 then
192 Add_Classification;
194 elsif Prag_Nam = Name_Volatile_Function
195 and then Ekind_In (Id, E_Function, E_Generic_Function)
196 then
197 Add_Classification;
199 elsif Nam_In (Prag_Nam, Name_Contract_Cases, Name_Test_Case) then
200 Add_Contract_Test_Case;
202 elsif Nam_In (Prag_Nam, Name_Postcondition, Name_Precondition) then
203 Add_Pre_Post_Condition;
205 -- The pragma is not a proper contract item
207 else
208 raise Program_Error;
209 end if;
211 -- Packages or instantiations, the applicable pragmas are:
212 -- Abstract_States
213 -- Initial_Condition
214 -- Initializes
215 -- Part_Of (instantiation only)
217 elsif Ekind_In (Id, E_Generic_Package, E_Package) then
218 if Nam_In (Prag_Nam, Name_Abstract_State,
219 Name_Initial_Condition,
220 Name_Initializes)
221 then
222 Add_Classification;
224 -- Indicator Part_Of must be associated with a package instantiation
226 elsif Prag_Nam = Name_Part_Of and then Is_Generic_Instance (Id) then
227 Add_Classification;
229 -- The pragma is not a proper contract item
231 else
232 raise Program_Error;
233 end if;
235 -- Package bodies, the applicable pragmas are:
236 -- Refined_States
238 elsif Ekind (Id) = E_Package_Body then
239 if Prag_Nam = Name_Refined_State then
240 Add_Classification;
242 -- The pragma is not a proper contract item
244 else
245 raise Program_Error;
246 end if;
248 -- Protected units, the applicable pragmas are:
249 -- Part_Of
251 elsif Ekind (Id) = E_Protected_Type then
252 if Prag_Nam = Name_Part_Of then
253 Add_Classification;
255 -- The pragma is not a proper contract item
257 else
258 raise Program_Error;
259 end if;
261 -- Subprogram bodies, the applicable pragmas are:
262 -- Postcondition
263 -- Precondition
264 -- Refined_Depends
265 -- Refined_Global
266 -- Refined_Post
268 elsif Ekind (Id) = E_Subprogram_Body then
269 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
270 Add_Classification;
272 elsif Nam_In (Prag_Nam, Name_Postcondition,
273 Name_Precondition,
274 Name_Refined_Post)
275 then
276 Add_Pre_Post_Condition;
278 -- The pragma is not a proper contract item
280 else
281 raise Program_Error;
282 end if;
284 -- Task bodies, the applicable pragmas are:
285 -- Refined_Depends
286 -- Refined_Global
288 elsif Ekind (Id) = E_Task_Body then
289 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
290 Add_Classification;
292 -- The pragma is not a proper contract item
294 else
295 raise Program_Error;
296 end if;
298 -- Task units, the applicable pragmas are:
299 -- Depends
300 -- Global
301 -- Part_Of
303 elsif Ekind (Id) = E_Task_Type then
304 if Nam_In (Prag_Nam, Name_Depends, Name_Global, Name_Part_Of) then
305 Add_Classification;
307 -- The pragma is not a proper contract item
309 else
310 raise Program_Error;
311 end if;
313 -- Variables, the applicable pragmas are:
314 -- Async_Readers
315 -- Async_Writers
316 -- Constant_After_Elaboration
317 -- Depends
318 -- Effective_Reads
319 -- Effective_Writes
320 -- Global
321 -- Part_Of
323 elsif Ekind (Id) = E_Variable then
324 if Nam_In (Prag_Nam, Name_Async_Readers,
325 Name_Async_Writers,
326 Name_Constant_After_Elaboration,
327 Name_Depends,
328 Name_Effective_Reads,
329 Name_Effective_Writes,
330 Name_Global,
331 Name_Part_Of)
332 then
333 Add_Classification;
335 -- The pragma is not a proper contract item
337 else
338 raise Program_Error;
339 end if;
340 end if;
341 end Add_Contract_Item;
343 -----------------------
344 -- Analyze_Contracts --
345 -----------------------
347 procedure Analyze_Contracts (L : List_Id) is
348 begin
349 Analyze_Contracts (L, Freeze_Nod => Empty, Freeze_Id => Empty);
350 end Analyze_Contracts;
352 procedure Analyze_Contracts
353 (L : List_Id;
354 Freeze_Nod : Node_Id;
355 Freeze_Id : Entity_Id)
357 Decl : Node_Id;
359 begin
360 Decl := First (L);
361 while Present (Decl) loop
363 -- The caller requests that the traversal stops at a particular node
364 -- that causes contract "freezing".
366 if Present (Freeze_Nod) and then Decl = Freeze_Nod then
367 exit;
368 end if;
370 -- Entry or subprogram declarations
372 if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
373 N_Entry_Declaration,
374 N_Generic_Subprogram_Declaration,
375 N_Subprogram_Declaration)
376 then
377 Analyze_Entry_Or_Subprogram_Contract
378 (Subp_Id => Defining_Entity (Decl),
379 Freeze_Id => Freeze_Id);
381 -- Entry or subprogram bodies
383 elsif Nkind_In (Decl, N_Entry_Body, N_Subprogram_Body) then
384 Analyze_Entry_Or_Subprogram_Body_Contract (Defining_Entity (Decl));
386 -- Objects
388 elsif Nkind (Decl) = N_Object_Declaration then
389 Analyze_Object_Contract
390 (Obj_Id => Defining_Entity (Decl),
391 Freeze_Id => Freeze_Id);
393 -- Protected untis
395 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
396 N_Single_Protected_Declaration)
397 then
398 Analyze_Protected_Contract (Defining_Entity (Decl));
400 -- Subprogram body stubs
402 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
403 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
405 -- Task units
407 elsif Nkind_In (Decl, N_Single_Task_Declaration,
408 N_Task_Type_Declaration)
409 then
410 Analyze_Task_Contract (Defining_Entity (Decl));
411 end if;
413 Next (Decl);
414 end loop;
415 end Analyze_Contracts;
417 -----------------------------------------------
418 -- Analyze_Entry_Or_Subprogram_Body_Contract --
419 -----------------------------------------------
421 procedure Analyze_Entry_Or_Subprogram_Body_Contract (Body_Id : Entity_Id) is
422 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
423 Items : constant Node_Id := Contract (Body_Id);
424 Spec_Id : constant Entity_Id := Unique_Defining_Entity (Body_Decl);
425 Mode : SPARK_Mode_Type;
427 begin
428 -- When a subprogram body declaration is illegal, its defining entity is
429 -- left unanalyzed. There is nothing left to do in this case because the
430 -- body lacks a contract, or even a proper Ekind.
432 if Ekind (Body_Id) = E_Void then
433 return;
435 -- Do not analyze a contract multiple times
437 elsif Present (Items) then
438 if Analyzed (Items) then
439 return;
440 else
441 Set_Analyzed (Items);
442 end if;
443 end if;
445 -- Due to the timing of contract analysis, delayed pragmas may be
446 -- subject to the wrong SPARK_Mode, usually that of the enclosing
447 -- context. To remedy this, restore the original SPARK_Mode of the
448 -- related subprogram body.
450 Save_SPARK_Mode_And_Set (Body_Id, Mode);
452 -- Ensure that the contract cases or postconditions mention 'Result or
453 -- define a post-state.
455 Check_Result_And_Post_State (Body_Id);
457 -- A stand-alone nonvolatile function body cannot have an effectively
458 -- volatile formal parameter or return type (SPARK RM 7.1.3(9)). This
459 -- check is relevant only when SPARK_Mode is on, as it is not a standard
460 -- legality rule. The check is performed here because Volatile_Function
461 -- is processed after the analysis of the related subprogram body.
463 if SPARK_Mode = On
464 and then Ekind_In (Body_Id, E_Function, E_Generic_Function)
465 and then not Is_Volatile_Function (Body_Id)
466 then
467 Check_Nonvolatile_Function_Profile (Body_Id);
468 end if;
470 -- Restore the SPARK_Mode of the enclosing context after all delayed
471 -- pragmas have been analyzed.
473 Restore_SPARK_Mode (Mode);
475 -- Capture all global references in a generic subprogram body now that
476 -- the contract has been analyzed.
478 if Is_Generic_Declaration_Or_Body (Body_Decl) then
479 Save_Global_References_In_Contract
480 (Templ => Original_Node (Body_Decl),
481 Gen_Id => Spec_Id);
482 end if;
484 -- Deal with preconditions, [refined] postconditions, Contract_Cases,
485 -- invariants and predicates associated with body and its spec. Do not
486 -- expand the contract of subprogram body stubs.
488 if Nkind (Body_Decl) = N_Subprogram_Body then
489 Expand_Subprogram_Contract (Body_Id);
490 end if;
491 end Analyze_Entry_Or_Subprogram_Body_Contract;
493 ------------------------------------------
494 -- Analyze_Entry_Or_Subprogram_Contract --
495 ------------------------------------------
497 procedure Analyze_Entry_Or_Subprogram_Contract
498 (Subp_Id : Entity_Id;
499 Freeze_Id : Entity_Id := Empty)
501 Items : constant Node_Id := Contract (Subp_Id);
502 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
504 Skip_Assert_Exprs : constant Boolean :=
505 Ekind_In (Subp_Id, E_Entry, E_Entry_Family)
506 and then not ASIS_Mode
507 and then not GNATprove_Mode;
509 Depends : Node_Id := Empty;
510 Global : Node_Id := Empty;
511 Mode : SPARK_Mode_Type;
512 Prag : Node_Id;
513 Prag_Nam : Name_Id;
515 begin
516 -- Do not analyze a contract multiple times
518 if Present (Items) then
519 if Analyzed (Items) then
520 return;
521 else
522 Set_Analyzed (Items);
523 end if;
524 end if;
526 -- Due to the timing of contract analysis, delayed pragmas may be
527 -- subject to the wrong SPARK_Mode, usually that of the enclosing
528 -- context. To remedy this, restore the original SPARK_Mode of the
529 -- related subprogram body.
531 Save_SPARK_Mode_And_Set (Subp_Id, Mode);
533 -- All subprograms carry a contract, but for some it is not significant
534 -- and should not be processed.
536 if not Has_Significant_Contract (Subp_Id) then
537 null;
539 elsif Present (Items) then
541 -- Do not analyze the pre/postconditions of an entry declaration
542 -- unless annotating the original tree for ASIS or GNATprove. The
543 -- real analysis occurs when the pre/postconditons are relocated to
544 -- the contract wrapper procedure (see Build_Contract_Wrapper).
546 if Skip_Assert_Exprs then
547 null;
549 -- Otherwise analyze the pre/postconditions
551 else
552 Prag := Pre_Post_Conditions (Items);
553 while Present (Prag) loop
554 Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
555 Prag := Next_Pragma (Prag);
556 end loop;
557 end if;
559 -- Analyze contract-cases and test-cases
561 Prag := Contract_Test_Cases (Items);
562 while Present (Prag) loop
563 Prag_Nam := Pragma_Name (Prag);
565 if Prag_Nam = Name_Contract_Cases then
567 -- Do not analyze the contract cases of an entry declaration
568 -- unless annotating the original tree for ASIS or GNATprove.
569 -- The real analysis occurs when the contract cases are moved
570 -- to the contract wrapper procedure (Build_Contract_Wrapper).
572 if Skip_Assert_Exprs then
573 null;
575 -- Otherwise analyze the contract cases
577 else
578 Analyze_Contract_Cases_In_Decl_Part (Prag, Freeze_Id);
579 end if;
580 else
581 pragma Assert (Prag_Nam = Name_Test_Case);
582 Analyze_Test_Case_In_Decl_Part (Prag);
583 end if;
585 Prag := Next_Pragma (Prag);
586 end loop;
588 -- Analyze classification pragmas
590 Prag := Classifications (Items);
591 while Present (Prag) loop
592 Prag_Nam := Pragma_Name (Prag);
594 if Prag_Nam = Name_Depends then
595 Depends := Prag;
597 elsif Prag_Nam = Name_Global then
598 Global := Prag;
599 end if;
601 Prag := Next_Pragma (Prag);
602 end loop;
604 -- Analyze Global first, as Depends may mention items classified in
605 -- the global categorization.
607 if Present (Global) then
608 Analyze_Global_In_Decl_Part (Global);
609 end if;
611 -- Depends must be analyzed after Global in order to see the modes of
612 -- all global items.
614 if Present (Depends) then
615 Analyze_Depends_In_Decl_Part (Depends);
616 end if;
618 -- Ensure that the contract cases or postconditions mention 'Result
619 -- or define a post-state.
621 Check_Result_And_Post_State (Subp_Id);
622 end if;
624 -- A nonvolatile function cannot have an effectively volatile formal
625 -- parameter or return type (SPARK RM 7.1.3(9)). This check is relevant
626 -- only when SPARK_Mode is on, as it is not a standard legality rule.
627 -- The check is performed here because pragma Volatile_Function is
628 -- processed after the analysis of the related subprogram declaration.
630 if SPARK_Mode = On
631 and then Ekind_In (Subp_Id, E_Function, E_Generic_Function)
632 and then not Is_Volatile_Function (Subp_Id)
633 then
634 Check_Nonvolatile_Function_Profile (Subp_Id);
635 end if;
637 -- Restore the SPARK_Mode of the enclosing context after all delayed
638 -- pragmas have been analyzed.
640 Restore_SPARK_Mode (Mode);
642 -- Capture all global references in a generic subprogram now that the
643 -- contract has been analyzed.
645 if Is_Generic_Declaration_Or_Body (Subp_Decl) then
646 Save_Global_References_In_Contract
647 (Templ => Original_Node (Subp_Decl),
648 Gen_Id => Subp_Id);
649 end if;
650 end Analyze_Entry_Or_Subprogram_Contract;
652 -----------------------------
653 -- Analyze_Object_Contract --
654 -----------------------------
656 procedure Analyze_Object_Contract
657 (Obj_Id : Entity_Id;
658 Freeze_Id : Entity_Id := Empty)
660 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
661 AR_Val : Boolean := False;
662 AW_Val : Boolean := False;
663 ER_Val : Boolean := False;
664 EW_Val : Boolean := False;
665 Items : Node_Id;
666 Mode : SPARK_Mode_Type;
667 Prag : Node_Id;
668 Ref_Elmt : Elmt_Id;
669 Restore_Mode : Boolean := False;
670 Seen : Boolean := False;
672 begin
673 -- The loop parameter in an element iterator over a formal container
674 -- is declared with an object declaration, but no contracts apply.
676 if Ekind (Obj_Id) = E_Loop_Parameter then
677 return;
678 end if;
680 -- Do not analyze a contract multiple times
682 Items := Contract (Obj_Id);
684 if Present (Items) then
685 if Analyzed (Items) then
686 return;
687 else
688 Set_Analyzed (Items);
689 end if;
690 end if;
692 -- The anonymous object created for a single concurrent type inherits
693 -- the SPARK_Mode from the type. Due to the timing of contract analysis,
694 -- delayed pragmas may be subject to the wrong SPARK_Mode, usually that
695 -- of the enclosing context. To remedy this, restore the original mode
696 -- of the related anonymous object.
698 if Is_Single_Concurrent_Object (Obj_Id)
699 and then Present (SPARK_Pragma (Obj_Id))
700 then
701 Restore_Mode := True;
702 Save_SPARK_Mode_And_Set (Obj_Id, Mode);
703 end if;
705 -- Constant-related checks
707 if Ekind (Obj_Id) = E_Constant then
709 -- Analyze indicator Part_Of
711 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
713 -- Check whether the lack of indicator Part_Of agrees with the
714 -- placement of the constant with respect to the state space.
716 if No (Prag) then
717 Check_Missing_Part_Of (Obj_Id);
718 end if;
720 -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
721 -- This check is relevant only when SPARK_Mode is on, as it is not
722 -- a standard Ada legality rule. Internally-generated constants that
723 -- map generic formals to actuals in instantiations are allowed to
724 -- be volatile.
726 if SPARK_Mode = On
727 and then Comes_From_Source (Obj_Id)
728 and then Is_Effectively_Volatile (Obj_Id)
729 and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
730 then
731 Error_Msg_N ("constant cannot be volatile", Obj_Id);
732 end if;
734 -- Variable-related checks
736 else pragma Assert (Ekind (Obj_Id) = E_Variable);
738 -- Analyze all external properties
740 Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
742 if Present (Prag) then
743 Analyze_External_Property_In_Decl_Part (Prag, AR_Val);
744 Seen := True;
745 end if;
747 Prag := Get_Pragma (Obj_Id, Pragma_Async_Writers);
749 if Present (Prag) then
750 Analyze_External_Property_In_Decl_Part (Prag, AW_Val);
751 Seen := True;
752 end if;
754 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Reads);
756 if Present (Prag) then
757 Analyze_External_Property_In_Decl_Part (Prag, ER_Val);
758 Seen := True;
759 end if;
761 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Writes);
763 if Present (Prag) then
764 Analyze_External_Property_In_Decl_Part (Prag, EW_Val);
765 Seen := True;
766 end if;
768 -- Verify the mutual interaction of the various external properties
770 if Seen then
771 Check_External_Properties (Obj_Id, AR_Val, AW_Val, ER_Val, EW_Val);
772 end if;
774 -- The anonymous object created for a single concurrent type carries
775 -- pragmas Depends and Globat of the type.
777 if Is_Single_Concurrent_Object (Obj_Id) then
779 -- Analyze Global first, as Depends may mention items classified
780 -- in the global categorization.
782 Prag := Get_Pragma (Obj_Id, Pragma_Global);
784 if Present (Prag) then
785 Analyze_Global_In_Decl_Part (Prag);
786 end if;
788 -- Depends must be analyzed after Global in order to see the modes
789 -- of all global items.
791 Prag := Get_Pragma (Obj_Id, Pragma_Depends);
793 if Present (Prag) then
794 Analyze_Depends_In_Decl_Part (Prag);
795 end if;
796 end if;
798 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
800 -- Analyze indicator Part_Of
802 if Present (Prag) then
803 Analyze_Part_Of_In_Decl_Part (Prag, Freeze_Id);
805 -- The variable is a constituent of a single protected/task type
806 -- and behaves as a component of the type. Verify that references
807 -- to the variable occur within the definition or body of the type
808 -- (SPARK RM 9.3).
810 if Present (Encapsulating_State (Obj_Id))
811 and then Is_Single_Concurrent_Object
812 (Encapsulating_State (Obj_Id))
813 and then Present (Part_Of_References (Obj_Id))
814 then
815 Ref_Elmt := First_Elmt (Part_Of_References (Obj_Id));
816 while Present (Ref_Elmt) loop
817 Check_Part_Of_Reference (Obj_Id, Node (Ref_Elmt));
818 Next_Elmt (Ref_Elmt);
819 end loop;
820 end if;
822 -- Otherwise check whether the lack of indicator Part_Of agrees with
823 -- the placement of the variable with respect to the state space.
825 else
826 Check_Missing_Part_Of (Obj_Id);
827 end if;
829 -- The following checks are relevant only when SPARK_Mode is on, as
830 -- they are not standard Ada legality rules. Internally generated
831 -- temporaries are ignored.
833 if SPARK_Mode = On and then Comes_From_Source (Obj_Id) then
834 if Is_Effectively_Volatile (Obj_Id) then
836 -- The declaration of an effectively volatile object must
837 -- appear at the library level (SPARK RM 7.1.3(3), C.6(6)).
839 if not Is_Library_Level_Entity (Obj_Id) then
840 Error_Msg_N
841 ("volatile variable & must be declared at library level",
842 Obj_Id);
844 -- An object of a discriminated type cannot be effectively
845 -- volatile except for protected objects (SPARK RM 7.1.3(5)).
847 elsif Has_Discriminants (Obj_Typ)
848 and then not Is_Protected_Type (Obj_Typ)
849 then
850 Error_Msg_N
851 ("discriminated object & cannot be volatile", Obj_Id);
853 -- An object of a tagged type cannot be effectively volatile
854 -- (SPARK RM C.6(5)).
856 elsif Is_Tagged_Type (Obj_Typ) then
857 Error_Msg_N ("tagged object & cannot be volatile", Obj_Id);
858 end if;
860 -- The object is not effectively volatile
862 else
863 -- A non-effectively volatile object cannot have effectively
864 -- volatile components (SPARK RM 7.1.3(6)).
866 if not Is_Effectively_Volatile (Obj_Id)
867 and then Has_Volatile_Component (Obj_Typ)
868 then
869 Error_Msg_N
870 ("non-volatile object & cannot have volatile components",
871 Obj_Id);
872 end if;
873 end if;
874 end if;
875 end if;
877 -- Common checks
879 if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
881 -- A Ghost object cannot be of a type that yields a synchronized
882 -- object (SPARK RM 6.9(19)).
884 if Yields_Synchronized_Object (Obj_Typ) then
885 Error_Msg_N ("ghost object & cannot be synchronized", Obj_Id);
887 -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and
888 -- SPARK RM 6.9(19)).
890 elsif Is_Effectively_Volatile (Obj_Id) then
891 Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
893 -- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)).
894 -- One exception to this is the object that represents the dispatch
895 -- table of a Ghost tagged type, as the symbol needs to be exported.
897 elsif Is_Exported (Obj_Id) then
898 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
900 elsif Is_Imported (Obj_Id) then
901 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
902 end if;
903 end if;
905 -- Restore the SPARK_Mode of the enclosing context after all delayed
906 -- pragmas have been analyzed.
908 if Restore_Mode then
909 Restore_SPARK_Mode (Mode);
910 end if;
911 end Analyze_Object_Contract;
913 -----------------------------------
914 -- Analyze_Package_Body_Contract --
915 -----------------------------------
917 procedure Analyze_Package_Body_Contract
918 (Body_Id : Entity_Id;
919 Freeze_Id : Entity_Id := Empty)
921 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
922 Items : constant Node_Id := Contract (Body_Id);
923 Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
924 Mode : SPARK_Mode_Type;
925 Ref_State : Node_Id;
927 begin
928 -- Do not analyze a contract multiple times
930 if Present (Items) then
931 if Analyzed (Items) then
932 return;
933 else
934 Set_Analyzed (Items);
935 end if;
936 end if;
938 -- Due to the timing of contract analysis, delayed pragmas may be
939 -- subject to the wrong SPARK_Mode, usually that of the enclosing
940 -- context. To remedy this, restore the original SPARK_Mode of the
941 -- related package body.
943 Save_SPARK_Mode_And_Set (Body_Id, Mode);
945 Ref_State := Get_Pragma (Body_Id, Pragma_Refined_State);
947 -- The analysis of pragma Refined_State detects whether the spec has
948 -- abstract states available for refinement.
950 if Present (Ref_State) then
951 Analyze_Refined_State_In_Decl_Part (Ref_State, Freeze_Id);
952 end if;
954 -- Restore the SPARK_Mode of the enclosing context after all delayed
955 -- pragmas have been analyzed.
957 Restore_SPARK_Mode (Mode);
959 -- Capture all global references in a generic package body now that the
960 -- contract has been analyzed.
962 if Is_Generic_Declaration_Or_Body (Body_Decl) then
963 Save_Global_References_In_Contract
964 (Templ => Original_Node (Body_Decl),
965 Gen_Id => Spec_Id);
966 end if;
967 end Analyze_Package_Body_Contract;
969 ------------------------------
970 -- Analyze_Package_Contract --
971 ------------------------------
973 procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
974 Items : constant Node_Id := Contract (Pack_Id);
975 Pack_Decl : constant Node_Id := Unit_Declaration_Node (Pack_Id);
976 Init : Node_Id := Empty;
977 Init_Cond : Node_Id := Empty;
978 Mode : SPARK_Mode_Type;
979 Prag : Node_Id;
980 Prag_Nam : Name_Id;
982 begin
983 -- Do not analyze a contract multiple times
985 if Present (Items) then
986 if Analyzed (Items) then
987 return;
988 else
989 Set_Analyzed (Items);
990 end if;
991 end if;
993 -- Due to the timing of contract analysis, delayed pragmas may be
994 -- subject to the wrong SPARK_Mode, usually that of the enclosing
995 -- context. To remedy this, restore the original SPARK_Mode of the
996 -- related package.
998 Save_SPARK_Mode_And_Set (Pack_Id, Mode);
1000 if Present (Items) then
1002 -- Locate and store pragmas Initial_Condition and Initializes, since
1003 -- their order of analysis matters.
1005 Prag := Classifications (Items);
1006 while Present (Prag) loop
1007 Prag_Nam := Pragma_Name (Prag);
1009 if Prag_Nam = Name_Initial_Condition then
1010 Init_Cond := Prag;
1012 elsif Prag_Nam = Name_Initializes then
1013 Init := Prag;
1014 end if;
1016 Prag := Next_Pragma (Prag);
1017 end loop;
1019 -- Analyze the initialization-related pragmas. Initializes must come
1020 -- before Initial_Condition due to item dependencies.
1022 if Present (Init) then
1023 Analyze_Initializes_In_Decl_Part (Init);
1024 end if;
1026 if Present (Init_Cond) then
1027 Analyze_Initial_Condition_In_Decl_Part (Init_Cond);
1028 end if;
1029 end if;
1031 -- Check whether the lack of indicator Part_Of agrees with the placement
1032 -- of the package instantiation with respect to the state space.
1034 if Is_Generic_Instance (Pack_Id) then
1035 Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
1037 if No (Prag) then
1038 Check_Missing_Part_Of (Pack_Id);
1039 end if;
1040 end if;
1042 -- Restore the SPARK_Mode of the enclosing context after all delayed
1043 -- pragmas have been analyzed.
1045 Restore_SPARK_Mode (Mode);
1047 -- Capture all global references in a generic package now that the
1048 -- contract has been analyzed.
1050 if Is_Generic_Declaration_Or_Body (Pack_Decl) then
1051 Save_Global_References_In_Contract
1052 (Templ => Original_Node (Pack_Decl),
1053 Gen_Id => Pack_Id);
1054 end if;
1055 end Analyze_Package_Contract;
1057 --------------------------------
1058 -- Analyze_Previous_Contracts --
1059 --------------------------------
1061 procedure Analyze_Previous_Contracts (Body_Decl : Node_Id) is
1062 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
1063 Par : Node_Id;
1065 begin
1066 -- A body that is in the process of being inlined appears from source,
1067 -- but carries name _parent. Such a body does not cause "freezing" of
1068 -- contracts.
1070 if Chars (Body_Id) = Name_uParent then
1071 return;
1072 end if;
1074 -- Climb the parent chain looking for an enclosing package body. Do not
1075 -- use the scope stack, as a body uses the entity of its corresponding
1076 -- spec.
1078 Par := Parent (Body_Decl);
1079 while Present (Par) loop
1080 if Nkind (Par) = N_Package_Body then
1081 Analyze_Package_Body_Contract
1082 (Body_Id => Defining_Entity (Par),
1083 Freeze_Id => Defining_Entity (Body_Decl));
1085 exit;
1086 end if;
1088 Par := Parent (Par);
1089 end loop;
1091 -- Analyze the contracts of all eligible construct up to the body which
1092 -- caused the "freezing".
1094 if Is_List_Member (Body_Decl) then
1095 Analyze_Contracts
1096 (L => List_Containing (Body_Decl),
1097 Freeze_Nod => Body_Decl,
1098 Freeze_Id => Body_Id);
1099 end if;
1100 end Analyze_Previous_Contracts;
1102 --------------------------------
1103 -- Analyze_Protected_Contract --
1104 --------------------------------
1106 procedure Analyze_Protected_Contract (Prot_Id : Entity_Id) is
1107 Items : constant Node_Id := Contract (Prot_Id);
1109 begin
1110 -- Do not analyze a contract multiple times
1112 if Present (Items) then
1113 if Analyzed (Items) then
1114 return;
1115 else
1116 Set_Analyzed (Items);
1117 end if;
1118 end if;
1119 end Analyze_Protected_Contract;
1121 -------------------------------------------
1122 -- Analyze_Subprogram_Body_Stub_Contract --
1123 -------------------------------------------
1125 procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id) is
1126 Stub_Decl : constant Node_Id := Parent (Parent (Stub_Id));
1127 Spec_Id : constant Entity_Id := Corresponding_Spec_Of_Stub (Stub_Decl);
1129 begin
1130 -- A subprogram body stub may act as its own spec or as the completion
1131 -- of a previous declaration. Depending on the context, the contract of
1132 -- the stub may contain two sets of pragmas.
1134 -- The stub is a completion, the applicable pragmas are:
1135 -- Refined_Depends
1136 -- Refined_Global
1138 if Present (Spec_Id) then
1139 Analyze_Entry_Or_Subprogram_Body_Contract (Stub_Id);
1141 -- The stub acts as its own spec, the applicable pragmas are:
1142 -- Contract_Cases
1143 -- Depends
1144 -- Global
1145 -- Postcondition
1146 -- Precondition
1147 -- Test_Case
1149 else
1150 Analyze_Entry_Or_Subprogram_Contract (Stub_Id);
1151 end if;
1152 end Analyze_Subprogram_Body_Stub_Contract;
1154 ---------------------------
1155 -- Analyze_Task_Contract --
1156 ---------------------------
1158 procedure Analyze_Task_Contract (Task_Id : Entity_Id) is
1159 Items : constant Node_Id := Contract (Task_Id);
1160 Mode : SPARK_Mode_Type;
1161 Prag : Node_Id;
1163 begin
1164 -- Do not analyze a contract multiple times
1166 if Present (Items) then
1167 if Analyzed (Items) then
1168 return;
1169 else
1170 Set_Analyzed (Items);
1171 end if;
1172 end if;
1174 -- Due to the timing of contract analysis, delayed pragmas may be
1175 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1176 -- context. To remedy this, restore the original SPARK_Mode of the
1177 -- related task unit.
1179 Save_SPARK_Mode_And_Set (Task_Id, Mode);
1181 -- Analyze Global first, as Depends may mention items classified in the
1182 -- global categorization.
1184 Prag := Get_Pragma (Task_Id, Pragma_Global);
1186 if Present (Prag) then
1187 Analyze_Global_In_Decl_Part (Prag);
1188 end if;
1190 -- Depends must be analyzed after Global in order to see the modes of
1191 -- all global items.
1193 Prag := Get_Pragma (Task_Id, Pragma_Depends);
1195 if Present (Prag) then
1196 Analyze_Depends_In_Decl_Part (Prag);
1197 end if;
1199 -- Restore the SPARK_Mode of the enclosing context after all delayed
1200 -- pragmas have been analyzed.
1202 Restore_SPARK_Mode (Mode);
1203 end Analyze_Task_Contract;
1205 -----------------------------
1206 -- Create_Generic_Contract --
1207 -----------------------------
1209 procedure Create_Generic_Contract (Unit : Node_Id) is
1210 Templ : constant Node_Id := Original_Node (Unit);
1211 Templ_Id : constant Entity_Id := Defining_Entity (Templ);
1213 procedure Add_Generic_Contract_Pragma (Prag : Node_Id);
1214 -- Add a single contract-related source pragma Prag to the contract of
1215 -- generic template Templ_Id.
1217 ---------------------------------
1218 -- Add_Generic_Contract_Pragma --
1219 ---------------------------------
1221 procedure Add_Generic_Contract_Pragma (Prag : Node_Id) is
1222 Prag_Templ : Node_Id;
1224 begin
1225 -- Mark the pragma to prevent the premature capture of global
1226 -- references when capturing global references of the context
1227 -- (see Save_References_In_Pragma).
1229 Set_Is_Generic_Contract_Pragma (Prag);
1231 -- Pragmas that apply to a generic subprogram declaration are not
1232 -- part of the semantic structure of the generic template:
1234 -- generic
1235 -- procedure Example (Formal : Integer);
1236 -- pragma Precondition (Formal > 0);
1238 -- Create a generic template for such pragmas and link the template
1239 -- of the pragma with the generic template.
1241 if Nkind (Templ) = N_Generic_Subprogram_Declaration then
1242 Rewrite
1243 (Prag, Copy_Generic_Node (Prag, Empty, Instantiating => False));
1244 Prag_Templ := Original_Node (Prag);
1246 Set_Is_Generic_Contract_Pragma (Prag_Templ);
1247 Add_Contract_Item (Prag_Templ, Templ_Id);
1249 -- Otherwise link the pragma with the generic template
1251 else
1252 Add_Contract_Item (Prag, Templ_Id);
1253 end if;
1254 end Add_Generic_Contract_Pragma;
1256 -- Local variables
1258 Context : constant Node_Id := Parent (Unit);
1259 Decl : Node_Id := Empty;
1261 -- Start of processing for Create_Generic_Contract
1263 begin
1264 -- A generic package declaration carries contract-related source pragmas
1265 -- in its visible declarations.
1267 if Nkind (Templ) = N_Generic_Package_Declaration then
1268 Set_Ekind (Templ_Id, E_Generic_Package);
1270 if Present (Visible_Declarations (Specification (Templ))) then
1271 Decl := First (Visible_Declarations (Specification (Templ)));
1272 end if;
1274 -- A generic package body carries contract-related source pragmas in its
1275 -- declarations.
1277 elsif Nkind (Templ) = N_Package_Body then
1278 Set_Ekind (Templ_Id, E_Package_Body);
1280 if Present (Declarations (Templ)) then
1281 Decl := First (Declarations (Templ));
1282 end if;
1284 -- Generic subprogram declaration
1286 elsif Nkind (Templ) = N_Generic_Subprogram_Declaration then
1287 if Nkind (Specification (Templ)) = N_Function_Specification then
1288 Set_Ekind (Templ_Id, E_Generic_Function);
1289 else
1290 Set_Ekind (Templ_Id, E_Generic_Procedure);
1291 end if;
1293 -- When the generic subprogram acts as a compilation unit, inspect
1294 -- the Pragmas_After list for contract-related source pragmas.
1296 if Nkind (Context) = N_Compilation_Unit then
1297 if Present (Aux_Decls_Node (Context))
1298 and then Present (Pragmas_After (Aux_Decls_Node (Context)))
1299 then
1300 Decl := First (Pragmas_After (Aux_Decls_Node (Context)));
1301 end if;
1303 -- Otherwise inspect the successive declarations for contract-related
1304 -- source pragmas.
1306 else
1307 Decl := Next (Unit);
1308 end if;
1310 -- A generic subprogram body carries contract-related source pragmas in
1311 -- its declarations.
1313 elsif Nkind (Templ) = N_Subprogram_Body then
1314 Set_Ekind (Templ_Id, E_Subprogram_Body);
1316 if Present (Declarations (Templ)) then
1317 Decl := First (Declarations (Templ));
1318 end if;
1319 end if;
1321 -- Inspect the relevant declarations looking for contract-related source
1322 -- pragmas and add them to the contract of the generic unit.
1324 while Present (Decl) loop
1325 if Comes_From_Source (Decl) then
1326 if Nkind (Decl) = N_Pragma then
1328 -- The source pragma is a contract annotation
1330 if Is_Contract_Annotation (Decl) then
1331 Add_Generic_Contract_Pragma (Decl);
1332 end if;
1334 -- The region where a contract-related source pragma may appear
1335 -- ends with the first source non-pragma declaration or statement.
1337 else
1338 exit;
1339 end if;
1340 end if;
1342 Next (Decl);
1343 end loop;
1344 end Create_Generic_Contract;
1346 --------------------------------
1347 -- Expand_Subprogram_Contract --
1348 --------------------------------
1350 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id) is
1351 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
1352 Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
1354 procedure Add_Invariant_And_Predicate_Checks
1355 (Subp_Id : Entity_Id;
1356 Stmts : in out List_Id;
1357 Result : out Node_Id);
1358 -- Process the result of function Subp_Id (if applicable) and all its
1359 -- formals. Add invariant and predicate checks where applicable. The
1360 -- routine appends all the checks to list Stmts. If Subp_Id denotes a
1361 -- function, Result contains the entity of parameter _Result, to be
1362 -- used in the creation of procedure _Postconditions.
1364 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
1365 -- Append a node to a list. If there is no list, create a new one. When
1366 -- the item denotes a pragma, it is added to the list only when it is
1367 -- enabled.
1369 procedure Build_Postconditions_Procedure
1370 (Subp_Id : Entity_Id;
1371 Stmts : List_Id;
1372 Result : Entity_Id);
1373 -- Create the body of procedure _Postconditions which handles various
1374 -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
1375 -- of statements to be checked on exit. Parameter Result is the entity
1376 -- of parameter _Result when Subp_Id denotes a function.
1378 procedure Process_Contract_Cases (Stmts : in out List_Id);
1379 -- Process pragma Contract_Cases. This routine prepends items to the
1380 -- body declarations and appends items to list Stmts.
1382 procedure Process_Postconditions (Stmts : in out List_Id);
1383 -- Collect all [inherited] spec and body postconditions and accumulate
1384 -- their pragma Check equivalents in list Stmts.
1386 procedure Process_Preconditions;
1387 -- Collect all [inherited] spec and body preconditions and prepend their
1388 -- pragma Check equivalents to the declarations of the body.
1390 ----------------------------------------
1391 -- Add_Invariant_And_Predicate_Checks --
1392 ----------------------------------------
1394 procedure Add_Invariant_And_Predicate_Checks
1395 (Subp_Id : Entity_Id;
1396 Stmts : in out List_Id;
1397 Result : out Node_Id)
1399 procedure Add_Invariant_Access_Checks (Id : Entity_Id);
1400 -- Id denotes the return value of a function or a formal parameter.
1401 -- Add an invariant check if the type of Id is access to a type with
1402 -- invariants. The routine appends the generated code to Stmts.
1404 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
1405 -- Determine whether type Typ can benefit from invariant checks. To
1406 -- qualify, the type must have a non-null invariant procedure and
1407 -- subprogram Subp_Id must appear visible from the point of view of
1408 -- the type.
1410 ---------------------------------
1411 -- Add_Invariant_Access_Checks --
1412 ---------------------------------
1414 procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
1415 Loc : constant Source_Ptr := Sloc (Body_Decl);
1416 Ref : Node_Id;
1417 Typ : Entity_Id;
1419 begin
1420 Typ := Etype (Id);
1422 if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
1423 Typ := Designated_Type (Typ);
1425 if Invariant_Checks_OK (Typ) then
1426 Ref :=
1427 Make_Explicit_Dereference (Loc,
1428 Prefix => New_Occurrence_Of (Id, Loc));
1429 Set_Etype (Ref, Typ);
1431 -- Generate:
1432 -- if <Id> /= null then
1433 -- <invariant_call (<Ref>)>
1434 -- end if;
1436 Append_Enabled_Item
1437 (Item =>
1438 Make_If_Statement (Loc,
1439 Condition =>
1440 Make_Op_Ne (Loc,
1441 Left_Opnd => New_Occurrence_Of (Id, Loc),
1442 Right_Opnd => Make_Null (Loc)),
1443 Then_Statements => New_List (
1444 Make_Invariant_Call (Ref))),
1445 List => Stmts);
1446 end if;
1447 end if;
1448 end Add_Invariant_Access_Checks;
1450 -------------------------
1451 -- Invariant_Checks_OK --
1452 -------------------------
1454 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
1455 function Has_Public_Visibility_Of_Subprogram return Boolean;
1456 -- Determine whether type Typ has public visibility of subprogram
1457 -- Subp_Id.
1459 -----------------------------------------
1460 -- Has_Public_Visibility_Of_Subprogram --
1461 -----------------------------------------
1463 function Has_Public_Visibility_Of_Subprogram return Boolean is
1464 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
1466 begin
1467 -- An Initialization procedure must be considered visible even
1468 -- though it is internally generated.
1470 if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
1471 return True;
1473 elsif Ekind (Scope (Typ)) /= E_Package then
1474 return False;
1476 -- Internally generated code is never publicly visible except
1477 -- for a subprogram that is the implementation of an expression
1478 -- function. In that case the visibility is determined by the
1479 -- last check.
1481 elsif not Comes_From_Source (Subp_Decl)
1482 and then
1483 (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
1484 or else not
1485 Comes_From_Source (Defining_Entity (Subp_Decl)))
1486 then
1487 return False;
1489 -- Determine whether the subprogram is declared in the visible
1490 -- declarations of the package containing the type.
1492 else
1493 return List_Containing (Subp_Decl) =
1494 Visible_Declarations
1495 (Specification (Unit_Declaration_Node (Scope (Typ))));
1496 end if;
1497 end Has_Public_Visibility_Of_Subprogram;
1499 -- Start of processing for Invariant_Checks_OK
1501 begin
1502 return
1503 Has_Invariants (Typ)
1504 and then Present (Invariant_Procedure (Typ))
1505 and then not Has_Null_Body (Invariant_Procedure (Typ))
1506 and then Has_Public_Visibility_Of_Subprogram;
1507 end Invariant_Checks_OK;
1509 -- Local variables
1511 Loc : constant Source_Ptr := Sloc (Body_Decl);
1512 -- Source location of subprogram body contract
1514 Formal : Entity_Id;
1515 Typ : Entity_Id;
1517 -- Start of processing for Add_Invariant_And_Predicate_Checks
1519 begin
1520 Result := Empty;
1522 -- Process the result of a function
1524 if Ekind (Subp_Id) = E_Function then
1525 Typ := Etype (Subp_Id);
1527 -- Generate _Result which is used in procedure _Postconditions to
1528 -- verify the return value.
1530 Result := Make_Defining_Identifier (Loc, Name_uResult);
1531 Set_Etype (Result, Typ);
1533 -- Add an invariant check when the return type has invariants and
1534 -- the related function is visible to the outside.
1536 if Invariant_Checks_OK (Typ) then
1537 Append_Enabled_Item
1538 (Item =>
1539 Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
1540 List => Stmts);
1541 end if;
1543 -- Add an invariant check when the return type is an access to a
1544 -- type with invariants.
1546 Add_Invariant_Access_Checks (Result);
1547 end if;
1549 -- Add invariant and predicates for all formals that qualify
1551 Formal := First_Formal (Subp_Id);
1552 while Present (Formal) loop
1553 Typ := Etype (Formal);
1555 if Ekind (Formal) /= E_In_Parameter
1556 or else Is_Access_Type (Typ)
1557 then
1558 if Invariant_Checks_OK (Typ) then
1559 Append_Enabled_Item
1560 (Item =>
1561 Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
1562 List => Stmts);
1563 end if;
1565 Add_Invariant_Access_Checks (Formal);
1567 -- Note: we used to add predicate checks for OUT and IN OUT
1568 -- formals here, but that was misguided, since such checks are
1569 -- performed on the caller side, based on the predicate of the
1570 -- actual, rather than the predicate of the formal.
1572 end if;
1574 Next_Formal (Formal);
1575 end loop;
1576 end Add_Invariant_And_Predicate_Checks;
1578 -------------------------
1579 -- Append_Enabled_Item --
1580 -------------------------
1582 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
1583 begin
1584 -- Do not chain ignored or disabled pragmas
1586 if Nkind (Item) = N_Pragma
1587 and then (Is_Ignored (Item) or else Is_Disabled (Item))
1588 then
1589 null;
1591 -- Otherwise, add the item
1593 else
1594 if No (List) then
1595 List := New_List;
1596 end if;
1598 -- If the pragma is a conjunct in a composite postcondition, it
1599 -- has been processed in reverse order. In the postcondition body
1600 -- it must appear before the others.
1602 if Nkind (Item) = N_Pragma
1603 and then From_Aspect_Specification (Item)
1604 and then Split_PPC (Item)
1605 then
1606 Prepend (Item, List);
1607 else
1608 Append (Item, List);
1609 end if;
1610 end if;
1611 end Append_Enabled_Item;
1613 ------------------------------------
1614 -- Build_Postconditions_Procedure --
1615 ------------------------------------
1617 procedure Build_Postconditions_Procedure
1618 (Subp_Id : Entity_Id;
1619 Stmts : List_Id;
1620 Result : Entity_Id)
1622 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id);
1623 -- Insert node Stmt before the first source declaration of the
1624 -- related subprogram's body. If no such declaration exists, Stmt
1625 -- becomes the last declaration.
1627 --------------------------------------------
1628 -- Insert_Before_First_Source_Declaration --
1629 --------------------------------------------
1631 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id) is
1632 Decls : constant List_Id := Declarations (Body_Decl);
1633 Decl : Node_Id;
1635 begin
1636 -- Inspect the declarations of the related subprogram body looking
1637 -- for the first source declaration.
1639 if Present (Decls) then
1640 Decl := First (Decls);
1641 while Present (Decl) loop
1642 if Comes_From_Source (Decl) then
1643 Insert_Before (Decl, Stmt);
1644 return;
1645 end if;
1647 Next (Decl);
1648 end loop;
1650 -- If we get there, then the subprogram body lacks any source
1651 -- declarations. The body of _Postconditions now acts as the
1652 -- last declaration.
1654 Append (Stmt, Decls);
1656 -- Ensure that the body has a declaration list
1658 else
1659 Set_Declarations (Body_Decl, New_List (Stmt));
1660 end if;
1661 end Insert_Before_First_Source_Declaration;
1663 -- Local variables
1665 Loc : constant Source_Ptr := Sloc (Body_Decl);
1666 Params : List_Id := No_List;
1667 Proc_Bod : Node_Id;
1668 Proc_Decl : Node_Id;
1669 Proc_Id : Entity_Id;
1670 Proc_Spec : Node_Id;
1672 -- Start of processing for Build_Postconditions_Procedure
1674 begin
1675 -- Nothing to do if there are no actions to check on exit
1677 if No (Stmts) then
1678 return;
1679 end if;
1681 Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
1682 Set_Debug_Info_Needed (Proc_Id);
1683 Set_Postconditions_Proc (Subp_Id, Proc_Id);
1685 -- Force the front-end inlining of _Postconditions when generating C
1686 -- code, since its body may have references to itypes defined in the
1687 -- enclosing subprogram, which would cause problems for unnesting
1688 -- routines in the absence of inlining.
1690 if Generate_C_Code then
1691 Set_Has_Pragma_Inline (Proc_Id);
1692 Set_Has_Pragma_Inline_Always (Proc_Id);
1693 Set_Is_Inlined (Proc_Id);
1694 end if;
1696 -- The related subprogram is a function: create the specification of
1697 -- parameter _Result.
1699 if Present (Result) then
1700 Params := New_List (
1701 Make_Parameter_Specification (Loc,
1702 Defining_Identifier => Result,
1703 Parameter_Type =>
1704 New_Occurrence_Of (Etype (Result), Loc)));
1705 end if;
1707 Proc_Spec :=
1708 Make_Procedure_Specification (Loc,
1709 Defining_Unit_Name => Proc_Id,
1710 Parameter_Specifications => Params);
1712 Proc_Decl := Make_Subprogram_Declaration (Loc, Proc_Spec);
1714 -- Insert _Postconditions before the first source declaration of the
1715 -- body. This ensures that the body will not cause any premature
1716 -- freezing, as it may mention types:
1718 -- procedure Proc (Obj : Array_Typ) is
1719 -- procedure _postconditions is
1720 -- begin
1721 -- ... Obj ...
1722 -- end _postconditions;
1724 -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
1725 -- begin
1727 -- In the example above, Obj is of type T but the incorrect placement
1728 -- of _Postconditions will cause a crash in gigi due to an out-of-
1729 -- order reference. The body of _Postconditions must be placed after
1730 -- the declaration of Temp to preserve correct visibility.
1732 Insert_Before_First_Source_Declaration (Proc_Decl);
1733 Analyze (Proc_Decl);
1735 -- Set an explicit End_Label to override the sloc of the implicit
1736 -- RETURN statement, and prevent it from inheriting the sloc of one
1737 -- the postconditions: this would cause confusing debug info to be
1738 -- produced, interfering with coverage-analysis tools.
1740 Proc_Bod :=
1741 Make_Subprogram_Body (Loc,
1742 Specification =>
1743 Copy_Subprogram_Spec (Proc_Spec),
1744 Declarations => Empty_List,
1745 Handled_Statement_Sequence =>
1746 Make_Handled_Sequence_Of_Statements (Loc,
1747 Statements => Stmts,
1748 End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
1750 Insert_After_And_Analyze (Proc_Decl, Proc_Bod);
1751 end Build_Postconditions_Procedure;
1753 ----------------------------
1754 -- Process_Contract_Cases --
1755 ----------------------------
1757 procedure Process_Contract_Cases (Stmts : in out List_Id) is
1758 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id);
1759 -- Process pragma Contract_Cases for subprogram Subp_Id
1761 --------------------------------
1762 -- Process_Contract_Cases_For --
1763 --------------------------------
1765 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id) is
1766 Items : constant Node_Id := Contract (Subp_Id);
1767 Prag : Node_Id;
1769 begin
1770 if Present (Items) then
1771 Prag := Contract_Test_Cases (Items);
1772 while Present (Prag) loop
1773 if Pragma_Name (Prag) = Name_Contract_Cases then
1774 Expand_Pragma_Contract_Cases
1775 (CCs => Prag,
1776 Subp_Id => Subp_Id,
1777 Decls => Declarations (Body_Decl),
1778 Stmts => Stmts);
1779 end if;
1781 Prag := Next_Pragma (Prag);
1782 end loop;
1783 end if;
1784 end Process_Contract_Cases_For;
1786 -- Start of processing for Process_Contract_Cases
1788 begin
1789 Process_Contract_Cases_For (Body_Id);
1791 if Present (Spec_Id) then
1792 Process_Contract_Cases_For (Spec_Id);
1793 end if;
1794 end Process_Contract_Cases;
1796 ----------------------------
1797 -- Process_Postconditions --
1798 ----------------------------
1800 procedure Process_Postconditions (Stmts : in out List_Id) is
1801 procedure Process_Body_Postconditions (Post_Nam : Name_Id);
1802 -- Collect all [refined] postconditions of a specific kind denoted
1803 -- by Post_Nam that belong to the body, and generate pragma Check
1804 -- equivalents in list Stmts.
1806 procedure Process_Spec_Postconditions;
1807 -- Collect all [inherited] postconditions of the spec, and generate
1808 -- pragma Check equivalents in list Stmts.
1810 ---------------------------------
1811 -- Process_Body_Postconditions --
1812 ---------------------------------
1814 procedure Process_Body_Postconditions (Post_Nam : Name_Id) is
1815 Items : constant Node_Id := Contract (Body_Id);
1816 Unit_Decl : constant Node_Id := Parent (Body_Decl);
1817 Decl : Node_Id;
1818 Prag : Node_Id;
1820 begin
1821 -- Process the contract
1823 if Present (Items) then
1824 Prag := Pre_Post_Conditions (Items);
1825 while Present (Prag) loop
1826 if Pragma_Name (Prag) = Post_Nam then
1827 Append_Enabled_Item
1828 (Item => Build_Pragma_Check_Equivalent (Prag),
1829 List => Stmts);
1830 end if;
1832 Prag := Next_Pragma (Prag);
1833 end loop;
1834 end if;
1836 -- The subprogram body being processed is actually the proper body
1837 -- of a stub with a corresponding spec. The subprogram stub may
1838 -- carry a postcondition pragma, in which case it must be taken
1839 -- into account. The pragma appears after the stub.
1841 if Present (Spec_Id) and then Nkind (Unit_Decl) = N_Subunit then
1842 Decl := Next (Corresponding_Stub (Unit_Decl));
1843 while Present (Decl) loop
1845 -- Note that non-matching pragmas are skipped
1847 if Nkind (Decl) = N_Pragma then
1848 if Pragma_Name (Decl) = Post_Nam then
1849 Append_Enabled_Item
1850 (Item => Build_Pragma_Check_Equivalent (Decl),
1851 List => Stmts);
1852 end if;
1854 -- Skip internally generated code
1856 elsif not Comes_From_Source (Decl) then
1857 null;
1859 -- Postcondition pragmas are usually grouped together. There
1860 -- is no need to inspect the whole declarative list.
1862 else
1863 exit;
1864 end if;
1866 Next (Decl);
1867 end loop;
1868 end if;
1869 end Process_Body_Postconditions;
1871 ---------------------------------
1872 -- Process_Spec_Postconditions --
1873 ---------------------------------
1875 procedure Process_Spec_Postconditions is
1876 Subps : constant Subprogram_List :=
1877 Inherited_Subprograms (Spec_Id);
1878 Items : Node_Id;
1879 Prag : Node_Id;
1880 Subp_Id : Entity_Id;
1882 begin
1883 -- Process the contract
1885 Items := Contract (Spec_Id);
1887 if Present (Items) then
1888 Prag := Pre_Post_Conditions (Items);
1889 while Present (Prag) loop
1890 if Pragma_Name (Prag) = Name_Postcondition then
1891 Append_Enabled_Item
1892 (Item => Build_Pragma_Check_Equivalent (Prag),
1893 List => Stmts);
1894 end if;
1896 Prag := Next_Pragma (Prag);
1897 end loop;
1898 end if;
1900 -- Process the contracts of all inherited subprograms, looking for
1901 -- class-wide postconditions.
1903 for Index in Subps'Range loop
1904 Subp_Id := Subps (Index);
1905 Items := Contract (Subp_Id);
1907 if Present (Items) then
1908 Prag := Pre_Post_Conditions (Items);
1909 while Present (Prag) loop
1910 if Pragma_Name (Prag) = Name_Postcondition
1911 and then Class_Present (Prag)
1912 then
1913 Append_Enabled_Item
1914 (Item =>
1915 Build_Pragma_Check_Equivalent
1916 (Prag => Prag,
1917 Subp_Id => Spec_Id,
1918 Inher_Id => Subp_Id),
1919 List => Stmts);
1920 end if;
1922 Prag := Next_Pragma (Prag);
1923 end loop;
1924 end if;
1925 end loop;
1926 end Process_Spec_Postconditions;
1928 -- Start of processing for Process_Postconditions
1930 begin
1931 -- The processing of postconditions is done in reverse order (body
1932 -- first) to ensure the following arrangement:
1934 -- <refined postconditions from body>
1935 -- <postconditions from body>
1936 -- <postconditions from spec>
1937 -- <inherited postconditions>
1939 Process_Body_Postconditions (Name_Refined_Post);
1940 Process_Body_Postconditions (Name_Postcondition);
1942 if Present (Spec_Id) then
1943 Process_Spec_Postconditions;
1944 end if;
1945 end Process_Postconditions;
1947 ---------------------------
1948 -- Process_Preconditions --
1949 ---------------------------
1951 procedure Process_Preconditions is
1952 Class_Pre : Node_Id := Empty;
1953 -- The sole [inherited] class-wide precondition pragma that applies
1954 -- to the subprogram.
1956 Insert_Node : Node_Id := Empty;
1957 -- The insertion node after which all pragma Check equivalents are
1958 -- inserted.
1960 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean;
1961 -- Determine whether arbitrary declaration Decl denotes a renaming of
1962 -- a discriminant or protection field _object.
1964 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
1965 -- Merge two class-wide preconditions by "or else"-ing them. The
1966 -- changes are accumulated in parameter Into. Update the error
1967 -- message of Into.
1969 procedure Prepend_To_Decls (Item : Node_Id);
1970 -- Prepend a single item to the declarations of the subprogram body
1972 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
1973 -- Save a class-wide precondition into Class_Pre, or prepend a normal
1974 -- precondition to the declarations of the body and analyze it.
1976 procedure Process_Inherited_Preconditions;
1977 -- Collect all inherited class-wide preconditions and merge them into
1978 -- one big precondition to be evaluated as pragma Check.
1980 procedure Process_Preconditions_For (Subp_Id : Entity_Id);
1981 -- Collect all preconditions of subprogram Subp_Id and prepend their
1982 -- pragma Check equivalents to the declarations of the body.
1984 --------------------------
1985 -- Is_Prologue_Renaming --
1986 --------------------------
1988 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean is
1989 Nam : Node_Id;
1990 Obj : Entity_Id;
1991 Pref : Node_Id;
1992 Sel : Node_Id;
1994 begin
1995 if Nkind (Decl) = N_Object_Renaming_Declaration then
1996 Obj := Defining_Entity (Decl);
1997 Nam := Name (Decl);
1999 if Nkind (Nam) = N_Selected_Component then
2000 Pref := Prefix (Nam);
2001 Sel := Selector_Name (Nam);
2003 -- A discriminant renaming appears as
2004 -- Discr : constant ... := Prefix.Discr;
2006 if Ekind (Obj) = E_Constant
2007 and then Is_Entity_Name (Sel)
2008 and then Present (Entity (Sel))
2009 and then Ekind (Entity (Sel)) = E_Discriminant
2010 then
2011 return True;
2013 -- A protection field renaming appears as
2014 -- Prot : ... := _object._object;
2016 elsif Ekind (Obj) = E_Variable
2017 and then Nkind (Pref) = N_Identifier
2018 and then Chars (Pref) = Name_uObject
2019 and then Nkind (Sel) = N_Identifier
2020 and then Chars (Sel) = Name_uObject
2021 then
2022 return True;
2023 end if;
2024 end if;
2025 end if;
2027 return False;
2028 end Is_Prologue_Renaming;
2030 -------------------------
2031 -- Merge_Preconditions --
2032 -------------------------
2034 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
2035 function Expression_Arg (Prag : Node_Id) return Node_Id;
2036 -- Return the boolean expression argument of a precondition while
2037 -- updating its parentheses count for the subsequent merge.
2039 function Message_Arg (Prag : Node_Id) return Node_Id;
2040 -- Return the message argument of a precondition
2042 --------------------
2043 -- Expression_Arg --
2044 --------------------
2046 function Expression_Arg (Prag : Node_Id) return Node_Id is
2047 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2048 Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
2050 begin
2051 if Paren_Count (Arg) = 0 then
2052 Set_Paren_Count (Arg, 1);
2053 end if;
2055 return Arg;
2056 end Expression_Arg;
2058 -----------------
2059 -- Message_Arg --
2060 -----------------
2062 function Message_Arg (Prag : Node_Id) return Node_Id is
2063 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2064 begin
2065 return Get_Pragma_Arg (Last (Args));
2066 end Message_Arg;
2068 -- Local variables
2070 From_Expr : constant Node_Id := Expression_Arg (From);
2071 From_Msg : constant Node_Id := Message_Arg (From);
2072 Into_Expr : constant Node_Id := Expression_Arg (Into);
2073 Into_Msg : constant Node_Id := Message_Arg (Into);
2074 Loc : constant Source_Ptr := Sloc (Into);
2076 -- Start of processing for Merge_Preconditions
2078 begin
2079 -- Merge the two preconditions by "or else"-ing them
2081 Rewrite (Into_Expr,
2082 Make_Or_Else (Loc,
2083 Right_Opnd => Relocate_Node (Into_Expr),
2084 Left_Opnd => From_Expr));
2086 -- Merge the two error messages to produce a single message of the
2087 -- form:
2089 -- failed precondition from ...
2090 -- also failed inherited precondition from ...
2092 if not Exception_Locations_Suppressed then
2093 Start_String (Strval (Into_Msg));
2094 Store_String_Char (ASCII.LF);
2095 Store_String_Chars (" also ");
2096 Store_String_Chars (Strval (From_Msg));
2098 Set_Strval (Into_Msg, End_String);
2099 end if;
2100 end Merge_Preconditions;
2102 ----------------------
2103 -- Prepend_To_Decls --
2104 ----------------------
2106 procedure Prepend_To_Decls (Item : Node_Id) is
2107 Decls : List_Id := Declarations (Body_Decl);
2109 begin
2110 -- Ensure that the body has a declarative list
2112 if No (Decls) then
2113 Decls := New_List;
2114 Set_Declarations (Body_Decl, Decls);
2115 end if;
2117 Prepend_To (Decls, Item);
2118 end Prepend_To_Decls;
2120 ------------------------------
2121 -- Prepend_To_Decls_Or_Save --
2122 ------------------------------
2124 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
2125 Check_Prag : Node_Id;
2127 begin
2128 Check_Prag := Build_Pragma_Check_Equivalent (Prag);
2130 -- Save the sole class-wide precondition (if any) for the next
2131 -- step, where it will be merged with inherited preconditions.
2133 if Class_Present (Prag) then
2134 pragma Assert (No (Class_Pre));
2135 Class_Pre := Check_Prag;
2137 -- Accumulate the corresponding Check pragmas at the top of the
2138 -- declarations. Prepending the items ensures that they will be
2139 -- evaluated in their original order.
2141 else
2142 if Present (Insert_Node) then
2143 Insert_After (Insert_Node, Check_Prag);
2144 else
2145 Prepend_To_Decls (Check_Prag);
2146 end if;
2148 Analyze (Check_Prag);
2149 end if;
2150 end Prepend_To_Decls_Or_Save;
2152 -------------------------------------
2153 -- Process_Inherited_Preconditions --
2154 -------------------------------------
2156 procedure Process_Inherited_Preconditions is
2157 Subps : constant Subprogram_List :=
2158 Inherited_Subprograms (Spec_Id);
2159 Check_Prag : Node_Id;
2160 Items : Node_Id;
2161 Prag : Node_Id;
2162 Subp_Id : Entity_Id;
2164 begin
2165 -- Process the contracts of all inherited subprograms, looking for
2166 -- class-wide preconditions.
2168 for Index in Subps'Range loop
2169 Subp_Id := Subps (Index);
2170 Items := Contract (Subp_Id);
2172 if Present (Items) then
2173 Prag := Pre_Post_Conditions (Items);
2174 while Present (Prag) loop
2175 if Pragma_Name (Prag) = Name_Precondition
2176 and then Class_Present (Prag)
2177 then
2178 Check_Prag :=
2179 Build_Pragma_Check_Equivalent
2180 (Prag => Prag,
2181 Subp_Id => Spec_Id,
2182 Inher_Id => Subp_Id);
2184 -- The spec of an inherited subprogram already yielded
2185 -- a class-wide precondition. Merge the existing
2186 -- precondition with the current one using "or else".
2188 if Present (Class_Pre) then
2189 Merge_Preconditions (Check_Prag, Class_Pre);
2190 else
2191 Class_Pre := Check_Prag;
2192 end if;
2193 end if;
2195 Prag := Next_Pragma (Prag);
2196 end loop;
2197 end if;
2198 end loop;
2200 -- Add the merged class-wide preconditions
2202 if Present (Class_Pre) then
2203 Prepend_To_Decls (Class_Pre);
2204 Analyze (Class_Pre);
2205 end if;
2206 end Process_Inherited_Preconditions;
2208 -------------------------------
2209 -- Process_Preconditions_For --
2210 -------------------------------
2212 procedure Process_Preconditions_For (Subp_Id : Entity_Id) is
2213 Items : constant Node_Id := Contract (Subp_Id);
2214 Decl : Node_Id;
2215 Prag : Node_Id;
2216 Subp_Decl : Node_Id;
2218 begin
2219 -- Process the contract
2221 if Present (Items) then
2222 Prag := Pre_Post_Conditions (Items);
2223 while Present (Prag) loop
2224 if Pragma_Name (Prag) = Name_Precondition then
2225 Prepend_To_Decls_Or_Save (Prag);
2226 end if;
2228 Prag := Next_Pragma (Prag);
2229 end loop;
2230 end if;
2232 -- The subprogram declaration being processed is actually a body
2233 -- stub. The stub may carry a precondition pragma, in which case
2234 -- it must be taken into account. The pragma appears after the
2235 -- stub.
2237 Subp_Decl := Unit_Declaration_Node (Subp_Id);
2239 if Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
2241 -- Inspect the declarations following the body stub
2243 Decl := Next (Subp_Decl);
2244 while Present (Decl) loop
2246 -- Note that non-matching pragmas are skipped
2248 if Nkind (Decl) = N_Pragma then
2249 if Pragma_Name (Decl) = Name_Precondition then
2250 Prepend_To_Decls_Or_Save (Decl);
2251 end if;
2253 -- Skip internally generated code
2255 elsif not Comes_From_Source (Decl) then
2256 null;
2258 -- Preconditions are usually grouped together. There is no
2259 -- need to inspect the whole declarative list.
2261 else
2262 exit;
2263 end if;
2265 Next (Decl);
2266 end loop;
2267 end if;
2268 end Process_Preconditions_For;
2270 -- Local variables
2272 Decls : constant List_Id := Declarations (Body_Decl);
2273 Decl : Node_Id;
2275 -- Start of processing for Process_Preconditions
2277 begin
2278 -- Find the proper insertion point for all pragma Check equivalents
2280 if Present (Decls) then
2281 Decl := First (Decls);
2282 while Present (Decl) loop
2284 -- First source declaration terminates the search, because all
2285 -- preconditions must be evaluated prior to it, by definition.
2287 if Comes_From_Source (Decl) then
2288 exit;
2290 -- Certain internally generated object renamings such as those
2291 -- for discriminants and protection fields must be elaborated
2292 -- before the preconditions are evaluated, as their expressions
2293 -- may mention the discriminants.
2295 elsif Is_Prologue_Renaming (Decl) then
2296 Insert_Node := Decl;
2298 -- Otherwise the declaration does not come from source. This
2299 -- also terminates the search, because internal code may raise
2300 -- exceptions which should not preempt the preconditions.
2302 else
2303 exit;
2304 end if;
2306 Next (Decl);
2307 end loop;
2308 end if;
2310 -- The processing of preconditions is done in reverse order (body
2311 -- first), because each pragma Check equivalent is inserted at the
2312 -- top of the declarations. This ensures that the final order is
2313 -- consistent with following diagram:
2315 -- <inherited preconditions>
2316 -- <preconditions from spec>
2317 -- <preconditions from body>
2319 Process_Preconditions_For (Body_Id);
2321 if Present (Spec_Id) then
2322 Process_Preconditions_For (Spec_Id);
2323 Process_Inherited_Preconditions;
2324 end if;
2325 end Process_Preconditions;
2327 -- Local variables
2329 Restore_Scope : Boolean := False;
2330 Result : Entity_Id;
2331 Stmts : List_Id := No_List;
2332 Subp_Id : Entity_Id;
2334 -- Start of processing for Expand_Subprogram_Contract
2336 begin
2337 -- Obtain the entity of the initial declaration
2339 if Present (Spec_Id) then
2340 Subp_Id := Spec_Id;
2341 else
2342 Subp_Id := Body_Id;
2343 end if;
2345 -- Do not perform expansion activity when it is not needed
2347 if not Expander_Active then
2348 return;
2350 -- ASIS requires an unaltered tree
2352 elsif ASIS_Mode then
2353 return;
2355 -- GNATprove does not need the executable semantics of a contract
2357 elsif GNATprove_Mode then
2358 return;
2360 -- The contract of a generic subprogram or one declared in a generic
2361 -- context is not expanded, as the corresponding instance will provide
2362 -- the executable semantics of the contract.
2364 elsif Is_Generic_Subprogram (Subp_Id) or else Inside_A_Generic then
2365 return;
2367 -- All subprograms carry a contract, but for some it is not significant
2368 -- and should not be processed. This is a small optimization.
2370 elsif not Has_Significant_Contract (Subp_Id) then
2371 return;
2373 -- The contract of an ignored Ghost subprogram does not need expansion,
2374 -- because the subprogram and all calls to it will be removed.
2376 elsif Is_Ignored_Ghost_Entity (Subp_Id) then
2377 return;
2378 end if;
2380 -- Do not re-expand the same contract. This scenario occurs when a
2381 -- construct is rewritten into something else during its analysis
2382 -- (expression functions for instance).
2384 if Has_Expanded_Contract (Subp_Id) then
2385 return;
2387 -- Otherwise mark the subprogram
2389 else
2390 Set_Has_Expanded_Contract (Subp_Id);
2391 end if;
2393 -- Ensure that the formal parameters are visible when expanding all
2394 -- contract items.
2396 if not In_Open_Scopes (Subp_Id) then
2397 Restore_Scope := True;
2398 Push_Scope (Subp_Id);
2400 if Is_Generic_Subprogram (Subp_Id) then
2401 Install_Generic_Formals (Subp_Id);
2402 else
2403 Install_Formals (Subp_Id);
2404 end if;
2405 end if;
2407 -- The expansion of a subprogram contract involves the creation of Check
2408 -- pragmas to verify the contract assertions of the spec and body in a
2409 -- particular order. The order is as follows:
2411 -- function Example (...) return ... is
2412 -- procedure _Postconditions (...) is
2413 -- begin
2414 -- <refined postconditions from body>
2415 -- <postconditions from body>
2416 -- <postconditions from spec>
2417 -- <inherited postconditions>
2418 -- <contract case consequences>
2419 -- <invariant check of function result>
2420 -- <invariant and predicate checks of parameters>
2421 -- end _Postconditions;
2423 -- <inherited preconditions>
2424 -- <preconditions from spec>
2425 -- <preconditions from body>
2426 -- <contract case conditions>
2428 -- <source declarations>
2429 -- begin
2430 -- <source statements>
2432 -- _Preconditions (Result);
2433 -- return Result;
2434 -- end Example;
2436 -- Routine _Postconditions holds all contract assertions that must be
2437 -- verified on exit from the related subprogram.
2439 -- Step 1: Handle all preconditions. This action must come before the
2440 -- processing of pragma Contract_Cases because the pragma prepends items
2441 -- to the body declarations.
2443 Process_Preconditions;
2445 -- Step 2: Handle all postconditions. This action must come before the
2446 -- processing of pragma Contract_Cases because the pragma appends items
2447 -- to list Stmts.
2449 Process_Postconditions (Stmts);
2451 -- Step 3: Handle pragma Contract_Cases. This action must come before
2452 -- the processing of invariants and predicates because those append
2453 -- items to list Stmts.
2455 Process_Contract_Cases (Stmts);
2457 -- Step 4: Apply invariant and predicate checks on a function result and
2458 -- all formals. The resulting checks are accumulated in list Stmts.
2460 Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
2462 -- Step 5: Construct procedure _Postconditions
2464 Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
2466 if Restore_Scope then
2467 End_Scope;
2468 end if;
2469 end Expand_Subprogram_Contract;
2471 ---------------------------------
2472 -- Inherit_Subprogram_Contract --
2473 ---------------------------------
2475 procedure Inherit_Subprogram_Contract
2476 (Subp : Entity_Id;
2477 From_Subp : Entity_Id)
2479 procedure Inherit_Pragma (Prag_Id : Pragma_Id);
2480 -- Propagate a pragma denoted by Prag_Id from From_Subp's contract to
2481 -- Subp's contract.
2483 --------------------
2484 -- Inherit_Pragma --
2485 --------------------
2487 procedure Inherit_Pragma (Prag_Id : Pragma_Id) is
2488 Prag : constant Node_Id := Get_Pragma (From_Subp, Prag_Id);
2489 New_Prag : Node_Id;
2491 begin
2492 -- A pragma cannot be part of more than one First_Pragma/Next_Pragma
2493 -- chains, therefore the node must be replicated. The new pragma is
2494 -- flagged as inherited for distinction purposes.
2496 if Present (Prag) then
2497 New_Prag := New_Copy_Tree (Prag);
2498 Set_Is_Inherited_Pragma (New_Prag);
2500 Add_Contract_Item (New_Prag, Subp);
2501 end if;
2502 end Inherit_Pragma;
2504 -- Start of processing for Inherit_Subprogram_Contract
2506 begin
2507 -- Inheritance is carried out only when both entities are subprograms
2508 -- with contracts.
2510 if Is_Subprogram_Or_Generic_Subprogram (Subp)
2511 and then Is_Subprogram_Or_Generic_Subprogram (From_Subp)
2512 and then Present (Contract (From_Subp))
2513 then
2514 Inherit_Pragma (Pragma_Extensions_Visible);
2515 end if;
2516 end Inherit_Subprogram_Contract;
2518 -------------------------------------
2519 -- Instantiate_Subprogram_Contract --
2520 -------------------------------------
2522 procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id) is
2523 procedure Instantiate_Pragmas (First_Prag : Node_Id);
2524 -- Instantiate all contract-related source pragmas found in the list,
2525 -- starting with pragma First_Prag. Each instantiated pragma is added
2526 -- to list L.
2528 -------------------------
2529 -- Instantiate_Pragmas --
2530 -------------------------
2532 procedure Instantiate_Pragmas (First_Prag : Node_Id) is
2533 Inst_Prag : Node_Id;
2534 Prag : Node_Id;
2536 begin
2537 Prag := First_Prag;
2538 while Present (Prag) loop
2539 if Is_Generic_Contract_Pragma (Prag) then
2540 Inst_Prag :=
2541 Copy_Generic_Node (Prag, Empty, Instantiating => True);
2543 Set_Analyzed (Inst_Prag, False);
2544 Append_To (L, Inst_Prag);
2545 end if;
2547 Prag := Next_Pragma (Prag);
2548 end loop;
2549 end Instantiate_Pragmas;
2551 -- Local variables
2553 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2555 -- Start of processing for Instantiate_Subprogram_Contract
2557 begin
2558 if Present (Items) then
2559 Instantiate_Pragmas (Pre_Post_Conditions (Items));
2560 Instantiate_Pragmas (Contract_Test_Cases (Items));
2561 Instantiate_Pragmas (Classifications (Items));
2562 end if;
2563 end Instantiate_Subprogram_Contract;
2565 ----------------------------------------
2566 -- Save_Global_References_In_Contract --
2567 ----------------------------------------
2569 procedure Save_Global_References_In_Contract
2570 (Templ : Node_Id;
2571 Gen_Id : Entity_Id)
2573 procedure Save_Global_References_In_List (First_Prag : Node_Id);
2574 -- Save all global references in contract-related source pragmas found
2575 -- in the list, starting with pragma First_Prag.
2577 ------------------------------------
2578 -- Save_Global_References_In_List --
2579 ------------------------------------
2581 procedure Save_Global_References_In_List (First_Prag : Node_Id) is
2582 Prag : Node_Id;
2584 begin
2585 Prag := First_Prag;
2586 while Present (Prag) loop
2587 if Is_Generic_Contract_Pragma (Prag) then
2588 Save_Global_References (Prag);
2589 end if;
2591 Prag := Next_Pragma (Prag);
2592 end loop;
2593 end Save_Global_References_In_List;
2595 -- Local variables
2597 Items : constant Node_Id := Contract (Defining_Entity (Templ));
2599 -- Start of processing for Save_Global_References_In_Contract
2601 begin
2602 -- The entity of the analyzed generic copy must be on the scope stack
2603 -- to ensure proper detection of global references.
2605 Push_Scope (Gen_Id);
2607 if Permits_Aspect_Specifications (Templ)
2608 and then Has_Aspects (Templ)
2609 then
2610 Save_Global_References_In_Aspects (Templ);
2611 end if;
2613 if Present (Items) then
2614 Save_Global_References_In_List (Pre_Post_Conditions (Items));
2615 Save_Global_References_In_List (Contract_Test_Cases (Items));
2616 Save_Global_References_In_List (Classifications (Items));
2617 end if;
2619 Pop_Scope;
2620 end Save_Global_References_In_Contract;
2622 end Contracts;