1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- E X P _ S P A R K --
9 -- Copyright (C) 1992-2021, 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 Checks
; use Checks
;
28 with Einfo
; use Einfo
;
29 with Einfo
.Entities
; use Einfo
.Entities
;
30 with Einfo
.Utils
; use Einfo
.Utils
;
33 with Exp_Ch5
; use Exp_Ch5
;
34 with Exp_Dbug
; use Exp_Dbug
;
35 with Exp_Util
; use Exp_Util
;
36 with Namet
; use Namet
;
37 with Nlists
; use Nlists
;
38 with Nmake
; use Nmake
;
39 with Rtsfind
; use Rtsfind
;
41 with Sem_Ch8
; use Sem_Ch8
;
42 with Sem_Prag
; use Sem_Prag
;
43 with Sem_Res
; use Sem_Res
;
44 with Sem_Util
; use Sem_Util
;
45 with Sinfo
; use Sinfo
;
46 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
47 with Sinfo
.Utils
; use Sinfo
.Utils
;
48 with Snames
; use Snames
;
49 with Stand
; use Stand
;
50 with Tbuild
; use Tbuild
;
51 with Uintp
; use Uintp
;
53 package body Exp_SPARK
is
55 -----------------------
56 -- Local Subprograms --
57 -----------------------
59 procedure Expand_SPARK_N_Attribute_Reference
(N
: Node_Id
);
60 -- Perform attribute-reference-specific expansion
62 procedure Expand_SPARK_N_Delta_Aggregate
(N
: Node_Id
);
63 -- Perform delta-aggregate-specific expansion
65 procedure Expand_SPARK_N_Freeze_Type
(E
: Entity_Id
);
66 -- Build the DIC procedure of a type when needed, if not already done
68 procedure Expand_SPARK_N_Loop_Statement
(N
: Node_Id
);
69 -- Perform loop-statement-specific expansion
71 procedure Expand_SPARK_N_Object_Declaration
(N
: Node_Id
);
72 -- Perform object-declaration-specific expansion
74 procedure Expand_SPARK_N_Object_Renaming_Declaration
(N
: Node_Id
);
75 -- Perform name evaluation for a renamed object
77 procedure Expand_SPARK_N_Op_Ne
(N
: Node_Id
);
78 -- Rewrite operator /= based on operator = when defined explicitly
80 procedure Expand_SPARK_Delta_Or_Update
(Typ
: Entity_Id
; Aggr
: Node_Id
);
81 -- Common expansion for attribute Update and delta aggregates
87 procedure Expand_SPARK
(N
: Node_Id
) is
91 -- Qualification of entity names in formal verification mode
92 -- is limited to the addition of a suffix for homonyms (see
93 -- Exp_Dbug.Qualify_Entity_Name). We used to qualify entity names
94 -- as full expansion does, but this was removed as this prevents the
95 -- verification back-end from using a short name for debugging and
96 -- user interaction. The verification back-end already takes care
97 -- of qualifying names when needed.
99 when N_Block_Statement
100 | N_Entry_Declaration
102 | N_Package_Declaration
103 | N_Protected_Type_Declaration
105 | N_Task_Type_Declaration
107 Qualify_Entity_Names
(N
);
109 -- Replace occurrences of System'To_Address by calls to
110 -- System.Storage_Elements.To_Address.
112 when N_Attribute_Reference
=>
113 Expand_SPARK_N_Attribute_Reference
(N
);
115 when N_Delta_Aggregate
=>
116 Expand_SPARK_N_Delta_Aggregate
(N
);
121 Expand_SPARK_Potential_Renaming
(N
);
123 -- Loop iterations over arrays need to be expanded, to avoid getting
124 -- two names referring to the same object in memory (the array and
125 -- the iterator) in GNATprove, especially since both can be written
126 -- (thus possibly leading to interferences due to aliasing). No such
127 -- problem arises with quantified expressions over arrays, which are
128 -- dealt with specially in GNATprove.
130 when N_Loop_Statement
=>
131 Expand_SPARK_N_Loop_Statement
(N
);
133 when N_Object_Declaration
=>
134 Expand_SPARK_N_Object_Declaration
(N
);
136 when N_Object_Renaming_Declaration
=>
137 Expand_SPARK_N_Object_Renaming_Declaration
(N
);
140 Expand_SPARK_N_Op_Ne
(N
);
142 when N_Freeze_Entity
=>
143 if Is_Type
(Entity
(N
)) then
144 Expand_SPARK_N_Freeze_Type
(Entity
(N
));
147 -- In SPARK mode, no other constructs require expansion
154 ----------------------------------
155 -- Expand_SPARK_Delta_Or_Update --
156 ----------------------------------
158 procedure Expand_SPARK_Delta_Or_Update
165 Comp_Type
: Entity_Id
;
168 Index_Typ
: Entity_Id
;
172 -- Apply scalar range checks on the updated components, if needed
174 if Is_Array_Type
(Typ
) then
176 -- Multidimensional arrays
178 if Present
(Next_Index
(First_Index
(Typ
))) then
179 Assoc
:= First
(Component_Associations
(Aggr
));
181 while Present
(Assoc
) loop
182 Expr
:= Expression
(Assoc
);
183 Comp_Type
:= Component_Type
(Typ
);
185 if Is_Scalar_Type
(Comp_Type
) then
186 Apply_Scalar_Range_Check
(Expr
, Comp_Type
);
189 -- The current association contains a sequence of indexes
190 -- denoting an element of a multidimensional array:
192 -- (Index_1, ..., Index_N)
194 Expr
:= First
(Choices
(Assoc
));
196 pragma Assert
(Nkind
(Aggr
) = N_Aggregate
);
198 while Present
(Expr
) loop
199 Index
:= First
(Expressions
(Expr
));
200 Index_Typ
:= First_Index
(Typ
);
202 while Present
(Index_Typ
) loop
203 Apply_Scalar_Range_Check
(Index
, Etype
(Index_Typ
));
205 Next_Index
(Index_Typ
);
214 -- One-dimensional arrays
217 Assoc
:= First
(Component_Associations
(Aggr
));
219 while Present
(Assoc
) loop
220 Expr
:= Expression
(Assoc
);
221 Comp_Type
:= Component_Type
(Typ
);
223 -- Analyze expression of the iterated_component_association
224 -- with its index parameter in scope.
226 if Nkind
(Assoc
) = N_Iterated_Component_Association
then
227 Push_Scope
(Scope
(Defining_Identifier
(Assoc
)));
228 Enter_Name
(Defining_Identifier
(Assoc
));
229 Analyze_And_Resolve
(Expr
, Comp_Type
);
232 if Is_Scalar_Type
(Comp_Type
) then
233 Apply_Scalar_Range_Check
(Expr
, Comp_Type
);
236 -- Restore scope of the iterated_component_association
238 if Nkind
(Assoc
) = N_Iterated_Component_Association
then
242 Index
:= First
(Choice_List
(Assoc
));
243 Index_Typ
:= First_Index
(Typ
);
245 while Present
(Index
) loop
246 -- If the index denotes a range of elements or a constrained
247 -- subtype indication, then their low and high bounds
248 -- already have range checks applied.
250 if Nkind
(Index
) in N_Range | N_Subtype_Indication
then
253 -- Otherwise the index denotes a single expression where
254 -- range checks need to be applied or a subtype name
255 -- (without range constraints) where applying checks is
258 -- In delta_aggregate and Update attribute on array the
259 -- others_choice is not allowed.
261 else pragma Assert
(Nkind
(Index
) in N_Subexpr
);
262 Apply_Scalar_Range_Check
(Index
, Etype
(Index_Typ
));
272 else pragma Assert
(Is_Record_Type
(Typ
));
274 -- If the aggregate has multiple component choices, e.g.:
276 -- X'Update (A | B | C => 123)
278 -- then each component might be of a different type and might or
279 -- might not require a range check. We first rewrite associations
280 -- into single-component choices, e.g.:
282 -- X'Update (A => 123, B => 123, C => 123)
284 -- and then apply range checks to individual copies of the
285 -- expressions. We do the same for delta aggregates, accordingly.
287 -- Iterate over associations of the original aggregate
289 Assoc
:= First
(Component_Associations
(Aggr
));
291 -- Rewrite into a new aggregate and decorate
298 (Sloc
=> Sloc
(Aggr
),
299 Component_Associations
=> New_List
));
301 when N_Delta_Aggregate
=>
305 (Sloc
=> Sloc
(Aggr
),
306 Expression
=> Expression
(Aggr
),
307 Component_Associations
=> New_List
));
313 Set_Etype
(Aggr
, Typ
);
315 -- Populate the new aggregate with component associations
317 while Present
(Assoc
) loop
318 Expr
:= Expression
(Assoc
);
319 Comp
:= First
(Choices
(Assoc
));
321 while Present
(Comp
) loop
322 Comp_Id
:= Entity
(Comp
);
323 Comp_Type
:= Etype
(Comp_Id
);
326 Make_Component_Association
327 (Sloc
=> Sloc
(Assoc
),
330 (New_Occurrence_Of
(Comp_Id
, Sloc
(Comp
))),
331 Expression
=> New_Copy_Tree
(Expr
));
333 -- New association must be attached to the aggregate before we
336 Append
(New_Assoc
, Component_Associations
(Aggr
));
338 Analyze_And_Resolve
(Expression
(New_Assoc
), Comp_Type
);
340 if Is_Scalar_Type
(Comp_Type
) then
341 Apply_Scalar_Range_Check
342 (Expression
(New_Assoc
), Comp_Type
);
351 end Expand_SPARK_Delta_Or_Update
;
353 --------------------------------
354 -- Expand_SPARK_N_Freeze_Type --
355 --------------------------------
357 procedure Expand_SPARK_N_Freeze_Type
(E
: Entity_Id
) is
359 -- When a DIC is inherited by a tagged type, it may need to be
360 -- specialized to the descendant type, hence build a separate DIC
361 -- procedure for it as done during regular expansion for compilation.
363 if Has_DIC
(E
) and then Is_Tagged_Type
(E
) then
364 -- Why is this needed for DIC, but not for other aspects (such as
365 -- Type_Invariant)???
367 Build_DIC_Procedure_Body
(E
);
369 end Expand_SPARK_N_Freeze_Type
;
371 ----------------------------------------
372 -- Expand_SPARK_N_Attribute_Reference --
373 ----------------------------------------
375 procedure Expand_SPARK_N_Attribute_Reference
(N
: Node_Id
) is
376 Aname
: constant Name_Id
:= Attribute_Name
(N
);
377 Attr_Id
: constant Attribute_Id
:= Get_Attribute_Id
(Aname
);
378 Loc
: constant Source_Ptr
:= Sloc
(N
);
379 Pref
: constant Node_Id
:= Prefix
(N
);
380 Typ
: constant Entity_Id
:= Etype
(N
);
385 when Attribute_To_Address
=>
387 -- Extract and convert argument to expected type for call
390 Make_Type_Conversion
(Loc
,
392 New_Occurrence_Of
(RTE
(RE_Integer_Address
), Loc
),
393 Expression
=> Relocate_Node
(First
(Expressions
(N
))));
395 -- Replace attribute reference with call
399 Make_Function_Call
(Loc
,
401 New_Occurrence_Of
(RTE
(RE_To_Address
), Loc
),
402 Parameter_Associations
=> New_List
(Expr
)));
403 Analyze_And_Resolve
(N
, Typ
);
405 when Attribute_Object_Size
407 | Attribute_Value_Size
408 | Attribute_VADS_Size
410 Exp_Attr
.Expand_Size_Attribute
(N
);
412 -- For attributes which return Universal_Integer, introduce a
413 -- conversion to the expected type with the appropriate check flags
417 | Attribute_Alignment
419 | Attribute_Bit_Position
420 | Attribute_Descriptor_Size
421 | Attribute_First_Bit
424 | Attribute_Max_Alignment_For_Allocation
425 | Attribute_Max_Size_In_Storage_Elements
428 | Attribute_Range_Length
430 -- If the expected type is Long_Long_Integer, there will be no
431 -- check flag as the compiler assumes attributes always fit in
432 -- this type. Since in SPARK_Mode we do not take Storage_Error
433 -- into account, we cannot make this assumption and need to
434 -- produce a check. ??? It should be enough to add this check for
435 -- attributes 'Length, 'Range_Length and 'Pos when the type is as
436 -- big as Long_Long_Integer.
441 if Attr_Id
in Attribute_Pos | Attribute_Range_Length
then
442 Typ
:= Etype
(Prefix
(N
));
444 elsif Attr_Id
= Attribute_Length
then
445 Typ
:= Get_Index_Subtype
(N
);
451 Apply_Universal_Integer_Attribute_Checks
(N
);
454 and then RM_Size
(Typ
) = RM_Size
(Standard_Long_Long_Integer
)
456 -- ??? This should rather be a range check, but this would
457 -- crash GNATprove which somehow recovers the proper kind
459 Set_Do_Overflow_Check
(N
);
463 when Attribute_Constrained
=>
465 -- If the prefix is an access to object, the attribute applies to
466 -- the designated object, so rewrite with an explicit dereference.
468 if Is_Access_Type
(Etype
(Pref
))
470 (not Is_Entity_Name
(Pref
) or else Is_Object
(Entity
(Pref
)))
473 Make_Explicit_Dereference
(Loc
, Relocate_Node
(Pref
)));
474 Analyze_And_Resolve
(N
, Standard_Boolean
);
477 when Attribute_Update
=>
478 Expand_SPARK_Delta_Or_Update
(Typ
, First
(Expressions
(N
)));
483 end Expand_SPARK_N_Attribute_Reference
;
485 ------------------------------------
486 -- Expand_SPARK_N_Delta_Aggregate --
487 ------------------------------------
489 procedure Expand_SPARK_N_Delta_Aggregate
(N
: Node_Id
) is
491 Expand_SPARK_Delta_Or_Update
(Etype
(N
), N
);
492 end Expand_SPARK_N_Delta_Aggregate
;
494 -----------------------------------
495 -- Expand_SPARK_N_Loop_Statement --
496 -----------------------------------
498 procedure Expand_SPARK_N_Loop_Statement
(N
: Node_Id
) is
499 Scheme
: constant Node_Id
:= Iteration_Scheme
(N
);
502 -- Loop iterations over arrays need to be expanded, to avoid getting
503 -- two names referring to the same object in memory (the array and the
504 -- iterator) in GNATprove, especially since both can be written (thus
505 -- possibly leading to interferences due to aliasing). No such problem
506 -- arises with quantified expressions over arrays, which are dealt with
507 -- specially in GNATprove.
510 and then Present
(Iterator_Specification
(Scheme
))
511 and then Is_Iterator_Over_Array
(Iterator_Specification
(Scheme
))
513 Expand_Iterator_Loop_Over_Array
(N
);
515 end Expand_SPARK_N_Loop_Statement
;
517 ---------------------------------------
518 -- Expand_SPARK_N_Object_Declaration --
519 ---------------------------------------
521 procedure Expand_SPARK_N_Object_Declaration
(N
: Node_Id
) is
522 Loc
: constant Source_Ptr
:= Sloc
(N
);
523 Obj_Id
: constant Entity_Id
:= Defining_Identifier
(N
);
524 Typ
: constant Entity_Id
:= Etype
(Obj_Id
);
529 -- If the object declaration denotes a variable without initialization
530 -- whose type is subject to pragma Default_Initial_Condition, create
531 -- and analyze a dummy call to the DIC procedure of the type in order
532 -- to detect potential elaboration issues.
534 if Comes_From_Source
(Obj_Id
)
535 and then Ekind
(Obj_Id
) = E_Variable
536 and then Has_DIC
(Typ
)
537 and then Present
(DIC_Procedure
(Typ
))
538 and then not Has_Init_Expression
(N
)
540 Call
:= Build_DIC_Call
(Loc
, New_Occurrence_Of
(Obj_Id
, Loc
), Typ
);
542 -- Partially insert the call into the tree by setting its parent
545 Set_Parent
(Call
, N
);
548 end Expand_SPARK_N_Object_Declaration
;
550 ------------------------------------------------
551 -- Expand_SPARK_N_Object_Renaming_Declaration --
552 ------------------------------------------------
554 procedure Expand_SPARK_N_Object_Renaming_Declaration
(N
: Node_Id
) is
555 CFS
: constant Boolean := Comes_From_Source
(N
);
556 Loc
: constant Source_Ptr
:= Sloc
(N
);
557 Obj_Id
: constant Entity_Id
:= Defining_Entity
(N
);
558 Nam
: constant Node_Id
:= Name
(N
);
559 Typ
: constant Entity_Id
:= Etype
(Obj_Id
);
562 -- Transform a renaming of the form
564 -- Obj_Id : <subtype mark> renames <function call>;
568 -- Obj_Id : constant <subtype mark> := <function call>;
570 -- Invoking Evaluate_Name and ultimately Remove_Side_Effects introduces
571 -- a temporary to capture the function result. Once potential renamings
572 -- are rewritten for SPARK, the temporary may be leaked out into source
573 -- constructs and lead to confusing error diagnostics. Using an object
574 -- declaration prevents this unwanted side effect.
576 if Nkind
(Nam
) = N_Function_Call
then
578 Make_Object_Declaration
(Loc
,
579 Defining_Identifier
=> Obj_Id
,
580 Constant_Present
=> True,
581 Object_Definition
=> New_Occurrence_Of
(Typ
, Loc
),
584 -- Inherit the original Comes_From_Source status of the renaming
586 Set_Comes_From_Source
(N
, CFS
);
588 -- Sever the link to the renamed function result because the entity
589 -- will no longer alias anything.
591 Set_Renamed_Object
(Obj_Id
, Empty
);
593 -- Remove the entity of the renaming declaration from visibility as
594 -- the analysis of the object declaration will reintroduce it again.
596 Remove_Entity_And_Homonym
(Obj_Id
);
599 -- Otherwise unconditionally remove all side effects from the name
604 end Expand_SPARK_N_Object_Renaming_Declaration
;
606 --------------------------
607 -- Expand_SPARK_N_Op_Ne --
608 --------------------------
610 procedure Expand_SPARK_N_Op_Ne
(N
: Node_Id
) is
611 Typ
: constant Entity_Id
:= Etype
(Left_Opnd
(N
));
614 -- Case of elementary type with standard operator
616 if Is_Elementary_Type
(Typ
)
617 and then Sloc
(Entity
(N
)) = Standard_Location
622 Exp_Ch4
.Expand_N_Op_Ne
(N
);
624 end Expand_SPARK_N_Op_Ne
;
626 -------------------------------------
627 -- Expand_SPARK_Potential_Renaming --
628 -------------------------------------
630 procedure Expand_SPARK_Potential_Renaming
(N
: Node_Id
) is
631 function In_Insignificant_Pragma
(Nod
: Node_Id
) return Boolean;
632 -- Determine whether arbitrary node Nod appears within a significant
635 -----------------------------
636 -- In_Insignificant_Pragma --
637 -----------------------------
639 function In_Insignificant_Pragma
(Nod
: Node_Id
) return Boolean is
643 -- Climb the parent chain looking for an enclosing pragma
646 while Present
(Par
) loop
647 if Nkind
(Par
) = N_Pragma
then
648 return not Pragma_Significant_In_SPARK
(Get_Pragma_Id
(Par
));
650 -- Prevent the search from going too far
652 elsif Is_Body_Or_Package_Declaration
(Par
) then
660 end In_Insignificant_Pragma
;
664 Loc
: constant Source_Ptr
:= Sloc
(N
);
665 Obj_Id
: constant Entity_Id
:= Entity
(N
);
666 Typ
: constant Entity_Id
:= Etype
(N
);
669 -- Start of processing for Expand_SPARK_Potential_Renaming
672 -- Replace a reference to a renaming with the actual renamed object
674 if Is_Object
(Obj_Id
) then
675 Ren
:= Renamed_Object
(Obj_Id
);
677 if Present
(Ren
) then
679 -- Do not process a reference when it appears within a pragma of
680 -- no significance to SPARK. It is assumed that the replacement
681 -- will violate the semantics of the pragma and cause a spurious
684 if In_Insignificant_Pragma
(N
) then
687 -- Instantiations and inlining of subprograms employ "prologues"
688 -- which map actual to formal parameters by means of renamings.
689 -- Replace a reference to a formal by the corresponding actual
692 elsif Nkind
(Ren
) in N_Entity
then
693 Rewrite
(N
, New_Occurrence_Of
(Ren
, Loc
));
695 -- Otherwise the renamed object denotes a name
698 Rewrite
(N
, New_Copy_Tree
(Ren
, New_Sloc
=> Loc
));
699 Reset_Analyzed_Flags
(N
);
702 Analyze_And_Resolve
(N
, Typ
);
705 end Expand_SPARK_Potential_Renaming
;