2018-08-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / ada / contracts.adb
blob26a8d2894b2ea0ab704e1d517fba755934919c87
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-2018, 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 Debug; use Debug;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Prag; use Exp_Prag;
33 with Exp_Tss; use Exp_Tss;
34 with Exp_Util; use Exp_Util;
35 with Freeze; use Freeze;
36 with Namet; use Namet;
37 with Nlists; use Nlists;
38 with Nmake; use Nmake;
39 with Opt; use Opt;
40 with Sem; use Sem;
41 with Sem_Aux; use Sem_Aux;
42 with Sem_Ch6; use Sem_Ch6;
43 with Sem_Ch8; use Sem_Ch8;
44 with Sem_Ch12; use Sem_Ch12;
45 with Sem_Ch13; use Sem_Ch13;
46 with Sem_Disp; use Sem_Disp;
47 with Sem_Prag; use Sem_Prag;
48 with Sem_Util; use Sem_Util;
49 with Sinfo; use Sinfo;
50 with Snames; use Snames;
51 with Stand; use Stand;
52 with Stringt; use Stringt;
53 with SCIL_LL; use SCIL_LL;
54 with Tbuild; use Tbuild;
56 package body Contracts is
58 procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id);
59 -- Analyze all delayed pragmas chained on the contract of package
60 -- instantiation Inst_Id as if they appear at the end of a declarative
61 -- region. The pragmas in question are:
63 -- Part_Of
65 procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id);
66 -- (CodePeer): Subsidiary procedure to Analyze_Contracts which builds the
67 -- contract-only subprogram body of eligible subprograms found in L, adds
68 -- them to their corresponding list of declarations, and analyzes them.
70 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
71 -- Expand the contracts of a subprogram body and its correspoding spec (if
72 -- any). This routine processes all [refined] pre- and postconditions as
73 -- well as Contract_Cases, invariants and predicates. Body_Id denotes the
74 -- entity of the subprogram body.
76 -----------------------
77 -- Add_Contract_Item --
78 -----------------------
80 procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
81 Items : Node_Id := Contract (Id);
83 procedure Add_Classification;
84 -- Prepend Prag to the list of classifications
86 procedure Add_Contract_Test_Case;
87 -- Prepend Prag to the list of contract and test cases
89 procedure Add_Pre_Post_Condition;
90 -- Prepend Prag to the list of pre- and postconditions
92 ------------------------
93 -- Add_Classification --
94 ------------------------
96 procedure Add_Classification is
97 begin
98 Set_Next_Pragma (Prag, Classifications (Items));
99 Set_Classifications (Items, Prag);
100 end Add_Classification;
102 ----------------------------
103 -- Add_Contract_Test_Case --
104 ----------------------------
106 procedure Add_Contract_Test_Case is
107 begin
108 Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
109 Set_Contract_Test_Cases (Items, Prag);
110 end Add_Contract_Test_Case;
112 ----------------------------
113 -- Add_Pre_Post_Condition --
114 ----------------------------
116 procedure Add_Pre_Post_Condition is
117 begin
118 Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
119 Set_Pre_Post_Conditions (Items, Prag);
120 end Add_Pre_Post_Condition;
122 -- Local variables
124 -- A contract must contain only pragmas
126 pragma Assert (Nkind (Prag) = N_Pragma);
127 Prag_Nam : constant Name_Id := Pragma_Name (Prag);
129 -- Start of processing for Add_Contract_Item
131 begin
132 -- Create a new contract when adding the first item
134 if No (Items) then
135 Items := Make_Contract (Sloc (Id));
136 Set_Contract (Id, Items);
137 end if;
139 -- Constants, the applicable pragmas are:
140 -- Part_Of
142 if Ekind (Id) = E_Constant then
143 if Prag_Nam = Name_Part_Of then
144 Add_Classification;
146 -- The pragma is not a proper contract item
148 else
149 raise Program_Error;
150 end if;
152 -- Entry bodies, the applicable pragmas are:
153 -- Refined_Depends
154 -- Refined_Global
155 -- Refined_Post
157 elsif Is_Entry_Body (Id) then
158 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
159 Add_Classification;
161 elsif Prag_Nam = Name_Refined_Post then
162 Add_Pre_Post_Condition;
164 -- The pragma is not a proper contract item
166 else
167 raise Program_Error;
168 end if;
170 -- Entry or subprogram declarations, the applicable pragmas are:
171 -- Attach_Handler
172 -- Contract_Cases
173 -- Depends
174 -- Extensions_Visible
175 -- Global
176 -- Interrupt_Handler
177 -- Postcondition
178 -- Precondition
179 -- Test_Case
180 -- Volatile_Function
182 elsif Is_Entry_Declaration (Id)
183 or else Ekind_In (Id, E_Function,
184 E_Generic_Function,
185 E_Generic_Procedure,
186 E_Procedure)
187 then
188 if Nam_In (Prag_Nam, Name_Attach_Handler, Name_Interrupt_Handler)
189 and then Ekind_In (Id, E_Generic_Procedure, E_Procedure)
190 then
191 Add_Classification;
193 elsif Nam_In (Prag_Nam, Name_Depends,
194 Name_Extensions_Visible,
195 Name_Global)
196 then
197 Add_Classification;
199 elsif Prag_Nam = Name_Volatile_Function
200 and then Ekind_In (Id, E_Function, E_Generic_Function)
201 then
202 Add_Classification;
204 elsif Nam_In (Prag_Nam, Name_Contract_Cases, Name_Test_Case) then
205 Add_Contract_Test_Case;
207 elsif Nam_In (Prag_Nam, Name_Postcondition, Name_Precondition) then
208 Add_Pre_Post_Condition;
210 -- The pragma is not a proper contract item
212 else
213 raise Program_Error;
214 end if;
216 -- Packages or instantiations, the applicable pragmas are:
217 -- Abstract_States
218 -- Initial_Condition
219 -- Initializes
220 -- Part_Of (instantiation only)
222 elsif Ekind_In (Id, E_Generic_Package, E_Package) then
223 if Nam_In (Prag_Nam, Name_Abstract_State,
224 Name_Initial_Condition,
225 Name_Initializes)
226 then
227 Add_Classification;
229 -- Indicator Part_Of must be associated with a package instantiation
231 elsif Prag_Nam = Name_Part_Of and then Is_Generic_Instance (Id) then
232 Add_Classification;
234 -- The pragma is not a proper contract item
236 else
237 raise Program_Error;
238 end if;
240 -- Package bodies, the applicable pragmas are:
241 -- Refined_States
243 elsif Ekind (Id) = E_Package_Body then
244 if Prag_Nam = Name_Refined_State then
245 Add_Classification;
247 -- The pragma is not a proper contract item
249 else
250 raise Program_Error;
251 end if;
253 -- Protected units, the applicable pragmas are:
254 -- Part_Of
256 elsif Ekind (Id) = E_Protected_Type then
257 if Prag_Nam = Name_Part_Of then
258 Add_Classification;
260 -- The pragma is not a proper contract item
262 else
263 raise Program_Error;
264 end if;
266 -- Subprogram bodies, the applicable pragmas are:
267 -- Postcondition
268 -- Precondition
269 -- Refined_Depends
270 -- Refined_Global
271 -- Refined_Post
273 elsif Ekind (Id) = E_Subprogram_Body then
274 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
275 Add_Classification;
277 elsif Nam_In (Prag_Nam, Name_Postcondition,
278 Name_Precondition,
279 Name_Refined_Post)
280 then
281 Add_Pre_Post_Condition;
283 -- The pragma is not a proper contract item
285 else
286 raise Program_Error;
287 end if;
289 -- Task bodies, the applicable pragmas are:
290 -- Refined_Depends
291 -- Refined_Global
293 elsif Ekind (Id) = E_Task_Body then
294 if Nam_In (Prag_Nam, Name_Refined_Depends, Name_Refined_Global) then
295 Add_Classification;
297 -- The pragma is not a proper contract item
299 else
300 raise Program_Error;
301 end if;
303 -- Task units, the applicable pragmas are:
304 -- Depends
305 -- Global
306 -- Part_Of
308 elsif Ekind (Id) = E_Task_Type then
309 if Nam_In (Prag_Nam, Name_Depends, Name_Global, Name_Part_Of) then
310 Add_Classification;
312 -- The pragma is not a proper contract item
314 else
315 raise Program_Error;
316 end if;
318 -- Variables, the applicable pragmas are:
319 -- Async_Readers
320 -- Async_Writers
321 -- Constant_After_Elaboration
322 -- Depends
323 -- Effective_Reads
324 -- Effective_Writes
325 -- Global
326 -- Part_Of
328 elsif Ekind (Id) = E_Variable then
329 if Nam_In (Prag_Nam, Name_Async_Readers,
330 Name_Async_Writers,
331 Name_Constant_After_Elaboration,
332 Name_Depends,
333 Name_Effective_Reads,
334 Name_Effective_Writes,
335 Name_Global,
336 Name_Part_Of)
337 then
338 Add_Classification;
340 -- The pragma is not a proper contract item
342 else
343 raise Program_Error;
344 end if;
345 end if;
346 end Add_Contract_Item;
348 -----------------------
349 -- Analyze_Contracts --
350 -----------------------
352 procedure Analyze_Contracts (L : List_Id) is
353 Decl : Node_Id;
355 begin
356 if CodePeer_Mode and then Debug_Flag_Dot_KK then
357 Build_And_Analyze_Contract_Only_Subprograms (L);
358 end if;
360 Decl := First (L);
361 while Present (Decl) loop
363 -- Entry or subprogram declarations
365 if Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
366 N_Entry_Declaration,
367 N_Generic_Subprogram_Declaration,
368 N_Subprogram_Declaration)
369 then
370 declare
371 Subp_Id : constant Entity_Id := Defining_Entity (Decl);
373 begin
374 Analyze_Entry_Or_Subprogram_Contract (Subp_Id);
376 -- If analysis of a class-wide pre/postcondition indicates
377 -- that a class-wide clone is needed, analyze its declaration
378 -- now. Its body is created when the body of the original
379 -- operation is analyzed (and rewritten).
381 if Is_Subprogram (Subp_Id)
382 and then Present (Class_Wide_Clone (Subp_Id))
383 then
384 Analyze (Unit_Declaration_Node (Class_Wide_Clone (Subp_Id)));
385 end if;
386 end;
388 -- Entry or subprogram bodies
390 elsif Nkind_In (Decl, N_Entry_Body, N_Subprogram_Body) then
391 Analyze_Entry_Or_Subprogram_Body_Contract (Defining_Entity (Decl));
393 -- Objects
395 elsif Nkind (Decl) = N_Object_Declaration then
396 Analyze_Object_Contract (Defining_Entity (Decl));
398 -- Package instantiation
400 elsif Nkind (Decl) = N_Package_Instantiation then
401 Analyze_Package_Instantiation_Contract (Defining_Entity (Decl));
403 -- Protected units
405 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
406 N_Single_Protected_Declaration)
407 then
408 Analyze_Protected_Contract (Defining_Entity (Decl));
410 -- Subprogram body stubs
412 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
413 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
415 -- Task units
417 elsif Nkind_In (Decl, N_Single_Task_Declaration,
418 N_Task_Type_Declaration)
419 then
420 Analyze_Task_Contract (Defining_Entity (Decl));
422 -- For type declarations, we need to do the preanalysis of Iterable
423 -- aspect specifications.
425 -- Other type aspects need to be resolved here???
427 elsif Nkind (Decl) = N_Private_Type_Declaration
428 and then Present (Aspect_Specifications (Decl))
429 then
430 declare
431 E : constant Entity_Id := Defining_Identifier (Decl);
432 It : constant Node_Id := Find_Aspect (E, Aspect_Iterable);
434 begin
435 if Present (It) then
436 Validate_Iterable_Aspect (E, It);
437 end if;
438 end;
439 end if;
441 Next (Decl);
442 end loop;
443 end Analyze_Contracts;
445 -----------------------------------------------
446 -- Analyze_Entry_Or_Subprogram_Body_Contract --
447 -----------------------------------------------
449 -- WARNING: This routine manages SPARK regions. Return statements must be
450 -- replaced by gotos which jump to the end of the routine and restore the
451 -- SPARK mode.
453 procedure Analyze_Entry_Or_Subprogram_Body_Contract (Body_Id : Entity_Id) is
454 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
455 Items : constant Node_Id := Contract (Body_Id);
456 Spec_Id : constant Entity_Id := Unique_Defining_Entity (Body_Decl);
458 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
459 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
460 -- Save the SPARK_Mode-related data to restore on exit
462 begin
463 -- When a subprogram body declaration is illegal, its defining entity is
464 -- left unanalyzed. There is nothing left to do in this case because the
465 -- body lacks a contract, or even a proper Ekind.
467 if Ekind (Body_Id) = E_Void then
468 return;
470 -- Do not analyze a contract multiple times
472 elsif Present (Items) then
473 if Analyzed (Items) then
474 return;
475 else
476 Set_Analyzed (Items);
477 end if;
478 end if;
480 -- Due to the timing of contract analysis, delayed pragmas may be
481 -- subject to the wrong SPARK_Mode, usually that of the enclosing
482 -- context. To remedy this, restore the original SPARK_Mode of the
483 -- related subprogram body.
485 Set_SPARK_Mode (Body_Id);
487 -- Ensure that the contract cases or postconditions mention 'Result or
488 -- define a post-state.
490 Check_Result_And_Post_State (Body_Id);
492 -- A stand-alone nonvolatile function body cannot have an effectively
493 -- volatile formal parameter or return type (SPARK RM 7.1.3(9)). This
494 -- check is relevant only when SPARK_Mode is on, as it is not a standard
495 -- legality rule. The check is performed here because Volatile_Function
496 -- is processed after the analysis of the related subprogram body. The
497 -- check only applies to source subprograms and not to generated TSS
498 -- subprograms.
500 if SPARK_Mode = On
501 and then Ekind_In (Body_Id, E_Function, E_Generic_Function)
502 and then Comes_From_Source (Spec_Id)
503 and then not Is_Volatile_Function (Body_Id)
504 then
505 Check_Nonvolatile_Function_Profile (Body_Id);
506 end if;
508 -- Restore the SPARK_Mode of the enclosing context after all delayed
509 -- pragmas have been analyzed.
511 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
513 -- Capture all global references in a generic subprogram body now that
514 -- the contract has been analyzed.
516 if Is_Generic_Declaration_Or_Body (Body_Decl) then
517 Save_Global_References_In_Contract
518 (Templ => Original_Node (Body_Decl),
519 Gen_Id => Spec_Id);
520 end if;
522 -- Deal with preconditions, [refined] postconditions, Contract_Cases,
523 -- invariants and predicates associated with body and its spec. Do not
524 -- expand the contract of subprogram body stubs.
526 if Nkind (Body_Decl) = N_Subprogram_Body then
527 Expand_Subprogram_Contract (Body_Id);
528 end if;
529 end Analyze_Entry_Or_Subprogram_Body_Contract;
531 ------------------------------------------
532 -- Analyze_Entry_Or_Subprogram_Contract --
533 ------------------------------------------
535 -- WARNING: This routine manages SPARK regions. Return statements must be
536 -- replaced by gotos which jump to the end of the routine and restore the
537 -- SPARK mode.
539 procedure Analyze_Entry_Or_Subprogram_Contract
540 (Subp_Id : Entity_Id;
541 Freeze_Id : Entity_Id := Empty)
543 Items : constant Node_Id := Contract (Subp_Id);
544 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
546 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
547 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
548 -- Save the SPARK_Mode-related data to restore on exit
550 Skip_Assert_Exprs : constant Boolean :=
551 Ekind_In (Subp_Id, E_Entry, E_Entry_Family)
552 and then not ASIS_Mode
553 and then not GNATprove_Mode;
555 Depends : Node_Id := Empty;
556 Global : Node_Id := Empty;
557 Prag : Node_Id;
558 Prag_Nam : Name_Id;
560 begin
561 -- Do not analyze a contract multiple times
563 if Present (Items) then
564 if Analyzed (Items) then
565 return;
566 else
567 Set_Analyzed (Items);
568 end if;
569 end if;
571 -- Due to the timing of contract analysis, delayed pragmas may be
572 -- subject to the wrong SPARK_Mode, usually that of the enclosing
573 -- context. To remedy this, restore the original SPARK_Mode of the
574 -- related subprogram body.
576 Set_SPARK_Mode (Subp_Id);
578 -- All subprograms carry a contract, but for some it is not significant
579 -- and should not be processed.
581 if not Has_Significant_Contract (Subp_Id) then
582 null;
584 elsif Present (Items) then
586 -- Do not analyze the pre/postconditions of an entry declaration
587 -- unless annotating the original tree for ASIS or GNATprove. The
588 -- real analysis occurs when the pre/postconditons are relocated to
589 -- the contract wrapper procedure (see Build_Contract_Wrapper).
591 if Skip_Assert_Exprs then
592 null;
594 -- Otherwise analyze the pre/postconditions. Their expressions
595 -- might include references to types that are not frozen yet, in the
596 -- case where the body is a rewritten expression function that is a
597 -- completion, so freeze all types within before constructing the
598 -- contract code.
600 else
601 declare
602 Bod : Node_Id;
603 Freeze_Types : Boolean := False;
605 begin
606 if Present (Freeze_Id) then
607 Bod := Unit_Declaration_Node (Freeze_Id);
609 if Nkind (Bod) = N_Subprogram_Body
610 and then Was_Expression_Function (Bod)
611 and then Ekind (Subp_Id) = E_Function
612 and then Chars (Subp_Id) = Chars (Freeze_Id)
613 and then Subp_Id /= Freeze_Id
614 then
615 Freeze_Types := True;
616 end if;
617 end if;
619 Prag := Pre_Post_Conditions (Items);
620 while Present (Prag) loop
621 if Freeze_Types then
622 Freeze_Expr_Types
623 (Def_Id => Subp_Id,
624 Typ => Standard_Boolean,
625 Expr => Expression (Corresponding_Aspect (Prag)),
626 N => Bod);
627 end if;
629 Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
630 Prag := Next_Pragma (Prag);
631 end loop;
632 end;
633 end if;
635 -- Analyze contract-cases and test-cases
637 Prag := Contract_Test_Cases (Items);
638 while Present (Prag) loop
639 Prag_Nam := Pragma_Name (Prag);
641 if Prag_Nam = Name_Contract_Cases then
643 -- Do not analyze the contract cases of an entry declaration
644 -- unless annotating the original tree for ASIS or GNATprove.
645 -- The real analysis occurs when the contract cases are moved
646 -- to the contract wrapper procedure (Build_Contract_Wrapper).
648 if Skip_Assert_Exprs then
649 null;
651 -- Otherwise analyze the contract cases
653 else
654 Analyze_Contract_Cases_In_Decl_Part (Prag, Freeze_Id);
655 end if;
656 else
657 pragma Assert (Prag_Nam = Name_Test_Case);
658 Analyze_Test_Case_In_Decl_Part (Prag);
659 end if;
661 Prag := Next_Pragma (Prag);
662 end loop;
664 -- Analyze classification pragmas
666 Prag := Classifications (Items);
667 while Present (Prag) loop
668 Prag_Nam := Pragma_Name (Prag);
670 if Prag_Nam = Name_Depends then
671 Depends := Prag;
673 elsif Prag_Nam = Name_Global then
674 Global := Prag;
675 end if;
677 Prag := Next_Pragma (Prag);
678 end loop;
680 -- Analyze Global first, as Depends may mention items classified in
681 -- the global categorization.
683 if Present (Global) then
684 Analyze_Global_In_Decl_Part (Global);
685 end if;
687 -- Depends must be analyzed after Global in order to see the modes of
688 -- all global items.
690 if Present (Depends) then
691 Analyze_Depends_In_Decl_Part (Depends);
692 end if;
694 -- Ensure that the contract cases or postconditions mention 'Result
695 -- or define a post-state.
697 Check_Result_And_Post_State (Subp_Id);
698 end if;
700 -- A nonvolatile function cannot have an effectively volatile formal
701 -- parameter or return type (SPARK RM 7.1.3(9)). This check is relevant
702 -- only when SPARK_Mode is on, as it is not a standard legality rule.
703 -- The check is performed here because pragma Volatile_Function is
704 -- processed after the analysis of the related subprogram declaration.
706 if SPARK_Mode = On
707 and then Ekind_In (Subp_Id, E_Function, E_Generic_Function)
708 and then Comes_From_Source (Subp_Id)
709 and then not Is_Volatile_Function (Subp_Id)
710 then
711 Check_Nonvolatile_Function_Profile (Subp_Id);
712 end if;
714 -- Restore the SPARK_Mode of the enclosing context after all delayed
715 -- pragmas have been analyzed.
717 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
719 -- Capture all global references in a generic subprogram now that the
720 -- contract has been analyzed.
722 if Is_Generic_Declaration_Or_Body (Subp_Decl) then
723 Save_Global_References_In_Contract
724 (Templ => Original_Node (Subp_Decl),
725 Gen_Id => Subp_Id);
726 end if;
727 end Analyze_Entry_Or_Subprogram_Contract;
729 -----------------------------
730 -- Analyze_Object_Contract --
731 -----------------------------
733 -- WARNING: This routine manages SPARK regions. Return statements must be
734 -- replaced by gotos which jump to the end of the routine and restore the
735 -- SPARK mode.
737 procedure Analyze_Object_Contract
738 (Obj_Id : Entity_Id;
739 Freeze_Id : Entity_Id := Empty)
741 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
743 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
744 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
745 -- Save the SPARK_Mode-related data to restore on exit
747 AR_Val : Boolean := False;
748 AW_Val : Boolean := False;
749 ER_Val : Boolean := False;
750 EW_Val : Boolean := False;
751 Items : Node_Id;
752 Prag : Node_Id;
753 Ref_Elmt : Elmt_Id;
754 Seen : Boolean := False;
756 begin
757 -- The loop parameter in an element iterator over a formal container
758 -- is declared with an object declaration, but no contracts apply.
760 if Ekind (Obj_Id) = E_Loop_Parameter then
761 return;
762 end if;
764 -- Do not analyze a contract multiple times
766 Items := Contract (Obj_Id);
768 if Present (Items) then
769 if Analyzed (Items) then
770 return;
771 else
772 Set_Analyzed (Items);
773 end if;
774 end if;
776 -- The anonymous object created for a single concurrent type inherits
777 -- the SPARK_Mode from the type. Due to the timing of contract analysis,
778 -- delayed pragmas may be subject to the wrong SPARK_Mode, usually that
779 -- of the enclosing context. To remedy this, restore the original mode
780 -- of the related anonymous object.
782 if Is_Single_Concurrent_Object (Obj_Id)
783 and then Present (SPARK_Pragma (Obj_Id))
784 then
785 Set_SPARK_Mode (Obj_Id);
786 end if;
788 -- Constant-related checks
790 if Ekind (Obj_Id) = E_Constant then
792 -- Analyze indicator Part_Of
794 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
796 -- Check whether the lack of indicator Part_Of agrees with the
797 -- placement of the constant with respect to the state space.
799 if No (Prag) then
800 Check_Missing_Part_Of (Obj_Id);
801 end if;
803 -- A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
804 -- This check is relevant only when SPARK_Mode is on, as it is not
805 -- a standard Ada legality rule. Internally-generated constants that
806 -- map generic formals to actuals in instantiations are allowed to
807 -- be volatile.
809 if SPARK_Mode = On
810 and then Comes_From_Source (Obj_Id)
811 and then Is_Effectively_Volatile (Obj_Id)
812 and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
813 then
814 Error_Msg_N ("constant cannot be volatile", Obj_Id);
815 end if;
817 -- Variable-related checks
819 else pragma Assert (Ekind (Obj_Id) = E_Variable);
821 -- Analyze all external properties
823 Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
825 if Present (Prag) then
826 Analyze_External_Property_In_Decl_Part (Prag, AR_Val);
827 Seen := True;
828 end if;
830 Prag := Get_Pragma (Obj_Id, Pragma_Async_Writers);
832 if Present (Prag) then
833 Analyze_External_Property_In_Decl_Part (Prag, AW_Val);
834 Seen := True;
835 end if;
837 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Reads);
839 if Present (Prag) then
840 Analyze_External_Property_In_Decl_Part (Prag, ER_Val);
841 Seen := True;
842 end if;
844 Prag := Get_Pragma (Obj_Id, Pragma_Effective_Writes);
846 if Present (Prag) then
847 Analyze_External_Property_In_Decl_Part (Prag, EW_Val);
848 Seen := True;
849 end if;
851 -- Verify the mutual interaction of the various external properties
853 if Seen then
854 Check_External_Properties (Obj_Id, AR_Val, AW_Val, ER_Val, EW_Val);
855 end if;
857 -- The anonymous object created for a single concurrent type carries
858 -- pragmas Depends and Globat of the type.
860 if Is_Single_Concurrent_Object (Obj_Id) then
862 -- Analyze Global first, as Depends may mention items classified
863 -- in the global categorization.
865 Prag := Get_Pragma (Obj_Id, Pragma_Global);
867 if Present (Prag) then
868 Analyze_Global_In_Decl_Part (Prag);
869 end if;
871 -- Depends must be analyzed after Global in order to see the modes
872 -- of all global items.
874 Prag := Get_Pragma (Obj_Id, Pragma_Depends);
876 if Present (Prag) then
877 Analyze_Depends_In_Decl_Part (Prag);
878 end if;
879 end if;
881 Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
883 -- Analyze indicator Part_Of
885 if Present (Prag) then
886 Analyze_Part_Of_In_Decl_Part (Prag, Freeze_Id);
888 -- The variable is a constituent of a single protected/task type
889 -- and behaves as a component of the type. Verify that references
890 -- to the variable occur within the definition or body of the type
891 -- (SPARK RM 9.3).
893 if Present (Encapsulating_State (Obj_Id))
894 and then Is_Single_Concurrent_Object
895 (Encapsulating_State (Obj_Id))
896 and then Present (Part_Of_References (Obj_Id))
897 then
898 Ref_Elmt := First_Elmt (Part_Of_References (Obj_Id));
899 while Present (Ref_Elmt) loop
900 Check_Part_Of_Reference (Obj_Id, Node (Ref_Elmt));
901 Next_Elmt (Ref_Elmt);
902 end loop;
903 end if;
905 -- Otherwise check whether the lack of indicator Part_Of agrees with
906 -- the placement of the variable with respect to the state space.
908 else
909 Check_Missing_Part_Of (Obj_Id);
910 end if;
912 -- The following checks are relevant only when SPARK_Mode is on, as
913 -- they are not standard Ada legality rules. Internally generated
914 -- temporaries are ignored.
916 if SPARK_Mode = On and then Comes_From_Source (Obj_Id) then
917 if Is_Effectively_Volatile (Obj_Id) then
919 -- The declaration of an effectively volatile object must
920 -- appear at the library level (SPARK RM 7.1.3(3), C.6(6)).
922 if not Is_Library_Level_Entity (Obj_Id) then
923 Error_Msg_N
924 ("volatile variable & must be declared at library level "
925 & "(SPARK RM 7.1.3(3))", Obj_Id);
927 -- An object of a discriminated type cannot be effectively
928 -- volatile except for protected objects (SPARK RM 7.1.3(5)).
930 elsif Has_Discriminants (Obj_Typ)
931 and then not Is_Protected_Type (Obj_Typ)
932 then
933 Error_Msg_N
934 ("discriminated object & cannot be volatile", Obj_Id);
935 end if;
937 -- The object is not effectively volatile
939 else
940 -- A non-effectively volatile object cannot have effectively
941 -- volatile components (SPARK RM 7.1.3(6)).
943 if not Is_Effectively_Volatile (Obj_Id)
944 and then Has_Volatile_Component (Obj_Typ)
945 then
946 Error_Msg_N
947 ("non-volatile object & cannot have volatile components",
948 Obj_Id);
949 end if;
950 end if;
951 end if;
952 end if;
954 -- Common checks
956 if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
958 -- A Ghost object cannot be of a type that yields a synchronized
959 -- object (SPARK RM 6.9(19)).
961 if Yields_Synchronized_Object (Obj_Typ) then
962 Error_Msg_N ("ghost object & cannot be synchronized", Obj_Id);
964 -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and
965 -- SPARK RM 6.9(19)).
967 elsif Is_Effectively_Volatile (Obj_Id) then
968 Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
970 -- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)).
971 -- One exception to this is the object that represents the dispatch
972 -- table of a Ghost tagged type, as the symbol needs to be exported.
974 elsif Is_Exported (Obj_Id) then
975 Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
977 elsif Is_Imported (Obj_Id) then
978 Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
979 end if;
980 end if;
982 -- Restore the SPARK_Mode of the enclosing context after all delayed
983 -- pragmas have been analyzed.
985 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
986 end Analyze_Object_Contract;
988 -----------------------------------
989 -- Analyze_Package_Body_Contract --
990 -----------------------------------
992 -- WARNING: This routine manages SPARK regions. Return statements must be
993 -- replaced by gotos which jump to the end of the routine and restore the
994 -- SPARK mode.
996 procedure Analyze_Package_Body_Contract
997 (Body_Id : Entity_Id;
998 Freeze_Id : Entity_Id := Empty)
1000 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
1001 Items : constant Node_Id := Contract (Body_Id);
1002 Spec_Id : constant Entity_Id := Spec_Entity (Body_Id);
1004 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
1005 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
1006 -- Save the SPARK_Mode-related data to restore on exit
1008 Ref_State : Node_Id;
1010 begin
1011 -- Do not analyze a contract multiple times
1013 if Present (Items) then
1014 if Analyzed (Items) then
1015 return;
1016 else
1017 Set_Analyzed (Items);
1018 end if;
1019 end if;
1021 -- Due to the timing of contract analysis, delayed pragmas may be
1022 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1023 -- context. To remedy this, restore the original SPARK_Mode of the
1024 -- related package body.
1026 Set_SPARK_Mode (Body_Id);
1028 Ref_State := Get_Pragma (Body_Id, Pragma_Refined_State);
1030 -- The analysis of pragma Refined_State detects whether the spec has
1031 -- abstract states available for refinement.
1033 if Present (Ref_State) then
1034 Analyze_Refined_State_In_Decl_Part (Ref_State, Freeze_Id);
1035 end if;
1037 -- Restore the SPARK_Mode of the enclosing context after all delayed
1038 -- pragmas have been analyzed.
1040 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
1042 -- Capture all global references in a generic package body now that the
1043 -- contract has been analyzed.
1045 if Is_Generic_Declaration_Or_Body (Body_Decl) then
1046 Save_Global_References_In_Contract
1047 (Templ => Original_Node (Body_Decl),
1048 Gen_Id => Spec_Id);
1049 end if;
1050 end Analyze_Package_Body_Contract;
1052 ------------------------------
1053 -- Analyze_Package_Contract --
1054 ------------------------------
1056 -- WARNING: This routine manages SPARK regions. Return statements must be
1057 -- replaced by gotos which jump to the end of the routine and restore the
1058 -- SPARK mode.
1060 procedure Analyze_Package_Contract (Pack_Id : Entity_Id) is
1061 Items : constant Node_Id := Contract (Pack_Id);
1062 Pack_Decl : constant Node_Id := Unit_Declaration_Node (Pack_Id);
1064 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
1065 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
1066 -- Save the SPARK_Mode-related data to restore on exit
1068 Init : Node_Id := Empty;
1069 Init_Cond : Node_Id := Empty;
1070 Prag : Node_Id;
1071 Prag_Nam : Name_Id;
1073 begin
1074 -- Do not analyze a contract multiple times
1076 if Present (Items) then
1077 if Analyzed (Items) then
1078 return;
1079 else
1080 Set_Analyzed (Items);
1081 end if;
1082 end if;
1084 -- Due to the timing of contract analysis, delayed pragmas may be
1085 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1086 -- context. To remedy this, restore the original SPARK_Mode of the
1087 -- related package.
1089 Set_SPARK_Mode (Pack_Id);
1091 if Present (Items) then
1093 -- Locate and store pragmas Initial_Condition and Initializes, since
1094 -- their order of analysis matters.
1096 Prag := Classifications (Items);
1097 while Present (Prag) loop
1098 Prag_Nam := Pragma_Name (Prag);
1100 if Prag_Nam = Name_Initial_Condition then
1101 Init_Cond := Prag;
1103 elsif Prag_Nam = Name_Initializes then
1104 Init := Prag;
1105 end if;
1107 Prag := Next_Pragma (Prag);
1108 end loop;
1110 -- Analyze the initialization-related pragmas. Initializes must come
1111 -- before Initial_Condition due to item dependencies.
1113 if Present (Init) then
1114 Analyze_Initializes_In_Decl_Part (Init);
1115 end if;
1117 if Present (Init_Cond) then
1118 Analyze_Initial_Condition_In_Decl_Part (Init_Cond);
1119 end if;
1120 end if;
1122 -- Restore the SPARK_Mode of the enclosing context after all delayed
1123 -- pragmas have been analyzed.
1125 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
1127 -- Capture all global references in a generic package now that the
1128 -- contract has been analyzed.
1130 if Is_Generic_Declaration_Or_Body (Pack_Decl) then
1131 Save_Global_References_In_Contract
1132 (Templ => Original_Node (Pack_Decl),
1133 Gen_Id => Pack_Id);
1134 end if;
1135 end Analyze_Package_Contract;
1137 --------------------------------------------
1138 -- Analyze_Package_Instantiation_Contract --
1139 --------------------------------------------
1141 -- WARNING: This routine manages SPARK regions. Return statements must be
1142 -- replaced by gotos which jump to the end of the routine and restore the
1143 -- SPARK mode.
1145 procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id) is
1146 Inst_Spec : constant Node_Id :=
1147 Instance_Spec (Unit_Declaration_Node (Inst_Id));
1149 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
1150 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
1151 -- Save the SPARK_Mode-related data to restore on exit
1153 Pack_Id : Entity_Id;
1154 Prag : Node_Id;
1156 begin
1157 -- Nothing to do when the package instantiation is erroneous or left
1158 -- partially decorated.
1160 if No (Inst_Spec) then
1161 return;
1162 end if;
1164 Pack_Id := Defining_Entity (Inst_Spec);
1165 Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
1167 -- Due to the timing of contract analysis, delayed pragmas may be
1168 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1169 -- context. To remedy this, restore the original SPARK_Mode of the
1170 -- related package.
1172 Set_SPARK_Mode (Pack_Id);
1174 -- Check whether the lack of indicator Part_Of agrees with the placement
1175 -- of the package instantiation with respect to the state space. Nested
1176 -- package instantiations do not need to be checked because they inherit
1177 -- Part_Of indicator of the outermost package instantiation (see routine
1178 -- Propagate_Part_Of in Sem_Prag).
1180 if In_Instance then
1181 null;
1183 elsif No (Prag) then
1184 Check_Missing_Part_Of (Pack_Id);
1185 end if;
1187 -- Restore the SPARK_Mode of the enclosing context after all delayed
1188 -- pragmas have been analyzed.
1190 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
1191 end Analyze_Package_Instantiation_Contract;
1193 --------------------------------
1194 -- Analyze_Protected_Contract --
1195 --------------------------------
1197 procedure Analyze_Protected_Contract (Prot_Id : Entity_Id) is
1198 Items : constant Node_Id := Contract (Prot_Id);
1200 begin
1201 -- Do not analyze a contract multiple times
1203 if Present (Items) then
1204 if Analyzed (Items) then
1205 return;
1206 else
1207 Set_Analyzed (Items);
1208 end if;
1209 end if;
1210 end Analyze_Protected_Contract;
1212 -------------------------------------------
1213 -- Analyze_Subprogram_Body_Stub_Contract --
1214 -------------------------------------------
1216 procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id) is
1217 Stub_Decl : constant Node_Id := Parent (Parent (Stub_Id));
1218 Spec_Id : constant Entity_Id := Corresponding_Spec_Of_Stub (Stub_Decl);
1220 begin
1221 -- A subprogram body stub may act as its own spec or as the completion
1222 -- of a previous declaration. Depending on the context, the contract of
1223 -- the stub may contain two sets of pragmas.
1225 -- The stub is a completion, the applicable pragmas are:
1226 -- Refined_Depends
1227 -- Refined_Global
1229 if Present (Spec_Id) then
1230 Analyze_Entry_Or_Subprogram_Body_Contract (Stub_Id);
1232 -- The stub acts as its own spec, the applicable pragmas are:
1233 -- Contract_Cases
1234 -- Depends
1235 -- Global
1236 -- Postcondition
1237 -- Precondition
1238 -- Test_Case
1240 else
1241 Analyze_Entry_Or_Subprogram_Contract (Stub_Id);
1242 end if;
1243 end Analyze_Subprogram_Body_Stub_Contract;
1245 ---------------------------
1246 -- Analyze_Task_Contract --
1247 ---------------------------
1249 -- WARNING: This routine manages SPARK regions. Return statements must be
1250 -- replaced by gotos which jump to the end of the routine and restore the
1251 -- SPARK mode.
1253 procedure Analyze_Task_Contract (Task_Id : Entity_Id) is
1254 Items : constant Node_Id := Contract (Task_Id);
1256 Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
1257 Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
1258 -- Save the SPARK_Mode-related data to restore on exit
1260 Prag : Node_Id;
1262 begin
1263 -- Do not analyze a contract multiple times
1265 if Present (Items) then
1266 if Analyzed (Items) then
1267 return;
1268 else
1269 Set_Analyzed (Items);
1270 end if;
1271 end if;
1273 -- Due to the timing of contract analysis, delayed pragmas may be
1274 -- subject to the wrong SPARK_Mode, usually that of the enclosing
1275 -- context. To remedy this, restore the original SPARK_Mode of the
1276 -- related task unit.
1278 Set_SPARK_Mode (Task_Id);
1280 -- Analyze Global first, as Depends may mention items classified in the
1281 -- global categorization.
1283 Prag := Get_Pragma (Task_Id, Pragma_Global);
1285 if Present (Prag) then
1286 Analyze_Global_In_Decl_Part (Prag);
1287 end if;
1289 -- Depends must be analyzed after Global in order to see the modes of
1290 -- all global items.
1292 Prag := Get_Pragma (Task_Id, Pragma_Depends);
1294 if Present (Prag) then
1295 Analyze_Depends_In_Decl_Part (Prag);
1296 end if;
1298 -- Restore the SPARK_Mode of the enclosing context after all delayed
1299 -- pragmas have been analyzed.
1301 Restore_SPARK_Mode (Saved_SM, Saved_SMP);
1302 end Analyze_Task_Contract;
1304 -------------------------------------------------
1305 -- Build_And_Analyze_Contract_Only_Subprograms --
1306 -------------------------------------------------
1308 procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id) is
1309 procedure Analyze_Contract_Only_Subprograms;
1310 -- Analyze the contract-only subprograms of L
1312 procedure Append_Contract_Only_Subprograms (Subp_List : List_Id);
1313 -- Append the contract-only bodies of Subp_List to its declarations list
1315 function Build_Contract_Only_Subprogram (E : Entity_Id) return Node_Id;
1316 -- If E is an entity for a non-imported subprogram specification with
1317 -- pre/postconditions and we are compiling with CodePeer mode, then
1318 -- this procedure will create a wrapper to help Gnat2scil process its
1319 -- contracts. Return Empty if the wrapper cannot be built.
1321 function Build_Contract_Only_Subprograms (L : List_Id) return List_Id;
1322 -- Build the contract-only subprograms of all eligible subprograms found
1323 -- in list L.
1325 function Has_Private_Declarations (N : Node_Id) return Boolean;
1326 -- Return True for package specs, task definitions, and protected type
1327 -- definitions whose list of private declarations is not empty.
1329 ---------------------------------------
1330 -- Analyze_Contract_Only_Subprograms --
1331 ---------------------------------------
1333 procedure Analyze_Contract_Only_Subprograms is
1334 procedure Analyze_Contract_Only_Bodies;
1335 -- Analyze all the contract-only bodies of L
1337 ----------------------------------
1338 -- Analyze_Contract_Only_Bodies --
1339 ----------------------------------
1341 procedure Analyze_Contract_Only_Bodies is
1342 Decl : Node_Id;
1344 begin
1345 Decl := First (L);
1346 while Present (Decl) loop
1347 if Nkind (Decl) = N_Subprogram_Body
1348 and then Is_Contract_Only_Body
1349 (Defining_Unit_Name (Specification (Decl)))
1350 then
1351 Analyze (Decl);
1352 end if;
1354 Next (Decl);
1355 end loop;
1356 end Analyze_Contract_Only_Bodies;
1358 -- Start of processing for Analyze_Contract_Only_Subprograms
1360 begin
1361 if Ekind (Current_Scope) /= E_Package then
1362 Analyze_Contract_Only_Bodies;
1364 else
1365 declare
1366 Pkg_Spec : constant Node_Id :=
1367 Package_Specification (Current_Scope);
1369 begin
1370 if not Has_Private_Declarations (Pkg_Spec) then
1371 Analyze_Contract_Only_Bodies;
1373 -- For packages with private declarations, the contract-only
1374 -- bodies of subprograms defined in the visible part of the
1375 -- package are added to its private declarations (to ensure
1376 -- that they do not cause premature freezing of types and also
1377 -- that they are analyzed with proper visibility). Hence they
1378 -- will be analyzed later.
1380 elsif Visible_Declarations (Pkg_Spec) = L then
1381 null;
1383 elsif Private_Declarations (Pkg_Spec) = L then
1384 Analyze_Contract_Only_Bodies;
1385 end if;
1386 end;
1387 end if;
1388 end Analyze_Contract_Only_Subprograms;
1390 --------------------------------------
1391 -- Append_Contract_Only_Subprograms --
1392 --------------------------------------
1394 procedure Append_Contract_Only_Subprograms (Subp_List : List_Id) is
1395 begin
1396 if No (Subp_List) then
1397 return;
1398 end if;
1400 if Ekind (Current_Scope) /= E_Package then
1401 Append_List (Subp_List, To => L);
1403 else
1404 declare
1405 Pkg_Spec : constant Node_Id :=
1406 Package_Specification (Current_Scope);
1408 begin
1409 if not Has_Private_Declarations (Pkg_Spec) then
1410 Append_List (Subp_List, To => L);
1412 -- If the package has private declarations then append them to
1413 -- its private declarations; they will be analyzed when the
1414 -- contracts of its private declarations are analyzed.
1416 else
1417 Append_List
1418 (List => Subp_List,
1419 To => Private_Declarations (Pkg_Spec));
1420 end if;
1421 end;
1422 end if;
1423 end Append_Contract_Only_Subprograms;
1425 ------------------------------------
1426 -- Build_Contract_Only_Subprogram --
1427 ------------------------------------
1429 -- This procedure takes care of building a wrapper to generate better
1430 -- analysis results in the case of a call to a subprogram whose body
1431 -- is unavailable to CodePeer but whose specification includes Pre/Post
1432 -- conditions. The body might be unavailable for any of a number or
1433 -- reasons (it is imported, the .adb file is simply missing, or the
1434 -- subprogram might be subject to an Annotate (CodePeer, Skip_Analysis)
1435 -- pragma). The built subprogram has the following contents:
1436 -- * check preconditions
1437 -- * call the subprogram
1438 -- * check postconditions
1440 function Build_Contract_Only_Subprogram (E : Entity_Id) return Node_Id is
1441 Loc : constant Source_Ptr := Sloc (E);
1443 Missing_Body_Name : constant Name_Id :=
1444 New_External_Name (Chars (E), "__missing_body");
1446 function Build_Missing_Body_Decls return List_Id;
1447 -- Build the declaration of the missing body subprogram and its
1448 -- corresponding pragma Import.
1450 function Build_Missing_Body_Subprogram_Call return Node_Id;
1451 -- Build the call to the missing body subprogram
1453 function Skip_Contract_Only_Subprogram (E : Entity_Id) return Boolean;
1454 -- Return True for cases where the wrapper is not needed or we cannot
1455 -- build it.
1457 ------------------------------
1458 -- Build_Missing_Body_Decls --
1459 ------------------------------
1461 function Build_Missing_Body_Decls return List_Id is
1462 Spec : constant Node_Id := Declaration_Node (E);
1463 Decl : Node_Id;
1464 Prag : Node_Id;
1466 begin
1467 Decl :=
1468 Make_Subprogram_Declaration (Loc, Copy_Subprogram_Spec (Spec));
1469 Set_Chars (Defining_Entity (Decl), Missing_Body_Name);
1471 Prag :=
1472 Make_Pragma (Loc,
1473 Chars => Name_Import,
1474 Pragma_Argument_Associations => New_List (
1475 Make_Pragma_Argument_Association (Loc,
1476 Expression => Make_Identifier (Loc, Name_Ada)),
1478 Make_Pragma_Argument_Association (Loc,
1479 Expression => Make_Identifier (Loc, Missing_Body_Name))));
1481 return New_List (Decl, Prag);
1482 end Build_Missing_Body_Decls;
1484 ----------------------------------------
1485 -- Build_Missing_Body_Subprogram_Call --
1486 ----------------------------------------
1488 function Build_Missing_Body_Subprogram_Call return Node_Id is
1489 Forml : Entity_Id;
1490 Parms : List_Id;
1492 begin
1493 Parms := New_List;
1495 -- Build parameter list that we need
1497 Forml := First_Formal (E);
1498 while Present (Forml) loop
1499 Append_To (Parms, Make_Identifier (Loc, Chars (Forml)));
1500 Next_Formal (Forml);
1501 end loop;
1503 -- Build the call to the missing body subprogram
1505 if Ekind_In (E, E_Function, E_Generic_Function) then
1506 return
1507 Make_Simple_Return_Statement (Loc,
1508 Expression =>
1509 Make_Function_Call (Loc,
1510 Name =>
1511 Make_Identifier (Loc, Missing_Body_Name),
1512 Parameter_Associations => Parms));
1514 else
1515 return
1516 Make_Procedure_Call_Statement (Loc,
1517 Name =>
1518 Make_Identifier (Loc, Missing_Body_Name),
1519 Parameter_Associations => Parms);
1520 end if;
1521 end Build_Missing_Body_Subprogram_Call;
1523 -----------------------------------
1524 -- Skip_Contract_Only_Subprogram --
1525 -----------------------------------
1527 function Skip_Contract_Only_Subprogram
1528 (E : Entity_Id) return Boolean
1530 function Depends_On_Enclosing_Private_Type return Boolean;
1531 -- Return True if some formal of E (or its return type) are
1532 -- private types defined in an enclosing package.
1534 function Some_Enclosing_Package_Has_Private_Decls return Boolean;
1535 -- Return True if some enclosing package of the current scope has
1536 -- private declarations.
1538 ---------------------------------------
1539 -- Depends_On_Enclosing_Private_Type --
1540 ---------------------------------------
1542 function Depends_On_Enclosing_Private_Type return Boolean is
1543 function Defined_In_Enclosing_Package
1544 (Typ : Entity_Id) return Boolean;
1545 -- Return True if Typ is an entity defined in an enclosing
1546 -- package of the current scope.
1548 ----------------------------------
1549 -- Defined_In_Enclosing_Package --
1550 ----------------------------------
1552 function Defined_In_Enclosing_Package
1553 (Typ : Entity_Id) return Boolean
1555 Scop : Entity_Id := Scope (Current_Scope);
1557 begin
1558 while Scop /= Scope (Typ)
1559 and then not Is_Compilation_Unit (Scop)
1560 loop
1561 Scop := Scope (Scop);
1562 end loop;
1564 return Scop = Scope (Typ);
1565 end Defined_In_Enclosing_Package;
1567 -- Local variables
1569 Param_E : Entity_Id;
1570 Typ : Entity_Id;
1572 -- Start of processing for Depends_On_Enclosing_Private_Type
1574 begin
1575 Param_E := First_Entity (E);
1576 while Present (Param_E) loop
1577 Typ := Etype (Param_E);
1579 if Is_Private_Type (Typ)
1580 and then Defined_In_Enclosing_Package (Typ)
1581 then
1582 return True;
1583 end if;
1585 Next_Entity (Param_E);
1586 end loop;
1588 return
1589 Ekind (E) = E_Function
1590 and then Is_Private_Type (Etype (E))
1591 and then Defined_In_Enclosing_Package (Etype (E));
1592 end Depends_On_Enclosing_Private_Type;
1594 ----------------------------------------------
1595 -- Some_Enclosing_Package_Has_Private_Decls --
1596 ----------------------------------------------
1598 function Some_Enclosing_Package_Has_Private_Decls return Boolean is
1599 Scop : Entity_Id := Current_Scope;
1600 Pkg_Spec : Node_Id := Package_Specification (Scop);
1602 begin
1603 loop
1604 if Ekind (Scop) = E_Package
1605 and then Has_Private_Declarations
1606 (Package_Specification (Scop))
1607 then
1608 Pkg_Spec := Package_Specification (Scop);
1609 end if;
1611 exit when Is_Compilation_Unit (Scop);
1612 Scop := Scope (Scop);
1613 end loop;
1615 return Pkg_Spec /= Package_Specification (Current_Scope);
1616 end Some_Enclosing_Package_Has_Private_Decls;
1618 -- Start of processing for Skip_Contract_Only_Subprogram
1620 begin
1621 if not CodePeer_Mode
1622 or else Inside_A_Generic
1623 or else not Is_Subprogram (E)
1624 or else Is_Abstract_Subprogram (E)
1625 or else Is_Imported (E)
1626 or else No (Contract (E))
1627 or else No (Pre_Post_Conditions (Contract (E)))
1628 or else Is_Contract_Only_Body (E)
1629 or else Convention (E) = Convention_Protected
1630 then
1631 return True;
1633 -- We do not support building the contract-only subprogram if E
1634 -- is a subprogram declared in a nested package that has some
1635 -- formal or return type depending on a private type defined in
1636 -- an enclosing package.
1638 elsif Ekind (Current_Scope) = E_Package
1639 and then Some_Enclosing_Package_Has_Private_Decls
1640 and then Depends_On_Enclosing_Private_Type
1641 then
1642 if Debug_Flag_Dot_KK then
1643 declare
1644 Saved_Mode : constant Warning_Mode_Type := Warning_Mode;
1646 begin
1647 -- Warnings are disabled by default under CodePeer_Mode
1648 -- (see switch-c). Enable them temporarily.
1650 Warning_Mode := Normal;
1651 Error_Msg_N
1652 ("cannot generate contract-only subprogram?", E);
1653 Warning_Mode := Saved_Mode;
1654 end;
1655 end if;
1657 return True;
1658 end if;
1660 return False;
1661 end Skip_Contract_Only_Subprogram;
1663 -- Start of processing for Build_Contract_Only_Subprogram
1665 begin
1666 -- Test cases where the wrapper is not needed and cases where we
1667 -- cannot build it.
1669 if Skip_Contract_Only_Subprogram (E) then
1670 return Empty;
1671 end if;
1673 -- Note on calls to Copy_Separate_Tree. The trees we are copying
1674 -- here are fully analyzed, but we definitely want fully syntactic
1675 -- unanalyzed trees in the body we construct, so that the analysis
1676 -- generates the right visibility, and that is exactly what the
1677 -- calls to Copy_Separate_Tree give us.
1679 declare
1680 Name : constant Name_Id :=
1681 New_External_Name (Chars (E), "__contract_only");
1682 Id : Entity_Id;
1683 Bod : Node_Id;
1685 begin
1686 Bod :=
1687 Make_Subprogram_Body (Loc,
1688 Specification =>
1689 Copy_Subprogram_Spec (Declaration_Node (E)),
1690 Declarations =>
1691 Build_Missing_Body_Decls,
1692 Handled_Statement_Sequence =>
1693 Make_Handled_Sequence_Of_Statements (Loc,
1694 Statements => New_List (
1695 Build_Missing_Body_Subprogram_Call),
1696 End_Label => Make_Identifier (Loc, Name)));
1698 Id := Defining_Unit_Name (Specification (Bod));
1700 -- Copy only the pre/postconditions of the original contract
1701 -- since it is what we need, but also because pragmas stored in
1702 -- the other fields have N_Pragmas with N_Aspect_Specifications
1703 -- that reference their associated pragma (thus causing an endless
1704 -- loop when trying to copy the subtree).
1706 declare
1707 New_Contract : constant Node_Id := Make_Contract (Sloc (E));
1709 begin
1710 Set_Pre_Post_Conditions (New_Contract,
1711 Copy_Separate_Tree (Pre_Post_Conditions (Contract (E))));
1712 Set_Contract (Id, New_Contract);
1713 end;
1715 -- Fix the name of this new subprogram and link the original
1716 -- subprogram with its Contract_Only_Body subprogram.
1718 Set_Chars (Id, Name);
1719 Set_Is_Contract_Only_Body (Id);
1720 Set_Contract_Only_Body (E, Id);
1722 return Bod;
1723 end;
1724 end Build_Contract_Only_Subprogram;
1726 -------------------------------------
1727 -- Build_Contract_Only_Subprograms --
1728 -------------------------------------
1730 function Build_Contract_Only_Subprograms (L : List_Id) return List_Id is
1731 Decl : Node_Id;
1732 New_Subp : Node_Id;
1733 Result : List_Id := No_List;
1734 Subp_Id : Entity_Id;
1736 begin
1737 Decl := First (L);
1738 while Present (Decl) loop
1739 if Nkind (Decl) = N_Subprogram_Declaration then
1740 Subp_Id := Defining_Unit_Name (Specification (Decl));
1741 New_Subp := Build_Contract_Only_Subprogram (Subp_Id);
1743 if Present (New_Subp) then
1744 if No (Result) then
1745 Result := New_List;
1746 end if;
1748 Append_To (Result, New_Subp);
1749 end if;
1750 end if;
1752 Next (Decl);
1753 end loop;
1755 return Result;
1756 end Build_Contract_Only_Subprograms;
1758 ------------------------------
1759 -- Has_Private_Declarations --
1760 ------------------------------
1762 function Has_Private_Declarations (N : Node_Id) return Boolean is
1763 begin
1764 if not Nkind_In (N, N_Package_Specification,
1765 N_Protected_Definition,
1766 N_Task_Definition)
1767 then
1768 return False;
1769 else
1770 return
1771 Present (Private_Declarations (N))
1772 and then Is_Non_Empty_List (Private_Declarations (N));
1773 end if;
1774 end Has_Private_Declarations;
1776 -- Local variables
1778 Subp_List : List_Id;
1780 -- Start of processing for Build_And_Analyze_Contract_Only_Subprograms
1782 begin
1783 Subp_List := Build_Contract_Only_Subprograms (L);
1784 Append_Contract_Only_Subprograms (Subp_List);
1785 Analyze_Contract_Only_Subprograms;
1786 end Build_And_Analyze_Contract_Only_Subprograms;
1788 -----------------------------
1789 -- Create_Generic_Contract --
1790 -----------------------------
1792 procedure Create_Generic_Contract (Unit : Node_Id) is
1793 Templ : constant Node_Id := Original_Node (Unit);
1794 Templ_Id : constant Entity_Id := Defining_Entity (Templ);
1796 procedure Add_Generic_Contract_Pragma (Prag : Node_Id);
1797 -- Add a single contract-related source pragma Prag to the contract of
1798 -- generic template Templ_Id.
1800 ---------------------------------
1801 -- Add_Generic_Contract_Pragma --
1802 ---------------------------------
1804 procedure Add_Generic_Contract_Pragma (Prag : Node_Id) is
1805 Prag_Templ : Node_Id;
1807 begin
1808 -- Mark the pragma to prevent the premature capture of global
1809 -- references when capturing global references of the context
1810 -- (see Save_References_In_Pragma).
1812 Set_Is_Generic_Contract_Pragma (Prag);
1814 -- Pragmas that apply to a generic subprogram declaration are not
1815 -- part of the semantic structure of the generic template:
1817 -- generic
1818 -- procedure Example (Formal : Integer);
1819 -- pragma Precondition (Formal > 0);
1821 -- Create a generic template for such pragmas and link the template
1822 -- of the pragma with the generic template.
1824 if Nkind (Templ) = N_Generic_Subprogram_Declaration then
1825 Rewrite
1826 (Prag, Copy_Generic_Node (Prag, Empty, Instantiating => False));
1827 Prag_Templ := Original_Node (Prag);
1829 Set_Is_Generic_Contract_Pragma (Prag_Templ);
1830 Add_Contract_Item (Prag_Templ, Templ_Id);
1832 -- Otherwise link the pragma with the generic template
1834 else
1835 Add_Contract_Item (Prag, Templ_Id);
1836 end if;
1837 end Add_Generic_Contract_Pragma;
1839 -- Local variables
1841 Context : constant Node_Id := Parent (Unit);
1842 Decl : Node_Id := Empty;
1844 -- Start of processing for Create_Generic_Contract
1846 begin
1847 -- A generic package declaration carries contract-related source pragmas
1848 -- in its visible declarations.
1850 if Nkind (Templ) = N_Generic_Package_Declaration then
1851 Set_Ekind (Templ_Id, E_Generic_Package);
1853 if Present (Visible_Declarations (Specification (Templ))) then
1854 Decl := First (Visible_Declarations (Specification (Templ)));
1855 end if;
1857 -- A generic package body carries contract-related source pragmas in its
1858 -- declarations.
1860 elsif Nkind (Templ) = N_Package_Body then
1861 Set_Ekind (Templ_Id, E_Package_Body);
1863 if Present (Declarations (Templ)) then
1864 Decl := First (Declarations (Templ));
1865 end if;
1867 -- Generic subprogram declaration
1869 elsif Nkind (Templ) = N_Generic_Subprogram_Declaration then
1870 if Nkind (Specification (Templ)) = N_Function_Specification then
1871 Set_Ekind (Templ_Id, E_Generic_Function);
1872 else
1873 Set_Ekind (Templ_Id, E_Generic_Procedure);
1874 end if;
1876 -- When the generic subprogram acts as a compilation unit, inspect
1877 -- the Pragmas_After list for contract-related source pragmas.
1879 if Nkind (Context) = N_Compilation_Unit then
1880 if Present (Aux_Decls_Node (Context))
1881 and then Present (Pragmas_After (Aux_Decls_Node (Context)))
1882 then
1883 Decl := First (Pragmas_After (Aux_Decls_Node (Context)));
1884 end if;
1886 -- Otherwise inspect the successive declarations for contract-related
1887 -- source pragmas.
1889 else
1890 Decl := Next (Unit);
1891 end if;
1893 -- A generic subprogram body carries contract-related source pragmas in
1894 -- its declarations.
1896 elsif Nkind (Templ) = N_Subprogram_Body then
1897 Set_Ekind (Templ_Id, E_Subprogram_Body);
1899 if Present (Declarations (Templ)) then
1900 Decl := First (Declarations (Templ));
1901 end if;
1902 end if;
1904 -- Inspect the relevant declarations looking for contract-related source
1905 -- pragmas and add them to the contract of the generic unit.
1907 while Present (Decl) loop
1908 if Comes_From_Source (Decl) then
1909 if Nkind (Decl) = N_Pragma then
1911 -- The source pragma is a contract annotation
1913 if Is_Contract_Annotation (Decl) then
1914 Add_Generic_Contract_Pragma (Decl);
1915 end if;
1917 -- The region where a contract-related source pragma may appear
1918 -- ends with the first source non-pragma declaration or statement.
1920 else
1921 exit;
1922 end if;
1923 end if;
1925 Next (Decl);
1926 end loop;
1927 end Create_Generic_Contract;
1929 --------------------------------
1930 -- Expand_Subprogram_Contract --
1931 --------------------------------
1933 procedure Expand_Subprogram_Contract (Body_Id : Entity_Id) is
1934 Body_Decl : constant Node_Id := Unit_Declaration_Node (Body_Id);
1935 Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
1937 procedure Add_Invariant_And_Predicate_Checks
1938 (Subp_Id : Entity_Id;
1939 Stmts : in out List_Id;
1940 Result : out Node_Id);
1941 -- Process the result of function Subp_Id (if applicable) and all its
1942 -- formals. Add invariant and predicate checks where applicable. The
1943 -- routine appends all the checks to list Stmts. If Subp_Id denotes a
1944 -- function, Result contains the entity of parameter _Result, to be
1945 -- used in the creation of procedure _Postconditions.
1947 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
1948 -- Append a node to a list. If there is no list, create a new one. When
1949 -- the item denotes a pragma, it is added to the list only when it is
1950 -- enabled.
1952 procedure Build_Postconditions_Procedure
1953 (Subp_Id : Entity_Id;
1954 Stmts : List_Id;
1955 Result : Entity_Id);
1956 -- Create the body of procedure _Postconditions which handles various
1957 -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
1958 -- of statements to be checked on exit. Parameter Result is the entity
1959 -- of parameter _Result when Subp_Id denotes a function.
1961 procedure Process_Contract_Cases (Stmts : in out List_Id);
1962 -- Process pragma Contract_Cases. This routine prepends items to the
1963 -- body declarations and appends items to list Stmts.
1965 procedure Process_Postconditions (Stmts : in out List_Id);
1966 -- Collect all [inherited] spec and body postconditions and accumulate
1967 -- their pragma Check equivalents in list Stmts.
1969 procedure Process_Preconditions;
1970 -- Collect all [inherited] spec and body preconditions and prepend their
1971 -- pragma Check equivalents to the declarations of the body.
1973 ----------------------------------------
1974 -- Add_Invariant_And_Predicate_Checks --
1975 ----------------------------------------
1977 procedure Add_Invariant_And_Predicate_Checks
1978 (Subp_Id : Entity_Id;
1979 Stmts : in out List_Id;
1980 Result : out Node_Id)
1982 procedure Add_Invariant_Access_Checks (Id : Entity_Id);
1983 -- Id denotes the return value of a function or a formal parameter.
1984 -- Add an invariant check if the type of Id is access to a type with
1985 -- invariants. The routine appends the generated code to Stmts.
1987 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
1988 -- Determine whether type Typ can benefit from invariant checks. To
1989 -- qualify, the type must have a non-null invariant procedure and
1990 -- subprogram Subp_Id must appear visible from the point of view of
1991 -- the type.
1993 ---------------------------------
1994 -- Add_Invariant_Access_Checks --
1995 ---------------------------------
1997 procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
1998 Loc : constant Source_Ptr := Sloc (Body_Decl);
1999 Ref : Node_Id;
2000 Typ : Entity_Id;
2002 begin
2003 Typ := Etype (Id);
2005 if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
2006 Typ := Designated_Type (Typ);
2008 if Invariant_Checks_OK (Typ) then
2009 Ref :=
2010 Make_Explicit_Dereference (Loc,
2011 Prefix => New_Occurrence_Of (Id, Loc));
2012 Set_Etype (Ref, Typ);
2014 -- Generate:
2015 -- if <Id> /= null then
2016 -- <invariant_call (<Ref>)>
2017 -- end if;
2019 Append_Enabled_Item
2020 (Item =>
2021 Make_If_Statement (Loc,
2022 Condition =>
2023 Make_Op_Ne (Loc,
2024 Left_Opnd => New_Occurrence_Of (Id, Loc),
2025 Right_Opnd => Make_Null (Loc)),
2026 Then_Statements => New_List (
2027 Make_Invariant_Call (Ref))),
2028 List => Stmts);
2029 end if;
2030 end if;
2031 end Add_Invariant_Access_Checks;
2033 -------------------------
2034 -- Invariant_Checks_OK --
2035 -------------------------
2037 function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
2038 function Has_Public_Visibility_Of_Subprogram return Boolean;
2039 -- Determine whether type Typ has public visibility of subprogram
2040 -- Subp_Id.
2042 -----------------------------------------
2043 -- Has_Public_Visibility_Of_Subprogram --
2044 -----------------------------------------
2046 function Has_Public_Visibility_Of_Subprogram return Boolean is
2047 Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
2049 begin
2050 -- An Initialization procedure must be considered visible even
2051 -- though it is internally generated.
2053 if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
2054 return True;
2056 elsif Ekind (Scope (Typ)) /= E_Package then
2057 return False;
2059 -- Internally generated code is never publicly visible except
2060 -- for a subprogram that is the implementation of an expression
2061 -- function. In that case the visibility is determined by the
2062 -- last check.
2064 elsif not Comes_From_Source (Subp_Decl)
2065 and then
2066 (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
2067 or else not
2068 Comes_From_Source (Defining_Entity (Subp_Decl)))
2069 then
2070 return False;
2072 -- Determine whether the subprogram is declared in the visible
2073 -- declarations of the package containing the type, or in the
2074 -- visible declaration of a child unit of that package.
2076 else
2077 declare
2078 Decls : constant List_Id :=
2079 List_Containing (Subp_Decl);
2080 Subp_Scope : constant Entity_Id :=
2081 Scope (Defining_Entity (Subp_Decl));
2082 Typ_Scope : constant Entity_Id := Scope (Typ);
2084 begin
2085 return
2086 Decls = Visible_Declarations
2087 (Specification (Unit_Declaration_Node (Typ_Scope)))
2089 or else
2090 (Ekind (Subp_Scope) = E_Package
2091 and then Typ_Scope /= Subp_Scope
2092 and then Is_Child_Unit (Subp_Scope)
2093 and then
2094 Is_Ancestor_Package (Typ_Scope, Subp_Scope)
2095 and then
2096 Decls = Visible_Declarations
2097 (Specification
2098 (Unit_Declaration_Node (Subp_Scope))));
2099 end;
2100 end if;
2101 end Has_Public_Visibility_Of_Subprogram;
2103 -- Start of processing for Invariant_Checks_OK
2105 begin
2106 return
2107 Has_Invariants (Typ)
2108 and then Present (Invariant_Procedure (Typ))
2109 and then not Has_Null_Body (Invariant_Procedure (Typ))
2110 and then Has_Public_Visibility_Of_Subprogram;
2111 end Invariant_Checks_OK;
2113 -- Local variables
2115 Loc : constant Source_Ptr := Sloc (Body_Decl);
2116 -- Source location of subprogram body contract
2118 Formal : Entity_Id;
2119 Typ : Entity_Id;
2121 -- Start of processing for Add_Invariant_And_Predicate_Checks
2123 begin
2124 Result := Empty;
2126 -- Process the result of a function
2128 if Ekind (Subp_Id) = E_Function then
2129 Typ := Etype (Subp_Id);
2131 -- Generate _Result which is used in procedure _Postconditions to
2132 -- verify the return value.
2134 Result := Make_Defining_Identifier (Loc, Name_uResult);
2135 Set_Etype (Result, Typ);
2137 -- Add an invariant check when the return type has invariants and
2138 -- the related function is visible to the outside.
2140 if Invariant_Checks_OK (Typ) then
2141 Append_Enabled_Item
2142 (Item =>
2143 Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
2144 List => Stmts);
2145 end if;
2147 -- Add an invariant check when the return type is an access to a
2148 -- type with invariants.
2150 Add_Invariant_Access_Checks (Result);
2151 end if;
2153 -- Add invariant and predicates for all formals that qualify
2155 Formal := First_Formal (Subp_Id);
2156 while Present (Formal) loop
2157 Typ := Etype (Formal);
2159 if Ekind (Formal) /= E_In_Parameter
2160 or else Is_Access_Type (Typ)
2161 then
2162 if Invariant_Checks_OK (Typ) then
2163 Append_Enabled_Item
2164 (Item =>
2165 Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
2166 List => Stmts);
2167 end if;
2169 Add_Invariant_Access_Checks (Formal);
2171 -- Note: we used to add predicate checks for OUT and IN OUT
2172 -- formals here, but that was misguided, since such checks are
2173 -- performed on the caller side, based on the predicate of the
2174 -- actual, rather than the predicate of the formal.
2176 end if;
2178 Next_Formal (Formal);
2179 end loop;
2180 end Add_Invariant_And_Predicate_Checks;
2182 -------------------------
2183 -- Append_Enabled_Item --
2184 -------------------------
2186 procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
2187 begin
2188 -- Do not chain ignored or disabled pragmas
2190 if Nkind (Item) = N_Pragma
2191 and then (Is_Ignored (Item) or else Is_Disabled (Item))
2192 then
2193 null;
2195 -- Otherwise, add the item
2197 else
2198 if No (List) then
2199 List := New_List;
2200 end if;
2202 -- If the pragma is a conjunct in a composite postcondition, it
2203 -- has been processed in reverse order. In the postcondition body
2204 -- it must appear before the others.
2206 if Nkind (Item) = N_Pragma
2207 and then From_Aspect_Specification (Item)
2208 and then Split_PPC (Item)
2209 then
2210 Prepend (Item, List);
2211 else
2212 Append (Item, List);
2213 end if;
2214 end if;
2215 end Append_Enabled_Item;
2217 ------------------------------------
2218 -- Build_Postconditions_Procedure --
2219 ------------------------------------
2221 procedure Build_Postconditions_Procedure
2222 (Subp_Id : Entity_Id;
2223 Stmts : List_Id;
2224 Result : Entity_Id)
2226 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id);
2227 -- Insert node Stmt before the first source declaration of the
2228 -- related subprogram's body. If no such declaration exists, Stmt
2229 -- becomes the last declaration.
2231 --------------------------------------------
2232 -- Insert_Before_First_Source_Declaration --
2233 --------------------------------------------
2235 procedure Insert_Before_First_Source_Declaration (Stmt : Node_Id) is
2236 Decls : constant List_Id := Declarations (Body_Decl);
2237 Decl : Node_Id;
2239 begin
2240 -- Inspect the declarations of the related subprogram body looking
2241 -- for the first source declaration.
2243 if Present (Decls) then
2244 Decl := First (Decls);
2245 while Present (Decl) loop
2246 if Comes_From_Source (Decl) then
2247 Insert_Before (Decl, Stmt);
2248 return;
2249 end if;
2251 Next (Decl);
2252 end loop;
2254 -- If we get there, then the subprogram body lacks any source
2255 -- declarations. The body of _Postconditions now acts as the
2256 -- last declaration.
2258 Append (Stmt, Decls);
2260 -- Ensure that the body has a declaration list
2262 else
2263 Set_Declarations (Body_Decl, New_List (Stmt));
2264 end if;
2265 end Insert_Before_First_Source_Declaration;
2267 -- Local variables
2269 Loc : constant Source_Ptr := Sloc (Body_Decl);
2270 Params : List_Id := No_List;
2271 Proc_Bod : Node_Id;
2272 Proc_Decl : Node_Id;
2273 Proc_Id : Entity_Id;
2274 Proc_Spec : Node_Id;
2276 -- Start of processing for Build_Postconditions_Procedure
2278 begin
2279 -- Nothing to do if there are no actions to check on exit
2281 if No (Stmts) then
2282 return;
2283 end if;
2285 Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
2286 Set_Debug_Info_Needed (Proc_Id);
2287 Set_Postconditions_Proc (Subp_Id, Proc_Id);
2289 -- Force the front-end inlining of _Postconditions when generating C
2290 -- code, since its body may have references to itypes defined in the
2291 -- enclosing subprogram, which would cause problems for unnesting
2292 -- routines in the absence of inlining.
2294 if Modify_Tree_For_C then
2295 Set_Has_Pragma_Inline (Proc_Id);
2296 Set_Has_Pragma_Inline_Always (Proc_Id);
2297 Set_Is_Inlined (Proc_Id);
2298 end if;
2300 -- The related subprogram is a function: create the specification of
2301 -- parameter _Result.
2303 if Present (Result) then
2304 Params := New_List (
2305 Make_Parameter_Specification (Loc,
2306 Defining_Identifier => Result,
2307 Parameter_Type =>
2308 New_Occurrence_Of (Etype (Result), Loc)));
2309 end if;
2311 Proc_Spec :=
2312 Make_Procedure_Specification (Loc,
2313 Defining_Unit_Name => Proc_Id,
2314 Parameter_Specifications => Params);
2316 Proc_Decl := Make_Subprogram_Declaration (Loc, Proc_Spec);
2318 -- Insert _Postconditions before the first source declaration of the
2319 -- body. This ensures that the body will not cause any premature
2320 -- freezing, as it may mention types:
2322 -- procedure Proc (Obj : Array_Typ) is
2323 -- procedure _postconditions is
2324 -- begin
2325 -- ... Obj ...
2326 -- end _postconditions;
2328 -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
2329 -- begin
2331 -- In the example above, Obj is of type T but the incorrect placement
2332 -- of _Postconditions will cause a crash in gigi due to an out-of-
2333 -- order reference. The body of _Postconditions must be placed after
2334 -- the declaration of Temp to preserve correct visibility.
2336 Insert_Before_First_Source_Declaration (Proc_Decl);
2337 Analyze (Proc_Decl);
2339 -- Set an explicit End_Label to override the sloc of the implicit
2340 -- RETURN statement, and prevent it from inheriting the sloc of one
2341 -- the postconditions: this would cause confusing debug info to be
2342 -- produced, interfering with coverage-analysis tools.
2344 Proc_Bod :=
2345 Make_Subprogram_Body (Loc,
2346 Specification =>
2347 Copy_Subprogram_Spec (Proc_Spec),
2348 Declarations => Empty_List,
2349 Handled_Statement_Sequence =>
2350 Make_Handled_Sequence_Of_Statements (Loc,
2351 Statements => Stmts,
2352 End_Label => Make_Identifier (Loc, Chars (Proc_Id))));
2354 Insert_After_And_Analyze (Proc_Decl, Proc_Bod);
2355 end Build_Postconditions_Procedure;
2357 ----------------------------
2358 -- Process_Contract_Cases --
2359 ----------------------------
2361 procedure Process_Contract_Cases (Stmts : in out List_Id) is
2362 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id);
2363 -- Process pragma Contract_Cases for subprogram Subp_Id
2365 --------------------------------
2366 -- Process_Contract_Cases_For --
2367 --------------------------------
2369 procedure Process_Contract_Cases_For (Subp_Id : Entity_Id) is
2370 Items : constant Node_Id := Contract (Subp_Id);
2371 Prag : Node_Id;
2373 begin
2374 if Present (Items) then
2375 Prag := Contract_Test_Cases (Items);
2376 while Present (Prag) loop
2377 if Pragma_Name (Prag) = Name_Contract_Cases
2378 and then Is_Checked (Prag)
2379 then
2380 Expand_Pragma_Contract_Cases
2381 (CCs => Prag,
2382 Subp_Id => Subp_Id,
2383 Decls => Declarations (Body_Decl),
2384 Stmts => Stmts);
2385 end if;
2387 Prag := Next_Pragma (Prag);
2388 end loop;
2389 end if;
2390 end Process_Contract_Cases_For;
2392 pragma Unmodified (Stmts);
2393 -- Stmts is passed as IN OUT to signal that the list can be updated,
2394 -- even if the corresponding integer value representing the list does
2395 -- not change.
2397 -- Start of processing for Process_Contract_Cases
2399 begin
2400 Process_Contract_Cases_For (Body_Id);
2402 if Present (Spec_Id) then
2403 Process_Contract_Cases_For (Spec_Id);
2404 end if;
2405 end Process_Contract_Cases;
2407 ----------------------------
2408 -- Process_Postconditions --
2409 ----------------------------
2411 procedure Process_Postconditions (Stmts : in out List_Id) is
2412 procedure Process_Body_Postconditions (Post_Nam : Name_Id);
2413 -- Collect all [refined] postconditions of a specific kind denoted
2414 -- by Post_Nam that belong to the body, and generate pragma Check
2415 -- equivalents in list Stmts.
2417 procedure Process_Spec_Postconditions;
2418 -- Collect all [inherited] postconditions of the spec, and generate
2419 -- pragma Check equivalents in list Stmts.
2421 ---------------------------------
2422 -- Process_Body_Postconditions --
2423 ---------------------------------
2425 procedure Process_Body_Postconditions (Post_Nam : Name_Id) is
2426 Items : constant Node_Id := Contract (Body_Id);
2427 Unit_Decl : constant Node_Id := Parent (Body_Decl);
2428 Decl : Node_Id;
2429 Prag : Node_Id;
2431 begin
2432 -- Process the contract
2434 if Present (Items) then
2435 Prag := Pre_Post_Conditions (Items);
2436 while Present (Prag) loop
2437 if Pragma_Name (Prag) = Post_Nam
2438 and then Is_Checked (Prag)
2439 then
2440 Append_Enabled_Item
2441 (Item => Build_Pragma_Check_Equivalent (Prag),
2442 List => Stmts);
2443 end if;
2445 Prag := Next_Pragma (Prag);
2446 end loop;
2447 end if;
2449 -- The subprogram body being processed is actually the proper body
2450 -- of a stub with a corresponding spec. The subprogram stub may
2451 -- carry a postcondition pragma, in which case it must be taken
2452 -- into account. The pragma appears after the stub.
2454 if Present (Spec_Id) and then Nkind (Unit_Decl) = N_Subunit then
2455 Decl := Next (Corresponding_Stub (Unit_Decl));
2456 while Present (Decl) loop
2458 -- Note that non-matching pragmas are skipped
2460 if Nkind (Decl) = N_Pragma then
2461 if Pragma_Name (Decl) = Post_Nam
2462 and then Is_Checked (Decl)
2463 then
2464 Append_Enabled_Item
2465 (Item => Build_Pragma_Check_Equivalent (Decl),
2466 List => Stmts);
2467 end if;
2469 -- Skip internally generated code
2471 elsif not Comes_From_Source (Decl) then
2472 null;
2474 -- Postcondition pragmas are usually grouped together. There
2475 -- is no need to inspect the whole declarative list.
2477 else
2478 exit;
2479 end if;
2481 Next (Decl);
2482 end loop;
2483 end if;
2484 end Process_Body_Postconditions;
2486 ---------------------------------
2487 -- Process_Spec_Postconditions --
2488 ---------------------------------
2490 procedure Process_Spec_Postconditions is
2491 Subps : constant Subprogram_List :=
2492 Inherited_Subprograms (Spec_Id);
2493 Item : Node_Id;
2494 Items : Node_Id;
2495 Prag : Node_Id;
2496 Subp_Id : Entity_Id;
2498 begin
2499 -- Process the contract
2501 Items := Contract (Spec_Id);
2503 if Present (Items) then
2504 Prag := Pre_Post_Conditions (Items);
2505 while Present (Prag) loop
2506 if Pragma_Name (Prag) = Name_Postcondition
2507 and then Is_Checked (Prag)
2508 then
2509 Append_Enabled_Item
2510 (Item => Build_Pragma_Check_Equivalent (Prag),
2511 List => Stmts);
2512 end if;
2514 Prag := Next_Pragma (Prag);
2515 end loop;
2516 end if;
2518 -- Process the contracts of all inherited subprograms, looking for
2519 -- class-wide postconditions.
2521 for Index in Subps'Range loop
2522 Subp_Id := Subps (Index);
2523 Items := Contract (Subp_Id);
2525 if Present (Items) then
2526 Prag := Pre_Post_Conditions (Items);
2527 while Present (Prag) loop
2528 if Pragma_Name (Prag) = Name_Postcondition
2529 and then Class_Present (Prag)
2530 then
2531 Item :=
2532 Build_Pragma_Check_Equivalent
2533 (Prag => Prag,
2534 Subp_Id => Spec_Id,
2535 Inher_Id => Subp_Id);
2537 -- The pragma Check equivalent of the class-wide
2538 -- postcondition is still created even though the
2539 -- pragma may be ignored because the equivalent
2540 -- performs semantic checks.
2542 if Is_Checked (Prag) then
2543 Append_Enabled_Item (Item, Stmts);
2544 end if;
2545 end if;
2547 Prag := Next_Pragma (Prag);
2548 end loop;
2549 end if;
2550 end loop;
2551 end Process_Spec_Postconditions;
2553 pragma Unmodified (Stmts);
2554 -- Stmts is passed as IN OUT to signal that the list can be updated,
2555 -- even if the corresponding integer value representing the list does
2556 -- not change.
2558 -- Start of processing for Process_Postconditions
2560 begin
2561 -- The processing of postconditions is done in reverse order (body
2562 -- first) to ensure the following arrangement:
2564 -- <refined postconditions from body>
2565 -- <postconditions from body>
2566 -- <postconditions from spec>
2567 -- <inherited postconditions>
2569 Process_Body_Postconditions (Name_Refined_Post);
2570 Process_Body_Postconditions (Name_Postcondition);
2572 if Present (Spec_Id) then
2573 Process_Spec_Postconditions;
2574 end if;
2575 end Process_Postconditions;
2577 ---------------------------
2578 -- Process_Preconditions --
2579 ---------------------------
2581 procedure Process_Preconditions is
2582 Class_Pre : Node_Id := Empty;
2583 -- The sole [inherited] class-wide precondition pragma that applies
2584 -- to the subprogram.
2586 Insert_Node : Node_Id := Empty;
2587 -- The insertion node after which all pragma Check equivalents are
2588 -- inserted.
2590 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean;
2591 -- Determine whether arbitrary declaration Decl denotes a renaming of
2592 -- a discriminant or protection field _object.
2594 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
2595 -- Merge two class-wide preconditions by "or else"-ing them. The
2596 -- changes are accumulated in parameter Into. Update the error
2597 -- message of Into.
2599 procedure Prepend_To_Decls (Item : Node_Id);
2600 -- Prepend a single item to the declarations of the subprogram body
2602 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id);
2603 -- Save a class-wide precondition into Class_Pre, or prepend a normal
2604 -- precondition to the declarations of the body and analyze it.
2606 procedure Process_Inherited_Preconditions;
2607 -- Collect all inherited class-wide preconditions and merge them into
2608 -- one big precondition to be evaluated as pragma Check.
2610 procedure Process_Preconditions_For (Subp_Id : Entity_Id);
2611 -- Collect all preconditions of subprogram Subp_Id and prepend their
2612 -- pragma Check equivalents to the declarations of the body.
2614 --------------------------
2615 -- Is_Prologue_Renaming --
2616 --------------------------
2618 function Is_Prologue_Renaming (Decl : Node_Id) return Boolean is
2619 Nam : Node_Id;
2620 Obj : Entity_Id;
2621 Pref : Node_Id;
2622 Sel : Node_Id;
2624 begin
2625 if Nkind (Decl) = N_Object_Renaming_Declaration then
2626 Obj := Defining_Entity (Decl);
2627 Nam := Name (Decl);
2629 if Nkind (Nam) = N_Selected_Component then
2630 Pref := Prefix (Nam);
2631 Sel := Selector_Name (Nam);
2633 -- A discriminant renaming appears as
2634 -- Discr : constant ... := Prefix.Discr;
2636 if Ekind (Obj) = E_Constant
2637 and then Is_Entity_Name (Sel)
2638 and then Present (Entity (Sel))
2639 and then Ekind (Entity (Sel)) = E_Discriminant
2640 then
2641 return True;
2643 -- A protection field renaming appears as
2644 -- Prot : ... := _object._object;
2646 -- A renamed private component is just a component of
2647 -- _object, with an arbitrary name.
2649 elsif Ekind (Obj) = E_Variable
2650 and then Nkind (Pref) = N_Identifier
2651 and then Chars (Pref) = Name_uObject
2652 and then Nkind (Sel) = N_Identifier
2653 then
2654 return True;
2655 end if;
2656 end if;
2657 end if;
2659 return False;
2660 end Is_Prologue_Renaming;
2662 -------------------------
2663 -- Merge_Preconditions --
2664 -------------------------
2666 procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
2667 function Expression_Arg (Prag : Node_Id) return Node_Id;
2668 -- Return the boolean expression argument of a precondition while
2669 -- updating its parentheses count for the subsequent merge.
2671 function Message_Arg (Prag : Node_Id) return Node_Id;
2672 -- Return the message argument of a precondition
2674 --------------------
2675 -- Expression_Arg --
2676 --------------------
2678 function Expression_Arg (Prag : Node_Id) return Node_Id is
2679 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2680 Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
2682 begin
2683 if Paren_Count (Arg) = 0 then
2684 Set_Paren_Count (Arg, 1);
2685 end if;
2687 return Arg;
2688 end Expression_Arg;
2690 -----------------
2691 -- Message_Arg --
2692 -----------------
2694 function Message_Arg (Prag : Node_Id) return Node_Id is
2695 Args : constant List_Id := Pragma_Argument_Associations (Prag);
2696 begin
2697 return Get_Pragma_Arg (Last (Args));
2698 end Message_Arg;
2700 -- Local variables
2702 From_Expr : constant Node_Id := Expression_Arg (From);
2703 From_Msg : constant Node_Id := Message_Arg (From);
2704 Into_Expr : constant Node_Id := Expression_Arg (Into);
2705 Into_Msg : constant Node_Id := Message_Arg (Into);
2706 Loc : constant Source_Ptr := Sloc (Into);
2708 -- Start of processing for Merge_Preconditions
2710 begin
2711 -- Merge the two preconditions by "or else"-ing them
2713 Rewrite (Into_Expr,
2714 Make_Or_Else (Loc,
2715 Right_Opnd => Relocate_Node (Into_Expr),
2716 Left_Opnd => From_Expr));
2718 -- Merge the two error messages to produce a single message of the
2719 -- form:
2721 -- failed precondition from ...
2722 -- also failed inherited precondition from ...
2724 if not Exception_Locations_Suppressed then
2725 Start_String (Strval (Into_Msg));
2726 Store_String_Char (ASCII.LF);
2727 Store_String_Chars (" also ");
2728 Store_String_Chars (Strval (From_Msg));
2730 Set_Strval (Into_Msg, End_String);
2731 end if;
2732 end Merge_Preconditions;
2734 ----------------------
2735 -- Prepend_To_Decls --
2736 ----------------------
2738 procedure Prepend_To_Decls (Item : Node_Id) is
2739 Decls : List_Id;
2741 begin
2742 Decls := Declarations (Body_Decl);
2744 -- Ensure that the body has a declarative list
2746 if No (Decls) then
2747 Decls := New_List;
2748 Set_Declarations (Body_Decl, Decls);
2749 end if;
2751 Prepend_To (Decls, Item);
2752 end Prepend_To_Decls;
2754 ------------------------------
2755 -- Prepend_To_Decls_Or_Save --
2756 ------------------------------
2758 procedure Prepend_To_Decls_Or_Save (Prag : Node_Id) is
2759 Check_Prag : Node_Id;
2761 begin
2762 Check_Prag := Build_Pragma_Check_Equivalent (Prag);
2764 -- Save the sole class-wide precondition (if any) for the next
2765 -- step, where it will be merged with inherited preconditions.
2767 if Class_Present (Prag) then
2768 pragma Assert (No (Class_Pre));
2769 Class_Pre := Check_Prag;
2771 -- Accumulate the corresponding Check pragmas at the top of the
2772 -- declarations. Prepending the items ensures that they will be
2773 -- evaluated in their original order.
2775 else
2776 if Present (Insert_Node) then
2777 Insert_After (Insert_Node, Check_Prag);
2778 else
2779 Prepend_To_Decls (Check_Prag);
2780 end if;
2782 Analyze (Check_Prag);
2783 end if;
2784 end Prepend_To_Decls_Or_Save;
2786 -------------------------------------
2787 -- Process_Inherited_Preconditions --
2788 -------------------------------------
2790 procedure Process_Inherited_Preconditions is
2791 Subps : constant Subprogram_List :=
2792 Inherited_Subprograms (Spec_Id);
2794 Item : Node_Id;
2795 Items : Node_Id;
2796 Prag : Node_Id;
2797 Subp_Id : Entity_Id;
2799 begin
2800 -- Process the contracts of all inherited subprograms, looking for
2801 -- class-wide preconditions.
2803 for Index in Subps'Range loop
2804 Subp_Id := Subps (Index);
2805 Items := Contract (Subp_Id);
2807 if Present (Items) then
2808 Prag := Pre_Post_Conditions (Items);
2809 while Present (Prag) loop
2810 if Pragma_Name (Prag) = Name_Precondition
2811 and then Class_Present (Prag)
2812 then
2813 Item :=
2814 Build_Pragma_Check_Equivalent
2815 (Prag => Prag,
2816 Subp_Id => Spec_Id,
2817 Inher_Id => Subp_Id);
2819 -- The pragma Check equivalent of the class-wide
2820 -- precondition is still created even though the
2821 -- pragma may be ignored because the equivalent
2822 -- performs semantic checks.
2824 if Is_Checked (Prag) then
2826 -- The spec of an inherited subprogram already
2827 -- yielded a class-wide precondition. Merge the
2828 -- existing precondition with the current one
2829 -- using "or else".
2831 if Present (Class_Pre) then
2832 Merge_Preconditions (Item, Class_Pre);
2833 else
2834 Class_Pre := Item;
2835 end if;
2836 end if;
2837 end if;
2839 Prag := Next_Pragma (Prag);
2840 end loop;
2841 end if;
2842 end loop;
2844 -- Add the merged class-wide preconditions
2846 if Present (Class_Pre) then
2847 Prepend_To_Decls (Class_Pre);
2848 Analyze (Class_Pre);
2849 end if;
2850 end Process_Inherited_Preconditions;
2852 -------------------------------
2853 -- Process_Preconditions_For --
2854 -------------------------------
2856 procedure Process_Preconditions_For (Subp_Id : Entity_Id) is
2857 Items : constant Node_Id := Contract (Subp_Id);
2859 Decl : Node_Id;
2860 Prag : Node_Id;
2861 Subp_Decl : Node_Id;
2863 begin
2864 -- Process the contract
2866 if Present (Items) then
2867 Prag := Pre_Post_Conditions (Items);
2868 while Present (Prag) loop
2869 if Pragma_Name (Prag) = Name_Precondition
2870 and then Is_Checked (Prag)
2871 then
2872 Prepend_To_Decls_Or_Save (Prag);
2873 end if;
2875 Prag := Next_Pragma (Prag);
2876 end loop;
2877 end if;
2879 -- The subprogram declaration being processed is actually a body
2880 -- stub. The stub may carry a precondition pragma, in which case
2881 -- it must be taken into account. The pragma appears after the
2882 -- stub.
2884 Subp_Decl := Unit_Declaration_Node (Subp_Id);
2886 if Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
2888 -- Inspect the declarations following the body stub
2890 Decl := Next (Subp_Decl);
2891 while Present (Decl) loop
2893 -- Note that non-matching pragmas are skipped
2895 if Nkind (Decl) = N_Pragma then
2896 if Pragma_Name (Decl) = Name_Precondition
2897 and then Is_Checked (Decl)
2898 then
2899 Prepend_To_Decls_Or_Save (Decl);
2900 end if;
2902 -- Skip internally generated code
2904 elsif not Comes_From_Source (Decl) then
2905 null;
2907 -- Preconditions are usually grouped together. There is no
2908 -- need to inspect the whole declarative list.
2910 else
2911 exit;
2912 end if;
2914 Next (Decl);
2915 end loop;
2916 end if;
2917 end Process_Preconditions_For;
2919 -- Local variables
2921 Decls : constant List_Id := Declarations (Body_Decl);
2922 Decl : Node_Id;
2924 -- Start of processing for Process_Preconditions
2926 begin
2927 -- Find the proper insertion point for all pragma Check equivalents
2929 if Present (Decls) then
2930 Decl := First (Decls);
2931 while Present (Decl) loop
2933 -- First source declaration terminates the search, because all
2934 -- preconditions must be evaluated prior to it, by definition.
2936 if Comes_From_Source (Decl) then
2937 exit;
2939 -- Certain internally generated object renamings such as those
2940 -- for discriminants and protection fields must be elaborated
2941 -- before the preconditions are evaluated, as their expressions
2942 -- may mention the discriminants. The renamings include those
2943 -- for private components so we need to find the last such.
2945 elsif Is_Prologue_Renaming (Decl) then
2946 while Present (Next (Decl))
2947 and then Is_Prologue_Renaming (Next (Decl))
2948 loop
2949 Next (Decl);
2950 end loop;
2952 Insert_Node := Decl;
2954 -- Otherwise the declaration does not come from source. This
2955 -- also terminates the search, because internal code may raise
2956 -- exceptions which should not preempt the preconditions.
2958 else
2959 exit;
2960 end if;
2962 Next (Decl);
2963 end loop;
2964 end if;
2966 -- The processing of preconditions is done in reverse order (body
2967 -- first), because each pragma Check equivalent is inserted at the
2968 -- top of the declarations. This ensures that the final order is
2969 -- consistent with following diagram:
2971 -- <inherited preconditions>
2972 -- <preconditions from spec>
2973 -- <preconditions from body>
2975 Process_Preconditions_For (Body_Id);
2977 if Present (Spec_Id) then
2978 Process_Preconditions_For (Spec_Id);
2979 Process_Inherited_Preconditions;
2980 end if;
2981 end Process_Preconditions;
2983 -- Local variables
2985 Restore_Scope : Boolean := False;
2986 Result : Entity_Id;
2987 Stmts : List_Id := No_List;
2988 Subp_Id : Entity_Id;
2990 -- Start of processing for Expand_Subprogram_Contract
2992 begin
2993 -- Obtain the entity of the initial declaration
2995 if Present (Spec_Id) then
2996 Subp_Id := Spec_Id;
2997 else
2998 Subp_Id := Body_Id;
2999 end if;
3001 -- Do not perform expansion activity when it is not needed
3003 if not Expander_Active then
3004 return;
3006 -- ASIS requires an unaltered tree
3008 elsif ASIS_Mode then
3009 return;
3011 -- GNATprove does not need the executable semantics of a contract
3013 elsif GNATprove_Mode then
3014 return;
3016 -- The contract of a generic subprogram or one declared in a generic
3017 -- context is not expanded, as the corresponding instance will provide
3018 -- the executable semantics of the contract.
3020 elsif Is_Generic_Subprogram (Subp_Id) or else Inside_A_Generic then
3021 return;
3023 -- All subprograms carry a contract, but for some it is not significant
3024 -- and should not be processed. This is a small optimization.
3026 elsif not Has_Significant_Contract (Subp_Id) then
3027 return;
3029 -- The contract of an ignored Ghost subprogram does not need expansion,
3030 -- because the subprogram and all calls to it will be removed.
3032 elsif Is_Ignored_Ghost_Entity (Subp_Id) then
3033 return;
3035 -- Do not re-expand the same contract. This scenario occurs when a
3036 -- construct is rewritten into something else during its analysis
3037 -- (expression functions for instance).
3039 elsif Has_Expanded_Contract (Subp_Id) then
3040 return;
3041 end if;
3043 -- Prevent multiple expansion attempts of the same contract
3045 Set_Has_Expanded_Contract (Subp_Id);
3047 -- Ensure that the formal parameters are visible when expanding all
3048 -- contract items.
3050 if not In_Open_Scopes (Subp_Id) then
3051 Restore_Scope := True;
3052 Push_Scope (Subp_Id);
3054 if Is_Generic_Subprogram (Subp_Id) then
3055 Install_Generic_Formals (Subp_Id);
3056 else
3057 Install_Formals (Subp_Id);
3058 end if;
3059 end if;
3061 -- The expansion of a subprogram contract involves the creation of Check
3062 -- pragmas to verify the contract assertions of the spec and body in a
3063 -- particular order. The order is as follows:
3065 -- function Example (...) return ... is
3066 -- procedure _Postconditions (...) is
3067 -- begin
3068 -- <refined postconditions from body>
3069 -- <postconditions from body>
3070 -- <postconditions from spec>
3071 -- <inherited postconditions>
3072 -- <contract case consequences>
3073 -- <invariant check of function result>
3074 -- <invariant and predicate checks of parameters>
3075 -- end _Postconditions;
3077 -- <inherited preconditions>
3078 -- <preconditions from spec>
3079 -- <preconditions from body>
3080 -- <contract case conditions>
3082 -- <source declarations>
3083 -- begin
3084 -- <source statements>
3086 -- _Preconditions (Result);
3087 -- return Result;
3088 -- end Example;
3090 -- Routine _Postconditions holds all contract assertions that must be
3091 -- verified on exit from the related subprogram.
3093 -- Step 1: Handle all preconditions. This action must come before the
3094 -- processing of pragma Contract_Cases because the pragma prepends items
3095 -- to the body declarations.
3097 Process_Preconditions;
3099 -- Step 2: Handle all postconditions. This action must come before the
3100 -- processing of pragma Contract_Cases because the pragma appends items
3101 -- to list Stmts.
3103 Process_Postconditions (Stmts);
3105 -- Step 3: Handle pragma Contract_Cases. This action must come before
3106 -- the processing of invariants and predicates because those append
3107 -- items to list Stmts.
3109 Process_Contract_Cases (Stmts);
3111 -- Step 4: Apply invariant and predicate checks on a function result and
3112 -- all formals. The resulting checks are accumulated in list Stmts.
3114 Add_Invariant_And_Predicate_Checks (Subp_Id, Stmts, Result);
3116 -- Step 5: Construct procedure _Postconditions
3118 Build_Postconditions_Procedure (Subp_Id, Stmts, Result);
3120 if Restore_Scope then
3121 End_Scope;
3122 end if;
3123 end Expand_Subprogram_Contract;
3125 -------------------------------
3126 -- Freeze_Previous_Contracts --
3127 -------------------------------
3129 procedure Freeze_Previous_Contracts (Body_Decl : Node_Id) is
3130 function Causes_Contract_Freezing (N : Node_Id) return Boolean;
3131 pragma Inline (Causes_Contract_Freezing);
3132 -- Determine whether arbitrary node N causes contract freezing
3134 procedure Freeze_Contracts;
3135 pragma Inline (Freeze_Contracts);
3136 -- Freeze the contracts of all eligible constructs which precede body
3137 -- Body_Decl.
3139 procedure Freeze_Enclosing_Package_Body;
3140 pragma Inline (Freeze_Enclosing_Package_Body);
3141 -- Freeze the contract of the nearest package body (if any) which
3142 -- encloses body Body_Decl.
3144 ------------------------------
3145 -- Causes_Contract_Freezing --
3146 ------------------------------
3148 function Causes_Contract_Freezing (N : Node_Id) return Boolean is
3149 begin
3150 return Nkind_In (N, N_Entry_Body,
3151 N_Package_Body,
3152 N_Protected_Body,
3153 N_Subprogram_Body,
3154 N_Subprogram_Body_Stub,
3155 N_Task_Body);
3156 end Causes_Contract_Freezing;
3158 ----------------------
3159 -- Freeze_Contracts --
3160 ----------------------
3162 procedure Freeze_Contracts is
3163 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
3164 Decl : Node_Id;
3166 begin
3167 -- Nothing to do when the body which causes freezing does not appear
3168 -- in a declarative list because there cannot possibly be constructs
3169 -- with contracts.
3171 if not Is_List_Member (Body_Decl) then
3172 return;
3173 end if;
3175 -- Inspect the declarations preceding the body, and freeze individual
3176 -- contracts of eligible constructs.
3178 Decl := Prev (Body_Decl);
3179 while Present (Decl) loop
3181 -- Stop the traversal when a preceding construct that causes
3182 -- freezing is encountered as there is no point in refreezing
3183 -- the already frozen constructs.
3185 if Causes_Contract_Freezing (Decl) then
3186 exit;
3188 -- Entry or subprogram declarations
3190 elsif Nkind_In (Decl, N_Abstract_Subprogram_Declaration,
3191 N_Entry_Declaration,
3192 N_Generic_Subprogram_Declaration,
3193 N_Subprogram_Declaration)
3194 then
3195 Analyze_Entry_Or_Subprogram_Contract
3196 (Subp_Id => Defining_Entity (Decl),
3197 Freeze_Id => Body_Id);
3199 -- Objects
3201 elsif Nkind (Decl) = N_Object_Declaration then
3202 Analyze_Object_Contract
3203 (Obj_Id => Defining_Entity (Decl),
3204 Freeze_Id => Body_Id);
3206 -- Protected units
3208 elsif Nkind_In (Decl, N_Protected_Type_Declaration,
3209 N_Single_Protected_Declaration)
3210 then
3211 Analyze_Protected_Contract (Defining_Entity (Decl));
3213 -- Subprogram body stubs
3215 elsif Nkind (Decl) = N_Subprogram_Body_Stub then
3216 Analyze_Subprogram_Body_Stub_Contract (Defining_Entity (Decl));
3218 -- Task units
3220 elsif Nkind_In (Decl, N_Single_Task_Declaration,
3221 N_Task_Type_Declaration)
3222 then
3223 Analyze_Task_Contract (Defining_Entity (Decl));
3224 end if;
3226 Prev (Decl);
3227 end loop;
3228 end Freeze_Contracts;
3230 -----------------------------------
3231 -- Freeze_Enclosing_Package_Body --
3232 -----------------------------------
3234 procedure Freeze_Enclosing_Package_Body is
3235 Orig_Decl : constant Node_Id := Original_Node (Body_Decl);
3236 Par : Node_Id;
3238 begin
3239 -- Climb the parent chain looking for an enclosing package body. Do
3240 -- not use the scope stack, because a body utilizes the entity of its
3241 -- corresponding spec.
3243 Par := Parent (Body_Decl);
3244 while Present (Par) loop
3245 if Nkind (Par) = N_Package_Body then
3246 Analyze_Package_Body_Contract
3247 (Body_Id => Defining_Entity (Par),
3248 Freeze_Id => Defining_Entity (Body_Decl));
3250 exit;
3252 -- Do not look for an enclosing package body when the construct
3253 -- which causes freezing is a body generated for an expression
3254 -- function and it appears within a package spec. This ensures
3255 -- that the traversal will not reach too far up the parent chain
3256 -- and attempt to freeze a package body which must not be frozen.
3258 -- package body Enclosing_Body
3259 -- with Refined_State => (State => Var)
3260 -- is
3261 -- package Nested is
3262 -- type Some_Type is ...;
3263 -- function Cause_Freezing return ...;
3264 -- private
3265 -- function Cause_Freezing is (...);
3266 -- end Nested;
3268 -- Var : Nested.Some_Type;
3270 elsif Nkind (Par) = N_Package_Declaration
3271 and then Nkind (Orig_Decl) = N_Expression_Function
3272 then
3273 exit;
3275 -- Prevent the search from going too far
3277 elsif Is_Body_Or_Package_Declaration (Par) then
3278 exit;
3279 end if;
3281 Par := Parent (Par);
3282 end loop;
3283 end Freeze_Enclosing_Package_Body;
3285 -- Local variables
3287 Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
3289 -- Start of processing for Freeze_Previous_Contracts
3291 begin
3292 pragma Assert (Causes_Contract_Freezing (Body_Decl));
3294 -- A body that is in the process of being inlined appears from source,
3295 -- but carries name _parent. Such a body does not cause freezing of
3296 -- contracts.
3298 if Chars (Body_Id) = Name_uParent then
3299 return;
3300 end if;
3302 Freeze_Enclosing_Package_Body;
3303 Freeze_Contracts;
3304 end Freeze_Previous_Contracts;
3306 ---------------------------------
3307 -- Inherit_Subprogram_Contract --
3308 ---------------------------------
3310 procedure Inherit_Subprogram_Contract
3311 (Subp : Entity_Id;
3312 From_Subp : Entity_Id)
3314 procedure Inherit_Pragma (Prag_Id : Pragma_Id);
3315 -- Propagate a pragma denoted by Prag_Id from From_Subp's contract to
3316 -- Subp's contract.
3318 --------------------
3319 -- Inherit_Pragma --
3320 --------------------
3322 procedure Inherit_Pragma (Prag_Id : Pragma_Id) is
3323 Prag : constant Node_Id := Get_Pragma (From_Subp, Prag_Id);
3324 New_Prag : Node_Id;
3326 begin
3327 -- A pragma cannot be part of more than one First_Pragma/Next_Pragma
3328 -- chains, therefore the node must be replicated. The new pragma is
3329 -- flagged as inherited for distinction purposes.
3331 if Present (Prag) then
3332 New_Prag := New_Copy_Tree (Prag);
3333 Set_Is_Inherited_Pragma (New_Prag);
3335 Add_Contract_Item (New_Prag, Subp);
3336 end if;
3337 end Inherit_Pragma;
3339 -- Start of processing for Inherit_Subprogram_Contract
3341 begin
3342 -- Inheritance is carried out only when both entities are subprograms
3343 -- with contracts.
3345 if Is_Subprogram_Or_Generic_Subprogram (Subp)
3346 and then Is_Subprogram_Or_Generic_Subprogram (From_Subp)
3347 and then Present (Contract (From_Subp))
3348 then
3349 Inherit_Pragma (Pragma_Extensions_Visible);
3350 end if;
3351 end Inherit_Subprogram_Contract;
3353 -------------------------------------
3354 -- Instantiate_Subprogram_Contract --
3355 -------------------------------------
3357 procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id) is
3358 procedure Instantiate_Pragmas (First_Prag : Node_Id);
3359 -- Instantiate all contract-related source pragmas found in the list,
3360 -- starting with pragma First_Prag. Each instantiated pragma is added
3361 -- to list L.
3363 -------------------------
3364 -- Instantiate_Pragmas --
3365 -------------------------
3367 procedure Instantiate_Pragmas (First_Prag : Node_Id) is
3368 Inst_Prag : Node_Id;
3369 Prag : Node_Id;
3371 begin
3372 Prag := First_Prag;
3373 while Present (Prag) loop
3374 if Is_Generic_Contract_Pragma (Prag) then
3375 Inst_Prag :=
3376 Copy_Generic_Node (Prag, Empty, Instantiating => True);
3378 Set_Analyzed (Inst_Prag, False);
3379 Append_To (L, Inst_Prag);
3380 end if;
3382 Prag := Next_Pragma (Prag);
3383 end loop;
3384 end Instantiate_Pragmas;
3386 -- Local variables
3388 Items : constant Node_Id := Contract (Defining_Entity (Templ));
3390 -- Start of processing for Instantiate_Subprogram_Contract
3392 begin
3393 if Present (Items) then
3394 Instantiate_Pragmas (Pre_Post_Conditions (Items));
3395 Instantiate_Pragmas (Contract_Test_Cases (Items));
3396 Instantiate_Pragmas (Classifications (Items));
3397 end if;
3398 end Instantiate_Subprogram_Contract;
3400 ----------------------------------------
3401 -- Save_Global_References_In_Contract --
3402 ----------------------------------------
3404 procedure Save_Global_References_In_Contract
3405 (Templ : Node_Id;
3406 Gen_Id : Entity_Id)
3408 procedure Save_Global_References_In_List (First_Prag : Node_Id);
3409 -- Save all global references in contract-related source pragmas found
3410 -- in the list, starting with pragma First_Prag.
3412 ------------------------------------
3413 -- Save_Global_References_In_List --
3414 ------------------------------------
3416 procedure Save_Global_References_In_List (First_Prag : Node_Id) is
3417 Prag : Node_Id;
3419 begin
3420 Prag := First_Prag;
3421 while Present (Prag) loop
3422 if Is_Generic_Contract_Pragma (Prag) then
3423 Save_Global_References (Prag);
3424 end if;
3426 Prag := Next_Pragma (Prag);
3427 end loop;
3428 end Save_Global_References_In_List;
3430 -- Local variables
3432 Items : constant Node_Id := Contract (Defining_Entity (Templ));
3434 -- Start of processing for Save_Global_References_In_Contract
3436 begin
3437 -- The entity of the analyzed generic copy must be on the scope stack
3438 -- to ensure proper detection of global references.
3440 Push_Scope (Gen_Id);
3442 if Permits_Aspect_Specifications (Templ)
3443 and then Has_Aspects (Templ)
3444 then
3445 Save_Global_References_In_Aspects (Templ);
3446 end if;
3448 if Present (Items) then
3449 Save_Global_References_In_List (Pre_Post_Conditions (Items));
3450 Save_Global_References_In_List (Contract_Test_Cases (Items));
3451 Save_Global_References_In_List (Classifications (Items));
3452 end if;
3454 Pop_Scope;
3455 end Save_Global_References_In_Contract;
3457 end Contracts;