1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2003, 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Atree
; use Atree
;
28 with Einfo
; use Einfo
;
29 with Namet
; use Namet
;
30 with Nlists
; use Nlists
;
31 with Nmake
; use Nmake
;
32 with Rtsfind
; use Rtsfind
;
33 with Sinfo
; use Sinfo
;
34 with Snames
; use Snames
;
35 with Stand
; use Stand
;
36 with Tbuild
; use Tbuild
;
37 with Ttypes
; use Ttypes
;
38 with Exp_Tss
; use Exp_Tss
;
39 with Uintp
; use Uintp
;
41 package body Exp_Strm
is
43 -----------------------
44 -- Local Subprograms --
45 -----------------------
47 procedure Build_Array_Read_Write_Procedure
53 -- Common routine shared to build either an array Read procedure or an
54 -- array Write procedure, Nam is Name_Read or Name_Write to select which.
55 -- Pnam is the defining identifier for the constructed procedure. The
56 -- other parameters are as for Build_Array_Read_Procedure except that
57 -- the first parameter Nod supplies the Sloc to be used to generate code.
59 procedure Build_Record_Read_Write_Procedure
65 -- Common routine shared to build a record Read Write procedure, Nam
66 -- is Name_Read or Name_Write to select which. Pnam is the defining
67 -- identifier for the constructed procedure. The other parameters are
68 -- as for Build_Record_Read_Procedure.
70 procedure Build_Stream_Function
77 -- Called to build an array or record stream function. The first three
78 -- arguments are the same as Build_Record_Or_Elementary_Input_Function.
79 -- Decls and Stms are the declarations and statements for the body and
80 -- The parameter Fnam is the name of the constructed function.
82 function Has_Stream_Standard_Rep
(U_Type
: Entity_Id
) return Boolean;
83 -- This function is used to test U_Type, which is a type
84 -- Returns True if U_Type has a standard representation for stream
85 -- purposes, i.e. there is no non-standard enumeration representation
86 -- clause, and the size of the first subtype is the same as the size
89 function Make_Stream_Subprogram_Name
92 Nam
: TSS_Name_Type
) return Entity_Id
;
93 -- Return the entity that identifies the stream subprogram for type Typ
94 -- that is identified by the given Nam. This procedure deals with the
95 -- difference between tagged types (where a single subprogram associated
96 -- with the type is generated) and all other cases (where a subprogram
97 -- is generated at the point of the stream attribute reference). The
98 -- Loc parameter is used as the Sloc of the created entity.
100 function Stream_Base_Type
(E
: Entity_Id
) return Entity_Id
;
101 -- Stream attributes work on the basis of the base type except for the
102 -- array case. For the array case, we do not go to the base type, but
103 -- to the first subtype if it is constrained. This avoids problems with
104 -- incorrect conversions in the packed array case. Stream_Base_Type is
105 -- exactly this function (returns the base type, unless we have an array
106 -- type whose first subtype is constrained, in which case it returns the
109 --------------------------------
110 -- Build_Array_Input_Function --
111 --------------------------------
113 -- The function we build looks like
115 -- function typSI[_nnn] (S : access RST) return Typ is
116 -- L1 : constant Index_Type_1 := Index_Type_1'Input (S);
117 -- H1 : constant Index_Type_1 := Index_Type_1'Input (S);
118 -- L2 : constant Index_Type_2 := Index_Type_2'Input (S);
119 -- H2 : constant Index_Type_2 := Index_Type_2'Input (S);
121 -- Ln : constant Index_Type_n := Index_Type_n'Input (S);
122 -- Hn : constant Index_Type_n := Index_Type_n'Input (S);
124 -- V : Typ'Base (L1 .. H1, L2 .. H2, ... Ln .. Hn)
131 -- Note: the suffix [_nnn] is present for non-tagged types, where we
132 -- generate a local subprogram at the point of the occurrence of the
133 -- attribute reference, so the name must be unique.
135 procedure Build_Array_Input_Function
139 Fnam
: out Entity_Id
)
141 Dim
: constant Pos
:= Number_Dimensions
(Typ
);
152 Indx
:= First_Index
(Typ
);
154 for J
in 1 .. Dim
loop
155 Lnam
:= New_External_Name
('L', J
);
156 Hnam
:= New_External_Name
('H', J
);
159 Make_Object_Declaration
(Loc
,
160 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Lnam
),
161 Constant_Present
=> True,
162 Object_Definition
=> New_Occurrence_Of
(Etype
(Indx
), Loc
),
164 Make_Attribute_Reference
(Loc
,
166 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Indx
)), Loc
),
167 Attribute_Name
=> Name_Input
,
168 Expressions
=> New_List
(Make_Identifier
(Loc
, Name_S
)))));
171 Make_Object_Declaration
(Loc
,
172 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Hnam
),
173 Constant_Present
=> True,
175 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Indx
)), Loc
),
177 Make_Attribute_Reference
(Loc
,
179 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Indx
)), Loc
),
180 Attribute_Name
=> Name_Input
,
181 Expressions
=> New_List
(Make_Identifier
(Loc
, Name_S
)))));
185 Low_Bound
=> Make_Identifier
(Loc
, Lnam
),
186 High_Bound
=> Make_Identifier
(Loc
, Hnam
)));
191 -- If the first subtype is constrained, use it directly. Otherwise
192 -- build a subtype indication with the proper bounds.
194 if Is_Constrained
(Stream_Base_Type
(Typ
)) then
196 Make_Object_Declaration
(Loc
,
197 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
199 New_Occurrence_Of
(Stream_Base_Type
(Typ
), Loc
)));
202 Make_Object_Declaration
(Loc
,
203 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
205 Make_Subtype_Indication
(Loc
,
207 New_Occurrence_Of
(Stream_Base_Type
(Typ
), Loc
),
209 Make_Index_Or_Discriminant_Constraint
(Loc
,
210 Constraints
=> Ranges
))));
214 Make_Attribute_Reference
(Loc
,
215 Prefix
=> New_Occurrence_Of
(Typ
, Loc
),
216 Attribute_Name
=> Name_Read
,
217 Expressions
=> New_List
(
218 Make_Identifier
(Loc
, Name_S
),
219 Make_Identifier
(Loc
, Name_V
))),
221 Make_Return_Statement
(Loc
,
222 Expression
=> Make_Identifier
(Loc
, Name_V
)));
225 Make_Defining_Identifier
(Loc
,
226 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Input
));
228 Build_Stream_Function
(Loc
, Typ
, Decl
, Fnam
, Decls
, Stms
);
229 end Build_Array_Input_Function
;
231 ----------------------------------
232 -- Build_Array_Output_Procedure --
233 ----------------------------------
235 procedure Build_Array_Output_Procedure
239 Pnam
: out Entity_Id
)
245 -- Build series of statements to output bounds
247 Indx
:= First_Index
(Typ
);
250 for J
in 1 .. Number_Dimensions
(Typ
) loop
252 Make_Attribute_Reference
(Loc
,
254 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Indx
)), Loc
),
255 Attribute_Name
=> Name_Write
,
256 Expressions
=> New_List
(
257 Make_Identifier
(Loc
, Name_S
),
258 Make_Attribute_Reference
(Loc
,
259 Prefix
=> Make_Identifier
(Loc
, Name_V
),
260 Attribute_Name
=> Name_First
,
261 Expressions
=> New_List
(
262 Make_Integer_Literal
(Loc
, J
))))));
265 Make_Attribute_Reference
(Loc
,
267 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Indx
)), Loc
),
268 Attribute_Name
=> Name_Write
,
269 Expressions
=> New_List
(
270 Make_Identifier
(Loc
, Name_S
),
271 Make_Attribute_Reference
(Loc
,
272 Prefix
=> Make_Identifier
(Loc
, Name_V
),
273 Attribute_Name
=> Name_Last
,
274 Expressions
=> New_List
(
275 Make_Integer_Literal
(Loc
, J
))))));
280 -- Append Write attribute to write array elements
283 Make_Attribute_Reference
(Loc
,
284 Prefix
=> New_Occurrence_Of
(Typ
, Loc
),
285 Attribute_Name
=> Name_Write
,
286 Expressions
=> New_List
(
287 Make_Identifier
(Loc
, Name_S
),
288 Make_Identifier
(Loc
, Name_V
))));
291 Make_Defining_Identifier
(Loc
,
292 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Output
));
294 Build_Stream_Procedure
(Loc
, Typ
, Decl
, Pnam
, Stms
, False);
295 end Build_Array_Output_Procedure
;
297 --------------------------------
298 -- Build_Array_Read_Procedure --
299 --------------------------------
301 procedure Build_Array_Read_Procedure
305 Pnam
: out Entity_Id
)
307 Loc
: constant Source_Ptr
:= Sloc
(Nod
);
311 Make_Defining_Identifier
(Loc
,
312 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Read
));
313 Build_Array_Read_Write_Procedure
(Nod
, Typ
, Decl
, Pnam
, Name_Read
);
314 end Build_Array_Read_Procedure
;
316 --------------------------------------
317 -- Build_Array_Read_Write_Procedure --
318 --------------------------------------
320 -- The form of the array read/write procedure is as follows:
322 -- procedure pnam (S : access RST, V : [out] Typ) is
324 -- for L1 in V'Range (1) loop
325 -- for L2 in V'Range (2) loop
327 -- for Ln in V'Range (n) loop
328 -- Component_Type'Read/Write (S, V (L1, L2, .. Ln));
335 -- The out keyword for V is supplied in the Read case
337 procedure Build_Array_Read_Write_Procedure
344 Loc
: constant Source_Ptr
:= Sloc
(Nod
);
345 Ndim
: constant Pos
:= Number_Dimensions
(Typ
);
346 Ctyp
: constant Entity_Id
:= Component_Type
(Typ
);
353 -- First build the inner attribute call
357 for J
in 1 .. Ndim
loop
358 Append_To
(Exl
, Make_Identifier
(Loc
, New_External_Name
('L', J
)));
362 Make_Attribute_Reference
(Loc
,
363 Prefix
=> New_Occurrence_Of
(Stream_Base_Type
(Ctyp
), Loc
),
364 Attribute_Name
=> Nam
,
365 Expressions
=> New_List
(
366 Make_Identifier
(Loc
, Name_S
),
367 Make_Indexed_Component
(Loc
,
368 Prefix
=> Make_Identifier
(Loc
, Name_V
),
369 Expressions
=> Exl
)));
371 -- The corresponding stream attribute for the component type of the
372 -- array may be user-defined, and be frozen after the type for which
373 -- we are generating the stream subprogram. In that case, freeze the
374 -- stream attribute of the component type, whose declaration could not
375 -- generate any additional freezing actions in any case. See 5509-003.
377 if Nam
= Name_Read
then
378 RW
:= TSS
(Base_Type
(Ctyp
), TSS_Stream_Read
);
380 RW
:= TSS
(Base_Type
(Ctyp
), TSS_Stream_Write
);
384 and then not Is_Frozen
(RW
)
389 -- Now this is the big loop to wrap that statement up in a sequence
390 -- of loops. The first time around, Stm is the attribute call. The
391 -- second and subsequent times, Stm is an inner loop.
393 for J
in 1 .. Ndim
loop
395 Make_Implicit_Loop_Statement
(Nod
,
397 Make_Iteration_Scheme
(Loc
,
398 Loop_Parameter_Specification
=>
399 Make_Loop_Parameter_Specification
(Loc
,
400 Defining_Identifier
=>
401 Make_Defining_Identifier
(Loc
,
402 Chars
=> New_External_Name
('L', Ndim
- J
+ 1)),
404 Discrete_Subtype_Definition
=>
405 Make_Attribute_Reference
(Loc
,
406 Prefix
=> Make_Identifier
(Loc
, Name_V
),
407 Attribute_Name
=> Name_Range
,
409 Expressions
=> New_List
(
410 Make_Integer_Literal
(Loc
, Ndim
- J
+ 1))))),
412 Statements
=> New_List
(Stm
));
416 Build_Stream_Procedure
417 (Loc
, Typ
, Decl
, Pnam
, New_List
(Stm
), Nam
= Name_Read
);
418 end Build_Array_Read_Write_Procedure
;
420 ---------------------------------
421 -- Build_Array_Write_Procedure --
422 ---------------------------------
424 procedure Build_Array_Write_Procedure
428 Pnam
: out Entity_Id
)
430 Loc
: constant Source_Ptr
:= Sloc
(Nod
);
434 Make_Defining_Identifier
(Loc
,
435 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Write
));
436 Build_Array_Read_Write_Procedure
(Nod
, Typ
, Decl
, Pnam
, Name_Write
);
437 end Build_Array_Write_Procedure
;
439 ---------------------------------
440 -- Build_Elementary_Input_Call --
441 ---------------------------------
443 function Build_Elementary_Input_Call
(N
: Node_Id
) return Node_Id
is
444 Loc
: constant Source_Ptr
:= Sloc
(N
);
445 P_Type
: constant Entity_Id
:= Entity
(Prefix
(N
));
446 U_Type
: constant Entity_Id
:= Underlying_Type
(P_Type
);
447 Rt_Type
: constant Entity_Id
:= Root_Type
(U_Type
);
448 FST
: constant Entity_Id
:= First_Subtype
(U_Type
);
449 P_Size
: constant Uint
:= Esize
(FST
);
451 Strm
: constant Node_Id
:= First
(Expressions
(N
));
452 Targ
: constant Node_Id
:= Next
(Strm
);
456 -- Check first for Boolean and Character. These are enumeration types,
457 -- but we treat them specially, since they may require special handling
458 -- in the transfer protocol. However, this special handling only applies
459 -- if they have standard representation, otherwise they are treated like
460 -- any other enumeration type.
462 if Rt_Type
= Standard_Boolean
463 and then Has_Stream_Standard_Rep
(U_Type
)
467 elsif Rt_Type
= Standard_Character
468 and then Has_Stream_Standard_Rep
(U_Type
)
472 elsif Rt_Type
= Standard_Wide_Character
473 and then Has_Stream_Standard_Rep
(U_Type
)
477 -- Floating point types
479 elsif Is_Floating_Point_Type
(U_Type
) then
481 if Rt_Type
= Standard_Short_Float
then
484 elsif Rt_Type
= Standard_Float
then
487 elsif Rt_Type
= Standard_Long_Float
then
490 else pragma Assert
(Rt_Type
= Standard_Long_Long_Float
);
494 -- Signed integer types. Also includes signed fixed-point types and
495 -- enumeration types with a signed representation.
497 -- Note on signed integer types. We do not consider types as signed for
498 -- this purpose if they have no negative numbers, or if they have biased
499 -- representation. The reason is that the value in either case basically
500 -- represents an unsigned value.
502 -- For example, consider:
504 -- type W is range 0 .. 2**32 - 1;
505 -- for W'Size use 32;
507 -- This is a signed type, but the representation is unsigned, and may
508 -- be outside the range of a 32-bit signed integer, so this must be
509 -- treated as 32-bit unsigned.
511 -- Similarly, if we have
513 -- type W is range -1 .. +254;
516 -- then the representation is unsigned
518 elsif not Is_Unsigned_Type
(FST
)
520 (Is_Fixed_Point_Type
(U_Type
)
522 Is_Enumeration_Type
(U_Type
)
524 (Is_Signed_Integer_Type
(U_Type
)
525 and then not Has_Biased_Representation
(FST
)))
527 if P_Size
<= Standard_Short_Short_Integer_Size
then
530 elsif P_Size
<= Standard_Short_Integer_Size
then
533 elsif P_Size
<= Standard_Integer_Size
then
536 elsif P_Size
<= Standard_Long_Integer_Size
then
543 -- Unsigned integer types, also includes unsigned fixed-point types
544 -- and enumeration types with an unsigned representation (note that
545 -- we know they are unsigned because we already tested for signed).
547 -- Also includes signed integer types that are unsigned in the sense
548 -- that they do not include negative numbers. See above for details.
550 elsif Is_Modular_Integer_Type
(U_Type
)
551 or else Is_Fixed_Point_Type
(U_Type
)
552 or else Is_Enumeration_Type
(U_Type
)
553 or else Is_Signed_Integer_Type
(U_Type
)
555 if P_Size
<= Standard_Short_Short_Integer_Size
then
558 elsif P_Size
<= Standard_Short_Integer_Size
then
561 elsif P_Size
<= Standard_Integer_Size
then
564 elsif P_Size
<= Standard_Long_Integer_Size
then
571 else pragma Assert
(Is_Access_Type
(U_Type
));
572 if P_Size
> System_Address_Size
then
579 -- Call the function, and do an unchecked conversion of the result
580 -- to the actual type of the prefix. If the target is a discriminant,
581 -- set target type to force a constraint check (13.13.2 (35)).
583 if Nkind
(Targ
) = N_Selected_Component
584 and then Present
(Entity
(Selector_Name
(Targ
)))
585 and then Ekind
(Entity
(Selector_Name
(Targ
)))
589 Unchecked_Convert_To
(Base_Type
(P_Type
),
590 Make_Function_Call
(Loc
,
591 Name
=> New_Occurrence_Of
(RTE
(Lib_RE
), Loc
),
592 Parameter_Associations
=> New_List
(
593 Relocate_Node
(Strm
))));
595 Set_Do_Range_Check
(Res
);
600 Unchecked_Convert_To
(P_Type
,
601 Make_Function_Call
(Loc
,
602 Name
=> New_Occurrence_Of
(RTE
(Lib_RE
), Loc
),
603 Parameter_Associations
=> New_List
(
604 Relocate_Node
(Strm
))));
606 end Build_Elementary_Input_Call
;
608 ---------------------------------
609 -- Build_Elementary_Write_Call --
610 ---------------------------------
612 function Build_Elementary_Write_Call
(N
: Node_Id
) return Node_Id
is
613 Loc
: constant Source_Ptr
:= Sloc
(N
);
614 P_Type
: constant Entity_Id
:= Entity
(Prefix
(N
));
615 U_Type
: constant Entity_Id
:= Underlying_Type
(P_Type
);
616 Rt_Type
: constant Entity_Id
:= Root_Type
(U_Type
);
617 FST
: constant Entity_Id
:= First_Subtype
(U_Type
);
618 P_Size
: constant Uint
:= Esize
(FST
);
619 Strm
: constant Node_Id
:= First
(Expressions
(N
));
620 Item
: constant Node_Id
:= Next
(Strm
);
625 -- Find the routine to be called
627 -- Check for First Boolean and Character. These are enumeration types,
628 -- but we treat them specially, since they may require special handling
629 -- in the transfer protocol. However, this special handling only applies
630 -- if they have standard representation, otherwise they are treated like
631 -- any other enumeration type.
633 if Rt_Type
= Standard_Boolean
634 and then Has_Stream_Standard_Rep
(U_Type
)
638 elsif Rt_Type
= Standard_Character
639 and then Has_Stream_Standard_Rep
(U_Type
)
643 elsif Rt_Type
= Standard_Wide_Character
644 and then Has_Stream_Standard_Rep
(U_Type
)
648 -- Floating point types
650 elsif Is_Floating_Point_Type
(U_Type
) then
652 if Rt_Type
= Standard_Short_Float
then
655 elsif Rt_Type
= Standard_Float
then
658 elsif Rt_Type
= Standard_Long_Float
then
661 else pragma Assert
(Rt_Type
= Standard_Long_Long_Float
);
665 -- Signed integer types. Also includes signed fixed-point types and
666 -- signed enumeration types share this circuitry.
668 -- Note on signed integer types. We do not consider types as signed for
669 -- this purpose if they have no negative numbers, or if they have biased
670 -- representation. The reason is that the value in either case basically
671 -- represents an unsigned value.
673 -- For example, consider:
675 -- type W is range 0 .. 2**32 - 1;
676 -- for W'Size use 32;
678 -- This is a signed type, but the representation is unsigned, and may
679 -- be outside the range of a 32-bit signed integer, so this must be
680 -- treated as 32-bit unsigned.
682 -- Similarly, if we have
684 -- type W is range -1 .. +254;
687 -- then the representation is also unsigned.
689 elsif not Is_Unsigned_Type
(FST
)
691 (Is_Fixed_Point_Type
(U_Type
)
693 Is_Enumeration_Type
(U_Type
)
695 (Is_Signed_Integer_Type
(U_Type
)
696 and then not Has_Biased_Representation
(FST
)))
698 if P_Size
<= Standard_Short_Short_Integer_Size
then
701 elsif P_Size
<= Standard_Short_Integer_Size
then
704 elsif P_Size
<= Standard_Integer_Size
then
707 elsif P_Size
<= Standard_Long_Integer_Size
then
714 -- Unsigned integer types, also includes unsigned fixed-point types
715 -- and unsigned enumeration types (note we know they are unsigned
716 -- because we already tested for signed above).
718 -- Also includes signed integer types that are unsigned in the sense
719 -- that they do not include negative numbers. See above for details.
721 elsif Is_Modular_Integer_Type
(U_Type
)
722 or else Is_Fixed_Point_Type
(U_Type
)
723 or else Is_Enumeration_Type
(U_Type
)
724 or else Is_Signed_Integer_Type
(U_Type
)
726 if P_Size
<= Standard_Short_Short_Integer_Size
then
729 elsif P_Size
<= Standard_Short_Integer_Size
then
732 elsif P_Size
<= Standard_Integer_Size
then
735 elsif P_Size
<= Standard_Long_Integer_Size
then
742 else pragma Assert
(Is_Access_Type
(U_Type
));
744 if P_Size
> System_Address_Size
then
751 -- Unchecked-convert parameter to the required type (i.e. the type of
752 -- the corresponding parameter, and call the appropriate routine.
754 Libent
:= RTE
(Lib_RE
);
757 Make_Procedure_Call_Statement
(Loc
,
758 Name
=> New_Occurrence_Of
(Libent
, Loc
),
759 Parameter_Associations
=> New_List
(
760 Relocate_Node
(Strm
),
761 Unchecked_Convert_To
(Etype
(Next_Formal
(First_Formal
(Libent
))),
762 Relocate_Node
(Item
))));
763 end Build_Elementary_Write_Call
;
765 -----------------------------------------
766 -- Build_Mutable_Record_Read_Procedure --
767 -----------------------------------------
769 procedure Build_Mutable_Record_Read_Procedure
773 Pnam
: out Entity_Id
)
781 Disc
:= First_Discriminant
(Typ
);
783 -- Generate Reads for the discriminants of the type.
785 while Present
(Disc
) loop
787 Make_Selected_Component
(Loc
,
788 Prefix
=> Make_Identifier
(Loc
, Name_V
),
789 Selector_Name
=> New_Occurrence_Of
(Disc
, Loc
));
791 Set_Assignment_OK
(Comp
);
794 Make_Attribute_Reference
(Loc
,
795 Prefix
=> New_Occurrence_Of
(Etype
(Disc
), Loc
),
796 Attribute_Name
=> Name_Read
,
797 Expressions
=> New_List
(
798 Make_Identifier
(Loc
, Name_S
),
801 Next_Discriminant
(Disc
);
804 -- A mutable type cannot be a tagged type, so we generate a new name
805 -- for the stream procedure.
808 Make_Defining_Identifier
(Loc
,
809 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Read
));
810 Build_Record_Read_Write_Procedure
(Loc
, Typ
, Decl
, Pnam
, Name_Read
);
812 -- Read the discriminants before the rest of the components, so
813 -- that discriminant values are properly set of variants, etc.
814 -- If this is an empty record with discriminants, there are no
815 -- previous statements. If this is an unchecked union, the stream
816 -- procedure is erroneous, because there are no discriminants to read.
818 if Is_Unchecked_Union
(Typ
) then
821 Make_Raise_Program_Error
(Loc
,
822 Reason
=> PE_Unchecked_Union_Restriction
));
825 if Is_Non_Empty_List
(
826 Statements
(Handled_Statement_Sequence
(Decl
)))
829 (First
(Statements
(Handled_Statement_Sequence
(Decl
))), Stms
);
831 Set_Statements
(Handled_Statement_Sequence
(Decl
), Stms
);
833 end Build_Mutable_Record_Read_Procedure
;
835 ------------------------------------------
836 -- Build_Mutable_Record_Write_Procedure --
837 ------------------------------------------
839 procedure Build_Mutable_Record_Write_Procedure
843 Pnam
: out Entity_Id
)
850 Disc
:= First_Discriminant
(Typ
);
852 -- Generate Writes for the discriminants of the type.
854 while Present
(Disc
) loop
857 Make_Attribute_Reference
(Loc
,
858 Prefix
=> New_Occurrence_Of
(Etype
(Disc
), Loc
),
859 Attribute_Name
=> Name_Write
,
860 Expressions
=> New_List
(
861 Make_Identifier
(Loc
, Name_S
),
862 Make_Selected_Component
(Loc
,
863 Prefix
=> Make_Identifier
(Loc
, Name_V
),
864 Selector_Name
=> New_Occurrence_Of
(Disc
, Loc
)))));
866 Next_Discriminant
(Disc
);
869 -- A mutable type cannot be a tagged type, so we generate a new name
870 -- for the stream procedure.
873 Make_Defining_Identifier
(Loc
,
874 Chars
=> Make_TSS_Name_Local
(Typ
, TSS_Stream_Write
));
875 Build_Record_Read_Write_Procedure
(Loc
, Typ
, Decl
, Pnam
, Name_Write
);
877 -- Write the discriminants before the rest of the components, so
878 -- that discriminant values are properly set of variants, etc.
879 -- If this is an unchecked union, the stream procedure is erroneous
880 -- because there are no discriminants to write.
882 if Is_Unchecked_Union
(Typ
) then
885 Make_Raise_Program_Error
(Loc
,
886 Reason
=> PE_Unchecked_Union_Restriction
));
889 if Is_Non_Empty_List
(
890 Statements
(Handled_Statement_Sequence
(Decl
)))
893 (First
(Statements
(Handled_Statement_Sequence
(Decl
))), Stms
);
895 Set_Statements
(Handled_Statement_Sequence
(Decl
), Stms
);
897 end Build_Mutable_Record_Write_Procedure
;
899 -----------------------------------------------
900 -- Build_Record_Or_Elementary_Input_Function --
901 -----------------------------------------------
903 -- The function we build looks like
905 -- function InputN (S : access RST) return Typ is
906 -- C1 : constant Disc_Type_1;
907 -- Discr_Type_1'Read (S, C1);
908 -- C2 : constant Disc_Type_2;
909 -- Discr_Type_2'Read (S, C2);
911 -- Cn : constant Disc_Type_n;
912 -- Discr_Type_n'Read (S, Cn);
913 -- V : Typ (C1, C2, .. Cn)
920 -- The discriminants are of course only present in the case of a record
921 -- with discriminants. In the case of a record with no discriminants, or
922 -- an elementary type, then no Cn constants are defined.
924 procedure Build_Record_Or_Elementary_Input_Function
928 Fnam
: out Entity_Id
)
944 if Has_Discriminants
(Typ
) then
945 Discr
:= First_Discriminant
(Typ
);
947 while Present
(Discr
) loop
948 Cn
:= New_External_Name
('C', J
);
951 Make_Object_Declaration
(Loc
,
952 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Cn
),
954 New_Occurrence_Of
(Etype
(Discr
), Loc
)));
957 Make_Attribute_Reference
(Loc
,
958 Prefix
=> New_Occurrence_Of
(Etype
(Discr
), Loc
),
959 Attribute_Name
=> Name_Read
,
960 Expressions
=> New_List
(
961 Make_Identifier
(Loc
, Name_S
),
962 Make_Identifier
(Loc
, Cn
))));
964 Append_To
(Constr
, Make_Identifier
(Loc
, Cn
));
966 Next_Discriminant
(Discr
);
971 Make_Subtype_Indication
(Loc
,
972 Subtype_Mark
=> New_Occurrence_Of
(Typ
, Loc
),
974 Make_Index_Or_Discriminant_Constraint
(Loc
,
975 Constraints
=> Constr
));
977 -- If no discriminants, then just use the type with no constraint
980 Odef
:= New_Occurrence_Of
(Typ
, Loc
);
984 Make_Object_Declaration
(Loc
,
985 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
986 Object_Definition
=> Odef
));
989 Make_Attribute_Reference
(Loc
,
990 Prefix
=> New_Occurrence_Of
(Typ
, Loc
),
991 Attribute_Name
=> Name_Read
,
992 Expressions
=> New_List
(
993 Make_Identifier
(Loc
, Name_S
),
994 Make_Identifier
(Loc
, Name_V
))),
996 Make_Return_Statement
(Loc
,
997 Expression
=> Make_Identifier
(Loc
, Name_V
)));
999 Fnam
:= Make_Stream_Subprogram_Name
(Loc
, Typ
, TSS_Stream_Input
);
1001 Build_Stream_Function
(Loc
, Typ
, Decl
, Fnam
, Decls
, Stms
);
1002 end Build_Record_Or_Elementary_Input_Function
;
1004 -------------------------------------------------
1005 -- Build_Record_Or_Elementary_Output_Procedure --
1006 -------------------------------------------------
1008 procedure Build_Record_Or_Elementary_Output_Procedure
1012 Pnam
: out Entity_Id
)
1020 -- Note that of course there will be no discriminants for the
1021 -- elementary type case, so Has_Discriminants will be False.
1023 if Has_Discriminants
(Typ
) then
1024 Disc
:= First_Discriminant
(Typ
);
1026 while Present
(Disc
) loop
1028 Make_Attribute_Reference
(Loc
,
1030 New_Occurrence_Of
(Stream_Base_Type
(Etype
(Disc
)), Loc
),
1031 Attribute_Name
=> Name_Write
,
1032 Expressions
=> New_List
(
1033 Make_Identifier
(Loc
, Name_S
),
1034 Make_Selected_Component
(Loc
,
1035 Prefix
=> Make_Identifier
(Loc
, Name_V
),
1036 Selector_Name
=> New_Occurrence_Of
(Disc
, Loc
)))));
1038 Next_Discriminant
(Disc
);
1043 Make_Attribute_Reference
(Loc
,
1044 Prefix
=> New_Occurrence_Of
(Typ
, Loc
),
1045 Attribute_Name
=> Name_Write
,
1046 Expressions
=> New_List
(
1047 Make_Identifier
(Loc
, Name_S
),
1048 Make_Identifier
(Loc
, Name_V
))));
1050 Pnam
:= Make_Stream_Subprogram_Name
(Loc
, Typ
, TSS_Stream_Output
);
1052 Build_Stream_Procedure
(Loc
, Typ
, Decl
, Pnam
, Stms
, False);
1053 end Build_Record_Or_Elementary_Output_Procedure
;
1055 ---------------------------------
1056 -- Build_Record_Read_Procedure --
1057 ---------------------------------
1059 procedure Build_Record_Read_Procedure
1063 Pnam
: out Entity_Id
)
1066 Pnam
:= Make_Stream_Subprogram_Name
(Loc
, Typ
, TSS_Stream_Read
);
1067 Build_Record_Read_Write_Procedure
(Loc
, Typ
, Decl
, Pnam
, Name_Read
);
1068 end Build_Record_Read_Procedure
;
1070 ---------------------------------------
1071 -- Build_Record_Read_Write_Procedure --
1072 ---------------------------------------
1074 -- The form of the record read/write procedure is as shown by the
1075 -- following example for a case with one discriminant case variant:
1077 -- procedure pnam (S : access RST, V : [out] Typ) is
1079 -- Component_Type'Read/Write (S, V.component);
1080 -- Component_Type'Read/Write (S, V.component);
1082 -- Component_Type'Read/Write (S, V.component);
1084 -- case V.discriminant is
1086 -- Component_Type'Read/Write (S, V.component);
1087 -- Component_Type'Read/Write (S, V.component);
1089 -- Component_Type'Read/Write (S, V.component);
1092 -- Component_Type'Read/Write (S, V.component);
1093 -- Component_Type'Read/Write (S, V.component);
1095 -- Component_Type'Read/Write (S, V.component);
1100 -- The out keyword for V is supplied in the Read case
1102 procedure Build_Record_Read_Write_Procedure
1113 function Make_Component_List_Attributes
(CL
: Node_Id
) return List_Id
;
1114 -- Returns a sequence of attributes to process the components that
1115 -- are referenced in the given component list.
1117 function Make_Field_Attribute
(C
: Entity_Id
) return Node_Id
;
1118 -- Given C, the entity for a discriminant or component, build
1119 -- an attribute for the corresponding field values.
1121 function Make_Field_Attributes
(Clist
: List_Id
) return List_Id
;
1122 -- Given Clist, a component items list, construct series of attributes
1123 -- for fieldwise processing of the corresponding components.
1125 ------------------------------------
1126 -- Make_Component_List_Attributes --
1127 ------------------------------------
1129 function Make_Component_List_Attributes
(CL
: Node_Id
) return List_Id
is
1130 CI
: constant List_Id
:= Component_Items
(CL
);
1131 VP
: constant Node_Id
:= Variant_Part
(CL
);
1140 Result
:= Make_Field_Attributes
(CI
);
1142 -- If a component is an unchecked union, there is no discriminant
1143 -- and we cannot generate a read/write procedure for it.
1145 if Present
(VP
) then
1146 if Is_Unchecked_Union
(Scope
(Entity
(Name
(VP
)))) then
1148 Make_Raise_Program_Error
(Sloc
(VP
),
1149 Reason
=> PE_Unchecked_Union_Restriction
));
1152 V
:= First_Non_Pragma
(Variants
(VP
));
1154 while Present
(V
) loop
1157 DC
:= First
(Discrete_Choices
(V
));
1158 while Present
(DC
) loop
1159 Append_To
(DCH
, New_Copy_Tree
(DC
));
1164 Make_Case_Statement_Alternative
(Loc
,
1165 Discrete_Choices
=> DCH
,
1167 Make_Component_List_Attributes
(Component_List
(V
))));
1168 Next_Non_Pragma
(V
);
1171 -- Note: in the following, we make sure that we use new occurrence
1172 -- of for the selector, since there are cases in which we make a
1173 -- reference to a hidden discriminant that is not visible.
1176 Make_Case_Statement
(Loc
,
1178 Make_Selected_Component
(Loc
,
1179 Prefix
=> Make_Identifier
(Loc
, Name_V
),
1181 New_Occurrence_Of
(Entity
(Name
(VP
)), Loc
)),
1182 Alternatives
=> Alts
));
1187 end Make_Component_List_Attributes
;
1189 --------------------------
1190 -- Make_Field_Attribute --
1191 --------------------------
1193 function Make_Field_Attribute
(C
: Entity_Id
) return Node_Id
is
1196 Make_Attribute_Reference
(Loc
,
1198 New_Occurrence_Of
(Stream_Base_Type
(Etype
(C
)), Loc
),
1199 Attribute_Name
=> Nam
,
1200 Expressions
=> New_List
(
1201 Make_Identifier
(Loc
, Name_S
),
1202 Make_Selected_Component
(Loc
,
1203 Prefix
=> Make_Identifier
(Loc
, Name_V
),
1204 Selector_Name
=> New_Occurrence_Of
(C
, Loc
))));
1205 end Make_Field_Attribute
;
1207 ---------------------------
1208 -- Make_Field_Attributes --
1209 ---------------------------
1211 function Make_Field_Attributes
(Clist
: List_Id
) return List_Id
is
1218 if Present
(Clist
) then
1219 Item
:= First
(Clist
);
1221 -- Loop through components, skipping all internal components,
1222 -- which are not part of the value (e.g. _Tag), except that we
1223 -- don't skip the _Parent, since we do want to process that
1226 while Present
(Item
) loop
1227 if Nkind
(Item
) = N_Component_Declaration
1229 (Chars
(Defining_Identifier
(Item
)) = Name_uParent
1231 not Is_Internal_Name
(Chars
(Defining_Identifier
(Item
))))
1235 Make_Field_Attribute
(Defining_Identifier
(Item
)));
1243 end Make_Field_Attributes
;
1245 -- Start of processing for Build_Record_Read_Write_Procedure
1248 -- For the protected type case, use corresponding record
1250 if Is_Protected_Type
(Typ
) then
1251 Typt
:= Corresponding_Record_Type
(Typ
);
1256 -- Note that we do nothing with the discriminants, since Read and
1257 -- Write do not read or write the discriminant values. All handling
1258 -- of discriminants occurs in the Input and Output subprograms.
1260 Rdef
:= Type_Definition
1261 (Declaration_Node
(Base_Type
(Underlying_Type
(Typt
))));
1264 -- In record extension case, the fields we want, including the _Parent
1265 -- field representing the parent type, are to be found in the extension.
1266 -- Note that we will naturally process the _Parent field using the type
1267 -- of the parent, and hence its stream attributes, which is appropriate.
1269 if Nkind
(Rdef
) = N_Derived_Type_Definition
then
1270 Rdef
:= Record_Extension_Part
(Rdef
);
1273 if Present
(Component_List
(Rdef
)) then
1274 Append_List_To
(Stms
,
1275 Make_Component_List_Attributes
(Component_List
(Rdef
)));
1278 Build_Stream_Procedure
1279 (Loc
, Typ
, Decl
, Pnam
, Stms
, Nam
= Name_Read
);
1280 end Build_Record_Read_Write_Procedure
;
1282 ----------------------------------
1283 -- Build_Record_Write_Procedure --
1284 ----------------------------------
1286 procedure Build_Record_Write_Procedure
1290 Pnam
: out Entity_Id
)
1293 Pnam
:= Make_Stream_Subprogram_Name
(Loc
, Typ
, TSS_Stream_Write
);
1294 Build_Record_Read_Write_Procedure
(Loc
, Typ
, Decl
, Pnam
, Name_Write
);
1295 end Build_Record_Write_Procedure
;
1297 -------------------------------
1298 -- Build_Stream_Attr_Profile --
1299 -------------------------------
1301 function Build_Stream_Attr_Profile
1304 Nam
: TSS_Name_Type
) return List_Id
1309 Profile
:= New_List
(
1310 Make_Parameter_Specification
(Loc
,
1311 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_S
),
1313 Make_Access_Definition
(Loc
,
1314 Subtype_Mark
=> New_Reference_To
(
1315 Class_Wide_Type
(RTE
(RE_Root_Stream_Type
)), Loc
))));
1317 if Nam
/= TSS_Stream_Input
then
1319 Make_Parameter_Specification
(Loc
,
1320 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
1321 Out_Present
=> (Nam
= TSS_Stream_Read
),
1322 Parameter_Type
=> New_Reference_To
(Typ
, Loc
)));
1326 end Build_Stream_Attr_Profile
;
1328 ---------------------------
1329 -- Build_Stream_Function --
1330 ---------------------------
1332 procedure Build_Stream_Function
1343 -- Construct function specification
1346 Make_Function_Specification
(Loc
,
1347 Defining_Unit_Name
=> Fnam
,
1349 Parameter_Specifications
=> New_List
(
1350 Make_Parameter_Specification
(Loc
,
1351 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_S
),
1353 Make_Access_Definition
(Loc
,
1354 Subtype_Mark
=> New_Reference_To
(
1355 Class_Wide_Type
(RTE
(RE_Root_Stream_Type
)), Loc
)))),
1357 Subtype_Mark
=> New_Occurrence_Of
(Typ
, Loc
));
1360 Make_Subprogram_Body
(Loc
,
1361 Specification
=> Spec
,
1362 Declarations
=> Decls
,
1363 Handled_Statement_Sequence
=>
1364 Make_Handled_Sequence_Of_Statements
(Loc
,
1365 Statements
=> Stms
));
1366 end Build_Stream_Function
;
1368 ----------------------------
1369 -- Build_Stream_Procedure --
1370 ----------------------------
1372 procedure Build_Stream_Procedure
1383 -- Construct procedure specification
1386 Make_Procedure_Specification
(Loc
,
1387 Defining_Unit_Name
=> Pnam
,
1389 Parameter_Specifications
=> New_List
(
1390 Make_Parameter_Specification
(Loc
,
1391 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_S
),
1393 Make_Access_Definition
(Loc
,
1394 Subtype_Mark
=> New_Reference_To
(
1395 Class_Wide_Type
(RTE
(RE_Root_Stream_Type
)), Loc
))),
1397 Make_Parameter_Specification
(Loc
,
1398 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
1399 Out_Present
=> Outp
,
1400 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
))));
1403 Make_Subprogram_Body
(Loc
,
1404 Specification
=> Spec
,
1405 Declarations
=> Empty_List
,
1406 Handled_Statement_Sequence
=>
1407 Make_Handled_Sequence_Of_Statements
(Loc
,
1408 Statements
=> Stms
));
1409 end Build_Stream_Procedure
;
1411 -----------------------------
1412 -- Has_Stream_Standard_Rep --
1413 -----------------------------
1415 function Has_Stream_Standard_Rep
(U_Type
: Entity_Id
) return Boolean is
1417 if Has_Non_Standard_Rep
(U_Type
) then
1421 Esize
(First_Subtype
(U_Type
)) = Esize
(Root_Type
(U_Type
));
1423 end Has_Stream_Standard_Rep
;
1425 ---------------------------------
1426 -- Make_Stream_Subprogram_Name --
1427 ---------------------------------
1429 function Make_Stream_Subprogram_Name
1432 Nam
: TSS_Name_Type
) return Entity_Id
1437 -- For tagged types, we are dealing with a TSS associated with the
1438 -- declaration, so we use the standard primitive function name. For
1439 -- other types, generate a local TSS name since we are generating
1440 -- the subprogram at the point of use.
1442 if Is_Tagged_Type
(Typ
) then
1443 Sname
:= Make_TSS_Name
(Typ
, Nam
);
1445 Sname
:= Make_TSS_Name_Local
(Typ
, Nam
);
1448 return Make_Defining_Identifier
(Loc
, Sname
);
1449 end Make_Stream_Subprogram_Name
;
1451 ----------------------
1452 -- Stream_Base_Type --
1453 ----------------------
1455 function Stream_Base_Type
(E
: Entity_Id
) return Entity_Id
is
1457 if Is_Array_Type
(E
)
1458 and then Is_First_Subtype
(E
)
1462 return Base_Type
(E
);
1464 end Stream_Base_Type
;