1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- E X P _ P U T _ I M A G E --
9 -- Copyright (C) 2020, 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 Einfo
; use Einfo
;
28 with Exp_Tss
; use Exp_Tss
;
31 with Namet
; use Namet
;
32 with Nlists
; use Nlists
;
33 with Nmake
; use Nmake
;
34 with Rtsfind
; use Rtsfind
;
35 with Sem_Aux
; use Sem_Aux
;
36 with Sem_Util
; use Sem_Util
;
37 with Sinfo
; use Sinfo
;
38 with Snames
; use Snames
;
40 with Tbuild
; use Tbuild
;
41 with Ttypes
; use Ttypes
;
42 with Uintp
; use Uintp
;
44 package body Exp_Put_Image
is
46 -----------------------
47 -- Local Subprograms --
48 -----------------------
50 procedure Build_Put_Image_Proc
56 -- Build an array or record Put_Image procedure. Stms is the list of
57 -- statements for the body and Pnam is the name of the constructed
58 -- procedure. (The declaration list is always null.)
60 function Make_Put_Image_Name
61 (Loc
: Source_Ptr
; Typ
: Entity_Id
) return Entity_Id
;
62 -- Return the entity that identifies the Put_Image subprogram for Typ. This
63 -- procedure deals with the difference between tagged types (where a single
64 -- subprogram associated with the type is generated) and all other cases
65 -- (where a subprogram is generated at the point of the attribute
66 -- reference). The Loc parameter is used as the Sloc of the created entity.
68 function Put_Image_Base_Type
(E
: Entity_Id
) return Entity_Id
;
69 -- Returns the base type, except for an array type whose whose first
70 -- subtype is constrained, in which case it returns the first subtype.
72 -------------------------------------
73 -- Build_Array_Put_Image_Procedure --
74 -------------------------------------
76 procedure Build_Array_Put_Image_Procedure
82 Loc
: constant Source_Ptr
:= Sloc
(Nod
);
87 Index_Subtype
: Entity_Id
;
88 Between_Proc
: RE_Id
) return Node_Id
;
89 -- Wrap Stms in a loop and if statement of the form:
91 -- if V'First (Dim) <= V'Last (Dim) then -- nonempty range?
93 -- LDim : Index_Type_For_Dim := V'First (Dim);
97 -- exit when LDim = V'Last (Dim);
99 -- LDim := Index_Type_For_Dim'Succ (LDim);
104 -- This is called once per dimension, from inner to outer.
106 function Wrap_In_Loop
109 Index_Subtype
: Entity_Id
;
110 Between_Proc
: RE_Id
) return Node_Id
112 Index
: constant Entity_Id
:=
113 Make_Defining_Identifier
114 (Loc
, Chars
=> New_External_Name
('L', Dim
));
115 Decl
: constant Node_Id
:=
116 Make_Object_Declaration
(Loc
,
117 Defining_Identifier
=> Index
,
119 New_Occurrence_Of
(Index_Subtype
, Loc
),
121 Make_Attribute_Reference
(Loc
,
122 Prefix
=> Make_Identifier
(Loc
, Name_V
),
123 Attribute_Name
=> Name_First
,
124 Expressions
=> New_List
(
125 Make_Integer_Literal
(Loc
, Dim
))));
126 Loop_Stm
: constant Node_Id
:=
127 Make_Implicit_Loop_Statement
(Nod
, Statements
=> Stms
);
128 Exit_Stm
: constant Node_Id
:=
129 Make_Exit_Statement
(Loc
,
132 Left_Opnd
=> New_Occurrence_Of
(Index
, Loc
),
134 Make_Attribute_Reference
(Loc
,
136 Make_Identifier
(Loc
, Name_V
),
137 Attribute_Name
=> Name_Last
,
138 Expressions
=> New_List
(
139 Make_Integer_Literal
(Loc
, Dim
)))));
140 Increment
: constant Node_Id
:=
141 Make_Increment
(Loc
, Index
, Index_Subtype
);
142 Between
: constant Node_Id
:=
143 Make_Procedure_Call_Statement
(Loc
,
145 New_Occurrence_Of
(RTE
(Between_Proc
), Loc
),
146 Parameter_Associations
=> New_List
147 (Make_Identifier
(Loc
, Name_S
)));
148 Block
: constant Node_Id
:=
149 Make_Block_Statement
(Loc
,
150 Declarations
=> New_List
(Decl
),
151 Handled_Statement_Sequence
=>
152 Make_Handled_Sequence_Of_Statements
(Loc
,
153 Statements
=> New_List
(Loop_Stm
)));
155 Append_To
(Stms
, Exit_Stm
);
156 Append_To
(Stms
, Between
);
157 Append_To
(Stms
, Increment
);
158 -- Note that we're appending to the Stms list passed in
161 Make_If_Statement
(Loc
,
165 Make_Attribute_Reference
(Loc
,
166 Prefix
=> Make_Identifier
(Loc
, Name_V
),
167 Attribute_Name
=> Name_First
,
168 Expressions
=> New_List
(
169 Make_Integer_Literal
(Loc
, Dim
))),
171 Make_Attribute_Reference
(Loc
,
172 Prefix
=> Make_Identifier
(Loc
, Name_V
),
173 Attribute_Name
=> Name_Last
,
174 Expressions
=> New_List
(
175 Make_Integer_Literal
(Loc
, Dim
)))),
176 Then_Statements
=> New_List
(Block
));
179 Ndim
: constant Pos
:= Number_Dimensions
(Typ
);
180 Ctyp
: constant Entity_Id
:= Component_Type
(Typ
);
183 Exl
: constant List_Id
:= New_List
;
184 PI_Entity
: Entity_Id
;
186 Indices
: array (1 .. Ndim
) of Entity_Id
;
188 -- Start of processing for Build_Array_Put_Image_Procedure
192 Make_Defining_Identifier
(Loc
,
193 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Put_Image
));
198 Index_Subtype
: Node_Id
:= First_Index
(Typ
);
200 for Dim
in 1 .. Ndim
loop
201 Indices
(Dim
) := Etype
(Index_Subtype
);
202 Next_Index
(Index_Subtype
);
204 pragma Assert
(No
(Index_Subtype
));
207 -- Build the inner attribute call
209 for Dim
in 1 .. Ndim
loop
210 Append_To
(Exl
, Make_Identifier
(Loc
, New_External_Name
('L', Dim
)));
214 Make_Attribute_Reference
(Loc
,
215 Prefix
=> New_Occurrence_Of
(Put_Image_Base_Type
(Ctyp
), Loc
),
216 Attribute_Name
=> Name_Put_Image
,
217 Expressions
=> New_List
(
218 Make_Identifier
(Loc
, Name_S
),
219 Make_Indexed_Component
(Loc
,
220 Prefix
=> Make_Identifier
(Loc
, Name_V
),
221 Expressions
=> Exl
)));
223 -- The corresponding attribute for the component type of the array might
224 -- be user-defined, and frozen after the array type. In that case,
225 -- freeze the Put_Image attribute of the component type, whose
226 -- declaration could not generate any additional freezing actions in any
229 PI_Entity
:= TSS
(Base_Type
(Ctyp
), TSS_Put_Image
);
231 if Present
(PI_Entity
) and then not Is_Frozen
(PI_Entity
) then
232 Set_Is_Frozen
(PI_Entity
);
235 -- Loop through the dimensions, innermost first, generating a loop for
239 Stms
: List_Id
:= New_List
(Stm
);
241 for Dim
in reverse 1 .. Ndim
loop
243 New_Stms
: constant List_Id
:= New_List
;
244 Between_Proc
: RE_Id
;
246 -- For a one-dimensional array of elementary type, use
247 -- RE_Simple_Array_Between. The same applies to the last
248 -- dimension of a multidimensional array.
250 if Is_Elementary_Type
(Ctyp
) and then Dim
= Ndim
then
251 Between_Proc
:= RE_Simple_Array_Between
;
253 Between_Proc
:= RE_Array_Between
;
257 Make_Procedure_Call_Statement
(Loc
,
258 Name
=> New_Occurrence_Of
(RTE
(RE_Array_Before
), Loc
),
259 Parameter_Associations
=> New_List
260 (Make_Identifier
(Loc
, Name_S
))));
264 Wrap_In_Loop
(Stms
, Dim
, Indices
(Dim
), Between_Proc
));
267 Make_Procedure_Call_Statement
(Loc
,
268 Name
=> New_Occurrence_Of
(RTE
(RE_Array_After
), Loc
),
269 Parameter_Associations
=> New_List
270 (Make_Identifier
(Loc
, Name_S
))));
276 Build_Put_Image_Proc
(Loc
, Typ
, Decl
, Pnam
, Stms
);
278 end Build_Array_Put_Image_Procedure
;
280 -------------------------------------
281 -- Build_Elementary_Put_Image_Call --
282 -------------------------------------
284 function Build_Elementary_Put_Image_Call
(N
: Node_Id
) return Node_Id
is
285 Loc
: constant Source_Ptr
:= Sloc
(N
);
286 P_Type
: constant Entity_Id
:= Entity
(Prefix
(N
));
287 U_Type
: constant Entity_Id
:= Underlying_Type
(P_Type
);
288 FST
: constant Entity_Id
:= First_Subtype
(U_Type
);
289 Sink
: constant Node_Id
:= First
(Expressions
(N
));
290 Item
: constant Node_Id
:= Next
(Sink
);
291 P_Size
: constant Uint
:= Esize
(FST
);
295 if Is_Signed_Integer_Type
(U_Type
) then
296 if P_Size
<= Standard_Integer_Size
then
297 Lib_RE
:= RE_Put_Image_Integer
;
299 pragma Assert
(P_Size
<= Standard_Long_Long_Integer_Size
);
300 Lib_RE
:= RE_Put_Image_Long_Long_Integer
;
303 elsif Is_Modular_Integer_Type
(U_Type
) then
304 if P_Size
<= Standard_Integer_Size
then -- Yes, Integer
305 Lib_RE
:= RE_Put_Image_Unsigned
;
307 pragma Assert
(P_Size
<= Standard_Long_Long_Integer_Size
);
308 Lib_RE
:= RE_Put_Image_Long_Long_Unsigned
;
311 elsif Is_Access_Type
(U_Type
) then
312 if P_Size
= System_Address_Size
then
313 Lib_RE
:= RE_Put_Image_Thin_Pointer
;
315 pragma Assert
(P_Size
= 2 * System_Address_Size
);
316 Lib_RE
:= RE_Put_Image_Fat_Pointer
;
321 (Is_Enumeration_Type
(U_Type
) or else Is_Real_Type
(U_Type
));
323 -- For other elementary types, generate:
325 -- Put_Wide_Wide_String (Sink, U_Type'Wide_Wide_Image (Item));
327 -- It would be more elegant to do it the other way around (define
328 -- '[[Wide_]Wide_]Image in terms of 'Put_Image). But this is easier
329 -- to implement, because we already have support for
330 -- 'Wide_Wide_Image. Furthermore, we don't want to remove the
331 -- existing support for '[[Wide_]Wide_]Image, because we don't
332 -- currently plan to support 'Put_Image on restricted runtimes.
336 -- Put_UTF_8 (Sink, U_Type'Image (Item));
338 -- because we need to generate UTF-8, but 'Image for enumeration
339 -- types uses the character encoding of the source file.
341 -- Note that this is putting a leading space for reals.
343 if Is_Real_Type
(U_Type
) then
344 return Build_Unknown_Put_Image_Call
(N
);
348 Image
: constant Node_Id
:=
349 Make_Attribute_Reference
(Loc
,
350 Prefix
=> New_Occurrence_Of
(U_Type
, Loc
),
351 Attribute_Name
=> Name_Wide_Wide_Image
,
352 Expressions
=> New_List
(Relocate_Node
(Item
)));
353 Put_Call
: constant Node_Id
:=
354 Make_Procedure_Call_Statement
(Loc
,
356 New_Occurrence_Of
(RTE
(RE_Put_Wide_Wide_String
), Loc
),
357 Parameter_Associations
=> New_List
358 (Relocate_Node
(Sink
), Image
));
364 -- Unchecked-convert parameter to the required type (i.e. the type of
365 -- the corresponding parameter), and call the appropriate routine.
366 -- We could use a normal type conversion for scalars, but the
367 -- "unchecked" is needed for access and private types.
370 Libent
: constant Entity_Id
:= RTE
(Lib_RE
);
373 Make_Procedure_Call_Statement
(Loc
,
374 Name
=> New_Occurrence_Of
(Libent
, Loc
),
375 Parameter_Associations
=> New_List
(
376 Relocate_Node
(Sink
),
378 (Etype
(Next_Formal
(First_Formal
(Libent
))),
379 Relocate_Node
(Item
))));
381 end Build_Elementary_Put_Image_Call
;
383 -------------------------------------
384 -- Build_String_Put_Image_Call --
385 -------------------------------------
387 function Build_String_Put_Image_Call
(N
: Node_Id
) return Node_Id
is
388 Loc
: constant Source_Ptr
:= Sloc
(N
);
389 P_Type
: constant Entity_Id
:= Entity
(Prefix
(N
));
390 U_Type
: constant Entity_Id
:= Underlying_Type
(P_Type
);
391 R
: constant Entity_Id
:= Root_Type
(U_Type
);
392 Sink
: constant Node_Id
:= First
(Expressions
(N
));
393 Item
: constant Node_Id
:= Next
(Sink
);
397 if R
= Standard_String
then
398 Lib_RE
:= RE_Put_Image_String
;
399 elsif R
= Standard_Wide_String
then
400 Lib_RE
:= RE_Put_Image_Wide_String
;
401 elsif R
= Standard_Wide_Wide_String
then
402 Lib_RE
:= RE_Put_Image_Wide_Wide_String
;
407 -- Convert parameter to the required type (i.e. the type of the
408 -- corresponding parameter), and call the appropriate routine.
411 Libent
: constant Entity_Id
:= RTE
(Lib_RE
);
414 Make_Procedure_Call_Statement
(Loc
,
415 Name
=> New_Occurrence_Of
(Libent
, Loc
),
416 Parameter_Associations
=> New_List
(
417 Relocate_Node
(Sink
),
419 (Etype
(Next_Formal
(First_Formal
(Libent
))),
420 Relocate_Node
(Item
))));
422 end Build_String_Put_Image_Call
;
424 ------------------------------------
425 -- Build_Protected_Put_Image_Call --
426 ------------------------------------
428 -- For "Protected_Type'Put_Image (S, Protected_Object)", build:
430 -- Put_Image_Protected (S);
432 -- The protected object is not passed.
434 function Build_Protected_Put_Image_Call
(N
: Node_Id
) return Node_Id
is
435 Loc
: constant Source_Ptr
:= Sloc
(N
);
436 Sink
: constant Node_Id
:= First
(Expressions
(N
));
437 Lib_RE
: constant RE_Id
:= RE_Put_Image_Protected
;
438 Libent
: constant Entity_Id
:= RTE
(Lib_RE
);
441 Make_Procedure_Call_Statement
(Loc
,
442 Name
=> New_Occurrence_Of
(Libent
, Loc
),
443 Parameter_Associations
=> New_List
(
444 Relocate_Node
(Sink
)));
445 end Build_Protected_Put_Image_Call
;
447 ------------------------------------
448 -- Build_Task_Put_Image_Call --
449 ------------------------------------
451 -- For "Task_Type'Put_Image (S, Task_Object)", build:
453 -- Put_Image_Task (S, Task_Object'Identity);
455 -- The task object is not passed; its Task_Id is.
457 function Build_Task_Put_Image_Call
(N
: Node_Id
) return Node_Id
is
458 Loc
: constant Source_Ptr
:= Sloc
(N
);
459 Sink
: constant Node_Id
:= First
(Expressions
(N
));
460 Item
: constant Node_Id
:= Next
(Sink
);
461 Lib_RE
: constant RE_Id
:= RE_Put_Image_Task
;
462 Libent
: constant Entity_Id
:= RTE
(Lib_RE
);
464 Task_Id
: constant Node_Id
:=
465 Make_Attribute_Reference
(Loc
,
466 Prefix
=> Relocate_Node
(Item
),
467 Attribute_Name
=> Name_Identity
,
468 Expressions
=> No_List
);
472 Make_Procedure_Call_Statement
(Loc
,
473 Name
=> New_Occurrence_Of
(Libent
, Loc
),
474 Parameter_Associations
=> New_List
(
475 Relocate_Node
(Sink
),
477 end Build_Task_Put_Image_Call
;
479 --------------------------------------
480 -- Build_Record_Put_Image_Procedure --
481 --------------------------------------
483 -- The form of the record Put_Image procedure is as shown by the
484 -- following example:
486 -- procedure Put_Image (S : in out Sink'Class; V : Typ) is
488 -- Component_Type'Put_Image (S, V.component);
489 -- Component_Type'Put_Image (S, V.component);
491 -- Component_Type'Put_Image (S, V.component);
493 -- case V.discriminant is
495 -- Component_Type'Put_Image (S, V.component);
496 -- Component_Type'Put_Image (S, V.component);
498 -- Component_Type'Put_Image (S, V.component);
501 -- Component_Type'Put_Image (S, V.component);
502 -- Component_Type'Put_Image (S, V.component);
504 -- Component_Type'Put_Image (S, V.component);
509 procedure Build_Record_Put_Image_Procedure
513 Pnam
: out Entity_Id
)
515 pragma Assert
(Typ
= Base_Type
(Typ
));
516 pragma Assert
(not Is_Unchecked_Union
(Typ
));
518 First_Time
: Boolean := True;
520 function Make_Component_List_Attributes
(CL
: Node_Id
) return List_Id
;
521 -- Returns a sequence of Component_Type'Put_Image attribute_references
522 -- to process the components that are referenced in the given component
523 -- list. Called for the main component list, and then recursively for
526 function Make_Component_Attributes
(Clist
: List_Id
) return List_Id
;
527 -- Given Clist, a component items list, construct series of
528 -- Component_Type'Put_Image attribute_references for componentwise
529 -- processing of the corresponding components. Called for the
530 -- discriminants, and then from Make_Component_List_Attributes for each
531 -- list (including in variants).
533 procedure Append_Component_Attr
(Clist
: List_Id
; C
: Entity_Id
);
534 -- Given C, the entity for a discriminant or component, build a call to
535 -- Component_Type'Put_Image for the corresponding component value, and
536 -- append it onto Clist. Called from Make_Component_Attributes.
538 function Make_Component_Name
(C
: Entity_Id
) return Node_Id
;
539 -- Create a call that prints "Comp_Name => "
541 ------------------------------------
542 -- Make_Component_List_Attributes --
543 ------------------------------------
545 function Make_Component_List_Attributes
(CL
: Node_Id
) return List_Id
is
546 CI
: constant List_Id
:= Component_Items
(CL
);
547 VP
: constant Node_Id
:= Variant_Part
(CL
);
557 Result
:= Make_Component_Attributes
(CI
);
562 V
:= First_Non_Pragma
(Variants
(VP
));
563 while Present
(V
) loop
566 DC
:= First
(Discrete_Choices
(V
));
567 while Present
(DC
) loop
568 Append_To
(DCH
, New_Copy_Tree
(DC
));
573 Make_Case_Statement_Alternative
(Loc
,
574 Discrete_Choices
=> DCH
,
576 Make_Component_List_Attributes
(Component_List
(V
))));
580 -- Note: in the following, we use New_Occurrence_Of for the
581 -- selector, since there are cases in which we make a reference
582 -- to a hidden discriminant that is not visible.
584 -- If the enclosing record is an unchecked_union, we use the
585 -- default expressions for the discriminant (it must exist)
586 -- because we cannot generate a reference to it, given that it is
587 -- not stored. ????This seems unfriendly. It should just print
588 -- "(unchecked union)" instead. (Note that this code is
589 -- unreachable -- see exp_attr.)
591 if Is_Unchecked_Union
(Scope
(Entity
(Name
(VP
)))) then
594 (Discriminant_Default_Value
(Entity
(Name
(VP
))));
597 Make_Selected_Component
(Loc
,
598 Prefix
=> Make_Identifier
(Loc
, Name_V
),
600 New_Occurrence_Of
(Entity
(Name
(VP
)), Loc
));
604 Make_Case_Statement
(Loc
,
606 Alternatives
=> Alts
));
610 end Make_Component_List_Attributes
;
612 --------------------------------
613 -- Append_Component_Attr --
614 --------------------------------
616 procedure Append_Component_Attr
(Clist
: List_Id
; C
: Entity_Id
) is
617 Component_Typ
: constant Entity_Id
:= Put_Image_Base_Type
(Etype
(C
));
619 if Ekind
(C
) /= E_Void
then
621 Make_Attribute_Reference
(Loc
,
622 Prefix
=> New_Occurrence_Of
(Component_Typ
, Loc
),
623 Attribute_Name
=> Name_Put_Image
,
624 Expressions
=> New_List
(
625 Make_Identifier
(Loc
, Name_S
),
626 Make_Selected_Component
(Loc
,
627 Prefix
=> Make_Identifier
(Loc
, Name_V
),
628 Selector_Name
=> New_Occurrence_Of
(C
, Loc
)))));
630 end Append_Component_Attr
;
632 -------------------------------
633 -- Make_Component_Attributes --
634 -------------------------------
636 function Make_Component_Attributes
(Clist
: List_Id
) return List_Id
is
643 if Present
(Clist
) then
644 Item
:= First
(Clist
);
646 -- Loop through components, skipping all internal components,
647 -- which are not part of the value (e.g. _Tag), except that we
648 -- don't skip the _Parent, since we do want to process that
649 -- recursively. If _Parent is an interface type, being abstract
650 -- with no components there is no need to handle it.
652 while Present
(Item
) loop
653 if Nkind_In
(Item
, N_Component_Declaration
,
654 N_Discriminant_Specification
)
656 ((Chars
(Defining_Identifier
(Item
)) = Name_uParent
657 and then not Is_Interface
658 (Etype
(Defining_Identifier
(Item
))))
660 not Is_Internal_Name
(Chars
(Defining_Identifier
(Item
))))
666 Make_Procedure_Call_Statement
(Loc
,
668 New_Occurrence_Of
(RTE
(RE_Record_Between
), Loc
),
669 Parameter_Associations
=> New_List
670 (Make_Identifier
(Loc
, Name_S
))));
673 Append_To
(Result
, Make_Component_Name
(Item
));
674 Append_Component_Attr
(Result
, Defining_Identifier
(Item
));
682 end Make_Component_Attributes
;
684 -------------------------
685 -- Make_Component_Name --
686 -------------------------
688 function Make_Component_Name
(C
: Entity_Id
) return Node_Id
is
689 Name
: constant Name_Id
:= Chars
(Defining_Identifier
(C
));
692 Make_Procedure_Call_Statement
(Loc
,
693 Name
=> New_Occurrence_Of
(RTE
(RE_Put_UTF_8
), Loc
),
694 Parameter_Associations
=> New_List
695 (Make_Identifier
(Loc
, Name_S
),
696 Make_String_Literal
(Loc
, Get_Name_String
(Name
) & " => ")));
697 end Make_Component_Name
;
699 Stms
: constant List_Id
:= New_List
;
701 Type_Decl
: constant Node_Id
:=
702 Declaration_Node
(Base_Type
(Underlying_Type
(Typ
)));
704 -- Start of processing for Build_Record_Put_Image_Procedure
708 Make_Procedure_Call_Statement
(Loc
,
709 Name
=> New_Occurrence_Of
(RTE
(RE_Record_Before
), Loc
),
710 Parameter_Associations
=> New_List
711 (Make_Identifier
(Loc
, Name_S
))));
713 -- Generate Put_Images for the discriminants of the type
714 -- If the type is an unchecked union, use the default values of
715 -- the discriminants, because they are not stored.
717 Append_List_To
(Stms
,
718 Make_Component_Attributes
(Discriminant_Specifications
(Type_Decl
)));
720 Rdef
:= Type_Definition
(Type_Decl
);
722 -- In the record extension case, the components we want, including the
723 -- _Parent component representing the parent type, are to be found in
724 -- the extension. We will process the _Parent component using the type
727 if Nkind
(Rdef
) = N_Derived_Type_Definition
then
728 Rdef
:= Record_Extension_Part
(Rdef
);
731 if Present
(Component_List
(Rdef
)) then
732 Append_List_To
(Stms
,
733 Make_Component_List_Attributes
(Component_List
(Rdef
)));
737 Make_Procedure_Call_Statement
(Loc
,
738 Name
=> New_Occurrence_Of
(RTE
(RE_Record_After
), Loc
),
739 Parameter_Associations
=> New_List
740 (Make_Identifier
(Loc
, Name_S
))));
742 Pnam
:= Make_Put_Image_Name
(Loc
, Typ
);
743 Build_Put_Image_Proc
(Loc
, Typ
, Decl
, Pnam
, Stms
);
744 end Build_Record_Put_Image_Procedure
;
746 -------------------------------
747 -- Build_Put_Image_Profile --
748 -------------------------------
750 function Build_Put_Image_Profile
751 (Loc
: Source_Ptr
; Typ
: Entity_Id
) return List_Id
755 Make_Parameter_Specification
(Loc
,
756 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_S
),
760 New_Occurrence_Of
(Class_Wide_Type
(RTE
(RE_Sink
)), Loc
)),
762 Make_Parameter_Specification
(Loc
,
763 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
764 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
)));
765 end Build_Put_Image_Profile
;
767 --------------------------
768 -- Build_Put_Image_Proc --
769 --------------------------
771 procedure Build_Put_Image_Proc
778 Spec
: constant Node_Id
:=
779 Make_Procedure_Specification
(Loc
,
780 Defining_Unit_Name
=> Pnam
,
781 Parameter_Specifications
=> Build_Put_Image_Profile
(Loc
, Typ
));
784 Make_Subprogram_Body
(Loc
,
785 Specification
=> Spec
,
786 Declarations
=> Empty_List
,
787 Handled_Statement_Sequence
=>
788 Make_Handled_Sequence_Of_Statements
(Loc
,
789 Statements
=> Stms
));
790 end Build_Put_Image_Proc
;
792 ------------------------------------
793 -- Build_Unknown_Put_Image_Call --
794 ------------------------------------
796 function Build_Unknown_Put_Image_Call
(N
: Node_Id
) return Node_Id
is
797 Loc
: constant Source_Ptr
:= Sloc
(N
);
798 Sink
: constant Node_Id
:= First
(Expressions
(N
));
799 Lib_RE
: constant RE_Id
:= RE_Put_Image_Unknown
;
800 Libent
: constant Entity_Id
:= RTE
(Lib_RE
);
803 Make_Procedure_Call_Statement
(Loc
,
804 Name
=> New_Occurrence_Of
(Libent
, Loc
),
805 Parameter_Associations
=> New_List
(
806 Relocate_Node
(Sink
),
807 Make_String_Literal
(Loc
,
808 Exp_Util
.Fully_Qualified_Name_String
(
809 Entity
(Prefix
(N
)), Append_NUL
=> False))));
810 end Build_Unknown_Put_Image_Call
;
812 ----------------------
813 -- Enable_Put_Image --
814 ----------------------
816 function Enable_Put_Image
(Typ
: Entity_Id
) return Boolean is
818 -- There's a bit of a chicken&egg problem. The compiler is likely to
819 -- have trouble if we refer to the Put_Image of Sink itself, because
820 -- Sink is part of the parameter profile:
822 -- function Sink'Put_Image (S : in out Sink'Class; V : T);
824 -- Likewise, the Ada.Strings.Text_Output package, where Sink is
825 -- declared, depends on various other packages, so if we refer to
826 -- Put_Image of types declared in those other packages, we could create
827 -- cyclic dependencies. Therefore, we disable Put_Image for some
828 -- types. It's not clear exactly what types should be disabled. Scalar
829 -- types are OK, even if predefined, because calls to Put_Image of
830 -- scalar types are expanded inline. We certainly want to be able to use
831 -- Integer'Put_Image, for example.
833 -- ???Temporarily disable to work around bugs:
835 -- Put_Image does not work for Remote_Types. We check the containing
836 -- package, rather than the type itself, because we want to include
837 -- types in the private part of a Remote_Types package.
839 -- Put_Image on tagged types triggers some bugs.
841 -- Put_Image doesn't work for private types whose full type is real.
843 if Is_Remote_Types
(Scope
(Typ
))
844 or else Is_Tagged_Type
(Typ
)
845 or else Is_Real_Type
(Typ
)
850 -- ???Disable Put_Image on type Sink declared in
851 -- Ada.Strings.Text_Output. Note that we can't call Is_RTU on
852 -- Ada_Strings_Text_Output, because it's not known yet (we might be
853 -- compiling it). But this is insufficient to allow support for tagged
857 Parent_Scope
: constant Entity_Id
:= Scope
(Scope
(Typ
));
859 if Present
(Parent_Scope
)
860 and then Is_RTU
(Parent_Scope
, Ada_Strings
)
861 and then Chars
(Scope
(Typ
)) = Name_Find
("text_output")
867 return Is_Scalar_Type
(Typ
) or else not In_Predefined_Unit
(Typ
);
868 end Enable_Put_Image
;
870 ---------------------------------
871 -- Make_Put_Image_Name --
872 ---------------------------------
874 function Make_Put_Image_Name
875 (Loc
: Source_Ptr
; Typ
: Entity_Id
) return Entity_Id
879 -- For tagged types, we are dealing with a TSS associated with the
880 -- declaration, so we use the standard primitive function name. For
881 -- other types, generate a local TSS name since we are generating
882 -- the subprogram at the point of use.
884 if Is_Tagged_Type
(Typ
) then
885 Sname
:= Make_TSS_Name
(Typ
, TSS_Put_Image
);
887 Sname
:= Make_TSS_Name_Local
(Typ
, TSS_Put_Image
);
890 return Make_Defining_Identifier
(Loc
, Sname
);
891 end Make_Put_Image_Name
;
893 ----------------------
894 -- Put_Image_Base_Type --
895 ----------------------
897 function Put_Image_Base_Type
(E
: Entity_Id
) return Entity_Id
is
899 if Is_Array_Type
(E
) and then Is_First_Subtype
(E
) then
902 return Base_Type
(E
);
904 end Put_Image_Base_Type
;