1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Casing
; use Casing
;
28 with Checks
; use Checks
;
29 with Debug
; use Debug
;
30 with Einfo
; use Einfo
;
31 with Errout
; use Errout
;
32 with Exp_Ch11
; use Exp_Ch11
;
33 with Exp_Util
; use Exp_Util
;
34 with Expander
; use Expander
;
35 with Inline
; use Inline
;
37 with Namet
; use Namet
;
38 with Nlists
; use Nlists
;
39 with Nmake
; use Nmake
;
41 with Restrict
; use Restrict
;
42 with Rident
; use Rident
;
43 with Rtsfind
; use Rtsfind
;
45 with Sem_Aux
; use Sem_Aux
;
46 with Sem_Ch8
; use Sem_Ch8
;
47 with Sem_Prag
; use Sem_Prag
;
48 with Sem_Util
; use Sem_Util
;
49 with Sinfo
; use Sinfo
;
50 with Sinput
; use Sinput
;
51 with Snames
; use Snames
;
52 with Stringt
; use Stringt
;
53 with Stand
; use Stand
;
54 with Tbuild
; use Tbuild
;
55 with Uintp
; use Uintp
;
56 with Validsw
; use Validsw
;
58 package body Exp_Prag
is
60 -----------------------
61 -- Local Subprograms --
62 -----------------------
64 function Arg1
(N
: Node_Id
) return Node_Id
;
65 function Arg2
(N
: Node_Id
) return Node_Id
;
66 function Arg3
(N
: Node_Id
) return Node_Id
;
67 -- Obtain specified pragma argument expression
69 procedure Expand_Pragma_Abort_Defer
(N
: Node_Id
);
70 procedure Expand_Pragma_Check
(N
: Node_Id
);
71 procedure Expand_Pragma_Common_Object
(N
: Node_Id
);
72 procedure Expand_Pragma_Import_Or_Interface
(N
: Node_Id
);
73 procedure Expand_Pragma_Inspection_Point
(N
: Node_Id
);
74 procedure Expand_Pragma_Interrupt_Priority
(N
: Node_Id
);
75 procedure Expand_Pragma_Loop_Variant
(N
: Node_Id
);
76 procedure Expand_Pragma_Psect_Object
(N
: Node_Id
);
77 procedure Expand_Pragma_Relative_Deadline
(N
: Node_Id
);
78 procedure Expand_Pragma_Suppress_Initialization
(N
: Node_Id
);
80 procedure Undo_Initialization
(Def_Id
: Entity_Id
; N
: Node_Id
);
81 -- This procedure is used to undo initialization already done for Def_Id,
82 -- which is always an E_Variable, in response to the occurrence of the
83 -- pragma N, a pragma Interface, Import, or Suppress_Initialization. In all
84 -- these cases we want no initialization to occur, but we have already done
85 -- the initialization by the time we see the pragma, so we have to undo it.
91 function Arg1
(N
: Node_Id
) return Node_Id
is
92 Arg
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
95 and then Nkind
(Arg
) = N_Pragma_Argument_Association
97 return Expression
(Arg
);
107 function Arg2
(N
: Node_Id
) return Node_Id
is
108 Arg1
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
116 Arg
: constant Node_Id
:= Next
(Arg1
);
119 and then Nkind
(Arg
) = N_Pragma_Argument_Association
121 return Expression
(Arg
);
133 function Arg3
(N
: Node_Id
) return Node_Id
is
134 Arg1
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
142 Arg
: Node_Id
:= Next
(Arg1
);
151 and then Nkind
(Arg
) = N_Pragma_Argument_Association
153 return Expression
(Arg
);
162 ---------------------
163 -- Expand_N_Pragma --
164 ---------------------
166 procedure Expand_N_Pragma
(N
: Node_Id
) is
167 Pname
: constant Name_Id
:= Pragma_Name
(N
);
168 Prag_Id
: constant Pragma_Id
:= Get_Pragma_Id
(Pname
);
171 -- Suppress the expansion of an ignored assertion pragma. Such a pragma
172 -- should not be transformed into a null statment because:
174 -- * The pragma may be part of the rep item chain of a type, in which
175 -- case rewriting it will destroy the chain.
177 -- * The analysis of the pragma may involve two parts (see routines
178 -- Analyze_xxx_In_Decl_Part). The second part of the analysis will
179 -- not happen if the pragma is rewritten.
181 if Assertion_Expression_Pragma
(Prag_Id
) and then Is_Ignored
(N
) then
184 -- Rewrite the pragma into a null statement when it is ignored using
185 -- pragma Ignore_Pragma, or denotes Default_Scalar_Storage_Order and
186 -- compilation switch -gnatI is in effect.
188 elsif Should_Ignore_Pragma_Sem
(N
)
189 or else (Prag_Id
= Pragma_Default_Scalar_Storage_Order
190 and then Ignore_Rep_Clauses
)
192 Rewrite
(N
, Make_Null_Statement
(Sloc
(N
)));
198 -- Pragmas requiring special expander action
200 when Pragma_Abort_Defer
=>
201 Expand_Pragma_Abort_Defer
(N
);
204 Expand_Pragma_Check
(N
);
206 when Pragma_Common_Object
=>
207 Expand_Pragma_Common_Object
(N
);
209 when Pragma_Import
=>
210 Expand_Pragma_Import_Or_Interface
(N
);
212 when Pragma_Inspection_Point
=>
213 Expand_Pragma_Inspection_Point
(N
);
215 when Pragma_Interface
=>
216 Expand_Pragma_Import_Or_Interface
(N
);
218 when Pragma_Interrupt_Priority
=>
219 Expand_Pragma_Interrupt_Priority
(N
);
221 when Pragma_Loop_Variant
=>
222 Expand_Pragma_Loop_Variant
(N
);
224 when Pragma_Psect_Object
=>
225 Expand_Pragma_Psect_Object
(N
);
227 when Pragma_Relative_Deadline
=>
228 Expand_Pragma_Relative_Deadline
(N
);
230 when Pragma_Suppress_Initialization
=>
231 Expand_Pragma_Suppress_Initialization
(N
);
233 -- All other pragmas need no expander action (includes
240 -------------------------------
241 -- Expand_Pragma_Abort_Defer --
242 -------------------------------
244 -- An Abort_Defer pragma appears as the first statement in a handled
245 -- statement sequence (right after the begin). It defers aborts for
246 -- the entire statement sequence, but not for any declarations or
247 -- handlers (if any) associated with this statement sequence.
249 -- The transformation is to transform
251 -- pragma Abort_Defer;
260 -- when all others =>
261 -- Abort_Undefer.all;
264 -- Abort_Undefer_Direct;
267 procedure Expand_Pragma_Abort_Defer
(N
: Node_Id
) is
269 -- Abort_Defer has no useful effect if Abort's are not allowed
271 if not Abort_Allowed
then
275 -- Normal case where abort is possible
278 Loc
: constant Source_Ptr
:= Sloc
(N
);
282 Blk
: constant Entity_Id
:=
283 New_Internal_Entity
(E_Block
, Current_Scope
, Sloc
(N
), 'B');
284 AUD
: constant Entity_Id
:= RTE
(RE_Abort_Undefer_Direct
);
287 Stms
:= New_List
(Build_Runtime_Call
(Loc
, RE_Abort_Defer
));
289 Stm
:= Remove_Next
(N
);
295 Make_Handled_Sequence_Of_Statements
(Loc
,
297 At_End_Proc
=> New_Occurrence_Of
(AUD
, Loc
));
299 -- Present the Abort_Undefer_Direct function to the backend so that
300 -- it can inline the call to the function.
302 Add_Inlined_Body
(AUD
, N
);
305 Make_Block_Statement
(Loc
, Handled_Statement_Sequence
=> HSS
));
307 Set_Scope
(Blk
, Current_Scope
);
308 Set_Etype
(Blk
, Standard_Void_Type
);
309 Set_Identifier
(N
, New_Occurrence_Of
(Blk
, Sloc
(N
)));
310 Expand_At_End_Handler
(HSS
, Blk
);
313 end Expand_Pragma_Abort_Defer
;
315 --------------------------
316 -- Expand_Pragma_Check --
317 --------------------------
319 procedure Expand_Pragma_Check
(N
: Node_Id
) is
320 Cond
: constant Node_Id
:= Arg2
(N
);
321 Nam
: constant Name_Id
:= Chars
(Arg1
(N
));
324 Loc
: constant Source_Ptr
:= Sloc
(First_Node
(Cond
));
325 -- Source location used in the case of a failed assertion: point to the
326 -- failing condition, not Loc. Note that the source location of the
327 -- expression is not usually the best choice here, because it points to
328 -- the location of the topmost tree node, which may be an operator in
329 -- the middle of the source text of the expression. For example, it gets
330 -- located on the last AND keyword in a chain of boolean expressiond
331 -- AND'ed together. It is best to put the message on the first character
332 -- of the condition, which is the effect of the First_Node call here.
333 -- This source location is used to build the default exception message,
334 -- and also as the sloc of the call to the runtime subprogram raising
335 -- Assert_Failure, so that coverage analysis tools can relate the
336 -- call to the failed check.
338 procedure Replace_Discriminals_Of_Protected_Op
(Expr
: Node_Id
);
339 -- Discriminants of the enclosing protected object may be referenced
340 -- in the expression of a precondition of a protected operation.
341 -- In the body of the operation these references must be replaced by
342 -- the discriminal created for them, which are renamings of the
343 -- discriminants of the object that is the target of the operation.
344 -- This replacement is done by visibility when the references appear
345 -- in the subprogram body, but in the case of a condition which appears
346 -- on the specification of the subprogram it has be done separately
347 -- because the condition has been replaced by a Check pragma and
348 -- analyzed earlier, before the creation of the discriminal renaming
349 -- declarations that are added to the subprogram body.
351 ------------------------------------------
352 -- Replace_Discriminals_Of_Protected_Op --
353 ------------------------------------------
355 procedure Replace_Discriminals_Of_Protected_Op
(Expr
: Node_Id
) is
356 function Find_Corresponding_Discriminal
357 (E
: Entity_Id
) return Entity_Id
;
358 -- Find the local entity that renames a discriminant of the enclosing
359 -- protected type, and has a matching name.
361 function Replace_Discr_Ref
(N
: Node_Id
) return Traverse_Result
;
362 -- Replace a reference to a discriminant of the original protected
363 -- type by the local renaming declaration of the discriminant of
364 -- the target object.
366 ------------------------------------
367 -- Find_Corresponding_Discriminal --
368 ------------------------------------
370 function Find_Corresponding_Discriminal
371 (E
: Entity_Id
) return Entity_Id
376 R
:= First_Entity
(Current_Scope
);
378 while Present
(R
) loop
379 if Nkind
(Parent
(R
)) = N_Object_Renaming_Declaration
380 and then Present
(Discriminal_Link
(R
))
381 and then Chars
(Discriminal_Link
(R
)) = Chars
(E
)
390 end Find_Corresponding_Discriminal
;
392 -----------------------
393 -- Replace_Discr_Ref --
394 -----------------------
396 function Replace_Discr_Ref
(N
: Node_Id
) return Traverse_Result
is
400 if Is_Entity_Name
(N
)
401 and then Present
(Discriminal_Link
(Entity
(N
)))
403 R
:= Find_Corresponding_Discriminal
(Entity
(N
));
404 Rewrite
(N
, New_Occurrence_Of
(R
, Sloc
(N
)));
408 end Replace_Discr_Ref
;
410 procedure Replace_Discriminant_References
is
411 new Traverse_Proc
(Replace_Discr_Ref
);
413 -- Start of processing for Replace_Discriminals_Of_Protected_Op
416 Replace_Discriminant_References
(Expr
);
417 end Replace_Discriminals_Of_Protected_Op
;
419 -- Start of processing for Expand_Pragma_Check
422 -- Nothing to do if pragma is ignored
424 if Is_Ignored
(N
) then
428 -- Since this check is active, rewrite the pragma into a corresponding
429 -- if statement, and then analyze the statement.
431 -- The normal case expansion transforms:
433 -- pragma Check (name, condition [,message]);
437 -- if not condition then
438 -- System.Assertions.Raise_Assert_Failure (Str);
441 -- where Str is the message if one is present, or the default of
442 -- name failed at file:line if no message is given (the "name failed
443 -- at" is omitted for name = Assertion, since it is redundant, given
444 -- that the name of the exception is Assert_Failure.)
446 -- Also, instead of "XXX failed at", we generate slightly
447 -- different messages for some of the contract assertions (see
448 -- code below for details).
450 -- An alternative expansion is used when the No_Exception_Propagation
451 -- restriction is active and there is a local Assert_Failure handler.
452 -- This is not a common combination of circumstances, but it occurs in
453 -- the context of Aunit and the zero footprint profile. In this case we
456 -- if not condition then
457 -- raise Assert_Failure;
460 -- This will then be transformed into a goto, and the local handler will
461 -- be able to handle the assert error (which would not be the case if a
462 -- call is made to the Raise_Assert_Failure procedure).
464 -- We also generate the direct raise if the Suppress_Exception_Locations
465 -- is active, since we don't want to generate messages in this case.
467 -- Note that the reason we do not always generate a direct raise is that
468 -- the form in which the procedure is called allows for more efficient
469 -- breakpointing of assertion errors.
471 -- Generate the appropriate if statement. Note that we consider this to
472 -- be an explicit conditional in the source, not an implicit if, so we
473 -- do not call Make_Implicit_If_Statement.
475 -- Case where we generate a direct raise
477 if ((Debug_Flag_Dot_G
478 or else Restriction_Active
(No_Exception_Propagation
))
479 and then Present
(Find_Local_Handler
(RTE
(RE_Assert_Failure
), N
)))
480 or else (Opt
.Exception_Locations_Suppressed
and then No
(Arg3
(N
)))
483 Make_If_Statement
(Loc
,
484 Condition
=> Make_Op_Not
(Loc
, Right_Opnd
=> Cond
),
485 Then_Statements
=> New_List
(
486 Make_Raise_Statement
(Loc
,
487 Name
=> New_Occurrence_Of
(RTE
(RE_Assert_Failure
), Loc
)))));
489 -- Case where we call the procedure
492 -- If we have a message given, use it
494 if Present
(Arg3
(N
)) then
495 Msg
:= Get_Pragma_Arg
(Arg3
(N
));
497 -- Here we have no string, so prepare one
501 Loc_Str
: constant String := Build_Location_String
(Loc
);
506 -- For Assert, we just use the location
508 if Nam
= Name_Assert
then
511 -- For predicate, we generate the string "predicate failed at
512 -- yyy". We prefer all lower case for predicate.
514 elsif Nam
= Name_Predicate
then
515 Add_Str_To_Name_Buffer
("predicate failed at ");
517 -- For special case of Precondition/Postcondition the string is
518 -- "failed xx from yy" where xx is precondition/postcondition
519 -- in all lower case. The reason for this different wording is
520 -- that the failure is not at the point of occurrence of the
521 -- pragma, unlike the other Check cases.
523 elsif Nam_In
(Nam
, Name_Precondition
, Name_Postcondition
) then
524 Get_Name_String
(Nam
);
525 Insert_Str_In_Name_Buffer
("failed ", 1);
526 Add_Str_To_Name_Buffer
(" from ");
528 -- For special case of Invariant, the string is "failed
529 -- invariant from yy", to be consistent with the string that is
530 -- generated for the aspect case (the code later on checks for
531 -- this specific string to modify it in some cases, so this is
532 -- functionally important).
534 elsif Nam
= Name_Invariant
then
535 Add_Str_To_Name_Buffer
("failed invariant from ");
537 -- For all other checks, the string is "xxx failed at yyy"
538 -- where xxx is the check name with appropriate casing.
541 Get_Name_String
(Nam
);
543 (Identifier_Casing
(Source_Index
(Current_Sem_Unit
)));
544 Add_Str_To_Name_Buffer
(" failed at ");
547 -- In all cases, add location string
549 Add_Str_To_Name_Buffer
(Loc_Str
);
553 Msg
:= Make_String_Literal
(Loc
, Name_Buffer
(1 .. Name_Len
));
557 -- For a precondition, replace references to discriminants of a
558 -- protected type with the local discriminals.
560 if Is_Protected_Type
(Scope
(Current_Scope
))
561 and then Has_Discriminants
(Scope
(Current_Scope
))
562 and then From_Aspect_Specification
(N
)
564 Replace_Discriminals_Of_Protected_Op
(Cond
);
567 -- Now rewrite as an if statement
570 Make_If_Statement
(Loc
,
571 Condition
=> Make_Op_Not
(Loc
, Right_Opnd
=> Cond
),
572 Then_Statements
=> New_List
(
573 Make_Procedure_Call_Statement
(Loc
,
575 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
576 Parameter_Associations
=> New_List
(Relocate_Node
(Msg
))))));
581 -- If new condition is always false, give a warning
583 if Warn_On_Assertion_Failure
584 and then Nkind
(N
) = N_Procedure_Call_Statement
585 and then Is_RTE
(Entity
(Name
(N
)), RE_Raise_Assert_Failure
)
587 -- If original condition was a Standard.False, we assume that this is
588 -- indeed intended to raise assert error and no warning is required.
590 if Is_Entity_Name
(Original_Node
(Cond
))
591 and then Entity
(Original_Node
(Cond
)) = Standard_False
595 elsif Nam
= Name_Assert
then
596 Error_Msg_N
("?A?assertion will fail at run time", N
);
598 Error_Msg_N
("?A?check will fail at run time", N
);
601 end Expand_Pragma_Check
;
603 ---------------------------------
604 -- Expand_Pragma_Common_Object --
605 ---------------------------------
607 -- Use a machine attribute to replicate semantic effect in DEC Ada
609 -- pragma Machine_Attribute (intern_name, "common_object", extern_name);
611 -- For now we do nothing with the size attribute ???
613 -- Note: Psect_Object shares this processing
615 procedure Expand_Pragma_Common_Object
(N
: Node_Id
) is
616 Loc
: constant Source_Ptr
:= Sloc
(N
);
618 Internal
: constant Node_Id
:= Arg1
(N
);
619 External
: constant Node_Id
:= Arg2
(N
);
622 -- Psect value upper cased as string literal
624 Iloc
: constant Source_Ptr
:= Sloc
(Internal
);
625 Eloc
: constant Source_Ptr
:= Sloc
(External
);
629 -- Acquire Psect value and fold to upper case
631 if Present
(External
) then
632 if Nkind
(External
) = N_String_Literal
then
633 String_To_Name_Buffer
(Strval
(External
));
635 Get_Name_String
(Chars
(External
));
641 Make_String_Literal
(Eloc
, Strval
=> String_From_Name_Buffer
);
644 Get_Name_String
(Chars
(Internal
));
647 Make_String_Literal
(Iloc
, Strval
=> String_From_Name_Buffer
);
650 Ploc
:= Sloc
(Psect
);
654 Insert_After_And_Analyze
(N
,
656 Chars
=> Name_Machine_Attribute
,
657 Pragma_Argument_Associations
=> New_List
(
658 Make_Pragma_Argument_Association
(Iloc
,
659 Expression
=> New_Copy_Tree
(Internal
)),
660 Make_Pragma_Argument_Association
(Eloc
,
662 Make_String_Literal
(Sloc
=> Ploc
, Strval
=> "common_object")),
663 Make_Pragma_Argument_Association
(Ploc
,
664 Expression
=> New_Copy_Tree
(Psect
)))));
665 end Expand_Pragma_Common_Object
;
667 ----------------------------------
668 -- Expand_Pragma_Contract_Cases --
669 ----------------------------------
671 -- Pragma Contract_Cases is expanded in the following manner:
674 -- Count : Natural := 0;
675 -- Flag_1 : Boolean := False;
677 -- Flag_N : Boolean := False;
678 -- Flag_N+1 : Boolean := False; -- when "others" present
683 -- <preconditions (if any)>
685 -- -- Evaluate all case guards
687 -- if Case_Guard_1 then
689 -- Count := Count + 1;
692 -- if Case_Guard_N then
694 -- Count := Count + 1;
697 -- -- Emit errors depending on the number of case guards that
698 -- -- evaluated to True.
701 -- raise Assertion_Error with "xxx contract cases incomplete";
703 -- Flag_N+1 := True; -- when "others" present
705 -- elsif Count > 1 then
707 -- Str0 : constant String :=
708 -- "contract cases overlap for subprogram ABC";
709 -- Str1 : constant String :=
711 -- Str0 & "case guard at xxx evaluates to True"
713 -- StrN : constant String :=
715 -- StrN-1 & "case guard at xxx evaluates to True"
718 -- raise Assertion_Error with StrN;
722 -- -- Evaluate all attribute 'Old prefixes found in the selected
726 -- Pref_1 := <prefix of 'Old found in Consequence_1>
729 -- Pref_M := <prefix of 'Old found in Consequence_N>
732 -- procedure _Postconditions is
734 -- <postconditions (if any)>
736 -- if Flag_1 and then not Consequence_1 then
737 -- raise Assertion_Error with "failed contract case at xxx";
740 -- if Flag_N[+1] and then not Consequence_N[+1] then
741 -- raise Assertion_Error with "failed contract case at xxx";
743 -- end _Postconditions;
748 procedure Expand_Pragma_Contract_Cases
752 Stmts
: in out List_Id
)
754 Loc
: constant Source_Ptr
:= Sloc
(CCs
);
756 procedure Case_Guard_Error
759 Error_Loc
: Source_Ptr
;
760 Msg
: in out Entity_Id
);
761 -- Given a declarative list Decls, status flag Flag, the location of the
762 -- error and a string Msg, construct the following check:
763 -- Msg : constant String :=
765 -- Msg & "case guard at Error_Loc evaluates to True"
767 -- The resulting code is added to Decls
769 procedure Consequence_Error
770 (Checks
: in out Node_Id
;
773 -- Given an if statement Checks, status flag Flag and a consequence
774 -- Conseq, construct the following check:
775 -- [els]if Flag and then not Conseq then
776 -- raise Assertion_Error
777 -- with "failed contract case at Sloc (Conseq)";
779 -- The resulting code is added to Checks
781 function Declaration_Of
(Id
: Entity_Id
) return Node_Id
;
782 -- Given the entity Id of a boolean flag, generate:
783 -- Id : Boolean := False;
785 procedure Expand_Attributes_In_Consequence
787 Evals
: in out Node_Id
;
790 -- Perform specialized expansion of all attribute 'Old references found
791 -- in consequence Conseq such that at runtime only prefixes coming from
792 -- the selected consequence are evaluated. Similarly expand attribute
793 -- 'Result references by replacing them with identifier _result which
794 -- resolves to the sole formal parameter of procedure _Postconditions.
795 -- Any temporaries generated in the process are added to declarations
796 -- Decls. Evals is a complex if statement tasked with the evaluation of
797 -- all prefixes coming from a single selected consequence. Flag is the
798 -- corresponding case guard flag. Conseq is the consequence expression.
800 function Increment
(Id
: Entity_Id
) return Node_Id
;
801 -- Given the entity Id of a numerical variable, generate:
804 function Set
(Id
: Entity_Id
) return Node_Id
;
805 -- Given the entity Id of a boolean variable, generate:
808 ----------------------
809 -- Case_Guard_Error --
810 ----------------------
812 procedure Case_Guard_Error
815 Error_Loc
: Source_Ptr
;
816 Msg
: in out Entity_Id
)
818 New_Line
: constant Character := Character'Val (10);
819 New_Msg
: constant Entity_Id
:= Make_Temporary
(Loc
, 'S');
823 Store_String_Char
(New_Line
);
824 Store_String_Chars
(" case guard at ");
825 Store_String_Chars
(Build_Location_String
(Error_Loc
));
826 Store_String_Chars
(" evaluates to True");
829 -- New_Msg : constant String :=
831 -- Msg & "case guard at Error_Loc evaluates to True"
835 Make_Object_Declaration
(Loc
,
836 Defining_Identifier
=> New_Msg
,
837 Constant_Present
=> True,
838 Object_Definition
=> New_Occurrence_Of
(Standard_String
, Loc
),
840 Make_If_Expression
(Loc
,
841 Expressions
=> New_List
(
842 New_Occurrence_Of
(Flag
, Loc
),
845 Left_Opnd
=> New_Occurrence_Of
(Msg
, Loc
),
846 Right_Opnd
=> Make_String_Literal
(Loc
, End_String
)),
848 New_Occurrence_Of
(Msg
, Loc
)))));
851 end Case_Guard_Error
;
853 -----------------------
854 -- Consequence_Error --
855 -----------------------
857 procedure Consequence_Error
858 (Checks
: in out Node_Id
;
867 -- Flag and then not Conseq
871 Left_Opnd
=> New_Occurrence_Of
(Flag
, Loc
),
874 Right_Opnd
=> Relocate_Node
(Conseq
)));
877 -- raise Assertion_Error
878 -- with "failed contract case at Sloc (Conseq)";
881 Store_String_Chars
("failed contract case at ");
882 Store_String_Chars
(Build_Location_String
(Sloc
(Conseq
)));
885 Make_Procedure_Call_Statement
(Loc
,
887 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
888 Parameter_Associations
=> New_List
(
889 Make_String_Literal
(Loc
, End_String
)));
893 Make_Implicit_If_Statement
(CCs
,
895 Then_Statements
=> New_List
(Error
));
898 if No
(Elsif_Parts
(Checks
)) then
899 Set_Elsif_Parts
(Checks
, New_List
);
902 Append_To
(Elsif_Parts
(Checks
),
903 Make_Elsif_Part
(Loc
,
905 Then_Statements
=> New_List
(Error
)));
907 end Consequence_Error
;
913 function Declaration_Of
(Id
: Entity_Id
) return Node_Id
is
916 Make_Object_Declaration
(Loc
,
917 Defining_Identifier
=> Id
,
918 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
919 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
));
922 --------------------------------------
923 -- Expand_Attributes_In_Consequence --
924 --------------------------------------
926 procedure Expand_Attributes_In_Consequence
928 Evals
: in out Node_Id
;
932 Eval_Stmts
: List_Id
:= No_List
;
933 -- The evaluation sequence expressed as assignment statements of all
934 -- prefixes of attribute 'Old found in the current consequence.
936 function Expand_Attributes
(N
: Node_Id
) return Traverse_Result
;
937 -- Determine whether an arbitrary node denotes attribute 'Old or
938 -- 'Result and if it does, perform all expansion-related actions.
940 -----------------------
941 -- Expand_Attributes --
942 -----------------------
944 function Expand_Attributes
(N
: Node_Id
) return Traverse_Result
is
952 if Nkind
(N
) = N_Attribute_Reference
953 and then Attribute_Name
(N
) = Name_Old
956 Temp
:= Make_Temporary
(Loc
, 'T', Pref
);
957 Set_Etype
(Temp
, Etype
(Pref
));
959 -- Generate a temporary to capture the value of the prefix:
960 -- Temp : <Pref type>;
963 Make_Object_Declaration
(Loc
,
964 Defining_Identifier
=> Temp
,
966 New_Occurrence_Of
(Etype
(Pref
), Loc
));
968 -- Place that temporary at the beginning of declarations, to
969 -- prevent anomalies in the GNATprove flow-analysis pass in
970 -- the precondition procedure that follows.
972 Prepend_To
(Decls
, Decl
);
974 -- If the type is unconstrained, the prefix provides its
975 -- value and constraint, so add it to declaration.
977 if not Is_Constrained
(Etype
(Pref
))
978 and then Is_Entity_Name
(Pref
)
980 Set_Expression
(Decl
, Pref
);
983 -- Otherwise add an assignment statement to temporary using
989 if No
(Eval_Stmts
) then
990 Eval_Stmts
:= New_List
;
993 Append_To
(Eval_Stmts
,
994 Make_Assignment_Statement
(Loc
,
995 Name
=> New_Occurrence_Of
(Temp
, Loc
),
996 Expression
=> Pref
));
1000 -- Ensure that the prefix is valid
1002 if Validity_Checks_On
and then Validity_Check_Operands
then
1003 Ensure_Valid
(Pref
);
1006 -- Replace the original attribute 'Old by a reference to the
1007 -- generated temporary.
1009 Rewrite
(N
, New_Occurrence_Of
(Temp
, Loc
));
1011 -- Attribute 'Result
1013 elsif Is_Attribute_Result
(N
) then
1014 Rewrite
(N
, Make_Identifier
(Loc
, Name_uResult
));
1018 end Expand_Attributes
;
1020 procedure Expand_Attributes_In
is
1021 new Traverse_Proc
(Expand_Attributes
);
1023 -- Start of processing for Expand_Attributes_In_Consequence
1026 -- Inspect the consequence and expand any attribute 'Old and 'Result
1027 -- references found within.
1029 Expand_Attributes_In
(Conseq
);
1031 -- The consequence does not contain any attribute 'Old references
1033 if No
(Eval_Stmts
) then
1037 -- Augment the machinery to trigger the evaluation of all prefixes
1038 -- found in the step above. If Eval is empty, then this is the first
1039 -- consequence to yield expansion of 'Old. Generate:
1042 -- <evaluation statements>
1047 Make_Implicit_If_Statement
(CCs
,
1048 Condition
=> New_Occurrence_Of
(Flag
, Loc
),
1049 Then_Statements
=> Eval_Stmts
);
1051 -- Otherwise generate:
1053 -- <evaluation statements>
1057 if No
(Elsif_Parts
(Evals
)) then
1058 Set_Elsif_Parts
(Evals
, New_List
);
1061 Append_To
(Elsif_Parts
(Evals
),
1062 Make_Elsif_Part
(Loc
,
1063 Condition
=> New_Occurrence_Of
(Flag
, Loc
),
1064 Then_Statements
=> Eval_Stmts
));
1066 end Expand_Attributes_In_Consequence
;
1072 function Increment
(Id
: Entity_Id
) return Node_Id
is
1075 Make_Assignment_Statement
(Loc
,
1076 Name
=> New_Occurrence_Of
(Id
, Loc
),
1079 Left_Opnd
=> New_Occurrence_Of
(Id
, Loc
),
1080 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)));
1087 function Set
(Id
: Entity_Id
) return Node_Id
is
1090 Make_Assignment_Statement
(Loc
,
1091 Name
=> New_Occurrence_Of
(Id
, Loc
),
1092 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
));
1097 Aggr
: constant Node_Id
:=
1098 Expression
(First
(Pragma_Argument_Associations
(CCs
)));
1100 Case_Guard
: Node_Id
;
1101 CG_Checks
: Node_Id
;
1104 Conseq_Checks
: Node_Id
:= Empty
;
1106 Count_Decl
: Node_Id
;
1107 Error_Decls
: List_Id
:= No_List
; -- init to avoid warning
1109 Flag_Decl
: Node_Id
;
1111 Msg_Str
: Entity_Id
:= Empty
;
1112 Multiple_PCs
: Boolean;
1113 Old_Evals
: Node_Id
:= Empty
;
1114 Others_Decl
: Node_Id
;
1115 Others_Flag
: Entity_Id
:= Empty
;
1116 Post_Case
: Node_Id
;
1118 -- Start of processing for Expand_Pragma_Contract_Cases
1121 -- Do nothing if pragma is not enabled. If pragma is disabled, it has
1122 -- already been rewritten as a Null statement.
1124 if Is_Ignored
(CCs
) then
1127 -- Guard against malformed contract cases
1129 elsif Nkind
(Aggr
) /= N_Aggregate
then
1133 -- The expansion of contract cases is quite distributed as it produces
1134 -- various statements to evaluate the case guards and consequences. To
1135 -- preserve the original context, set the Is_Assertion_Expr flag. This
1136 -- aids the Ghost legality checks when verifying the placement of a
1137 -- reference to a Ghost entity.
1139 In_Assertion_Expr
:= In_Assertion_Expr
+ 1;
1141 Multiple_PCs
:= List_Length
(Component_Associations
(Aggr
)) > 1;
1143 -- Create the counter which tracks the number of case guards that
1144 -- evaluate to True.
1146 -- Count : Natural := 0;
1148 Count
:= Make_Temporary
(Loc
, 'C');
1150 Make_Object_Declaration
(Loc
,
1151 Defining_Identifier
=> Count
,
1152 Object_Definition
=> New_Occurrence_Of
(Standard_Natural
, Loc
),
1153 Expression
=> Make_Integer_Literal
(Loc
, 0));
1155 Prepend_To
(Decls
, Count_Decl
);
1156 Analyze
(Count_Decl
);
1158 -- Create the base error message for multiple overlapping case guards
1160 -- Msg_Str : constant String :=
1161 -- "contract cases overlap for subprogram Subp_Id";
1163 if Multiple_PCs
then
1164 Msg_Str
:= Make_Temporary
(Loc
, 'S');
1167 Store_String_Chars
("contract cases overlap for subprogram ");
1168 Store_String_Chars
(Get_Name_String
(Chars
(Subp_Id
)));
1170 Error_Decls
:= New_List
(
1171 Make_Object_Declaration
(Loc
,
1172 Defining_Identifier
=> Msg_Str
,
1173 Constant_Present
=> True,
1174 Object_Definition
=> New_Occurrence_Of
(Standard_String
, Loc
),
1175 Expression
=> Make_String_Literal
(Loc
, End_String
)));
1178 -- Process individual post cases
1180 Post_Case
:= First
(Component_Associations
(Aggr
));
1181 while Present
(Post_Case
) loop
1182 Case_Guard
:= First
(Choices
(Post_Case
));
1183 Conseq
:= Expression
(Post_Case
);
1185 -- The "others" choice requires special processing
1187 if Nkind
(Case_Guard
) = N_Others_Choice
then
1188 Others_Flag
:= Make_Temporary
(Loc
, 'F');
1189 Others_Decl
:= Declaration_Of
(Others_Flag
);
1191 Prepend_To
(Decls
, Others_Decl
);
1192 Analyze
(Others_Decl
);
1194 -- Check possible overlap between a case guard and "others"
1196 if Multiple_PCs
and Exception_Extra_Info
then
1198 (Decls
=> Error_Decls
,
1199 Flag
=> Others_Flag
,
1200 Error_Loc
=> Sloc
(Case_Guard
),
1204 -- Inspect the consequence and perform special expansion of any
1205 -- attribute 'Old and 'Result references found within.
1207 Expand_Attributes_In_Consequence
1210 Flag
=> Others_Flag
,
1213 -- Check the corresponding consequence of "others"
1216 (Checks
=> Conseq_Checks
,
1217 Flag
=> Others_Flag
,
1220 -- Regular post case
1223 -- Create the flag which tracks the state of its associated case
1226 Flag
:= Make_Temporary
(Loc
, 'F');
1227 Flag_Decl
:= Declaration_Of
(Flag
);
1229 Prepend_To
(Decls
, Flag_Decl
);
1230 Analyze
(Flag_Decl
);
1232 -- The flag is set when the case guard is evaluated to True
1233 -- if Case_Guard then
1235 -- Count := Count + 1;
1239 Make_Implicit_If_Statement
(CCs
,
1240 Condition
=> Relocate_Node
(Case_Guard
),
1241 Then_Statements
=> New_List
(
1243 Increment
(Count
)));
1245 Append_To
(Decls
, If_Stmt
);
1248 -- Check whether this case guard overlaps with another one
1250 if Multiple_PCs
and Exception_Extra_Info
then
1252 (Decls
=> Error_Decls
,
1254 Error_Loc
=> Sloc
(Case_Guard
),
1258 -- Inspect the consequence and perform special expansion of any
1259 -- attribute 'Old and 'Result references found within.
1261 Expand_Attributes_In_Consequence
1267 -- The corresponding consequence of the case guard which evaluated
1268 -- to True must hold on exit from the subprogram.
1271 (Checks
=> Conseq_Checks
,
1279 -- Raise Assertion_Error when none of the case guards evaluate to True.
1280 -- The only exception is when we have "others", in which case there is
1281 -- no error because "others" acts as a default True.
1286 if Present
(Others_Flag
) then
1287 CG_Stmts
:= New_List
(Set
(Others_Flag
));
1290 -- raise Assertion_Error with "xxx contract cases incomplete";
1294 Store_String_Chars
(Build_Location_String
(Loc
));
1295 Store_String_Chars
(" contract cases incomplete");
1297 CG_Stmts
:= New_List
(
1298 Make_Procedure_Call_Statement
(Loc
,
1300 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
1301 Parameter_Associations
=> New_List
(
1302 Make_String_Literal
(Loc
, End_String
))));
1306 Make_Implicit_If_Statement
(CCs
,
1309 Left_Opnd
=> New_Occurrence_Of
(Count
, Loc
),
1310 Right_Opnd
=> Make_Integer_Literal
(Loc
, 0)),
1311 Then_Statements
=> CG_Stmts
);
1313 -- Detect a possible failure due to several case guards evaluating to
1317 -- elsif Count > 0 then
1321 -- raise Assertion_Error with <Msg_Str>;
1324 if Multiple_PCs
then
1325 Set_Elsif_Parts
(CG_Checks
, New_List
(
1326 Make_Elsif_Part
(Loc
,
1329 Left_Opnd
=> New_Occurrence_Of
(Count
, Loc
),
1330 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)),
1332 Then_Statements
=> New_List
(
1333 Make_Block_Statement
(Loc
,
1334 Declarations
=> Error_Decls
,
1335 Handled_Statement_Sequence
=>
1336 Make_Handled_Sequence_Of_Statements
(Loc
,
1337 Statements
=> New_List
(
1338 Make_Procedure_Call_Statement
(Loc
,
1341 (RTE
(RE_Raise_Assert_Failure
), Loc
),
1342 Parameter_Associations
=> New_List
(
1343 New_Occurrence_Of
(Msg_Str
, Loc
))))))))));
1346 Append_To
(Decls
, CG_Checks
);
1347 Analyze
(CG_Checks
);
1349 -- Once all case guards are evaluated and checked, evaluate any prefixes
1350 -- of attribute 'Old founds in the selected consequence.
1352 if Present
(Old_Evals
) then
1353 Append_To
(Decls
, Old_Evals
);
1354 Analyze
(Old_Evals
);
1357 -- Raise Assertion_Error when the corresponding consequence of a case
1358 -- guard that evaluated to True fails.
1364 Append_To
(Stmts
, Conseq_Checks
);
1366 In_Assertion_Expr
:= In_Assertion_Expr
- 1;
1367 end Expand_Pragma_Contract_Cases
;
1369 ---------------------------------------
1370 -- Expand_Pragma_Import_Or_Interface --
1371 ---------------------------------------
1373 procedure Expand_Pragma_Import_Or_Interface
(N
: Node_Id
) is
1377 -- In Relaxed_RM_Semantics, support old Ada 83 style:
1378 -- pragma Import (Entity, "external name");
1380 if Relaxed_RM_Semantics
1381 and then List_Length
(Pragma_Argument_Associations
(N
)) = 2
1382 and then Pragma_Name
(N
) = Name_Import
1383 and then Nkind
(Arg2
(N
)) = N_String_Literal
1385 Def_Id
:= Entity
(Arg1
(N
));
1387 Def_Id
:= Entity
(Arg2
(N
));
1390 -- Variable case (we have to undo any initialization already done)
1392 if Ekind
(Def_Id
) = E_Variable
then
1393 Undo_Initialization
(Def_Id
, N
);
1395 -- Case of exception with convention C++
1397 elsif Ekind
(Def_Id
) = E_Exception
1398 and then Convention
(Def_Id
) = Convention_CPP
1400 -- Import a C++ convention
1403 Loc
: constant Source_Ptr
:= Sloc
(N
);
1404 Rtti_Name
: constant Node_Id
:= Arg3
(N
);
1405 Dum
: constant Entity_Id
:= Make_Temporary
(Loc
, 'D');
1407 Lang_Char
: Node_Id
;
1408 Foreign_Data
: Node_Id
;
1411 Exdata
:= Component_Associations
(Expression
(Parent
(Def_Id
)));
1413 Lang_Char
:= Next
(First
(Exdata
));
1415 -- Change the one-character language designator to 'C'
1417 Rewrite
(Expression
(Lang_Char
),
1418 Make_Character_Literal
(Loc
,
1420 Char_Literal_Value
=> UI_From_Int
(Character'Pos ('C'))));
1421 Analyze
(Expression
(Lang_Char
));
1423 -- Change the value of Foreign_Data
1425 Foreign_Data
:= Next
(Next
(Next
(Next
(Lang_Char
))));
1427 Insert_Actions
(Def_Id
, New_List
(
1428 Make_Object_Declaration
(Loc
,
1429 Defining_Identifier
=> Dum
,
1430 Object_Definition
=>
1431 New_Occurrence_Of
(Standard_Character
, Loc
)),
1434 Chars
=> Name_Import
,
1435 Pragma_Argument_Associations
=> New_List
(
1436 Make_Pragma_Argument_Association
(Loc
,
1437 Expression
=> Make_Identifier
(Loc
, Name_Ada
)),
1439 Make_Pragma_Argument_Association
(Loc
,
1440 Expression
=> Make_Identifier
(Loc
, Chars
(Dum
))),
1442 Make_Pragma_Argument_Association
(Loc
,
1443 Chars
=> Name_External_Name
,
1444 Expression
=> Relocate_Node
(Rtti_Name
))))));
1446 Rewrite
(Expression
(Foreign_Data
),
1447 Unchecked_Convert_To
(Standard_A_Char
,
1448 Make_Attribute_Reference
(Loc
,
1449 Prefix
=> Make_Identifier
(Loc
, Chars
(Dum
)),
1450 Attribute_Name
=> Name_Address
)));
1451 Analyze
(Expression
(Foreign_Data
));
1454 -- No special expansion required for any other case
1459 end Expand_Pragma_Import_Or_Interface
;
1461 -------------------------------------
1462 -- Expand_Pragma_Initial_Condition --
1463 -------------------------------------
1465 procedure Expand_Pragma_Initial_Condition
1466 (Pack_Id
: Entity_Id
;
1469 procedure Extract_Package_Body_Lists
1470 (Pack_Body
: Node_Id
;
1471 Body_List
: out List_Id
;
1472 Call_List
: out List_Id
;
1473 Spec_List
: out List_Id
);
1474 -- Obtain the various declarative and statement lists of package body
1475 -- Pack_Body needed to insert the initial condition procedure and the
1476 -- call to it. The lists are as follows:
1478 -- * Body_List - used to insert the initial condition procedure body
1480 -- * Call_List - used to insert the call to the initial condition
1483 -- * Spec_List - used to insert the initial condition procedure spec
1485 procedure Extract_Package_Declaration_Lists
1486 (Pack_Decl
: Node_Id
;
1487 Body_List
: out List_Id
;
1488 Call_List
: out List_Id
;
1489 Spec_List
: out List_Id
);
1490 -- Obtain the various declarative lists of package declaration Pack_Decl
1491 -- needed to insert the initial condition procedure and the call to it.
1492 -- The lists are as follows:
1494 -- * Body_List - used to insert the initial condition procedure body
1496 -- * Call_List - used to insert the call to the initial condition
1499 -- * Spec_List - used to insert the initial condition procedure spec
1501 --------------------------------
1502 -- Extract_Package_Body_Lists --
1503 --------------------------------
1505 procedure Extract_Package_Body_Lists
1506 (Pack_Body
: Node_Id
;
1507 Body_List
: out List_Id
;
1508 Call_List
: out List_Id
;
1509 Spec_List
: out List_Id
)
1511 Pack_Spec
: constant Entity_Id
:= Corresponding_Spec
(Pack_Body
);
1518 pragma Assert
(Present
(Pack_Spec
));
1520 -- The different parts of the invariant procedure are inserted as
1523 -- package Pack is package body Pack is
1524 -- <IC spec> <IC body>
1527 -- end Pack; end Pack;
1529 -- The initial condition procedure spec is inserted in the visible
1530 -- declaration of the corresponding package spec.
1532 Extract_Package_Declaration_Lists
1533 (Pack_Decl
=> Unit_Declaration_Node
(Pack_Spec
),
1534 Body_List
=> Dummy_1
,
1535 Call_List
=> Dummy_2
,
1536 Spec_List
=> Spec_List
);
1538 -- The initial condition procedure body is added to the declarations
1539 -- of the package body.
1541 Body_List
:= Declarations
(Pack_Body
);
1543 if No
(Body_List
) then
1544 Body_List
:= New_List
;
1545 Set_Declarations
(Pack_Body
, Body_List
);
1548 -- The call to the initial condition procedure is inserted in the
1549 -- statements of the package body.
1551 HSS
:= Handled_Statement_Sequence
(Pack_Body
);
1555 Make_Handled_Sequence_Of_Statements
(Sloc
(Pack_Body
),
1556 Statements
=> New_List
);
1557 Set_Handled_Statement_Sequence
(Pack_Body
, HSS
);
1560 Call_List
:= Statements
(HSS
);
1561 end Extract_Package_Body_Lists
;
1563 ---------------------------------------
1564 -- Extract_Package_Declaration_Lists --
1565 ---------------------------------------
1567 procedure Extract_Package_Declaration_Lists
1568 (Pack_Decl
: Node_Id
;
1569 Body_List
: out List_Id
;
1570 Call_List
: out List_Id
;
1571 Spec_List
: out List_Id
)
1573 Pack_Spec
: constant Node_Id
:= Specification
(Pack_Decl
);
1576 -- The different parts of the invariant procedure are inserted as
1586 -- The initial condition procedure spec and body are inserted in the
1587 -- visible declarations of the package spec.
1589 Body_List
:= Visible_Declarations
(Pack_Spec
);
1591 if No
(Body_List
) then
1592 Body_List
:= New_List
;
1593 Set_Visible_Declarations
(Pack_Spec
, Body_List
);
1596 Spec_List
:= Body_List
;
1598 -- The call to the initial procedure is inserted in the private
1599 -- declarations of the package spec.
1601 Call_List
:= Private_Declarations
(Pack_Spec
);
1603 if No
(Call_List
) then
1604 Call_List
:= New_List
;
1605 Set_Private_Declarations
(Pack_Spec
, Call_List
);
1607 end Extract_Package_Declaration_Lists
;
1611 IC_Prag
: constant Node_Id
:=
1612 Get_Pragma
(Pack_Id
, Pragma_Initial_Condition
);
1614 Body_List
: List_Id
;
1616 Call_List
: List_Id
;
1617 Call_Loc
: Source_Ptr
;
1620 Proc_Body
: Node_Id
;
1621 Proc_Body_Id
: Entity_Id
;
1622 Proc_Decl
: Node_Id
;
1623 Proc_Id
: Entity_Id
;
1624 Spec_List
: List_Id
;
1626 -- Start of processing for Expand_Pragma_Initial_Condition
1629 -- Nothing to do when the package is not subject to an Initial_Condition
1632 if No
(IC_Prag
) then
1636 Expr
:= Get_Pragma_Arg
(First
(Pragma_Argument_Associations
(IC_Prag
)));
1637 Loc
:= Sloc
(IC_Prag
);
1639 -- Nothing to do when the pragma or its argument are illegal because
1640 -- there is no valid expression to check.
1642 if Error_Posted
(IC_Prag
) or else Error_Posted
(Expr
) then
1646 -- Obtain the various lists of the context where the individual pieces
1647 -- of the initial condition procedure are to be inserted.
1649 if Nkind
(N
) = N_Package_Body
then
1650 Extract_Package_Body_Lists
1652 Body_List
=> Body_List
,
1653 Call_List
=> Call_List
,
1654 Spec_List
=> Spec_List
);
1656 elsif Nkind
(N
) = N_Package_Declaration
then
1657 Extract_Package_Declaration_Lists
1659 Body_List
=> Body_List
,
1660 Call_List
=> Call_List
,
1661 Spec_List
=> Spec_List
);
1663 -- This routine should not be used on anything other than packages
1666 pragma Assert
(False);
1671 Make_Defining_Identifier
(Loc
,
1672 Chars
=> New_External_Name
(Chars
(Pack_Id
), "Initial_Condition"));
1674 Set_Ekind
(Proc_Id
, E_Procedure
);
1675 Set_Is_Initial_Condition_Procedure
(Proc_Id
);
1678 -- procedure <Pack_Id>Initial_Condition;
1681 Make_Subprogram_Declaration
(Loc
,
1682 Make_Procedure_Specification
(Loc
,
1683 Defining_Unit_Name
=> Proc_Id
));
1685 Append_To
(Spec_List
, Proc_Decl
);
1687 -- The initial condition procedure requires debug info when initial
1688 -- condition is subject to Source Coverage Obligations.
1690 if Generate_SCO
then
1691 Set_Debug_Info_Needed
(Proc_Id
);
1695 -- procedure <Pack_Id>Initial_Condition is
1697 -- pragma Check (Initial_Condition, <Expr>);
1698 -- end <Pack_Id>Initial_Condition;
1701 Make_Subprogram_Body
(Loc
,
1703 Copy_Subprogram_Spec
(Specification
(Proc_Decl
)),
1704 Declarations
=> Empty_List
,
1705 Handled_Statement_Sequence
=>
1706 Make_Handled_Sequence_Of_Statements
(Loc
,
1707 Statements
=> New_List
(
1709 Chars
=> Name_Check
,
1710 Pragma_Argument_Associations
=> New_List
(
1711 Make_Pragma_Argument_Association
(Loc
,
1713 Make_Identifier
(Loc
, Name_Initial_Condition
)),
1714 Make_Pragma_Argument_Association
(Loc
,
1715 Expression
=> New_Copy_Tree
(Expr
)))))));
1717 Append_To
(Body_List
, Proc_Body
);
1719 -- The initial condition procedure requires debug info when initial
1720 -- condition is subject to Source Coverage Obligations.
1722 Proc_Body_Id
:= Defining_Entity
(Proc_Body
);
1724 if Generate_SCO
then
1725 Set_Debug_Info_Needed
(Proc_Body_Id
);
1728 -- The location of the initial condition procedure call must be as close
1729 -- as possible to the intended semantic location of the check because
1730 -- the ABE mechanism relies heavily on accurate locations.
1732 Call_Loc
:= End_Keyword_Location
(N
);
1735 -- <Pack_Id>Initial_Condition;
1738 Make_Procedure_Call_Statement
(Call_Loc
,
1739 Name
=> New_Occurrence_Of
(Proc_Id
, Call_Loc
));
1741 Append_To
(Call_List
, Call
);
1743 Analyze
(Proc_Decl
);
1744 Analyze
(Proc_Body
);
1746 end Expand_Pragma_Initial_Condition
;
1748 ------------------------------------
1749 -- Expand_Pragma_Inspection_Point --
1750 ------------------------------------
1752 -- If no argument is given, then we supply a default argument list that
1753 -- includes all objects declared at the source level in all subprograms
1754 -- that enclose the inspection point pragma.
1756 procedure Expand_Pragma_Inspection_Point
(N
: Node_Id
) is
1757 Loc
: constant Source_Ptr
:= Sloc
(N
);
1764 if No
(Pragma_Argument_Associations
(N
)) then
1768 while S
/= Standard_Standard
loop
1769 E
:= First_Entity
(S
);
1770 while Present
(E
) loop
1771 if Comes_From_Source
(E
)
1772 and then Is_Object
(E
)
1773 and then not Is_Entry_Formal
(E
)
1774 and then Ekind
(E
) /= E_Component
1775 and then Ekind
(E
) /= E_Discriminant
1776 and then Ekind
(E
) /= E_Generic_In_Parameter
1777 and then Ekind
(E
) /= E_Generic_In_Out_Parameter
1780 Make_Pragma_Argument_Association
(Loc
,
1781 Expression
=> New_Occurrence_Of
(E
, Loc
)));
1790 Set_Pragma_Argument_Associations
(N
, A
);
1793 -- Expand the arguments of the pragma. Expanding an entity reference
1794 -- is a noop, except in a protected operation, where a reference may
1795 -- have to be transformed into a reference to the corresponding prival.
1796 -- Are there other pragmas that may require this ???
1798 Assoc
:= First
(Pragma_Argument_Associations
(N
));
1799 while Present
(Assoc
) loop
1800 Expand
(Expression
(Assoc
));
1803 end Expand_Pragma_Inspection_Point
;
1805 --------------------------------------
1806 -- Expand_Pragma_Interrupt_Priority --
1807 --------------------------------------
1809 -- Supply default argument if none exists (System.Interrupt_Priority'Last)
1811 procedure Expand_Pragma_Interrupt_Priority
(N
: Node_Id
) is
1812 Loc
: constant Source_Ptr
:= Sloc
(N
);
1814 if No
(Pragma_Argument_Associations
(N
)) then
1815 Set_Pragma_Argument_Associations
(N
, New_List
(
1816 Make_Pragma_Argument_Association
(Loc
,
1818 Make_Attribute_Reference
(Loc
,
1820 New_Occurrence_Of
(RTE
(RE_Interrupt_Priority
), Loc
),
1821 Attribute_Name
=> Name_Last
))));
1823 end Expand_Pragma_Interrupt_Priority
;
1825 --------------------------------
1826 -- Expand_Pragma_Loop_Variant --
1827 --------------------------------
1829 -- Pragma Loop_Variant is expanded in the following manner:
1833 -- for | while ... loop
1834 -- <preceding source statements>
1835 -- pragma Loop_Variant
1836 -- (Increases => Incr_Expr,
1837 -- Decreases => Decr_Expr);
1838 -- <succeeding source statements>
1843 -- Curr_1 : <type of Incr_Expr>;
1844 -- Curr_2 : <type of Decr_Expr>;
1845 -- Old_1 : <type of Incr_Expr>;
1846 -- Old_2 : <type of Decr_Expr>;
1847 -- Flag : Boolean := False;
1849 -- for | while ... loop
1850 -- <preceding source statements>
1857 -- Curr_1 := <Incr_Expr>;
1858 -- Curr_2 := <Decr_Expr>;
1861 -- if Curr_1 /= Old_1 then
1862 -- pragma Check (Loop_Variant, Curr_1 > Old_1);
1864 -- pragma Check (Loop_Variant, Curr_2 < Old_2);
1870 -- <succeeding source statements>
1873 procedure Expand_Pragma_Loop_Variant
(N
: Node_Id
) is
1874 Loc
: constant Source_Ptr
:= Sloc
(N
);
1875 Last_Var
: constant Node_Id
:=
1876 Last
(Pragma_Argument_Associations
(N
));
1878 Curr_Assign
: List_Id
:= No_List
;
1879 Flag_Id
: Entity_Id
:= Empty
;
1880 If_Stmt
: Node_Id
:= Empty
;
1881 Old_Assign
: List_Id
:= No_List
;
1882 Loop_Scop
: Entity_Id
;
1883 Loop_Stmt
: Node_Id
;
1886 procedure Process_Variant
(Variant
: Node_Id
; Is_Last
: Boolean);
1887 -- Process a single increasing / decreasing termination variant. Flag
1888 -- Is_Last should be set when processing the last variant.
1890 ---------------------
1891 -- Process_Variant --
1892 ---------------------
1894 procedure Process_Variant
(Variant
: Node_Id
; Is_Last
: Boolean) is
1898 Old_Val
: Node_Id
) return Node_Id
;
1899 -- Generate a comparison between Curr_Val and Old_Val depending on
1900 -- the change mode (Increases / Decreases) of the variant.
1909 Old_Val
: Node_Id
) return Node_Id
1912 if Chars
(Variant
) = Name_Increases
then
1913 return Make_Op_Gt
(Loc
, Curr_Val
, Old_Val
);
1914 else pragma Assert
(Chars
(Variant
) = Name_Decreases
);
1915 return Make_Op_Lt
(Loc
, Curr_Val
, Old_Val
);
1921 Expr
: constant Node_Id
:= Expression
(Variant
);
1922 Expr_Typ
: constant Entity_Id
:= Etype
(Expr
);
1923 Loc
: constant Source_Ptr
:= Sloc
(Expr
);
1924 Loop_Loc
: constant Source_Ptr
:= Sloc
(Loop_Stmt
);
1925 Curr_Id
: Entity_Id
;
1929 -- Start of processing for Process_Variant
1932 -- All temporaries generated in this routine must be inserted before
1933 -- the related loop statement. Ensure that the proper scope is on the
1934 -- stack when analyzing the temporaries. Note that we also use the
1935 -- Sloc of the related loop.
1937 Push_Scope
(Scope
(Loop_Scop
));
1939 -- Step 1: Create the declaration of the flag which controls the
1940 -- behavior of the assertion on the first iteration of the loop.
1942 if No
(Flag_Id
) then
1945 -- Flag : Boolean := False;
1947 Flag_Id
:= Make_Temporary
(Loop_Loc
, 'F');
1949 Insert_Action
(Loop_Stmt
,
1950 Make_Object_Declaration
(Loop_Loc
,
1951 Defining_Identifier
=> Flag_Id
,
1952 Object_Definition
=>
1953 New_Occurrence_Of
(Standard_Boolean
, Loop_Loc
),
1955 New_Occurrence_Of
(Standard_False
, Loop_Loc
)));
1957 -- Prevent an unwanted optimization where the Current_Value of
1958 -- the flag eliminates the if statement which stores the variant
1959 -- values coming from the previous iteration.
1961 -- Flag : Boolean := False;
1963 -- if Flag then -- condition rewritten to False
1964 -- Old_N := Curr_N; -- and if statement eliminated
1970 Set_Current_Value
(Flag_Id
, Empty
);
1973 -- Step 2: Create the temporaries which store the old and current
1974 -- values of the associated expression.
1977 -- Curr : <type of Expr>;
1979 Curr_Id
:= Make_Temporary
(Loc
, 'C');
1981 Insert_Action
(Loop_Stmt
,
1982 Make_Object_Declaration
(Loop_Loc
,
1983 Defining_Identifier
=> Curr_Id
,
1984 Object_Definition
=> New_Occurrence_Of
(Expr_Typ
, Loop_Loc
)));
1987 -- Old : <type of Expr>;
1989 Old_Id
:= Make_Temporary
(Loc
, 'P');
1991 Insert_Action
(Loop_Stmt
,
1992 Make_Object_Declaration
(Loop_Loc
,
1993 Defining_Identifier
=> Old_Id
,
1994 Object_Definition
=> New_Occurrence_Of
(Expr_Typ
, Loop_Loc
)));
1996 -- Restore original scope after all temporaries have been analyzed
2000 -- Step 3: Store value of the expression from the previous iteration
2002 if No
(Old_Assign
) then
2003 Old_Assign
:= New_List
;
2009 Append_To
(Old_Assign
,
2010 Make_Assignment_Statement
(Loc
,
2011 Name
=> New_Occurrence_Of
(Old_Id
, Loc
),
2012 Expression
=> New_Occurrence_Of
(Curr_Id
, Loc
)));
2014 -- Step 4: Store the current value of the expression
2016 if No
(Curr_Assign
) then
2017 Curr_Assign
:= New_List
;
2023 Append_To
(Curr_Assign
,
2024 Make_Assignment_Statement
(Loc
,
2025 Name
=> New_Occurrence_Of
(Curr_Id
, Loc
),
2026 Expression
=> Relocate_Node
(Expr
)));
2028 -- Step 5: Create corresponding assertion to verify change of value
2031 -- pragma Check (Loop_Variant, Curr <|> Old);
2035 Chars
=> Name_Check
,
2036 Pragma_Argument_Associations
=> New_List
(
2037 Make_Pragma_Argument_Association
(Loc
,
2038 Expression
=> Make_Identifier
(Loc
, Name_Loop_Variant
)),
2039 Make_Pragma_Argument_Association
(Loc
,
2042 Curr_Val
=> New_Occurrence_Of
(Curr_Id
, Loc
),
2043 Old_Val
=> New_Occurrence_Of
(Old_Id
, Loc
)))));
2046 -- if Curr /= Old then
2049 if No
(If_Stmt
) then
2051 -- When there is just one termination variant, do not compare the
2052 -- old and current value for equality, just check the pragma.
2058 Make_If_Statement
(Loc
,
2061 Left_Opnd
=> New_Occurrence_Of
(Curr_Id
, Loc
),
2062 Right_Opnd
=> New_Occurrence_Of
(Old_Id
, Loc
)),
2063 Then_Statements
=> New_List
(Prag
));
2072 Set_Else_Statements
(If_Stmt
, New_List
(Prag
));
2075 -- elsif Curr /= Old then
2079 if Elsif_Parts
(If_Stmt
) = No_List
then
2080 Set_Elsif_Parts
(If_Stmt
, New_List
);
2083 Append_To
(Elsif_Parts
(If_Stmt
),
2084 Make_Elsif_Part
(Loc
,
2087 Left_Opnd
=> New_Occurrence_Of
(Curr_Id
, Loc
),
2088 Right_Opnd
=> New_Occurrence_Of
(Old_Id
, Loc
)),
2089 Then_Statements
=> New_List
(Prag
)));
2091 end Process_Variant
;
2093 -- Start of processing for Expand_Pragma_Loop_Variant
2096 -- If pragma is not enabled, rewrite as Null statement. If pragma is
2097 -- disabled, it has already been rewritten as a Null statement.
2099 if Is_Ignored
(N
) then
2100 Rewrite
(N
, Make_Null_Statement
(Loc
));
2105 -- The expansion of Loop_Variant is quite distributed as it produces
2106 -- various statements to capture and compare the arguments. To preserve
2107 -- the original context, set the Is_Assertion_Expr flag. This aids the
2108 -- Ghost legality checks when verifying the placement of a reference to
2111 In_Assertion_Expr
:= In_Assertion_Expr
+ 1;
2113 -- Locate the enclosing loop for which this assertion applies. In the
2114 -- case of Ada 2012 array iteration, we might be dealing with nested
2115 -- loops. Only the outermost loop has an identifier.
2118 while Present
(Loop_Stmt
) loop
2119 if Nkind
(Loop_Stmt
) = N_Loop_Statement
2120 and then Present
(Identifier
(Loop_Stmt
))
2125 Loop_Stmt
:= Parent
(Loop_Stmt
);
2128 Loop_Scop
:= Entity
(Identifier
(Loop_Stmt
));
2130 -- Create the circuitry which verifies individual variants
2132 Variant
:= First
(Pragma_Argument_Associations
(N
));
2133 while Present
(Variant
) loop
2134 Process_Variant
(Variant
, Is_Last
=> Variant
= Last_Var
);
2138 -- Construct the segment which stores the old values of all expressions.
2145 Make_If_Statement
(Loc
,
2146 Condition
=> New_Occurrence_Of
(Flag_Id
, Loc
),
2147 Then_Statements
=> Old_Assign
));
2149 -- Update the values of all expressions
2151 Insert_Actions
(N
, Curr_Assign
);
2153 -- Add the assertion circuitry to test all changes in expressions.
2162 Make_If_Statement
(Loc
,
2163 Condition
=> New_Occurrence_Of
(Flag_Id
, Loc
),
2164 Then_Statements
=> New_List
(If_Stmt
),
2165 Else_Statements
=> New_List
(
2166 Make_Assignment_Statement
(Loc
,
2167 Name
=> New_Occurrence_Of
(Flag_Id
, Loc
),
2168 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)))));
2170 -- Note: the pragma has been completely transformed into a sequence of
2171 -- corresponding declarations and statements. We leave it in the tree
2172 -- for documentation purposes. It will be ignored by the backend.
2174 In_Assertion_Expr
:= In_Assertion_Expr
- 1;
2175 end Expand_Pragma_Loop_Variant
;
2177 --------------------------------
2178 -- Expand_Pragma_Psect_Object --
2179 --------------------------------
2181 -- Convert to Common_Object, and expand the resulting pragma
2183 procedure Expand_Pragma_Psect_Object
(N
: Node_Id
)
2184 renames Expand_Pragma_Common_Object
;
2186 -------------------------------------
2187 -- Expand_Pragma_Relative_Deadline --
2188 -------------------------------------
2190 procedure Expand_Pragma_Relative_Deadline
(N
: Node_Id
) is
2191 P
: constant Node_Id
:= Parent
(N
);
2192 Loc
: constant Source_Ptr
:= Sloc
(N
);
2195 -- Expand the pragma only in the case of the main subprogram. For tasks
2196 -- the expansion is done in exp_ch9. Generate a call to Set_Deadline
2197 -- at Clock plus the relative deadline specified in the pragma. Time
2198 -- values are translated into Duration to allow for non-private
2199 -- addition operation.
2201 if Nkind
(P
) = N_Subprogram_Body
then
2204 Make_Procedure_Call_Statement
(Loc
,
2205 Name
=> New_Occurrence_Of
(RTE
(RE_Set_Deadline
), Loc
),
2206 Parameter_Associations
=> New_List
(
2207 Unchecked_Convert_To
(RTE
(RO_RT_Time
),
2210 Make_Function_Call
(Loc
,
2211 New_Occurrence_Of
(RTE
(RO_RT_To_Duration
), Loc
),
2214 (Loc
, New_Occurrence_Of
(RTE
(RE_Clock
), Loc
)))),
2216 Unchecked_Convert_To
(Standard_Duration
, Arg1
(N
)))))));
2220 end Expand_Pragma_Relative_Deadline
;
2222 -------------------------------------------
2223 -- Expand_Pragma_Suppress_Initialization --
2224 -------------------------------------------
2226 procedure Expand_Pragma_Suppress_Initialization
(N
: Node_Id
) is
2227 Def_Id
: constant Entity_Id
:= Entity
(Arg1
(N
));
2230 -- Variable case (we have to undo any initialization already done)
2232 if Ekind
(Def_Id
) = E_Variable
then
2233 Undo_Initialization
(Def_Id
, N
);
2235 end Expand_Pragma_Suppress_Initialization
;
2237 -------------------------
2238 -- Undo_Initialization --
2239 -------------------------
2241 procedure Undo_Initialization
(Def_Id
: Entity_Id
; N
: Node_Id
) is
2242 Init_Call
: Node_Id
;
2245 -- When applied to a variable, the default initialization must not be
2246 -- done. As it is already done when the pragma is found, we just get rid
2247 -- of the call the initialization procedure which followed the object
2248 -- declaration. The call is inserted after the declaration, but validity
2249 -- checks may also have been inserted and thus the initialization call
2250 -- does not necessarily appear immediately after the object declaration.
2252 -- We can't use the freezing mechanism for this purpose, since we have
2253 -- to elaborate the initialization expression when it is first seen (so
2254 -- this elaboration cannot be deferred to the freeze point).
2256 -- Find and remove generated initialization call for object, if any
2258 Init_Call
:= Remove_Init_Call
(Def_Id
, Rep_Clause
=> N
);
2260 -- Any default initialization expression should be removed (e.g.
2261 -- null defaults for access objects, zero initialization of packed
2262 -- bit arrays). Imported objects aren't allowed to have explicit
2263 -- initialization, so the expression must have been generated by
2266 if No
(Init_Call
) and then Present
(Expression
(Parent
(Def_Id
))) then
2267 Set_Expression
(Parent
(Def_Id
), Empty
);
2270 -- The object may not have any initialization, but in the presence of
2271 -- Initialize_Scalars code is inserted after then declaration, which
2272 -- must now be removed as well. The code carries the same source
2273 -- location as the declaration itself.
2275 if Initialize_Scalars
and then Is_Array_Type
(Etype
(Def_Id
)) then
2280 Init
:= Next
(Parent
(Def_Id
));
2281 while not Comes_From_Source
(Init
)
2282 and then Sloc
(Init
) = Sloc
(Def_Id
)
2290 end Undo_Initialization
;