1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2015, 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 Ghost
; use Ghost
;
36 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_Ch8
; use Sem_Ch8
;
46 with Sem_Util
; use Sem_Util
;
47 with Sinfo
; use Sinfo
;
48 with Sinput
; use Sinput
;
49 with Snames
; use Snames
;
50 with Stringt
; use Stringt
;
51 with Stand
; use Stand
;
52 with Tbuild
; use Tbuild
;
53 with Uintp
; use Uintp
;
54 with Validsw
; use Validsw
;
56 package body Exp_Prag
is
58 -----------------------
59 -- Local Subprograms --
60 -----------------------
62 function Arg1
(N
: Node_Id
) return Node_Id
;
63 function Arg2
(N
: Node_Id
) return Node_Id
;
64 function Arg3
(N
: Node_Id
) return Node_Id
;
65 -- Obtain specified pragma argument expression
67 procedure Expand_Pragma_Abort_Defer
(N
: Node_Id
);
68 procedure Expand_Pragma_Check
(N
: Node_Id
);
69 procedure Expand_Pragma_Common_Object
(N
: Node_Id
);
70 procedure Expand_Pragma_Import_Or_Interface
(N
: Node_Id
);
71 procedure Expand_Pragma_Inspection_Point
(N
: Node_Id
);
72 procedure Expand_Pragma_Interrupt_Priority
(N
: Node_Id
);
73 procedure Expand_Pragma_Loop_Variant
(N
: Node_Id
);
74 procedure Expand_Pragma_Psect_Object
(N
: Node_Id
);
75 procedure Expand_Pragma_Relative_Deadline
(N
: Node_Id
);
76 procedure Expand_Pragma_Suppress_Initialization
(N
: Node_Id
);
78 procedure Undo_Initialization
(Def_Id
: Entity_Id
; N
: Node_Id
);
79 -- This procedure is used to undo initialization already done for Def_Id,
80 -- which is always an E_Variable, in response to the occurrence of the
81 -- pragma N, a pragma Interface, Import, or Suppress_Initialization. In all
82 -- these cases we want no initialization to occur, but we have already done
83 -- the initialization by the time we see the pragma, so we have to undo it.
89 function Arg1
(N
: Node_Id
) return Node_Id
is
90 Arg
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
93 and then Nkind
(Arg
) = N_Pragma_Argument_Association
95 return Expression
(Arg
);
105 function Arg2
(N
: Node_Id
) return Node_Id
is
106 Arg1
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
114 Arg
: constant Node_Id
:= Next
(Arg1
);
117 and then Nkind
(Arg
) = N_Pragma_Argument_Association
119 return Expression
(Arg
);
131 function Arg3
(N
: Node_Id
) return Node_Id
is
132 Arg1
: constant Node_Id
:= First
(Pragma_Argument_Associations
(N
));
140 Arg
: Node_Id
:= Next
(Arg1
);
149 and then Nkind
(Arg
) = N_Pragma_Argument_Association
151 return Expression
(Arg
);
160 ---------------------
161 -- Expand_N_Pragma --
162 ---------------------
164 procedure Expand_N_Pragma
(N
: Node_Id
) is
165 Pname
: constant Name_Id
:= Pragma_Name
(N
);
168 -- Rewrite pragma ignored by Ignore_Pragma to null statement, so that
169 -- the back end or the expander here does not get overenthusiastic and
170 -- start processing such a pragma!
172 if Get_Name_Table_Boolean3
(Pname
) then
173 Rewrite
(N
, Make_Null_Statement
(Sloc
(N
)));
177 -- Note: we may have a pragma whose Pragma_Identifier field is not a
178 -- recognized pragma, and we must ignore it at this stage.
180 if Is_Pragma_Name
(Pname
) then
181 case Get_Pragma_Id
(Pname
) is
183 -- Pragmas requiring special expander action
185 when Pragma_Abort_Defer
=>
186 Expand_Pragma_Abort_Defer
(N
);
189 Expand_Pragma_Check
(N
);
191 when Pragma_Common_Object
=>
192 Expand_Pragma_Common_Object
(N
);
194 when Pragma_Import
=>
195 Expand_Pragma_Import_Or_Interface
(N
);
197 when Pragma_Inspection_Point
=>
198 Expand_Pragma_Inspection_Point
(N
);
200 when Pragma_Interface
=>
201 Expand_Pragma_Import_Or_Interface
(N
);
203 when Pragma_Interrupt_Priority
=>
204 Expand_Pragma_Interrupt_Priority
(N
);
206 when Pragma_Loop_Variant
=>
207 Expand_Pragma_Loop_Variant
(N
);
209 when Pragma_Psect_Object
=>
210 Expand_Pragma_Psect_Object
(N
);
212 when Pragma_Relative_Deadline
=>
213 Expand_Pragma_Relative_Deadline
(N
);
215 when Pragma_Suppress_Initialization
=>
216 Expand_Pragma_Suppress_Initialization
(N
);
218 -- All other pragmas need no expander action
226 -------------------------------
227 -- Expand_Pragma_Abort_Defer --
228 -------------------------------
230 -- An Abort_Defer pragma appears as the first statement in a handled
231 -- statement sequence (right after the begin). It defers aborts for
232 -- the entire statement sequence, but not for any declarations or
233 -- handlers (if any) associated with this statement sequence.
235 -- The transformation is to transform
237 -- pragma Abort_Defer;
246 -- when all others =>
247 -- Abort_Undefer.all;
250 -- Abort_Undefer_Direct;
253 procedure Expand_Pragma_Abort_Defer
(N
: Node_Id
) is
255 -- Abort_Defer has no useful effect if Abort's are not allowed
257 if not Abort_Allowed
then
261 -- Normal case where abort is possible
264 Loc
: constant Source_Ptr
:= Sloc
(N
);
268 Blk
: constant Entity_Id
:=
269 New_Internal_Entity
(E_Block
, Current_Scope
, Sloc
(N
), 'B');
270 AUD
: constant Entity_Id
:= RTE
(RE_Abort_Undefer_Direct
);
273 Stms
:= New_List
(Build_Runtime_Call
(Loc
, RE_Abort_Defer
));
275 Stm
:= Remove_Next
(N
);
281 Make_Handled_Sequence_Of_Statements
(Loc
,
283 At_End_Proc
=> New_Occurrence_Of
(AUD
, Loc
));
285 -- Present the Abort_Undefer_Direct function to the backend so that
286 -- it can inline the call to the function.
288 Add_Inlined_Body
(AUD
, N
);
291 Make_Block_Statement
(Loc
, Handled_Statement_Sequence
=> HSS
));
293 Set_Scope
(Blk
, Current_Scope
);
294 Set_Etype
(Blk
, Standard_Void_Type
);
295 Set_Identifier
(N
, New_Occurrence_Of
(Blk
, Sloc
(N
)));
296 Expand_At_End_Handler
(HSS
, Blk
);
299 end Expand_Pragma_Abort_Defer
;
301 --------------------------
302 -- Expand_Pragma_Check --
303 --------------------------
305 procedure Expand_Pragma_Check
(N
: Node_Id
) is
306 GM
: constant Ghost_Mode_Type
:= Ghost_Mode
;
307 Cond
: constant Node_Id
:= Arg2
(N
);
308 Nam
: constant Name_Id
:= Chars
(Arg1
(N
));
311 Loc
: constant Source_Ptr
:= Sloc
(First_Node
(Cond
));
312 -- Source location used in the case of a failed assertion: point to the
313 -- failing condition, not Loc. Note that the source location of the
314 -- expression is not usually the best choice here, because it points to
315 -- the location of the topmost tree node, which may be an operator in
316 -- the middle of the source text of the expression. For example, it gets
317 -- located on the last AND keyword in a chain of boolean expressiond
318 -- AND'ed together. It is best to put the message on the first character
319 -- of the condition, which is the effect of the First_Node call here.
320 -- This source location is used to build the default exception message,
321 -- and also as the sloc of the call to the runtime subprogram raising
322 -- Assert_Failure, so that coverage analysis tools can relate the
323 -- call to the failed check.
326 -- Nothing to do if pragma is ignored
328 if Is_Ignored
(N
) then
332 -- Set the Ghost mode in effect from the pragma. In general both the
333 -- assertion policy and the Ghost policy of pragma Check must agree,
334 -- but there are cases where this can be circumvented. For instance,
335 -- a living subtype with an ignored predicate may be declared in one
336 -- packade, an ignored Ghost object in another and the compilation may
337 -- use -gnata to enable assertions.
338 -- ??? Ghost predicates are under redesign
342 -- Since this check is active, we rewrite the pragma into a
343 -- corresponding if statement, and then analyze the statement.
345 -- The normal case expansion transforms:
347 -- pragma Check (name, condition [,message]);
351 -- if not condition then
352 -- System.Assertions.Raise_Assert_Failure (Str);
355 -- where Str is the message if one is present, or the default of
356 -- name failed at file:line if no message is given (the "name failed
357 -- at" is omitted for name = Assertion, since it is redundant, given
358 -- that the name of the exception is Assert_Failure.)
360 -- Also, instead of "XXX failed at", we generate slightly
361 -- different messages for some of the contract assertions (see
362 -- code below for details).
364 -- An alternative expansion is used when the No_Exception_Propagation
365 -- restriction is active and there is a local Assert_Failure handler.
366 -- This is not a common combination of circumstances, but it occurs in
367 -- the context of Aunit and the zero footprint profile. In this case we
370 -- if not condition then
371 -- raise Assert_Failure;
374 -- This will then be transformed into a goto, and the local handler will
375 -- be able to handle the assert error (which would not be the case if a
376 -- call is made to the Raise_Assert_Failure procedure).
378 -- We also generate the direct raise if the Suppress_Exception_Locations
379 -- is active, since we don't want to generate messages in this case.
381 -- Note that the reason we do not always generate a direct raise is that
382 -- the form in which the procedure is called allows for more efficient
383 -- breakpointing of assertion errors.
385 -- Generate the appropriate if statement. Note that we consider this to
386 -- be an explicit conditional in the source, not an implicit if, so we
387 -- do not call Make_Implicit_If_Statement.
389 -- Case where we generate a direct raise
391 if ((Debug_Flag_Dot_G
392 or else Restriction_Active
(No_Exception_Propagation
))
393 and then Present
(Find_Local_Handler
(RTE
(RE_Assert_Failure
), N
)))
394 or else (Opt
.Exception_Locations_Suppressed
and then No
(Arg3
(N
)))
397 Make_If_Statement
(Loc
,
398 Condition
=> Make_Op_Not
(Loc
, Right_Opnd
=> Cond
),
399 Then_Statements
=> New_List
(
400 Make_Raise_Statement
(Loc
,
401 Name
=> New_Occurrence_Of
(RTE
(RE_Assert_Failure
), Loc
)))));
403 -- Case where we call the procedure
406 -- If we have a message given, use it
408 if Present
(Arg3
(N
)) then
409 Msg
:= Get_Pragma_Arg
(Arg3
(N
));
411 -- Here we have no string, so prepare one
415 Loc_Str
: constant String := Build_Location_String
(Loc
);
420 -- For Assert, we just use the location
422 if Nam
= Name_Assert
then
425 -- For predicate, we generate the string "predicate failed at
426 -- yyy". We prefer all lower case for predicate.
428 elsif Nam
= Name_Predicate
then
429 Add_Str_To_Name_Buffer
("predicate failed at ");
431 -- For special case of Precondition/Postcondition the string is
432 -- "failed xx from yy" where xx is precondition/postcondition
433 -- in all lower case. The reason for this different wording is
434 -- that the failure is not at the point of occurrence of the
435 -- pragma, unlike the other Check cases.
437 elsif Nam_In
(Nam
, Name_Precondition
, Name_Postcondition
) then
438 Get_Name_String
(Nam
);
439 Insert_Str_In_Name_Buffer
("failed ", 1);
440 Add_Str_To_Name_Buffer
(" from ");
442 -- For special case of Invariant, the string is "failed
443 -- invariant from yy", to be consistent with the string that is
444 -- generated for the aspect case (the code later on checks for
445 -- this specific string to modify it in some cases, so this is
446 -- functionally important).
448 elsif Nam
= Name_Invariant
then
449 Add_Str_To_Name_Buffer
("failed invariant from ");
451 -- For all other checks, the string is "xxx failed at yyy"
452 -- where xxx is the check name with current source file casing.
455 Get_Name_String
(Nam
);
456 Set_Casing
(Identifier_Casing
(Current_Source_File
));
457 Add_Str_To_Name_Buffer
(" failed at ");
460 -- In all cases, add location string
462 Add_Str_To_Name_Buffer
(Loc_Str
);
466 Msg
:= Make_String_Literal
(Loc
, Name_Buffer
(1 .. Name_Len
));
470 -- Now rewrite as an if statement
473 Make_If_Statement
(Loc
,
474 Condition
=> Make_Op_Not
(Loc
, Right_Opnd
=> Cond
),
475 Then_Statements
=> New_List
(
476 Make_Procedure_Call_Statement
(Loc
,
478 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
479 Parameter_Associations
=> New_List
(Relocate_Node
(Msg
))))));
484 -- If new condition is always false, give a warning
486 if Warn_On_Assertion_Failure
487 and then Nkind
(N
) = N_Procedure_Call_Statement
488 and then Is_RTE
(Entity
(Name
(N
)), RE_Raise_Assert_Failure
)
490 -- If original condition was a Standard.False, we assume that this is
491 -- indeed intended to raise assert error and no warning is required.
493 if Is_Entity_Name
(Original_Node
(Cond
))
494 and then Entity
(Original_Node
(Cond
)) = Standard_False
498 elsif Nam
= Name_Assert
then
499 Error_Msg_N
("?A?assertion will fail at run time", N
);
502 Error_Msg_N
("?A?check will fail at run time", N
);
506 -- Restore the original Ghost mode once analysis and expansion have
510 end Expand_Pragma_Check
;
512 ---------------------------------
513 -- Expand_Pragma_Common_Object --
514 ---------------------------------
516 -- Use a machine attribute to replicate semantic effect in DEC Ada
518 -- pragma Machine_Attribute (intern_name, "common_object", extern_name);
520 -- For now we do nothing with the size attribute ???
522 -- Note: Psect_Object shares this processing
524 procedure Expand_Pragma_Common_Object
(N
: Node_Id
) is
525 Loc
: constant Source_Ptr
:= Sloc
(N
);
527 Internal
: constant Node_Id
:= Arg1
(N
);
528 External
: constant Node_Id
:= Arg2
(N
);
531 -- Psect value upper cased as string literal
533 Iloc
: constant Source_Ptr
:= Sloc
(Internal
);
534 Eloc
: constant Source_Ptr
:= Sloc
(External
);
538 -- Acquire Psect value and fold to upper case
540 if Present
(External
) then
541 if Nkind
(External
) = N_String_Literal
then
542 String_To_Name_Buffer
(Strval
(External
));
544 Get_Name_String
(Chars
(External
));
550 Make_String_Literal
(Eloc
, Strval
=> String_From_Name_Buffer
);
553 Get_Name_String
(Chars
(Internal
));
556 Make_String_Literal
(Iloc
, Strval
=> String_From_Name_Buffer
);
559 Ploc
:= Sloc
(Psect
);
563 Insert_After_And_Analyze
(N
,
565 Chars
=> Name_Machine_Attribute
,
566 Pragma_Argument_Associations
=> New_List
(
567 Make_Pragma_Argument_Association
(Iloc
,
568 Expression
=> New_Copy_Tree
(Internal
)),
569 Make_Pragma_Argument_Association
(Eloc
,
571 Make_String_Literal
(Sloc
=> Ploc
, Strval
=> "common_object")),
572 Make_Pragma_Argument_Association
(Ploc
,
573 Expression
=> New_Copy_Tree
(Psect
)))));
574 end Expand_Pragma_Common_Object
;
576 ----------------------------------
577 -- Expand_Pragma_Contract_Cases --
578 ----------------------------------
580 -- Pragma Contract_Cases is expanded in the following manner:
583 -- Count : Natural := 0;
584 -- Flag_1 : Boolean := False;
586 -- Flag_N : Boolean := False;
587 -- Flag_N+1 : Boolean := False; -- when "others" present
592 -- <preconditions (if any)>
594 -- -- Evaluate all case guards
596 -- if Case_Guard_1 then
598 -- Count := Count + 1;
601 -- if Case_Guard_N then
603 -- Count := Count + 1;
606 -- -- Emit errors depending on the number of case guards that
607 -- -- evaluated to True.
610 -- raise Assertion_Error with "xxx contract cases incomplete";
612 -- Flag_N+1 := True; -- when "others" present
614 -- elsif Count > 1 then
616 -- Str0 : constant String :=
617 -- "contract cases overlap for subprogram ABC";
618 -- Str1 : constant String :=
620 -- Str0 & "case guard at xxx evaluates to True"
622 -- StrN : constant String :=
624 -- StrN-1 & "case guard at xxx evaluates to True"
627 -- raise Assertion_Error with StrN;
631 -- -- Evaluate all attribute 'Old prefixes found in the selected
635 -- Pref_1 := <prefix of 'Old found in Consequence_1>
638 -- Pref_M := <prefix of 'Old found in Consequence_N>
641 -- procedure _Postconditions is
643 -- <postconditions (if any)>
645 -- if Flag_1 and then not Consequence_1 then
646 -- raise Assertion_Error with "failed contract case at xxx";
649 -- if Flag_N[+1] and then not Consequence_N[+1] then
650 -- raise Assertion_Error with "failed contract case at xxx";
652 -- end _Postconditions;
657 procedure Expand_Pragma_Contract_Cases
661 Stmts
: in out List_Id
)
663 Loc
: constant Source_Ptr
:= Sloc
(CCs
);
665 procedure Case_Guard_Error
668 Error_Loc
: Source_Ptr
;
669 Msg
: in out Entity_Id
);
670 -- Given a declarative list Decls, status flag Flag, the location of the
671 -- error and a string Msg, construct the following check:
672 -- Msg : constant String :=
674 -- Msg & "case guard at Error_Loc evaluates to True"
676 -- The resulting code is added to Decls
678 procedure Consequence_Error
679 (Checks
: in out Node_Id
;
682 -- Given an if statement Checks, status flag Flag and a consequence
683 -- Conseq, construct the following check:
684 -- [els]if Flag and then not Conseq then
685 -- raise Assertion_Error
686 -- with "failed contract case at Sloc (Conseq)";
688 -- The resulting code is added to Checks
690 function Declaration_Of
(Id
: Entity_Id
) return Node_Id
;
691 -- Given the entity Id of a boolean flag, generate:
692 -- Id : Boolean := False;
694 procedure Expand_Attributes_In_Consequence
696 Evals
: in out Node_Id
;
699 -- Perform specialized expansion of all attribute 'Old references found
700 -- in consequence Conseq such that at runtime only prefixes coming from
701 -- the selected consequence are evaluated. Similarly expand attribute
702 -- 'Result references by replacing them with identifier _result which
703 -- resolves to the sole formal parameter of procedure _Postconditions.
704 -- Any temporaries generated in the process are added to declarations
705 -- Decls. Evals is a complex if statement tasked with the evaluation of
706 -- all prefixes coming from a single selected consequence. Flag is the
707 -- corresponding case guard flag. Conseq is the consequence expression.
709 function Increment
(Id
: Entity_Id
) return Node_Id
;
710 -- Given the entity Id of a numerical variable, generate:
713 function Set
(Id
: Entity_Id
) return Node_Id
;
714 -- Given the entity Id of a boolean variable, generate:
717 ----------------------
718 -- Case_Guard_Error --
719 ----------------------
721 procedure Case_Guard_Error
724 Error_Loc
: Source_Ptr
;
725 Msg
: in out Entity_Id
)
727 New_Line
: constant Character := Character'Val (10);
728 New_Msg
: constant Entity_Id
:= Make_Temporary
(Loc
, 'S');
732 Store_String_Char
(New_Line
);
733 Store_String_Chars
(" case guard at ");
734 Store_String_Chars
(Build_Location_String
(Error_Loc
));
735 Store_String_Chars
(" evaluates to True");
738 -- New_Msg : constant String :=
740 -- Msg & "case guard at Error_Loc evaluates to True"
744 Make_Object_Declaration
(Loc
,
745 Defining_Identifier
=> New_Msg
,
746 Constant_Present
=> True,
747 Object_Definition
=> New_Occurrence_Of
(Standard_String
, Loc
),
749 Make_If_Expression
(Loc
,
750 Expressions
=> New_List
(
751 New_Occurrence_Of
(Flag
, Loc
),
754 Left_Opnd
=> New_Occurrence_Of
(Msg
, Loc
),
755 Right_Opnd
=> Make_String_Literal
(Loc
, End_String
)),
757 New_Occurrence_Of
(Msg
, Loc
)))));
760 end Case_Guard_Error
;
762 -----------------------
763 -- Consequence_Error --
764 -----------------------
766 procedure Consequence_Error
767 (Checks
: in out Node_Id
;
776 -- Flag and then not Conseq
780 Left_Opnd
=> New_Occurrence_Of
(Flag
, Loc
),
783 Right_Opnd
=> Relocate_Node
(Conseq
)));
786 -- raise Assertion_Error
787 -- with "failed contract case at Sloc (Conseq)";
790 Store_String_Chars
("failed contract case at ");
791 Store_String_Chars
(Build_Location_String
(Sloc
(Conseq
)));
794 Make_Procedure_Call_Statement
(Loc
,
796 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
797 Parameter_Associations
=> New_List
(
798 Make_String_Literal
(Loc
, End_String
)));
802 Make_Implicit_If_Statement
(CCs
,
804 Then_Statements
=> New_List
(Error
));
807 if No
(Elsif_Parts
(Checks
)) then
808 Set_Elsif_Parts
(Checks
, New_List
);
811 Append_To
(Elsif_Parts
(Checks
),
812 Make_Elsif_Part
(Loc
,
814 Then_Statements
=> New_List
(Error
)));
816 end Consequence_Error
;
822 function Declaration_Of
(Id
: Entity_Id
) return Node_Id
is
825 Make_Object_Declaration
(Loc
,
826 Defining_Identifier
=> Id
,
827 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
828 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
));
831 --------------------------------------
832 -- Expand_Attributes_In_Consequence --
833 --------------------------------------
835 procedure Expand_Attributes_In_Consequence
837 Evals
: in out Node_Id
;
841 Eval_Stmts
: List_Id
:= No_List
;
842 -- The evaluation sequence expressed as assignment statements of all
843 -- prefixes of attribute 'Old found in the current consequence.
845 function Expand_Attributes
(N
: Node_Id
) return Traverse_Result
;
846 -- Determine whether an arbitrary node denotes attribute 'Old or
847 -- 'Result and if it does, perform all expansion-related actions.
849 -----------------------
850 -- Expand_Attributes --
851 -----------------------
853 function Expand_Attributes
(N
: Node_Id
) return Traverse_Result
is
861 if Nkind
(N
) = N_Attribute_Reference
862 and then Attribute_Name
(N
) = Name_Old
865 Temp
:= Make_Temporary
(Loc
, 'T', Pref
);
866 Set_Etype
(Temp
, Etype
(Pref
));
868 -- Generate a temporary to capture the value of the prefix:
869 -- Temp : <Pref type>;
870 -- Place that temporary at the beginning of declarations, to
871 -- prevent anomalies in the GNATprove flow-analysis pass in
872 -- the precondition procedure that follows.
875 Make_Object_Declaration
(Loc
,
876 Defining_Identifier
=> Temp
,
878 New_Occurrence_Of
(Etype
(Pref
), Loc
));
879 Set_No_Initialization
(Decl
);
881 Prepend_To
(Decls
, Decl
);
884 -- Evaluate the prefix, generate:
887 if No
(Eval_Stmts
) then
888 Eval_Stmts
:= New_List
;
891 Append_To
(Eval_Stmts
,
892 Make_Assignment_Statement
(Loc
,
893 Name
=> New_Occurrence_Of
(Temp
, Loc
),
894 Expression
=> Pref
));
896 -- Ensure that the prefix is valid
898 if Validity_Checks_On
and then Validity_Check_Operands
then
902 -- Replace the original attribute 'Old by a reference to the
903 -- generated temporary.
905 Rewrite
(N
, New_Occurrence_Of
(Temp
, Loc
));
909 elsif Is_Attribute_Result
(N
) then
910 Rewrite
(N
, Make_Identifier
(Loc
, Name_uResult
));
914 end Expand_Attributes
;
916 procedure Expand_Attributes_In
is
917 new Traverse_Proc
(Expand_Attributes
);
919 -- Start of processing for Expand_Attributes_In_Consequence
922 -- Inspect the consequence and expand any attribute 'Old and 'Result
923 -- references found within.
925 Expand_Attributes_In
(Conseq
);
927 -- The consequence does not contain any attribute 'Old references
929 if No
(Eval_Stmts
) then
933 -- Augment the machinery to trigger the evaluation of all prefixes
934 -- found in the step above. If Eval is empty, then this is the first
935 -- consequence to yield expansion of 'Old. Generate:
938 -- <evaluation statements>
943 Make_Implicit_If_Statement
(CCs
,
944 Condition
=> New_Occurrence_Of
(Flag
, Loc
),
945 Then_Statements
=> Eval_Stmts
);
947 -- Otherwise generate:
949 -- <evaluation statements>
953 if No
(Elsif_Parts
(Evals
)) then
954 Set_Elsif_Parts
(Evals
, New_List
);
957 Append_To
(Elsif_Parts
(Evals
),
958 Make_Elsif_Part
(Loc
,
959 Condition
=> New_Occurrence_Of
(Flag
, Loc
),
960 Then_Statements
=> Eval_Stmts
));
962 end Expand_Attributes_In_Consequence
;
968 function Increment
(Id
: Entity_Id
) return Node_Id
is
971 Make_Assignment_Statement
(Loc
,
972 Name
=> New_Occurrence_Of
(Id
, Loc
),
975 Left_Opnd
=> New_Occurrence_Of
(Id
, Loc
),
976 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)));
983 function Set
(Id
: Entity_Id
) return Node_Id
is
986 Make_Assignment_Statement
(Loc
,
987 Name
=> New_Occurrence_Of
(Id
, Loc
),
988 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
));
993 Aggr
: constant Node_Id
:=
994 Expression
(First
(Pragma_Argument_Associations
(CCs
)));
995 GM
: constant Ghost_Mode_Type
:= Ghost_Mode
;
997 Case_Guard
: Node_Id
;
1001 Conseq_Checks
: Node_Id
:= Empty
;
1003 Count_Decl
: Node_Id
;
1004 Error_Decls
: List_Id
;
1006 Flag_Decl
: Node_Id
;
1008 Msg_Str
: Entity_Id
;
1009 Multiple_PCs
: Boolean;
1010 Old_Evals
: Node_Id
:= Empty
;
1011 Others_Decl
: Node_Id
;
1012 Others_Flag
: Entity_Id
:= Empty
;
1013 Post_Case
: Node_Id
;
1015 -- Start of processing for Expand_Pragma_Contract_Cases
1018 -- Do nothing if pragma is not enabled. If pragma is disabled, it has
1019 -- already been rewritten as a Null statement.
1021 if Is_Ignored
(CCs
) then
1024 -- Guard against malformed contract cases
1026 elsif Nkind
(Aggr
) /= N_Aggregate
then
1030 -- The contract cases may be subject to pragma Ghost with policy Ignore.
1031 -- Set the mode now to ensure that any nodes generated during expansion
1032 -- are properly flagged as ignored Ghost.
1034 Set_Ghost_Mode
(CCs
);
1036 Multiple_PCs
:= List_Length
(Component_Associations
(Aggr
)) > 1;
1038 -- Create the counter which tracks the number of case guards that
1039 -- evaluate to True.
1041 -- Count : Natural := 0;
1043 Count
:= Make_Temporary
(Loc
, 'C');
1045 Make_Object_Declaration
(Loc
,
1046 Defining_Identifier
=> Count
,
1047 Object_Definition
=> New_Occurrence_Of
(Standard_Natural
, Loc
),
1048 Expression
=> Make_Integer_Literal
(Loc
, 0));
1050 Prepend_To
(Decls
, Count_Decl
);
1051 Analyze
(Count_Decl
);
1053 -- Create the base error message for multiple overlapping case guards
1055 -- Msg_Str : constant String :=
1056 -- "contract cases overlap for subprogram Subp_Id";
1058 if Multiple_PCs
then
1059 Msg_Str
:= Make_Temporary
(Loc
, 'S');
1062 Store_String_Chars
("contract cases overlap for subprogram ");
1063 Store_String_Chars
(Get_Name_String
(Chars
(Subp_Id
)));
1065 Error_Decls
:= New_List
(
1066 Make_Object_Declaration
(Loc
,
1067 Defining_Identifier
=> Msg_Str
,
1068 Constant_Present
=> True,
1069 Object_Definition
=> New_Occurrence_Of
(Standard_String
, Loc
),
1070 Expression
=> Make_String_Literal
(Loc
, End_String
)));
1073 -- Process individual post cases
1075 Post_Case
:= First
(Component_Associations
(Aggr
));
1076 while Present
(Post_Case
) loop
1077 Case_Guard
:= First
(Choices
(Post_Case
));
1078 Conseq
:= Expression
(Post_Case
);
1080 -- The "others" choice requires special processing
1082 if Nkind
(Case_Guard
) = N_Others_Choice
then
1083 Others_Flag
:= Make_Temporary
(Loc
, 'F');
1084 Others_Decl
:= Declaration_Of
(Others_Flag
);
1086 Prepend_To
(Decls
, Others_Decl
);
1087 Analyze
(Others_Decl
);
1089 -- Check possible overlap between a case guard and "others"
1091 if Multiple_PCs
and Exception_Extra_Info
then
1093 (Decls
=> Error_Decls
,
1094 Flag
=> Others_Flag
,
1095 Error_Loc
=> Sloc
(Case_Guard
),
1099 -- Inspect the consequence and perform special expansion of any
1100 -- attribute 'Old and 'Result references found within.
1102 Expand_Attributes_In_Consequence
1105 Flag
=> Others_Flag
,
1108 -- Check the corresponding consequence of "others"
1111 (Checks
=> Conseq_Checks
,
1112 Flag
=> Others_Flag
,
1115 -- Regular post case
1118 -- Create the flag which tracks the state of its associated case
1121 Flag
:= Make_Temporary
(Loc
, 'F');
1122 Flag_Decl
:= Declaration_Of
(Flag
);
1124 Prepend_To
(Decls
, Flag_Decl
);
1125 Analyze
(Flag_Decl
);
1127 -- The flag is set when the case guard is evaluated to True
1128 -- if Case_Guard then
1130 -- Count := Count + 1;
1134 Make_Implicit_If_Statement
(CCs
,
1135 Condition
=> Relocate_Node
(Case_Guard
),
1136 Then_Statements
=> New_List
(
1138 Increment
(Count
)));
1140 Append_To
(Decls
, If_Stmt
);
1143 -- Check whether this case guard overlaps with another one
1145 if Multiple_PCs
and Exception_Extra_Info
then
1147 (Decls
=> Error_Decls
,
1149 Error_Loc
=> Sloc
(Case_Guard
),
1153 -- Inspect the consequence and perform special expansion of any
1154 -- attribute 'Old and 'Result references found within.
1156 Expand_Attributes_In_Consequence
1162 -- The corresponding consequence of the case guard which evaluated
1163 -- to True must hold on exit from the subprogram.
1166 (Checks
=> Conseq_Checks
,
1174 -- Raise Assertion_Error when none of the case guards evaluate to True.
1175 -- The only exception is when we have "others", in which case there is
1176 -- no error because "others" acts as a default True.
1181 if Present
(Others_Flag
) then
1182 CG_Stmts
:= New_List
(Set
(Others_Flag
));
1185 -- raise Assertion_Error with "xxx contract cases incomplete";
1189 Store_String_Chars
(Build_Location_String
(Loc
));
1190 Store_String_Chars
(" contract cases incomplete");
1192 CG_Stmts
:= New_List
(
1193 Make_Procedure_Call_Statement
(Loc
,
1195 New_Occurrence_Of
(RTE
(RE_Raise_Assert_Failure
), Loc
),
1196 Parameter_Associations
=> New_List
(
1197 Make_String_Literal
(Loc
, End_String
))));
1201 Make_Implicit_If_Statement
(CCs
,
1204 Left_Opnd
=> New_Occurrence_Of
(Count
, Loc
),
1205 Right_Opnd
=> Make_Integer_Literal
(Loc
, 0)),
1206 Then_Statements
=> CG_Stmts
);
1208 -- Detect a possible failure due to several case guards evaluating to
1212 -- elsif Count > 0 then
1216 -- raise Assertion_Error with <Msg_Str>;
1219 if Multiple_PCs
then
1220 Set_Elsif_Parts
(CG_Checks
, New_List
(
1221 Make_Elsif_Part
(Loc
,
1224 Left_Opnd
=> New_Occurrence_Of
(Count
, Loc
),
1225 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)),
1227 Then_Statements
=> New_List
(
1228 Make_Block_Statement
(Loc
,
1229 Declarations
=> Error_Decls
,
1230 Handled_Statement_Sequence
=>
1231 Make_Handled_Sequence_Of_Statements
(Loc
,
1232 Statements
=> New_List
(
1233 Make_Procedure_Call_Statement
(Loc
,
1236 (RTE
(RE_Raise_Assert_Failure
), Loc
),
1237 Parameter_Associations
=> New_List
(
1238 New_Occurrence_Of
(Msg_Str
, Loc
))))))))));
1241 Append_To
(Decls
, CG_Checks
);
1242 Analyze
(CG_Checks
);
1244 -- Once all case guards are evaluated and checked, evaluate any prefixes
1245 -- of attribute 'Old founds in the selected consequence.
1247 if Present
(Old_Evals
) then
1248 Append_To
(Decls
, Old_Evals
);
1249 Analyze
(Old_Evals
);
1252 -- Raise Assertion_Error when the corresponding consequence of a case
1253 -- guard that evaluated to True fails.
1259 Append_To
(Stmts
, Conseq_Checks
);
1261 -- Restore the original Ghost mode once analysis and expansion have
1265 end Expand_Pragma_Contract_Cases
;
1267 ---------------------------------------
1268 -- Expand_Pragma_Import_Or_Interface --
1269 ---------------------------------------
1271 procedure Expand_Pragma_Import_Or_Interface
(N
: Node_Id
) is
1275 -- In Relaxed_RM_Semantics, support old Ada 83 style:
1276 -- pragma Import (Entity, "external name");
1278 if Relaxed_RM_Semantics
1279 and then List_Length
(Pragma_Argument_Associations
(N
)) = 2
1280 and then Chars
(Pragma_Identifier
(N
)) = Name_Import
1281 and then Nkind
(Arg2
(N
)) = N_String_Literal
1283 Def_Id
:= Entity
(Arg1
(N
));
1285 Def_Id
:= Entity
(Arg2
(N
));
1288 -- Variable case (we have to undo any initialization already done)
1290 if Ekind
(Def_Id
) = E_Variable
then
1291 Undo_Initialization
(Def_Id
, N
);
1293 -- Case of exception with convention C++
1295 elsif Ekind
(Def_Id
) = E_Exception
1296 and then Convention
(Def_Id
) = Convention_CPP
1298 -- Import a C++ convention
1301 Loc
: constant Source_Ptr
:= Sloc
(N
);
1302 Rtti_Name
: constant Node_Id
:= Arg3
(N
);
1303 Dum
: constant Entity_Id
:= Make_Temporary
(Loc
, 'D');
1305 Lang_Char
: Node_Id
;
1306 Foreign_Data
: Node_Id
;
1309 Exdata
:= Component_Associations
(Expression
(Parent
(Def_Id
)));
1311 Lang_Char
:= Next
(First
(Exdata
));
1313 -- Change the one-character language designator to 'C'
1315 Rewrite
(Expression
(Lang_Char
),
1316 Make_Character_Literal
(Loc
,
1318 Char_Literal_Value
=> UI_From_Int
(Character'Pos ('C'))));
1319 Analyze
(Expression
(Lang_Char
));
1321 -- Change the value of Foreign_Data
1323 Foreign_Data
:= Next
(Next
(Next
(Next
(Lang_Char
))));
1325 Insert_Actions
(Def_Id
, New_List
(
1326 Make_Object_Declaration
(Loc
,
1327 Defining_Identifier
=> Dum
,
1328 Object_Definition
=>
1329 New_Occurrence_Of
(Standard_Character
, Loc
)),
1332 Chars
=> Name_Import
,
1333 Pragma_Argument_Associations
=> New_List
(
1334 Make_Pragma_Argument_Association
(Loc
,
1335 Expression
=> Make_Identifier
(Loc
, Name_Ada
)),
1337 Make_Pragma_Argument_Association
(Loc
,
1338 Expression
=> Make_Identifier
(Loc
, Chars
(Dum
))),
1340 Make_Pragma_Argument_Association
(Loc
,
1341 Chars
=> Name_External_Name
,
1342 Expression
=> Relocate_Node
(Rtti_Name
))))));
1344 Rewrite
(Expression
(Foreign_Data
),
1345 Unchecked_Convert_To
(Standard_A_Char
,
1346 Make_Attribute_Reference
(Loc
,
1347 Prefix
=> Make_Identifier
(Loc
, Chars
(Dum
)),
1348 Attribute_Name
=> Name_Address
)));
1349 Analyze
(Expression
(Foreign_Data
));
1352 -- No special expansion required for any other case
1357 end Expand_Pragma_Import_Or_Interface
;
1359 -------------------------------------
1360 -- Expand_Pragma_Initial_Condition --
1361 -------------------------------------
1363 procedure Expand_Pragma_Initial_Condition
(Spec_Or_Body
: Node_Id
) is
1364 GM
: constant Ghost_Mode_Type
:= Ghost_Mode
;
1366 procedure Restore_Globals
;
1367 -- Restore the values of all saved global variables
1369 ---------------------
1370 -- Restore_Globals --
1371 ---------------------
1373 procedure Restore_Globals
is
1376 end Restore_Globals
;
1380 Loc
: constant Source_Ptr
:= Sloc
(Spec_Or_Body
);
1383 Init_Cond
: Node_Id
;
1385 Pack_Id
: Entity_Id
;
1387 -- Start of processing for Expand_Pragma_Initial_Condition
1390 if Nkind
(Spec_Or_Body
) = N_Package_Body
then
1391 Pack_Id
:= Corresponding_Spec
(Spec_Or_Body
);
1393 if Present
(Handled_Statement_Sequence
(Spec_Or_Body
)) then
1394 List
:= Statements
(Handled_Statement_Sequence
(Spec_Or_Body
));
1396 -- The package body lacks statements, create an empty list
1401 Set_Handled_Statement_Sequence
(Spec_Or_Body
,
1402 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> List
));
1405 elsif Nkind
(Spec_Or_Body
) = N_Package_Declaration
then
1406 Pack_Id
:= Defining_Entity
(Spec_Or_Body
);
1408 if Present
(Visible_Declarations
(Specification
(Spec_Or_Body
))) then
1409 List
:= Visible_Declarations
(Specification
(Spec_Or_Body
));
1411 -- The package lacks visible declarations, create an empty list
1416 Set_Visible_Declarations
(Specification
(Spec_Or_Body
), List
);
1419 -- This routine should not be used on anything other than packages
1422 raise Program_Error
;
1425 Init_Cond
:= Get_Pragma
(Pack_Id
, Pragma_Initial_Condition
);
1427 -- The initial condition be subject to pragma Ghost with policy Ignore.
1428 -- Set the mode now to ensure that any nodes generated during expansion
1429 -- are properly flagged as ignored Ghost.
1431 Set_Ghost_Mode
(Init_Cond
);
1433 -- The caller should check whether the package is subject to pragma
1434 -- Initial_Condition.
1436 pragma Assert
(Present
(Init_Cond
));
1439 Get_Pragma_Arg
(First
(Pragma_Argument_Associations
(Init_Cond
)));
1441 -- The assertion expression was found to be illegal, do not generate the
1442 -- runtime check as it will repeat the illegality.
1444 if Error_Posted
(Init_Cond
) or else Error_Posted
(Expr
) then
1450 -- pragma Check (Initial_Condition, <Expr>);
1454 Chars
=> Name_Check
,
1455 Pragma_Argument_Associations
=> New_List
(
1456 Make_Pragma_Argument_Association
(Loc
,
1457 Expression
=> Make_Identifier
(Loc
, Name_Initial_Condition
)),
1458 Make_Pragma_Argument_Association
(Loc
,
1459 Expression
=> New_Copy_Tree
(Expr
))));
1461 Append_To
(List
, Check
);
1465 end Expand_Pragma_Initial_Condition
;
1467 ------------------------------------
1468 -- Expand_Pragma_Inspection_Point --
1469 ------------------------------------
1471 -- If no argument is given, then we supply a default argument list that
1472 -- includes all objects declared at the source level in all subprograms
1473 -- that enclose the inspection point pragma.
1475 procedure Expand_Pragma_Inspection_Point
(N
: Node_Id
) is
1476 Loc
: constant Source_Ptr
:= Sloc
(N
);
1483 if No
(Pragma_Argument_Associations
(N
)) then
1487 while S
/= Standard_Standard
loop
1488 E
:= First_Entity
(S
);
1489 while Present
(E
) loop
1490 if Comes_From_Source
(E
)
1491 and then Is_Object
(E
)
1492 and then not Is_Entry_Formal
(E
)
1493 and then Ekind
(E
) /= E_Component
1494 and then Ekind
(E
) /= E_Discriminant
1495 and then Ekind
(E
) /= E_Generic_In_Parameter
1496 and then Ekind
(E
) /= E_Generic_In_Out_Parameter
1499 Make_Pragma_Argument_Association
(Loc
,
1500 Expression
=> New_Occurrence_Of
(E
, Loc
)));
1509 Set_Pragma_Argument_Associations
(N
, A
);
1512 -- Expand the arguments of the pragma. Expanding an entity reference
1513 -- is a noop, except in a protected operation, where a reference may
1514 -- have to be transformed into a reference to the corresponding prival.
1515 -- Are there other pragmas that may require this ???
1517 Assoc
:= First
(Pragma_Argument_Associations
(N
));
1518 while Present
(Assoc
) loop
1519 Expand
(Expression
(Assoc
));
1522 end Expand_Pragma_Inspection_Point
;
1524 --------------------------------------
1525 -- Expand_Pragma_Interrupt_Priority --
1526 --------------------------------------
1528 -- Supply default argument if none exists (System.Interrupt_Priority'Last)
1530 procedure Expand_Pragma_Interrupt_Priority
(N
: Node_Id
) is
1531 Loc
: constant Source_Ptr
:= Sloc
(N
);
1533 if No
(Pragma_Argument_Associations
(N
)) then
1534 Set_Pragma_Argument_Associations
(N
, New_List
(
1535 Make_Pragma_Argument_Association
(Loc
,
1537 Make_Attribute_Reference
(Loc
,
1539 New_Occurrence_Of
(RTE
(RE_Interrupt_Priority
), Loc
),
1540 Attribute_Name
=> Name_Last
))));
1542 end Expand_Pragma_Interrupt_Priority
;
1544 --------------------------------
1545 -- Expand_Pragma_Loop_Variant --
1546 --------------------------------
1548 -- Pragma Loop_Variant is expanded in the following manner:
1552 -- for | while ... loop
1553 -- <preceding source statements>
1554 -- pragma Loop_Variant
1555 -- (Increases => Incr_Expr,
1556 -- Decreases => Decr_Expr);
1557 -- <succeeding source statements>
1562 -- Curr_1 : <type of Incr_Expr>;
1563 -- Curr_2 : <type of Decr_Expr>;
1564 -- Old_1 : <type of Incr_Expr>;
1565 -- Old_2 : <type of Decr_Expr>;
1566 -- Flag : Boolean := False;
1568 -- for | while ... loop
1569 -- <preceding source statements>
1576 -- Curr_1 := <Incr_Expr>;
1577 -- Curr_2 := <Decr_Expr>;
1580 -- if Curr_1 /= Old_1 then
1581 -- pragma Check (Loop_Variant, Curr_1 > Old_1);
1583 -- pragma Check (Loop_Variant, Curr_2 < Old_2);
1589 -- <succeeding source statements>
1592 procedure Expand_Pragma_Loop_Variant
(N
: Node_Id
) is
1593 Loc
: constant Source_Ptr
:= Sloc
(N
);
1594 Last_Var
: constant Node_Id
:=
1595 Last
(Pragma_Argument_Associations
(N
));
1597 Curr_Assign
: List_Id
:= No_List
;
1598 Flag_Id
: Entity_Id
:= Empty
;
1599 If_Stmt
: Node_Id
:= Empty
;
1600 Old_Assign
: List_Id
:= No_List
;
1601 Loop_Scop
: Entity_Id
;
1602 Loop_Stmt
: Node_Id
;
1605 procedure Process_Variant
(Variant
: Node_Id
; Is_Last
: Boolean);
1606 -- Process a single increasing / decreasing termination variant. Flag
1607 -- Is_Last should be set when processing the last variant.
1609 ---------------------
1610 -- Process_Variant --
1611 ---------------------
1613 procedure Process_Variant
(Variant
: Node_Id
; Is_Last
: Boolean) is
1617 Old_Val
: Node_Id
) return Node_Id
;
1618 -- Generate a comparison between Curr_Val and Old_Val depending on
1619 -- the change mode (Increases / Decreases) of the variant.
1628 Old_Val
: Node_Id
) return Node_Id
1631 if Chars
(Variant
) = Name_Increases
then
1632 return Make_Op_Gt
(Loc
, Curr_Val
, Old_Val
);
1633 else pragma Assert
(Chars
(Variant
) = Name_Decreases
);
1634 return Make_Op_Lt
(Loc
, Curr_Val
, Old_Val
);
1640 Expr
: constant Node_Id
:= Expression
(Variant
);
1641 Expr_Typ
: constant Entity_Id
:= Etype
(Expr
);
1642 Loc
: constant Source_Ptr
:= Sloc
(Expr
);
1643 Loop_Loc
: constant Source_Ptr
:= Sloc
(Loop_Stmt
);
1644 Curr_Id
: Entity_Id
;
1648 -- Start of processing for Process_Variant
1651 -- All temporaries generated in this routine must be inserted before
1652 -- the related loop statement. Ensure that the proper scope is on the
1653 -- stack when analyzing the temporaries. Note that we also use the
1654 -- Sloc of the related loop.
1656 Push_Scope
(Scope
(Loop_Scop
));
1658 -- Step 1: Create the declaration of the flag which controls the
1659 -- behavior of the assertion on the first iteration of the loop.
1661 if No
(Flag_Id
) then
1664 -- Flag : Boolean := False;
1666 Flag_Id
:= Make_Temporary
(Loop_Loc
, 'F');
1668 Insert_Action
(Loop_Stmt
,
1669 Make_Object_Declaration
(Loop_Loc
,
1670 Defining_Identifier
=> Flag_Id
,
1671 Object_Definition
=>
1672 New_Occurrence_Of
(Standard_Boolean
, Loop_Loc
),
1674 New_Occurrence_Of
(Standard_False
, Loop_Loc
)));
1676 -- Prevent an unwanted optimization where the Current_Value of
1677 -- the flag eliminates the if statement which stores the variant
1678 -- values coming from the previous iteration.
1680 -- Flag : Boolean := False;
1682 -- if Flag then -- condition rewritten to False
1683 -- Old_N := Curr_N; -- and if statement eliminated
1689 Set_Current_Value
(Flag_Id
, Empty
);
1692 -- Step 2: Create the temporaries which store the old and current
1693 -- values of the associated expression.
1696 -- Curr : <type of Expr>;
1698 Curr_Id
:= Make_Temporary
(Loc
, 'C');
1700 Insert_Action
(Loop_Stmt
,
1701 Make_Object_Declaration
(Loop_Loc
,
1702 Defining_Identifier
=> Curr_Id
,
1703 Object_Definition
=> New_Occurrence_Of
(Expr_Typ
, Loop_Loc
)));
1706 -- Old : <type of Expr>;
1708 Old_Id
:= Make_Temporary
(Loc
, 'P');
1710 Insert_Action
(Loop_Stmt
,
1711 Make_Object_Declaration
(Loop_Loc
,
1712 Defining_Identifier
=> Old_Id
,
1713 Object_Definition
=> New_Occurrence_Of
(Expr_Typ
, Loop_Loc
)));
1715 -- Restore original scope after all temporaries have been analyzed
1719 -- Step 3: Store value of the expression from the previous iteration
1721 if No
(Old_Assign
) then
1722 Old_Assign
:= New_List
;
1728 Append_To
(Old_Assign
,
1729 Make_Assignment_Statement
(Loc
,
1730 Name
=> New_Occurrence_Of
(Old_Id
, Loc
),
1731 Expression
=> New_Occurrence_Of
(Curr_Id
, Loc
)));
1733 -- Step 4: Store the current value of the expression
1735 if No
(Curr_Assign
) then
1736 Curr_Assign
:= New_List
;
1742 Append_To
(Curr_Assign
,
1743 Make_Assignment_Statement
(Loc
,
1744 Name
=> New_Occurrence_Of
(Curr_Id
, Loc
),
1745 Expression
=> Relocate_Node
(Expr
)));
1747 -- Step 5: Create corresponding assertion to verify change of value
1750 -- pragma Check (Loop_Variant, Curr <|> Old);
1754 Chars
=> Name_Check
,
1755 Pragma_Argument_Associations
=> New_List
(
1756 Make_Pragma_Argument_Association
(Loc
,
1757 Expression
=> Make_Identifier
(Loc
, Name_Loop_Variant
)),
1758 Make_Pragma_Argument_Association
(Loc
,
1761 Curr_Val
=> New_Occurrence_Of
(Curr_Id
, Loc
),
1762 Old_Val
=> New_Occurrence_Of
(Old_Id
, Loc
)))));
1765 -- if Curr /= Old then
1768 if No
(If_Stmt
) then
1770 -- When there is just one termination variant, do not compare the
1771 -- old and current value for equality, just check the pragma.
1777 Make_If_Statement
(Loc
,
1780 Left_Opnd
=> New_Occurrence_Of
(Curr_Id
, Loc
),
1781 Right_Opnd
=> New_Occurrence_Of
(Old_Id
, Loc
)),
1782 Then_Statements
=> New_List
(Prag
));
1791 Set_Else_Statements
(If_Stmt
, New_List
(Prag
));
1794 -- elsif Curr /= Old then
1798 if Elsif_Parts
(If_Stmt
) = No_List
then
1799 Set_Elsif_Parts
(If_Stmt
, New_List
);
1802 Append_To
(Elsif_Parts
(If_Stmt
),
1803 Make_Elsif_Part
(Loc
,
1806 Left_Opnd
=> New_Occurrence_Of
(Curr_Id
, Loc
),
1807 Right_Opnd
=> New_Occurrence_Of
(Old_Id
, Loc
)),
1808 Then_Statements
=> New_List
(Prag
)));
1810 end Process_Variant
;
1814 GM
: constant Ghost_Mode_Type
:= Ghost_Mode
;
1816 -- Start of processing for Expand_Pragma_Loop_Variant
1819 -- If pragma is not enabled, rewrite as Null statement. If pragma is
1820 -- disabled, it has already been rewritten as a Null statement.
1822 if Is_Ignored
(N
) then
1823 Rewrite
(N
, Make_Null_Statement
(Loc
));
1828 -- The loop variant may be subject to pragma Ghost with policy Ignore.
1829 -- Set the mode now to ensure that any nodes generated during expansion
1830 -- are properly flagged as ignored Ghost.
1834 -- Locate the enclosing loop for which this assertion applies. In the
1835 -- case of Ada 2012 array iteration, we might be dealing with nested
1836 -- loops. Only the outermost loop has an identifier.
1839 while Present
(Loop_Stmt
) loop
1840 if Nkind
(Loop_Stmt
) = N_Loop_Statement
1841 and then Present
(Identifier
(Loop_Stmt
))
1846 Loop_Stmt
:= Parent
(Loop_Stmt
);
1849 Loop_Scop
:= Entity
(Identifier
(Loop_Stmt
));
1851 -- Create the circuitry which verifies individual variants
1853 Variant
:= First
(Pragma_Argument_Associations
(N
));
1854 while Present
(Variant
) loop
1855 Process_Variant
(Variant
, Is_Last
=> Variant
= Last_Var
);
1859 -- Construct the segment which stores the old values of all expressions.
1866 Make_If_Statement
(Loc
,
1867 Condition
=> New_Occurrence_Of
(Flag_Id
, Loc
),
1868 Then_Statements
=> Old_Assign
));
1870 -- Update the values of all expressions
1872 Insert_Actions
(N
, Curr_Assign
);
1874 -- Add the assertion circuitry to test all changes in expressions.
1883 Make_If_Statement
(Loc
,
1884 Condition
=> New_Occurrence_Of
(Flag_Id
, Loc
),
1885 Then_Statements
=> New_List
(If_Stmt
),
1886 Else_Statements
=> New_List
(
1887 Make_Assignment_Statement
(Loc
,
1888 Name
=> New_Occurrence_Of
(Flag_Id
, Loc
),
1889 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)))));
1891 -- Note: the pragma has been completely transformed into a sequence of
1892 -- corresponding declarations and statements. We leave it in the tree
1893 -- for documentation purposes. It will be ignored by the backend.
1895 -- Restore the original Ghost mode once analysis and expansion have
1899 end Expand_Pragma_Loop_Variant
;
1901 --------------------------------
1902 -- Expand_Pragma_Psect_Object --
1903 --------------------------------
1905 -- Convert to Common_Object, and expand the resulting pragma
1907 procedure Expand_Pragma_Psect_Object
(N
: Node_Id
)
1908 renames Expand_Pragma_Common_Object
;
1910 -------------------------------------
1911 -- Expand_Pragma_Relative_Deadline --
1912 -------------------------------------
1914 procedure Expand_Pragma_Relative_Deadline
(N
: Node_Id
) is
1915 P
: constant Node_Id
:= Parent
(N
);
1916 Loc
: constant Source_Ptr
:= Sloc
(N
);
1919 -- Expand the pragma only in the case of the main subprogram. For tasks
1920 -- the expansion is done in exp_ch9. Generate a call to Set_Deadline
1921 -- at Clock plus the relative deadline specified in the pragma. Time
1922 -- values are translated into Duration to allow for non-private
1923 -- addition operation.
1925 if Nkind
(P
) = N_Subprogram_Body
then
1928 Make_Procedure_Call_Statement
(Loc
,
1929 Name
=> New_Occurrence_Of
(RTE
(RE_Set_Deadline
), Loc
),
1930 Parameter_Associations
=> New_List
(
1931 Unchecked_Convert_To
(RTE
(RO_RT_Time
),
1934 Make_Function_Call
(Loc
,
1935 New_Occurrence_Of
(RTE
(RO_RT_To_Duration
), Loc
),
1938 (Loc
, New_Occurrence_Of
(RTE
(RE_Clock
), Loc
)))),
1940 Unchecked_Convert_To
(Standard_Duration
, Arg1
(N
)))))));
1944 end Expand_Pragma_Relative_Deadline
;
1946 -------------------------------------------
1947 -- Expand_Pragma_Suppress_Initialization --
1948 -------------------------------------------
1950 procedure Expand_Pragma_Suppress_Initialization
(N
: Node_Id
) is
1951 Def_Id
: constant Entity_Id
:= Entity
(Arg1
(N
));
1954 -- Variable case (we have to undo any initialization already done)
1956 if Ekind
(Def_Id
) = E_Variable
then
1957 Undo_Initialization
(Def_Id
, N
);
1959 end Expand_Pragma_Suppress_Initialization
;
1961 -------------------------
1962 -- Undo_Initialization --
1963 -------------------------
1965 procedure Undo_Initialization
(Def_Id
: Entity_Id
; N
: Node_Id
) is
1966 Init_Call
: Node_Id
;
1969 -- When applied to a variable, the default initialization must not be
1970 -- done. As it is already done when the pragma is found, we just get rid
1971 -- of the call the initialization procedure which followed the object
1972 -- declaration. The call is inserted after the declaration, but validity
1973 -- checks may also have been inserted and thus the initialization call
1974 -- does not necessarily appear immediately after the object declaration.
1976 -- We can't use the freezing mechanism for this purpose, since we have
1977 -- to elaborate the initialization expression when it is first seen (so
1978 -- this elaboration cannot be deferred to the freeze point).
1980 -- Find and remove generated initialization call for object, if any
1982 Init_Call
:= Remove_Init_Call
(Def_Id
, Rep_Clause
=> N
);
1984 -- Any default initialization expression should be removed (e.g.
1985 -- null defaults for access objects, zero initialization of packed
1986 -- bit arrays). Imported objects aren't allowed to have explicit
1987 -- initialization, so the expression must have been generated by
1990 if No
(Init_Call
) and then Present
(Expression
(Parent
(Def_Id
))) then
1991 Set_Expression
(Parent
(Def_Id
), Empty
);
1994 -- The object may not have any initialization, but in the presence of
1995 -- Initialize_Scalars code is inserted after then declaration, which
1996 -- must now be removed as well. The code carries the same source
1997 -- location as the declaration itself.
1999 if Initialize_Scalars
and then Is_Array_Type
(Etype
(Def_Id
)) then
2004 Init
:= Next
(Parent
(Def_Id
));
2005 while not Comes_From_Source
(Init
)
2006 and then Sloc
(Init
) = Sloc
(Def_Id
)
2014 end Undo_Initialization
;