Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/exp_ch3.adb @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ------------------------------------------------------------------------------ | |
2 -- -- | |
3 -- GNAT COMPILER COMPONENTS -- | |
4 -- -- | |
5 -- E X P _ C H 3 -- | |
6 -- -- | |
7 -- B o d y -- | |
8 -- -- | |
9 -- Copyright (C) 1992-2017, Free Software Foundation, Inc. -- | |
10 -- -- | |
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. -- | |
20 -- -- | |
21 -- GNAT was originally developed by the GNAT team at New York University. -- | |
22 -- Extensive contributions were provided by Ada Core Technologies Inc. -- | |
23 -- -- | |
24 ------------------------------------------------------------------------------ | |
25 | |
26 with Aspects; use Aspects; | |
27 with Atree; use Atree; | |
28 with Checks; use Checks; | |
29 with Einfo; use Einfo; | |
30 with Errout; use Errout; | |
31 with Exp_Aggr; use Exp_Aggr; | |
32 with Exp_Atag; use Exp_Atag; | |
33 with Exp_Ch4; use Exp_Ch4; | |
34 with Exp_Ch6; use Exp_Ch6; | |
35 with Exp_Ch7; use Exp_Ch7; | |
36 with Exp_Ch9; use Exp_Ch9; | |
37 with Exp_Dbug; use Exp_Dbug; | |
38 with Exp_Disp; use Exp_Disp; | |
39 with Exp_Dist; use Exp_Dist; | |
40 with Exp_Smem; use Exp_Smem; | |
41 with Exp_Strm; use Exp_Strm; | |
42 with Exp_Tss; use Exp_Tss; | |
43 with Exp_Util; use Exp_Util; | |
44 with Freeze; use Freeze; | |
45 with Ghost; use Ghost; | |
46 with Lib; use Lib; | |
47 with Namet; use Namet; | |
48 with Nlists; use Nlists; | |
49 with Nmake; use Nmake; | |
50 with Opt; use Opt; | |
51 with Restrict; use Restrict; | |
52 with Rident; use Rident; | |
53 with Rtsfind; use Rtsfind; | |
54 with Sem; use Sem; | |
55 with Sem_Aux; use Sem_Aux; | |
56 with Sem_Attr; use Sem_Attr; | |
57 with Sem_Cat; use Sem_Cat; | |
58 with Sem_Ch3; use Sem_Ch3; | |
59 with Sem_Ch6; use Sem_Ch6; | |
60 with Sem_Ch8; use Sem_Ch8; | |
61 with Sem_Disp; use Sem_Disp; | |
62 with Sem_Eval; use Sem_Eval; | |
63 with Sem_Mech; use Sem_Mech; | |
64 with Sem_Res; use Sem_Res; | |
65 with Sem_SCIL; use Sem_SCIL; | |
66 with Sem_Type; use Sem_Type; | |
67 with Sem_Util; use Sem_Util; | |
68 with Sinfo; use Sinfo; | |
69 with Stand; use Stand; | |
70 with Snames; use Snames; | |
71 with Tbuild; use Tbuild; | |
72 with Ttypes; use Ttypes; | |
73 with Validsw; use Validsw; | |
74 | |
75 package body Exp_Ch3 is | |
76 | |
77 ----------------------- | |
78 -- Local Subprograms -- | |
79 ----------------------- | |
80 | |
81 procedure Adjust_Discriminants (Rtype : Entity_Id); | |
82 -- This is used when freezing a record type. It attempts to construct | |
83 -- more restrictive subtypes for discriminants so that the max size of | |
84 -- the record can be calculated more accurately. See the body of this | |
85 -- procedure for details. | |
86 | |
87 procedure Build_Array_Init_Proc (A_Type : Entity_Id; Nod : Node_Id); | |
88 -- Build initialization procedure for given array type. Nod is a node | |
89 -- used for attachment of any actions required in its construction. | |
90 -- It also supplies the source location used for the procedure. | |
91 | |
92 function Build_Discriminant_Formals | |
93 (Rec_Id : Entity_Id; | |
94 Use_Dl : Boolean) return List_Id; | |
95 -- This function uses the discriminants of a type to build a list of | |
96 -- formal parameters, used in Build_Init_Procedure among other places. | |
97 -- If the flag Use_Dl is set, the list is built using the already | |
98 -- defined discriminals of the type, as is the case for concurrent | |
99 -- types with discriminants. Otherwise new identifiers are created, | |
100 -- with the source names of the discriminants. | |
101 | |
102 function Build_Equivalent_Array_Aggregate (T : Entity_Id) return Node_Id; | |
103 -- This function builds a static aggregate that can serve as the initial | |
104 -- value for an array type whose bounds are static, and whose component | |
105 -- type is a composite type that has a static equivalent aggregate. | |
106 -- The equivalent array aggregate is used both for object initialization | |
107 -- and for component initialization, when used in the following function. | |
108 | |
109 function Build_Equivalent_Record_Aggregate (T : Entity_Id) return Node_Id; | |
110 -- This function builds a static aggregate that can serve as the initial | |
111 -- value for a record type whose components are scalar and initialized | |
112 -- with compile-time values, or arrays with similar initialization or | |
113 -- defaults. When possible, initialization of an object of the type can | |
114 -- be achieved by using a copy of the aggregate as an initial value, thus | |
115 -- removing the implicit call that would otherwise constitute elaboration | |
116 -- code. | |
117 | |
118 procedure Build_Record_Init_Proc (N : Node_Id; Rec_Ent : Entity_Id); | |
119 -- Build record initialization procedure. N is the type declaration | |
120 -- node, and Rec_Ent is the corresponding entity for the record type. | |
121 | |
122 procedure Build_Slice_Assignment (Typ : Entity_Id); | |
123 -- Build assignment procedure for one-dimensional arrays of controlled | |
124 -- types. Other array and slice assignments are expanded in-line, but | |
125 -- the code expansion for controlled components (when control actions | |
126 -- are active) can lead to very large blocks that GCC3 handles poorly. | |
127 | |
128 procedure Build_Untagged_Equality (Typ : Entity_Id); | |
129 -- AI05-0123: Equality on untagged records composes. This procedure | |
130 -- builds the equality routine for an untagged record that has components | |
131 -- of a record type that has user-defined primitive equality operations. | |
132 -- The resulting operation is a TSS subprogram. | |
133 | |
134 procedure Build_Variant_Record_Equality (Typ : Entity_Id); | |
135 -- Create An Equality function for the untagged variant record Typ and | |
136 -- attach it to the TSS list | |
137 | |
138 procedure Check_Stream_Attributes (Typ : Entity_Id); | |
139 -- Check that if a limited extension has a parent with user-defined stream | |
140 -- attributes, and does not itself have user-defined stream-attributes, | |
141 -- then any limited component of the extension also has the corresponding | |
142 -- user-defined stream attributes. | |
143 | |
144 procedure Clean_Task_Names | |
145 (Typ : Entity_Id; | |
146 Proc_Id : Entity_Id); | |
147 -- If an initialization procedure includes calls to generate names | |
148 -- for task subcomponents, indicate that secondary stack cleanup is | |
149 -- needed after an initialization. Typ is the component type, and Proc_Id | |
150 -- the initialization procedure for the enclosing composite type. | |
151 | |
152 procedure Expand_Freeze_Array_Type (N : Node_Id); | |
153 -- Freeze an array type. Deals with building the initialization procedure, | |
154 -- creating the packed array type for a packed array and also with the | |
155 -- creation of the controlling procedures for the controlled case. The | |
156 -- argument N is the N_Freeze_Entity node for the type. | |
157 | |
158 procedure Expand_Freeze_Class_Wide_Type (N : Node_Id); | |
159 -- Freeze a class-wide type. Build routine Finalize_Address for the purpose | |
160 -- of finalizing controlled derivations from the class-wide's root type. | |
161 | |
162 procedure Expand_Freeze_Enumeration_Type (N : Node_Id); | |
163 -- Freeze enumeration type with non-standard representation. Builds the | |
164 -- array and function needed to convert between enumeration pos and | |
165 -- enumeration representation values. N is the N_Freeze_Entity node | |
166 -- for the type. | |
167 | |
168 procedure Expand_Freeze_Record_Type (N : Node_Id); | |
169 -- Freeze record type. Builds all necessary discriminant checking | |
170 -- and other ancillary functions, and builds dispatch tables where | |
171 -- needed. The argument N is the N_Freeze_Entity node. This processing | |
172 -- applies only to E_Record_Type entities, not to class wide types, | |
173 -- record subtypes, or private types. | |
174 | |
175 procedure Expand_Tagged_Root (T : Entity_Id); | |
176 -- Add a field _Tag at the beginning of the record. This field carries | |
177 -- the value of the access to the Dispatch table. This procedure is only | |
178 -- called on root type, the _Tag field being inherited by the descendants. | |
179 | |
180 procedure Freeze_Stream_Operations (N : Node_Id; Typ : Entity_Id); | |
181 -- Treat user-defined stream operations as renaming_as_body if the | |
182 -- subprogram they rename is not frozen when the type is frozen. | |
183 | |
184 procedure Initialization_Warning (E : Entity_Id); | |
185 -- If static elaboration of the package is requested, indicate | |
186 -- when a type does meet the conditions for static initialization. If | |
187 -- E is a type, it has components that have no static initialization. | |
188 -- if E is an entity, its initial expression is not compile-time known. | |
189 | |
190 function Init_Formals (Typ : Entity_Id) return List_Id; | |
191 -- This function builds the list of formals for an initialization routine. | |
192 -- The first formal is always _Init with the given type. For task value | |
193 -- record types and types containing tasks, three additional formals are | |
194 -- added: | |
195 -- | |
196 -- _Master : Master_Id | |
197 -- _Chain : in out Activation_Chain | |
198 -- _Task_Name : String | |
199 -- | |
200 -- The caller must append additional entries for discriminants if required. | |
201 | |
202 function Inline_Init_Proc (Typ : Entity_Id) return Boolean; | |
203 -- Returns true if the initialization procedure of Typ should be inlined | |
204 | |
205 function In_Runtime (E : Entity_Id) return Boolean; | |
206 -- Check if E is defined in the RTL (in a child of Ada or System). Used | |
207 -- to avoid to bring in the overhead of _Input, _Output for tagged types. | |
208 | |
209 function Is_User_Defined_Equality (Prim : Node_Id) return Boolean; | |
210 -- Returns true if Prim is a user defined equality function | |
211 | |
212 function Make_Eq_Body | |
213 (Typ : Entity_Id; | |
214 Eq_Name : Name_Id) return Node_Id; | |
215 -- Build the body of a primitive equality operation for a tagged record | |
216 -- type, or in Ada 2012 for any record type that has components with a | |
217 -- user-defined equality. Factored out of Predefined_Primitive_Bodies. | |
218 | |
219 function Make_Eq_Case | |
220 (E : Entity_Id; | |
221 CL : Node_Id; | |
222 Discrs : Elist_Id := New_Elmt_List) return List_Id; | |
223 -- Building block for variant record equality. Defined to share the code | |
224 -- between the tagged and untagged case. Given a Component_List node CL, | |
225 -- it generates an 'if' followed by a 'case' statement that compares all | |
226 -- components of local temporaries named X and Y (that are declared as | |
227 -- formals at some upper level). E provides the Sloc to be used for the | |
228 -- generated code. | |
229 -- | |
230 -- IF E is an unchecked_union, Discrs is the list of formals created for | |
231 -- the inferred discriminants of one operand. These formals are used in | |
232 -- the generated case statements for each variant of the unchecked union. | |
233 | |
234 function Make_Eq_If | |
235 (E : Entity_Id; | |
236 L : List_Id) return Node_Id; | |
237 -- Building block for variant record equality. Defined to share the code | |
238 -- between the tagged and untagged case. Given the list of components | |
239 -- (or discriminants) L, it generates a return statement that compares all | |
240 -- components of local temporaries named X and Y (that are declared as | |
241 -- formals at some upper level). E provides the Sloc to be used for the | |
242 -- generated code. | |
243 | |
244 function Make_Neq_Body (Tag_Typ : Entity_Id) return Node_Id; | |
245 -- Search for a renaming of the inequality dispatching primitive of | |
246 -- this tagged type. If found then build and return the corresponding | |
247 -- rename-as-body inequality subprogram; otherwise return Empty. | |
248 | |
249 procedure Make_Predefined_Primitive_Specs | |
250 (Tag_Typ : Entity_Id; | |
251 Predef_List : out List_Id; | |
252 Renamed_Eq : out Entity_Id); | |
253 -- Create a list with the specs of the predefined primitive operations. | |
254 -- For tagged types that are interfaces all these primitives are defined | |
255 -- abstract. | |
256 -- | |
257 -- The following entries are present for all tagged types, and provide | |
258 -- the results of the corresponding attribute applied to the object. | |
259 -- Dispatching is required in general, since the result of the attribute | |
260 -- will vary with the actual object subtype. | |
261 -- | |
262 -- _size provides result of 'Size attribute | |
263 -- typSR provides result of 'Read attribute | |
264 -- typSW provides result of 'Write attribute | |
265 -- typSI provides result of 'Input attribute | |
266 -- typSO provides result of 'Output attribute | |
267 -- | |
268 -- The following entries are additionally present for non-limited tagged | |
269 -- types, and implement additional dispatching operations for predefined | |
270 -- operations: | |
271 -- | |
272 -- _equality implements "=" operator | |
273 -- _assign implements assignment operation | |
274 -- typDF implements deep finalization | |
275 -- typDA implements deep adjust | |
276 -- | |
277 -- The latter two are empty procedures unless the type contains some | |
278 -- controlled components that require finalization actions (the deep | |
279 -- in the name refers to the fact that the action applies to components). | |
280 -- | |
281 -- The list is returned in Predef_List. The Parameter Renamed_Eq either | |
282 -- returns the value Empty, or else the defining unit name for the | |
283 -- predefined equality function in the case where the type has a primitive | |
284 -- operation that is a renaming of predefined equality (but only if there | |
285 -- is also an overriding user-defined equality function). The returned | |
286 -- Renamed_Eq will be passed to the corresponding parameter of | |
287 -- Predefined_Primitive_Bodies. | |
288 | |
289 function Has_New_Non_Standard_Rep (T : Entity_Id) return Boolean; | |
290 -- Returns True if there are representation clauses for type T that are not | |
291 -- inherited. If the result is false, the init_proc and the discriminant | |
292 -- checking functions of the parent can be reused by a derived type. | |
293 | |
294 procedure Make_Controlling_Function_Wrappers | |
295 (Tag_Typ : Entity_Id; | |
296 Decl_List : out List_Id; | |
297 Body_List : out List_Id); | |
298 -- Ada 2005 (AI-391): Makes specs and bodies for the wrapper functions | |
299 -- associated with inherited functions with controlling results which | |
300 -- are not overridden. The body of each wrapper function consists solely | |
301 -- of a return statement whose expression is an extension aggregate | |
302 -- invoking the inherited subprogram's parent subprogram and extended | |
303 -- with a null association list. | |
304 | |
305 function Make_Null_Procedure_Specs (Tag_Typ : Entity_Id) return List_Id; | |
306 -- Ada 2005 (AI-251): Makes specs for null procedures associated with any | |
307 -- null procedures inherited from an interface type that have not been | |
308 -- overridden. Only one null procedure will be created for a given set of | |
309 -- inherited null procedures with homographic profiles. | |
310 | |
311 function Predef_Spec_Or_Body | |
312 (Loc : Source_Ptr; | |
313 Tag_Typ : Entity_Id; | |
314 Name : Name_Id; | |
315 Profile : List_Id; | |
316 Ret_Type : Entity_Id := Empty; | |
317 For_Body : Boolean := False) return Node_Id; | |
318 -- This function generates the appropriate expansion for a predefined | |
319 -- primitive operation specified by its name, parameter profile and | |
320 -- return type (Empty means this is a procedure). If For_Body is false, | |
321 -- then the returned node is a subprogram declaration. If For_Body is | |
322 -- true, then the returned node is a empty subprogram body containing | |
323 -- no declarations and no statements. | |
324 | |
325 function Predef_Stream_Attr_Spec | |
326 (Loc : Source_Ptr; | |
327 Tag_Typ : Entity_Id; | |
328 Name : TSS_Name_Type; | |
329 For_Body : Boolean := False) return Node_Id; | |
330 -- Specialized version of Predef_Spec_Or_Body that apply to read, write, | |
331 -- input and output attribute whose specs are constructed in Exp_Strm. | |
332 | |
333 function Predef_Deep_Spec | |
334 (Loc : Source_Ptr; | |
335 Tag_Typ : Entity_Id; | |
336 Name : TSS_Name_Type; | |
337 For_Body : Boolean := False) return Node_Id; | |
338 -- Specialized version of Predef_Spec_Or_Body that apply to _deep_adjust | |
339 -- and _deep_finalize | |
340 | |
341 function Predefined_Primitive_Bodies | |
342 (Tag_Typ : Entity_Id; | |
343 Renamed_Eq : Entity_Id) return List_Id; | |
344 -- Create the bodies of the predefined primitives that are described in | |
345 -- Predefined_Primitive_Specs. When not empty, Renamed_Eq must denote | |
346 -- the defining unit name of the type's predefined equality as returned | |
347 -- by Make_Predefined_Primitive_Specs. | |
348 | |
349 function Predefined_Primitive_Freeze (Tag_Typ : Entity_Id) return List_Id; | |
350 -- Freeze entities of all predefined primitive operations. This is needed | |
351 -- because the bodies of these operations do not normally do any freezing. | |
352 | |
353 function Stream_Operation_OK | |
354 (Typ : Entity_Id; | |
355 Operation : TSS_Name_Type) return Boolean; | |
356 -- Check whether the named stream operation must be emitted for a given | |
357 -- type. The rules for inheritance of stream attributes by type extensions | |
358 -- are enforced by this function. Furthermore, various restrictions prevent | |
359 -- the generation of these operations, as a useful optimization or for | |
360 -- certification purposes and to save unnecessary generated code. | |
361 | |
362 -------------------------- | |
363 -- Adjust_Discriminants -- | |
364 -------------------------- | |
365 | |
366 -- This procedure attempts to define subtypes for discriminants that are | |
367 -- more restrictive than those declared. Such a replacement is possible if | |
368 -- we can demonstrate that values outside the restricted range would cause | |
369 -- constraint errors in any case. The advantage of restricting the | |
370 -- discriminant types in this way is that the maximum size of the variant | |
371 -- record can be calculated more conservatively. | |
372 | |
373 -- An example of a situation in which we can perform this type of | |
374 -- restriction is the following: | |
375 | |
376 -- subtype B is range 1 .. 10; | |
377 -- type Q is array (B range <>) of Integer; | |
378 | |
379 -- type V (N : Natural) is record | |
380 -- C : Q (1 .. N); | |
381 -- end record; | |
382 | |
383 -- In this situation, we can restrict the upper bound of N to 10, since | |
384 -- any larger value would cause a constraint error in any case. | |
385 | |
386 -- There are many situations in which such restriction is possible, but | |
387 -- for now, we just look for cases like the above, where the component | |
388 -- in question is a one dimensional array whose upper bound is one of | |
389 -- the record discriminants. Also the component must not be part of | |
390 -- any variant part, since then the component does not always exist. | |
391 | |
392 procedure Adjust_Discriminants (Rtype : Entity_Id) is | |
393 Loc : constant Source_Ptr := Sloc (Rtype); | |
394 Comp : Entity_Id; | |
395 Ctyp : Entity_Id; | |
396 Ityp : Entity_Id; | |
397 Lo : Node_Id; | |
398 Hi : Node_Id; | |
399 P : Node_Id; | |
400 Loval : Uint; | |
401 Discr : Entity_Id; | |
402 Dtyp : Entity_Id; | |
403 Dhi : Node_Id; | |
404 Dhiv : Uint; | |
405 Ahi : Node_Id; | |
406 Ahiv : Uint; | |
407 Tnn : Entity_Id; | |
408 | |
409 begin | |
410 Comp := First_Component (Rtype); | |
411 while Present (Comp) loop | |
412 | |
413 -- If our parent is a variant, quit, we do not look at components | |
414 -- that are in variant parts, because they may not always exist. | |
415 | |
416 P := Parent (Comp); -- component declaration | |
417 P := Parent (P); -- component list | |
418 | |
419 exit when Nkind (Parent (P)) = N_Variant; | |
420 | |
421 -- We are looking for a one dimensional array type | |
422 | |
423 Ctyp := Etype (Comp); | |
424 | |
425 if not Is_Array_Type (Ctyp) or else Number_Dimensions (Ctyp) > 1 then | |
426 goto Continue; | |
427 end if; | |
428 | |
429 -- The lower bound must be constant, and the upper bound is a | |
430 -- discriminant (which is a discriminant of the current record). | |
431 | |
432 Ityp := Etype (First_Index (Ctyp)); | |
433 Lo := Type_Low_Bound (Ityp); | |
434 Hi := Type_High_Bound (Ityp); | |
435 | |
436 if not Compile_Time_Known_Value (Lo) | |
437 or else Nkind (Hi) /= N_Identifier | |
438 or else No (Entity (Hi)) | |
439 or else Ekind (Entity (Hi)) /= E_Discriminant | |
440 then | |
441 goto Continue; | |
442 end if; | |
443 | |
444 -- We have an array with appropriate bounds | |
445 | |
446 Loval := Expr_Value (Lo); | |
447 Discr := Entity (Hi); | |
448 Dtyp := Etype (Discr); | |
449 | |
450 -- See if the discriminant has a known upper bound | |
451 | |
452 Dhi := Type_High_Bound (Dtyp); | |
453 | |
454 if not Compile_Time_Known_Value (Dhi) then | |
455 goto Continue; | |
456 end if; | |
457 | |
458 Dhiv := Expr_Value (Dhi); | |
459 | |
460 -- See if base type of component array has known upper bound | |
461 | |
462 Ahi := Type_High_Bound (Etype (First_Index (Base_Type (Ctyp)))); | |
463 | |
464 if not Compile_Time_Known_Value (Ahi) then | |
465 goto Continue; | |
466 end if; | |
467 | |
468 Ahiv := Expr_Value (Ahi); | |
469 | |
470 -- The condition for doing the restriction is that the high bound | |
471 -- of the discriminant is greater than the low bound of the array, | |
472 -- and is also greater than the high bound of the base type index. | |
473 | |
474 if Dhiv > Loval and then Dhiv > Ahiv then | |
475 | |
476 -- We can reset the upper bound of the discriminant type to | |
477 -- whichever is larger, the low bound of the component, or | |
478 -- the high bound of the base type array index. | |
479 | |
480 -- We build a subtype that is declared as | |
481 | |
482 -- subtype Tnn is discr_type range discr_type'First .. max; | |
483 | |
484 -- And insert this declaration into the tree. The type of the | |
485 -- discriminant is then reset to this more restricted subtype. | |
486 | |
487 Tnn := Make_Temporary (Loc, 'T'); | |
488 | |
489 Insert_Action (Declaration_Node (Rtype), | |
490 Make_Subtype_Declaration (Loc, | |
491 Defining_Identifier => Tnn, | |
492 Subtype_Indication => | |
493 Make_Subtype_Indication (Loc, | |
494 Subtype_Mark => New_Occurrence_Of (Dtyp, Loc), | |
495 Constraint => | |
496 Make_Range_Constraint (Loc, | |
497 Range_Expression => | |
498 Make_Range (Loc, | |
499 Low_Bound => | |
500 Make_Attribute_Reference (Loc, | |
501 Attribute_Name => Name_First, | |
502 Prefix => New_Occurrence_Of (Dtyp, Loc)), | |
503 High_Bound => | |
504 Make_Integer_Literal (Loc, | |
505 Intval => UI_Max (Loval, Ahiv))))))); | |
506 | |
507 Set_Etype (Discr, Tnn); | |
508 end if; | |
509 | |
510 <<Continue>> | |
511 Next_Component (Comp); | |
512 end loop; | |
513 end Adjust_Discriminants; | |
514 | |
515 --------------------------- | |
516 -- Build_Array_Init_Proc -- | |
517 --------------------------- | |
518 | |
519 procedure Build_Array_Init_Proc (A_Type : Entity_Id; Nod : Node_Id) is | |
520 Comp_Type : constant Entity_Id := Component_Type (A_Type); | |
521 Comp_Simple_Init : constant Boolean := | |
522 Needs_Simple_Initialization | |
523 (T => Comp_Type, | |
524 Consider_IS => | |
525 not (Validity_Check_Copies and Is_Bit_Packed_Array (A_Type))); | |
526 -- True if the component needs simple initialization, based on its type, | |
527 -- plus the fact that we do not do simple initialization for components | |
528 -- of bit-packed arrays when validity checks are enabled, because the | |
529 -- initialization with deliberately out-of-range values would raise | |
530 -- Constraint_Error. | |
531 | |
532 Body_Stmts : List_Id; | |
533 Has_Default_Init : Boolean; | |
534 Index_List : List_Id; | |
535 Loc : Source_Ptr; | |
536 Proc_Id : Entity_Id; | |
537 | |
538 function Init_Component return List_Id; | |
539 -- Create one statement to initialize one array component, designated | |
540 -- by a full set of indexes. | |
541 | |
542 function Init_One_Dimension (N : Int) return List_Id; | |
543 -- Create loop to initialize one dimension of the array. The single | |
544 -- statement in the loop body initializes the inner dimensions if any, | |
545 -- or else the single component. Note that this procedure is called | |
546 -- recursively, with N being the dimension to be initialized. A call | |
547 -- with N greater than the number of dimensions simply generates the | |
548 -- component initialization, terminating the recursion. | |
549 | |
550 -------------------- | |
551 -- Init_Component -- | |
552 -------------------- | |
553 | |
554 function Init_Component return List_Id is | |
555 Comp : Node_Id; | |
556 | |
557 begin | |
558 Comp := | |
559 Make_Indexed_Component (Loc, | |
560 Prefix => Make_Identifier (Loc, Name_uInit), | |
561 Expressions => Index_List); | |
562 | |
563 if Has_Default_Aspect (A_Type) then | |
564 Set_Assignment_OK (Comp); | |
565 return New_List ( | |
566 Make_Assignment_Statement (Loc, | |
567 Name => Comp, | |
568 Expression => | |
569 Convert_To (Comp_Type, | |
570 Default_Aspect_Component_Value (First_Subtype (A_Type))))); | |
571 | |
572 elsif Comp_Simple_Init then | |
573 Set_Assignment_OK (Comp); | |
574 return New_List ( | |
575 Make_Assignment_Statement (Loc, | |
576 Name => Comp, | |
577 Expression => | |
578 Get_Simple_Init_Val | |
579 (Comp_Type, Nod, Component_Size (A_Type)))); | |
580 | |
581 else | |
582 Clean_Task_Names (Comp_Type, Proc_Id); | |
583 return | |
584 Build_Initialization_Call | |
585 (Loc, Comp, Comp_Type, | |
586 In_Init_Proc => True, | |
587 Enclos_Type => A_Type); | |
588 end if; | |
589 end Init_Component; | |
590 | |
591 ------------------------ | |
592 -- Init_One_Dimension -- | |
593 ------------------------ | |
594 | |
595 function Init_One_Dimension (N : Int) return List_Id is | |
596 Index : Entity_Id; | |
597 | |
598 begin | |
599 -- If the component does not need initializing, then there is nothing | |
600 -- to do here, so we return a null body. This occurs when generating | |
601 -- the dummy Init_Proc needed for Initialize_Scalars processing. | |
602 | |
603 if not Has_Non_Null_Base_Init_Proc (Comp_Type) | |
604 and then not Comp_Simple_Init | |
605 and then not Has_Task (Comp_Type) | |
606 and then not Has_Default_Aspect (A_Type) | |
607 then | |
608 return New_List (Make_Null_Statement (Loc)); | |
609 | |
610 -- If all dimensions dealt with, we simply initialize the component | |
611 | |
612 elsif N > Number_Dimensions (A_Type) then | |
613 return Init_Component; | |
614 | |
615 -- Here we generate the required loop | |
616 | |
617 else | |
618 Index := | |
619 Make_Defining_Identifier (Loc, New_External_Name ('J', N)); | |
620 | |
621 Append (New_Occurrence_Of (Index, Loc), Index_List); | |
622 | |
623 return New_List ( | |
624 Make_Implicit_Loop_Statement (Nod, | |
625 Identifier => Empty, | |
626 Iteration_Scheme => | |
627 Make_Iteration_Scheme (Loc, | |
628 Loop_Parameter_Specification => | |
629 Make_Loop_Parameter_Specification (Loc, | |
630 Defining_Identifier => Index, | |
631 Discrete_Subtype_Definition => | |
632 Make_Attribute_Reference (Loc, | |
633 Prefix => | |
634 Make_Identifier (Loc, Name_uInit), | |
635 Attribute_Name => Name_Range, | |
636 Expressions => New_List ( | |
637 Make_Integer_Literal (Loc, N))))), | |
638 Statements => Init_One_Dimension (N + 1))); | |
639 end if; | |
640 end Init_One_Dimension; | |
641 | |
642 -- Start of processing for Build_Array_Init_Proc | |
643 | |
644 begin | |
645 -- The init proc is created when analyzing the freeze node for the type, | |
646 -- but it properly belongs with the array type declaration. However, if | |
647 -- the freeze node is for a subtype of a type declared in another unit | |
648 -- it seems preferable to use the freeze node as the source location of | |
649 -- the init proc. In any case this is preferable for gcov usage, and | |
650 -- the Sloc is not otherwise used by the compiler. | |
651 | |
652 if In_Open_Scopes (Scope (A_Type)) then | |
653 Loc := Sloc (A_Type); | |
654 else | |
655 Loc := Sloc (Nod); | |
656 end if; | |
657 | |
658 -- Nothing to generate in the following cases: | |
659 | |
660 -- 1. Initialization is suppressed for the type | |
661 -- 2. An initialization already exists for the base type | |
662 | |
663 if Initialization_Suppressed (A_Type) | |
664 or else Present (Base_Init_Proc (A_Type)) | |
665 then | |
666 return; | |
667 end if; | |
668 | |
669 Index_List := New_List; | |
670 | |
671 -- We need an initialization procedure if any of the following is true: | |
672 | |
673 -- 1. The component type has an initialization procedure | |
674 -- 2. The component type needs simple initialization | |
675 -- 3. Tasks are present | |
676 -- 4. The type is marked as a public entity | |
677 -- 5. The array type has a Default_Component_Value aspect | |
678 | |
679 -- The reason for the public entity test is to deal properly with the | |
680 -- Initialize_Scalars pragma. This pragma can be set in the client and | |
681 -- not in the declaring package, this means the client will make a call | |
682 -- to the initialization procedure (because one of conditions 1-3 must | |
683 -- apply in this case), and we must generate a procedure (even if it is | |
684 -- null) to satisfy the call in this case. | |
685 | |
686 -- Exception: do not build an array init_proc for a type whose root | |
687 -- type is Standard.String or Standard.Wide_[Wide_]String, since there | |
688 -- is no place to put the code, and in any case we handle initialization | |
689 -- of such types (in the Initialize_Scalars case, that's the only time | |
690 -- the issue arises) in a special manner anyway which does not need an | |
691 -- init_proc. | |
692 | |
693 Has_Default_Init := Has_Non_Null_Base_Init_Proc (Comp_Type) | |
694 or else Comp_Simple_Init | |
695 or else Has_Task (Comp_Type) | |
696 or else Has_Default_Aspect (A_Type); | |
697 | |
698 if Has_Default_Init | |
699 or else (not Restriction_Active (No_Initialize_Scalars) | |
700 and then Is_Public (A_Type) | |
701 and then not Is_Standard_String_Type (A_Type)) | |
702 then | |
703 Proc_Id := | |
704 Make_Defining_Identifier (Loc, | |
705 Chars => Make_Init_Proc_Name (A_Type)); | |
706 | |
707 -- If No_Default_Initialization restriction is active, then we don't | |
708 -- want to build an init_proc, but we need to mark that an init_proc | |
709 -- would be needed if this restriction was not active (so that we can | |
710 -- detect attempts to call it), so set a dummy init_proc in place. | |
711 -- This is only done though when actual default initialization is | |
712 -- needed (and not done when only Is_Public is True), since otherwise | |
713 -- objects such as arrays of scalars could be wrongly flagged as | |
714 -- violating the restriction. | |
715 | |
716 if Restriction_Active (No_Default_Initialization) then | |
717 if Has_Default_Init then | |
718 Set_Init_Proc (A_Type, Proc_Id); | |
719 end if; | |
720 | |
721 return; | |
722 end if; | |
723 | |
724 Body_Stmts := Init_One_Dimension (1); | |
725 | |
726 Discard_Node ( | |
727 Make_Subprogram_Body (Loc, | |
728 Specification => | |
729 Make_Procedure_Specification (Loc, | |
730 Defining_Unit_Name => Proc_Id, | |
731 Parameter_Specifications => Init_Formals (A_Type)), | |
732 Declarations => New_List, | |
733 Handled_Statement_Sequence => | |
734 Make_Handled_Sequence_Of_Statements (Loc, | |
735 Statements => Body_Stmts))); | |
736 | |
737 Set_Ekind (Proc_Id, E_Procedure); | |
738 Set_Is_Public (Proc_Id, Is_Public (A_Type)); | |
739 Set_Is_Internal (Proc_Id); | |
740 Set_Has_Completion (Proc_Id); | |
741 | |
742 if not Debug_Generated_Code then | |
743 Set_Debug_Info_Off (Proc_Id); | |
744 end if; | |
745 | |
746 -- Set Inlined on Init_Proc if it is set on the Init_Proc of the | |
747 -- component type itself (see also Build_Record_Init_Proc). | |
748 | |
749 Set_Is_Inlined (Proc_Id, Inline_Init_Proc (Comp_Type)); | |
750 | |
751 -- Associate Init_Proc with type, and determine if the procedure | |
752 -- is null (happens because of the Initialize_Scalars pragma case, | |
753 -- where we have to generate a null procedure in case it is called | |
754 -- by a client with Initialize_Scalars set). Such procedures have | |
755 -- to be generated, but do not have to be called, so we mark them | |
756 -- as null to suppress the call. | |
757 | |
758 Set_Init_Proc (A_Type, Proc_Id); | |
759 | |
760 if List_Length (Body_Stmts) = 1 | |
761 | |
762 -- We must skip SCIL nodes because they may have been added to this | |
763 -- list by Insert_Actions. | |
764 | |
765 and then Nkind (First_Non_SCIL_Node (Body_Stmts)) = N_Null_Statement | |
766 then | |
767 Set_Is_Null_Init_Proc (Proc_Id); | |
768 | |
769 else | |
770 -- Try to build a static aggregate to statically initialize | |
771 -- objects of the type. This can only be done for constrained | |
772 -- one-dimensional arrays with static bounds. | |
773 | |
774 Set_Static_Initialization | |
775 (Proc_Id, | |
776 Build_Equivalent_Array_Aggregate (First_Subtype (A_Type))); | |
777 end if; | |
778 end if; | |
779 end Build_Array_Init_Proc; | |
780 | |
781 -------------------------------- | |
782 -- Build_Discr_Checking_Funcs -- | |
783 -------------------------------- | |
784 | |
785 procedure Build_Discr_Checking_Funcs (N : Node_Id) is | |
786 Rec_Id : Entity_Id; | |
787 Loc : Source_Ptr; | |
788 Enclosing_Func_Id : Entity_Id; | |
789 Sequence : Nat := 1; | |
790 Type_Def : Node_Id; | |
791 V : Node_Id; | |
792 | |
793 function Build_Case_Statement | |
794 (Case_Id : Entity_Id; | |
795 Variant : Node_Id) return Node_Id; | |
796 -- Build a case statement containing only two alternatives. The first | |
797 -- alternative corresponds exactly to the discrete choices given on the | |
798 -- variant with contains the components that we are generating the | |
799 -- checks for. If the discriminant is one of these return False. The | |
800 -- second alternative is an OTHERS choice that will return True | |
801 -- indicating the discriminant did not match. | |
802 | |
803 function Build_Dcheck_Function | |
804 (Case_Id : Entity_Id; | |
805 Variant : Node_Id) return Entity_Id; | |
806 -- Build the discriminant checking function for a given variant | |
807 | |
808 procedure Build_Dcheck_Functions (Variant_Part_Node : Node_Id); | |
809 -- Builds the discriminant checking function for each variant of the | |
810 -- given variant part of the record type. | |
811 | |
812 -------------------------- | |
813 -- Build_Case_Statement -- | |
814 -------------------------- | |
815 | |
816 function Build_Case_Statement | |
817 (Case_Id : Entity_Id; | |
818 Variant : Node_Id) return Node_Id | |
819 is | |
820 Alt_List : constant List_Id := New_List; | |
821 Actuals_List : List_Id; | |
822 Case_Node : Node_Id; | |
823 Case_Alt_Node : Node_Id; | |
824 Choice : Node_Id; | |
825 Choice_List : List_Id; | |
826 D : Entity_Id; | |
827 Return_Node : Node_Id; | |
828 | |
829 begin | |
830 Case_Node := New_Node (N_Case_Statement, Loc); | |
831 | |
832 -- Replace the discriminant which controls the variant with the name | |
833 -- of the formal of the checking function. | |
834 | |
835 Set_Expression (Case_Node, Make_Identifier (Loc, Chars (Case_Id))); | |
836 | |
837 Choice := First (Discrete_Choices (Variant)); | |
838 | |
839 if Nkind (Choice) = N_Others_Choice then | |
840 Choice_List := New_Copy_List (Others_Discrete_Choices (Choice)); | |
841 else | |
842 Choice_List := New_Copy_List (Discrete_Choices (Variant)); | |
843 end if; | |
844 | |
845 if not Is_Empty_List (Choice_List) then | |
846 Case_Alt_Node := New_Node (N_Case_Statement_Alternative, Loc); | |
847 Set_Discrete_Choices (Case_Alt_Node, Choice_List); | |
848 | |
849 -- In case this is a nested variant, we need to return the result | |
850 -- of the discriminant checking function for the immediately | |
851 -- enclosing variant. | |
852 | |
853 if Present (Enclosing_Func_Id) then | |
854 Actuals_List := New_List; | |
855 | |
856 D := First_Discriminant (Rec_Id); | |
857 while Present (D) loop | |
858 Append (Make_Identifier (Loc, Chars (D)), Actuals_List); | |
859 Next_Discriminant (D); | |
860 end loop; | |
861 | |
862 Return_Node := | |
863 Make_Simple_Return_Statement (Loc, | |
864 Expression => | |
865 Make_Function_Call (Loc, | |
866 Name => | |
867 New_Occurrence_Of (Enclosing_Func_Id, Loc), | |
868 Parameter_Associations => | |
869 Actuals_List)); | |
870 | |
871 else | |
872 Return_Node := | |
873 Make_Simple_Return_Statement (Loc, | |
874 Expression => | |
875 New_Occurrence_Of (Standard_False, Loc)); | |
876 end if; | |
877 | |
878 Set_Statements (Case_Alt_Node, New_List (Return_Node)); | |
879 Append (Case_Alt_Node, Alt_List); | |
880 end if; | |
881 | |
882 Case_Alt_Node := New_Node (N_Case_Statement_Alternative, Loc); | |
883 Choice_List := New_List (New_Node (N_Others_Choice, Loc)); | |
884 Set_Discrete_Choices (Case_Alt_Node, Choice_List); | |
885 | |
886 Return_Node := | |
887 Make_Simple_Return_Statement (Loc, | |
888 Expression => | |
889 New_Occurrence_Of (Standard_True, Loc)); | |
890 | |
891 Set_Statements (Case_Alt_Node, New_List (Return_Node)); | |
892 Append (Case_Alt_Node, Alt_List); | |
893 | |
894 Set_Alternatives (Case_Node, Alt_List); | |
895 return Case_Node; | |
896 end Build_Case_Statement; | |
897 | |
898 --------------------------- | |
899 -- Build_Dcheck_Function -- | |
900 --------------------------- | |
901 | |
902 function Build_Dcheck_Function | |
903 (Case_Id : Entity_Id; | |
904 Variant : Node_Id) return Entity_Id | |
905 is | |
906 Body_Node : Node_Id; | |
907 Func_Id : Entity_Id; | |
908 Parameter_List : List_Id; | |
909 Spec_Node : Node_Id; | |
910 | |
911 begin | |
912 Body_Node := New_Node (N_Subprogram_Body, Loc); | |
913 Sequence := Sequence + 1; | |
914 | |
915 Func_Id := | |
916 Make_Defining_Identifier (Loc, | |
917 Chars => New_External_Name (Chars (Rec_Id), 'D', Sequence)); | |
918 Set_Is_Discriminant_Check_Function (Func_Id); | |
919 | |
920 Spec_Node := New_Node (N_Function_Specification, Loc); | |
921 Set_Defining_Unit_Name (Spec_Node, Func_Id); | |
922 | |
923 Parameter_List := Build_Discriminant_Formals (Rec_Id, False); | |
924 | |
925 Set_Parameter_Specifications (Spec_Node, Parameter_List); | |
926 Set_Result_Definition (Spec_Node, | |
927 New_Occurrence_Of (Standard_Boolean, Loc)); | |
928 Set_Specification (Body_Node, Spec_Node); | |
929 Set_Declarations (Body_Node, New_List); | |
930 | |
931 Set_Handled_Statement_Sequence (Body_Node, | |
932 Make_Handled_Sequence_Of_Statements (Loc, | |
933 Statements => New_List ( | |
934 Build_Case_Statement (Case_Id, Variant)))); | |
935 | |
936 Set_Ekind (Func_Id, E_Function); | |
937 Set_Mechanism (Func_Id, Default_Mechanism); | |
938 Set_Is_Inlined (Func_Id, True); | |
939 Set_Is_Pure (Func_Id, True); | |
940 Set_Is_Public (Func_Id, Is_Public (Rec_Id)); | |
941 Set_Is_Internal (Func_Id, True); | |
942 | |
943 if not Debug_Generated_Code then | |
944 Set_Debug_Info_Off (Func_Id); | |
945 end if; | |
946 | |
947 Analyze (Body_Node); | |
948 | |
949 Append_Freeze_Action (Rec_Id, Body_Node); | |
950 Set_Dcheck_Function (Variant, Func_Id); | |
951 return Func_Id; | |
952 end Build_Dcheck_Function; | |
953 | |
954 ---------------------------- | |
955 -- Build_Dcheck_Functions -- | |
956 ---------------------------- | |
957 | |
958 procedure Build_Dcheck_Functions (Variant_Part_Node : Node_Id) is | |
959 Component_List_Node : Node_Id; | |
960 Decl : Entity_Id; | |
961 Discr_Name : Entity_Id; | |
962 Func_Id : Entity_Id; | |
963 Variant : Node_Id; | |
964 Saved_Enclosing_Func_Id : Entity_Id; | |
965 | |
966 begin | |
967 -- Build the discriminant-checking function for each variant, and | |
968 -- label all components of that variant with the function's name. | |
969 -- We only Generate a discriminant-checking function when the | |
970 -- variant is not empty, to prevent the creation of dead code. | |
971 | |
972 Discr_Name := Entity (Name (Variant_Part_Node)); | |
973 Variant := First_Non_Pragma (Variants (Variant_Part_Node)); | |
974 | |
975 while Present (Variant) loop | |
976 Component_List_Node := Component_List (Variant); | |
977 | |
978 if not Null_Present (Component_List_Node) then | |
979 Func_Id := Build_Dcheck_Function (Discr_Name, Variant); | |
980 | |
981 Decl := | |
982 First_Non_Pragma (Component_Items (Component_List_Node)); | |
983 while Present (Decl) loop | |
984 Set_Discriminant_Checking_Func | |
985 (Defining_Identifier (Decl), Func_Id); | |
986 Next_Non_Pragma (Decl); | |
987 end loop; | |
988 | |
989 if Present (Variant_Part (Component_List_Node)) then | |
990 Saved_Enclosing_Func_Id := Enclosing_Func_Id; | |
991 Enclosing_Func_Id := Func_Id; | |
992 Build_Dcheck_Functions (Variant_Part (Component_List_Node)); | |
993 Enclosing_Func_Id := Saved_Enclosing_Func_Id; | |
994 end if; | |
995 end if; | |
996 | |
997 Next_Non_Pragma (Variant); | |
998 end loop; | |
999 end Build_Dcheck_Functions; | |
1000 | |
1001 -- Start of processing for Build_Discr_Checking_Funcs | |
1002 | |
1003 begin | |
1004 -- Only build if not done already | |
1005 | |
1006 if not Discr_Check_Funcs_Built (N) then | |
1007 Type_Def := Type_Definition (N); | |
1008 | |
1009 if Nkind (Type_Def) = N_Record_Definition then | |
1010 if No (Component_List (Type_Def)) then -- null record. | |
1011 return; | |
1012 else | |
1013 V := Variant_Part (Component_List (Type_Def)); | |
1014 end if; | |
1015 | |
1016 else pragma Assert (Nkind (Type_Def) = N_Derived_Type_Definition); | |
1017 if No (Component_List (Record_Extension_Part (Type_Def))) then | |
1018 return; | |
1019 else | |
1020 V := Variant_Part | |
1021 (Component_List (Record_Extension_Part (Type_Def))); | |
1022 end if; | |
1023 end if; | |
1024 | |
1025 Rec_Id := Defining_Identifier (N); | |
1026 | |
1027 if Present (V) and then not Is_Unchecked_Union (Rec_Id) then | |
1028 Loc := Sloc (N); | |
1029 Enclosing_Func_Id := Empty; | |
1030 Build_Dcheck_Functions (V); | |
1031 end if; | |
1032 | |
1033 Set_Discr_Check_Funcs_Built (N); | |
1034 end if; | |
1035 end Build_Discr_Checking_Funcs; | |
1036 | |
1037 -------------------------------- | |
1038 -- Build_Discriminant_Formals -- | |
1039 -------------------------------- | |
1040 | |
1041 function Build_Discriminant_Formals | |
1042 (Rec_Id : Entity_Id; | |
1043 Use_Dl : Boolean) return List_Id | |
1044 is | |
1045 Loc : Source_Ptr := Sloc (Rec_Id); | |
1046 Parameter_List : constant List_Id := New_List; | |
1047 D : Entity_Id; | |
1048 Formal : Entity_Id; | |
1049 Formal_Type : Entity_Id; | |
1050 Param_Spec_Node : Node_Id; | |
1051 | |
1052 begin | |
1053 if Has_Discriminants (Rec_Id) then | |
1054 D := First_Discriminant (Rec_Id); | |
1055 while Present (D) loop | |
1056 Loc := Sloc (D); | |
1057 | |
1058 if Use_Dl then | |
1059 Formal := Discriminal (D); | |
1060 Formal_Type := Etype (Formal); | |
1061 else | |
1062 Formal := Make_Defining_Identifier (Loc, Chars (D)); | |
1063 Formal_Type := Etype (D); | |
1064 end if; | |
1065 | |
1066 Param_Spec_Node := | |
1067 Make_Parameter_Specification (Loc, | |
1068 Defining_Identifier => Formal, | |
1069 Parameter_Type => | |
1070 New_Occurrence_Of (Formal_Type, Loc)); | |
1071 Append (Param_Spec_Node, Parameter_List); | |
1072 Next_Discriminant (D); | |
1073 end loop; | |
1074 end if; | |
1075 | |
1076 return Parameter_List; | |
1077 end Build_Discriminant_Formals; | |
1078 | |
1079 -------------------------------------- | |
1080 -- Build_Equivalent_Array_Aggregate -- | |
1081 -------------------------------------- | |
1082 | |
1083 function Build_Equivalent_Array_Aggregate (T : Entity_Id) return Node_Id is | |
1084 Loc : constant Source_Ptr := Sloc (T); | |
1085 Comp_Type : constant Entity_Id := Component_Type (T); | |
1086 Index_Type : constant Entity_Id := Etype (First_Index (T)); | |
1087 Proc : constant Entity_Id := Base_Init_Proc (T); | |
1088 Lo, Hi : Node_Id; | |
1089 Aggr : Node_Id; | |
1090 Expr : Node_Id; | |
1091 | |
1092 begin | |
1093 if not Is_Constrained (T) | |
1094 or else Number_Dimensions (T) > 1 | |
1095 or else No (Proc) | |
1096 then | |
1097 Initialization_Warning (T); | |
1098 return Empty; | |
1099 end if; | |
1100 | |
1101 Lo := Type_Low_Bound (Index_Type); | |
1102 Hi := Type_High_Bound (Index_Type); | |
1103 | |
1104 if not Compile_Time_Known_Value (Lo) | |
1105 or else not Compile_Time_Known_Value (Hi) | |
1106 then | |
1107 Initialization_Warning (T); | |
1108 return Empty; | |
1109 end if; | |
1110 | |
1111 if Is_Record_Type (Comp_Type) | |
1112 and then Present (Base_Init_Proc (Comp_Type)) | |
1113 then | |
1114 Expr := Static_Initialization (Base_Init_Proc (Comp_Type)); | |
1115 | |
1116 if No (Expr) then | |
1117 Initialization_Warning (T); | |
1118 return Empty; | |
1119 end if; | |
1120 | |
1121 else | |
1122 Initialization_Warning (T); | |
1123 return Empty; | |
1124 end if; | |
1125 | |
1126 Aggr := Make_Aggregate (Loc, No_List, New_List); | |
1127 Set_Etype (Aggr, T); | |
1128 Set_Aggregate_Bounds (Aggr, | |
1129 Make_Range (Loc, | |
1130 Low_Bound => New_Copy (Lo), | |
1131 High_Bound => New_Copy (Hi))); | |
1132 Set_Parent (Aggr, Parent (Proc)); | |
1133 | |
1134 Append_To (Component_Associations (Aggr), | |
1135 Make_Component_Association (Loc, | |
1136 Choices => | |
1137 New_List ( | |
1138 Make_Range (Loc, | |
1139 Low_Bound => New_Copy (Lo), | |
1140 High_Bound => New_Copy (Hi))), | |
1141 Expression => Expr)); | |
1142 | |
1143 if Static_Array_Aggregate (Aggr) then | |
1144 return Aggr; | |
1145 else | |
1146 Initialization_Warning (T); | |
1147 return Empty; | |
1148 end if; | |
1149 end Build_Equivalent_Array_Aggregate; | |
1150 | |
1151 --------------------------------------- | |
1152 -- Build_Equivalent_Record_Aggregate -- | |
1153 --------------------------------------- | |
1154 | |
1155 function Build_Equivalent_Record_Aggregate (T : Entity_Id) return Node_Id is | |
1156 Agg : Node_Id; | |
1157 Comp : Entity_Id; | |
1158 Comp_Type : Entity_Id; | |
1159 | |
1160 -- Start of processing for Build_Equivalent_Record_Aggregate | |
1161 | |
1162 begin | |
1163 if not Is_Record_Type (T) | |
1164 or else Has_Discriminants (T) | |
1165 or else Is_Limited_Type (T) | |
1166 or else Has_Non_Standard_Rep (T) | |
1167 then | |
1168 Initialization_Warning (T); | |
1169 return Empty; | |
1170 end if; | |
1171 | |
1172 Comp := First_Component (T); | |
1173 | |
1174 -- A null record needs no warning | |
1175 | |
1176 if No (Comp) then | |
1177 return Empty; | |
1178 end if; | |
1179 | |
1180 while Present (Comp) loop | |
1181 | |
1182 -- Array components are acceptable if initialized by a positional | |
1183 -- aggregate with static components. | |
1184 | |
1185 if Is_Array_Type (Etype (Comp)) then | |
1186 Comp_Type := Component_Type (Etype (Comp)); | |
1187 | |
1188 if Nkind (Parent (Comp)) /= N_Component_Declaration | |
1189 or else No (Expression (Parent (Comp))) | |
1190 or else Nkind (Expression (Parent (Comp))) /= N_Aggregate | |
1191 then | |
1192 Initialization_Warning (T); | |
1193 return Empty; | |
1194 | |
1195 elsif Is_Scalar_Type (Component_Type (Etype (Comp))) | |
1196 and then | |
1197 (not Compile_Time_Known_Value (Type_Low_Bound (Comp_Type)) | |
1198 or else | |
1199 not Compile_Time_Known_Value (Type_High_Bound (Comp_Type))) | |
1200 then | |
1201 Initialization_Warning (T); | |
1202 return Empty; | |
1203 | |
1204 elsif | |
1205 not Static_Array_Aggregate (Expression (Parent (Comp))) | |
1206 then | |
1207 Initialization_Warning (T); | |
1208 return Empty; | |
1209 end if; | |
1210 | |
1211 elsif Is_Scalar_Type (Etype (Comp)) then | |
1212 Comp_Type := Etype (Comp); | |
1213 | |
1214 if Nkind (Parent (Comp)) /= N_Component_Declaration | |
1215 or else No (Expression (Parent (Comp))) | |
1216 or else not Compile_Time_Known_Value (Expression (Parent (Comp))) | |
1217 or else not Compile_Time_Known_Value (Type_Low_Bound (Comp_Type)) | |
1218 or else not | |
1219 Compile_Time_Known_Value (Type_High_Bound (Comp_Type)) | |
1220 then | |
1221 Initialization_Warning (T); | |
1222 return Empty; | |
1223 end if; | |
1224 | |
1225 -- For now, other types are excluded | |
1226 | |
1227 else | |
1228 Initialization_Warning (T); | |
1229 return Empty; | |
1230 end if; | |
1231 | |
1232 Next_Component (Comp); | |
1233 end loop; | |
1234 | |
1235 -- All components have static initialization. Build positional aggregate | |
1236 -- from the given expressions or defaults. | |
1237 | |
1238 Agg := Make_Aggregate (Sloc (T), New_List, New_List); | |
1239 Set_Parent (Agg, Parent (T)); | |
1240 | |
1241 Comp := First_Component (T); | |
1242 while Present (Comp) loop | |
1243 Append | |
1244 (New_Copy_Tree (Expression (Parent (Comp))), Expressions (Agg)); | |
1245 Next_Component (Comp); | |
1246 end loop; | |
1247 | |
1248 Analyze_And_Resolve (Agg, T); | |
1249 return Agg; | |
1250 end Build_Equivalent_Record_Aggregate; | |
1251 | |
1252 ------------------------------- | |
1253 -- Build_Initialization_Call -- | |
1254 ------------------------------- | |
1255 | |
1256 -- References to a discriminant inside the record type declaration can | |
1257 -- appear either in the subtype_indication to constrain a record or an | |
1258 -- array, or as part of a larger expression given for the initial value | |
1259 -- of a component. In both of these cases N appears in the record | |
1260 -- initialization procedure and needs to be replaced by the formal | |
1261 -- parameter of the initialization procedure which corresponds to that | |
1262 -- discriminant. | |
1263 | |
1264 -- In the example below, references to discriminants D1 and D2 in proc_1 | |
1265 -- are replaced by references to formals with the same name | |
1266 -- (discriminals) | |
1267 | |
1268 -- A similar replacement is done for calls to any record initialization | |
1269 -- procedure for any components that are themselves of a record type. | |
1270 | |
1271 -- type R (D1, D2 : Integer) is record | |
1272 -- X : Integer := F * D1; | |
1273 -- Y : Integer := F * D2; | |
1274 -- end record; | |
1275 | |
1276 -- procedure proc_1 (Out_2 : out R; D1 : Integer; D2 : Integer) is | |
1277 -- begin | |
1278 -- Out_2.D1 := D1; | |
1279 -- Out_2.D2 := D2; | |
1280 -- Out_2.X := F * D1; | |
1281 -- Out_2.Y := F * D2; | |
1282 -- end; | |
1283 | |
1284 function Build_Initialization_Call | |
1285 (Loc : Source_Ptr; | |
1286 Id_Ref : Node_Id; | |
1287 Typ : Entity_Id; | |
1288 In_Init_Proc : Boolean := False; | |
1289 Enclos_Type : Entity_Id := Empty; | |
1290 Discr_Map : Elist_Id := New_Elmt_List; | |
1291 With_Default_Init : Boolean := False; | |
1292 Constructor_Ref : Node_Id := Empty) return List_Id | |
1293 is | |
1294 Res : constant List_Id := New_List; | |
1295 | |
1296 Full_Type : Entity_Id; | |
1297 | |
1298 procedure Check_Predicated_Discriminant | |
1299 (Val : Node_Id; | |
1300 Discr : Entity_Id); | |
1301 -- Discriminants whose subtypes have predicates are checked in two | |
1302 -- cases: | |
1303 -- a) When an object is default-initialized and assertions are enabled | |
1304 -- we check that the value of the discriminant obeys the predicate. | |
1305 | |
1306 -- b) In all cases, if the discriminant controls a variant and the | |
1307 -- variant has no others_choice, Constraint_Error must be raised if | |
1308 -- the predicate is violated, because there is no variant covered | |
1309 -- by the illegal discriminant value. | |
1310 | |
1311 ----------------------------------- | |
1312 -- Check_Predicated_Discriminant -- | |
1313 ----------------------------------- | |
1314 | |
1315 procedure Check_Predicated_Discriminant | |
1316 (Val : Node_Id; | |
1317 Discr : Entity_Id) | |
1318 is | |
1319 Typ : constant Entity_Id := Etype (Discr); | |
1320 | |
1321 procedure Check_Missing_Others (V : Node_Id); | |
1322 -- ??? | |
1323 | |
1324 -------------------------- | |
1325 -- Check_Missing_Others -- | |
1326 -------------------------- | |
1327 | |
1328 procedure Check_Missing_Others (V : Node_Id) is | |
1329 Alt : Node_Id; | |
1330 Choice : Node_Id; | |
1331 Last_Var : Node_Id; | |
1332 | |
1333 begin | |
1334 Last_Var := Last_Non_Pragma (Variants (V)); | |
1335 Choice := First (Discrete_Choices (Last_Var)); | |
1336 | |
1337 -- An others_choice is added during expansion for gcc use, but | |
1338 -- does not cover the illegality. | |
1339 | |
1340 if Entity (Name (V)) = Discr then | |
1341 if Present (Choice) | |
1342 and then (Nkind (Choice) /= N_Others_Choice | |
1343 or else not Comes_From_Source (Choice)) | |
1344 then | |
1345 Check_Expression_Against_Static_Predicate (Val, Typ); | |
1346 | |
1347 if not Is_Static_Expression (Val) then | |
1348 Prepend_To (Res, | |
1349 Make_Raise_Constraint_Error (Loc, | |
1350 Condition => | |
1351 Make_Op_Not (Loc, | |
1352 Right_Opnd => Make_Predicate_Call (Typ, Val)), | |
1353 Reason => CE_Invalid_Data)); | |
1354 end if; | |
1355 end if; | |
1356 end if; | |
1357 | |
1358 -- Check whether some nested variant is ruled by the predicated | |
1359 -- discriminant. | |
1360 | |
1361 Alt := First (Variants (V)); | |
1362 while Present (Alt) loop | |
1363 if Nkind (Alt) = N_Variant | |
1364 and then Present (Variant_Part (Component_List (Alt))) | |
1365 then | |
1366 Check_Missing_Others | |
1367 (Variant_Part (Component_List (Alt))); | |
1368 end if; | |
1369 | |
1370 Next (Alt); | |
1371 end loop; | |
1372 end Check_Missing_Others; | |
1373 | |
1374 -- Local variables | |
1375 | |
1376 Def : Node_Id; | |
1377 | |
1378 -- Start of processing for Check_Predicated_Discriminant | |
1379 | |
1380 begin | |
1381 if Ekind (Base_Type (Full_Type)) = E_Record_Type then | |
1382 Def := Type_Definition (Parent (Base_Type (Full_Type))); | |
1383 else | |
1384 return; | |
1385 end if; | |
1386 | |
1387 if Policy_In_Effect (Name_Assert) = Name_Check | |
1388 and then not Predicates_Ignored (Etype (Discr)) | |
1389 then | |
1390 Prepend_To (Res, Make_Predicate_Check (Typ, Val)); | |
1391 end if; | |
1392 | |
1393 -- If discriminant controls a variant, verify that predicate is | |
1394 -- obeyed or else an Others_Choice is present. | |
1395 | |
1396 if Nkind (Def) = N_Record_Definition | |
1397 and then Present (Variant_Part (Component_List (Def))) | |
1398 and then Policy_In_Effect (Name_Assert) = Name_Ignore | |
1399 then | |
1400 Check_Missing_Others (Variant_Part (Component_List (Def))); | |
1401 end if; | |
1402 end Check_Predicated_Discriminant; | |
1403 | |
1404 -- Local variables | |
1405 | |
1406 Arg : Node_Id; | |
1407 Args : List_Id; | |
1408 Decls : List_Id; | |
1409 Decl : Node_Id; | |
1410 Discr : Entity_Id; | |
1411 First_Arg : Node_Id; | |
1412 Full_Init_Type : Entity_Id; | |
1413 Init_Call : Node_Id; | |
1414 Init_Type : Entity_Id; | |
1415 Proc : Entity_Id; | |
1416 | |
1417 -- Start of processing for Build_Initialization_Call | |
1418 | |
1419 begin | |
1420 pragma Assert (Constructor_Ref = Empty | |
1421 or else Is_CPP_Constructor_Call (Constructor_Ref)); | |
1422 | |
1423 if No (Constructor_Ref) then | |
1424 Proc := Base_Init_Proc (Typ); | |
1425 else | |
1426 Proc := Base_Init_Proc (Typ, Entity (Name (Constructor_Ref))); | |
1427 end if; | |
1428 | |
1429 pragma Assert (Present (Proc)); | |
1430 Init_Type := Etype (First_Formal (Proc)); | |
1431 Full_Init_Type := Underlying_Type (Init_Type); | |
1432 | |
1433 -- Nothing to do if the Init_Proc is null, unless Initialize_Scalars | |
1434 -- is active (in which case we make the call anyway, since in the | |
1435 -- actual compiled client it may be non null). | |
1436 | |
1437 if Is_Null_Init_Proc (Proc) and then not Init_Or_Norm_Scalars then | |
1438 return Empty_List; | |
1439 | |
1440 -- Nothing to do for an array of controlled components that have only | |
1441 -- the inherited Initialize primitive. This is a useful optimization | |
1442 -- for CodePeer. | |
1443 | |
1444 elsif Is_Trivial_Subprogram (Proc) | |
1445 and then Is_Array_Type (Full_Init_Type) | |
1446 then | |
1447 return New_List (Make_Null_Statement (Loc)); | |
1448 end if; | |
1449 | |
1450 -- Use the [underlying] full view when dealing with a private type. This | |
1451 -- may require several steps depending on derivations. | |
1452 | |
1453 Full_Type := Typ; | |
1454 loop | |
1455 if Is_Private_Type (Full_Type) then | |
1456 if Present (Full_View (Full_Type)) then | |
1457 Full_Type := Full_View (Full_Type); | |
1458 | |
1459 elsif Present (Underlying_Full_View (Full_Type)) then | |
1460 Full_Type := Underlying_Full_View (Full_Type); | |
1461 | |
1462 -- When a private type acts as a generic actual and lacks a full | |
1463 -- view, use the base type. | |
1464 | |
1465 elsif Is_Generic_Actual_Type (Full_Type) then | |
1466 Full_Type := Base_Type (Full_Type); | |
1467 | |
1468 elsif Ekind (Full_Type) = E_Private_Subtype | |
1469 and then (not Has_Discriminants (Full_Type) | |
1470 or else No (Discriminant_Constraint (Full_Type))) | |
1471 then | |
1472 Full_Type := Etype (Full_Type); | |
1473 | |
1474 -- The loop has recovered the [underlying] full view, stop the | |
1475 -- traversal. | |
1476 | |
1477 else | |
1478 exit; | |
1479 end if; | |
1480 | |
1481 -- The type is not private, nothing to do | |
1482 | |
1483 else | |
1484 exit; | |
1485 end if; | |
1486 end loop; | |
1487 | |
1488 -- If Typ is derived, the procedure is the initialization procedure for | |
1489 -- the root type. Wrap the argument in an conversion to make it type | |
1490 -- honest. Actually it isn't quite type honest, because there can be | |
1491 -- conflicts of views in the private type case. That is why we set | |
1492 -- Conversion_OK in the conversion node. | |
1493 | |
1494 if (Is_Record_Type (Typ) | |
1495 or else Is_Array_Type (Typ) | |
1496 or else Is_Private_Type (Typ)) | |
1497 and then Init_Type /= Base_Type (Typ) | |
1498 then | |
1499 First_Arg := OK_Convert_To (Etype (Init_Type), Id_Ref); | |
1500 Set_Etype (First_Arg, Init_Type); | |
1501 | |
1502 else | |
1503 First_Arg := Id_Ref; | |
1504 end if; | |
1505 | |
1506 Args := New_List (Convert_Concurrent (First_Arg, Typ)); | |
1507 | |
1508 -- In the tasks case, add _Master as the value of the _Master parameter | |
1509 -- and _Chain as the value of the _Chain parameter. At the outer level, | |
1510 -- these will be variables holding the corresponding values obtained | |
1511 -- from GNARL. At inner levels, they will be the parameters passed down | |
1512 -- through the outer routines. | |
1513 | |
1514 if Has_Task (Full_Type) then | |
1515 if Restriction_Active (No_Task_Hierarchy) then | |
1516 Append_To (Args, | |
1517 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc)); | |
1518 else | |
1519 Append_To (Args, Make_Identifier (Loc, Name_uMaster)); | |
1520 end if; | |
1521 | |
1522 -- Add _Chain (not done for sequential elaboration policy, see | |
1523 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads). | |
1524 | |
1525 if Partition_Elaboration_Policy /= 'S' then | |
1526 Append_To (Args, Make_Identifier (Loc, Name_uChain)); | |
1527 end if; | |
1528 | |
1529 -- Ada 2005 (AI-287): In case of default initialized components | |
1530 -- with tasks, we generate a null string actual parameter. | |
1531 -- This is just a workaround that must be improved later??? | |
1532 | |
1533 if With_Default_Init then | |
1534 Append_To (Args, | |
1535 Make_String_Literal (Loc, | |
1536 Strval => "")); | |
1537 | |
1538 else | |
1539 Decls := | |
1540 Build_Task_Image_Decls (Loc, Id_Ref, Enclos_Type, In_Init_Proc); | |
1541 Decl := Last (Decls); | |
1542 | |
1543 Append_To (Args, | |
1544 New_Occurrence_Of (Defining_Identifier (Decl), Loc)); | |
1545 Append_List (Decls, Res); | |
1546 end if; | |
1547 | |
1548 else | |
1549 Decls := No_List; | |
1550 Decl := Empty; | |
1551 end if; | |
1552 | |
1553 -- Add discriminant values if discriminants are present | |
1554 | |
1555 if Has_Discriminants (Full_Init_Type) then | |
1556 Discr := First_Discriminant (Full_Init_Type); | |
1557 while Present (Discr) loop | |
1558 | |
1559 -- If this is a discriminated concurrent type, the init_proc | |
1560 -- for the corresponding record is being called. Use that type | |
1561 -- directly to find the discriminant value, to handle properly | |
1562 -- intervening renamed discriminants. | |
1563 | |
1564 declare | |
1565 T : Entity_Id := Full_Type; | |
1566 | |
1567 begin | |
1568 if Is_Protected_Type (T) then | |
1569 T := Corresponding_Record_Type (T); | |
1570 end if; | |
1571 | |
1572 Arg := | |
1573 Get_Discriminant_Value ( | |
1574 Discr, | |
1575 T, | |
1576 Discriminant_Constraint (Full_Type)); | |
1577 end; | |
1578 | |
1579 -- If the target has access discriminants, and is constrained by | |
1580 -- an access to the enclosing construct, i.e. a current instance, | |
1581 -- replace the reference to the type by a reference to the object. | |
1582 | |
1583 if Nkind (Arg) = N_Attribute_Reference | |
1584 and then Is_Access_Type (Etype (Arg)) | |
1585 and then Is_Entity_Name (Prefix (Arg)) | |
1586 and then Is_Type (Entity (Prefix (Arg))) | |
1587 then | |
1588 Arg := | |
1589 Make_Attribute_Reference (Loc, | |
1590 Prefix => New_Copy (Prefix (Id_Ref)), | |
1591 Attribute_Name => Name_Unrestricted_Access); | |
1592 | |
1593 elsif In_Init_Proc then | |
1594 | |
1595 -- Replace any possible references to the discriminant in the | |
1596 -- call to the record initialization procedure with references | |
1597 -- to the appropriate formal parameter. | |
1598 | |
1599 if Nkind (Arg) = N_Identifier | |
1600 and then Ekind (Entity (Arg)) = E_Discriminant | |
1601 then | |
1602 Arg := New_Occurrence_Of (Discriminal (Entity (Arg)), Loc); | |
1603 | |
1604 -- Otherwise make a copy of the default expression. Note that | |
1605 -- we use the current Sloc for this, because we do not want the | |
1606 -- call to appear to be at the declaration point. Within the | |
1607 -- expression, replace discriminants with their discriminals. | |
1608 | |
1609 else | |
1610 Arg := | |
1611 New_Copy_Tree (Arg, Map => Discr_Map, New_Sloc => Loc); | |
1612 end if; | |
1613 | |
1614 else | |
1615 if Is_Constrained (Full_Type) then | |
1616 Arg := Duplicate_Subexpr_No_Checks (Arg); | |
1617 else | |
1618 -- The constraints come from the discriminant default exps, | |
1619 -- they must be reevaluated, so we use New_Copy_Tree but we | |
1620 -- ensure the proper Sloc (for any embedded calls). | |
1621 -- In addition, if a predicate check is needed on the value | |
1622 -- of the discriminant, insert it ahead of the call. | |
1623 | |
1624 Arg := New_Copy_Tree (Arg, New_Sloc => Loc); | |
1625 end if; | |
1626 | |
1627 if Has_Predicates (Etype (Discr)) then | |
1628 Check_Predicated_Discriminant (Arg, Discr); | |
1629 end if; | |
1630 end if; | |
1631 | |
1632 -- Ada 2005 (AI-287): In case of default initialized components, | |
1633 -- if the component is constrained with a discriminant of the | |
1634 -- enclosing type, we need to generate the corresponding selected | |
1635 -- component node to access the discriminant value. In other cases | |
1636 -- this is not required, either because we are inside the init | |
1637 -- proc and we use the corresponding formal, or else because the | |
1638 -- component is constrained by an expression. | |
1639 | |
1640 if With_Default_Init | |
1641 and then Nkind (Id_Ref) = N_Selected_Component | |
1642 and then Nkind (Arg) = N_Identifier | |
1643 and then Ekind (Entity (Arg)) = E_Discriminant | |
1644 then | |
1645 Append_To (Args, | |
1646 Make_Selected_Component (Loc, | |
1647 Prefix => New_Copy_Tree (Prefix (Id_Ref)), | |
1648 Selector_Name => Arg)); | |
1649 else | |
1650 Append_To (Args, Arg); | |
1651 end if; | |
1652 | |
1653 Next_Discriminant (Discr); | |
1654 end loop; | |
1655 end if; | |
1656 | |
1657 -- If this is a call to initialize the parent component of a derived | |
1658 -- tagged type, indicate that the tag should not be set in the parent. | |
1659 | |
1660 if Is_Tagged_Type (Full_Init_Type) | |
1661 and then not Is_CPP_Class (Full_Init_Type) | |
1662 and then Nkind (Id_Ref) = N_Selected_Component | |
1663 and then Chars (Selector_Name (Id_Ref)) = Name_uParent | |
1664 then | |
1665 Append_To (Args, New_Occurrence_Of (Standard_False, Loc)); | |
1666 | |
1667 elsif Present (Constructor_Ref) then | |
1668 Append_List_To (Args, | |
1669 New_Copy_List (Parameter_Associations (Constructor_Ref))); | |
1670 end if; | |
1671 | |
1672 Append_To (Res, | |
1673 Make_Procedure_Call_Statement (Loc, | |
1674 Name => New_Occurrence_Of (Proc, Loc), | |
1675 Parameter_Associations => Args)); | |
1676 | |
1677 if Needs_Finalization (Typ) | |
1678 and then Nkind (Id_Ref) = N_Selected_Component | |
1679 then | |
1680 if Chars (Selector_Name (Id_Ref)) /= Name_uParent then | |
1681 Init_Call := | |
1682 Make_Init_Call | |
1683 (Obj_Ref => New_Copy_Tree (First_Arg), | |
1684 Typ => Typ); | |
1685 | |
1686 -- Guard against a missing [Deep_]Initialize when the type was not | |
1687 -- properly frozen. | |
1688 | |
1689 if Present (Init_Call) then | |
1690 Append_To (Res, Init_Call); | |
1691 end if; | |
1692 end if; | |
1693 end if; | |
1694 | |
1695 return Res; | |
1696 | |
1697 exception | |
1698 when RE_Not_Available => | |
1699 return Empty_List; | |
1700 end Build_Initialization_Call; | |
1701 | |
1702 ---------------------------- | |
1703 -- Build_Record_Init_Proc -- | |
1704 ---------------------------- | |
1705 | |
1706 procedure Build_Record_Init_Proc (N : Node_Id; Rec_Ent : Entity_Id) is | |
1707 Decls : constant List_Id := New_List; | |
1708 Discr_Map : constant Elist_Id := New_Elmt_List; | |
1709 Loc : constant Source_Ptr := Sloc (Rec_Ent); | |
1710 Counter : Nat := 0; | |
1711 Proc_Id : Entity_Id; | |
1712 Rec_Type : Entity_Id; | |
1713 Set_Tag : Entity_Id := Empty; | |
1714 | |
1715 function Build_Assignment | |
1716 (Id : Entity_Id; | |
1717 Default : Node_Id) return List_Id; | |
1718 -- Build an assignment statement that assigns the default expression to | |
1719 -- its corresponding record component if defined. The left-hand side of | |
1720 -- the assignment is marked Assignment_OK so that initialization of | |
1721 -- limited private records works correctly. This routine may also build | |
1722 -- an adjustment call if the component is controlled. | |
1723 | |
1724 procedure Build_Discriminant_Assignments (Statement_List : List_Id); | |
1725 -- If the record has discriminants, add assignment statements to | |
1726 -- Statement_List to initialize the discriminant values from the | |
1727 -- arguments of the initialization procedure. | |
1728 | |
1729 function Build_Init_Statements (Comp_List : Node_Id) return List_Id; | |
1730 -- Build a list representing a sequence of statements which initialize | |
1731 -- components of the given component list. This may involve building | |
1732 -- case statements for the variant parts. Append any locally declared | |
1733 -- objects on list Decls. | |
1734 | |
1735 function Build_Init_Call_Thru (Parameters : List_Id) return List_Id; | |
1736 -- Given an untagged type-derivation that declares discriminants, e.g. | |
1737 -- | |
1738 -- type R (R1, R2 : Integer) is record ... end record; | |
1739 -- type D (D1 : Integer) is new R (1, D1); | |
1740 -- | |
1741 -- we make the _init_proc of D be | |
1742 -- | |
1743 -- procedure _init_proc (X : D; D1 : Integer) is | |
1744 -- begin | |
1745 -- _init_proc (R (X), 1, D1); | |
1746 -- end _init_proc; | |
1747 -- | |
1748 -- This function builds the call statement in this _init_proc. | |
1749 | |
1750 procedure Build_CPP_Init_Procedure; | |
1751 -- Build the tree corresponding to the procedure specification and body | |
1752 -- of the IC procedure that initializes the C++ part of the dispatch | |
1753 -- table of an Ada tagged type that is a derivation of a CPP type. | |
1754 -- Install it as the CPP_Init TSS. | |
1755 | |
1756 procedure Build_Init_Procedure; | |
1757 -- Build the tree corresponding to the procedure specification and body | |
1758 -- of the initialization procedure and install it as the _init TSS. | |
1759 | |
1760 procedure Build_Offset_To_Top_Functions; | |
1761 -- Ada 2005 (AI-251): Build the tree corresponding to the procedure spec | |
1762 -- and body of Offset_To_Top, a function used in conjuction with types | |
1763 -- having secondary dispatch tables. | |
1764 | |
1765 procedure Build_Record_Checks (S : Node_Id; Check_List : List_Id); | |
1766 -- Add range checks to components of discriminated records. S is a | |
1767 -- subtype indication of a record component. Check_List is a list | |
1768 -- to which the check actions are appended. | |
1769 | |
1770 function Component_Needs_Simple_Initialization | |
1771 (T : Entity_Id) return Boolean; | |
1772 -- Determine if a component needs simple initialization, given its type | |
1773 -- T. This routine is the same as Needs_Simple_Initialization except for | |
1774 -- components of type Tag and Interface_Tag. These two access types do | |
1775 -- not require initialization since they are explicitly initialized by | |
1776 -- other means. | |
1777 | |
1778 function Parent_Subtype_Renaming_Discrims return Boolean; | |
1779 -- Returns True for base types N that rename discriminants, else False | |
1780 | |
1781 function Requires_Init_Proc (Rec_Id : Entity_Id) return Boolean; | |
1782 -- Determine whether a record initialization procedure needs to be | |
1783 -- generated for the given record type. | |
1784 | |
1785 ---------------------- | |
1786 -- Build_Assignment -- | |
1787 ---------------------- | |
1788 | |
1789 function Build_Assignment | |
1790 (Id : Entity_Id; | |
1791 Default : Node_Id) return List_Id | |
1792 is | |
1793 Default_Loc : constant Source_Ptr := Sloc (Default); | |
1794 Typ : constant Entity_Id := Underlying_Type (Etype (Id)); | |
1795 | |
1796 Adj_Call : Node_Id; | |
1797 Exp : Node_Id := Default; | |
1798 Kind : Node_Kind := Nkind (Default); | |
1799 Lhs : Node_Id; | |
1800 Res : List_Id; | |
1801 | |
1802 function Replace_Discr_Ref (N : Node_Id) return Traverse_Result; | |
1803 -- Analysis of the aggregate has replaced discriminants by their | |
1804 -- corresponding discriminals, but these are irrelevant when the | |
1805 -- component has a mutable type and is initialized with an aggregate. | |
1806 -- Instead, they must be replaced by the values supplied in the | |
1807 -- aggregate, that will be assigned during the expansion of the | |
1808 -- assignment. | |
1809 | |
1810 ----------------------- | |
1811 -- Replace_Discr_Ref -- | |
1812 ----------------------- | |
1813 | |
1814 function Replace_Discr_Ref (N : Node_Id) return Traverse_Result is | |
1815 Val : Node_Id; | |
1816 | |
1817 begin | |
1818 if Is_Entity_Name (N) | |
1819 and then Present (Entity (N)) | |
1820 and then Is_Formal (Entity (N)) | |
1821 and then Present (Discriminal_Link (Entity (N))) | |
1822 then | |
1823 Val := | |
1824 Make_Selected_Component (Default_Loc, | |
1825 Prefix => New_Copy_Tree (Lhs), | |
1826 Selector_Name => | |
1827 New_Occurrence_Of | |
1828 (Discriminal_Link (Entity (N)), Default_Loc)); | |
1829 | |
1830 if Present (Val) then | |
1831 Rewrite (N, New_Copy_Tree (Val)); | |
1832 end if; | |
1833 end if; | |
1834 | |
1835 return OK; | |
1836 end Replace_Discr_Ref; | |
1837 | |
1838 procedure Replace_Discriminant_References is | |
1839 new Traverse_Proc (Replace_Discr_Ref); | |
1840 | |
1841 -- Start of processing for Build_Assignment | |
1842 | |
1843 begin | |
1844 Lhs := | |
1845 Make_Selected_Component (Default_Loc, | |
1846 Prefix => Make_Identifier (Loc, Name_uInit), | |
1847 Selector_Name => New_Occurrence_Of (Id, Default_Loc)); | |
1848 Set_Assignment_OK (Lhs); | |
1849 | |
1850 if Nkind (Exp) = N_Aggregate | |
1851 and then Has_Discriminants (Typ) | |
1852 and then not Is_Constrained (Base_Type (Typ)) | |
1853 then | |
1854 -- The aggregate may provide new values for the discriminants | |
1855 -- of the component, and other components may depend on those | |
1856 -- discriminants. Previous analysis of those expressions have | |
1857 -- replaced the discriminants by the formals of the initialization | |
1858 -- procedure for the type, but these are irrelevant in the | |
1859 -- enclosing initialization procedure: those discriminant | |
1860 -- references must be replaced by the values provided in the | |
1861 -- aggregate. | |
1862 | |
1863 Replace_Discriminant_References (Exp); | |
1864 end if; | |
1865 | |
1866 -- Case of an access attribute applied to the current instance. | |
1867 -- Replace the reference to the type by a reference to the actual | |
1868 -- object. (Note that this handles the case of the top level of | |
1869 -- the expression being given by such an attribute, but does not | |
1870 -- cover uses nested within an initial value expression. Nested | |
1871 -- uses are unlikely to occur in practice, but are theoretically | |
1872 -- possible.) It is not clear how to handle them without fully | |
1873 -- traversing the expression. ??? | |
1874 | |
1875 if Kind = N_Attribute_Reference | |
1876 and then Nam_In (Attribute_Name (Default), Name_Unchecked_Access, | |
1877 Name_Unrestricted_Access) | |
1878 and then Is_Entity_Name (Prefix (Default)) | |
1879 and then Is_Type (Entity (Prefix (Default))) | |
1880 and then Entity (Prefix (Default)) = Rec_Type | |
1881 then | |
1882 Exp := | |
1883 Make_Attribute_Reference (Default_Loc, | |
1884 Prefix => | |
1885 Make_Identifier (Default_Loc, Name_uInit), | |
1886 Attribute_Name => Name_Unrestricted_Access); | |
1887 end if; | |
1888 | |
1889 -- Take a copy of Exp to ensure that later copies of this component | |
1890 -- declaration in derived types see the original tree, not a node | |
1891 -- rewritten during expansion of the init_proc. If the copy contains | |
1892 -- itypes, the scope of the new itypes is the init_proc being built. | |
1893 | |
1894 Exp := New_Copy_Tree (Exp, New_Scope => Proc_Id); | |
1895 | |
1896 Res := New_List ( | |
1897 Make_Assignment_Statement (Loc, | |
1898 Name => Lhs, | |
1899 Expression => Exp)); | |
1900 | |
1901 Set_No_Ctrl_Actions (First (Res)); | |
1902 | |
1903 -- Adjust the tag if tagged (because of possible view conversions). | |
1904 -- Suppress the tag adjustment when not Tagged_Type_Expansion because | |
1905 -- tags are represented implicitly in objects. | |
1906 | |
1907 if Is_Tagged_Type (Typ) and then Tagged_Type_Expansion then | |
1908 Append_To (Res, | |
1909 Make_Assignment_Statement (Default_Loc, | |
1910 Name => | |
1911 Make_Selected_Component (Default_Loc, | |
1912 Prefix => | |
1913 New_Copy_Tree (Lhs, New_Scope => Proc_Id), | |
1914 Selector_Name => | |
1915 New_Occurrence_Of | |
1916 (First_Tag_Component (Typ), Default_Loc)), | |
1917 | |
1918 Expression => | |
1919 Unchecked_Convert_To (RTE (RE_Tag), | |
1920 New_Occurrence_Of | |
1921 (Node (First_Elmt (Access_Disp_Table (Underlying_Type | |
1922 (Typ)))), | |
1923 Default_Loc)))); | |
1924 end if; | |
1925 | |
1926 -- Adjust the component if controlled except if it is an aggregate | |
1927 -- that will be expanded inline. | |
1928 | |
1929 if Kind = N_Qualified_Expression then | |
1930 Kind := Nkind (Expression (Default)); | |
1931 end if; | |
1932 | |
1933 if Needs_Finalization (Typ) | |
1934 and then not (Nkind_In (Kind, N_Aggregate, N_Extension_Aggregate)) | |
1935 and then not Is_Build_In_Place_Function_Call (Exp) | |
1936 then | |
1937 Adj_Call := | |
1938 Make_Adjust_Call | |
1939 (Obj_Ref => New_Copy_Tree (Lhs), | |
1940 Typ => Etype (Id)); | |
1941 | |
1942 -- Guard against a missing [Deep_]Adjust when the component type | |
1943 -- was not properly frozen. | |
1944 | |
1945 if Present (Adj_Call) then | |
1946 Append_To (Res, Adj_Call); | |
1947 end if; | |
1948 end if; | |
1949 | |
1950 -- If a component type has a predicate, add check to the component | |
1951 -- assignment. Discriminants are handled at the point of the call, | |
1952 -- which provides for a better error message. | |
1953 | |
1954 if Comes_From_Source (Exp) | |
1955 and then Has_Predicates (Typ) | |
1956 and then not Predicate_Checks_Suppressed (Empty) | |
1957 and then not Predicates_Ignored (Typ) | |
1958 then | |
1959 Append (Make_Predicate_Check (Typ, Exp), Res); | |
1960 end if; | |
1961 | |
1962 return Res; | |
1963 | |
1964 exception | |
1965 when RE_Not_Available => | |
1966 return Empty_List; | |
1967 end Build_Assignment; | |
1968 | |
1969 ------------------------------------ | |
1970 -- Build_Discriminant_Assignments -- | |
1971 ------------------------------------ | |
1972 | |
1973 procedure Build_Discriminant_Assignments (Statement_List : List_Id) is | |
1974 Is_Tagged : constant Boolean := Is_Tagged_Type (Rec_Type); | |
1975 D : Entity_Id; | |
1976 D_Loc : Source_Ptr; | |
1977 | |
1978 begin | |
1979 if Has_Discriminants (Rec_Type) | |
1980 and then not Is_Unchecked_Union (Rec_Type) | |
1981 then | |
1982 D := First_Discriminant (Rec_Type); | |
1983 while Present (D) loop | |
1984 | |
1985 -- Don't generate the assignment for discriminants in derived | |
1986 -- tagged types if the discriminant is a renaming of some | |
1987 -- ancestor discriminant. This initialization will be done | |
1988 -- when initializing the _parent field of the derived record. | |
1989 | |
1990 if Is_Tagged | |
1991 and then Present (Corresponding_Discriminant (D)) | |
1992 then | |
1993 null; | |
1994 | |
1995 else | |
1996 D_Loc := Sloc (D); | |
1997 Append_List_To (Statement_List, | |
1998 Build_Assignment (D, | |
1999 New_Occurrence_Of (Discriminal (D), D_Loc))); | |
2000 end if; | |
2001 | |
2002 Next_Discriminant (D); | |
2003 end loop; | |
2004 end if; | |
2005 end Build_Discriminant_Assignments; | |
2006 | |
2007 -------------------------- | |
2008 -- Build_Init_Call_Thru -- | |
2009 -------------------------- | |
2010 | |
2011 function Build_Init_Call_Thru (Parameters : List_Id) return List_Id is | |
2012 Parent_Proc : constant Entity_Id := | |
2013 Base_Init_Proc (Etype (Rec_Type)); | |
2014 | |
2015 Parent_Type : constant Entity_Id := | |
2016 Etype (First_Formal (Parent_Proc)); | |
2017 | |
2018 Uparent_Type : constant Entity_Id := | |
2019 Underlying_Type (Parent_Type); | |
2020 | |
2021 First_Discr_Param : Node_Id; | |
2022 | |
2023 Arg : Node_Id; | |
2024 Args : List_Id; | |
2025 First_Arg : Node_Id; | |
2026 Parent_Discr : Entity_Id; | |
2027 Res : List_Id; | |
2028 | |
2029 begin | |
2030 -- First argument (_Init) is the object to be initialized. | |
2031 -- ??? not sure where to get a reasonable Loc for First_Arg | |
2032 | |
2033 First_Arg := | |
2034 OK_Convert_To (Parent_Type, | |
2035 New_Occurrence_Of | |
2036 (Defining_Identifier (First (Parameters)), Loc)); | |
2037 | |
2038 Set_Etype (First_Arg, Parent_Type); | |
2039 | |
2040 Args := New_List (Convert_Concurrent (First_Arg, Rec_Type)); | |
2041 | |
2042 -- In the tasks case, | |
2043 -- add _Master as the value of the _Master parameter | |
2044 -- add _Chain as the value of the _Chain parameter. | |
2045 -- add _Task_Name as the value of the _Task_Name parameter. | |
2046 -- At the outer level, these will be variables holding the | |
2047 -- corresponding values obtained from GNARL or the expander. | |
2048 -- | |
2049 -- At inner levels, they will be the parameters passed down through | |
2050 -- the outer routines. | |
2051 | |
2052 First_Discr_Param := Next (First (Parameters)); | |
2053 | |
2054 if Has_Task (Rec_Type) then | |
2055 if Restriction_Active (No_Task_Hierarchy) then | |
2056 Append_To (Args, | |
2057 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc)); | |
2058 else | |
2059 Append_To (Args, Make_Identifier (Loc, Name_uMaster)); | |
2060 end if; | |
2061 | |
2062 -- Add _Chain (not done for sequential elaboration policy, see | |
2063 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads). | |
2064 | |
2065 if Partition_Elaboration_Policy /= 'S' then | |
2066 Append_To (Args, Make_Identifier (Loc, Name_uChain)); | |
2067 end if; | |
2068 | |
2069 Append_To (Args, Make_Identifier (Loc, Name_uTask_Name)); | |
2070 First_Discr_Param := Next (Next (Next (First_Discr_Param))); | |
2071 end if; | |
2072 | |
2073 -- Append discriminant values | |
2074 | |
2075 if Has_Discriminants (Uparent_Type) then | |
2076 pragma Assert (not Is_Tagged_Type (Uparent_Type)); | |
2077 | |
2078 Parent_Discr := First_Discriminant (Uparent_Type); | |
2079 while Present (Parent_Discr) loop | |
2080 | |
2081 -- Get the initial value for this discriminant | |
2082 -- ??? needs to be cleaned up to use parent_Discr_Constr | |
2083 -- directly. | |
2084 | |
2085 declare | |
2086 Discr : Entity_Id := | |
2087 First_Stored_Discriminant (Uparent_Type); | |
2088 | |
2089 Discr_Value : Elmt_Id := | |
2090 First_Elmt (Stored_Constraint (Rec_Type)); | |
2091 | |
2092 begin | |
2093 while Original_Record_Component (Parent_Discr) /= Discr loop | |
2094 Next_Stored_Discriminant (Discr); | |
2095 Next_Elmt (Discr_Value); | |
2096 end loop; | |
2097 | |
2098 Arg := Node (Discr_Value); | |
2099 end; | |
2100 | |
2101 -- Append it to the list | |
2102 | |
2103 if Nkind (Arg) = N_Identifier | |
2104 and then Ekind (Entity (Arg)) = E_Discriminant | |
2105 then | |
2106 Append_To (Args, | |
2107 New_Occurrence_Of (Discriminal (Entity (Arg)), Loc)); | |
2108 | |
2109 -- Case of access discriminants. We replace the reference | |
2110 -- to the type by a reference to the actual object. | |
2111 | |
2112 -- Is above comment right??? Use of New_Copy below seems mighty | |
2113 -- suspicious ??? | |
2114 | |
2115 else | |
2116 Append_To (Args, New_Copy (Arg)); | |
2117 end if; | |
2118 | |
2119 Next_Discriminant (Parent_Discr); | |
2120 end loop; | |
2121 end if; | |
2122 | |
2123 Res := | |
2124 New_List ( | |
2125 Make_Procedure_Call_Statement (Loc, | |
2126 Name => | |
2127 New_Occurrence_Of (Parent_Proc, Loc), | |
2128 Parameter_Associations => Args)); | |
2129 | |
2130 return Res; | |
2131 end Build_Init_Call_Thru; | |
2132 | |
2133 ----------------------------------- | |
2134 -- Build_Offset_To_Top_Functions -- | |
2135 ----------------------------------- | |
2136 | |
2137 procedure Build_Offset_To_Top_Functions is | |
2138 | |
2139 procedure Build_Offset_To_Top_Function (Iface_Comp : Entity_Id); | |
2140 -- Generate: | |
2141 -- function Fxx (O : Address) return Storage_Offset is | |
2142 -- type Acc is access all <Typ>; | |
2143 -- begin | |
2144 -- return Acc!(O).Iface_Comp'Position; | |
2145 -- end Fxx; | |
2146 | |
2147 ---------------------------------- | |
2148 -- Build_Offset_To_Top_Function -- | |
2149 ---------------------------------- | |
2150 | |
2151 procedure Build_Offset_To_Top_Function (Iface_Comp : Entity_Id) is | |
2152 Body_Node : Node_Id; | |
2153 Func_Id : Entity_Id; | |
2154 Spec_Node : Node_Id; | |
2155 Acc_Type : Entity_Id; | |
2156 | |
2157 begin | |
2158 Func_Id := Make_Temporary (Loc, 'F'); | |
2159 Set_DT_Offset_To_Top_Func (Iface_Comp, Func_Id); | |
2160 | |
2161 -- Generate | |
2162 -- function Fxx (O : in Rec_Typ) return Storage_Offset; | |
2163 | |
2164 Spec_Node := New_Node (N_Function_Specification, Loc); | |
2165 Set_Defining_Unit_Name (Spec_Node, Func_Id); | |
2166 Set_Parameter_Specifications (Spec_Node, New_List ( | |
2167 Make_Parameter_Specification (Loc, | |
2168 Defining_Identifier => | |
2169 Make_Defining_Identifier (Loc, Name_uO), | |
2170 In_Present => True, | |
2171 Parameter_Type => | |
2172 New_Occurrence_Of (RTE (RE_Address), Loc)))); | |
2173 Set_Result_Definition (Spec_Node, | |
2174 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc)); | |
2175 | |
2176 -- Generate | |
2177 -- function Fxx (O : in Rec_Typ) return Storage_Offset is | |
2178 -- begin | |
2179 -- return O.Iface_Comp'Position; | |
2180 -- end Fxx; | |
2181 | |
2182 Body_Node := New_Node (N_Subprogram_Body, Loc); | |
2183 Set_Specification (Body_Node, Spec_Node); | |
2184 | |
2185 Acc_Type := Make_Temporary (Loc, 'T'); | |
2186 Set_Declarations (Body_Node, New_List ( | |
2187 Make_Full_Type_Declaration (Loc, | |
2188 Defining_Identifier => Acc_Type, | |
2189 Type_Definition => | |
2190 Make_Access_To_Object_Definition (Loc, | |
2191 All_Present => True, | |
2192 Null_Exclusion_Present => False, | |
2193 Constant_Present => False, | |
2194 Subtype_Indication => | |
2195 New_Occurrence_Of (Rec_Type, Loc))))); | |
2196 | |
2197 Set_Handled_Statement_Sequence (Body_Node, | |
2198 Make_Handled_Sequence_Of_Statements (Loc, | |
2199 Statements => New_List ( | |
2200 Make_Simple_Return_Statement (Loc, | |
2201 Expression => | |
2202 Make_Attribute_Reference (Loc, | |
2203 Prefix => | |
2204 Make_Selected_Component (Loc, | |
2205 Prefix => | |
2206 Unchecked_Convert_To (Acc_Type, | |
2207 Make_Identifier (Loc, Name_uO)), | |
2208 Selector_Name => | |
2209 New_Occurrence_Of (Iface_Comp, Loc)), | |
2210 Attribute_Name => Name_Position))))); | |
2211 | |
2212 Set_Ekind (Func_Id, E_Function); | |
2213 Set_Mechanism (Func_Id, Default_Mechanism); | |
2214 Set_Is_Internal (Func_Id, True); | |
2215 | |
2216 if not Debug_Generated_Code then | |
2217 Set_Debug_Info_Off (Func_Id); | |
2218 end if; | |
2219 | |
2220 Analyze (Body_Node); | |
2221 | |
2222 Append_Freeze_Action (Rec_Type, Body_Node); | |
2223 end Build_Offset_To_Top_Function; | |
2224 | |
2225 -- Local variables | |
2226 | |
2227 Iface_Comp : Node_Id; | |
2228 Iface_Comp_Elmt : Elmt_Id; | |
2229 Ifaces_Comp_List : Elist_Id; | |
2230 | |
2231 -- Start of processing for Build_Offset_To_Top_Functions | |
2232 | |
2233 begin | |
2234 -- Offset_To_Top_Functions are built only for derivations of types | |
2235 -- with discriminants that cover interface types. | |
2236 -- Nothing is needed either in case of virtual targets, since | |
2237 -- interfaces are handled directly by the target. | |
2238 | |
2239 if not Is_Tagged_Type (Rec_Type) | |
2240 or else Etype (Rec_Type) = Rec_Type | |
2241 or else not Has_Discriminants (Etype (Rec_Type)) | |
2242 or else not Tagged_Type_Expansion | |
2243 then | |
2244 return; | |
2245 end if; | |
2246 | |
2247 Collect_Interface_Components (Rec_Type, Ifaces_Comp_List); | |
2248 | |
2249 -- For each interface type with secondary dispatch table we generate | |
2250 -- the Offset_To_Top_Functions (required to displace the pointer in | |
2251 -- interface conversions) | |
2252 | |
2253 Iface_Comp_Elmt := First_Elmt (Ifaces_Comp_List); | |
2254 while Present (Iface_Comp_Elmt) loop | |
2255 Iface_Comp := Node (Iface_Comp_Elmt); | |
2256 pragma Assert (Is_Interface (Related_Type (Iface_Comp))); | |
2257 | |
2258 -- If the interface is a parent of Rec_Type it shares the primary | |
2259 -- dispatch table and hence there is no need to build the function | |
2260 | |
2261 if not Is_Ancestor (Related_Type (Iface_Comp), Rec_Type, | |
2262 Use_Full_View => True) | |
2263 then | |
2264 Build_Offset_To_Top_Function (Iface_Comp); | |
2265 end if; | |
2266 | |
2267 Next_Elmt (Iface_Comp_Elmt); | |
2268 end loop; | |
2269 end Build_Offset_To_Top_Functions; | |
2270 | |
2271 ------------------------------ | |
2272 -- Build_CPP_Init_Procedure -- | |
2273 ------------------------------ | |
2274 | |
2275 procedure Build_CPP_Init_Procedure is | |
2276 Body_Node : Node_Id; | |
2277 Body_Stmts : List_Id; | |
2278 Flag_Id : Entity_Id; | |
2279 Handled_Stmt_Node : Node_Id; | |
2280 Init_Tags_List : List_Id; | |
2281 Proc_Id : Entity_Id; | |
2282 Proc_Spec_Node : Node_Id; | |
2283 | |
2284 begin | |
2285 -- Check cases requiring no IC routine | |
2286 | |
2287 if not Is_CPP_Class (Root_Type (Rec_Type)) | |
2288 or else Is_CPP_Class (Rec_Type) | |
2289 or else CPP_Num_Prims (Rec_Type) = 0 | |
2290 or else not Tagged_Type_Expansion | |
2291 or else No_Run_Time_Mode | |
2292 then | |
2293 return; | |
2294 end if; | |
2295 | |
2296 -- Generate: | |
2297 | |
2298 -- Flag : Boolean := False; | |
2299 -- | |
2300 -- procedure Typ_IC is | |
2301 -- begin | |
2302 -- if not Flag then | |
2303 -- Copy C++ dispatch table slots from parent | |
2304 -- Update C++ slots of overridden primitives | |
2305 -- end if; | |
2306 -- end; | |
2307 | |
2308 Flag_Id := Make_Temporary (Loc, 'F'); | |
2309 | |
2310 Append_Freeze_Action (Rec_Type, | |
2311 Make_Object_Declaration (Loc, | |
2312 Defining_Identifier => Flag_Id, | |
2313 Object_Definition => | |
2314 New_Occurrence_Of (Standard_Boolean, Loc), | |
2315 Expression => | |
2316 New_Occurrence_Of (Standard_True, Loc))); | |
2317 | |
2318 Body_Stmts := New_List; | |
2319 Body_Node := New_Node (N_Subprogram_Body, Loc); | |
2320 | |
2321 Proc_Spec_Node := New_Node (N_Procedure_Specification, Loc); | |
2322 | |
2323 Proc_Id := | |
2324 Make_Defining_Identifier (Loc, | |
2325 Chars => Make_TSS_Name (Rec_Type, TSS_CPP_Init_Proc)); | |
2326 | |
2327 Set_Ekind (Proc_Id, E_Procedure); | |
2328 Set_Is_Internal (Proc_Id); | |
2329 | |
2330 Set_Defining_Unit_Name (Proc_Spec_Node, Proc_Id); | |
2331 | |
2332 Set_Parameter_Specifications (Proc_Spec_Node, New_List); | |
2333 Set_Specification (Body_Node, Proc_Spec_Node); | |
2334 Set_Declarations (Body_Node, New_List); | |
2335 | |
2336 Init_Tags_List := Build_Inherit_CPP_Prims (Rec_Type); | |
2337 | |
2338 Append_To (Init_Tags_List, | |
2339 Make_Assignment_Statement (Loc, | |
2340 Name => | |
2341 New_Occurrence_Of (Flag_Id, Loc), | |
2342 Expression => | |
2343 New_Occurrence_Of (Standard_False, Loc))); | |
2344 | |
2345 Append_To (Body_Stmts, | |
2346 Make_If_Statement (Loc, | |
2347 Condition => New_Occurrence_Of (Flag_Id, Loc), | |
2348 Then_Statements => Init_Tags_List)); | |
2349 | |
2350 Handled_Stmt_Node := | |
2351 New_Node (N_Handled_Sequence_Of_Statements, Loc); | |
2352 Set_Statements (Handled_Stmt_Node, Body_Stmts); | |
2353 Set_Exception_Handlers (Handled_Stmt_Node, No_List); | |
2354 Set_Handled_Statement_Sequence (Body_Node, Handled_Stmt_Node); | |
2355 | |
2356 if not Debug_Generated_Code then | |
2357 Set_Debug_Info_Off (Proc_Id); | |
2358 end if; | |
2359 | |
2360 -- Associate CPP_Init_Proc with type | |
2361 | |
2362 Set_Init_Proc (Rec_Type, Proc_Id); | |
2363 end Build_CPP_Init_Procedure; | |
2364 | |
2365 -------------------------- | |
2366 -- Build_Init_Procedure -- | |
2367 -------------------------- | |
2368 | |
2369 procedure Build_Init_Procedure is | |
2370 Body_Stmts : List_Id; | |
2371 Body_Node : Node_Id; | |
2372 Handled_Stmt_Node : Node_Id; | |
2373 Init_Tags_List : List_Id; | |
2374 Parameters : List_Id; | |
2375 Proc_Spec_Node : Node_Id; | |
2376 Record_Extension_Node : Node_Id; | |
2377 | |
2378 begin | |
2379 Body_Stmts := New_List; | |
2380 Body_Node := New_Node (N_Subprogram_Body, Loc); | |
2381 Set_Ekind (Proc_Id, E_Procedure); | |
2382 | |
2383 Proc_Spec_Node := New_Node (N_Procedure_Specification, Loc); | |
2384 Set_Defining_Unit_Name (Proc_Spec_Node, Proc_Id); | |
2385 | |
2386 Parameters := Init_Formals (Rec_Type); | |
2387 Append_List_To (Parameters, | |
2388 Build_Discriminant_Formals (Rec_Type, True)); | |
2389 | |
2390 -- For tagged types, we add a flag to indicate whether the routine | |
2391 -- is called to initialize a parent component in the init_proc of | |
2392 -- a type extension. If the flag is false, we do not set the tag | |
2393 -- because it has been set already in the extension. | |
2394 | |
2395 if Is_Tagged_Type (Rec_Type) then | |
2396 Set_Tag := Make_Temporary (Loc, 'P'); | |
2397 | |
2398 Append_To (Parameters, | |
2399 Make_Parameter_Specification (Loc, | |
2400 Defining_Identifier => Set_Tag, | |
2401 Parameter_Type => | |
2402 New_Occurrence_Of (Standard_Boolean, Loc), | |
2403 Expression => | |
2404 New_Occurrence_Of (Standard_True, Loc))); | |
2405 end if; | |
2406 | |
2407 Set_Parameter_Specifications (Proc_Spec_Node, Parameters); | |
2408 Set_Specification (Body_Node, Proc_Spec_Node); | |
2409 Set_Declarations (Body_Node, Decls); | |
2410 | |
2411 -- N is a Derived_Type_Definition that renames the parameters of the | |
2412 -- ancestor type. We initialize it by expanding our discriminants and | |
2413 -- call the ancestor _init_proc with a type-converted object. | |
2414 | |
2415 if Parent_Subtype_Renaming_Discrims then | |
2416 Append_List_To (Body_Stmts, Build_Init_Call_Thru (Parameters)); | |
2417 | |
2418 elsif Nkind (Type_Definition (N)) = N_Record_Definition then | |
2419 Build_Discriminant_Assignments (Body_Stmts); | |
2420 | |
2421 if not Null_Present (Type_Definition (N)) then | |
2422 Append_List_To (Body_Stmts, | |
2423 Build_Init_Statements (Component_List (Type_Definition (N)))); | |
2424 end if; | |
2425 | |
2426 -- N is a Derived_Type_Definition with a possible non-empty | |
2427 -- extension. The initialization of a type extension consists in the | |
2428 -- initialization of the components in the extension. | |
2429 | |
2430 else | |
2431 Build_Discriminant_Assignments (Body_Stmts); | |
2432 | |
2433 Record_Extension_Node := | |
2434 Record_Extension_Part (Type_Definition (N)); | |
2435 | |
2436 if not Null_Present (Record_Extension_Node) then | |
2437 declare | |
2438 Stmts : constant List_Id := | |
2439 Build_Init_Statements ( | |
2440 Component_List (Record_Extension_Node)); | |
2441 | |
2442 begin | |
2443 -- The parent field must be initialized first because the | |
2444 -- offset of the new discriminants may depend on it. This is | |
2445 -- not needed if the parent is an interface type because in | |
2446 -- such case the initialization of the _parent field was not | |
2447 -- generated. | |
2448 | |
2449 if not Is_Interface (Etype (Rec_Ent)) then | |
2450 declare | |
2451 Parent_IP : constant Name_Id := | |
2452 Make_Init_Proc_Name (Etype (Rec_Ent)); | |
2453 Stmt : Node_Id; | |
2454 IP_Call : Node_Id; | |
2455 IP_Stmts : List_Id; | |
2456 | |
2457 begin | |
2458 -- Look for a call to the parent IP at the beginning | |
2459 -- of Stmts associated with the record extension | |
2460 | |
2461 Stmt := First (Stmts); | |
2462 IP_Call := Empty; | |
2463 while Present (Stmt) loop | |
2464 if Nkind (Stmt) = N_Procedure_Call_Statement | |
2465 and then Chars (Name (Stmt)) = Parent_IP | |
2466 then | |
2467 IP_Call := Stmt; | |
2468 exit; | |
2469 end if; | |
2470 | |
2471 Next (Stmt); | |
2472 end loop; | |
2473 | |
2474 -- If found then move it to the beginning of the | |
2475 -- statements of this IP routine | |
2476 | |
2477 if Present (IP_Call) then | |
2478 IP_Stmts := New_List; | |
2479 loop | |
2480 Stmt := Remove_Head (Stmts); | |
2481 Append_To (IP_Stmts, Stmt); | |
2482 exit when Stmt = IP_Call; | |
2483 end loop; | |
2484 | |
2485 Prepend_List_To (Body_Stmts, IP_Stmts); | |
2486 end if; | |
2487 end; | |
2488 end if; | |
2489 | |
2490 Append_List_To (Body_Stmts, Stmts); | |
2491 end; | |
2492 end if; | |
2493 end if; | |
2494 | |
2495 -- Add here the assignment to instantiate the Tag | |
2496 | |
2497 -- The assignment corresponds to the code: | |
2498 | |
2499 -- _Init._Tag := Typ'Tag; | |
2500 | |
2501 -- Suppress the tag assignment when not Tagged_Type_Expansion because | |
2502 -- tags are represented implicitly in objects. It is also suppressed | |
2503 -- in case of CPP_Class types because in this case the tag is | |
2504 -- initialized in the C++ side. | |
2505 | |
2506 if Is_Tagged_Type (Rec_Type) | |
2507 and then Tagged_Type_Expansion | |
2508 and then not No_Run_Time_Mode | |
2509 then | |
2510 -- Case 1: Ada tagged types with no CPP ancestor. Set the tags of | |
2511 -- the actual object and invoke the IP of the parent (in this | |
2512 -- order). The tag must be initialized before the call to the IP | |
2513 -- of the parent and the assignments to other components because | |
2514 -- the initial value of the components may depend on the tag (eg. | |
2515 -- through a dispatching operation on an access to the current | |
2516 -- type). The tag assignment is not done when initializing the | |
2517 -- parent component of a type extension, because in that case the | |
2518 -- tag is set in the extension. | |
2519 | |
2520 if not Is_CPP_Class (Root_Type (Rec_Type)) then | |
2521 | |
2522 -- Initialize the primary tag component | |
2523 | |
2524 Init_Tags_List := New_List ( | |
2525 Make_Assignment_Statement (Loc, | |
2526 Name => | |
2527 Make_Selected_Component (Loc, | |
2528 Prefix => Make_Identifier (Loc, Name_uInit), | |
2529 Selector_Name => | |
2530 New_Occurrence_Of | |
2531 (First_Tag_Component (Rec_Type), Loc)), | |
2532 Expression => | |
2533 New_Occurrence_Of | |
2534 (Node | |
2535 (First_Elmt (Access_Disp_Table (Rec_Type))), Loc))); | |
2536 | |
2537 -- Ada 2005 (AI-251): Initialize the secondary tags components | |
2538 -- located at fixed positions (tags whose position depends on | |
2539 -- variable size components are initialized later ---see below) | |
2540 | |
2541 if Ada_Version >= Ada_2005 | |
2542 and then not Is_Interface (Rec_Type) | |
2543 and then Has_Interfaces (Rec_Type) | |
2544 then | |
2545 declare | |
2546 Elab_Sec_DT_Stmts_List : constant List_Id := New_List; | |
2547 | |
2548 begin | |
2549 Init_Secondary_Tags | |
2550 (Typ => Rec_Type, | |
2551 Target => Make_Identifier (Loc, Name_uInit), | |
2552 Init_Tags_List => Init_Tags_List, | |
2553 Stmts_List => Elab_Sec_DT_Stmts_List, | |
2554 Fixed_Comps => True, | |
2555 Variable_Comps => False); | |
2556 | |
2557 Append_To (Elab_Sec_DT_Stmts_List, | |
2558 Make_Assignment_Statement (Loc, | |
2559 Name => | |
2560 New_Occurrence_Of | |
2561 (Access_Disp_Table_Elab_Flag (Rec_Type), Loc), | |
2562 Expression => | |
2563 New_Occurrence_Of (Standard_False, Loc))); | |
2564 | |
2565 Prepend_List_To (Body_Stmts, New_List ( | |
2566 Make_If_Statement (Loc, | |
2567 Condition => New_Occurrence_Of (Set_Tag, Loc), | |
2568 Then_Statements => Init_Tags_List), | |
2569 | |
2570 Make_If_Statement (Loc, | |
2571 Condition => | |
2572 New_Occurrence_Of | |
2573 (Access_Disp_Table_Elab_Flag (Rec_Type), Loc), | |
2574 Then_Statements => Elab_Sec_DT_Stmts_List))); | |
2575 end; | |
2576 else | |
2577 Prepend_To (Body_Stmts, | |
2578 Make_If_Statement (Loc, | |
2579 Condition => New_Occurrence_Of (Set_Tag, Loc), | |
2580 Then_Statements => Init_Tags_List)); | |
2581 end if; | |
2582 | |
2583 -- Case 2: CPP type. The imported C++ constructor takes care of | |
2584 -- tags initialization. No action needed here because the IP | |
2585 -- is built by Set_CPP_Constructors; in this case the IP is a | |
2586 -- wrapper that invokes the C++ constructor and copies the C++ | |
2587 -- tags locally. Done to inherit the C++ slots in Ada derivations | |
2588 -- (see case 3). | |
2589 | |
2590 elsif Is_CPP_Class (Rec_Type) then | |
2591 pragma Assert (False); | |
2592 null; | |
2593 | |
2594 -- Case 3: Combined hierarchy containing C++ types and Ada tagged | |
2595 -- type derivations. Derivations of imported C++ classes add a | |
2596 -- complication, because we cannot inhibit tag setting in the | |
2597 -- constructor for the parent. Hence we initialize the tag after | |
2598 -- the call to the parent IP (that is, in reverse order compared | |
2599 -- with pure Ada hierarchies ---see comment on case 1). | |
2600 | |
2601 else | |
2602 -- Initialize the primary tag | |
2603 | |
2604 Init_Tags_List := New_List ( | |
2605 Make_Assignment_Statement (Loc, | |
2606 Name => | |
2607 Make_Selected_Component (Loc, | |
2608 Prefix => Make_Identifier (Loc, Name_uInit), | |
2609 Selector_Name => | |
2610 New_Occurrence_Of | |
2611 (First_Tag_Component (Rec_Type), Loc)), | |
2612 Expression => | |
2613 New_Occurrence_Of | |
2614 (Node | |
2615 (First_Elmt (Access_Disp_Table (Rec_Type))), Loc))); | |
2616 | |
2617 -- Ada 2005 (AI-251): Initialize the secondary tags components | |
2618 -- located at fixed positions (tags whose position depends on | |
2619 -- variable size components are initialized later ---see below) | |
2620 | |
2621 if Ada_Version >= Ada_2005 | |
2622 and then not Is_Interface (Rec_Type) | |
2623 and then Has_Interfaces (Rec_Type) | |
2624 then | |
2625 Init_Secondary_Tags | |
2626 (Typ => Rec_Type, | |
2627 Target => Make_Identifier (Loc, Name_uInit), | |
2628 Init_Tags_List => Init_Tags_List, | |
2629 Stmts_List => Init_Tags_List, | |
2630 Fixed_Comps => True, | |
2631 Variable_Comps => False); | |
2632 end if; | |
2633 | |
2634 -- Initialize the tag component after invocation of parent IP. | |
2635 | |
2636 -- Generate: | |
2637 -- parent_IP(_init.parent); // Invokes the C++ constructor | |
2638 -- [ typIC; ] // Inherit C++ slots from parent | |
2639 -- init_tags | |
2640 | |
2641 declare | |
2642 Ins_Nod : Node_Id; | |
2643 | |
2644 begin | |
2645 -- Search for the call to the IP of the parent. We assume | |
2646 -- that the first init_proc call is for the parent. | |
2647 | |
2648 Ins_Nod := First (Body_Stmts); | |
2649 while Present (Next (Ins_Nod)) | |
2650 and then (Nkind (Ins_Nod) /= N_Procedure_Call_Statement | |
2651 or else not Is_Init_Proc (Name (Ins_Nod))) | |
2652 loop | |
2653 Next (Ins_Nod); | |
2654 end loop; | |
2655 | |
2656 -- The IC routine copies the inherited slots of the C+ part | |
2657 -- of the dispatch table from the parent and updates the | |
2658 -- overridden C++ slots. | |
2659 | |
2660 if CPP_Num_Prims (Rec_Type) > 0 then | |
2661 declare | |
2662 Init_DT : Entity_Id; | |
2663 New_Nod : Node_Id; | |
2664 | |
2665 begin | |
2666 Init_DT := CPP_Init_Proc (Rec_Type); | |
2667 pragma Assert (Present (Init_DT)); | |
2668 | |
2669 New_Nod := | |
2670 Make_Procedure_Call_Statement (Loc, | |
2671 New_Occurrence_Of (Init_DT, Loc)); | |
2672 Insert_After (Ins_Nod, New_Nod); | |
2673 | |
2674 -- Update location of init tag statements | |
2675 | |
2676 Ins_Nod := New_Nod; | |
2677 end; | |
2678 end if; | |
2679 | |
2680 Insert_List_After (Ins_Nod, Init_Tags_List); | |
2681 end; | |
2682 end if; | |
2683 | |
2684 -- Ada 2005 (AI-251): Initialize the secondary tag components | |
2685 -- located at variable positions. We delay the generation of this | |
2686 -- code until here because the value of the attribute 'Position | |
2687 -- applied to variable size components of the parent type that | |
2688 -- depend on discriminants is only safely read at runtime after | |
2689 -- the parent components have been initialized. | |
2690 | |
2691 if Ada_Version >= Ada_2005 | |
2692 and then not Is_Interface (Rec_Type) | |
2693 and then Has_Interfaces (Rec_Type) | |
2694 and then Has_Discriminants (Etype (Rec_Type)) | |
2695 and then Is_Variable_Size_Record (Etype (Rec_Type)) | |
2696 then | |
2697 Init_Tags_List := New_List; | |
2698 | |
2699 Init_Secondary_Tags | |
2700 (Typ => Rec_Type, | |
2701 Target => Make_Identifier (Loc, Name_uInit), | |
2702 Init_Tags_List => Init_Tags_List, | |
2703 Stmts_List => Init_Tags_List, | |
2704 Fixed_Comps => False, | |
2705 Variable_Comps => True); | |
2706 | |
2707 if Is_Non_Empty_List (Init_Tags_List) then | |
2708 Append_List_To (Body_Stmts, Init_Tags_List); | |
2709 end if; | |
2710 end if; | |
2711 end if; | |
2712 | |
2713 Handled_Stmt_Node := New_Node (N_Handled_Sequence_Of_Statements, Loc); | |
2714 Set_Statements (Handled_Stmt_Node, Body_Stmts); | |
2715 | |
2716 -- Generate: | |
2717 -- Deep_Finalize (_init, C1, ..., CN); | |
2718 -- raise; | |
2719 | |
2720 if Counter > 0 | |
2721 and then Needs_Finalization (Rec_Type) | |
2722 and then not Is_Abstract_Type (Rec_Type) | |
2723 and then not Restriction_Active (No_Exception_Propagation) | |
2724 then | |
2725 declare | |
2726 DF_Id : Entity_Id; | |
2727 | |
2728 begin | |
2729 -- Create a local version of Deep_Finalize which has indication | |
2730 -- of partial initialization state. | |
2731 | |
2732 DF_Id := | |
2733 Make_Defining_Identifier (Loc, | |
2734 Chars => New_External_Name (Name_uFinalizer)); | |
2735 | |
2736 Append_To (Decls, Make_Local_Deep_Finalize (Rec_Type, DF_Id)); | |
2737 | |
2738 Set_Exception_Handlers (Handled_Stmt_Node, New_List ( | |
2739 Make_Exception_Handler (Loc, | |
2740 Exception_Choices => New_List ( | |
2741 Make_Others_Choice (Loc)), | |
2742 Statements => New_List ( | |
2743 Make_Procedure_Call_Statement (Loc, | |
2744 Name => | |
2745 New_Occurrence_Of (DF_Id, Loc), | |
2746 Parameter_Associations => New_List ( | |
2747 Make_Identifier (Loc, Name_uInit), | |
2748 New_Occurrence_Of (Standard_False, Loc))), | |
2749 | |
2750 Make_Raise_Statement (Loc))))); | |
2751 end; | |
2752 else | |
2753 Set_Exception_Handlers (Handled_Stmt_Node, No_List); | |
2754 end if; | |
2755 | |
2756 Set_Handled_Statement_Sequence (Body_Node, Handled_Stmt_Node); | |
2757 | |
2758 if not Debug_Generated_Code then | |
2759 Set_Debug_Info_Off (Proc_Id); | |
2760 end if; | |
2761 | |
2762 -- Associate Init_Proc with type, and determine if the procedure | |
2763 -- is null (happens because of the Initialize_Scalars pragma case, | |
2764 -- where we have to generate a null procedure in case it is called | |
2765 -- by a client with Initialize_Scalars set). Such procedures have | |
2766 -- to be generated, but do not have to be called, so we mark them | |
2767 -- as null to suppress the call. | |
2768 | |
2769 Set_Init_Proc (Rec_Type, Proc_Id); | |
2770 | |
2771 if List_Length (Body_Stmts) = 1 | |
2772 | |
2773 -- We must skip SCIL nodes because they may have been added to this | |
2774 -- list by Insert_Actions. | |
2775 | |
2776 and then Nkind (First_Non_SCIL_Node (Body_Stmts)) = N_Null_Statement | |
2777 then | |
2778 Set_Is_Null_Init_Proc (Proc_Id); | |
2779 end if; | |
2780 end Build_Init_Procedure; | |
2781 | |
2782 --------------------------- | |
2783 -- Build_Init_Statements -- | |
2784 --------------------------- | |
2785 | |
2786 function Build_Init_Statements (Comp_List : Node_Id) return List_Id is | |
2787 Checks : constant List_Id := New_List; | |
2788 Actions : List_Id := No_List; | |
2789 Counter_Id : Entity_Id := Empty; | |
2790 Comp_Loc : Source_Ptr; | |
2791 Decl : Node_Id; | |
2792 Has_POC : Boolean; | |
2793 Id : Entity_Id; | |
2794 Parent_Stmts : List_Id; | |
2795 Stmts : List_Id; | |
2796 Typ : Entity_Id; | |
2797 | |
2798 procedure Increment_Counter (Loc : Source_Ptr); | |
2799 -- Generate an "increment by one" statement for the current counter | |
2800 -- and append it to the list Stmts. | |
2801 | |
2802 procedure Make_Counter (Loc : Source_Ptr); | |
2803 -- Create a new counter for the current component list. The routine | |
2804 -- creates a new defining Id, adds an object declaration and sets | |
2805 -- the Id generator for the next variant. | |
2806 | |
2807 ----------------------- | |
2808 -- Increment_Counter -- | |
2809 ----------------------- | |
2810 | |
2811 procedure Increment_Counter (Loc : Source_Ptr) is | |
2812 begin | |
2813 -- Generate: | |
2814 -- Counter := Counter + 1; | |
2815 | |
2816 Append_To (Stmts, | |
2817 Make_Assignment_Statement (Loc, | |
2818 Name => New_Occurrence_Of (Counter_Id, Loc), | |
2819 Expression => | |
2820 Make_Op_Add (Loc, | |
2821 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), | |
2822 Right_Opnd => Make_Integer_Literal (Loc, 1)))); | |
2823 end Increment_Counter; | |
2824 | |
2825 ------------------ | |
2826 -- Make_Counter -- | |
2827 ------------------ | |
2828 | |
2829 procedure Make_Counter (Loc : Source_Ptr) is | |
2830 begin | |
2831 -- Increment the Id generator | |
2832 | |
2833 Counter := Counter + 1; | |
2834 | |
2835 -- Create the entity and declaration | |
2836 | |
2837 Counter_Id := | |
2838 Make_Defining_Identifier (Loc, | |
2839 Chars => New_External_Name ('C', Counter)); | |
2840 | |
2841 -- Generate: | |
2842 -- Cnn : Integer := 0; | |
2843 | |
2844 Append_To (Decls, | |
2845 Make_Object_Declaration (Loc, | |
2846 Defining_Identifier => Counter_Id, | |
2847 Object_Definition => | |
2848 New_Occurrence_Of (Standard_Integer, Loc), | |
2849 Expression => | |
2850 Make_Integer_Literal (Loc, 0))); | |
2851 end Make_Counter; | |
2852 | |
2853 -- Start of processing for Build_Init_Statements | |
2854 | |
2855 begin | |
2856 if Null_Present (Comp_List) then | |
2857 return New_List (Make_Null_Statement (Loc)); | |
2858 end if; | |
2859 | |
2860 Parent_Stmts := New_List; | |
2861 Stmts := New_List; | |
2862 | |
2863 -- Loop through visible declarations of task types and protected | |
2864 -- types moving any expanded code from the spec to the body of the | |
2865 -- init procedure. | |
2866 | |
2867 if Is_Task_Record_Type (Rec_Type) | |
2868 or else Is_Protected_Record_Type (Rec_Type) | |
2869 then | |
2870 declare | |
2871 Decl : constant Node_Id := | |
2872 Parent (Corresponding_Concurrent_Type (Rec_Type)); | |
2873 Def : Node_Id; | |
2874 N1 : Node_Id; | |
2875 N2 : Node_Id; | |
2876 | |
2877 begin | |
2878 if Is_Task_Record_Type (Rec_Type) then | |
2879 Def := Task_Definition (Decl); | |
2880 else | |
2881 Def := Protected_Definition (Decl); | |
2882 end if; | |
2883 | |
2884 if Present (Def) then | |
2885 N1 := First (Visible_Declarations (Def)); | |
2886 while Present (N1) loop | |
2887 N2 := N1; | |
2888 N1 := Next (N1); | |
2889 | |
2890 if Nkind (N2) in N_Statement_Other_Than_Procedure_Call | |
2891 or else Nkind (N2) in N_Raise_xxx_Error | |
2892 or else Nkind (N2) = N_Procedure_Call_Statement | |
2893 then | |
2894 Append_To (Stmts, | |
2895 New_Copy_Tree (N2, New_Scope => Proc_Id)); | |
2896 Rewrite (N2, Make_Null_Statement (Sloc (N2))); | |
2897 Analyze (N2); | |
2898 end if; | |
2899 end loop; | |
2900 end if; | |
2901 end; | |
2902 end if; | |
2903 | |
2904 -- Loop through components, skipping pragmas, in 2 steps. The first | |
2905 -- step deals with regular components. The second step deals with | |
2906 -- components that have per object constraints and no explicit | |
2907 -- initialization. | |
2908 | |
2909 Has_POC := False; | |
2910 | |
2911 -- First pass : regular components | |
2912 | |
2913 Decl := First_Non_Pragma (Component_Items (Comp_List)); | |
2914 while Present (Decl) loop | |
2915 Comp_Loc := Sloc (Decl); | |
2916 Build_Record_Checks | |
2917 (Subtype_Indication (Component_Definition (Decl)), Checks); | |
2918 | |
2919 Id := Defining_Identifier (Decl); | |
2920 Typ := Etype (Id); | |
2921 | |
2922 -- Leave any processing of per-object constrained component for | |
2923 -- the second pass. | |
2924 | |
2925 if Has_Access_Constraint (Id) and then No (Expression (Decl)) then | |
2926 Has_POC := True; | |
2927 | |
2928 -- Regular component cases | |
2929 | |
2930 else | |
2931 -- In the context of the init proc, references to discriminants | |
2932 -- resolve to denote the discriminals: this is where we can | |
2933 -- freeze discriminant dependent component subtypes. | |
2934 | |
2935 if not Is_Frozen (Typ) then | |
2936 Append_List_To (Stmts, Freeze_Entity (Typ, N)); | |
2937 end if; | |
2938 | |
2939 -- Explicit initialization | |
2940 | |
2941 if Present (Expression (Decl)) then | |
2942 if Is_CPP_Constructor_Call (Expression (Decl)) then | |
2943 Actions := | |
2944 Build_Initialization_Call | |
2945 (Comp_Loc, | |
2946 Id_Ref => | |
2947 Make_Selected_Component (Comp_Loc, | |
2948 Prefix => | |
2949 Make_Identifier (Comp_Loc, Name_uInit), | |
2950 Selector_Name => | |
2951 New_Occurrence_Of (Id, Comp_Loc)), | |
2952 Typ => Typ, | |
2953 In_Init_Proc => True, | |
2954 Enclos_Type => Rec_Type, | |
2955 Discr_Map => Discr_Map, | |
2956 Constructor_Ref => Expression (Decl)); | |
2957 else | |
2958 Actions := Build_Assignment (Id, Expression (Decl)); | |
2959 end if; | |
2960 | |
2961 -- CPU, Dispatching_Domain, Priority, and Secondary_Stack_Size | |
2962 -- components are filled in with the corresponding rep-item | |
2963 -- expression of the concurrent type (if any). | |
2964 | |
2965 elsif Ekind (Scope (Id)) = E_Record_Type | |
2966 and then Present (Corresponding_Concurrent_Type (Scope (Id))) | |
2967 and then Nam_In (Chars (Id), Name_uCPU, | |
2968 Name_uDispatching_Domain, | |
2969 Name_uPriority, | |
2970 Name_uSecondary_Stack_Size) | |
2971 then | |
2972 declare | |
2973 Exp : Node_Id; | |
2974 Nam : Name_Id; | |
2975 pragma Warnings (Off, Nam); | |
2976 Ritem : Node_Id; | |
2977 | |
2978 begin | |
2979 if Chars (Id) = Name_uCPU then | |
2980 Nam := Name_CPU; | |
2981 | |
2982 elsif Chars (Id) = Name_uDispatching_Domain then | |
2983 Nam := Name_Dispatching_Domain; | |
2984 | |
2985 elsif Chars (Id) = Name_uPriority then | |
2986 Nam := Name_Priority; | |
2987 | |
2988 elsif Chars (Id) = Name_uSecondary_Stack_Size then | |
2989 Nam := Name_Secondary_Stack_Size; | |
2990 end if; | |
2991 | |
2992 -- Get the Rep Item (aspect specification, attribute | |
2993 -- definition clause or pragma) of the corresponding | |
2994 -- concurrent type. | |
2995 | |
2996 Ritem := | |
2997 Get_Rep_Item | |
2998 (Corresponding_Concurrent_Type (Scope (Id)), | |
2999 Nam, | |
3000 Check_Parents => False); | |
3001 | |
3002 if Present (Ritem) then | |
3003 | |
3004 -- Pragma case | |
3005 | |
3006 if Nkind (Ritem) = N_Pragma then | |
3007 Exp := First (Pragma_Argument_Associations (Ritem)); | |
3008 | |
3009 if Nkind (Exp) = N_Pragma_Argument_Association then | |
3010 Exp := Expression (Exp); | |
3011 end if; | |
3012 | |
3013 -- Conversion for Priority expression | |
3014 | |
3015 if Nam = Name_Priority then | |
3016 if Pragma_Name (Ritem) = Name_Priority | |
3017 and then not GNAT_Mode | |
3018 then | |
3019 Exp := Convert_To (RTE (RE_Priority), Exp); | |
3020 else | |
3021 Exp := | |
3022 Convert_To (RTE (RE_Any_Priority), Exp); | |
3023 end if; | |
3024 end if; | |
3025 | |
3026 -- Aspect/Attribute definition clause case | |
3027 | |
3028 else | |
3029 Exp := Expression (Ritem); | |
3030 | |
3031 -- Conversion for Priority expression | |
3032 | |
3033 if Nam = Name_Priority then | |
3034 if Chars (Ritem) = Name_Priority | |
3035 and then not GNAT_Mode | |
3036 then | |
3037 Exp := Convert_To (RTE (RE_Priority), Exp); | |
3038 else | |
3039 Exp := | |
3040 Convert_To (RTE (RE_Any_Priority), Exp); | |
3041 end if; | |
3042 end if; | |
3043 end if; | |
3044 | |
3045 -- Conversion for Dispatching_Domain value | |
3046 | |
3047 if Nam = Name_Dispatching_Domain then | |
3048 Exp := | |
3049 Unchecked_Convert_To | |
3050 (RTE (RE_Dispatching_Domain_Access), Exp); | |
3051 | |
3052 -- Conversion for Secondary_Stack_Size value | |
3053 | |
3054 elsif Nam = Name_Secondary_Stack_Size then | |
3055 Exp := Convert_To (RTE (RE_Size_Type), Exp); | |
3056 end if; | |
3057 | |
3058 Actions := Build_Assignment (Id, Exp); | |
3059 | |
3060 -- Nothing needed if no Rep Item | |
3061 | |
3062 else | |
3063 Actions := No_List; | |
3064 end if; | |
3065 end; | |
3066 | |
3067 -- Composite component with its own Init_Proc | |
3068 | |
3069 elsif not Is_Interface (Typ) | |
3070 and then Has_Non_Null_Base_Init_Proc (Typ) | |
3071 then | |
3072 Actions := | |
3073 Build_Initialization_Call | |
3074 (Comp_Loc, | |
3075 Make_Selected_Component (Comp_Loc, | |
3076 Prefix => | |
3077 Make_Identifier (Comp_Loc, Name_uInit), | |
3078 Selector_Name => New_Occurrence_Of (Id, Comp_Loc)), | |
3079 Typ, | |
3080 In_Init_Proc => True, | |
3081 Enclos_Type => Rec_Type, | |
3082 Discr_Map => Discr_Map); | |
3083 | |
3084 Clean_Task_Names (Typ, Proc_Id); | |
3085 | |
3086 -- Simple initialization | |
3087 | |
3088 elsif Component_Needs_Simple_Initialization (Typ) then | |
3089 Actions := | |
3090 Build_Assignment | |
3091 (Id, Get_Simple_Init_Val (Typ, N, Esize (Id))); | |
3092 | |
3093 -- Nothing needed for this case | |
3094 | |
3095 else | |
3096 Actions := No_List; | |
3097 end if; | |
3098 | |
3099 if Present (Checks) then | |
3100 if Chars (Id) = Name_uParent then | |
3101 Append_List_To (Parent_Stmts, Checks); | |
3102 else | |
3103 Append_List_To (Stmts, Checks); | |
3104 end if; | |
3105 end if; | |
3106 | |
3107 if Present (Actions) then | |
3108 if Chars (Id) = Name_uParent then | |
3109 Append_List_To (Parent_Stmts, Actions); | |
3110 | |
3111 else | |
3112 Append_List_To (Stmts, Actions); | |
3113 | |
3114 -- Preserve initialization state in the current counter | |
3115 | |
3116 if Needs_Finalization (Typ) then | |
3117 if No (Counter_Id) then | |
3118 Make_Counter (Comp_Loc); | |
3119 end if; | |
3120 | |
3121 Increment_Counter (Comp_Loc); | |
3122 end if; | |
3123 end if; | |
3124 end if; | |
3125 end if; | |
3126 | |
3127 Next_Non_Pragma (Decl); | |
3128 end loop; | |
3129 | |
3130 -- The parent field must be initialized first because variable | |
3131 -- size components of the parent affect the location of all the | |
3132 -- new components. | |
3133 | |
3134 Prepend_List_To (Stmts, Parent_Stmts); | |
3135 | |
3136 -- Set up tasks and protected object support. This needs to be done | |
3137 -- before any component with a per-object access discriminant | |
3138 -- constraint, or any variant part (which may contain such | |
3139 -- components) is initialized, because the initialization of these | |
3140 -- components may reference the enclosing concurrent object. | |
3141 | |
3142 -- For a task record type, add the task create call and calls to bind | |
3143 -- any interrupt (signal) entries. | |
3144 | |
3145 if Is_Task_Record_Type (Rec_Type) then | |
3146 | |
3147 -- In the case of the restricted run time the ATCB has already | |
3148 -- been preallocated. | |
3149 | |
3150 if Restricted_Profile then | |
3151 Append_To (Stmts, | |
3152 Make_Assignment_Statement (Loc, | |
3153 Name => | |
3154 Make_Selected_Component (Loc, | |
3155 Prefix => Make_Identifier (Loc, Name_uInit), | |
3156 Selector_Name => Make_Identifier (Loc, Name_uTask_Id)), | |
3157 Expression => | |
3158 Make_Attribute_Reference (Loc, | |
3159 Prefix => | |
3160 Make_Selected_Component (Loc, | |
3161 Prefix => Make_Identifier (Loc, Name_uInit), | |
3162 Selector_Name => Make_Identifier (Loc, Name_uATCB)), | |
3163 Attribute_Name => Name_Unchecked_Access))); | |
3164 end if; | |
3165 | |
3166 Append_To (Stmts, Make_Task_Create_Call (Rec_Type)); | |
3167 | |
3168 declare | |
3169 Task_Type : constant Entity_Id := | |
3170 Corresponding_Concurrent_Type (Rec_Type); | |
3171 Task_Decl : constant Node_Id := Parent (Task_Type); | |
3172 Task_Def : constant Node_Id := Task_Definition (Task_Decl); | |
3173 Decl_Loc : Source_Ptr; | |
3174 Ent : Entity_Id; | |
3175 Vis_Decl : Node_Id; | |
3176 | |
3177 begin | |
3178 if Present (Task_Def) then | |
3179 Vis_Decl := First (Visible_Declarations (Task_Def)); | |
3180 while Present (Vis_Decl) loop | |
3181 Decl_Loc := Sloc (Vis_Decl); | |
3182 | |
3183 if Nkind (Vis_Decl) = N_Attribute_Definition_Clause then | |
3184 if Get_Attribute_Id (Chars (Vis_Decl)) = | |
3185 Attribute_Address | |
3186 then | |
3187 Ent := Entity (Name (Vis_Decl)); | |
3188 | |
3189 if Ekind (Ent) = E_Entry then | |
3190 Append_To (Stmts, | |
3191 Make_Procedure_Call_Statement (Decl_Loc, | |
3192 Name => | |
3193 New_Occurrence_Of (RTE ( | |
3194 RE_Bind_Interrupt_To_Entry), Decl_Loc), | |
3195 Parameter_Associations => New_List ( | |
3196 Make_Selected_Component (Decl_Loc, | |
3197 Prefix => | |
3198 Make_Identifier (Decl_Loc, Name_uInit), | |
3199 Selector_Name => | |
3200 Make_Identifier | |
3201 (Decl_Loc, Name_uTask_Id)), | |
3202 Entry_Index_Expression | |
3203 (Decl_Loc, Ent, Empty, Task_Type), | |
3204 Expression (Vis_Decl)))); | |
3205 end if; | |
3206 end if; | |
3207 end if; | |
3208 | |
3209 Next (Vis_Decl); | |
3210 end loop; | |
3211 end if; | |
3212 end; | |
3213 end if; | |
3214 | |
3215 -- For a protected type, add statements generated by | |
3216 -- Make_Initialize_Protection. | |
3217 | |
3218 if Is_Protected_Record_Type (Rec_Type) then | |
3219 Append_List_To (Stmts, | |
3220 Make_Initialize_Protection (Rec_Type)); | |
3221 end if; | |
3222 | |
3223 -- Second pass: components with per-object constraints | |
3224 | |
3225 if Has_POC then | |
3226 Decl := First_Non_Pragma (Component_Items (Comp_List)); | |
3227 while Present (Decl) loop | |
3228 Comp_Loc := Sloc (Decl); | |
3229 Id := Defining_Identifier (Decl); | |
3230 Typ := Etype (Id); | |
3231 | |
3232 if Has_Access_Constraint (Id) | |
3233 and then No (Expression (Decl)) | |
3234 then | |
3235 if Has_Non_Null_Base_Init_Proc (Typ) then | |
3236 Append_List_To (Stmts, | |
3237 Build_Initialization_Call (Comp_Loc, | |
3238 Make_Selected_Component (Comp_Loc, | |
3239 Prefix => | |
3240 Make_Identifier (Comp_Loc, Name_uInit), | |
3241 Selector_Name => New_Occurrence_Of (Id, Comp_Loc)), | |
3242 Typ, | |
3243 In_Init_Proc => True, | |
3244 Enclos_Type => Rec_Type, | |
3245 Discr_Map => Discr_Map)); | |
3246 | |
3247 Clean_Task_Names (Typ, Proc_Id); | |
3248 | |
3249 -- Preserve initialization state in the current counter | |
3250 | |
3251 if Needs_Finalization (Typ) then | |
3252 if No (Counter_Id) then | |
3253 Make_Counter (Comp_Loc); | |
3254 end if; | |
3255 | |
3256 Increment_Counter (Comp_Loc); | |
3257 end if; | |
3258 | |
3259 elsif Component_Needs_Simple_Initialization (Typ) then | |
3260 Append_List_To (Stmts, | |
3261 Build_Assignment | |
3262 (Id, Get_Simple_Init_Val (Typ, N, Esize (Id)))); | |
3263 end if; | |
3264 end if; | |
3265 | |
3266 Next_Non_Pragma (Decl); | |
3267 end loop; | |
3268 end if; | |
3269 | |
3270 -- Process the variant part | |
3271 | |
3272 if Present (Variant_Part (Comp_List)) then | |
3273 declare | |
3274 Variant_Alts : constant List_Id := New_List; | |
3275 Var_Loc : Source_Ptr := No_Location; | |
3276 Variant : Node_Id; | |
3277 | |
3278 begin | |
3279 Variant := | |
3280 First_Non_Pragma (Variants (Variant_Part (Comp_List))); | |
3281 while Present (Variant) loop | |
3282 Var_Loc := Sloc (Variant); | |
3283 Append_To (Variant_Alts, | |
3284 Make_Case_Statement_Alternative (Var_Loc, | |
3285 Discrete_Choices => | |
3286 New_Copy_List (Discrete_Choices (Variant)), | |
3287 Statements => | |
3288 Build_Init_Statements (Component_List (Variant)))); | |
3289 Next_Non_Pragma (Variant); | |
3290 end loop; | |
3291 | |
3292 -- The expression of the case statement which is a reference | |
3293 -- to one of the discriminants is replaced by the appropriate | |
3294 -- formal parameter of the initialization procedure. | |
3295 | |
3296 Append_To (Stmts, | |
3297 Make_Case_Statement (Var_Loc, | |
3298 Expression => | |
3299 New_Occurrence_Of (Discriminal ( | |
3300 Entity (Name (Variant_Part (Comp_List)))), Var_Loc), | |
3301 Alternatives => Variant_Alts)); | |
3302 end; | |
3303 end if; | |
3304 | |
3305 -- If no initializations when generated for component declarations | |
3306 -- corresponding to this Stmts, append a null statement to Stmts to | |
3307 -- to make it a valid Ada tree. | |
3308 | |
3309 if Is_Empty_List (Stmts) then | |
3310 Append (Make_Null_Statement (Loc), Stmts); | |
3311 end if; | |
3312 | |
3313 return Stmts; | |
3314 | |
3315 exception | |
3316 when RE_Not_Available => | |
3317 return Empty_List; | |
3318 end Build_Init_Statements; | |
3319 | |
3320 ------------------------- | |
3321 -- Build_Record_Checks -- | |
3322 ------------------------- | |
3323 | |
3324 procedure Build_Record_Checks (S : Node_Id; Check_List : List_Id) is | |
3325 Subtype_Mark_Id : Entity_Id; | |
3326 | |
3327 procedure Constrain_Array | |
3328 (SI : Node_Id; | |
3329 Check_List : List_Id); | |
3330 -- Apply a list of index constraints to an unconstrained array type. | |
3331 -- The first parameter is the entity for the resulting subtype. | |
3332 -- Check_List is a list to which the check actions are appended. | |
3333 | |
3334 --------------------- | |
3335 -- Constrain_Array -- | |
3336 --------------------- | |
3337 | |
3338 procedure Constrain_Array | |
3339 (SI : Node_Id; | |
3340 Check_List : List_Id) | |
3341 is | |
3342 C : constant Node_Id := Constraint (SI); | |
3343 Number_Of_Constraints : Nat := 0; | |
3344 Index : Node_Id; | |
3345 S, T : Entity_Id; | |
3346 | |
3347 procedure Constrain_Index | |
3348 (Index : Node_Id; | |
3349 S : Node_Id; | |
3350 Check_List : List_Id); | |
3351 -- Process an index constraint in a constrained array declaration. | |
3352 -- The constraint can be either a subtype name or a range with or | |
3353 -- without an explicit subtype mark. Index is the corresponding | |
3354 -- index of the unconstrained array. S is the range expression. | |
3355 -- Check_List is a list to which the check actions are appended. | |
3356 | |
3357 --------------------- | |
3358 -- Constrain_Index -- | |
3359 --------------------- | |
3360 | |
3361 procedure Constrain_Index | |
3362 (Index : Node_Id; | |
3363 S : Node_Id; | |
3364 Check_List : List_Id) | |
3365 is | |
3366 T : constant Entity_Id := Etype (Index); | |
3367 | |
3368 begin | |
3369 if Nkind (S) = N_Range then | |
3370 Process_Range_Expr_In_Decl (S, T, Check_List => Check_List); | |
3371 end if; | |
3372 end Constrain_Index; | |
3373 | |
3374 -- Start of processing for Constrain_Array | |
3375 | |
3376 begin | |
3377 T := Entity (Subtype_Mark (SI)); | |
3378 | |
3379 if Is_Access_Type (T) then | |
3380 T := Designated_Type (T); | |
3381 end if; | |
3382 | |
3383 S := First (Constraints (C)); | |
3384 while Present (S) loop | |
3385 Number_Of_Constraints := Number_Of_Constraints + 1; | |
3386 Next (S); | |
3387 end loop; | |
3388 | |
3389 -- In either case, the index constraint must provide a discrete | |
3390 -- range for each index of the array type and the type of each | |
3391 -- discrete range must be the same as that of the corresponding | |
3392 -- index. (RM 3.6.1) | |
3393 | |
3394 S := First (Constraints (C)); | |
3395 Index := First_Index (T); | |
3396 Analyze (Index); | |
3397 | |
3398 -- Apply constraints to each index type | |
3399 | |
3400 for J in 1 .. Number_Of_Constraints loop | |
3401 Constrain_Index (Index, S, Check_List); | |
3402 Next (Index); | |
3403 Next (S); | |
3404 end loop; | |
3405 end Constrain_Array; | |
3406 | |
3407 -- Start of processing for Build_Record_Checks | |
3408 | |
3409 begin | |
3410 if Nkind (S) = N_Subtype_Indication then | |
3411 Find_Type (Subtype_Mark (S)); | |
3412 Subtype_Mark_Id := Entity (Subtype_Mark (S)); | |
3413 | |
3414 -- Remaining processing depends on type | |
3415 | |
3416 case Ekind (Subtype_Mark_Id) is | |
3417 when Array_Kind => | |
3418 Constrain_Array (S, Check_List); | |
3419 | |
3420 when others => | |
3421 null; | |
3422 end case; | |
3423 end if; | |
3424 end Build_Record_Checks; | |
3425 | |
3426 ------------------------------------------- | |
3427 -- Component_Needs_Simple_Initialization -- | |
3428 ------------------------------------------- | |
3429 | |
3430 function Component_Needs_Simple_Initialization | |
3431 (T : Entity_Id) return Boolean | |
3432 is | |
3433 begin | |
3434 return | |
3435 Needs_Simple_Initialization (T) | |
3436 and then not Is_RTE (T, RE_Tag) | |
3437 | |
3438 -- Ada 2005 (AI-251): Check also the tag of abstract interfaces | |
3439 | |
3440 and then not Is_RTE (T, RE_Interface_Tag); | |
3441 end Component_Needs_Simple_Initialization; | |
3442 | |
3443 -------------------------------------- | |
3444 -- Parent_Subtype_Renaming_Discrims -- | |
3445 -------------------------------------- | |
3446 | |
3447 function Parent_Subtype_Renaming_Discrims return Boolean is | |
3448 De : Entity_Id; | |
3449 Dp : Entity_Id; | |
3450 | |
3451 begin | |
3452 if Base_Type (Rec_Ent) /= Rec_Ent then | |
3453 return False; | |
3454 end if; | |
3455 | |
3456 if Etype (Rec_Ent) = Rec_Ent | |
3457 or else not Has_Discriminants (Rec_Ent) | |
3458 or else Is_Constrained (Rec_Ent) | |
3459 or else Is_Tagged_Type (Rec_Ent) | |
3460 then | |
3461 return False; | |
3462 end if; | |
3463 | |
3464 -- If there are no explicit stored discriminants we have inherited | |
3465 -- the root type discriminants so far, so no renamings occurred. | |
3466 | |
3467 if First_Discriminant (Rec_Ent) = | |
3468 First_Stored_Discriminant (Rec_Ent) | |
3469 then | |
3470 return False; | |
3471 end if; | |
3472 | |
3473 -- Check if we have done some trivial renaming of the parent | |
3474 -- discriminants, i.e. something like | |
3475 -- | |
3476 -- type DT (X1, X2: int) is new PT (X1, X2); | |
3477 | |
3478 De := First_Discriminant (Rec_Ent); | |
3479 Dp := First_Discriminant (Etype (Rec_Ent)); | |
3480 while Present (De) loop | |
3481 pragma Assert (Present (Dp)); | |
3482 | |
3483 if Corresponding_Discriminant (De) /= Dp then | |
3484 return True; | |
3485 end if; | |
3486 | |
3487 Next_Discriminant (De); | |
3488 Next_Discriminant (Dp); | |
3489 end loop; | |
3490 | |
3491 return Present (Dp); | |
3492 end Parent_Subtype_Renaming_Discrims; | |
3493 | |
3494 ------------------------ | |
3495 -- Requires_Init_Proc -- | |
3496 ------------------------ | |
3497 | |
3498 function Requires_Init_Proc (Rec_Id : Entity_Id) return Boolean is | |
3499 Comp_Decl : Node_Id; | |
3500 Id : Entity_Id; | |
3501 Typ : Entity_Id; | |
3502 | |
3503 begin | |
3504 -- Definitely do not need one if specifically suppressed | |
3505 | |
3506 if Initialization_Suppressed (Rec_Id) then | |
3507 return False; | |
3508 end if; | |
3509 | |
3510 -- If it is a type derived from a type with unknown discriminants, | |
3511 -- we cannot build an initialization procedure for it. | |
3512 | |
3513 if Has_Unknown_Discriminants (Rec_Id) | |
3514 or else Has_Unknown_Discriminants (Etype (Rec_Id)) | |
3515 then | |
3516 return False; | |
3517 end if; | |
3518 | |
3519 -- Otherwise we need to generate an initialization procedure if | |
3520 -- Is_CPP_Class is False and at least one of the following applies: | |
3521 | |
3522 -- 1. Discriminants are present, since they need to be initialized | |
3523 -- with the appropriate discriminant constraint expressions. | |
3524 -- However, the discriminant of an unchecked union does not | |
3525 -- count, since the discriminant is not present. | |
3526 | |
3527 -- 2. The type is a tagged type, since the implicit Tag component | |
3528 -- needs to be initialized with a pointer to the dispatch table. | |
3529 | |
3530 -- 3. The type contains tasks | |
3531 | |
3532 -- 4. One or more components has an initial value | |
3533 | |
3534 -- 5. One or more components is for a type which itself requires | |
3535 -- an initialization procedure. | |
3536 | |
3537 -- 6. One or more components is a type that requires simple | |
3538 -- initialization (see Needs_Simple_Initialization), except | |
3539 -- that types Tag and Interface_Tag are excluded, since fields | |
3540 -- of these types are initialized by other means. | |
3541 | |
3542 -- 7. The type is the record type built for a task type (since at | |
3543 -- the very least, Create_Task must be called) | |
3544 | |
3545 -- 8. The type is the record type built for a protected type (since | |
3546 -- at least Initialize_Protection must be called) | |
3547 | |
3548 -- 9. The type is marked as a public entity. The reason we add this | |
3549 -- case (even if none of the above apply) is to properly handle | |
3550 -- Initialize_Scalars. If a package is compiled without an IS | |
3551 -- pragma, and the client is compiled with an IS pragma, then | |
3552 -- the client will think an initialization procedure is present | |
3553 -- and call it, when in fact no such procedure is required, but | |
3554 -- since the call is generated, there had better be a routine | |
3555 -- at the other end of the call, even if it does nothing). | |
3556 | |
3557 -- Note: the reason we exclude the CPP_Class case is because in this | |
3558 -- case the initialization is performed by the C++ constructors, and | |
3559 -- the IP is built by Set_CPP_Constructors. | |
3560 | |
3561 if Is_CPP_Class (Rec_Id) then | |
3562 return False; | |
3563 | |
3564 elsif Is_Interface (Rec_Id) then | |
3565 return False; | |
3566 | |
3567 elsif (Has_Discriminants (Rec_Id) | |
3568 and then not Is_Unchecked_Union (Rec_Id)) | |
3569 or else Is_Tagged_Type (Rec_Id) | |
3570 or else Is_Concurrent_Record_Type (Rec_Id) | |
3571 or else Has_Task (Rec_Id) | |
3572 then | |
3573 return True; | |
3574 end if; | |
3575 | |
3576 Id := First_Component (Rec_Id); | |
3577 while Present (Id) loop | |
3578 Comp_Decl := Parent (Id); | |
3579 Typ := Etype (Id); | |
3580 | |
3581 if Present (Expression (Comp_Decl)) | |
3582 or else Has_Non_Null_Base_Init_Proc (Typ) | |
3583 or else Component_Needs_Simple_Initialization (Typ) | |
3584 then | |
3585 return True; | |
3586 end if; | |
3587 | |
3588 Next_Component (Id); | |
3589 end loop; | |
3590 | |
3591 -- As explained above, a record initialization procedure is needed | |
3592 -- for public types in case Initialize_Scalars applies to a client. | |
3593 -- However, such a procedure is not needed in the case where either | |
3594 -- of restrictions No_Initialize_Scalars or No_Default_Initialization | |
3595 -- applies. No_Initialize_Scalars excludes the possibility of using | |
3596 -- Initialize_Scalars in any partition, and No_Default_Initialization | |
3597 -- implies that no initialization should ever be done for objects of | |
3598 -- the type, so is incompatible with Initialize_Scalars. | |
3599 | |
3600 if not Restriction_Active (No_Initialize_Scalars) | |
3601 and then not Restriction_Active (No_Default_Initialization) | |
3602 and then Is_Public (Rec_Id) | |
3603 then | |
3604 return True; | |
3605 end if; | |
3606 | |
3607 return False; | |
3608 end Requires_Init_Proc; | |
3609 | |
3610 -- Start of processing for Build_Record_Init_Proc | |
3611 | |
3612 begin | |
3613 Rec_Type := Defining_Identifier (N); | |
3614 | |
3615 -- This may be full declaration of a private type, in which case | |
3616 -- the visible entity is a record, and the private entity has been | |
3617 -- exchanged with it in the private part of the current package. | |
3618 -- The initialization procedure is built for the record type, which | |
3619 -- is retrievable from the private entity. | |
3620 | |
3621 if Is_Incomplete_Or_Private_Type (Rec_Type) then | |
3622 Rec_Type := Underlying_Type (Rec_Type); | |
3623 end if; | |
3624 | |
3625 -- If we have a variant record with restriction No_Implicit_Conditionals | |
3626 -- in effect, then we skip building the procedure. This is safe because | |
3627 -- if we can see the restriction, so can any caller, calls to initialize | |
3628 -- such records are not allowed for variant records if this restriction | |
3629 -- is active. | |
3630 | |
3631 if Has_Variant_Part (Rec_Type) | |
3632 and then Restriction_Active (No_Implicit_Conditionals) | |
3633 then | |
3634 return; | |
3635 end if; | |
3636 | |
3637 -- If there are discriminants, build the discriminant map to replace | |
3638 -- discriminants by their discriminals in complex bound expressions. | |
3639 -- These only arise for the corresponding records of synchronized types. | |
3640 | |
3641 if Is_Concurrent_Record_Type (Rec_Type) | |
3642 and then Has_Discriminants (Rec_Type) | |
3643 then | |
3644 declare | |
3645 Disc : Entity_Id; | |
3646 begin | |
3647 Disc := First_Discriminant (Rec_Type); | |
3648 while Present (Disc) loop | |
3649 Append_Elmt (Disc, Discr_Map); | |
3650 Append_Elmt (Discriminal (Disc), Discr_Map); | |
3651 Next_Discriminant (Disc); | |
3652 end loop; | |
3653 end; | |
3654 end if; | |
3655 | |
3656 -- Derived types that have no type extension can use the initialization | |
3657 -- procedure of their parent and do not need a procedure of their own. | |
3658 -- This is only correct if there are no representation clauses for the | |
3659 -- type or its parent, and if the parent has in fact been frozen so | |
3660 -- that its initialization procedure exists. | |
3661 | |
3662 if Is_Derived_Type (Rec_Type) | |
3663 and then not Is_Tagged_Type (Rec_Type) | |
3664 and then not Is_Unchecked_Union (Rec_Type) | |
3665 and then not Has_New_Non_Standard_Rep (Rec_Type) | |
3666 and then not Parent_Subtype_Renaming_Discrims | |
3667 and then Has_Non_Null_Base_Init_Proc (Etype (Rec_Type)) | |
3668 then | |
3669 Copy_TSS (Base_Init_Proc (Etype (Rec_Type)), Rec_Type); | |
3670 | |
3671 -- Otherwise if we need an initialization procedure, then build one, | |
3672 -- mark it as public and inlinable and as having a completion. | |
3673 | |
3674 elsif Requires_Init_Proc (Rec_Type) | |
3675 or else Is_Unchecked_Union (Rec_Type) | |
3676 then | |
3677 Proc_Id := | |
3678 Make_Defining_Identifier (Loc, | |
3679 Chars => Make_Init_Proc_Name (Rec_Type)); | |
3680 | |
3681 -- If No_Default_Initialization restriction is active, then we don't | |
3682 -- want to build an init_proc, but we need to mark that an init_proc | |
3683 -- would be needed if this restriction was not active (so that we can | |
3684 -- detect attempts to call it), so set a dummy init_proc in place. | |
3685 | |
3686 if Restriction_Active (No_Default_Initialization) then | |
3687 Set_Init_Proc (Rec_Type, Proc_Id); | |
3688 return; | |
3689 end if; | |
3690 | |
3691 Build_Offset_To_Top_Functions; | |
3692 Build_CPP_Init_Procedure; | |
3693 Build_Init_Procedure; | |
3694 | |
3695 Set_Is_Public (Proc_Id, Is_Public (Rec_Ent)); | |
3696 Set_Is_Internal (Proc_Id); | |
3697 Set_Has_Completion (Proc_Id); | |
3698 | |
3699 if not Debug_Generated_Code then | |
3700 Set_Debug_Info_Off (Proc_Id); | |
3701 end if; | |
3702 | |
3703 Set_Is_Inlined (Proc_Id, Inline_Init_Proc (Rec_Type)); | |
3704 | |
3705 -- Do not build an aggregate if Modify_Tree_For_C, this isn't | |
3706 -- needed and may generate early references to non frozen types | |
3707 -- since we expand aggregate much more systematically. | |
3708 | |
3709 if Modify_Tree_For_C then | |
3710 return; | |
3711 end if; | |
3712 | |
3713 declare | |
3714 Agg : constant Node_Id := | |
3715 Build_Equivalent_Record_Aggregate (Rec_Type); | |
3716 | |
3717 procedure Collect_Itypes (Comp : Node_Id); | |
3718 -- Generate references to itypes in the aggregate, because | |
3719 -- the first use of the aggregate may be in a nested scope. | |
3720 | |
3721 -------------------- | |
3722 -- Collect_Itypes -- | |
3723 -------------------- | |
3724 | |
3725 procedure Collect_Itypes (Comp : Node_Id) is | |
3726 Ref : Node_Id; | |
3727 Sub_Aggr : Node_Id; | |
3728 Typ : constant Entity_Id := Etype (Comp); | |
3729 | |
3730 begin | |
3731 if Is_Array_Type (Typ) and then Is_Itype (Typ) then | |
3732 Ref := Make_Itype_Reference (Loc); | |
3733 Set_Itype (Ref, Typ); | |
3734 Append_Freeze_Action (Rec_Type, Ref); | |
3735 | |
3736 Ref := Make_Itype_Reference (Loc); | |
3737 Set_Itype (Ref, Etype (First_Index (Typ))); | |
3738 Append_Freeze_Action (Rec_Type, Ref); | |
3739 | |
3740 -- Recurse on nested arrays | |
3741 | |
3742 Sub_Aggr := First (Expressions (Comp)); | |
3743 while Present (Sub_Aggr) loop | |
3744 Collect_Itypes (Sub_Aggr); | |
3745 Next (Sub_Aggr); | |
3746 end loop; | |
3747 end if; | |
3748 end Collect_Itypes; | |
3749 | |
3750 begin | |
3751 -- If there is a static initialization aggregate for the type, | |
3752 -- generate itype references for the types of its (sub)components, | |
3753 -- to prevent out-of-scope errors in the resulting tree. | |
3754 -- The aggregate may have been rewritten as a Raise node, in which | |
3755 -- case there are no relevant itypes. | |
3756 | |
3757 if Present (Agg) and then Nkind (Agg) = N_Aggregate then | |
3758 Set_Static_Initialization (Proc_Id, Agg); | |
3759 | |
3760 declare | |
3761 Comp : Node_Id; | |
3762 begin | |
3763 Comp := First (Component_Associations (Agg)); | |
3764 while Present (Comp) loop | |
3765 Collect_Itypes (Expression (Comp)); | |
3766 Next (Comp); | |
3767 end loop; | |
3768 end; | |
3769 end if; | |
3770 end; | |
3771 end if; | |
3772 end Build_Record_Init_Proc; | |
3773 | |
3774 ---------------------------- | |
3775 -- Build_Slice_Assignment -- | |
3776 ---------------------------- | |
3777 | |
3778 -- Generates the following subprogram: | |
3779 | |
3780 -- procedure Assign | |
3781 -- (Source, Target : Array_Type, | |
3782 -- Left_Lo, Left_Hi : Index; | |
3783 -- Right_Lo, Right_Hi : Index; | |
3784 -- Rev : Boolean) | |
3785 -- is | |
3786 -- Li1 : Index; | |
3787 -- Ri1 : Index; | |
3788 | |
3789 -- begin | |
3790 | |
3791 -- if Left_Hi < Left_Lo then | |
3792 -- return; | |
3793 -- end if; | |
3794 | |
3795 -- if Rev then | |
3796 -- Li1 := Left_Hi; | |
3797 -- Ri1 := Right_Hi; | |
3798 -- else | |
3799 -- Li1 := Left_Lo; | |
3800 -- Ri1 := Right_Lo; | |
3801 -- end if; | |
3802 | |
3803 -- loop | |
3804 -- Target (Li1) := Source (Ri1); | |
3805 | |
3806 -- if Rev then | |
3807 -- exit when Li1 = Left_Lo; | |
3808 -- Li1 := Index'pred (Li1); | |
3809 -- Ri1 := Index'pred (Ri1); | |
3810 -- else | |
3811 -- exit when Li1 = Left_Hi; | |
3812 -- Li1 := Index'succ (Li1); | |
3813 -- Ri1 := Index'succ (Ri1); | |
3814 -- end if; | |
3815 -- end loop; | |
3816 -- end Assign; | |
3817 | |
3818 procedure Build_Slice_Assignment (Typ : Entity_Id) is | |
3819 Loc : constant Source_Ptr := Sloc (Typ); | |
3820 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ))); | |
3821 | |
3822 Larray : constant Entity_Id := Make_Temporary (Loc, 'A'); | |
3823 Rarray : constant Entity_Id := Make_Temporary (Loc, 'R'); | |
3824 Left_Lo : constant Entity_Id := Make_Temporary (Loc, 'L'); | |
3825 Left_Hi : constant Entity_Id := Make_Temporary (Loc, 'L'); | |
3826 Right_Lo : constant Entity_Id := Make_Temporary (Loc, 'R'); | |
3827 Right_Hi : constant Entity_Id := Make_Temporary (Loc, 'R'); | |
3828 Rev : constant Entity_Id := Make_Temporary (Loc, 'D'); | |
3829 -- Formal parameters of procedure | |
3830 | |
3831 Proc_Name : constant Entity_Id := | |
3832 Make_Defining_Identifier (Loc, | |
3833 Chars => Make_TSS_Name (Typ, TSS_Slice_Assign)); | |
3834 | |
3835 Lnn : constant Entity_Id := Make_Temporary (Loc, 'L'); | |
3836 Rnn : constant Entity_Id := Make_Temporary (Loc, 'R'); | |
3837 -- Subscripts for left and right sides | |
3838 | |
3839 Decls : List_Id; | |
3840 Loops : Node_Id; | |
3841 Stats : List_Id; | |
3842 | |
3843 begin | |
3844 -- Build declarations for indexes | |
3845 | |
3846 Decls := New_List; | |
3847 | |
3848 Append_To (Decls, | |
3849 Make_Object_Declaration (Loc, | |
3850 Defining_Identifier => Lnn, | |
3851 Object_Definition => | |
3852 New_Occurrence_Of (Index, Loc))); | |
3853 | |
3854 Append_To (Decls, | |
3855 Make_Object_Declaration (Loc, | |
3856 Defining_Identifier => Rnn, | |
3857 Object_Definition => | |
3858 New_Occurrence_Of (Index, Loc))); | |
3859 | |
3860 Stats := New_List; | |
3861 | |
3862 -- Build test for empty slice case | |
3863 | |
3864 Append_To (Stats, | |
3865 Make_If_Statement (Loc, | |
3866 Condition => | |
3867 Make_Op_Lt (Loc, | |
3868 Left_Opnd => New_Occurrence_Of (Left_Hi, Loc), | |
3869 Right_Opnd => New_Occurrence_Of (Left_Lo, Loc)), | |
3870 Then_Statements => New_List (Make_Simple_Return_Statement (Loc)))); | |
3871 | |
3872 -- Build initializations for indexes | |
3873 | |
3874 declare | |
3875 F_Init : constant List_Id := New_List; | |
3876 B_Init : constant List_Id := New_List; | |
3877 | |
3878 begin | |
3879 Append_To (F_Init, | |
3880 Make_Assignment_Statement (Loc, | |
3881 Name => New_Occurrence_Of (Lnn, Loc), | |
3882 Expression => New_Occurrence_Of (Left_Lo, Loc))); | |
3883 | |
3884 Append_To (F_Init, | |
3885 Make_Assignment_Statement (Loc, | |
3886 Name => New_Occurrence_Of (Rnn, Loc), | |
3887 Expression => New_Occurrence_Of (Right_Lo, Loc))); | |
3888 | |
3889 Append_To (B_Init, | |
3890 Make_Assignment_Statement (Loc, | |
3891 Name => New_Occurrence_Of (Lnn, Loc), | |
3892 Expression => New_Occurrence_Of (Left_Hi, Loc))); | |
3893 | |
3894 Append_To (B_Init, | |
3895 Make_Assignment_Statement (Loc, | |
3896 Name => New_Occurrence_Of (Rnn, Loc), | |
3897 Expression => New_Occurrence_Of (Right_Hi, Loc))); | |
3898 | |
3899 Append_To (Stats, | |
3900 Make_If_Statement (Loc, | |
3901 Condition => New_Occurrence_Of (Rev, Loc), | |
3902 Then_Statements => B_Init, | |
3903 Else_Statements => F_Init)); | |
3904 end; | |
3905 | |
3906 -- Now construct the assignment statement | |
3907 | |
3908 Loops := | |
3909 Make_Loop_Statement (Loc, | |
3910 Statements => New_List ( | |
3911 Make_Assignment_Statement (Loc, | |
3912 Name => | |
3913 Make_Indexed_Component (Loc, | |
3914 Prefix => New_Occurrence_Of (Larray, Loc), | |
3915 Expressions => New_List (New_Occurrence_Of (Lnn, Loc))), | |
3916 Expression => | |
3917 Make_Indexed_Component (Loc, | |
3918 Prefix => New_Occurrence_Of (Rarray, Loc), | |
3919 Expressions => New_List (New_Occurrence_Of (Rnn, Loc))))), | |
3920 End_Label => Empty); | |
3921 | |
3922 -- Build the exit condition and increment/decrement statements | |
3923 | |
3924 declare | |
3925 F_Ass : constant List_Id := New_List; | |
3926 B_Ass : constant List_Id := New_List; | |
3927 | |
3928 begin | |
3929 Append_To (F_Ass, | |
3930 Make_Exit_Statement (Loc, | |
3931 Condition => | |
3932 Make_Op_Eq (Loc, | |
3933 Left_Opnd => New_Occurrence_Of (Lnn, Loc), | |
3934 Right_Opnd => New_Occurrence_Of (Left_Hi, Loc)))); | |
3935 | |
3936 Append_To (F_Ass, | |
3937 Make_Assignment_Statement (Loc, | |
3938 Name => New_Occurrence_Of (Lnn, Loc), | |
3939 Expression => | |
3940 Make_Attribute_Reference (Loc, | |
3941 Prefix => | |
3942 New_Occurrence_Of (Index, Loc), | |
3943 Attribute_Name => Name_Succ, | |
3944 Expressions => New_List ( | |
3945 New_Occurrence_Of (Lnn, Loc))))); | |
3946 | |
3947 Append_To (F_Ass, | |
3948 Make_Assignment_Statement (Loc, | |
3949 Name => New_Occurrence_Of (Rnn, Loc), | |
3950 Expression => | |
3951 Make_Attribute_Reference (Loc, | |
3952 Prefix => | |
3953 New_Occurrence_Of (Index, Loc), | |
3954 Attribute_Name => Name_Succ, | |
3955 Expressions => New_List ( | |
3956 New_Occurrence_Of (Rnn, Loc))))); | |
3957 | |
3958 Append_To (B_Ass, | |
3959 Make_Exit_Statement (Loc, | |
3960 Condition => | |
3961 Make_Op_Eq (Loc, | |
3962 Left_Opnd => New_Occurrence_Of (Lnn, Loc), | |
3963 Right_Opnd => New_Occurrence_Of (Left_Lo, Loc)))); | |
3964 | |
3965 Append_To (B_Ass, | |
3966 Make_Assignment_Statement (Loc, | |
3967 Name => New_Occurrence_Of (Lnn, Loc), | |
3968 Expression => | |
3969 Make_Attribute_Reference (Loc, | |
3970 Prefix => | |
3971 New_Occurrence_Of (Index, Loc), | |
3972 Attribute_Name => Name_Pred, | |
3973 Expressions => New_List ( | |
3974 New_Occurrence_Of (Lnn, Loc))))); | |
3975 | |
3976 Append_To (B_Ass, | |
3977 Make_Assignment_Statement (Loc, | |
3978 Name => New_Occurrence_Of (Rnn, Loc), | |
3979 Expression => | |
3980 Make_Attribute_Reference (Loc, | |
3981 Prefix => | |
3982 New_Occurrence_Of (Index, Loc), | |
3983 Attribute_Name => Name_Pred, | |
3984 Expressions => New_List ( | |
3985 New_Occurrence_Of (Rnn, Loc))))); | |
3986 | |
3987 Append_To (Statements (Loops), | |
3988 Make_If_Statement (Loc, | |
3989 Condition => New_Occurrence_Of (Rev, Loc), | |
3990 Then_Statements => B_Ass, | |
3991 Else_Statements => F_Ass)); | |
3992 end; | |
3993 | |
3994 Append_To (Stats, Loops); | |
3995 | |
3996 declare | |
3997 Spec : Node_Id; | |
3998 Formals : List_Id := New_List; | |
3999 | |
4000 begin | |
4001 Formals := New_List ( | |
4002 Make_Parameter_Specification (Loc, | |
4003 Defining_Identifier => Larray, | |
4004 Out_Present => True, | |
4005 Parameter_Type => | |
4006 New_Occurrence_Of (Base_Type (Typ), Loc)), | |
4007 | |
4008 Make_Parameter_Specification (Loc, | |
4009 Defining_Identifier => Rarray, | |
4010 Parameter_Type => | |
4011 New_Occurrence_Of (Base_Type (Typ), Loc)), | |
4012 | |
4013 Make_Parameter_Specification (Loc, | |
4014 Defining_Identifier => Left_Lo, | |
4015 Parameter_Type => | |
4016 New_Occurrence_Of (Index, Loc)), | |
4017 | |
4018 Make_Parameter_Specification (Loc, | |
4019 Defining_Identifier => Left_Hi, | |
4020 Parameter_Type => | |
4021 New_Occurrence_Of (Index, Loc)), | |
4022 | |
4023 Make_Parameter_Specification (Loc, | |
4024 Defining_Identifier => Right_Lo, | |
4025 Parameter_Type => | |
4026 New_Occurrence_Of (Index, Loc)), | |
4027 | |
4028 Make_Parameter_Specification (Loc, | |
4029 Defining_Identifier => Right_Hi, | |
4030 Parameter_Type => | |
4031 New_Occurrence_Of (Index, Loc))); | |
4032 | |
4033 Append_To (Formals, | |
4034 Make_Parameter_Specification (Loc, | |
4035 Defining_Identifier => Rev, | |
4036 Parameter_Type => | |
4037 New_Occurrence_Of (Standard_Boolean, Loc))); | |
4038 | |
4039 Spec := | |
4040 Make_Procedure_Specification (Loc, | |
4041 Defining_Unit_Name => Proc_Name, | |
4042 Parameter_Specifications => Formals); | |
4043 | |
4044 Discard_Node ( | |
4045 Make_Subprogram_Body (Loc, | |
4046 Specification => Spec, | |
4047 Declarations => Decls, | |
4048 Handled_Statement_Sequence => | |
4049 Make_Handled_Sequence_Of_Statements (Loc, | |
4050 Statements => Stats))); | |
4051 end; | |
4052 | |
4053 Set_TSS (Typ, Proc_Name); | |
4054 Set_Is_Pure (Proc_Name); | |
4055 end Build_Slice_Assignment; | |
4056 | |
4057 ----------------------------- | |
4058 -- Build_Untagged_Equality -- | |
4059 ----------------------------- | |
4060 | |
4061 procedure Build_Untagged_Equality (Typ : Entity_Id) is | |
4062 Build_Eq : Boolean; | |
4063 Comp : Entity_Id; | |
4064 Decl : Node_Id; | |
4065 Op : Entity_Id; | |
4066 Prim : Elmt_Id; | |
4067 Eq_Op : Entity_Id; | |
4068 | |
4069 function User_Defined_Eq (T : Entity_Id) return Entity_Id; | |
4070 -- Check whether the type T has a user-defined primitive equality. If so | |
4071 -- return it, else return Empty. If true for a component of Typ, we have | |
4072 -- to build the primitive equality for it. | |
4073 | |
4074 --------------------- | |
4075 -- User_Defined_Eq -- | |
4076 --------------------- | |
4077 | |
4078 function User_Defined_Eq (T : Entity_Id) return Entity_Id is | |
4079 Prim : Elmt_Id; | |
4080 Op : Entity_Id; | |
4081 | |
4082 begin | |
4083 Op := TSS (T, TSS_Composite_Equality); | |
4084 | |
4085 if Present (Op) then | |
4086 return Op; | |
4087 end if; | |
4088 | |
4089 Prim := First_Elmt (Collect_Primitive_Operations (T)); | |
4090 while Present (Prim) loop | |
4091 Op := Node (Prim); | |
4092 | |
4093 if Chars (Op) = Name_Op_Eq | |
4094 and then Etype (Op) = Standard_Boolean | |
4095 and then Etype (First_Formal (Op)) = T | |
4096 and then Etype (Next_Formal (First_Formal (Op))) = T | |
4097 then | |
4098 return Op; | |
4099 end if; | |
4100 | |
4101 Next_Elmt (Prim); | |
4102 end loop; | |
4103 | |
4104 return Empty; | |
4105 end User_Defined_Eq; | |
4106 | |
4107 -- Start of processing for Build_Untagged_Equality | |
4108 | |
4109 begin | |
4110 -- If a record component has a primitive equality operation, we must | |
4111 -- build the corresponding one for the current type. | |
4112 | |
4113 Build_Eq := False; | |
4114 Comp := First_Component (Typ); | |
4115 while Present (Comp) loop | |
4116 if Is_Record_Type (Etype (Comp)) | |
4117 and then Present (User_Defined_Eq (Etype (Comp))) | |
4118 then | |
4119 Build_Eq := True; | |
4120 end if; | |
4121 | |
4122 Next_Component (Comp); | |
4123 end loop; | |
4124 | |
4125 -- If there is a user-defined equality for the type, we do not create | |
4126 -- the implicit one. | |
4127 | |
4128 Prim := First_Elmt (Collect_Primitive_Operations (Typ)); | |
4129 Eq_Op := Empty; | |
4130 while Present (Prim) loop | |
4131 if Chars (Node (Prim)) = Name_Op_Eq | |
4132 and then Comes_From_Source (Node (Prim)) | |
4133 | |
4134 -- Don't we also need to check formal types and return type as in | |
4135 -- User_Defined_Eq above??? | |
4136 | |
4137 then | |
4138 Eq_Op := Node (Prim); | |
4139 Build_Eq := False; | |
4140 exit; | |
4141 end if; | |
4142 | |
4143 Next_Elmt (Prim); | |
4144 end loop; | |
4145 | |
4146 -- If the type is derived, inherit the operation, if present, from the | |
4147 -- parent type. It may have been declared after the type derivation. If | |
4148 -- the parent type itself is derived, it may have inherited an operation | |
4149 -- that has itself been overridden, so update its alias and related | |
4150 -- flags. Ditto for inequality. | |
4151 | |
4152 if No (Eq_Op) and then Is_Derived_Type (Typ) then | |
4153 Prim := First_Elmt (Collect_Primitive_Operations (Etype (Typ))); | |
4154 while Present (Prim) loop | |
4155 if Chars (Node (Prim)) = Name_Op_Eq then | |
4156 Copy_TSS (Node (Prim), Typ); | |
4157 Build_Eq := False; | |
4158 | |
4159 declare | |
4160 Op : constant Entity_Id := User_Defined_Eq (Typ); | |
4161 Eq_Op : constant Entity_Id := Node (Prim); | |
4162 NE_Op : constant Entity_Id := Next_Entity (Eq_Op); | |
4163 | |
4164 begin | |
4165 if Present (Op) then | |
4166 Set_Alias (Op, Eq_Op); | |
4167 Set_Is_Abstract_Subprogram | |
4168 (Op, Is_Abstract_Subprogram (Eq_Op)); | |
4169 | |
4170 if Chars (Next_Entity (Op)) = Name_Op_Ne then | |
4171 Set_Is_Abstract_Subprogram | |
4172 (Next_Entity (Op), Is_Abstract_Subprogram (NE_Op)); | |
4173 end if; | |
4174 end if; | |
4175 end; | |
4176 | |
4177 exit; | |
4178 end if; | |
4179 | |
4180 Next_Elmt (Prim); | |
4181 end loop; | |
4182 end if; | |
4183 | |
4184 -- If not inherited and not user-defined, build body as for a type with | |
4185 -- tagged components. | |
4186 | |
4187 if Build_Eq then | |
4188 Decl := | |
4189 Make_Eq_Body (Typ, Make_TSS_Name (Typ, TSS_Composite_Equality)); | |
4190 Op := Defining_Entity (Decl); | |
4191 Set_TSS (Typ, Op); | |
4192 Set_Is_Pure (Op); | |
4193 | |
4194 if Is_Library_Level_Entity (Typ) then | |
4195 Set_Is_Public (Op); | |
4196 end if; | |
4197 end if; | |
4198 end Build_Untagged_Equality; | |
4199 | |
4200 ----------------------------------- | |
4201 -- Build_Variant_Record_Equality -- | |
4202 ----------------------------------- | |
4203 | |
4204 -- Generates: | |
4205 | |
4206 -- function _Equality (X, Y : T) return Boolean is | |
4207 -- begin | |
4208 -- -- Compare discriminants | |
4209 | |
4210 -- if X.D1 /= Y.D1 or else X.D2 /= Y.D2 or else ... then | |
4211 -- return False; | |
4212 -- end if; | |
4213 | |
4214 -- -- Compare components | |
4215 | |
4216 -- if X.C1 /= Y.C1 or else X.C2 /= Y.C2 or else ... then | |
4217 -- return False; | |
4218 -- end if; | |
4219 | |
4220 -- -- Compare variant part | |
4221 | |
4222 -- case X.D1 is | |
4223 -- when V1 => | |
4224 -- if X.C2 /= Y.C2 or else X.C3 /= Y.C3 or else ... then | |
4225 -- return False; | |
4226 -- end if; | |
4227 -- ... | |
4228 -- when Vn => | |
4229 -- if X.Cn /= Y.Cn or else ... then | |
4230 -- return False; | |
4231 -- end if; | |
4232 -- end case; | |
4233 | |
4234 -- return True; | |
4235 -- end _Equality; | |
4236 | |
4237 procedure Build_Variant_Record_Equality (Typ : Entity_Id) is | |
4238 Loc : constant Source_Ptr := Sloc (Typ); | |
4239 | |
4240 F : constant Entity_Id := | |
4241 Make_Defining_Identifier (Loc, | |
4242 Chars => Make_TSS_Name (Typ, TSS_Composite_Equality)); | |
4243 | |
4244 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_X); | |
4245 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_Y); | |
4246 | |
4247 Def : constant Node_Id := Parent (Typ); | |
4248 Comps : constant Node_Id := Component_List (Type_Definition (Def)); | |
4249 Stmts : constant List_Id := New_List; | |
4250 Pspecs : constant List_Id := New_List; | |
4251 | |
4252 begin | |
4253 -- If we have a variant record with restriction No_Implicit_Conditionals | |
4254 -- in effect, then we skip building the procedure. This is safe because | |
4255 -- if we can see the restriction, so can any caller, calls to equality | |
4256 -- test routines are not allowed for variant records if this restriction | |
4257 -- is active. | |
4258 | |
4259 if Restriction_Active (No_Implicit_Conditionals) then | |
4260 return; | |
4261 end if; | |
4262 | |
4263 -- Derived Unchecked_Union types no longer inherit the equality function | |
4264 -- of their parent. | |
4265 | |
4266 if Is_Derived_Type (Typ) | |
4267 and then not Is_Unchecked_Union (Typ) | |
4268 and then not Has_New_Non_Standard_Rep (Typ) | |
4269 then | |
4270 declare | |
4271 Parent_Eq : constant Entity_Id := | |
4272 TSS (Root_Type (Typ), TSS_Composite_Equality); | |
4273 begin | |
4274 if Present (Parent_Eq) then | |
4275 Copy_TSS (Parent_Eq, Typ); | |
4276 return; | |
4277 end if; | |
4278 end; | |
4279 end if; | |
4280 | |
4281 Discard_Node ( | |
4282 Make_Subprogram_Body (Loc, | |
4283 Specification => | |
4284 Make_Function_Specification (Loc, | |
4285 Defining_Unit_Name => F, | |
4286 Parameter_Specifications => Pspecs, | |
4287 Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)), | |
4288 Declarations => New_List, | |
4289 Handled_Statement_Sequence => | |
4290 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts))); | |
4291 | |
4292 Append_To (Pspecs, | |
4293 Make_Parameter_Specification (Loc, | |
4294 Defining_Identifier => X, | |
4295 Parameter_Type => New_Occurrence_Of (Typ, Loc))); | |
4296 | |
4297 Append_To (Pspecs, | |
4298 Make_Parameter_Specification (Loc, | |
4299 Defining_Identifier => Y, | |
4300 Parameter_Type => New_Occurrence_Of (Typ, Loc))); | |
4301 | |
4302 -- Unchecked_Unions require additional machinery to support equality. | |
4303 -- Two extra parameters (A and B) are added to the equality function | |
4304 -- parameter list for each discriminant of the type, in order to | |
4305 -- capture the inferred values of the discriminants in equality calls. | |
4306 -- The names of the parameters match the names of the corresponding | |
4307 -- discriminant, with an added suffix. | |
4308 | |
4309 if Is_Unchecked_Union (Typ) then | |
4310 declare | |
4311 Discr : Entity_Id; | |
4312 Discr_Type : Entity_Id; | |
4313 A, B : Entity_Id; | |
4314 New_Discrs : Elist_Id; | |
4315 | |
4316 begin | |
4317 New_Discrs := New_Elmt_List; | |
4318 | |
4319 Discr := First_Discriminant (Typ); | |
4320 while Present (Discr) loop | |
4321 Discr_Type := Etype (Discr); | |
4322 A := Make_Defining_Identifier (Loc, | |
4323 Chars => New_External_Name (Chars (Discr), 'A')); | |
4324 | |
4325 B := Make_Defining_Identifier (Loc, | |
4326 Chars => New_External_Name (Chars (Discr), 'B')); | |
4327 | |
4328 -- Add new parameters to the parameter list | |
4329 | |
4330 Append_To (Pspecs, | |
4331 Make_Parameter_Specification (Loc, | |
4332 Defining_Identifier => A, | |
4333 Parameter_Type => | |
4334 New_Occurrence_Of (Discr_Type, Loc))); | |
4335 | |
4336 Append_To (Pspecs, | |
4337 Make_Parameter_Specification (Loc, | |
4338 Defining_Identifier => B, | |
4339 Parameter_Type => | |
4340 New_Occurrence_Of (Discr_Type, Loc))); | |
4341 | |
4342 Append_Elmt (A, New_Discrs); | |
4343 | |
4344 -- Generate the following code to compare each of the inferred | |
4345 -- discriminants: | |
4346 | |
4347 -- if a /= b then | |
4348 -- return False; | |
4349 -- end if; | |
4350 | |
4351 Append_To (Stmts, | |
4352 Make_If_Statement (Loc, | |
4353 Condition => | |
4354 Make_Op_Ne (Loc, | |
4355 Left_Opnd => New_Occurrence_Of (A, Loc), | |
4356 Right_Opnd => New_Occurrence_Of (B, Loc)), | |
4357 Then_Statements => New_List ( | |
4358 Make_Simple_Return_Statement (Loc, | |
4359 Expression => | |
4360 New_Occurrence_Of (Standard_False, Loc))))); | |
4361 Next_Discriminant (Discr); | |
4362 end loop; | |
4363 | |
4364 -- Generate component-by-component comparison. Note that we must | |
4365 -- propagate the inferred discriminants formals to act as | |
4366 -- the case statement switch. Their value is added when an | |
4367 -- equality call on unchecked unions is expanded. | |
4368 | |
4369 Append_List_To (Stmts, Make_Eq_Case (Typ, Comps, New_Discrs)); | |
4370 end; | |
4371 | |
4372 -- Normal case (not unchecked union) | |
4373 | |
4374 else | |
4375 Append_To (Stmts, | |
4376 Make_Eq_If (Typ, Discriminant_Specifications (Def))); | |
4377 Append_List_To (Stmts, Make_Eq_Case (Typ, Comps)); | |
4378 end if; | |
4379 | |
4380 Append_To (Stmts, | |
4381 Make_Simple_Return_Statement (Loc, | |
4382 Expression => New_Occurrence_Of (Standard_True, Loc))); | |
4383 | |
4384 Set_TSS (Typ, F); | |
4385 Set_Is_Pure (F); | |
4386 | |
4387 if not Debug_Generated_Code then | |
4388 Set_Debug_Info_Off (F); | |
4389 end if; | |
4390 end Build_Variant_Record_Equality; | |
4391 | |
4392 ----------------------------- | |
4393 -- Check_Stream_Attributes -- | |
4394 ----------------------------- | |
4395 | |
4396 procedure Check_Stream_Attributes (Typ : Entity_Id) is | |
4397 Comp : Entity_Id; | |
4398 Par_Read : constant Boolean := | |
4399 Stream_Attribute_Available (Typ, TSS_Stream_Read) | |
4400 and then not Has_Specified_Stream_Read (Typ); | |
4401 Par_Write : constant Boolean := | |
4402 Stream_Attribute_Available (Typ, TSS_Stream_Write) | |
4403 and then not Has_Specified_Stream_Write (Typ); | |
4404 | |
4405 procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type); | |
4406 -- Check that Comp has a user-specified Nam stream attribute | |
4407 | |
4408 ---------------- | |
4409 -- Check_Attr -- | |
4410 ---------------- | |
4411 | |
4412 procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type) is | |
4413 begin | |
4414 if not Stream_Attribute_Available (Etype (Comp), TSS_Nam) then | |
4415 Error_Msg_Name_1 := Nam; | |
4416 Error_Msg_N | |
4417 ("|component& in limited extension must have% attribute", Comp); | |
4418 end if; | |
4419 end Check_Attr; | |
4420 | |
4421 -- Start of processing for Check_Stream_Attributes | |
4422 | |
4423 begin | |
4424 if Par_Read or else Par_Write then | |
4425 Comp := First_Component (Typ); | |
4426 while Present (Comp) loop | |
4427 if Comes_From_Source (Comp) | |
4428 and then Original_Record_Component (Comp) = Comp | |
4429 and then Is_Limited_Type (Etype (Comp)) | |
4430 then | |
4431 if Par_Read then | |
4432 Check_Attr (Name_Read, TSS_Stream_Read); | |
4433 end if; | |
4434 | |
4435 if Par_Write then | |
4436 Check_Attr (Name_Write, TSS_Stream_Write); | |
4437 end if; | |
4438 end if; | |
4439 | |
4440 Next_Component (Comp); | |
4441 end loop; | |
4442 end if; | |
4443 end Check_Stream_Attributes; | |
4444 | |
4445 ---------------------- | |
4446 -- Clean_Task_Names -- | |
4447 ---------------------- | |
4448 | |
4449 procedure Clean_Task_Names | |
4450 (Typ : Entity_Id; | |
4451 Proc_Id : Entity_Id) | |
4452 is | |
4453 begin | |
4454 if Has_Task (Typ) | |
4455 and then not Restriction_Active (No_Implicit_Heap_Allocations) | |
4456 and then not Global_Discard_Names | |
4457 and then Tagged_Type_Expansion | |
4458 then | |
4459 Set_Uses_Sec_Stack (Proc_Id); | |
4460 end if; | |
4461 end Clean_Task_Names; | |
4462 | |
4463 ------------------------------ | |
4464 -- Expand_Freeze_Array_Type -- | |
4465 ------------------------------ | |
4466 | |
4467 procedure Expand_Freeze_Array_Type (N : Node_Id) is | |
4468 Typ : constant Entity_Id := Entity (N); | |
4469 Base : constant Entity_Id := Base_Type (Typ); | |
4470 Comp_Typ : constant Entity_Id := Component_Type (Typ); | |
4471 | |
4472 begin | |
4473 if not Is_Bit_Packed_Array (Typ) then | |
4474 | |
4475 -- If the component contains tasks, so does the array type. This may | |
4476 -- not be indicated in the array type because the component may have | |
4477 -- been a private type at the point of definition. Same if component | |
4478 -- type is controlled or contains protected objects. | |
4479 | |
4480 Propagate_Concurrent_Flags (Base, Comp_Typ); | |
4481 Set_Has_Controlled_Component | |
4482 (Base, Has_Controlled_Component (Comp_Typ) | |
4483 or else Is_Controlled (Comp_Typ)); | |
4484 | |
4485 if No (Init_Proc (Base)) then | |
4486 | |
4487 -- If this is an anonymous array created for a declaration with | |
4488 -- an initial value, its init_proc will never be called. The | |
4489 -- initial value itself may have been expanded into assignments, | |
4490 -- in which case the object declaration is carries the | |
4491 -- No_Initialization flag. | |
4492 | |
4493 if Is_Itype (Base) | |
4494 and then Nkind (Associated_Node_For_Itype (Base)) = | |
4495 N_Object_Declaration | |
4496 and then | |
4497 (Present (Expression (Associated_Node_For_Itype (Base))) | |
4498 or else No_Initialization (Associated_Node_For_Itype (Base))) | |
4499 then | |
4500 null; | |
4501 | |
4502 -- We do not need an init proc for string or wide [wide] string, | |
4503 -- since the only time these need initialization in normalize or | |
4504 -- initialize scalars mode, and these types are treated specially | |
4505 -- and do not need initialization procedures. | |
4506 | |
4507 elsif Is_Standard_String_Type (Base) then | |
4508 null; | |
4509 | |
4510 -- Otherwise we have to build an init proc for the subtype | |
4511 | |
4512 else | |
4513 Build_Array_Init_Proc (Base, N); | |
4514 end if; | |
4515 end if; | |
4516 | |
4517 if Typ = Base and then Has_Controlled_Component (Base) then | |
4518 Build_Controlling_Procs (Base); | |
4519 | |
4520 if not Is_Limited_Type (Comp_Typ) | |
4521 and then Number_Dimensions (Typ) = 1 | |
4522 then | |
4523 Build_Slice_Assignment (Typ); | |
4524 end if; | |
4525 end if; | |
4526 | |
4527 -- For packed case, default initialization, except if the component type | |
4528 -- is itself a packed structure with an initialization procedure, or | |
4529 -- initialize/normalize scalars active, and we have a base type, or the | |
4530 -- type is public, because in that case a client might specify | |
4531 -- Normalize_Scalars and there better be a public Init_Proc for it. | |
4532 | |
4533 elsif (Present (Init_Proc (Component_Type (Base))) | |
4534 and then No (Base_Init_Proc (Base))) | |
4535 or else (Init_Or_Norm_Scalars and then Base = Typ) | |
4536 or else Is_Public (Typ) | |
4537 then | |
4538 Build_Array_Init_Proc (Base, N); | |
4539 end if; | |
4540 end Expand_Freeze_Array_Type; | |
4541 | |
4542 ----------------------------------- | |
4543 -- Expand_Freeze_Class_Wide_Type -- | |
4544 ----------------------------------- | |
4545 | |
4546 procedure Expand_Freeze_Class_Wide_Type (N : Node_Id) is | |
4547 function Is_C_Derivation (Typ : Entity_Id) return Boolean; | |
4548 -- Given a type, determine whether it is derived from a C or C++ root | |
4549 | |
4550 --------------------- | |
4551 -- Is_C_Derivation -- | |
4552 --------------------- | |
4553 | |
4554 function Is_C_Derivation (Typ : Entity_Id) return Boolean is | |
4555 T : Entity_Id; | |
4556 | |
4557 begin | |
4558 T := Typ; | |
4559 loop | |
4560 if Is_CPP_Class (T) | |
4561 or else Convention (T) = Convention_C | |
4562 or else Convention (T) = Convention_CPP | |
4563 then | |
4564 return True; | |
4565 end if; | |
4566 | |
4567 exit when T = Etype (T); | |
4568 | |
4569 T := Etype (T); | |
4570 end loop; | |
4571 | |
4572 return False; | |
4573 end Is_C_Derivation; | |
4574 | |
4575 -- Local variables | |
4576 | |
4577 Typ : constant Entity_Id := Entity (N); | |
4578 Root : constant Entity_Id := Root_Type (Typ); | |
4579 | |
4580 -- Start of processing for Expand_Freeze_Class_Wide_Type | |
4581 | |
4582 begin | |
4583 -- Certain run-time configurations and targets do not provide support | |
4584 -- for controlled types. | |
4585 | |
4586 if Restriction_Active (No_Finalization) then | |
4587 return; | |
4588 | |
4589 -- Do not create TSS routine Finalize_Address when dispatching calls are | |
4590 -- disabled since the core of the routine is a dispatching call. | |
4591 | |
4592 elsif Restriction_Active (No_Dispatching_Calls) then | |
4593 return; | |
4594 | |
4595 -- Do not create TSS routine Finalize_Address for concurrent class-wide | |
4596 -- types. Ignore C, C++, CIL and Java types since it is assumed that the | |
4597 -- non-Ada side will handle their destruction. | |
4598 | |
4599 elsif Is_Concurrent_Type (Root) | |
4600 or else Is_C_Derivation (Root) | |
4601 or else Convention (Typ) = Convention_CPP | |
4602 then | |
4603 return; | |
4604 | |
4605 -- Do not create TSS routine Finalize_Address when compiling in CodePeer | |
4606 -- mode since the routine contains an Unchecked_Conversion. | |
4607 | |
4608 elsif CodePeer_Mode then | |
4609 return; | |
4610 end if; | |
4611 | |
4612 -- Create the body of TSS primitive Finalize_Address. This automatically | |
4613 -- sets the TSS entry for the class-wide type. | |
4614 | |
4615 Make_Finalize_Address_Body (Typ); | |
4616 end Expand_Freeze_Class_Wide_Type; | |
4617 | |
4618 ------------------------------------ | |
4619 -- Expand_Freeze_Enumeration_Type -- | |
4620 ------------------------------------ | |
4621 | |
4622 procedure Expand_Freeze_Enumeration_Type (N : Node_Id) is | |
4623 Typ : constant Entity_Id := Entity (N); | |
4624 Loc : constant Source_Ptr := Sloc (Typ); | |
4625 | |
4626 Arr : Entity_Id; | |
4627 Ent : Entity_Id; | |
4628 Fent : Entity_Id; | |
4629 Is_Contiguous : Boolean; | |
4630 Ityp : Entity_Id; | |
4631 Last_Repval : Uint; | |
4632 Lst : List_Id; | |
4633 Num : Nat; | |
4634 Pos_Expr : Node_Id; | |
4635 | |
4636 Func : Entity_Id; | |
4637 pragma Warnings (Off, Func); | |
4638 | |
4639 begin | |
4640 -- Various optimizations possible if given representation is contiguous | |
4641 | |
4642 Is_Contiguous := True; | |
4643 | |
4644 Ent := First_Literal (Typ); | |
4645 Last_Repval := Enumeration_Rep (Ent); | |
4646 | |
4647 Next_Literal (Ent); | |
4648 while Present (Ent) loop | |
4649 if Enumeration_Rep (Ent) - Last_Repval /= 1 then | |
4650 Is_Contiguous := False; | |
4651 exit; | |
4652 else | |
4653 Last_Repval := Enumeration_Rep (Ent); | |
4654 end if; | |
4655 | |
4656 Next_Literal (Ent); | |
4657 end loop; | |
4658 | |
4659 if Is_Contiguous then | |
4660 Set_Has_Contiguous_Rep (Typ); | |
4661 Ent := First_Literal (Typ); | |
4662 Num := 1; | |
4663 Lst := New_List (New_Occurrence_Of (Ent, Sloc (Ent))); | |
4664 | |
4665 else | |
4666 -- Build list of literal references | |
4667 | |
4668 Lst := New_List; | |
4669 Num := 0; | |
4670 | |
4671 Ent := First_Literal (Typ); | |
4672 while Present (Ent) loop | |
4673 Append_To (Lst, New_Occurrence_Of (Ent, Sloc (Ent))); | |
4674 Num := Num + 1; | |
4675 Next_Literal (Ent); | |
4676 end loop; | |
4677 end if; | |
4678 | |
4679 -- Now build an array declaration | |
4680 | |
4681 -- typA : array (Natural range 0 .. num - 1) of ctype := | |
4682 -- (v, v, v, v, v, ....) | |
4683 | |
4684 -- where ctype is the corresponding integer type. If the representation | |
4685 -- is contiguous, we only keep the first literal, which provides the | |
4686 -- offset for Pos_To_Rep computations. | |
4687 | |
4688 Arr := | |
4689 Make_Defining_Identifier (Loc, | |
4690 Chars => New_External_Name (Chars (Typ), 'A')); | |
4691 | |
4692 Append_Freeze_Action (Typ, | |
4693 Make_Object_Declaration (Loc, | |
4694 Defining_Identifier => Arr, | |
4695 Constant_Present => True, | |
4696 | |
4697 Object_Definition => | |
4698 Make_Constrained_Array_Definition (Loc, | |
4699 Discrete_Subtype_Definitions => New_List ( | |
4700 Make_Subtype_Indication (Loc, | |
4701 Subtype_Mark => New_Occurrence_Of (Standard_Natural, Loc), | |
4702 Constraint => | |
4703 Make_Range_Constraint (Loc, | |
4704 Range_Expression => | |
4705 Make_Range (Loc, | |
4706 Low_Bound => | |
4707 Make_Integer_Literal (Loc, 0), | |
4708 High_Bound => | |
4709 Make_Integer_Literal (Loc, Num - 1))))), | |
4710 | |
4711 Component_Definition => | |
4712 Make_Component_Definition (Loc, | |
4713 Aliased_Present => False, | |
4714 Subtype_Indication => New_Occurrence_Of (Typ, Loc))), | |
4715 | |
4716 Expression => | |
4717 Make_Aggregate (Loc, | |
4718 Expressions => Lst))); | |
4719 | |
4720 Set_Enum_Pos_To_Rep (Typ, Arr); | |
4721 | |
4722 -- Now we build the function that converts representation values to | |
4723 -- position values. This function has the form: | |
4724 | |
4725 -- function _Rep_To_Pos (A : etype; F : Boolean) return Integer is | |
4726 -- begin | |
4727 -- case ityp!(A) is | |
4728 -- when enum-lit'Enum_Rep => return posval; | |
4729 -- when enum-lit'Enum_Rep => return posval; | |
4730 -- ... | |
4731 -- when others => | |
4732 -- [raise Constraint_Error when F "invalid data"] | |
4733 -- return -1; | |
4734 -- end case; | |
4735 -- end; | |
4736 | |
4737 -- Note: the F parameter determines whether the others case (no valid | |
4738 -- representation) raises Constraint_Error or returns a unique value | |
4739 -- of minus one. The latter case is used, e.g. in 'Valid code. | |
4740 | |
4741 -- Note: the reason we use Enum_Rep values in the case here is to avoid | |
4742 -- the code generator making inappropriate assumptions about the range | |
4743 -- of the values in the case where the value is invalid. ityp is a | |
4744 -- signed or unsigned integer type of appropriate width. | |
4745 | |
4746 -- Note: if exceptions are not supported, then we suppress the raise | |
4747 -- and return -1 unconditionally (this is an erroneous program in any | |
4748 -- case and there is no obligation to raise Constraint_Error here). We | |
4749 -- also do this if pragma Restrictions (No_Exceptions) is active. | |
4750 | |
4751 -- Is this right??? What about No_Exception_Propagation??? | |
4752 | |
4753 -- Representations are signed | |
4754 | |
4755 if Enumeration_Rep (First_Literal (Typ)) < 0 then | |
4756 | |
4757 -- The underlying type is signed. Reset the Is_Unsigned_Type | |
4758 -- explicitly, because it might have been inherited from | |
4759 -- parent type. | |
4760 | |
4761 Set_Is_Unsigned_Type (Typ, False); | |
4762 | |
4763 if Esize (Typ) <= Standard_Integer_Size then | |
4764 Ityp := Standard_Integer; | |
4765 else | |
4766 Ityp := Universal_Integer; | |
4767 end if; | |
4768 | |
4769 -- Representations are unsigned | |
4770 | |
4771 else | |
4772 if Esize (Typ) <= Standard_Integer_Size then | |
4773 Ityp := RTE (RE_Unsigned); | |
4774 else | |
4775 Ityp := RTE (RE_Long_Long_Unsigned); | |
4776 end if; | |
4777 end if; | |
4778 | |
4779 -- The body of the function is a case statement. First collect case | |
4780 -- alternatives, or optimize the contiguous case. | |
4781 | |
4782 Lst := New_List; | |
4783 | |
4784 -- If representation is contiguous, Pos is computed by subtracting | |
4785 -- the representation of the first literal. | |
4786 | |
4787 if Is_Contiguous then | |
4788 Ent := First_Literal (Typ); | |
4789 | |
4790 if Enumeration_Rep (Ent) = Last_Repval then | |
4791 | |
4792 -- Another special case: for a single literal, Pos is zero | |
4793 | |
4794 Pos_Expr := Make_Integer_Literal (Loc, Uint_0); | |
4795 | |
4796 else | |
4797 Pos_Expr := | |
4798 Convert_To (Standard_Integer, | |
4799 Make_Op_Subtract (Loc, | |
4800 Left_Opnd => | |
4801 Unchecked_Convert_To | |
4802 (Ityp, Make_Identifier (Loc, Name_uA)), | |
4803 Right_Opnd => | |
4804 Make_Integer_Literal (Loc, | |
4805 Intval => Enumeration_Rep (First_Literal (Typ))))); | |
4806 end if; | |
4807 | |
4808 Append_To (Lst, | |
4809 Make_Case_Statement_Alternative (Loc, | |
4810 Discrete_Choices => New_List ( | |
4811 Make_Range (Sloc (Enumeration_Rep_Expr (Ent)), | |
4812 Low_Bound => | |
4813 Make_Integer_Literal (Loc, | |
4814 Intval => Enumeration_Rep (Ent)), | |
4815 High_Bound => | |
4816 Make_Integer_Literal (Loc, Intval => Last_Repval))), | |
4817 | |
4818 Statements => New_List ( | |
4819 Make_Simple_Return_Statement (Loc, | |
4820 Expression => Pos_Expr)))); | |
4821 | |
4822 else | |
4823 Ent := First_Literal (Typ); | |
4824 while Present (Ent) loop | |
4825 Append_To (Lst, | |
4826 Make_Case_Statement_Alternative (Loc, | |
4827 Discrete_Choices => New_List ( | |
4828 Make_Integer_Literal (Sloc (Enumeration_Rep_Expr (Ent)), | |
4829 Intval => Enumeration_Rep (Ent))), | |
4830 | |
4831 Statements => New_List ( | |
4832 Make_Simple_Return_Statement (Loc, | |
4833 Expression => | |
4834 Make_Integer_Literal (Loc, | |
4835 Intval => Enumeration_Pos (Ent)))))); | |
4836 | |
4837 Next_Literal (Ent); | |
4838 end loop; | |
4839 end if; | |
4840 | |
4841 -- In normal mode, add the others clause with the test. | |
4842 -- If Predicates_Ignored is True, validity checks do not apply to | |
4843 -- the subtype. | |
4844 | |
4845 if not No_Exception_Handlers_Set | |
4846 and then not Predicates_Ignored (Typ) | |
4847 then | |
4848 Append_To (Lst, | |
4849 Make_Case_Statement_Alternative (Loc, | |
4850 Discrete_Choices => New_List (Make_Others_Choice (Loc)), | |
4851 Statements => New_List ( | |
4852 Make_Raise_Constraint_Error (Loc, | |
4853 Condition => Make_Identifier (Loc, Name_uF), | |
4854 Reason => CE_Invalid_Data), | |
4855 Make_Simple_Return_Statement (Loc, | |
4856 Expression => Make_Integer_Literal (Loc, -1))))); | |
4857 | |
4858 -- If either of the restrictions No_Exceptions_Handlers/Propagation is | |
4859 -- active then return -1 (we cannot usefully raise Constraint_Error in | |
4860 -- this case). See description above for further details. | |
4861 | |
4862 else | |
4863 Append_To (Lst, | |
4864 Make_Case_Statement_Alternative (Loc, | |
4865 Discrete_Choices => New_List (Make_Others_Choice (Loc)), | |
4866 Statements => New_List ( | |
4867 Make_Simple_Return_Statement (Loc, | |
4868 Expression => Make_Integer_Literal (Loc, -1))))); | |
4869 end if; | |
4870 | |
4871 -- Now we can build the function body | |
4872 | |
4873 Fent := | |
4874 Make_Defining_Identifier (Loc, Make_TSS_Name (Typ, TSS_Rep_To_Pos)); | |
4875 | |
4876 Func := | |
4877 Make_Subprogram_Body (Loc, | |
4878 Specification => | |
4879 Make_Function_Specification (Loc, | |
4880 Defining_Unit_Name => Fent, | |
4881 Parameter_Specifications => New_List ( | |
4882 Make_Parameter_Specification (Loc, | |
4883 Defining_Identifier => | |
4884 Make_Defining_Identifier (Loc, Name_uA), | |
4885 Parameter_Type => New_Occurrence_Of (Typ, Loc)), | |
4886 Make_Parameter_Specification (Loc, | |
4887 Defining_Identifier => | |
4888 Make_Defining_Identifier (Loc, Name_uF), | |
4889 Parameter_Type => | |
4890 New_Occurrence_Of (Standard_Boolean, Loc))), | |
4891 | |
4892 Result_Definition => New_Occurrence_Of (Standard_Integer, Loc)), | |
4893 | |
4894 Declarations => Empty_List, | |
4895 | |
4896 Handled_Statement_Sequence => | |
4897 Make_Handled_Sequence_Of_Statements (Loc, | |
4898 Statements => New_List ( | |
4899 Make_Case_Statement (Loc, | |
4900 Expression => | |
4901 Unchecked_Convert_To | |
4902 (Ityp, Make_Identifier (Loc, Name_uA)), | |
4903 Alternatives => Lst)))); | |
4904 | |
4905 Set_TSS (Typ, Fent); | |
4906 | |
4907 -- Set Pure flag (it will be reset if the current context is not Pure). | |
4908 -- We also pretend there was a pragma Pure_Function so that for purposes | |
4909 -- of optimization and constant-folding, we will consider the function | |
4910 -- Pure even if we are not in a Pure context). | |
4911 | |
4912 Set_Is_Pure (Fent); | |
4913 Set_Has_Pragma_Pure_Function (Fent); | |
4914 | |
4915 -- Unless we are in -gnatD mode, where we are debugging generated code, | |
4916 -- this is an internal entity for which we don't need debug info. | |
4917 | |
4918 if not Debug_Generated_Code then | |
4919 Set_Debug_Info_Off (Fent); | |
4920 end if; | |
4921 | |
4922 Set_Is_Inlined (Fent); | |
4923 | |
4924 exception | |
4925 when RE_Not_Available => | |
4926 return; | |
4927 end Expand_Freeze_Enumeration_Type; | |
4928 | |
4929 ------------------------------- | |
4930 -- Expand_Freeze_Record_Type -- | |
4931 ------------------------------- | |
4932 | |
4933 procedure Expand_Freeze_Record_Type (N : Node_Id) is | |
4934 Typ : constant Node_Id := Entity (N); | |
4935 Typ_Decl : constant Node_Id := Parent (Typ); | |
4936 | |
4937 Comp : Entity_Id; | |
4938 Comp_Typ : Entity_Id; | |
4939 Predef_List : List_Id; | |
4940 | |
4941 Wrapper_Decl_List : List_Id := No_List; | |
4942 Wrapper_Body_List : List_Id := No_List; | |
4943 | |
4944 Renamed_Eq : Node_Id := Empty; | |
4945 -- Defining unit name for the predefined equality function in the case | |
4946 -- where the type has a primitive operation that is a renaming of | |
4947 -- predefined equality (but only if there is also an overriding | |
4948 -- user-defined equality function). Used to pass this entity from | |
4949 -- Make_Predefined_Primitive_Specs to Predefined_Primitive_Bodies. | |
4950 | |
4951 -- Start of processing for Expand_Freeze_Record_Type | |
4952 | |
4953 begin | |
4954 -- Build discriminant checking functions if not a derived type (for | |
4955 -- derived types that are not tagged types, always use the discriminant | |
4956 -- checking functions of the parent type). However, for untagged types | |
4957 -- the derivation may have taken place before the parent was frozen, so | |
4958 -- we copy explicitly the discriminant checking functions from the | |
4959 -- parent into the components of the derived type. | |
4960 | |
4961 if not Is_Derived_Type (Typ) | |
4962 or else Has_New_Non_Standard_Rep (Typ) | |
4963 or else Is_Tagged_Type (Typ) | |
4964 then | |
4965 Build_Discr_Checking_Funcs (Typ_Decl); | |
4966 | |
4967 elsif Is_Derived_Type (Typ) | |
4968 and then not Is_Tagged_Type (Typ) | |
4969 | |
4970 -- If we have a derived Unchecked_Union, we do not inherit the | |
4971 -- discriminant checking functions from the parent type since the | |
4972 -- discriminants are non existent. | |
4973 | |
4974 and then not Is_Unchecked_Union (Typ) | |
4975 and then Has_Discriminants (Typ) | |
4976 then | |
4977 declare | |
4978 Old_Comp : Entity_Id; | |
4979 | |
4980 begin | |
4981 Old_Comp := | |
4982 First_Component (Base_Type (Underlying_Type (Etype (Typ)))); | |
4983 Comp := First_Component (Typ); | |
4984 while Present (Comp) loop | |
4985 if Ekind (Comp) = E_Component | |
4986 and then Chars (Comp) = Chars (Old_Comp) | |
4987 then | |
4988 Set_Discriminant_Checking_Func | |
4989 (Comp, Discriminant_Checking_Func (Old_Comp)); | |
4990 end if; | |
4991 | |
4992 Next_Component (Old_Comp); | |
4993 Next_Component (Comp); | |
4994 end loop; | |
4995 end; | |
4996 end if; | |
4997 | |
4998 if Is_Derived_Type (Typ) | |
4999 and then Is_Limited_Type (Typ) | |
5000 and then Is_Tagged_Type (Typ) | |
5001 then | |
5002 Check_Stream_Attributes (Typ); | |
5003 end if; | |
5004 | |
5005 -- Update task, protected, and controlled component flags, because some | |
5006 -- of the component types may have been private at the point of the | |
5007 -- record declaration. Detect anonymous access-to-controlled components. | |
5008 | |
5009 Comp := First_Component (Typ); | |
5010 while Present (Comp) loop | |
5011 Comp_Typ := Etype (Comp); | |
5012 | |
5013 Propagate_Concurrent_Flags (Typ, Comp_Typ); | |
5014 | |
5015 -- Do not set Has_Controlled_Component on a class-wide equivalent | |
5016 -- type. See Make_CW_Equivalent_Type. | |
5017 | |
5018 if not Is_Class_Wide_Equivalent_Type (Typ) | |
5019 and then | |
5020 (Has_Controlled_Component (Comp_Typ) | |
5021 or else (Chars (Comp) /= Name_uParent | |
5022 and then Is_Controlled (Comp_Typ))) | |
5023 then | |
5024 Set_Has_Controlled_Component (Typ); | |
5025 end if; | |
5026 | |
5027 Next_Component (Comp); | |
5028 end loop; | |
5029 | |
5030 -- Handle constructors of untagged CPP_Class types | |
5031 | |
5032 if not Is_Tagged_Type (Typ) and then Is_CPP_Class (Typ) then | |
5033 Set_CPP_Constructors (Typ); | |
5034 end if; | |
5035 | |
5036 -- Creation of the Dispatch Table. Note that a Dispatch Table is built | |
5037 -- for regular tagged types as well as for Ada types deriving from a C++ | |
5038 -- Class, but not for tagged types directly corresponding to C++ classes | |
5039 -- In the later case we assume that it is created in the C++ side and we | |
5040 -- just use it. | |
5041 | |
5042 if Is_Tagged_Type (Typ) then | |
5043 | |
5044 -- Add the _Tag component | |
5045 | |
5046 if Underlying_Type (Etype (Typ)) = Typ then | |
5047 Expand_Tagged_Root (Typ); | |
5048 end if; | |
5049 | |
5050 if Is_CPP_Class (Typ) then | |
5051 Set_All_DT_Position (Typ); | |
5052 | |
5053 -- Create the tag entities with a minimum decoration | |
5054 | |
5055 if Tagged_Type_Expansion then | |
5056 Append_Freeze_Actions (Typ, Make_Tags (Typ)); | |
5057 end if; | |
5058 | |
5059 Set_CPP_Constructors (Typ); | |
5060 | |
5061 else | |
5062 if not Building_Static_DT (Typ) then | |
5063 | |
5064 -- Usually inherited primitives are not delayed but the first | |
5065 -- Ada extension of a CPP_Class is an exception since the | |
5066 -- address of the inherited subprogram has to be inserted in | |
5067 -- the new Ada Dispatch Table and this is a freezing action. | |
5068 | |
5069 -- Similarly, if this is an inherited operation whose parent is | |
5070 -- not frozen yet, it is not in the DT of the parent, and we | |
5071 -- generate an explicit freeze node for the inherited operation | |
5072 -- so it is properly inserted in the DT of the current type. | |
5073 | |
5074 declare | |
5075 Elmt : Elmt_Id; | |
5076 Subp : Entity_Id; | |
5077 | |
5078 begin | |
5079 Elmt := First_Elmt (Primitive_Operations (Typ)); | |
5080 while Present (Elmt) loop | |
5081 Subp := Node (Elmt); | |
5082 | |
5083 if Present (Alias (Subp)) then | |
5084 if Is_CPP_Class (Etype (Typ)) then | |
5085 Set_Has_Delayed_Freeze (Subp); | |
5086 | |
5087 elsif Has_Delayed_Freeze (Alias (Subp)) | |
5088 and then not Is_Frozen (Alias (Subp)) | |
5089 then | |
5090 Set_Is_Frozen (Subp, False); | |
5091 Set_Has_Delayed_Freeze (Subp); | |
5092 end if; | |
5093 end if; | |
5094 | |
5095 Next_Elmt (Elmt); | |
5096 end loop; | |
5097 end; | |
5098 end if; | |
5099 | |
5100 -- Unfreeze momentarily the type to add the predefined primitives | |
5101 -- operations. The reason we unfreeze is so that these predefined | |
5102 -- operations will indeed end up as primitive operations (which | |
5103 -- must be before the freeze point). | |
5104 | |
5105 Set_Is_Frozen (Typ, False); | |
5106 | |
5107 -- Do not add the spec of predefined primitives in case of | |
5108 -- CPP tagged type derivations that have convention CPP. | |
5109 | |
5110 if Is_CPP_Class (Root_Type (Typ)) | |
5111 and then Convention (Typ) = Convention_CPP | |
5112 then | |
5113 null; | |
5114 | |
5115 -- Do not add the spec of the predefined primitives if we are | |
5116 -- compiling under restriction No_Dispatching_Calls. | |
5117 | |
5118 elsif not Restriction_Active (No_Dispatching_Calls) then | |
5119 Make_Predefined_Primitive_Specs (Typ, Predef_List, Renamed_Eq); | |
5120 Insert_List_Before_And_Analyze (N, Predef_List); | |
5121 end if; | |
5122 | |
5123 -- Ada 2005 (AI-391): For a nonabstract null extension, create | |
5124 -- wrapper functions for each nonoverridden inherited function | |
5125 -- with a controlling result of the type. The wrapper for such | |
5126 -- a function returns an extension aggregate that invokes the | |
5127 -- parent function. | |
5128 | |
5129 if Ada_Version >= Ada_2005 | |
5130 and then not Is_Abstract_Type (Typ) | |
5131 and then Is_Null_Extension (Typ) | |
5132 then | |
5133 Make_Controlling_Function_Wrappers | |
5134 (Typ, Wrapper_Decl_List, Wrapper_Body_List); | |
5135 Insert_List_Before_And_Analyze (N, Wrapper_Decl_List); | |
5136 end if; | |
5137 | |
5138 -- Ada 2005 (AI-251): For a nonabstract type extension, build | |
5139 -- null procedure declarations for each set of homographic null | |
5140 -- procedures that are inherited from interface types but not | |
5141 -- overridden. This is done to ensure that the dispatch table | |
5142 -- entry associated with such null primitives are properly filled. | |
5143 | |
5144 if Ada_Version >= Ada_2005 | |
5145 and then Etype (Typ) /= Typ | |
5146 and then not Is_Abstract_Type (Typ) | |
5147 and then Has_Interfaces (Typ) | |
5148 then | |
5149 Insert_Actions (N, Make_Null_Procedure_Specs (Typ)); | |
5150 end if; | |
5151 | |
5152 Set_Is_Frozen (Typ); | |
5153 | |
5154 if not Is_Derived_Type (Typ) | |
5155 or else Is_Tagged_Type (Etype (Typ)) | |
5156 then | |
5157 Set_All_DT_Position (Typ); | |
5158 | |
5159 -- If this is a type derived from an untagged private type whose | |
5160 -- full view is tagged, the type is marked tagged for layout | |
5161 -- reasons, but it has no dispatch table. | |
5162 | |
5163 elsif Is_Derived_Type (Typ) | |
5164 and then Is_Private_Type (Etype (Typ)) | |
5165 and then not Is_Tagged_Type (Etype (Typ)) | |
5166 then | |
5167 return; | |
5168 end if; | |
5169 | |
5170 -- Create and decorate the tags. Suppress their creation when | |
5171 -- not Tagged_Type_Expansion because the dispatching mechanism is | |
5172 -- handled internally by the virtual target. | |
5173 | |
5174 if Tagged_Type_Expansion then | |
5175 Append_Freeze_Actions (Typ, Make_Tags (Typ)); | |
5176 | |
5177 -- Generate dispatch table of locally defined tagged type. | |
5178 -- Dispatch tables of library level tagged types are built | |
5179 -- later (see Analyze_Declarations). | |
5180 | |
5181 if not Building_Static_DT (Typ) then | |
5182 Append_Freeze_Actions (Typ, Make_DT (Typ)); | |
5183 end if; | |
5184 end if; | |
5185 | |
5186 -- If the type has unknown discriminants, propagate dispatching | |
5187 -- information to its underlying record view, which does not get | |
5188 -- its own dispatch table. | |
5189 | |
5190 if Is_Derived_Type (Typ) | |
5191 and then Has_Unknown_Discriminants (Typ) | |
5192 and then Present (Underlying_Record_View (Typ)) | |
5193 then | |
5194 declare | |
5195 Rep : constant Entity_Id := Underlying_Record_View (Typ); | |
5196 begin | |
5197 Set_Access_Disp_Table | |
5198 (Rep, Access_Disp_Table (Typ)); | |
5199 Set_Dispatch_Table_Wrappers | |
5200 (Rep, Dispatch_Table_Wrappers (Typ)); | |
5201 Set_Direct_Primitive_Operations | |
5202 (Rep, Direct_Primitive_Operations (Typ)); | |
5203 end; | |
5204 end if; | |
5205 | |
5206 -- Make sure that the primitives Initialize, Adjust and Finalize | |
5207 -- are Frozen before other TSS subprograms. We don't want them | |
5208 -- Frozen inside. | |
5209 | |
5210 if Is_Controlled (Typ) then | |
5211 if not Is_Limited_Type (Typ) then | |
5212 Append_Freeze_Actions (Typ, | |
5213 Freeze_Entity (Find_Prim_Op (Typ, Name_Adjust), Typ)); | |
5214 end if; | |
5215 | |
5216 Append_Freeze_Actions (Typ, | |
5217 Freeze_Entity (Find_Prim_Op (Typ, Name_Initialize), Typ)); | |
5218 | |
5219 Append_Freeze_Actions (Typ, | |
5220 Freeze_Entity (Find_Prim_Op (Typ, Name_Finalize), Typ)); | |
5221 end if; | |
5222 | |
5223 -- Freeze rest of primitive operations. There is no need to handle | |
5224 -- the predefined primitives if we are compiling under restriction | |
5225 -- No_Dispatching_Calls. | |
5226 | |
5227 if not Restriction_Active (No_Dispatching_Calls) then | |
5228 Append_Freeze_Actions (Typ, Predefined_Primitive_Freeze (Typ)); | |
5229 end if; | |
5230 end if; | |
5231 | |
5232 -- In the untagged case, ever since Ada 83 an equality function must | |
5233 -- be provided for variant records that are not unchecked unions. | |
5234 -- In Ada 2012 the equality function composes, and thus must be built | |
5235 -- explicitly just as for tagged records. | |
5236 | |
5237 elsif Has_Discriminants (Typ) | |
5238 and then not Is_Limited_Type (Typ) | |
5239 then | |
5240 declare | |
5241 Comps : constant Node_Id := | |
5242 Component_List (Type_Definition (Typ_Decl)); | |
5243 begin | |
5244 if Present (Comps) | |
5245 and then Present (Variant_Part (Comps)) | |
5246 then | |
5247 Build_Variant_Record_Equality (Typ); | |
5248 end if; | |
5249 end; | |
5250 | |
5251 -- Otherwise create primitive equality operation (AI05-0123) | |
5252 | |
5253 -- This is done unconditionally to ensure that tools can be linked | |
5254 -- properly with user programs compiled with older language versions. | |
5255 -- In addition, this is needed because "=" composes for bounded strings | |
5256 -- in all language versions (see Exp_Ch4.Expand_Composite_Equality). | |
5257 | |
5258 elsif Comes_From_Source (Typ) | |
5259 and then Convention (Typ) = Convention_Ada | |
5260 and then not Is_Limited_Type (Typ) | |
5261 then | |
5262 Build_Untagged_Equality (Typ); | |
5263 end if; | |
5264 | |
5265 -- Before building the record initialization procedure, if we are | |
5266 -- dealing with a concurrent record value type, then we must go through | |
5267 -- the discriminants, exchanging discriminals between the concurrent | |
5268 -- type and the concurrent record value type. See the section "Handling | |
5269 -- of Discriminants" in the Einfo spec for details. | |
5270 | |
5271 if Is_Concurrent_Record_Type (Typ) | |
5272 and then Has_Discriminants (Typ) | |
5273 then | |
5274 declare | |
5275 Ctyp : constant Entity_Id := | |
5276 Corresponding_Concurrent_Type (Typ); | |
5277 Conc_Discr : Entity_Id; | |
5278 Rec_Discr : Entity_Id; | |
5279 Temp : Entity_Id; | |
5280 | |
5281 begin | |
5282 Conc_Discr := First_Discriminant (Ctyp); | |
5283 Rec_Discr := First_Discriminant (Typ); | |
5284 while Present (Conc_Discr) loop | |
5285 Temp := Discriminal (Conc_Discr); | |
5286 Set_Discriminal (Conc_Discr, Discriminal (Rec_Discr)); | |
5287 Set_Discriminal (Rec_Discr, Temp); | |
5288 | |
5289 Set_Discriminal_Link (Discriminal (Conc_Discr), Conc_Discr); | |
5290 Set_Discriminal_Link (Discriminal (Rec_Discr), Rec_Discr); | |
5291 | |
5292 Next_Discriminant (Conc_Discr); | |
5293 Next_Discriminant (Rec_Discr); | |
5294 end loop; | |
5295 end; | |
5296 end if; | |
5297 | |
5298 if Has_Controlled_Component (Typ) then | |
5299 Build_Controlling_Procs (Typ); | |
5300 end if; | |
5301 | |
5302 Adjust_Discriminants (Typ); | |
5303 | |
5304 -- Do not need init for interfaces on virtual targets since they're | |
5305 -- abstract. | |
5306 | |
5307 if Tagged_Type_Expansion or else not Is_Interface (Typ) then | |
5308 Build_Record_Init_Proc (Typ_Decl, Typ); | |
5309 end if; | |
5310 | |
5311 -- For tagged type that are not interfaces, build bodies of primitive | |
5312 -- operations. Note: do this after building the record initialization | |
5313 -- procedure, since the primitive operations may need the initialization | |
5314 -- routine. There is no need to add predefined primitives of interfaces | |
5315 -- because all their predefined primitives are abstract. | |
5316 | |
5317 if Is_Tagged_Type (Typ) and then not Is_Interface (Typ) then | |
5318 | |
5319 -- Do not add the body of predefined primitives in case of CPP tagged | |
5320 -- type derivations that have convention CPP. | |
5321 | |
5322 if Is_CPP_Class (Root_Type (Typ)) | |
5323 and then Convention (Typ) = Convention_CPP | |
5324 then | |
5325 null; | |
5326 | |
5327 -- Do not add the body of the predefined primitives if we are | |
5328 -- compiling under restriction No_Dispatching_Calls or if we are | |
5329 -- compiling a CPP tagged type. | |
5330 | |
5331 elsif not Restriction_Active (No_Dispatching_Calls) then | |
5332 | |
5333 -- Create the body of TSS primitive Finalize_Address. This must | |
5334 -- be done before the bodies of all predefined primitives are | |
5335 -- created. If Typ is limited, Stream_Input and Stream_Read may | |
5336 -- produce build-in-place allocations and for those the expander | |
5337 -- needs Finalize_Address. | |
5338 | |
5339 Make_Finalize_Address_Body (Typ); | |
5340 Predef_List := Predefined_Primitive_Bodies (Typ, Renamed_Eq); | |
5341 Append_Freeze_Actions (Typ, Predef_List); | |
5342 end if; | |
5343 | |
5344 -- Ada 2005 (AI-391): If any wrappers were created for nonoverridden | |
5345 -- inherited functions, then add their bodies to the freeze actions. | |
5346 | |
5347 if Present (Wrapper_Body_List) then | |
5348 Append_Freeze_Actions (Typ, Wrapper_Body_List); | |
5349 end if; | |
5350 | |
5351 -- Create extra formals for the primitive operations of the type. | |
5352 -- This must be done before analyzing the body of the initialization | |
5353 -- procedure, because a self-referential type might call one of these | |
5354 -- primitives in the body of the init_proc itself. | |
5355 | |
5356 declare | |
5357 Elmt : Elmt_Id; | |
5358 Subp : Entity_Id; | |
5359 | |
5360 begin | |
5361 Elmt := First_Elmt (Primitive_Operations (Typ)); | |
5362 while Present (Elmt) loop | |
5363 Subp := Node (Elmt); | |
5364 if not Has_Foreign_Convention (Subp) | |
5365 and then not Is_Predefined_Dispatching_Operation (Subp) | |
5366 then | |
5367 Create_Extra_Formals (Subp); | |
5368 end if; | |
5369 | |
5370 Next_Elmt (Elmt); | |
5371 end loop; | |
5372 end; | |
5373 end if; | |
5374 end Expand_Freeze_Record_Type; | |
5375 | |
5376 ------------------------------------ | |
5377 -- Expand_N_Full_Type_Declaration -- | |
5378 ------------------------------------ | |
5379 | |
5380 procedure Expand_N_Full_Type_Declaration (N : Node_Id) is | |
5381 procedure Build_Master (Ptr_Typ : Entity_Id); | |
5382 -- Create the master associated with Ptr_Typ | |
5383 | |
5384 ------------------ | |
5385 -- Build_Master -- | |
5386 ------------------ | |
5387 | |
5388 procedure Build_Master (Ptr_Typ : Entity_Id) is | |
5389 Desig_Typ : Entity_Id := Designated_Type (Ptr_Typ); | |
5390 | |
5391 begin | |
5392 -- If the designated type is an incomplete view coming from a | |
5393 -- limited-with'ed package, we need to use the nonlimited view in | |
5394 -- case it has tasks. | |
5395 | |
5396 if Ekind (Desig_Typ) in Incomplete_Kind | |
5397 and then Present (Non_Limited_View (Desig_Typ)) | |
5398 then | |
5399 Desig_Typ := Non_Limited_View (Desig_Typ); | |
5400 end if; | |
5401 | |
5402 -- Anonymous access types are created for the components of the | |
5403 -- record parameter for an entry declaration. No master is created | |
5404 -- for such a type. | |
5405 | |
5406 if Comes_From_Source (N) and then Has_Task (Desig_Typ) then | |
5407 Build_Master_Entity (Ptr_Typ); | |
5408 Build_Master_Renaming (Ptr_Typ); | |
5409 | |
5410 -- Create a class-wide master because a Master_Id must be generated | |
5411 -- for access-to-limited-class-wide types whose root may be extended | |
5412 -- with task components. | |
5413 | |
5414 -- Note: This code covers access-to-limited-interfaces because they | |
5415 -- can be used to reference tasks implementing them. | |
5416 | |
5417 elsif Is_Limited_Class_Wide_Type (Desig_Typ) | |
5418 and then Tasking_Allowed | |
5419 then | |
5420 Build_Class_Wide_Master (Ptr_Typ); | |
5421 end if; | |
5422 end Build_Master; | |
5423 | |
5424 -- Local declarations | |
5425 | |
5426 Def_Id : constant Entity_Id := Defining_Identifier (N); | |
5427 B_Id : constant Entity_Id := Base_Type (Def_Id); | |
5428 FN : Node_Id; | |
5429 Par_Id : Entity_Id; | |
5430 | |
5431 -- Start of processing for Expand_N_Full_Type_Declaration | |
5432 | |
5433 begin | |
5434 if Is_Access_Type (Def_Id) then | |
5435 Build_Master (Def_Id); | |
5436 | |
5437 if Ekind (Def_Id) = E_Access_Protected_Subprogram_Type then | |
5438 Expand_Access_Protected_Subprogram_Type (N); | |
5439 end if; | |
5440 | |
5441 -- Array of anonymous access-to-task pointers | |
5442 | |
5443 elsif Ada_Version >= Ada_2005 | |
5444 and then Is_Array_Type (Def_Id) | |
5445 and then Is_Access_Type (Component_Type (Def_Id)) | |
5446 and then Ekind (Component_Type (Def_Id)) = E_Anonymous_Access_Type | |
5447 then | |
5448 Build_Master (Component_Type (Def_Id)); | |
5449 | |
5450 elsif Has_Task (Def_Id) then | |
5451 Expand_Previous_Access_Type (Def_Id); | |
5452 | |
5453 -- Check the components of a record type or array of records for | |
5454 -- anonymous access-to-task pointers. | |
5455 | |
5456 elsif Ada_Version >= Ada_2005 | |
5457 and then (Is_Record_Type (Def_Id) | |
5458 or else | |
5459 (Is_Array_Type (Def_Id) | |
5460 and then Is_Record_Type (Component_Type (Def_Id)))) | |
5461 then | |
5462 declare | |
5463 Comp : Entity_Id; | |
5464 First : Boolean; | |
5465 M_Id : Entity_Id; | |
5466 Typ : Entity_Id; | |
5467 | |
5468 begin | |
5469 if Is_Array_Type (Def_Id) then | |
5470 Comp := First_Entity (Component_Type (Def_Id)); | |
5471 else | |
5472 Comp := First_Entity (Def_Id); | |
5473 end if; | |
5474 | |
5475 -- Examine all components looking for anonymous access-to-task | |
5476 -- types. | |
5477 | |
5478 First := True; | |
5479 while Present (Comp) loop | |
5480 Typ := Etype (Comp); | |
5481 | |
5482 if Ekind (Typ) = E_Anonymous_Access_Type | |
5483 and then Has_Task (Available_View (Designated_Type (Typ))) | |
5484 and then No (Master_Id (Typ)) | |
5485 then | |
5486 -- Ensure that the record or array type have a _master | |
5487 | |
5488 if First then | |
5489 Build_Master_Entity (Def_Id); | |
5490 Build_Master_Renaming (Typ); | |
5491 M_Id := Master_Id (Typ); | |
5492 | |
5493 First := False; | |
5494 | |
5495 -- Reuse the same master to service any additional types | |
5496 | |
5497 else | |
5498 Set_Master_Id (Typ, M_Id); | |
5499 end if; | |
5500 end if; | |
5501 | |
5502 Next_Entity (Comp); | |
5503 end loop; | |
5504 end; | |
5505 end if; | |
5506 | |
5507 Par_Id := Etype (B_Id); | |
5508 | |
5509 -- The parent type is private then we need to inherit any TSS operations | |
5510 -- from the full view. | |
5511 | |
5512 if Ekind (Par_Id) in Private_Kind | |
5513 and then Present (Full_View (Par_Id)) | |
5514 then | |
5515 Par_Id := Base_Type (Full_View (Par_Id)); | |
5516 end if; | |
5517 | |
5518 if Nkind (Type_Definition (Original_Node (N))) = | |
5519 N_Derived_Type_Definition | |
5520 and then not Is_Tagged_Type (Def_Id) | |
5521 and then Present (Freeze_Node (Par_Id)) | |
5522 and then Present (TSS_Elist (Freeze_Node (Par_Id))) | |
5523 then | |
5524 Ensure_Freeze_Node (B_Id); | |
5525 FN := Freeze_Node (B_Id); | |
5526 | |
5527 if No (TSS_Elist (FN)) then | |
5528 Set_TSS_Elist (FN, New_Elmt_List); | |
5529 end if; | |
5530 | |
5531 declare | |
5532 T_E : constant Elist_Id := TSS_Elist (FN); | |
5533 Elmt : Elmt_Id; | |
5534 | |
5535 begin | |
5536 Elmt := First_Elmt (TSS_Elist (Freeze_Node (Par_Id))); | |
5537 while Present (Elmt) loop | |
5538 if Chars (Node (Elmt)) /= Name_uInit then | |
5539 Append_Elmt (Node (Elmt), T_E); | |
5540 end if; | |
5541 | |
5542 Next_Elmt (Elmt); | |
5543 end loop; | |
5544 | |
5545 -- If the derived type itself is private with a full view, then | |
5546 -- associate the full view with the inherited TSS_Elist as well. | |
5547 | |
5548 if Ekind (B_Id) in Private_Kind | |
5549 and then Present (Full_View (B_Id)) | |
5550 then | |
5551 Ensure_Freeze_Node (Base_Type (Full_View (B_Id))); | |
5552 Set_TSS_Elist | |
5553 (Freeze_Node (Base_Type (Full_View (B_Id))), TSS_Elist (FN)); | |
5554 end if; | |
5555 end; | |
5556 end if; | |
5557 end Expand_N_Full_Type_Declaration; | |
5558 | |
5559 --------------------------------- | |
5560 -- Expand_N_Object_Declaration -- | |
5561 --------------------------------- | |
5562 | |
5563 procedure Expand_N_Object_Declaration (N : Node_Id) is | |
5564 Loc : constant Source_Ptr := Sloc (N); | |
5565 Def_Id : constant Entity_Id := Defining_Identifier (N); | |
5566 Expr : constant Node_Id := Expression (N); | |
5567 Obj_Def : constant Node_Id := Object_Definition (N); | |
5568 Typ : constant Entity_Id := Etype (Def_Id); | |
5569 Base_Typ : constant Entity_Id := Base_Type (Typ); | |
5570 Expr_Q : Node_Id; | |
5571 | |
5572 function Build_Equivalent_Aggregate return Boolean; | |
5573 -- If the object has a constrained discriminated type and no initial | |
5574 -- value, it may be possible to build an equivalent aggregate instead, | |
5575 -- and prevent an actual call to the initialization procedure. | |
5576 | |
5577 procedure Check_Large_Modular_Array; | |
5578 -- Check that the size of the array can be computed without overflow, | |
5579 -- and generate a Storage_Error otherwise. This is only relevant for | |
5580 -- array types whose index in a (mod 2**64) type, where wrap-around | |
5581 -- arithmetic might yield a meaningless value for the length of the | |
5582 -- array, or its corresponding attribute. | |
5583 | |
5584 procedure Count_Default_Sized_Task_Stacks | |
5585 (Typ : Entity_Id; | |
5586 Pri_Stacks : out Int; | |
5587 Sec_Stacks : out Int); | |
5588 -- Count the number of default-sized primary and secondary task stacks | |
5589 -- required for task objects contained within type Typ. If the number of | |
5590 -- task objects contained within the type is not known at compile time | |
5591 -- the procedure will return the stack counts of zero. | |
5592 | |
5593 procedure Default_Initialize_Object (After : Node_Id); | |
5594 -- Generate all default initialization actions for object Def_Id. Any | |
5595 -- new code is inserted after node After. | |
5596 | |
5597 function Rewrite_As_Renaming return Boolean; | |
5598 -- Indicate whether to rewrite a declaration with initialization into an | |
5599 -- object renaming declaration (see below). | |
5600 | |
5601 -------------------------------- | |
5602 -- Build_Equivalent_Aggregate -- | |
5603 -------------------------------- | |
5604 | |
5605 function Build_Equivalent_Aggregate return Boolean is | |
5606 Aggr : Node_Id; | |
5607 Comp : Entity_Id; | |
5608 Discr : Elmt_Id; | |
5609 Full_Type : Entity_Id; | |
5610 | |
5611 begin | |
5612 Full_Type := Typ; | |
5613 | |
5614 if Is_Private_Type (Typ) and then Present (Full_View (Typ)) then | |
5615 Full_Type := Full_View (Typ); | |
5616 end if; | |
5617 | |
5618 -- Only perform this transformation if Elaboration_Code is forbidden | |
5619 -- or undesirable, and if this is a global entity of a constrained | |
5620 -- record type. | |
5621 | |
5622 -- If Initialize_Scalars might be active this transformation cannot | |
5623 -- be performed either, because it will lead to different semantics | |
5624 -- or because elaboration code will in fact be created. | |
5625 | |
5626 if Ekind (Full_Type) /= E_Record_Subtype | |
5627 or else not Has_Discriminants (Full_Type) | |
5628 or else not Is_Constrained (Full_Type) | |
5629 or else Is_Controlled (Full_Type) | |
5630 or else Is_Limited_Type (Full_Type) | |
5631 or else not Restriction_Active (No_Initialize_Scalars) | |
5632 then | |
5633 return False; | |
5634 end if; | |
5635 | |
5636 if Ekind (Current_Scope) = E_Package | |
5637 and then | |
5638 (Restriction_Active (No_Elaboration_Code) | |
5639 or else Is_Preelaborated (Current_Scope)) | |
5640 then | |
5641 -- Building a static aggregate is possible if the discriminants | |
5642 -- have static values and the other components have static | |
5643 -- defaults or none. | |
5644 | |
5645 Discr := First_Elmt (Discriminant_Constraint (Full_Type)); | |
5646 while Present (Discr) loop | |
5647 if not Is_OK_Static_Expression (Node (Discr)) then | |
5648 return False; | |
5649 end if; | |
5650 | |
5651 Next_Elmt (Discr); | |
5652 end loop; | |
5653 | |
5654 -- Check that initialized components are OK, and that non- | |
5655 -- initialized components do not require a call to their own | |
5656 -- initialization procedure. | |
5657 | |
5658 Comp := First_Component (Full_Type); | |
5659 while Present (Comp) loop | |
5660 if Ekind (Comp) = E_Component | |
5661 and then Present (Expression (Parent (Comp))) | |
5662 and then | |
5663 not Is_OK_Static_Expression (Expression (Parent (Comp))) | |
5664 then | |
5665 return False; | |
5666 | |
5667 elsif Has_Non_Null_Base_Init_Proc (Etype (Comp)) then | |
5668 return False; | |
5669 | |
5670 end if; | |
5671 | |
5672 Next_Component (Comp); | |
5673 end loop; | |
5674 | |
5675 -- Everything is static, assemble the aggregate, discriminant | |
5676 -- values first. | |
5677 | |
5678 Aggr := | |
5679 Make_Aggregate (Loc, | |
5680 Expressions => New_List, | |
5681 Component_Associations => New_List); | |
5682 | |
5683 Discr := First_Elmt (Discriminant_Constraint (Full_Type)); | |
5684 while Present (Discr) loop | |
5685 Append_To (Expressions (Aggr), New_Copy (Node (Discr))); | |
5686 Next_Elmt (Discr); | |
5687 end loop; | |
5688 | |
5689 -- Now collect values of initialized components | |
5690 | |
5691 Comp := First_Component (Full_Type); | |
5692 while Present (Comp) loop | |
5693 if Ekind (Comp) = E_Component | |
5694 and then Present (Expression (Parent (Comp))) | |
5695 then | |
5696 Append_To (Component_Associations (Aggr), | |
5697 Make_Component_Association (Loc, | |
5698 Choices => New_List (New_Occurrence_Of (Comp, Loc)), | |
5699 Expression => New_Copy_Tree | |
5700 (Expression (Parent (Comp))))); | |
5701 end if; | |
5702 | |
5703 Next_Component (Comp); | |
5704 end loop; | |
5705 | |
5706 -- Finally, box-initialize remaining components | |
5707 | |
5708 Append_To (Component_Associations (Aggr), | |
5709 Make_Component_Association (Loc, | |
5710 Choices => New_List (Make_Others_Choice (Loc)), | |
5711 Expression => Empty)); | |
5712 Set_Box_Present (Last (Component_Associations (Aggr))); | |
5713 Set_Expression (N, Aggr); | |
5714 | |
5715 if Typ /= Full_Type then | |
5716 Analyze_And_Resolve (Aggr, Full_View (Base_Type (Full_Type))); | |
5717 Rewrite (Aggr, Unchecked_Convert_To (Typ, Aggr)); | |
5718 Analyze_And_Resolve (Aggr, Typ); | |
5719 else | |
5720 Analyze_And_Resolve (Aggr, Full_Type); | |
5721 end if; | |
5722 | |
5723 return True; | |
5724 | |
5725 else | |
5726 return False; | |
5727 end if; | |
5728 end Build_Equivalent_Aggregate; | |
5729 | |
5730 ------------------------------- | |
5731 -- Check_Large_Modular_Array -- | |
5732 ------------------------------- | |
5733 | |
5734 procedure Check_Large_Modular_Array is | |
5735 Index_Typ : Entity_Id; | |
5736 | |
5737 begin | |
5738 if Is_Array_Type (Typ) | |
5739 and then Is_Modular_Integer_Type (Etype (First_Index (Typ))) | |
5740 then | |
5741 -- To prevent arithmetic overflow with large values, we raise | |
5742 -- Storage_Error under the following guard: | |
5743 | |
5744 -- (Arr'Last / 2 - Arr'First / 2) > (2 ** 30) | |
5745 | |
5746 -- This takes care of the boundary case, but it is preferable to | |
5747 -- use a smaller limit, because even on 64-bit architectures an | |
5748 -- array of more than 2 ** 30 bytes is likely to raise | |
5749 -- Storage_Error. | |
5750 | |
5751 Index_Typ := Etype (First_Index (Typ)); | |
5752 | |
5753 if RM_Size (Index_Typ) = RM_Size (Standard_Long_Long_Integer) then | |
5754 Insert_Action (N, | |
5755 Make_Raise_Storage_Error (Loc, | |
5756 Condition => | |
5757 Make_Op_Ge (Loc, | |
5758 Left_Opnd => | |
5759 Make_Op_Subtract (Loc, | |
5760 Left_Opnd => | |
5761 Make_Op_Divide (Loc, | |
5762 Left_Opnd => | |
5763 Make_Attribute_Reference (Loc, | |
5764 Prefix => | |
5765 New_Occurrence_Of (Typ, Loc), | |
5766 Attribute_Name => Name_Last), | |
5767 Right_Opnd => | |
5768 Make_Integer_Literal (Loc, Uint_2)), | |
5769 Right_Opnd => | |
5770 Make_Op_Divide (Loc, | |
5771 Left_Opnd => | |
5772 Make_Attribute_Reference (Loc, | |
5773 Prefix => | |
5774 New_Occurrence_Of (Typ, Loc), | |
5775 Attribute_Name => Name_First), | |
5776 Right_Opnd => | |
5777 Make_Integer_Literal (Loc, Uint_2))), | |
5778 Right_Opnd => | |
5779 Make_Integer_Literal (Loc, (Uint_2 ** 30))), | |
5780 Reason => SE_Object_Too_Large)); | |
5781 end if; | |
5782 end if; | |
5783 end Check_Large_Modular_Array; | |
5784 | |
5785 ------------------------------------- | |
5786 -- Count_Default_Sized_Task_Stacks -- | |
5787 ------------------------------------- | |
5788 | |
5789 procedure Count_Default_Sized_Task_Stacks | |
5790 (Typ : Entity_Id; | |
5791 Pri_Stacks : out Int; | |
5792 Sec_Stacks : out Int) | |
5793 is | |
5794 Component : Entity_Id; | |
5795 | |
5796 begin | |
5797 -- To calculate the number of default-sized task stacks required for | |
5798 -- an object of Typ, a depth-first recursive traversal of the AST | |
5799 -- from the Typ entity node is undertaken. Only type nodes containing | |
5800 -- task objects are visited. | |
5801 | |
5802 Pri_Stacks := 0; | |
5803 Sec_Stacks := 0; | |
5804 | |
5805 if not Has_Task (Typ) then | |
5806 return; | |
5807 end if; | |
5808 | |
5809 case Ekind (Typ) is | |
5810 when E_Task_Subtype | |
5811 | E_Task_Type | |
5812 => | |
5813 -- A task type is found marking the bottom of the descent. If | |
5814 -- the type has no representation aspect for the corresponding | |
5815 -- stack then that stack is using the default size. | |
5816 | |
5817 if Present (Get_Rep_Item (Typ, Name_Storage_Size)) then | |
5818 Pri_Stacks := 0; | |
5819 else | |
5820 Pri_Stacks := 1; | |
5821 end if; | |
5822 | |
5823 if Present (Get_Rep_Item (Typ, Name_Secondary_Stack_Size)) then | |
5824 Sec_Stacks := 0; | |
5825 else | |
5826 Sec_Stacks := 1; | |
5827 end if; | |
5828 | |
5829 when E_Array_Subtype | |
5830 | E_Array_Type | |
5831 => | |
5832 -- First find the number of default stacks contained within an | |
5833 -- array component. | |
5834 | |
5835 Count_Default_Sized_Task_Stacks | |
5836 (Component_Type (Typ), | |
5837 Pri_Stacks, | |
5838 Sec_Stacks); | |
5839 | |
5840 -- Then multiply the result by the size of the array | |
5841 | |
5842 declare | |
5843 Quantity : constant Int := Number_Of_Elements_In_Array (Typ); | |
5844 -- Number_Of_Elements_In_Array is non-trival, consequently | |
5845 -- its result is captured as an optimization. | |
5846 | |
5847 begin | |
5848 Pri_Stacks := Pri_Stacks * Quantity; | |
5849 Sec_Stacks := Sec_Stacks * Quantity; | |
5850 end; | |
5851 | |
5852 when E_Protected_Subtype | |
5853 | E_Protected_Type | |
5854 | E_Record_Subtype | |
5855 | E_Record_Type | |
5856 => | |
5857 Component := First_Component_Or_Discriminant (Typ); | |
5858 | |
5859 -- Recursively descend each component of the composite type | |
5860 -- looking for tasks, but only if the component is marked as | |
5861 -- having a task. | |
5862 | |
5863 while Present (Component) loop | |
5864 if Has_Task (Etype (Component)) then | |
5865 declare | |
5866 P : Int; | |
5867 S : Int; | |
5868 | |
5869 begin | |
5870 Count_Default_Sized_Task_Stacks | |
5871 (Etype (Component), P, S); | |
5872 Pri_Stacks := Pri_Stacks + P; | |
5873 Sec_Stacks := Sec_Stacks + S; | |
5874 end; | |
5875 end if; | |
5876 | |
5877 Next_Component_Or_Discriminant (Component); | |
5878 end loop; | |
5879 | |
5880 when E_Limited_Private_Subtype | |
5881 | E_Limited_Private_Type | |
5882 | E_Record_Subtype_With_Private | |
5883 | E_Record_Type_With_Private | |
5884 => | |
5885 -- Switch to the full view of the private type to continue | |
5886 -- search. | |
5887 | |
5888 Count_Default_Sized_Task_Stacks | |
5889 (Full_View (Typ), Pri_Stacks, Sec_Stacks); | |
5890 | |
5891 -- Other types should not contain tasks | |
5892 | |
5893 when others => | |
5894 raise Program_Error; | |
5895 end case; | |
5896 end Count_Default_Sized_Task_Stacks; | |
5897 | |
5898 ------------------------------- | |
5899 -- Default_Initialize_Object -- | |
5900 ------------------------------- | |
5901 | |
5902 procedure Default_Initialize_Object (After : Node_Id) is | |
5903 function New_Object_Reference return Node_Id; | |
5904 -- Return a new reference to Def_Id with attributes Assignment_OK and | |
5905 -- Must_Not_Freeze already set. | |
5906 | |
5907 -------------------------- | |
5908 -- New_Object_Reference -- | |
5909 -------------------------- | |
5910 | |
5911 function New_Object_Reference return Node_Id is | |
5912 Obj_Ref : constant Node_Id := New_Occurrence_Of (Def_Id, Loc); | |
5913 | |
5914 begin | |
5915 -- The call to the type init proc or [Deep_]Finalize must not | |
5916 -- freeze the related object as the call is internally generated. | |
5917 -- This way legal rep clauses that apply to the object will not be | |
5918 -- flagged. Note that the initialization call may be removed if | |
5919 -- pragma Import is encountered or moved to the freeze actions of | |
5920 -- the object because of an address clause. | |
5921 | |
5922 Set_Assignment_OK (Obj_Ref); | |
5923 Set_Must_Not_Freeze (Obj_Ref); | |
5924 | |
5925 return Obj_Ref; | |
5926 end New_Object_Reference; | |
5927 | |
5928 -- Local variables | |
5929 | |
5930 Exceptions_OK : constant Boolean := | |
5931 not Restriction_Active (No_Exception_Propagation); | |
5932 | |
5933 Aggr_Init : Node_Id; | |
5934 Comp_Init : List_Id := No_List; | |
5935 Fin_Block : Node_Id; | |
5936 Fin_Call : Node_Id; | |
5937 Init_Stmts : List_Id := No_List; | |
5938 Obj_Init : Node_Id := Empty; | |
5939 Obj_Ref : Node_Id; | |
5940 | |
5941 -- Start of processing for Default_Initialize_Object | |
5942 | |
5943 begin | |
5944 -- Default initialization is suppressed for objects that are already | |
5945 -- known to be imported (i.e. whose declaration specifies the Import | |
5946 -- aspect). Note that for objects with a pragma Import, we generate | |
5947 -- initialization here, and then remove it downstream when processing | |
5948 -- the pragma. It is also suppressed for variables for which a pragma | |
5949 -- Suppress_Initialization has been explicitly given | |
5950 | |
5951 if Is_Imported (Def_Id) or else Suppress_Initialization (Def_Id) then | |
5952 return; | |
5953 | |
5954 -- Nothing to do if the object being initialized is of a task type | |
5955 -- and restriction No_Tasking is in effect, because this is a direct | |
5956 -- violation of the restriction. | |
5957 | |
5958 elsif Is_Task_Type (Base_Typ) | |
5959 and then Restriction_Active (No_Tasking) | |
5960 then | |
5961 return; | |
5962 end if; | |
5963 | |
5964 -- The expansion performed by this routine is as follows: | |
5965 | |
5966 -- begin | |
5967 -- Abort_Defer; | |
5968 -- Type_Init_Proc (Obj); | |
5969 | |
5970 -- begin | |
5971 -- [Deep_]Initialize (Obj); | |
5972 | |
5973 -- exception | |
5974 -- when others => | |
5975 -- [Deep_]Finalize (Obj, Self => False); | |
5976 -- raise; | |
5977 -- end; | |
5978 -- at end | |
5979 -- Abort_Undefer_Direct; | |
5980 -- end; | |
5981 | |
5982 -- Initialize the components of the object | |
5983 | |
5984 if Has_Non_Null_Base_Init_Proc (Typ) | |
5985 and then not No_Initialization (N) | |
5986 and then not Initialization_Suppressed (Typ) | |
5987 then | |
5988 -- Do not initialize the components if No_Default_Initialization | |
5989 -- applies as the actual restriction check will occur later | |
5990 -- when the object is frozen as it is not known yet whether the | |
5991 -- object is imported or not. | |
5992 | |
5993 if not Restriction_Active (No_Default_Initialization) then | |
5994 | |
5995 -- If the values of the components are compile-time known, use | |
5996 -- their prebuilt aggregate form directly. | |
5997 | |
5998 Aggr_Init := Static_Initialization (Base_Init_Proc (Typ)); | |
5999 | |
6000 if Present (Aggr_Init) then | |
6001 Set_Expression | |
6002 (N, New_Copy_Tree (Aggr_Init, New_Scope => Current_Scope)); | |
6003 | |
6004 -- If type has discriminants, try to build an equivalent | |
6005 -- aggregate using discriminant values from the declaration. | |
6006 -- This is a useful optimization, in particular if restriction | |
6007 -- No_Elaboration_Code is active. | |
6008 | |
6009 elsif Build_Equivalent_Aggregate then | |
6010 null; | |
6011 | |
6012 -- Otherwise invoke the type init proc, generate: | |
6013 -- Type_Init_Proc (Obj); | |
6014 | |
6015 else | |
6016 Obj_Ref := New_Object_Reference; | |
6017 | |
6018 if Comes_From_Source (Def_Id) then | |
6019 Initialization_Warning (Obj_Ref); | |
6020 end if; | |
6021 | |
6022 Comp_Init := Build_Initialization_Call (Loc, Obj_Ref, Typ); | |
6023 end if; | |
6024 end if; | |
6025 | |
6026 -- Provide a default value if the object needs simple initialization | |
6027 -- and does not already have an initial value. A generated temporary | |
6028 -- does not require initialization because it will be assigned later. | |
6029 | |
6030 elsif Needs_Simple_Initialization | |
6031 (Typ, Initialize_Scalars | |
6032 and then No (Following_Address_Clause (N))) | |
6033 and then not Is_Internal (Def_Id) | |
6034 and then not Has_Init_Expression (N) | |
6035 then | |
6036 Set_No_Initialization (N, False); | |
6037 Set_Expression (N, Get_Simple_Init_Val (Typ, N, Esize (Def_Id))); | |
6038 Analyze_And_Resolve (Expression (N), Typ); | |
6039 end if; | |
6040 | |
6041 -- Initialize the object, generate: | |
6042 -- [Deep_]Initialize (Obj); | |
6043 | |
6044 if Needs_Finalization (Typ) and then not No_Initialization (N) then | |
6045 Obj_Init := | |
6046 Make_Init_Call | |
6047 (Obj_Ref => New_Occurrence_Of (Def_Id, Loc), | |
6048 Typ => Typ); | |
6049 end if; | |
6050 | |
6051 -- Build a special finalization block when both the object and its | |
6052 -- controlled components are to be initialized. The block finalizes | |
6053 -- the components if the object initialization fails. Generate: | |
6054 | |
6055 -- begin | |
6056 -- <Obj_Init> | |
6057 | |
6058 -- exception | |
6059 -- when others => | |
6060 -- <Fin_Call> | |
6061 -- raise; | |
6062 -- end; | |
6063 | |
6064 if Has_Controlled_Component (Typ) | |
6065 and then Present (Comp_Init) | |
6066 and then Present (Obj_Init) | |
6067 and then Exceptions_OK | |
6068 then | |
6069 Init_Stmts := Comp_Init; | |
6070 | |
6071 Fin_Call := | |
6072 Make_Final_Call | |
6073 (Obj_Ref => New_Object_Reference, | |
6074 Typ => Typ, | |
6075 Skip_Self => True); | |
6076 | |
6077 if Present (Fin_Call) then | |
6078 Fin_Block := | |
6079 Make_Block_Statement (Loc, | |
6080 Declarations => No_List, | |
6081 | |
6082 Handled_Statement_Sequence => | |
6083 Make_Handled_Sequence_Of_Statements (Loc, | |
6084 Statements => New_List (Obj_Init), | |
6085 | |
6086 Exception_Handlers => New_List ( | |
6087 Make_Exception_Handler (Loc, | |
6088 Exception_Choices => New_List ( | |
6089 Make_Others_Choice (Loc)), | |
6090 | |
6091 Statements => New_List ( | |
6092 Fin_Call, | |
6093 Make_Raise_Statement (Loc)))))); | |
6094 | |
6095 -- Signal the ABE mechanism that the block carries out | |
6096 -- initialization actions. | |
6097 | |
6098 Set_Is_Initialization_Block (Fin_Block); | |
6099 | |
6100 Append_To (Init_Stmts, Fin_Block); | |
6101 end if; | |
6102 | |
6103 -- Otherwise finalization is not required, the initialization calls | |
6104 -- are passed to the abort block building circuitry, generate: | |
6105 | |
6106 -- Type_Init_Proc (Obj); | |
6107 -- [Deep_]Initialize (Obj); | |
6108 | |
6109 else | |
6110 if Present (Comp_Init) then | |
6111 Init_Stmts := Comp_Init; | |
6112 end if; | |
6113 | |
6114 if Present (Obj_Init) then | |
6115 if No (Init_Stmts) then | |
6116 Init_Stmts := New_List; | |
6117 end if; | |
6118 | |
6119 Append_To (Init_Stmts, Obj_Init); | |
6120 end if; | |
6121 end if; | |
6122 | |
6123 -- Build an abort block to protect the initialization calls | |
6124 | |
6125 if Abort_Allowed | |
6126 and then Present (Comp_Init) | |
6127 and then Present (Obj_Init) | |
6128 then | |
6129 -- Generate: | |
6130 -- Abort_Defer; | |
6131 | |
6132 Prepend_To (Init_Stmts, Build_Runtime_Call (Loc, RE_Abort_Defer)); | |
6133 | |
6134 -- When exceptions are propagated, abort deferral must take place | |
6135 -- in the presence of initialization or finalization exceptions. | |
6136 -- Generate: | |
6137 | |
6138 -- begin | |
6139 -- Abort_Defer; | |
6140 -- <Init_Stmts> | |
6141 -- at end | |
6142 -- Abort_Undefer_Direct; | |
6143 -- end; | |
6144 | |
6145 if Exceptions_OK then | |
6146 Init_Stmts := New_List ( | |
6147 Build_Abort_Undefer_Block (Loc, | |
6148 Stmts => Init_Stmts, | |
6149 Context => N)); | |
6150 | |
6151 -- Otherwise exceptions are not propagated. Generate: | |
6152 | |
6153 -- Abort_Defer; | |
6154 -- <Init_Stmts> | |
6155 -- Abort_Undefer; | |
6156 | |
6157 else | |
6158 Append_To (Init_Stmts, | |
6159 Build_Runtime_Call (Loc, RE_Abort_Undefer)); | |
6160 end if; | |
6161 end if; | |
6162 | |
6163 -- Insert the whole initialization sequence into the tree. If the | |
6164 -- object has a delayed freeze, as will be the case when it has | |
6165 -- aspect specifications, the initialization sequence is part of | |
6166 -- the freeze actions. | |
6167 | |
6168 if Present (Init_Stmts) then | |
6169 if Has_Delayed_Freeze (Def_Id) then | |
6170 Append_Freeze_Actions (Def_Id, Init_Stmts); | |
6171 else | |
6172 Insert_Actions_After (After, Init_Stmts); | |
6173 end if; | |
6174 end if; | |
6175 end Default_Initialize_Object; | |
6176 | |
6177 ------------------------- | |
6178 -- Rewrite_As_Renaming -- | |
6179 ------------------------- | |
6180 | |
6181 function Rewrite_As_Renaming return Boolean is | |
6182 begin | |
6183 -- If the object declaration appears in the form | |
6184 | |
6185 -- Obj : Ctrl_Typ := Func (...); | |
6186 | |
6187 -- where Ctrl_Typ is controlled but not immutably limited type, then | |
6188 -- the expansion of the function call should use a dereference of the | |
6189 -- result to reference the value on the secondary stack. | |
6190 | |
6191 -- Obj : Ctrl_Typ renames Func (...).all; | |
6192 | |
6193 -- As a result, the call avoids an extra copy. This an optimization, | |
6194 -- but it is required for passing ACATS tests in some cases where it | |
6195 -- would otherwise make two copies. The RM allows removing redunant | |
6196 -- Adjust/Finalize calls, but does not allow insertion of extra ones. | |
6197 | |
6198 -- This part is disabled for now, because it breaks GPS builds | |
6199 | |
6200 return (False -- ??? | |
6201 and then Nkind (Expr_Q) = N_Explicit_Dereference | |
6202 and then not Comes_From_Source (Expr_Q) | |
6203 and then Nkind (Original_Node (Expr_Q)) = N_Function_Call | |
6204 and then Nkind (Object_Definition (N)) in N_Has_Entity | |
6205 and then (Needs_Finalization (Entity (Object_Definition (N))))) | |
6206 | |
6207 -- If the initializing expression is for a variable with attribute | |
6208 -- OK_To_Rename set, then transform: | |
6209 | |
6210 -- Obj : Typ := Expr; | |
6211 | |
6212 -- into | |
6213 | |
6214 -- Obj : Typ renames Expr; | |
6215 | |
6216 -- provided that Obj is not aliased. The aliased case has to be | |
6217 -- excluded in general because Expr will not be aliased in | |
6218 -- general. | |
6219 | |
6220 or else | |
6221 (not Aliased_Present (N) | |
6222 and then Is_Entity_Name (Expr_Q) | |
6223 and then Ekind (Entity (Expr_Q)) = E_Variable | |
6224 and then OK_To_Rename (Entity (Expr_Q)) | |
6225 and then Is_Entity_Name (Obj_Def)); | |
6226 end Rewrite_As_Renaming; | |
6227 | |
6228 -- Local variables | |
6229 | |
6230 Next_N : constant Node_Id := Next (N); | |
6231 | |
6232 Adj_Call : Node_Id; | |
6233 Id_Ref : Node_Id; | |
6234 Tag_Assign : Node_Id; | |
6235 | |
6236 Init_After : Node_Id := N; | |
6237 -- Node after which the initialization actions are to be inserted. This | |
6238 -- is normally N, except for the case of a shared passive variable, in | |
6239 -- which case the init proc call must be inserted only after the bodies | |
6240 -- of the shared variable procedures have been seen. | |
6241 | |
6242 -- Start of processing for Expand_N_Object_Declaration | |
6243 | |
6244 begin | |
6245 -- Don't do anything for deferred constants. All proper actions will be | |
6246 -- expanded during the full declaration. | |
6247 | |
6248 if No (Expr) and Constant_Present (N) then | |
6249 return; | |
6250 end if; | |
6251 | |
6252 -- The type of the object cannot be abstract. This is diagnosed at the | |
6253 -- point the object is frozen, which happens after the declaration is | |
6254 -- fully expanded, so simply return now. | |
6255 | |
6256 if Is_Abstract_Type (Typ) then | |
6257 return; | |
6258 end if; | |
6259 | |
6260 -- No action needed for the internal imported dummy object added by | |
6261 -- Make_DT to compute the offset of the components that reference | |
6262 -- secondary dispatch tables; required to avoid never-ending loop | |
6263 -- processing this internal object declaration. | |
6264 | |
6265 if Tagged_Type_Expansion | |
6266 and then Is_Internal (Def_Id) | |
6267 and then Is_Imported (Def_Id) | |
6268 and then Related_Type (Def_Id) = Implementation_Base_Type (Typ) | |
6269 then | |
6270 return; | |
6271 end if; | |
6272 | |
6273 -- First we do special processing for objects of a tagged type where | |
6274 -- this is the point at which the type is frozen. The creation of the | |
6275 -- dispatch table and the initialization procedure have to be deferred | |
6276 -- to this point, since we reference previously declared primitive | |
6277 -- subprograms. | |
6278 | |
6279 -- Force construction of dispatch tables of library level tagged types | |
6280 | |
6281 if Tagged_Type_Expansion | |
6282 and then Static_Dispatch_Tables | |
6283 and then Is_Library_Level_Entity (Def_Id) | |
6284 and then Is_Library_Level_Tagged_Type (Base_Typ) | |
6285 and then Ekind_In (Base_Typ, E_Record_Type, | |
6286 E_Protected_Type, | |
6287 E_Task_Type) | |
6288 and then not Has_Dispatch_Table (Base_Typ) | |
6289 then | |
6290 declare | |
6291 New_Nodes : List_Id := No_List; | |
6292 | |
6293 begin | |
6294 if Is_Concurrent_Type (Base_Typ) then | |
6295 New_Nodes := Make_DT (Corresponding_Record_Type (Base_Typ), N); | |
6296 else | |
6297 New_Nodes := Make_DT (Base_Typ, N); | |
6298 end if; | |
6299 | |
6300 if not Is_Empty_List (New_Nodes) then | |
6301 Insert_List_Before (N, New_Nodes); | |
6302 end if; | |
6303 end; | |
6304 end if; | |
6305 | |
6306 -- Make shared memory routines for shared passive variable | |
6307 | |
6308 if Is_Shared_Passive (Def_Id) then | |
6309 Init_After := Make_Shared_Var_Procs (N); | |
6310 end if; | |
6311 | |
6312 -- If tasks being declared, make sure we have an activation chain | |
6313 -- defined for the tasks (has no effect if we already have one), and | |
6314 -- also that a Master variable is established and that the appropriate | |
6315 -- enclosing construct is established as a task master. | |
6316 | |
6317 if Has_Task (Typ) then | |
6318 Build_Activation_Chain_Entity (N); | |
6319 Build_Master_Entity (Def_Id); | |
6320 end if; | |
6321 | |
6322 Check_Large_Modular_Array; | |
6323 | |
6324 -- If No_Implicit_Heap_Allocations or No_Implicit_Task_Allocations | |
6325 -- restrictions are active then default-sized secondary stacks are | |
6326 -- generated by the binder and allocated by SS_Init. To provide the | |
6327 -- binder the number of stacks to generate, the number of default-sized | |
6328 -- stacks required for task objects contained within the object | |
6329 -- declaration N is calculated here as it is at this point where | |
6330 -- unconstrained types become constrained. The result is stored in the | |
6331 -- enclosing unit's Unit_Record. | |
6332 | |
6333 -- Note if N is an array object declaration that has an initialization | |
6334 -- expression, a second object declaration for the initialization | |
6335 -- expression is created by the compiler. To prevent double counting | |
6336 -- of the stacks in this scenario, the stacks of the first array are | |
6337 -- not counted. | |
6338 | |
6339 if Has_Task (Typ) | |
6340 and then not Restriction_Active (No_Secondary_Stack) | |
6341 and then (Restriction_Active (No_Implicit_Heap_Allocations) | |
6342 or else Restriction_Active (No_Implicit_Task_Allocations)) | |
6343 and then not (Ekind_In (Ekind (Typ), E_Array_Type, E_Array_Subtype) | |
6344 and then (Has_Init_Expression (N))) | |
6345 then | |
6346 declare | |
6347 PS_Count, SS_Count : Int := 0; | |
6348 begin | |
6349 Count_Default_Sized_Task_Stacks (Typ, PS_Count, SS_Count); | |
6350 Increment_Primary_Stack_Count (PS_Count); | |
6351 Increment_Sec_Stack_Count (SS_Count); | |
6352 end; | |
6353 end if; | |
6354 | |
6355 -- Default initialization required, and no expression present | |
6356 | |
6357 if No (Expr) then | |
6358 | |
6359 -- If we have a type with a variant part, the initialization proc | |
6360 -- will contain implicit tests of the discriminant values, which | |
6361 -- counts as a violation of the restriction No_Implicit_Conditionals. | |
6362 | |
6363 if Has_Variant_Part (Typ) then | |
6364 declare | |
6365 Msg : Boolean; | |
6366 | |
6367 begin | |
6368 Check_Restriction (Msg, No_Implicit_Conditionals, Obj_Def); | |
6369 | |
6370 if Msg then | |
6371 Error_Msg_N | |
6372 ("\initialization of variant record tests discriminants", | |
6373 Obj_Def); | |
6374 return; | |
6375 end if; | |
6376 end; | |
6377 end if; | |
6378 | |
6379 -- For the default initialization case, if we have a private type | |
6380 -- with invariants, and invariant checks are enabled, then insert an | |
6381 -- invariant check after the object declaration. Note that it is OK | |
6382 -- to clobber the object with an invalid value since if the exception | |
6383 -- is raised, then the object will go out of scope. In the case where | |
6384 -- an array object is initialized with an aggregate, the expression | |
6385 -- is removed. Check flag Has_Init_Expression to avoid generating a | |
6386 -- junk invariant check and flag No_Initialization to avoid checking | |
6387 -- an uninitialized object such as a compiler temporary used for an | |
6388 -- aggregate. | |
6389 | |
6390 if Has_Invariants (Base_Typ) | |
6391 and then Present (Invariant_Procedure (Base_Typ)) | |
6392 and then not Has_Init_Expression (N) | |
6393 and then not No_Initialization (N) | |
6394 then | |
6395 -- If entity has an address clause or aspect, make invariant | |
6396 -- call into a freeze action for the explicit freeze node for | |
6397 -- object. Otherwise insert invariant check after declaration. | |
6398 | |
6399 if Present (Following_Address_Clause (N)) | |
6400 or else Has_Aspect (Def_Id, Aspect_Address) | |
6401 then | |
6402 Ensure_Freeze_Node (Def_Id); | |
6403 Set_Has_Delayed_Freeze (Def_Id); | |
6404 Set_Is_Frozen (Def_Id, False); | |
6405 | |
6406 if not Partial_View_Has_Unknown_Discr (Typ) then | |
6407 Append_Freeze_Action (Def_Id, | |
6408 Make_Invariant_Call (New_Occurrence_Of (Def_Id, Loc))); | |
6409 end if; | |
6410 | |
6411 elsif not Partial_View_Has_Unknown_Discr (Typ) then | |
6412 Insert_After (N, | |
6413 Make_Invariant_Call (New_Occurrence_Of (Def_Id, Loc))); | |
6414 end if; | |
6415 end if; | |
6416 | |
6417 Default_Initialize_Object (Init_After); | |
6418 | |
6419 -- Generate attribute for Persistent_BSS if needed | |
6420 | |
6421 if Persistent_BSS_Mode | |
6422 and then Comes_From_Source (N) | |
6423 and then Is_Potentially_Persistent_Type (Typ) | |
6424 and then not Has_Init_Expression (N) | |
6425 and then Is_Library_Level_Entity (Def_Id) | |
6426 then | |
6427 declare | |
6428 Prag : Node_Id; | |
6429 begin | |
6430 Prag := | |
6431 Make_Linker_Section_Pragma | |
6432 (Def_Id, Sloc (N), ".persistent.bss"); | |
6433 Insert_After (N, Prag); | |
6434 Analyze (Prag); | |
6435 end; | |
6436 end if; | |
6437 | |
6438 -- If access type, then we know it is null if not initialized | |
6439 | |
6440 if Is_Access_Type (Typ) then | |
6441 Set_Is_Known_Null (Def_Id); | |
6442 end if; | |
6443 | |
6444 -- Explicit initialization present | |
6445 | |
6446 else | |
6447 -- Obtain actual expression from qualified expression | |
6448 | |
6449 if Nkind (Expr) = N_Qualified_Expression then | |
6450 Expr_Q := Expression (Expr); | |
6451 else | |
6452 Expr_Q := Expr; | |
6453 end if; | |
6454 | |
6455 -- When we have the appropriate type of aggregate in the expression | |
6456 -- (it has been determined during analysis of the aggregate by | |
6457 -- setting the delay flag), let's perform in place assignment and | |
6458 -- thus avoid creating a temporary. | |
6459 | |
6460 if Is_Delayed_Aggregate (Expr_Q) then | |
6461 Convert_Aggr_In_Object_Decl (N); | |
6462 | |
6463 -- Ada 2005 (AI-318-02): If the initialization expression is a call | |
6464 -- to a build-in-place function, then access to the declared object | |
6465 -- must be passed to the function. Currently we limit such functions | |
6466 -- to those with constrained limited result subtypes, but eventually | |
6467 -- plan to expand the allowed forms of functions that are treated as | |
6468 -- build-in-place. | |
6469 | |
6470 elsif Is_Build_In_Place_Function_Call (Expr_Q) then | |
6471 Make_Build_In_Place_Call_In_Object_Declaration (N, Expr_Q); | |
6472 | |
6473 -- The previous call expands the expression initializing the | |
6474 -- built-in-place object into further code that will be analyzed | |
6475 -- later. No further expansion needed here. | |
6476 | |
6477 return; | |
6478 | |
6479 -- This is the same as the previous 'elsif', except that the call has | |
6480 -- been transformed by other expansion activities into something like | |
6481 -- F(...)'Reference. | |
6482 | |
6483 elsif Nkind (Expr_Q) = N_Reference | |
6484 and then Is_Build_In_Place_Function_Call (Prefix (Expr_Q)) | |
6485 and then not Is_Expanded_Build_In_Place_Call | |
6486 (Unqual_Conv (Prefix (Expr_Q))) | |
6487 then | |
6488 Make_Build_In_Place_Call_In_Anonymous_Context (Prefix (Expr_Q)); | |
6489 | |
6490 -- The previous call expands the expression initializing the | |
6491 -- built-in-place object into further code that will be analyzed | |
6492 -- later. No further expansion needed here. | |
6493 | |
6494 return; | |
6495 | |
6496 -- Ada 2005 (AI-318-02): Specialization of the previous case for | |
6497 -- expressions containing a build-in-place function call whose | |
6498 -- returned object covers interface types, and Expr_Q has calls to | |
6499 -- Ada.Tags.Displace to displace the pointer to the returned build- | |
6500 -- in-place object to reference the secondary dispatch table of a | |
6501 -- covered interface type. | |
6502 | |
6503 elsif Present (Unqual_BIP_Iface_Function_Call (Expr_Q)) then | |
6504 Make_Build_In_Place_Iface_Call_In_Object_Declaration (N, Expr_Q); | |
6505 | |
6506 -- The previous call expands the expression initializing the | |
6507 -- built-in-place object into further code that will be analyzed | |
6508 -- later. No further expansion needed here. | |
6509 | |
6510 return; | |
6511 | |
6512 -- Ada 2005 (AI-251): Rewrite the expression that initializes a | |
6513 -- class-wide interface object to ensure that we copy the full | |
6514 -- object, unless we are targetting a VM where interfaces are handled | |
6515 -- by VM itself. Note that if the root type of Typ is an ancestor of | |
6516 -- Expr's type, both types share the same dispatch table and there is | |
6517 -- no need to displace the pointer. | |
6518 | |
6519 elsif Is_Interface (Typ) | |
6520 | |
6521 -- Avoid never-ending recursion because if Equivalent_Type is set | |
6522 -- then we've done it already and must not do it again. | |
6523 | |
6524 and then not | |
6525 (Nkind (Obj_Def) = N_Identifier | |
6526 and then Present (Equivalent_Type (Entity (Obj_Def)))) | |
6527 then | |
6528 pragma Assert (Is_Class_Wide_Type (Typ)); | |
6529 | |
6530 -- If the object is a return object of an inherently limited type, | |
6531 -- which implies build-in-place treatment, bypass the special | |
6532 -- treatment of class-wide interface initialization below. In this | |
6533 -- case, the expansion of the return statement will take care of | |
6534 -- creating the object (via allocator) and initializing it. | |
6535 | |
6536 if Is_Return_Object (Def_Id) and then Is_Limited_View (Typ) then | |
6537 null; | |
6538 | |
6539 elsif Tagged_Type_Expansion then | |
6540 declare | |
6541 Iface : constant Entity_Id := Root_Type (Typ); | |
6542 Expr_N : Node_Id := Expr; | |
6543 Expr_Typ : Entity_Id; | |
6544 New_Expr : Node_Id; | |
6545 Obj_Id : Entity_Id; | |
6546 Tag_Comp : Node_Id; | |
6547 | |
6548 begin | |
6549 -- If the original node of the expression was a conversion | |
6550 -- to this specific class-wide interface type then restore | |
6551 -- the original node because we must copy the object before | |
6552 -- displacing the pointer to reference the secondary tag | |
6553 -- component. This code must be kept synchronized with the | |
6554 -- expansion done by routine Expand_Interface_Conversion | |
6555 | |
6556 if not Comes_From_Source (Expr_N) | |
6557 and then Nkind (Expr_N) = N_Explicit_Dereference | |
6558 and then Nkind (Original_Node (Expr_N)) = N_Type_Conversion | |
6559 and then Etype (Original_Node (Expr_N)) = Typ | |
6560 then | |
6561 Rewrite (Expr_N, Original_Node (Expression (N))); | |
6562 end if; | |
6563 | |
6564 -- Avoid expansion of redundant interface conversion | |
6565 | |
6566 if Is_Interface (Etype (Expr_N)) | |
6567 and then Nkind (Expr_N) = N_Type_Conversion | |
6568 and then Etype (Expr_N) = Typ | |
6569 then | |
6570 Expr_N := Expression (Expr_N); | |
6571 Set_Expression (N, Expr_N); | |
6572 end if; | |
6573 | |
6574 Obj_Id := Make_Temporary (Loc, 'D', Expr_N); | |
6575 Expr_Typ := Base_Type (Etype (Expr_N)); | |
6576 | |
6577 if Is_Class_Wide_Type (Expr_Typ) then | |
6578 Expr_Typ := Root_Type (Expr_Typ); | |
6579 end if; | |
6580 | |
6581 -- Replace | |
6582 -- CW : I'Class := Obj; | |
6583 -- by | |
6584 -- Tmp : T := Obj; | |
6585 -- type Ityp is not null access I'Class; | |
6586 -- CW : I'Class renames Ityp (Tmp.I_Tag'Address).all; | |
6587 | |
6588 if Comes_From_Source (Expr_N) | |
6589 and then Nkind (Expr_N) = N_Identifier | |
6590 and then not Is_Interface (Expr_Typ) | |
6591 and then Interface_Present_In_Ancestor (Expr_Typ, Typ) | |
6592 and then (Expr_Typ = Etype (Expr_Typ) | |
6593 or else not | |
6594 Is_Variable_Size_Record (Etype (Expr_Typ))) | |
6595 then | |
6596 -- Copy the object | |
6597 | |
6598 Insert_Action (N, | |
6599 Make_Object_Declaration (Loc, | |
6600 Defining_Identifier => Obj_Id, | |
6601 Object_Definition => | |
6602 New_Occurrence_Of (Expr_Typ, Loc), | |
6603 Expression => Relocate_Node (Expr_N))); | |
6604 | |
6605 -- Statically reference the tag associated with the | |
6606 -- interface | |
6607 | |
6608 Tag_Comp := | |
6609 Make_Selected_Component (Loc, | |
6610 Prefix => New_Occurrence_Of (Obj_Id, Loc), | |
6611 Selector_Name => | |
6612 New_Occurrence_Of | |
6613 (Find_Interface_Tag (Expr_Typ, Iface), Loc)); | |
6614 | |
6615 -- Replace | |
6616 -- IW : I'Class := Obj; | |
6617 -- by | |
6618 -- type Equiv_Record is record ... end record; | |
6619 -- implicit subtype CW is <Class_Wide_Subtype>; | |
6620 -- Tmp : CW := CW!(Obj); | |
6621 -- type Ityp is not null access I'Class; | |
6622 -- IW : I'Class renames | |
6623 -- Ityp!(Displace (Temp'Address, I'Tag)).all; | |
6624 | |
6625 else | |
6626 -- Generate the equivalent record type and update the | |
6627 -- subtype indication to reference it. | |
6628 | |
6629 Expand_Subtype_From_Expr | |
6630 (N => N, | |
6631 Unc_Type => Typ, | |
6632 Subtype_Indic => Obj_Def, | |
6633 Exp => Expr_N); | |
6634 | |
6635 if not Is_Interface (Etype (Expr_N)) then | |
6636 New_Expr := Relocate_Node (Expr_N); | |
6637 | |
6638 -- For interface types we use 'Address which displaces | |
6639 -- the pointer to the base of the object (if required) | |
6640 | |
6641 else | |
6642 New_Expr := | |
6643 Unchecked_Convert_To (Etype (Obj_Def), | |
6644 Make_Explicit_Dereference (Loc, | |
6645 Unchecked_Convert_To (RTE (RE_Tag_Ptr), | |
6646 Make_Attribute_Reference (Loc, | |
6647 Prefix => Relocate_Node (Expr_N), | |
6648 Attribute_Name => Name_Address)))); | |
6649 end if; | |
6650 | |
6651 -- Copy the object | |
6652 | |
6653 if not Is_Limited_Record (Expr_Typ) then | |
6654 Insert_Action (N, | |
6655 Make_Object_Declaration (Loc, | |
6656 Defining_Identifier => Obj_Id, | |
6657 Object_Definition => | |
6658 New_Occurrence_Of (Etype (Obj_Def), Loc), | |
6659 Expression => New_Expr)); | |
6660 | |
6661 -- Rename limited type object since they cannot be copied | |
6662 -- This case occurs when the initialization expression | |
6663 -- has been previously expanded into a temporary object. | |
6664 | |
6665 else pragma Assert (not Comes_From_Source (Expr_Q)); | |
6666 Insert_Action (N, | |
6667 Make_Object_Renaming_Declaration (Loc, | |
6668 Defining_Identifier => Obj_Id, | |
6669 Subtype_Mark => | |
6670 New_Occurrence_Of (Etype (Obj_Def), Loc), | |
6671 Name => | |
6672 Unchecked_Convert_To | |
6673 (Etype (Obj_Def), New_Expr))); | |
6674 end if; | |
6675 | |
6676 -- Dynamically reference the tag associated with the | |
6677 -- interface. | |
6678 | |
6679 Tag_Comp := | |
6680 Make_Function_Call (Loc, | |
6681 Name => New_Occurrence_Of (RTE (RE_Displace), Loc), | |
6682 Parameter_Associations => New_List ( | |
6683 Make_Attribute_Reference (Loc, | |
6684 Prefix => New_Occurrence_Of (Obj_Id, Loc), | |
6685 Attribute_Name => Name_Address), | |
6686 New_Occurrence_Of | |
6687 (Node (First_Elmt (Access_Disp_Table (Iface))), | |
6688 Loc))); | |
6689 end if; | |
6690 | |
6691 Rewrite (N, | |
6692 Make_Object_Renaming_Declaration (Loc, | |
6693 Defining_Identifier => Make_Temporary (Loc, 'D'), | |
6694 Subtype_Mark => New_Occurrence_Of (Typ, Loc), | |
6695 Name => | |
6696 Convert_Tag_To_Interface (Typ, Tag_Comp))); | |
6697 | |
6698 -- If the original entity comes from source, then mark the | |
6699 -- new entity as needing debug information, even though it's | |
6700 -- defined by a generated renaming that does not come from | |
6701 -- source, so that Materialize_Entity will be set on the | |
6702 -- entity when Debug_Renaming_Declaration is called during | |
6703 -- analysis. | |
6704 | |
6705 if Comes_From_Source (Def_Id) then | |
6706 Set_Debug_Info_Needed (Defining_Identifier (N)); | |
6707 end if; | |
6708 | |
6709 Analyze (N, Suppress => All_Checks); | |
6710 | |
6711 -- Replace internal identifier of rewritten node by the | |
6712 -- identifier found in the sources. We also have to exchange | |
6713 -- entities containing their defining identifiers to ensure | |
6714 -- the correct replacement of the object declaration by this | |
6715 -- object renaming declaration because these identifiers | |
6716 -- were previously added by Enter_Name to the current scope. | |
6717 -- We must preserve the homonym chain of the source entity | |
6718 -- as well. We must also preserve the kind of the entity, | |
6719 -- which may be a constant. Preserve entity chain because | |
6720 -- itypes may have been generated already, and the full | |
6721 -- chain must be preserved for final freezing. Finally, | |
6722 -- preserve Comes_From_Source setting, so that debugging | |
6723 -- and cross-referencing information is properly kept, and | |
6724 -- preserve source location, to prevent spurious errors when | |
6725 -- entities are declared (they must have their own Sloc). | |
6726 | |
6727 declare | |
6728 New_Id : constant Entity_Id := Defining_Identifier (N); | |
6729 Next_Temp : constant Entity_Id := Next_Entity (New_Id); | |
6730 S_Flag : constant Boolean := | |
6731 Comes_From_Source (Def_Id); | |
6732 | |
6733 begin | |
6734 Set_Next_Entity (New_Id, Next_Entity (Def_Id)); | |
6735 Set_Next_Entity (Def_Id, Next_Temp); | |
6736 | |
6737 Set_Chars (Defining_Identifier (N), Chars (Def_Id)); | |
6738 Set_Homonym (Defining_Identifier (N), Homonym (Def_Id)); | |
6739 Set_Ekind (Defining_Identifier (N), Ekind (Def_Id)); | |
6740 Set_Sloc (Defining_Identifier (N), Sloc (Def_Id)); | |
6741 | |
6742 Set_Comes_From_Source (Def_Id, False); | |
6743 Exchange_Entities (Defining_Identifier (N), Def_Id); | |
6744 Set_Comes_From_Source (Def_Id, S_Flag); | |
6745 end; | |
6746 end; | |
6747 end if; | |
6748 | |
6749 return; | |
6750 | |
6751 -- Common case of explicit object initialization | |
6752 | |
6753 else | |
6754 -- In most cases, we must check that the initial value meets any | |
6755 -- constraint imposed by the declared type. However, there is one | |
6756 -- very important exception to this rule. If the entity has an | |
6757 -- unconstrained nominal subtype, then it acquired its constraints | |
6758 -- from the expression in the first place, and not only does this | |
6759 -- mean that the constraint check is not needed, but an attempt to | |
6760 -- perform the constraint check can cause order of elaboration | |
6761 -- problems. | |
6762 | |
6763 if not Is_Constr_Subt_For_U_Nominal (Typ) then | |
6764 | |
6765 -- If this is an allocator for an aggregate that has been | |
6766 -- allocated in place, delay checks until assignments are | |
6767 -- made, because the discriminants are not initialized. | |
6768 | |
6769 if Nkind (Expr) = N_Allocator | |
6770 and then No_Initialization (Expr) | |
6771 then | |
6772 null; | |
6773 | |
6774 -- Otherwise apply a constraint check now if no prev error | |
6775 | |
6776 elsif Nkind (Expr) /= N_Error then | |
6777 Apply_Constraint_Check (Expr, Typ); | |
6778 | |
6779 -- Deal with possible range check | |
6780 | |
6781 if Do_Range_Check (Expr) then | |
6782 | |
6783 -- If assignment checks are suppressed, turn off flag | |
6784 | |
6785 if Suppress_Assignment_Checks (N) then | |
6786 Set_Do_Range_Check (Expr, False); | |
6787 | |
6788 -- Otherwise generate the range check | |
6789 | |
6790 else | |
6791 Generate_Range_Check | |
6792 (Expr, Typ, CE_Range_Check_Failed); | |
6793 end if; | |
6794 end if; | |
6795 end if; | |
6796 end if; | |
6797 | |
6798 -- If the type is controlled and not inherently limited, then | |
6799 -- the target is adjusted after the copy and attached to the | |
6800 -- finalization list. However, no adjustment is done in the case | |
6801 -- where the object was initialized by a call to a function whose | |
6802 -- result is built in place, since no copy occurred. Similarly, no | |
6803 -- adjustment is required if we are going to rewrite the object | |
6804 -- declaration into a renaming declaration. | |
6805 | |
6806 if Needs_Finalization (Typ) | |
6807 and then not Is_Limited_View (Typ) | |
6808 and then not Rewrite_As_Renaming | |
6809 then | |
6810 Adj_Call := | |
6811 Make_Adjust_Call ( | |
6812 Obj_Ref => New_Occurrence_Of (Def_Id, Loc), | |
6813 Typ => Base_Typ); | |
6814 | |
6815 -- Guard against a missing [Deep_]Adjust when the base type | |
6816 -- was not properly frozen. | |
6817 | |
6818 if Present (Adj_Call) then | |
6819 Insert_Action_After (Init_After, Adj_Call); | |
6820 end if; | |
6821 end if; | |
6822 | |
6823 -- For tagged types, when an init value is given, the tag has to | |
6824 -- be re-initialized separately in order to avoid the propagation | |
6825 -- of a wrong tag coming from a view conversion unless the type | |
6826 -- is class wide (in this case the tag comes from the init value). | |
6827 -- Suppress the tag assignment when not Tagged_Type_Expansion | |
6828 -- because tags are represented implicitly in objects. Ditto for | |
6829 -- types that are CPP_CLASS, and for initializations that are | |
6830 -- aggregates, because they have to have the right tag. | |
6831 | |
6832 -- The re-assignment of the tag has to be done even if the object | |
6833 -- is a constant. The assignment must be analyzed after the | |
6834 -- declaration. If an address clause follows, this is handled as | |
6835 -- part of the freeze actions for the object, otherwise insert | |
6836 -- tag assignment here. | |
6837 | |
6838 Tag_Assign := Make_Tag_Assignment (N); | |
6839 | |
6840 if Present (Tag_Assign) then | |
6841 if Present (Following_Address_Clause (N)) then | |
6842 Ensure_Freeze_Node (Def_Id); | |
6843 | |
6844 else | |
6845 Insert_Action_After (Init_After, Tag_Assign); | |
6846 end if; | |
6847 | |
6848 -- Handle C++ constructor calls. Note that we do not check that | |
6849 -- Typ is a tagged type since the equivalent Ada type of a C++ | |
6850 -- class that has no virtual methods is an untagged limited | |
6851 -- record type. | |
6852 | |
6853 elsif Is_CPP_Constructor_Call (Expr) then | |
6854 | |
6855 -- The call to the initialization procedure does NOT freeze the | |
6856 -- object being initialized. | |
6857 | |
6858 Id_Ref := New_Occurrence_Of (Def_Id, Loc); | |
6859 Set_Must_Not_Freeze (Id_Ref); | |
6860 Set_Assignment_OK (Id_Ref); | |
6861 | |
6862 Insert_Actions_After (Init_After, | |
6863 Build_Initialization_Call (Loc, Id_Ref, Typ, | |
6864 Constructor_Ref => Expr)); | |
6865 | |
6866 -- We remove here the original call to the constructor | |
6867 -- to avoid its management in the backend | |
6868 | |
6869 Set_Expression (N, Empty); | |
6870 return; | |
6871 | |
6872 -- Handle initialization of limited tagged types | |
6873 | |
6874 elsif Is_Tagged_Type (Typ) | |
6875 and then Is_Class_Wide_Type (Typ) | |
6876 and then Is_Limited_Record (Typ) | |
6877 and then not Is_Limited_Interface (Typ) | |
6878 then | |
6879 -- Given that the type is limited we cannot perform a copy. If | |
6880 -- Expr_Q is the reference to a variable we mark the variable | |
6881 -- as OK_To_Rename to expand this declaration into a renaming | |
6882 -- declaration (see bellow). | |
6883 | |
6884 if Is_Entity_Name (Expr_Q) then | |
6885 Set_OK_To_Rename (Entity (Expr_Q)); | |
6886 | |
6887 -- If we cannot convert the expression into a renaming we must | |
6888 -- consider it an internal error because the backend does not | |
6889 -- have support to handle it. | |
6890 | |
6891 else | |
6892 pragma Assert (False); | |
6893 raise Program_Error; | |
6894 end if; | |
6895 | |
6896 -- For discrete types, set the Is_Known_Valid flag if the | |
6897 -- initializing value is known to be valid. Only do this for | |
6898 -- source assignments, since otherwise we can end up turning | |
6899 -- on the known valid flag prematurely from inserted code. | |
6900 | |
6901 elsif Comes_From_Source (N) | |
6902 and then Is_Discrete_Type (Typ) | |
6903 and then Expr_Known_Valid (Expr) | |
6904 then | |
6905 Set_Is_Known_Valid (Def_Id); | |
6906 | |
6907 elsif Is_Access_Type (Typ) then | |
6908 | |
6909 -- For access types set the Is_Known_Non_Null flag if the | |
6910 -- initializing value is known to be non-null. We can also set | |
6911 -- Can_Never_Be_Null if this is a constant. | |
6912 | |
6913 if Known_Non_Null (Expr) then | |
6914 Set_Is_Known_Non_Null (Def_Id, True); | |
6915 | |
6916 if Constant_Present (N) then | |
6917 Set_Can_Never_Be_Null (Def_Id); | |
6918 end if; | |
6919 end if; | |
6920 end if; | |
6921 | |
6922 -- If validity checking on copies, validate initial expression. | |
6923 -- But skip this if declaration is for a generic type, since it | |
6924 -- makes no sense to validate generic types. Not clear if this | |
6925 -- can happen for legal programs, but it definitely can arise | |
6926 -- from previous instantiation errors. | |
6927 | |
6928 if Validity_Checks_On | |
6929 and then Comes_From_Source (N) | |
6930 and then Validity_Check_Copies | |
6931 and then not Is_Generic_Type (Etype (Def_Id)) | |
6932 then | |
6933 Ensure_Valid (Expr); | |
6934 Set_Is_Known_Valid (Def_Id); | |
6935 end if; | |
6936 end if; | |
6937 | |
6938 -- Cases where the back end cannot handle the initialization | |
6939 -- directly. In such cases, we expand an assignment that will | |
6940 -- be appropriately handled by Expand_N_Assignment_Statement. | |
6941 | |
6942 -- The exclusion of the unconstrained case is wrong, but for now it | |
6943 -- is too much trouble ??? | |
6944 | |
6945 if (Is_Possibly_Unaligned_Slice (Expr) | |
6946 or else (Is_Possibly_Unaligned_Object (Expr) | |
6947 and then not Represented_As_Scalar (Etype (Expr)))) | |
6948 and then not (Is_Array_Type (Etype (Expr)) | |
6949 and then not Is_Constrained (Etype (Expr))) | |
6950 then | |
6951 declare | |
6952 Stat : constant Node_Id := | |
6953 Make_Assignment_Statement (Loc, | |
6954 Name => New_Occurrence_Of (Def_Id, Loc), | |
6955 Expression => Relocate_Node (Expr)); | |
6956 begin | |
6957 Set_Expression (N, Empty); | |
6958 Set_No_Initialization (N); | |
6959 Set_Assignment_OK (Name (Stat)); | |
6960 Set_No_Ctrl_Actions (Stat); | |
6961 Insert_After_And_Analyze (Init_After, Stat); | |
6962 end; | |
6963 end if; | |
6964 end if; | |
6965 | |
6966 if Nkind (Obj_Def) = N_Access_Definition | |
6967 and then not Is_Local_Anonymous_Access (Etype (Def_Id)) | |
6968 then | |
6969 -- An Ada 2012 stand-alone object of an anonymous access type | |
6970 | |
6971 declare | |
6972 Loc : constant Source_Ptr := Sloc (N); | |
6973 | |
6974 Level : constant Entity_Id := | |
6975 Make_Defining_Identifier (Sloc (N), | |
6976 Chars => | |
6977 New_External_Name (Chars (Def_Id), Suffix => "L")); | |
6978 | |
6979 Level_Expr : Node_Id; | |
6980 Level_Decl : Node_Id; | |
6981 | |
6982 begin | |
6983 Set_Ekind (Level, Ekind (Def_Id)); | |
6984 Set_Etype (Level, Standard_Natural); | |
6985 Set_Scope (Level, Scope (Def_Id)); | |
6986 | |
6987 if No (Expr) then | |
6988 | |
6989 -- Set accessibility level of null | |
6990 | |
6991 Level_Expr := | |
6992 Make_Integer_Literal (Loc, Scope_Depth (Standard_Standard)); | |
6993 | |
6994 else | |
6995 Level_Expr := Dynamic_Accessibility_Level (Expr); | |
6996 end if; | |
6997 | |
6998 Level_Decl := | |
6999 Make_Object_Declaration (Loc, | |
7000 Defining_Identifier => Level, | |
7001 Object_Definition => | |
7002 New_Occurrence_Of (Standard_Natural, Loc), | |
7003 Expression => Level_Expr, | |
7004 Constant_Present => Constant_Present (N), | |
7005 Has_Init_Expression => True); | |
7006 | |
7007 Insert_Action_After (Init_After, Level_Decl); | |
7008 | |
7009 Set_Extra_Accessibility (Def_Id, Level); | |
7010 end; | |
7011 end if; | |
7012 | |
7013 -- If the object is default initialized and its type is subject to | |
7014 -- pragma Default_Initial_Condition, add a runtime check to verify | |
7015 -- the assumption of the pragma (SPARK RM 7.3.3). Generate: | |
7016 | |
7017 -- <Base_Typ>DIC (<Base_Typ> (Def_Id)); | |
7018 | |
7019 -- Note that the check is generated for source objects only | |
7020 | |
7021 if Comes_From_Source (Def_Id) | |
7022 and then Has_DIC (Typ) | |
7023 and then Present (DIC_Procedure (Typ)) | |
7024 and then not Has_Init_Expression (N) | |
7025 then | |
7026 declare | |
7027 DIC_Call : constant Node_Id := Build_DIC_Call (Loc, Def_Id, Typ); | |
7028 | |
7029 begin | |
7030 if Present (Next_N) then | |
7031 Insert_Before_And_Analyze (Next_N, DIC_Call); | |
7032 | |
7033 -- The object declaration is the last node in a declarative or a | |
7034 -- statement list. | |
7035 | |
7036 else | |
7037 Append_To (List_Containing (N), DIC_Call); | |
7038 Analyze (DIC_Call); | |
7039 end if; | |
7040 end; | |
7041 end if; | |
7042 | |
7043 -- Final transformation - turn the object declaration into a renaming | |
7044 -- if appropriate. If this is the completion of a deferred constant | |
7045 -- declaration, then this transformation generates what would be | |
7046 -- illegal code if written by hand, but that's OK. | |
7047 | |
7048 if Present (Expr) then | |
7049 if Rewrite_As_Renaming then | |
7050 Rewrite (N, | |
7051 Make_Object_Renaming_Declaration (Loc, | |
7052 Defining_Identifier => Defining_Identifier (N), | |
7053 Subtype_Mark => Obj_Def, | |
7054 Name => Expr_Q)); | |
7055 | |
7056 -- We do not analyze this renaming declaration, because all its | |
7057 -- components have already been analyzed, and if we were to go | |
7058 -- ahead and analyze it, we would in effect be trying to generate | |
7059 -- another declaration of X, which won't do. | |
7060 | |
7061 Set_Renamed_Object (Defining_Identifier (N), Expr_Q); | |
7062 Set_Analyzed (N); | |
7063 | |
7064 -- We do need to deal with debug issues for this renaming | |
7065 | |
7066 -- First, if entity comes from source, then mark it as needing | |
7067 -- debug information, even though it is defined by a generated | |
7068 -- renaming that does not come from source. | |
7069 | |
7070 if Comes_From_Source (Defining_Identifier (N)) then | |
7071 Set_Debug_Info_Needed (Defining_Identifier (N)); | |
7072 end if; | |
7073 | |
7074 -- Now call the routine to generate debug info for the renaming | |
7075 | |
7076 declare | |
7077 Decl : constant Node_Id := Debug_Renaming_Declaration (N); | |
7078 begin | |
7079 if Present (Decl) then | |
7080 Insert_Action (N, Decl); | |
7081 end if; | |
7082 end; | |
7083 end if; | |
7084 end if; | |
7085 | |
7086 -- Exception on library entity not available | |
7087 | |
7088 exception | |
7089 when RE_Not_Available => | |
7090 return; | |
7091 end Expand_N_Object_Declaration; | |
7092 | |
7093 --------------------------------- | |
7094 -- Expand_N_Subtype_Indication -- | |
7095 --------------------------------- | |
7096 | |
7097 -- Add a check on the range of the subtype. The static case is partially | |
7098 -- duplicated by Process_Range_Expr_In_Decl in Sem_Ch3, but we still need | |
7099 -- to check here for the static case in order to avoid generating | |
7100 -- extraneous expanded code. Also deal with validity checking. | |
7101 | |
7102 procedure Expand_N_Subtype_Indication (N : Node_Id) is | |
7103 Ran : constant Node_Id := Range_Expression (Constraint (N)); | |
7104 Typ : constant Entity_Id := Entity (Subtype_Mark (N)); | |
7105 | |
7106 begin | |
7107 if Nkind (Constraint (N)) = N_Range_Constraint then | |
7108 Validity_Check_Range (Range_Expression (Constraint (N))); | |
7109 end if; | |
7110 | |
7111 if Nkind_In (Parent (N), N_Constrained_Array_Definition, N_Slice) then | |
7112 Apply_Range_Check (Ran, Typ); | |
7113 end if; | |
7114 end Expand_N_Subtype_Indication; | |
7115 | |
7116 --------------------------- | |
7117 -- Expand_N_Variant_Part -- | |
7118 --------------------------- | |
7119 | |
7120 -- Note: this procedure no longer has any effect. It used to be that we | |
7121 -- would replace the choices in the last variant by a when others, and | |
7122 -- also expanded static predicates in variant choices here, but both of | |
7123 -- those activities were being done too early, since we can't check the | |
7124 -- choices until the statically predicated subtypes are frozen, which can | |
7125 -- happen as late as the free point of the record, and we can't change the | |
7126 -- last choice to an others before checking the choices, which is now done | |
7127 -- at the freeze point of the record. | |
7128 | |
7129 procedure Expand_N_Variant_Part (N : Node_Id) is | |
7130 begin | |
7131 null; | |
7132 end Expand_N_Variant_Part; | |
7133 | |
7134 --------------------------------- | |
7135 -- Expand_Previous_Access_Type -- | |
7136 --------------------------------- | |
7137 | |
7138 procedure Expand_Previous_Access_Type (Def_Id : Entity_Id) is | |
7139 Ptr_Typ : Entity_Id; | |
7140 | |
7141 begin | |
7142 -- Find all access types in the current scope whose designated type is | |
7143 -- Def_Id and build master renamings for them. | |
7144 | |
7145 Ptr_Typ := First_Entity (Current_Scope); | |
7146 while Present (Ptr_Typ) loop | |
7147 if Is_Access_Type (Ptr_Typ) | |
7148 and then Designated_Type (Ptr_Typ) = Def_Id | |
7149 and then No (Master_Id (Ptr_Typ)) | |
7150 then | |
7151 -- Ensure that the designated type has a master | |
7152 | |
7153 Build_Master_Entity (Def_Id); | |
7154 | |
7155 -- Private and incomplete types complicate the insertion of master | |
7156 -- renamings because the access type may precede the full view of | |
7157 -- the designated type. For this reason, the master renamings are | |
7158 -- inserted relative to the designated type. | |
7159 | |
7160 Build_Master_Renaming (Ptr_Typ, Ins_Nod => Parent (Def_Id)); | |
7161 end if; | |
7162 | |
7163 Next_Entity (Ptr_Typ); | |
7164 end loop; | |
7165 end Expand_Previous_Access_Type; | |
7166 | |
7167 ----------------------------- | |
7168 -- Expand_Record_Extension -- | |
7169 ----------------------------- | |
7170 | |
7171 -- Add a field _parent at the beginning of the record extension. This is | |
7172 -- used to implement inheritance. Here are some examples of expansion: | |
7173 | |
7174 -- 1. no discriminants | |
7175 -- type T2 is new T1 with null record; | |
7176 -- gives | |
7177 -- type T2 is new T1 with record | |
7178 -- _Parent : T1; | |
7179 -- end record; | |
7180 | |
7181 -- 2. renamed discriminants | |
7182 -- type T2 (B, C : Int) is new T1 (A => B) with record | |
7183 -- _Parent : T1 (A => B); | |
7184 -- D : Int; | |
7185 -- end; | |
7186 | |
7187 -- 3. inherited discriminants | |
7188 -- type T2 is new T1 with record -- discriminant A inherited | |
7189 -- _Parent : T1 (A); | |
7190 -- D : Int; | |
7191 -- end; | |
7192 | |
7193 procedure Expand_Record_Extension (T : Entity_Id; Def : Node_Id) is | |
7194 Indic : constant Node_Id := Subtype_Indication (Def); | |
7195 Loc : constant Source_Ptr := Sloc (Def); | |
7196 Rec_Ext_Part : Node_Id := Record_Extension_Part (Def); | |
7197 Par_Subtype : Entity_Id; | |
7198 Comp_List : Node_Id; | |
7199 Comp_Decl : Node_Id; | |
7200 Parent_N : Node_Id; | |
7201 D : Entity_Id; | |
7202 List_Constr : constant List_Id := New_List; | |
7203 | |
7204 begin | |
7205 -- Expand_Record_Extension is called directly from the semantics, so | |
7206 -- we must check to see whether expansion is active before proceeding, | |
7207 -- because this affects the visibility of selected components in bodies | |
7208 -- of instances. | |
7209 | |
7210 if not Expander_Active then | |
7211 return; | |
7212 end if; | |
7213 | |
7214 -- This may be a derivation of an untagged private type whose full | |
7215 -- view is tagged, in which case the Derived_Type_Definition has no | |
7216 -- extension part. Build an empty one now. | |
7217 | |
7218 if No (Rec_Ext_Part) then | |
7219 Rec_Ext_Part := | |
7220 Make_Record_Definition (Loc, | |
7221 End_Label => Empty, | |
7222 Component_List => Empty, | |
7223 Null_Present => True); | |
7224 | |
7225 Set_Record_Extension_Part (Def, Rec_Ext_Part); | |
7226 Mark_Rewrite_Insertion (Rec_Ext_Part); | |
7227 end if; | |
7228 | |
7229 Comp_List := Component_List (Rec_Ext_Part); | |
7230 | |
7231 Parent_N := Make_Defining_Identifier (Loc, Name_uParent); | |
7232 | |
7233 -- If the derived type inherits its discriminants the type of the | |
7234 -- _parent field must be constrained by the inherited discriminants | |
7235 | |
7236 if Has_Discriminants (T) | |
7237 and then Nkind (Indic) /= N_Subtype_Indication | |
7238 and then not Is_Constrained (Entity (Indic)) | |
7239 then | |
7240 D := First_Discriminant (T); | |
7241 while Present (D) loop | |
7242 Append_To (List_Constr, New_Occurrence_Of (D, Loc)); | |
7243 Next_Discriminant (D); | |
7244 end loop; | |
7245 | |
7246 Par_Subtype := | |
7247 Process_Subtype ( | |
7248 Make_Subtype_Indication (Loc, | |
7249 Subtype_Mark => New_Occurrence_Of (Entity (Indic), Loc), | |
7250 Constraint => | |
7251 Make_Index_Or_Discriminant_Constraint (Loc, | |
7252 Constraints => List_Constr)), | |
7253 Def); | |
7254 | |
7255 -- Otherwise the original subtype_indication is just what is needed | |
7256 | |
7257 else | |
7258 Par_Subtype := Process_Subtype (New_Copy_Tree (Indic), Def); | |
7259 end if; | |
7260 | |
7261 Set_Parent_Subtype (T, Par_Subtype); | |
7262 | |
7263 Comp_Decl := | |
7264 Make_Component_Declaration (Loc, | |
7265 Defining_Identifier => Parent_N, | |
7266 Component_Definition => | |
7267 Make_Component_Definition (Loc, | |
7268 Aliased_Present => False, | |
7269 Subtype_Indication => New_Occurrence_Of (Par_Subtype, Loc))); | |
7270 | |
7271 if Null_Present (Rec_Ext_Part) then | |
7272 Set_Component_List (Rec_Ext_Part, | |
7273 Make_Component_List (Loc, | |
7274 Component_Items => New_List (Comp_Decl), | |
7275 Variant_Part => Empty, | |
7276 Null_Present => False)); | |
7277 Set_Null_Present (Rec_Ext_Part, False); | |
7278 | |
7279 elsif Null_Present (Comp_List) | |
7280 or else Is_Empty_List (Component_Items (Comp_List)) | |
7281 then | |
7282 Set_Component_Items (Comp_List, New_List (Comp_Decl)); | |
7283 Set_Null_Present (Comp_List, False); | |
7284 | |
7285 else | |
7286 Insert_Before (First (Component_Items (Comp_List)), Comp_Decl); | |
7287 end if; | |
7288 | |
7289 Analyze (Comp_Decl); | |
7290 end Expand_Record_Extension; | |
7291 | |
7292 ------------------------ | |
7293 -- Expand_Tagged_Root -- | |
7294 ------------------------ | |
7295 | |
7296 procedure Expand_Tagged_Root (T : Entity_Id) is | |
7297 Def : constant Node_Id := Type_Definition (Parent (T)); | |
7298 Comp_List : Node_Id; | |
7299 Comp_Decl : Node_Id; | |
7300 Sloc_N : Source_Ptr; | |
7301 | |
7302 begin | |
7303 if Null_Present (Def) then | |
7304 Set_Component_List (Def, | |
7305 Make_Component_List (Sloc (Def), | |
7306 Component_Items => Empty_List, | |
7307 Variant_Part => Empty, | |
7308 Null_Present => True)); | |
7309 end if; | |
7310 | |
7311 Comp_List := Component_List (Def); | |
7312 | |
7313 if Null_Present (Comp_List) | |
7314 or else Is_Empty_List (Component_Items (Comp_List)) | |
7315 then | |
7316 Sloc_N := Sloc (Comp_List); | |
7317 else | |
7318 Sloc_N := Sloc (First (Component_Items (Comp_List))); | |
7319 end if; | |
7320 | |
7321 Comp_Decl := | |
7322 Make_Component_Declaration (Sloc_N, | |
7323 Defining_Identifier => First_Tag_Component (T), | |
7324 Component_Definition => | |
7325 Make_Component_Definition (Sloc_N, | |
7326 Aliased_Present => False, | |
7327 Subtype_Indication => New_Occurrence_Of (RTE (RE_Tag), Sloc_N))); | |
7328 | |
7329 if Null_Present (Comp_List) | |
7330 or else Is_Empty_List (Component_Items (Comp_List)) | |
7331 then | |
7332 Set_Component_Items (Comp_List, New_List (Comp_Decl)); | |
7333 Set_Null_Present (Comp_List, False); | |
7334 | |
7335 else | |
7336 Insert_Before (First (Component_Items (Comp_List)), Comp_Decl); | |
7337 end if; | |
7338 | |
7339 -- We don't Analyze the whole expansion because the tag component has | |
7340 -- already been analyzed previously. Here we just insure that the tree | |
7341 -- is coherent with the semantic decoration | |
7342 | |
7343 Find_Type (Subtype_Indication (Component_Definition (Comp_Decl))); | |
7344 | |
7345 exception | |
7346 when RE_Not_Available => | |
7347 return; | |
7348 end Expand_Tagged_Root; | |
7349 | |
7350 ------------------------------ | |
7351 -- Freeze_Stream_Operations -- | |
7352 ------------------------------ | |
7353 | |
7354 procedure Freeze_Stream_Operations (N : Node_Id; Typ : Entity_Id) is | |
7355 Names : constant array (1 .. 4) of TSS_Name_Type := | |
7356 (TSS_Stream_Input, | |
7357 TSS_Stream_Output, | |
7358 TSS_Stream_Read, | |
7359 TSS_Stream_Write); | |
7360 Stream_Op : Entity_Id; | |
7361 | |
7362 begin | |
7363 -- Primitive operations of tagged types are frozen when the dispatch | |
7364 -- table is constructed. | |
7365 | |
7366 if not Comes_From_Source (Typ) or else Is_Tagged_Type (Typ) then | |
7367 return; | |
7368 end if; | |
7369 | |
7370 for J in Names'Range loop | |
7371 Stream_Op := TSS (Typ, Names (J)); | |
7372 | |
7373 if Present (Stream_Op) | |
7374 and then Is_Subprogram (Stream_Op) | |
7375 and then Nkind (Unit_Declaration_Node (Stream_Op)) = | |
7376 N_Subprogram_Declaration | |
7377 and then not Is_Frozen (Stream_Op) | |
7378 then | |
7379 Append_Freeze_Actions (Typ, Freeze_Entity (Stream_Op, N)); | |
7380 end if; | |
7381 end loop; | |
7382 end Freeze_Stream_Operations; | |
7383 | |
7384 ----------------- | |
7385 -- Freeze_Type -- | |
7386 ----------------- | |
7387 | |
7388 -- Full type declarations are expanded at the point at which the type is | |
7389 -- frozen. The formal N is the Freeze_Node for the type. Any statements or | |
7390 -- declarations generated by the freezing (e.g. the procedure generated | |
7391 -- for initialization) are chained in the Actions field list of the freeze | |
7392 -- node using Append_Freeze_Actions. | |
7393 | |
7394 -- WARNING: This routine manages Ghost regions. Return statements must be | |
7395 -- replaced by gotos which jump to the end of the routine and restore the | |
7396 -- Ghost mode. | |
7397 | |
7398 function Freeze_Type (N : Node_Id) return Boolean is | |
7399 procedure Process_RACW_Types (Typ : Entity_Id); | |
7400 -- Validate and generate stubs for all RACW types associated with type | |
7401 -- Typ. | |
7402 | |
7403 procedure Process_Pending_Access_Types (Typ : Entity_Id); | |
7404 -- Associate type Typ's Finalize_Address primitive with the finalization | |
7405 -- masters of pending access-to-Typ types. | |
7406 | |
7407 ------------------------ | |
7408 -- Process_RACW_Types -- | |
7409 ------------------------ | |
7410 | |
7411 procedure Process_RACW_Types (Typ : Entity_Id) is | |
7412 List : constant Elist_Id := Access_Types_To_Process (N); | |
7413 E : Elmt_Id; | |
7414 Seen : Boolean := False; | |
7415 | |
7416 begin | |
7417 if Present (List) then | |
7418 E := First_Elmt (List); | |
7419 while Present (E) loop | |
7420 if Is_Remote_Access_To_Class_Wide_Type (Node (E)) then | |
7421 Validate_RACW_Primitives (Node (E)); | |
7422 Seen := True; | |
7423 end if; | |
7424 | |
7425 Next_Elmt (E); | |
7426 end loop; | |
7427 end if; | |
7428 | |
7429 -- If there are RACWs designating this type, make stubs now | |
7430 | |
7431 if Seen then | |
7432 Remote_Types_Tagged_Full_View_Encountered (Typ); | |
7433 end if; | |
7434 end Process_RACW_Types; | |
7435 | |
7436 ---------------------------------- | |
7437 -- Process_Pending_Access_Types -- | |
7438 ---------------------------------- | |
7439 | |
7440 procedure Process_Pending_Access_Types (Typ : Entity_Id) is | |
7441 E : Elmt_Id; | |
7442 | |
7443 begin | |
7444 -- Finalize_Address is not generated in CodePeer mode because the | |
7445 -- body contains address arithmetic. This processing is disabled. | |
7446 | |
7447 if CodePeer_Mode then | |
7448 null; | |
7449 | |
7450 -- Certain itypes are generated for contexts that cannot allocate | |
7451 -- objects and should not set primitive Finalize_Address. | |
7452 | |
7453 elsif Is_Itype (Typ) | |
7454 and then Nkind (Associated_Node_For_Itype (Typ)) = | |
7455 N_Explicit_Dereference | |
7456 then | |
7457 null; | |
7458 | |
7459 -- When an access type is declared after the incomplete view of a | |
7460 -- Taft-amendment type, the access type is considered pending in | |
7461 -- case the full view of the Taft-amendment type is controlled. If | |
7462 -- this is indeed the case, associate the Finalize_Address routine | |
7463 -- of the full view with the finalization masters of all pending | |
7464 -- access types. This scenario applies to anonymous access types as | |
7465 -- well. | |
7466 | |
7467 elsif Needs_Finalization (Typ) | |
7468 and then Present (Pending_Access_Types (Typ)) | |
7469 then | |
7470 E := First_Elmt (Pending_Access_Types (Typ)); | |
7471 while Present (E) loop | |
7472 | |
7473 -- Generate: | |
7474 -- Set_Finalize_Address | |
7475 -- (Ptr_Typ, <Typ>FD'Unrestricted_Access); | |
7476 | |
7477 Append_Freeze_Action (Typ, | |
7478 Make_Set_Finalize_Address_Call | |
7479 (Loc => Sloc (N), | |
7480 Ptr_Typ => Node (E))); | |
7481 | |
7482 Next_Elmt (E); | |
7483 end loop; | |
7484 end if; | |
7485 end Process_Pending_Access_Types; | |
7486 | |
7487 -- Local variables | |
7488 | |
7489 Def_Id : constant Entity_Id := Entity (N); | |
7490 | |
7491 Saved_GM : constant Ghost_Mode_Type := Ghost_Mode; | |
7492 -- Save the Ghost mode to restore on exit | |
7493 | |
7494 Result : Boolean := False; | |
7495 | |
7496 -- Start of processing for Freeze_Type | |
7497 | |
7498 begin | |
7499 -- The type being frozen may be subject to pragma Ghost. Set the mode | |
7500 -- now to ensure that any nodes generated during freezing are properly | |
7501 -- marked as Ghost. | |
7502 | |
7503 Set_Ghost_Mode (Def_Id); | |
7504 | |
7505 -- Process any remote access-to-class-wide types designating the type | |
7506 -- being frozen. | |
7507 | |
7508 Process_RACW_Types (Def_Id); | |
7509 | |
7510 -- Freeze processing for record types | |
7511 | |
7512 if Is_Record_Type (Def_Id) then | |
7513 if Ekind (Def_Id) = E_Record_Type then | |
7514 Expand_Freeze_Record_Type (N); | |
7515 elsif Is_Class_Wide_Type (Def_Id) then | |
7516 Expand_Freeze_Class_Wide_Type (N); | |
7517 end if; | |
7518 | |
7519 -- Freeze processing for array types | |
7520 | |
7521 elsif Is_Array_Type (Def_Id) then | |
7522 Expand_Freeze_Array_Type (N); | |
7523 | |
7524 -- Freeze processing for access types | |
7525 | |
7526 -- For pool-specific access types, find out the pool object used for | |
7527 -- this type, needs actual expansion of it in some cases. Here are the | |
7528 -- different cases : | |
7529 | |
7530 -- 1. Rep Clause "for Def_Id'Storage_Size use 0;" | |
7531 -- ---> don't use any storage pool | |
7532 | |
7533 -- 2. Rep Clause : for Def_Id'Storage_Size use Expr. | |
7534 -- Expand: | |
7535 -- Def_Id__Pool : Stack_Bounded_Pool (Expr, DT'Size, DT'Alignment); | |
7536 | |
7537 -- 3. Rep Clause "for Def_Id'Storage_Pool use a_Pool_Object" | |
7538 -- ---> Storage Pool is the specified one | |
7539 | |
7540 -- See GNAT Pool packages in the Run-Time for more details | |
7541 | |
7542 elsif Ekind_In (Def_Id, E_Access_Type, E_General_Access_Type) then | |
7543 declare | |
7544 Loc : constant Source_Ptr := Sloc (N); | |
7545 Desig_Type : constant Entity_Id := Designated_Type (Def_Id); | |
7546 | |
7547 Freeze_Action_Typ : Entity_Id; | |
7548 Pool_Object : Entity_Id; | |
7549 | |
7550 begin | |
7551 -- Case 1 | |
7552 | |
7553 -- Rep Clause "for Def_Id'Storage_Size use 0;" | |
7554 -- ---> don't use any storage pool | |
7555 | |
7556 if No_Pool_Assigned (Def_Id) then | |
7557 null; | |
7558 | |
7559 -- Case 2 | |
7560 | |
7561 -- Rep Clause : for Def_Id'Storage_Size use Expr. | |
7562 -- ---> Expand: | |
7563 -- Def_Id__Pool : Stack_Bounded_Pool | |
7564 -- (Expr, DT'Size, DT'Alignment); | |
7565 | |
7566 elsif Has_Storage_Size_Clause (Def_Id) then | |
7567 declare | |
7568 DT_Align : Node_Id; | |
7569 DT_Size : Node_Id; | |
7570 | |
7571 begin | |
7572 -- For unconstrained composite types we give a size of zero | |
7573 -- so that the pool knows that it needs a special algorithm | |
7574 -- for variable size object allocation. | |
7575 | |
7576 if Is_Composite_Type (Desig_Type) | |
7577 and then not Is_Constrained (Desig_Type) | |
7578 then | |
7579 DT_Size := Make_Integer_Literal (Loc, 0); | |
7580 DT_Align := Make_Integer_Literal (Loc, Maximum_Alignment); | |
7581 | |
7582 else | |
7583 DT_Size := | |
7584 Make_Attribute_Reference (Loc, | |
7585 Prefix => New_Occurrence_Of (Desig_Type, Loc), | |
7586 Attribute_Name => Name_Max_Size_In_Storage_Elements); | |
7587 | |
7588 DT_Align := | |
7589 Make_Attribute_Reference (Loc, | |
7590 Prefix => New_Occurrence_Of (Desig_Type, Loc), | |
7591 Attribute_Name => Name_Alignment); | |
7592 end if; | |
7593 | |
7594 Pool_Object := | |
7595 Make_Defining_Identifier (Loc, | |
7596 Chars => New_External_Name (Chars (Def_Id), 'P')); | |
7597 | |
7598 -- We put the code associated with the pools in the entity | |
7599 -- that has the later freeze node, usually the access type | |
7600 -- but it can also be the designated_type; because the pool | |
7601 -- code requires both those types to be frozen | |
7602 | |
7603 if Is_Frozen (Desig_Type) | |
7604 and then (No (Freeze_Node (Desig_Type)) | |
7605 or else Analyzed (Freeze_Node (Desig_Type))) | |
7606 then | |
7607 Freeze_Action_Typ := Def_Id; | |
7608 | |
7609 -- A Taft amendment type cannot get the freeze actions | |
7610 -- since the full view is not there. | |
7611 | |
7612 elsif Is_Incomplete_Or_Private_Type (Desig_Type) | |
7613 and then No (Full_View (Desig_Type)) | |
7614 then | |
7615 Freeze_Action_Typ := Def_Id; | |
7616 | |
7617 else | |
7618 Freeze_Action_Typ := Desig_Type; | |
7619 end if; | |
7620 | |
7621 Append_Freeze_Action (Freeze_Action_Typ, | |
7622 Make_Object_Declaration (Loc, | |
7623 Defining_Identifier => Pool_Object, | |
7624 Object_Definition => | |
7625 Make_Subtype_Indication (Loc, | |
7626 Subtype_Mark => | |
7627 New_Occurrence_Of | |
7628 (RTE (RE_Stack_Bounded_Pool), Loc), | |
7629 | |
7630 Constraint => | |
7631 Make_Index_Or_Discriminant_Constraint (Loc, | |
7632 Constraints => New_List ( | |
7633 | |
7634 -- First discriminant is the Pool Size | |
7635 | |
7636 New_Occurrence_Of ( | |
7637 Storage_Size_Variable (Def_Id), Loc), | |
7638 | |
7639 -- Second discriminant is the element size | |
7640 | |
7641 DT_Size, | |
7642 | |
7643 -- Third discriminant is the alignment | |
7644 | |
7645 DT_Align))))); | |
7646 end; | |
7647 | |
7648 Set_Associated_Storage_Pool (Def_Id, Pool_Object); | |
7649 | |
7650 -- Case 3 | |
7651 | |
7652 -- Rep Clause "for Def_Id'Storage_Pool use a_Pool_Object" | |
7653 -- ---> Storage Pool is the specified one | |
7654 | |
7655 -- When compiling in Ada 2012 mode, ensure that the accessibility | |
7656 -- level of the subpool access type is not deeper than that of the | |
7657 -- pool_with_subpools. | |
7658 | |
7659 elsif Ada_Version >= Ada_2012 | |
7660 and then Present (Associated_Storage_Pool (Def_Id)) | |
7661 | |
7662 -- Omit this check for the case of a configurable run-time that | |
7663 -- does not provide package System.Storage_Pools.Subpools. | |
7664 | |
7665 and then RTE_Available (RE_Root_Storage_Pool_With_Subpools) | |
7666 then | |
7667 declare | |
7668 Loc : constant Source_Ptr := Sloc (Def_Id); | |
7669 Pool : constant Entity_Id := | |
7670 Associated_Storage_Pool (Def_Id); | |
7671 RSPWS : constant Entity_Id := | |
7672 RTE (RE_Root_Storage_Pool_With_Subpools); | |
7673 | |
7674 begin | |
7675 -- It is known that the accessibility level of the access | |
7676 -- type is deeper than that of the pool. | |
7677 | |
7678 if Type_Access_Level (Def_Id) > Object_Access_Level (Pool) | |
7679 and then not Accessibility_Checks_Suppressed (Def_Id) | |
7680 and then not Accessibility_Checks_Suppressed (Pool) | |
7681 then | |
7682 -- Static case: the pool is known to be a descendant of | |
7683 -- Root_Storage_Pool_With_Subpools. | |
7684 | |
7685 if Is_Ancestor (RSPWS, Etype (Pool)) then | |
7686 Error_Msg_N | |
7687 ("??subpool access type has deeper accessibility " | |
7688 & "level than pool", Def_Id); | |
7689 | |
7690 Append_Freeze_Action (Def_Id, | |
7691 Make_Raise_Program_Error (Loc, | |
7692 Reason => PE_Accessibility_Check_Failed)); | |
7693 | |
7694 -- Dynamic case: when the pool is of a class-wide type, | |
7695 -- it may or may not support subpools depending on the | |
7696 -- path of derivation. Generate: | |
7697 | |
7698 -- if Def_Id in RSPWS'Class then | |
7699 -- raise Program_Error; | |
7700 -- end if; | |
7701 | |
7702 elsif Is_Class_Wide_Type (Etype (Pool)) then | |
7703 Append_Freeze_Action (Def_Id, | |
7704 Make_If_Statement (Loc, | |
7705 Condition => | |
7706 Make_In (Loc, | |
7707 Left_Opnd => New_Occurrence_Of (Pool, Loc), | |
7708 Right_Opnd => | |
7709 New_Occurrence_Of | |
7710 (Class_Wide_Type (RSPWS), Loc)), | |
7711 | |
7712 Then_Statements => New_List ( | |
7713 Make_Raise_Program_Error (Loc, | |
7714 Reason => PE_Accessibility_Check_Failed)))); | |
7715 end if; | |
7716 end if; | |
7717 end; | |
7718 end if; | |
7719 | |
7720 -- For access-to-controlled types (including class-wide types and | |
7721 -- Taft-amendment types, which potentially have controlled | |
7722 -- components), expand the list controller object that will store | |
7723 -- the dynamically allocated objects. Don't do this transformation | |
7724 -- for expander-generated access types, but do it for types that | |
7725 -- are the full view of types derived from other private types. | |
7726 -- Also suppress the list controller in the case of a designated | |
7727 -- type with convention Java, since this is used when binding to | |
7728 -- Java API specs, where there's no equivalent of a finalization | |
7729 -- list and we don't want to pull in the finalization support if | |
7730 -- not needed. | |
7731 | |
7732 if not Comes_From_Source (Def_Id) | |
7733 and then not Has_Private_Declaration (Def_Id) | |
7734 then | |
7735 null; | |
7736 | |
7737 -- An exception is made for types defined in the run-time because | |
7738 -- Ada.Tags.Tag itself is such a type and cannot afford this | |
7739 -- unnecessary overhead that would generates a loop in the | |
7740 -- expansion scheme. Another exception is if Restrictions | |
7741 -- (No_Finalization) is active, since then we know nothing is | |
7742 -- controlled. | |
7743 | |
7744 elsif Restriction_Active (No_Finalization) | |
7745 or else In_Runtime (Def_Id) | |
7746 then | |
7747 null; | |
7748 | |
7749 -- Create a finalization master for an access-to-controlled type | |
7750 -- or an access-to-incomplete type. It is assumed that the full | |
7751 -- view will be controlled. | |
7752 | |
7753 elsif Needs_Finalization (Desig_Type) | |
7754 or else (Is_Incomplete_Type (Desig_Type) | |
7755 and then No (Full_View (Desig_Type))) | |
7756 then | |
7757 Build_Finalization_Master (Def_Id); | |
7758 | |
7759 -- Create a finalization master when the designated type contains | |
7760 -- a private component. It is assumed that the full view will be | |
7761 -- controlled. | |
7762 | |
7763 elsif Has_Private_Component (Desig_Type) then | |
7764 Build_Finalization_Master | |
7765 (Typ => Def_Id, | |
7766 For_Private => True, | |
7767 Context_Scope => Scope (Def_Id), | |
7768 Insertion_Node => Declaration_Node (Desig_Type)); | |
7769 end if; | |
7770 end; | |
7771 | |
7772 -- Freeze processing for enumeration types | |
7773 | |
7774 elsif Ekind (Def_Id) = E_Enumeration_Type then | |
7775 | |
7776 -- We only have something to do if we have a non-standard | |
7777 -- representation (i.e. at least one literal whose pos value | |
7778 -- is not the same as its representation) | |
7779 | |
7780 if Has_Non_Standard_Rep (Def_Id) then | |
7781 Expand_Freeze_Enumeration_Type (N); | |
7782 end if; | |
7783 | |
7784 -- Private types that are completed by a derivation from a private | |
7785 -- type have an internally generated full view, that needs to be | |
7786 -- frozen. This must be done explicitly because the two views share | |
7787 -- the freeze node, and the underlying full view is not visible when | |
7788 -- the freeze node is analyzed. | |
7789 | |
7790 elsif Is_Private_Type (Def_Id) | |
7791 and then Is_Derived_Type (Def_Id) | |
7792 and then Present (Full_View (Def_Id)) | |
7793 and then Is_Itype (Full_View (Def_Id)) | |
7794 and then Has_Private_Declaration (Full_View (Def_Id)) | |
7795 and then Freeze_Node (Full_View (Def_Id)) = N | |
7796 then | |
7797 Set_Entity (N, Full_View (Def_Id)); | |
7798 Result := Freeze_Type (N); | |
7799 Set_Entity (N, Def_Id); | |
7800 | |
7801 -- All other types require no expander action. There are such cases | |
7802 -- (e.g. task types and protected types). In such cases, the freeze | |
7803 -- nodes are there for use by Gigi. | |
7804 | |
7805 end if; | |
7806 | |
7807 -- Complete the initialization of all pending access types' finalization | |
7808 -- masters now that the designated type has been is frozen and primitive | |
7809 -- Finalize_Address generated. | |
7810 | |
7811 Process_Pending_Access_Types (Def_Id); | |
7812 Freeze_Stream_Operations (N, Def_Id); | |
7813 | |
7814 -- Generate the [spec and] body of the procedure tasked with the runtime | |
7815 -- verification of pragma Default_Initial_Condition's expression. | |
7816 | |
7817 if Has_DIC (Def_Id) then | |
7818 Build_DIC_Procedure_Body (Def_Id, For_Freeze => True); | |
7819 end if; | |
7820 | |
7821 -- Generate the [spec and] body of the invariant procedure tasked with | |
7822 -- the runtime verification of all invariants that pertain to the type. | |
7823 -- This includes invariants on the partial and full view, inherited | |
7824 -- class-wide invariants from parent types or interfaces, and invariants | |
7825 -- on array elements or record components. | |
7826 | |
7827 if Is_Interface (Def_Id) then | |
7828 | |
7829 -- Interfaces are treated as the partial view of a private type in | |
7830 -- order to achieve uniformity with the general case. As a result, an | |
7831 -- interface receives only a "partial" invariant procedure which is | |
7832 -- never called. | |
7833 | |
7834 if Has_Own_Invariants (Def_Id) then | |
7835 Build_Invariant_Procedure_Body | |
7836 (Typ => Def_Id, | |
7837 Partial_Invariant => Is_Interface (Def_Id)); | |
7838 end if; | |
7839 | |
7840 -- Non-interface types | |
7841 | |
7842 -- Do not generate invariant procedure within other assertion | |
7843 -- subprograms, which may involve local declarations of local | |
7844 -- subtypes to which these checks do not apply. | |
7845 | |
7846 elsif Has_Invariants (Def_Id) then | |
7847 if Within_Internal_Subprogram | |
7848 or else (Ekind (Current_Scope) = E_Function | |
7849 and then Is_Predicate_Function (Current_Scope)) | |
7850 then | |
7851 null; | |
7852 else | |
7853 Build_Invariant_Procedure_Body (Def_Id); | |
7854 end if; | |
7855 end if; | |
7856 | |
7857 Restore_Ghost_Mode (Saved_GM); | |
7858 | |
7859 return Result; | |
7860 | |
7861 exception | |
7862 when RE_Not_Available => | |
7863 Restore_Ghost_Mode (Saved_GM); | |
7864 | |
7865 return False; | |
7866 end Freeze_Type; | |
7867 | |
7868 ------------------------- | |
7869 -- Get_Simple_Init_Val -- | |
7870 ------------------------- | |
7871 | |
7872 function Get_Simple_Init_Val | |
7873 (T : Entity_Id; | |
7874 N : Node_Id; | |
7875 Size : Uint := No_Uint) return Node_Id | |
7876 is | |
7877 Loc : constant Source_Ptr := Sloc (N); | |
7878 Val : Node_Id; | |
7879 Result : Node_Id; | |
7880 Val_RE : RE_Id; | |
7881 | |
7882 Size_To_Use : Uint; | |
7883 -- This is the size to be used for computation of the appropriate | |
7884 -- initial value for the Normalize_Scalars and Initialize_Scalars case. | |
7885 | |
7886 IV_Attribute : constant Boolean := | |
7887 Nkind (N) = N_Attribute_Reference | |
7888 and then Attribute_Name (N) = Name_Invalid_Value; | |
7889 | |
7890 Lo_Bound : Uint; | |
7891 Hi_Bound : Uint; | |
7892 -- These are the values computed by the procedure Check_Subtype_Bounds | |
7893 | |
7894 procedure Check_Subtype_Bounds; | |
7895 -- This procedure examines the subtype T, and its ancestor subtypes and | |
7896 -- derived types to determine the best known information about the | |
7897 -- bounds of the subtype. After the call Lo_Bound is set either to | |
7898 -- No_Uint if no information can be determined, or to a value which | |
7899 -- represents a known low bound, i.e. a valid value of the subtype can | |
7900 -- not be less than this value. Hi_Bound is similarly set to a known | |
7901 -- high bound (valid value cannot be greater than this). | |
7902 | |
7903 -------------------------- | |
7904 -- Check_Subtype_Bounds -- | |
7905 -------------------------- | |
7906 | |
7907 procedure Check_Subtype_Bounds is | |
7908 ST1 : Entity_Id; | |
7909 ST2 : Entity_Id; | |
7910 Lo : Node_Id; | |
7911 Hi : Node_Id; | |
7912 Loval : Uint; | |
7913 Hival : Uint; | |
7914 | |
7915 begin | |
7916 Lo_Bound := No_Uint; | |
7917 Hi_Bound := No_Uint; | |
7918 | |
7919 -- Loop to climb ancestor subtypes and derived types | |
7920 | |
7921 ST1 := T; | |
7922 loop | |
7923 if not Is_Discrete_Type (ST1) then | |
7924 return; | |
7925 end if; | |
7926 | |
7927 Lo := Type_Low_Bound (ST1); | |
7928 Hi := Type_High_Bound (ST1); | |
7929 | |
7930 if Compile_Time_Known_Value (Lo) then | |
7931 Loval := Expr_Value (Lo); | |
7932 | |
7933 if Lo_Bound = No_Uint or else Lo_Bound < Loval then | |
7934 Lo_Bound := Loval; | |
7935 end if; | |
7936 end if; | |
7937 | |
7938 if Compile_Time_Known_Value (Hi) then | |
7939 Hival := Expr_Value (Hi); | |
7940 | |
7941 if Hi_Bound = No_Uint or else Hi_Bound > Hival then | |
7942 Hi_Bound := Hival; | |
7943 end if; | |
7944 end if; | |
7945 | |
7946 ST2 := Ancestor_Subtype (ST1); | |
7947 | |
7948 if No (ST2) then | |
7949 ST2 := Etype (ST1); | |
7950 end if; | |
7951 | |
7952 exit when ST1 = ST2; | |
7953 ST1 := ST2; | |
7954 end loop; | |
7955 end Check_Subtype_Bounds; | |
7956 | |
7957 -- Start of processing for Get_Simple_Init_Val | |
7958 | |
7959 begin | |
7960 -- For a private type, we should always have an underlying type (because | |
7961 -- this was already checked in Needs_Simple_Initialization). What we do | |
7962 -- is to get the value for the underlying type and then do an unchecked | |
7963 -- conversion to the private type. | |
7964 | |
7965 if Is_Private_Type (T) then | |
7966 Val := Get_Simple_Init_Val (Underlying_Type (T), N, Size); | |
7967 | |
7968 -- A special case, if the underlying value is null, then qualify it | |
7969 -- with the underlying type, so that the null is properly typed. | |
7970 -- Similarly, if it is an aggregate it must be qualified, because an | |
7971 -- unchecked conversion does not provide a context for it. | |
7972 | |
7973 if Nkind_In (Val, N_Null, N_Aggregate) then | |
7974 Val := | |
7975 Make_Qualified_Expression (Loc, | |
7976 Subtype_Mark => | |
7977 New_Occurrence_Of (Underlying_Type (T), Loc), | |
7978 Expression => Val); | |
7979 end if; | |
7980 | |
7981 Result := Unchecked_Convert_To (T, Val); | |
7982 | |
7983 -- Don't truncate result (important for Initialize/Normalize_Scalars) | |
7984 | |
7985 if Nkind (Result) = N_Unchecked_Type_Conversion | |
7986 and then Is_Scalar_Type (Underlying_Type (T)) | |
7987 then | |
7988 Set_No_Truncation (Result); | |
7989 end if; | |
7990 | |
7991 return Result; | |
7992 | |
7993 -- Scalars with Default_Value aspect. The first subtype may now be | |
7994 -- private, so retrieve value from underlying type. | |
7995 | |
7996 elsif Is_Scalar_Type (T) and then Has_Default_Aspect (T) then | |
7997 if Is_Private_Type (First_Subtype (T)) then | |
7998 return Unchecked_Convert_To (T, | |
7999 Default_Aspect_Value (Full_View (First_Subtype (T)))); | |
8000 else | |
8001 return | |
8002 Convert_To (T, Default_Aspect_Value (First_Subtype (T))); | |
8003 end if; | |
8004 | |
8005 -- Otherwise, for scalars, we must have normalize/initialize scalars | |
8006 -- case, or if the node N is an 'Invalid_Value attribute node. | |
8007 | |
8008 elsif Is_Scalar_Type (T) then | |
8009 pragma Assert (Init_Or_Norm_Scalars or IV_Attribute); | |
8010 | |
8011 -- Compute size of object. If it is given by the caller, we can use | |
8012 -- it directly, otherwise we use Esize (T) as an estimate. As far as | |
8013 -- we know this covers all cases correctly. | |
8014 | |
8015 if Size = No_Uint or else Size <= Uint_0 then | |
8016 Size_To_Use := UI_Max (Uint_1, Esize (T)); | |
8017 else | |
8018 Size_To_Use := Size; | |
8019 end if; | |
8020 | |
8021 -- Maximum size to use is 64 bits, since we will create values of | |
8022 -- type Unsigned_64 and the range must fit this type. | |
8023 | |
8024 if Size_To_Use /= No_Uint and then Size_To_Use > Uint_64 then | |
8025 Size_To_Use := Uint_64; | |
8026 end if; | |
8027 | |
8028 -- Check known bounds of subtype | |
8029 | |
8030 Check_Subtype_Bounds; | |
8031 | |
8032 -- Processing for Normalize_Scalars case | |
8033 | |
8034 if Normalize_Scalars and then not IV_Attribute then | |
8035 | |
8036 -- If zero is invalid, it is a convenient value to use that is | |
8037 -- for sure an appropriate invalid value in all situations. | |
8038 | |
8039 if Lo_Bound /= No_Uint and then Lo_Bound > Uint_0 then | |
8040 Val := Make_Integer_Literal (Loc, 0); | |
8041 | |
8042 -- Cases where all one bits is the appropriate invalid value | |
8043 | |
8044 -- For modular types, all 1 bits is either invalid or valid. If | |
8045 -- it is valid, then there is nothing that can be done since there | |
8046 -- are no invalid values (we ruled out zero already). | |
8047 | |
8048 -- For signed integer types that have no negative values, either | |
8049 -- there is room for negative values, or there is not. If there | |
8050 -- is, then all 1-bits may be interpreted as minus one, which is | |
8051 -- certainly invalid. Alternatively it is treated as the largest | |
8052 -- positive value, in which case the observation for modular types | |
8053 -- still applies. | |
8054 | |
8055 -- For float types, all 1-bits is a NaN (not a number), which is | |
8056 -- certainly an appropriately invalid value. | |
8057 | |
8058 elsif Is_Unsigned_Type (T) | |
8059 or else Is_Floating_Point_Type (T) | |
8060 or else Is_Enumeration_Type (T) | |
8061 then | |
8062 Val := Make_Integer_Literal (Loc, 2 ** Size_To_Use - 1); | |
8063 | |
8064 -- Resolve as Unsigned_64, because the largest number we can | |
8065 -- generate is out of range of universal integer. | |
8066 | |
8067 Analyze_And_Resolve (Val, RTE (RE_Unsigned_64)); | |
8068 | |
8069 -- Case of signed types | |
8070 | |
8071 else | |
8072 declare | |
8073 Signed_Size : constant Uint := | |
8074 UI_Min (Uint_63, Size_To_Use - 1); | |
8075 | |
8076 begin | |
8077 -- Normally we like to use the most negative number. The one | |
8078 -- exception is when this number is in the known subtype | |
8079 -- range and the largest positive number is not in the known | |
8080 -- subtype range. | |
8081 | |
8082 -- For this exceptional case, use largest positive value | |
8083 | |
8084 if Lo_Bound /= No_Uint and then Hi_Bound /= No_Uint | |
8085 and then Lo_Bound <= (-(2 ** Signed_Size)) | |
8086 and then Hi_Bound < 2 ** Signed_Size | |
8087 then | |
8088 Val := Make_Integer_Literal (Loc, 2 ** Signed_Size - 1); | |
8089 | |
8090 -- Normal case of largest negative value | |
8091 | |
8092 else | |
8093 Val := Make_Integer_Literal (Loc, -(2 ** Signed_Size)); | |
8094 end if; | |
8095 end; | |
8096 end if; | |
8097 | |
8098 -- Here for Initialize_Scalars case (or Invalid_Value attribute used) | |
8099 | |
8100 else | |
8101 -- For float types, use float values from System.Scalar_Values | |
8102 | |
8103 if Is_Floating_Point_Type (T) then | |
8104 if Root_Type (T) = Standard_Short_Float then | |
8105 Val_RE := RE_IS_Isf; | |
8106 elsif Root_Type (T) = Standard_Float then | |
8107 Val_RE := RE_IS_Ifl; | |
8108 elsif Root_Type (T) = Standard_Long_Float then | |
8109 Val_RE := RE_IS_Ilf; | |
8110 else pragma Assert (Root_Type (T) = Standard_Long_Long_Float); | |
8111 Val_RE := RE_IS_Ill; | |
8112 end if; | |
8113 | |
8114 -- If zero is invalid, use zero values from System.Scalar_Values | |
8115 | |
8116 elsif Lo_Bound /= No_Uint and then Lo_Bound > Uint_0 then | |
8117 if Size_To_Use <= 8 then | |
8118 Val_RE := RE_IS_Iz1; | |
8119 elsif Size_To_Use <= 16 then | |
8120 Val_RE := RE_IS_Iz2; | |
8121 elsif Size_To_Use <= 32 then | |
8122 Val_RE := RE_IS_Iz4; | |
8123 else | |
8124 Val_RE := RE_IS_Iz8; | |
8125 end if; | |
8126 | |
8127 -- For unsigned, use unsigned values from System.Scalar_Values | |
8128 | |
8129 elsif Is_Unsigned_Type (T) then | |
8130 if Size_To_Use <= 8 then | |
8131 Val_RE := RE_IS_Iu1; | |
8132 elsif Size_To_Use <= 16 then | |
8133 Val_RE := RE_IS_Iu2; | |
8134 elsif Size_To_Use <= 32 then | |
8135 Val_RE := RE_IS_Iu4; | |
8136 else | |
8137 Val_RE := RE_IS_Iu8; | |
8138 end if; | |
8139 | |
8140 -- For signed, use signed values from System.Scalar_Values | |
8141 | |
8142 else | |
8143 if Size_To_Use <= 8 then | |
8144 Val_RE := RE_IS_Is1; | |
8145 elsif Size_To_Use <= 16 then | |
8146 Val_RE := RE_IS_Is2; | |
8147 elsif Size_To_Use <= 32 then | |
8148 Val_RE := RE_IS_Is4; | |
8149 else | |
8150 Val_RE := RE_IS_Is8; | |
8151 end if; | |
8152 end if; | |
8153 | |
8154 Val := New_Occurrence_Of (RTE (Val_RE), Loc); | |
8155 end if; | |
8156 | |
8157 -- The final expression is obtained by doing an unchecked conversion | |
8158 -- of this result to the base type of the required subtype. Use the | |
8159 -- base type to prevent the unchecked conversion from chopping bits, | |
8160 -- and then we set Kill_Range_Check to preserve the "bad" value. | |
8161 | |
8162 Result := Unchecked_Convert_To (Base_Type (T), Val); | |
8163 | |
8164 -- Ensure result is not truncated, since we want the "bad" bits, and | |
8165 -- also kill range check on result. | |
8166 | |
8167 if Nkind (Result) = N_Unchecked_Type_Conversion then | |
8168 Set_No_Truncation (Result); | |
8169 Set_Kill_Range_Check (Result, True); | |
8170 end if; | |
8171 | |
8172 return Result; | |
8173 | |
8174 -- String or Wide_[Wide]_String (must have Initialize_Scalars set) | |
8175 | |
8176 elsif Is_Standard_String_Type (T) then | |
8177 pragma Assert (Init_Or_Norm_Scalars); | |
8178 | |
8179 return | |
8180 Make_Aggregate (Loc, | |
8181 Component_Associations => New_List ( | |
8182 Make_Component_Association (Loc, | |
8183 Choices => New_List ( | |
8184 Make_Others_Choice (Loc)), | |
8185 Expression => | |
8186 Get_Simple_Init_Val | |
8187 (Component_Type (T), N, Esize (Root_Type (T)))))); | |
8188 | |
8189 -- Access type is initialized to null | |
8190 | |
8191 elsif Is_Access_Type (T) then | |
8192 return Make_Null (Loc); | |
8193 | |
8194 -- No other possibilities should arise, since we should only be calling | |
8195 -- Get_Simple_Init_Val if Needs_Simple_Initialization returned True, | |
8196 -- indicating one of the above cases held. | |
8197 | |
8198 else | |
8199 raise Program_Error; | |
8200 end if; | |
8201 | |
8202 exception | |
8203 when RE_Not_Available => | |
8204 return Empty; | |
8205 end Get_Simple_Init_Val; | |
8206 | |
8207 ------------------------------ | |
8208 -- Has_New_Non_Standard_Rep -- | |
8209 ------------------------------ | |
8210 | |
8211 function Has_New_Non_Standard_Rep (T : Entity_Id) return Boolean is | |
8212 begin | |
8213 if not Is_Derived_Type (T) then | |
8214 return Has_Non_Standard_Rep (T) | |
8215 or else Has_Non_Standard_Rep (Root_Type (T)); | |
8216 | |
8217 -- If Has_Non_Standard_Rep is not set on the derived type, the | |
8218 -- representation is fully inherited. | |
8219 | |
8220 elsif not Has_Non_Standard_Rep (T) then | |
8221 return False; | |
8222 | |
8223 else | |
8224 return First_Rep_Item (T) /= First_Rep_Item (Root_Type (T)); | |
8225 | |
8226 -- May need a more precise check here: the First_Rep_Item may be a | |
8227 -- stream attribute, which does not affect the representation of the | |
8228 -- type ??? | |
8229 | |
8230 end if; | |
8231 end Has_New_Non_Standard_Rep; | |
8232 | |
8233 ---------------------- | |
8234 -- Inline_Init_Proc -- | |
8235 ---------------------- | |
8236 | |
8237 function Inline_Init_Proc (Typ : Entity_Id) return Boolean is | |
8238 begin | |
8239 -- The initialization proc of protected records is not worth inlining. | |
8240 -- In addition, when compiled for another unit for inlining purposes, | |
8241 -- it may make reference to entities that have not been elaborated yet. | |
8242 -- The initialization proc of records that need finalization contains | |
8243 -- a nested clean-up procedure that makes it impractical to inline as | |
8244 -- well, except for simple controlled types themselves. And similar | |
8245 -- considerations apply to task types. | |
8246 | |
8247 if Is_Concurrent_Type (Typ) then | |
8248 return False; | |
8249 | |
8250 elsif Needs_Finalization (Typ) and then not Is_Controlled (Typ) then | |
8251 return False; | |
8252 | |
8253 elsif Has_Task (Typ) then | |
8254 return False; | |
8255 | |
8256 else | |
8257 return True; | |
8258 end if; | |
8259 end Inline_Init_Proc; | |
8260 | |
8261 ---------------- | |
8262 -- In_Runtime -- | |
8263 ---------------- | |
8264 | |
8265 function In_Runtime (E : Entity_Id) return Boolean is | |
8266 S1 : Entity_Id; | |
8267 | |
8268 begin | |
8269 S1 := Scope (E); | |
8270 while Scope (S1) /= Standard_Standard loop | |
8271 S1 := Scope (S1); | |
8272 end loop; | |
8273 | |
8274 return Is_RTU (S1, System) or else Is_RTU (S1, Ada); | |
8275 end In_Runtime; | |
8276 | |
8277 ---------------------------- | |
8278 -- Initialization_Warning -- | |
8279 ---------------------------- | |
8280 | |
8281 procedure Initialization_Warning (E : Entity_Id) is | |
8282 Warning_Needed : Boolean; | |
8283 | |
8284 begin | |
8285 Warning_Needed := False; | |
8286 | |
8287 if Ekind (Current_Scope) = E_Package | |
8288 and then Static_Elaboration_Desired (Current_Scope) | |
8289 then | |
8290 if Is_Type (E) then | |
8291 if Is_Record_Type (E) then | |
8292 if Has_Discriminants (E) | |
8293 or else Is_Limited_Type (E) | |
8294 or else Has_Non_Standard_Rep (E) | |
8295 then | |
8296 Warning_Needed := True; | |
8297 | |
8298 else | |
8299 -- Verify that at least one component has an initialization | |
8300 -- expression. No need for a warning on a type if all its | |
8301 -- components have no initialization. | |
8302 | |
8303 declare | |
8304 Comp : Entity_Id; | |
8305 | |
8306 begin | |
8307 Comp := First_Component (E); | |
8308 while Present (Comp) loop | |
8309 if Ekind (Comp) = E_Discriminant | |
8310 or else | |
8311 (Nkind (Parent (Comp)) = N_Component_Declaration | |
8312 and then Present (Expression (Parent (Comp)))) | |
8313 then | |
8314 Warning_Needed := True; | |
8315 exit; | |
8316 end if; | |
8317 | |
8318 Next_Component (Comp); | |
8319 end loop; | |
8320 end; | |
8321 end if; | |
8322 | |
8323 if Warning_Needed then | |
8324 Error_Msg_N | |
8325 ("Objects of the type cannot be initialized statically " | |
8326 & "by default??", Parent (E)); | |
8327 end if; | |
8328 end if; | |
8329 | |
8330 else | |
8331 Error_Msg_N ("Object cannot be initialized statically??", E); | |
8332 end if; | |
8333 end if; | |
8334 end Initialization_Warning; | |
8335 | |
8336 ------------------ | |
8337 -- Init_Formals -- | |
8338 ------------------ | |
8339 | |
8340 function Init_Formals (Typ : Entity_Id) return List_Id is | |
8341 Loc : constant Source_Ptr := Sloc (Typ); | |
8342 Formals : List_Id; | |
8343 | |
8344 begin | |
8345 -- First parameter is always _Init : in out typ. Note that we need this | |
8346 -- to be in/out because in the case of the task record value, there | |
8347 -- are default record fields (_Priority, _Size, -Task_Info) that may | |
8348 -- be referenced in the generated initialization routine. | |
8349 | |
8350 Formals := New_List ( | |
8351 Make_Parameter_Specification (Loc, | |
8352 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uInit), | |
8353 In_Present => True, | |
8354 Out_Present => True, | |
8355 Parameter_Type => New_Occurrence_Of (Typ, Loc))); | |
8356 | |
8357 -- For task record value, or type that contains tasks, add two more | |
8358 -- formals, _Master : Master_Id and _Chain : in out Activation_Chain | |
8359 -- We also add these parameters for the task record type case. | |
8360 | |
8361 if Has_Task (Typ) | |
8362 or else (Is_Record_Type (Typ) and then Is_Task_Record_Type (Typ)) | |
8363 then | |
8364 Append_To (Formals, | |
8365 Make_Parameter_Specification (Loc, | |
8366 Defining_Identifier => | |
8367 Make_Defining_Identifier (Loc, Name_uMaster), | |
8368 Parameter_Type => | |
8369 New_Occurrence_Of (RTE (RE_Master_Id), Loc))); | |
8370 | |
8371 -- Add _Chain (not done for sequential elaboration policy, see | |
8372 -- comment for Create_Restricted_Task_Sequential in s-tarest.ads). | |
8373 | |
8374 if Partition_Elaboration_Policy /= 'S' then | |
8375 Append_To (Formals, | |
8376 Make_Parameter_Specification (Loc, | |
8377 Defining_Identifier => | |
8378 Make_Defining_Identifier (Loc, Name_uChain), | |
8379 In_Present => True, | |
8380 Out_Present => True, | |
8381 Parameter_Type => | |
8382 New_Occurrence_Of (RTE (RE_Activation_Chain), Loc))); | |
8383 end if; | |
8384 | |
8385 Append_To (Formals, | |
8386 Make_Parameter_Specification (Loc, | |
8387 Defining_Identifier => | |
8388 Make_Defining_Identifier (Loc, Name_uTask_Name), | |
8389 In_Present => True, | |
8390 Parameter_Type => New_Occurrence_Of (Standard_String, Loc))); | |
8391 end if; | |
8392 | |
8393 return Formals; | |
8394 | |
8395 exception | |
8396 when RE_Not_Available => | |
8397 return Empty_List; | |
8398 end Init_Formals; | |
8399 | |
8400 ------------------------- | |
8401 -- Init_Secondary_Tags -- | |
8402 ------------------------- | |
8403 | |
8404 procedure Init_Secondary_Tags | |
8405 (Typ : Entity_Id; | |
8406 Target : Node_Id; | |
8407 Init_Tags_List : List_Id; | |
8408 Stmts_List : List_Id; | |
8409 Fixed_Comps : Boolean := True; | |
8410 Variable_Comps : Boolean := True) | |
8411 is | |
8412 Loc : constant Source_Ptr := Sloc (Target); | |
8413 | |
8414 -- Inherit the C++ tag of the secondary dispatch table of Typ associated | |
8415 -- with Iface. Tag_Comp is the component of Typ that stores Iface_Tag. | |
8416 | |
8417 procedure Initialize_Tag | |
8418 (Typ : Entity_Id; | |
8419 Iface : Entity_Id; | |
8420 Tag_Comp : Entity_Id; | |
8421 Iface_Tag : Node_Id); | |
8422 -- Initialize the tag of the secondary dispatch table of Typ associated | |
8423 -- with Iface. Tag_Comp is the component of Typ that stores Iface_Tag. | |
8424 -- Compiling under the CPP full ABI compatibility mode, if the ancestor | |
8425 -- of Typ CPP tagged type we generate code to inherit the contents of | |
8426 -- the dispatch table directly from the ancestor. | |
8427 | |
8428 -------------------- | |
8429 -- Initialize_Tag -- | |
8430 -------------------- | |
8431 | |
8432 procedure Initialize_Tag | |
8433 (Typ : Entity_Id; | |
8434 Iface : Entity_Id; | |
8435 Tag_Comp : Entity_Id; | |
8436 Iface_Tag : Node_Id) | |
8437 is | |
8438 Comp_Typ : Entity_Id; | |
8439 Offset_To_Top_Comp : Entity_Id := Empty; | |
8440 | |
8441 begin | |
8442 -- Initialize pointer to secondary DT associated with the interface | |
8443 | |
8444 if not Is_Ancestor (Iface, Typ, Use_Full_View => True) then | |
8445 Append_To (Init_Tags_List, | |
8446 Make_Assignment_Statement (Loc, | |
8447 Name => | |
8448 Make_Selected_Component (Loc, | |
8449 Prefix => New_Copy_Tree (Target), | |
8450 Selector_Name => New_Occurrence_Of (Tag_Comp, Loc)), | |
8451 Expression => | |
8452 New_Occurrence_Of (Iface_Tag, Loc))); | |
8453 end if; | |
8454 | |
8455 Comp_Typ := Scope (Tag_Comp); | |
8456 | |
8457 -- Initialize the entries of the table of interfaces. We generate a | |
8458 -- different call when the parent of the type has variable size | |
8459 -- components. | |
8460 | |
8461 if Comp_Typ /= Etype (Comp_Typ) | |
8462 and then Is_Variable_Size_Record (Etype (Comp_Typ)) | |
8463 and then Chars (Tag_Comp) /= Name_uTag | |
8464 then | |
8465 pragma Assert (Present (DT_Offset_To_Top_Func (Tag_Comp))); | |
8466 | |
8467 -- Issue error if Set_Dynamic_Offset_To_Top is not available in a | |
8468 -- configurable run-time environment. | |
8469 | |
8470 if not RTE_Available (RE_Set_Dynamic_Offset_To_Top) then | |
8471 Error_Msg_CRT | |
8472 ("variable size record with interface types", Typ); | |
8473 return; | |
8474 end if; | |
8475 | |
8476 -- Generate: | |
8477 -- Set_Dynamic_Offset_To_Top | |
8478 -- (This => Init, | |
8479 -- Prim_T => Typ'Tag, | |
8480 -- Interface_T => Iface'Tag, | |
8481 -- Offset_Value => n, | |
8482 -- Offset_Func => Fn'Address) | |
8483 | |
8484 Append_To (Stmts_List, | |
8485 Make_Procedure_Call_Statement (Loc, | |
8486 Name => | |
8487 New_Occurrence_Of (RTE (RE_Set_Dynamic_Offset_To_Top), Loc), | |
8488 Parameter_Associations => New_List ( | |
8489 Make_Attribute_Reference (Loc, | |
8490 Prefix => New_Copy_Tree (Target), | |
8491 Attribute_Name => Name_Address), | |
8492 | |
8493 Unchecked_Convert_To (RTE (RE_Tag), | |
8494 New_Occurrence_Of | |
8495 (Node (First_Elmt (Access_Disp_Table (Typ))), Loc)), | |
8496 | |
8497 Unchecked_Convert_To (RTE (RE_Tag), | |
8498 New_Occurrence_Of | |
8499 (Node (First_Elmt (Access_Disp_Table (Iface))), | |
8500 Loc)), | |
8501 | |
8502 Unchecked_Convert_To | |
8503 (RTE (RE_Storage_Offset), | |
8504 Make_Attribute_Reference (Loc, | |
8505 Prefix => | |
8506 Make_Selected_Component (Loc, | |
8507 Prefix => New_Copy_Tree (Target), | |
8508 Selector_Name => | |
8509 New_Occurrence_Of (Tag_Comp, Loc)), | |
8510 Attribute_Name => Name_Position)), | |
8511 | |
8512 Unchecked_Convert_To (RTE (RE_Offset_To_Top_Function_Ptr), | |
8513 Make_Attribute_Reference (Loc, | |
8514 Prefix => New_Occurrence_Of | |
8515 (DT_Offset_To_Top_Func (Tag_Comp), Loc), | |
8516 Attribute_Name => Name_Address))))); | |
8517 | |
8518 -- In this case the next component stores the value of the offset | |
8519 -- to the top. | |
8520 | |
8521 Offset_To_Top_Comp := Next_Entity (Tag_Comp); | |
8522 pragma Assert (Present (Offset_To_Top_Comp)); | |
8523 | |
8524 Append_To (Init_Tags_List, | |
8525 Make_Assignment_Statement (Loc, | |
8526 Name => | |
8527 Make_Selected_Component (Loc, | |
8528 Prefix => New_Copy_Tree (Target), | |
8529 Selector_Name => | |
8530 New_Occurrence_Of (Offset_To_Top_Comp, Loc)), | |
8531 | |
8532 Expression => | |
8533 Make_Attribute_Reference (Loc, | |
8534 Prefix => | |
8535 Make_Selected_Component (Loc, | |
8536 Prefix => New_Copy_Tree (Target), | |
8537 Selector_Name => New_Occurrence_Of (Tag_Comp, Loc)), | |
8538 Attribute_Name => Name_Position))); | |
8539 | |
8540 -- Normal case: No discriminants in the parent type | |
8541 | |
8542 else | |
8543 -- Don't need to set any value if the offset-to-top field is | |
8544 -- statically set or if this interface shares the primary | |
8545 -- dispatch table. | |
8546 | |
8547 if not Building_Static_Secondary_DT (Typ) | |
8548 and then not Is_Ancestor (Iface, Typ, Use_Full_View => True) | |
8549 then | |
8550 Append_To (Stmts_List, | |
8551 Build_Set_Static_Offset_To_Top (Loc, | |
8552 Iface_Tag => New_Occurrence_Of (Iface_Tag, Loc), | |
8553 Offset_Value => | |
8554 Unchecked_Convert_To (RTE (RE_Storage_Offset), | |
8555 Make_Attribute_Reference (Loc, | |
8556 Prefix => | |
8557 Make_Selected_Component (Loc, | |
8558 Prefix => New_Copy_Tree (Target), | |
8559 Selector_Name => | |
8560 New_Occurrence_Of (Tag_Comp, Loc)), | |
8561 Attribute_Name => Name_Position)))); | |
8562 end if; | |
8563 | |
8564 -- Generate: | |
8565 -- Register_Interface_Offset | |
8566 -- (Prim_T => Typ'Tag, | |
8567 -- Interface_T => Iface'Tag, | |
8568 -- Is_Constant => True, | |
8569 -- Offset_Value => n, | |
8570 -- Offset_Func => null); | |
8571 | |
8572 if RTE_Available (RE_Register_Interface_Offset) then | |
8573 Append_To (Stmts_List, | |
8574 Make_Procedure_Call_Statement (Loc, | |
8575 Name => | |
8576 New_Occurrence_Of | |
8577 (RTE (RE_Register_Interface_Offset), Loc), | |
8578 Parameter_Associations => New_List ( | |
8579 Unchecked_Convert_To (RTE (RE_Tag), | |
8580 New_Occurrence_Of | |
8581 (Node (First_Elmt (Access_Disp_Table (Typ))), Loc)), | |
8582 | |
8583 Unchecked_Convert_To (RTE (RE_Tag), | |
8584 New_Occurrence_Of | |
8585 (Node (First_Elmt (Access_Disp_Table (Iface))), Loc)), | |
8586 | |
8587 New_Occurrence_Of (Standard_True, Loc), | |
8588 | |
8589 Unchecked_Convert_To (RTE (RE_Storage_Offset), | |
8590 Make_Attribute_Reference (Loc, | |
8591 Prefix => | |
8592 Make_Selected_Component (Loc, | |
8593 Prefix => New_Copy_Tree (Target), | |
8594 Selector_Name => | |
8595 New_Occurrence_Of (Tag_Comp, Loc)), | |
8596 Attribute_Name => Name_Position)), | |
8597 | |
8598 Make_Null (Loc)))); | |
8599 end if; | |
8600 end if; | |
8601 end Initialize_Tag; | |
8602 | |
8603 -- Local variables | |
8604 | |
8605 Full_Typ : Entity_Id; | |
8606 Ifaces_List : Elist_Id; | |
8607 Ifaces_Comp_List : Elist_Id; | |
8608 Ifaces_Tag_List : Elist_Id; | |
8609 Iface_Elmt : Elmt_Id; | |
8610 Iface_Comp_Elmt : Elmt_Id; | |
8611 Iface_Tag_Elmt : Elmt_Id; | |
8612 Tag_Comp : Node_Id; | |
8613 In_Variable_Pos : Boolean; | |
8614 | |
8615 -- Start of processing for Init_Secondary_Tags | |
8616 | |
8617 begin | |
8618 -- Handle private types | |
8619 | |
8620 if Present (Full_View (Typ)) then | |
8621 Full_Typ := Full_View (Typ); | |
8622 else | |
8623 Full_Typ := Typ; | |
8624 end if; | |
8625 | |
8626 Collect_Interfaces_Info | |
8627 (Full_Typ, Ifaces_List, Ifaces_Comp_List, Ifaces_Tag_List); | |
8628 | |
8629 Iface_Elmt := First_Elmt (Ifaces_List); | |
8630 Iface_Comp_Elmt := First_Elmt (Ifaces_Comp_List); | |
8631 Iface_Tag_Elmt := First_Elmt (Ifaces_Tag_List); | |
8632 while Present (Iface_Elmt) loop | |
8633 Tag_Comp := Node (Iface_Comp_Elmt); | |
8634 | |
8635 -- Check if parent of record type has variable size components | |
8636 | |
8637 In_Variable_Pos := Scope (Tag_Comp) /= Etype (Scope (Tag_Comp)) | |
8638 and then Is_Variable_Size_Record (Etype (Scope (Tag_Comp))); | |
8639 | |
8640 -- If we are compiling under the CPP full ABI compatibility mode and | |
8641 -- the ancestor is a CPP_Pragma tagged type then we generate code to | |
8642 -- initialize the secondary tag components from tags that reference | |
8643 -- secondary tables filled with copy of parent slots. | |
8644 | |
8645 if Is_CPP_Class (Root_Type (Full_Typ)) then | |
8646 | |
8647 -- Reject interface components located at variable offset in | |
8648 -- C++ derivations. This is currently unsupported. | |
8649 | |
8650 if not Fixed_Comps and then In_Variable_Pos then | |
8651 | |
8652 -- Locate the first dynamic component of the record. Done to | |
8653 -- improve the text of the warning. | |
8654 | |
8655 declare | |
8656 Comp : Entity_Id; | |
8657 Comp_Typ : Entity_Id; | |
8658 | |
8659 begin | |
8660 Comp := First_Entity (Typ); | |
8661 while Present (Comp) loop | |
8662 Comp_Typ := Etype (Comp); | |
8663 | |
8664 if Ekind (Comp) /= E_Discriminant | |
8665 and then not Is_Tag (Comp) | |
8666 then | |
8667 exit when | |
8668 (Is_Record_Type (Comp_Typ) | |
8669 and then | |
8670 Is_Variable_Size_Record (Base_Type (Comp_Typ))) | |
8671 or else | |
8672 (Is_Array_Type (Comp_Typ) | |
8673 and then Is_Variable_Size_Array (Comp_Typ)); | |
8674 end if; | |
8675 | |
8676 Next_Entity (Comp); | |
8677 end loop; | |
8678 | |
8679 pragma Assert (Present (Comp)); | |
8680 Error_Msg_Node_2 := Comp; | |
8681 Error_Msg_NE | |
8682 ("parent type & with dynamic component & cannot be parent" | |
8683 & " of 'C'P'P derivation if new interfaces are present", | |
8684 Typ, Scope (Original_Record_Component (Comp))); | |
8685 | |
8686 Error_Msg_Sloc := | |
8687 Sloc (Scope (Original_Record_Component (Comp))); | |
8688 Error_Msg_NE | |
8689 ("type derived from 'C'P'P type & defined #", | |
8690 Typ, Scope (Original_Record_Component (Comp))); | |
8691 | |
8692 -- Avoid duplicated warnings | |
8693 | |
8694 exit; | |
8695 end; | |
8696 | |
8697 -- Initialize secondary tags | |
8698 | |
8699 else | |
8700 Append_To (Init_Tags_List, | |
8701 Make_Assignment_Statement (Loc, | |
8702 Name => | |
8703 Make_Selected_Component (Loc, | |
8704 Prefix => New_Copy_Tree (Target), | |
8705 Selector_Name => | |
8706 New_Occurrence_Of (Node (Iface_Comp_Elmt), Loc)), | |
8707 Expression => | |
8708 New_Occurrence_Of (Node (Iface_Tag_Elmt), Loc))); | |
8709 end if; | |
8710 | |
8711 -- Otherwise generate code to initialize the tag | |
8712 | |
8713 else | |
8714 if (In_Variable_Pos and then Variable_Comps) | |
8715 or else (not In_Variable_Pos and then Fixed_Comps) | |
8716 then | |
8717 Initialize_Tag (Full_Typ, | |
8718 Iface => Node (Iface_Elmt), | |
8719 Tag_Comp => Tag_Comp, | |
8720 Iface_Tag => Node (Iface_Tag_Elmt)); | |
8721 end if; | |
8722 end if; | |
8723 | |
8724 Next_Elmt (Iface_Elmt); | |
8725 Next_Elmt (Iface_Comp_Elmt); | |
8726 Next_Elmt (Iface_Tag_Elmt); | |
8727 end loop; | |
8728 end Init_Secondary_Tags; | |
8729 | |
8730 ------------------------ | |
8731 -- Is_User_Defined_Eq -- | |
8732 ------------------------ | |
8733 | |
8734 function Is_User_Defined_Equality (Prim : Node_Id) return Boolean is | |
8735 begin | |
8736 return Chars (Prim) = Name_Op_Eq | |
8737 and then Etype (First_Formal (Prim)) = | |
8738 Etype (Next_Formal (First_Formal (Prim))) | |
8739 and then Base_Type (Etype (Prim)) = Standard_Boolean; | |
8740 end Is_User_Defined_Equality; | |
8741 | |
8742 ---------------------------------------- | |
8743 -- Make_Controlling_Function_Wrappers -- | |
8744 ---------------------------------------- | |
8745 | |
8746 procedure Make_Controlling_Function_Wrappers | |
8747 (Tag_Typ : Entity_Id; | |
8748 Decl_List : out List_Id; | |
8749 Body_List : out List_Id) | |
8750 is | |
8751 Loc : constant Source_Ptr := Sloc (Tag_Typ); | |
8752 Prim_Elmt : Elmt_Id; | |
8753 Subp : Entity_Id; | |
8754 Actual_List : List_Id; | |
8755 Formal_List : List_Id; | |
8756 Formal : Entity_Id; | |
8757 Par_Formal : Entity_Id; | |
8758 Formal_Node : Node_Id; | |
8759 Func_Body : Node_Id; | |
8760 Func_Decl : Node_Id; | |
8761 Func_Spec : Node_Id; | |
8762 Return_Stmt : Node_Id; | |
8763 | |
8764 begin | |
8765 Decl_List := New_List; | |
8766 Body_List := New_List; | |
8767 | |
8768 Prim_Elmt := First_Elmt (Primitive_Operations (Tag_Typ)); | |
8769 while Present (Prim_Elmt) loop | |
8770 Subp := Node (Prim_Elmt); | |
8771 | |
8772 -- If a primitive function with a controlling result of the type has | |
8773 -- not been overridden by the user, then we must create a wrapper | |
8774 -- function here that effectively overrides it and invokes the | |
8775 -- (non-abstract) parent function. This can only occur for a null | |
8776 -- extension. Note that functions with anonymous controlling access | |
8777 -- results don't qualify and must be overridden. We also exclude | |
8778 -- Input attributes, since each type will have its own version of | |
8779 -- Input constructed by the expander. The test for Comes_From_Source | |
8780 -- is needed to distinguish inherited operations from renamings | |
8781 -- (which also have Alias set). We exclude internal entities with | |
8782 -- Interface_Alias to avoid generating duplicated wrappers since | |
8783 -- the primitive which covers the interface is also available in | |
8784 -- the list of primitive operations. | |
8785 | |
8786 -- The function may be abstract, or require_Overriding may be set | |
8787 -- for it, because tests for null extensions may already have reset | |
8788 -- the Is_Abstract_Subprogram_Flag. If Requires_Overriding is not | |
8789 -- set, functions that need wrappers are recognized by having an | |
8790 -- alias that returns the parent type. | |
8791 | |
8792 if Comes_From_Source (Subp) | |
8793 or else No (Alias (Subp)) | |
8794 or else Present (Interface_Alias (Subp)) | |
8795 or else Ekind (Subp) /= E_Function | |
8796 or else not Has_Controlling_Result (Subp) | |
8797 or else Is_Access_Type (Etype (Subp)) | |
8798 or else Is_Abstract_Subprogram (Alias (Subp)) | |
8799 or else Is_TSS (Subp, TSS_Stream_Input) | |
8800 then | |
8801 goto Next_Prim; | |
8802 | |
8803 elsif Is_Abstract_Subprogram (Subp) | |
8804 or else Requires_Overriding (Subp) | |
8805 or else | |
8806 (Is_Null_Extension (Etype (Subp)) | |
8807 and then Etype (Alias (Subp)) /= Etype (Subp)) | |
8808 then | |
8809 Formal_List := No_List; | |
8810 Formal := First_Formal (Subp); | |
8811 | |
8812 if Present (Formal) then | |
8813 Formal_List := New_List; | |
8814 | |
8815 while Present (Formal) loop | |
8816 Append | |
8817 (Make_Parameter_Specification | |
8818 (Loc, | |
8819 Defining_Identifier => | |
8820 Make_Defining_Identifier (Sloc (Formal), | |
8821 Chars => Chars (Formal)), | |
8822 In_Present => In_Present (Parent (Formal)), | |
8823 Out_Present => Out_Present (Parent (Formal)), | |
8824 Null_Exclusion_Present => | |
8825 Null_Exclusion_Present (Parent (Formal)), | |
8826 Parameter_Type => | |
8827 New_Occurrence_Of (Etype (Formal), Loc), | |
8828 Expression => | |
8829 New_Copy_Tree (Expression (Parent (Formal)))), | |
8830 Formal_List); | |
8831 | |
8832 Next_Formal (Formal); | |
8833 end loop; | |
8834 end if; | |
8835 | |
8836 Func_Spec := | |
8837 Make_Function_Specification (Loc, | |
8838 Defining_Unit_Name => | |
8839 Make_Defining_Identifier (Loc, | |
8840 Chars => Chars (Subp)), | |
8841 Parameter_Specifications => Formal_List, | |
8842 Result_Definition => | |
8843 New_Occurrence_Of (Etype (Subp), Loc)); | |
8844 | |
8845 Func_Decl := Make_Subprogram_Declaration (Loc, Func_Spec); | |
8846 Append_To (Decl_List, Func_Decl); | |
8847 | |
8848 -- Build a wrapper body that calls the parent function. The body | |
8849 -- contains a single return statement that returns an extension | |
8850 -- aggregate whose ancestor part is a call to the parent function, | |
8851 -- passing the formals as actuals (with any controlling arguments | |
8852 -- converted to the types of the corresponding formals of the | |
8853 -- parent function, which might be anonymous access types), and | |
8854 -- having a null extension. | |
8855 | |
8856 Formal := First_Formal (Subp); | |
8857 Par_Formal := First_Formal (Alias (Subp)); | |
8858 Formal_Node := First (Formal_List); | |
8859 | |
8860 if Present (Formal) then | |
8861 Actual_List := New_List; | |
8862 else | |
8863 Actual_List := No_List; | |
8864 end if; | |
8865 | |
8866 while Present (Formal) loop | |
8867 if Is_Controlling_Formal (Formal) then | |
8868 Append_To (Actual_List, | |
8869 Make_Type_Conversion (Loc, | |
8870 Subtype_Mark => | |
8871 New_Occurrence_Of (Etype (Par_Formal), Loc), | |
8872 Expression => | |
8873 New_Occurrence_Of | |
8874 (Defining_Identifier (Formal_Node), Loc))); | |
8875 else | |
8876 Append_To | |
8877 (Actual_List, | |
8878 New_Occurrence_Of | |
8879 (Defining_Identifier (Formal_Node), Loc)); | |
8880 end if; | |
8881 | |
8882 Next_Formal (Formal); | |
8883 Next_Formal (Par_Formal); | |
8884 Next (Formal_Node); | |
8885 end loop; | |
8886 | |
8887 Return_Stmt := | |
8888 Make_Simple_Return_Statement (Loc, | |
8889 Expression => | |
8890 Make_Extension_Aggregate (Loc, | |
8891 Ancestor_Part => | |
8892 Make_Function_Call (Loc, | |
8893 Name => | |
8894 New_Occurrence_Of (Alias (Subp), Loc), | |
8895 Parameter_Associations => Actual_List), | |
8896 Null_Record_Present => True)); | |
8897 | |
8898 Func_Body := | |
8899 Make_Subprogram_Body (Loc, | |
8900 Specification => New_Copy_Tree (Func_Spec), | |
8901 Declarations => Empty_List, | |
8902 Handled_Statement_Sequence => | |
8903 Make_Handled_Sequence_Of_Statements (Loc, | |
8904 Statements => New_List (Return_Stmt))); | |
8905 | |
8906 Set_Defining_Unit_Name | |
8907 (Specification (Func_Body), | |
8908 Make_Defining_Identifier (Loc, Chars (Subp))); | |
8909 | |
8910 Append_To (Body_List, Func_Body); | |
8911 | |
8912 -- Replace the inherited function with the wrapper function in the | |
8913 -- primitive operations list. We add the minimum decoration needed | |
8914 -- to override interface primitives. | |
8915 | |
8916 Set_Ekind (Defining_Unit_Name (Func_Spec), E_Function); | |
8917 | |
8918 Override_Dispatching_Operation | |
8919 (Tag_Typ, Subp, New_Op => Defining_Unit_Name (Func_Spec), | |
8920 Is_Wrapper => True); | |
8921 end if; | |
8922 | |
8923 <<Next_Prim>> | |
8924 Next_Elmt (Prim_Elmt); | |
8925 end loop; | |
8926 end Make_Controlling_Function_Wrappers; | |
8927 | |
8928 ------------------- | |
8929 -- Make_Eq_Body -- | |
8930 ------------------- | |
8931 | |
8932 function Make_Eq_Body | |
8933 (Typ : Entity_Id; | |
8934 Eq_Name : Name_Id) return Node_Id | |
8935 is | |
8936 Loc : constant Source_Ptr := Sloc (Parent (Typ)); | |
8937 Decl : Node_Id; | |
8938 Def : constant Node_Id := Parent (Typ); | |
8939 Stmts : constant List_Id := New_List; | |
8940 Variant_Case : Boolean := Has_Discriminants (Typ); | |
8941 Comps : Node_Id := Empty; | |
8942 Typ_Def : Node_Id := Type_Definition (Def); | |
8943 | |
8944 begin | |
8945 Decl := | |
8946 Predef_Spec_Or_Body (Loc, | |
8947 Tag_Typ => Typ, | |
8948 Name => Eq_Name, | |
8949 Profile => New_List ( | |
8950 Make_Parameter_Specification (Loc, | |
8951 Defining_Identifier => | |
8952 Make_Defining_Identifier (Loc, Name_X), | |
8953 Parameter_Type => New_Occurrence_Of (Typ, Loc)), | |
8954 | |
8955 Make_Parameter_Specification (Loc, | |
8956 Defining_Identifier => | |
8957 Make_Defining_Identifier (Loc, Name_Y), | |
8958 Parameter_Type => New_Occurrence_Of (Typ, Loc))), | |
8959 | |
8960 Ret_Type => Standard_Boolean, | |
8961 For_Body => True); | |
8962 | |
8963 if Variant_Case then | |
8964 if Nkind (Typ_Def) = N_Derived_Type_Definition then | |
8965 Typ_Def := Record_Extension_Part (Typ_Def); | |
8966 end if; | |
8967 | |
8968 if Present (Typ_Def) then | |
8969 Comps := Component_List (Typ_Def); | |
8970 end if; | |
8971 | |
8972 Variant_Case := | |
8973 Present (Comps) and then Present (Variant_Part (Comps)); | |
8974 end if; | |
8975 | |
8976 if Variant_Case then | |
8977 Append_To (Stmts, | |
8978 Make_Eq_If (Typ, Discriminant_Specifications (Def))); | |
8979 Append_List_To (Stmts, Make_Eq_Case (Typ, Comps)); | |
8980 Append_To (Stmts, | |
8981 Make_Simple_Return_Statement (Loc, | |
8982 Expression => New_Occurrence_Of (Standard_True, Loc))); | |
8983 | |
8984 else | |
8985 Append_To (Stmts, | |
8986 Make_Simple_Return_Statement (Loc, | |
8987 Expression => | |
8988 Expand_Record_Equality | |
8989 (Typ, | |
8990 Typ => Typ, | |
8991 Lhs => Make_Identifier (Loc, Name_X), | |
8992 Rhs => Make_Identifier (Loc, Name_Y), | |
8993 Bodies => Declarations (Decl)))); | |
8994 end if; | |
8995 | |
8996 Set_Handled_Statement_Sequence | |
8997 (Decl, Make_Handled_Sequence_Of_Statements (Loc, Stmts)); | |
8998 return Decl; | |
8999 end Make_Eq_Body; | |
9000 | |
9001 ------------------ | |
9002 -- Make_Eq_Case -- | |
9003 ------------------ | |
9004 | |
9005 -- <Make_Eq_If shared components> | |
9006 | |
9007 -- case X.D1 is | |
9008 -- when V1 => <Make_Eq_Case> on subcomponents | |
9009 -- ... | |
9010 -- when Vn => <Make_Eq_Case> on subcomponents | |
9011 -- end case; | |
9012 | |
9013 function Make_Eq_Case | |
9014 (E : Entity_Id; | |
9015 CL : Node_Id; | |
9016 Discrs : Elist_Id := New_Elmt_List) return List_Id | |
9017 is | |
9018 Loc : constant Source_Ptr := Sloc (E); | |
9019 Result : constant List_Id := New_List; | |
9020 Variant : Node_Id; | |
9021 Alt_List : List_Id; | |
9022 | |
9023 function Corresponding_Formal (C : Node_Id) return Entity_Id; | |
9024 -- Given the discriminant that controls a given variant of an unchecked | |
9025 -- union, find the formal of the equality function that carries the | |
9026 -- inferred value of the discriminant. | |
9027 | |
9028 function External_Name (E : Entity_Id) return Name_Id; | |
9029 -- The value of a given discriminant is conveyed in the corresponding | |
9030 -- formal parameter of the equality routine. The name of this formal | |
9031 -- parameter carries a one-character suffix which is removed here. | |
9032 | |
9033 -------------------------- | |
9034 -- Corresponding_Formal -- | |
9035 -------------------------- | |
9036 | |
9037 function Corresponding_Formal (C : Node_Id) return Entity_Id is | |
9038 Discr : constant Entity_Id := Entity (Name (Variant_Part (C))); | |
9039 Elm : Elmt_Id; | |
9040 | |
9041 begin | |
9042 Elm := First_Elmt (Discrs); | |
9043 while Present (Elm) loop | |
9044 if Chars (Discr) = External_Name (Node (Elm)) then | |
9045 return Node (Elm); | |
9046 end if; | |
9047 | |
9048 Next_Elmt (Elm); | |
9049 end loop; | |
9050 | |
9051 -- A formal of the proper name must be found | |
9052 | |
9053 raise Program_Error; | |
9054 end Corresponding_Formal; | |
9055 | |
9056 ------------------- | |
9057 -- External_Name -- | |
9058 ------------------- | |
9059 | |
9060 function External_Name (E : Entity_Id) return Name_Id is | |
9061 begin | |
9062 Get_Name_String (Chars (E)); | |
9063 Name_Len := Name_Len - 1; | |
9064 return Name_Find; | |
9065 end External_Name; | |
9066 | |
9067 -- Start of processing for Make_Eq_Case | |
9068 | |
9069 begin | |
9070 Append_To (Result, Make_Eq_If (E, Component_Items (CL))); | |
9071 | |
9072 if No (Variant_Part (CL)) then | |
9073 return Result; | |
9074 end if; | |
9075 | |
9076 Variant := First_Non_Pragma (Variants (Variant_Part (CL))); | |
9077 | |
9078 if No (Variant) then | |
9079 return Result; | |
9080 end if; | |
9081 | |
9082 Alt_List := New_List; | |
9083 while Present (Variant) loop | |
9084 Append_To (Alt_List, | |
9085 Make_Case_Statement_Alternative (Loc, | |
9086 Discrete_Choices => New_Copy_List (Discrete_Choices (Variant)), | |
9087 Statements => | |
9088 Make_Eq_Case (E, Component_List (Variant), Discrs))); | |
9089 Next_Non_Pragma (Variant); | |
9090 end loop; | |
9091 | |
9092 -- If we have an Unchecked_Union, use one of the parameters of the | |
9093 -- enclosing equality routine that captures the discriminant, to use | |
9094 -- as the expression in the generated case statement. | |
9095 | |
9096 if Is_Unchecked_Union (E) then | |
9097 Append_To (Result, | |
9098 Make_Case_Statement (Loc, | |
9099 Expression => | |
9100 New_Occurrence_Of (Corresponding_Formal (CL), Loc), | |
9101 Alternatives => Alt_List)); | |
9102 | |
9103 else | |
9104 Append_To (Result, | |
9105 Make_Case_Statement (Loc, | |
9106 Expression => | |
9107 Make_Selected_Component (Loc, | |
9108 Prefix => Make_Identifier (Loc, Name_X), | |
9109 Selector_Name => New_Copy (Name (Variant_Part (CL)))), | |
9110 Alternatives => Alt_List)); | |
9111 end if; | |
9112 | |
9113 return Result; | |
9114 end Make_Eq_Case; | |
9115 | |
9116 ---------------- | |
9117 -- Make_Eq_If -- | |
9118 ---------------- | |
9119 | |
9120 -- Generates: | |
9121 | |
9122 -- if | |
9123 -- X.C1 /= Y.C1 | |
9124 -- or else | |
9125 -- X.C2 /= Y.C2 | |
9126 -- ... | |
9127 -- then | |
9128 -- return False; | |
9129 -- end if; | |
9130 | |
9131 -- or a null statement if the list L is empty | |
9132 | |
9133 function Make_Eq_If | |
9134 (E : Entity_Id; | |
9135 L : List_Id) return Node_Id | |
9136 is | |
9137 Loc : constant Source_Ptr := Sloc (E); | |
9138 C : Node_Id; | |
9139 Field_Name : Name_Id; | |
9140 Cond : Node_Id; | |
9141 | |
9142 begin | |
9143 if No (L) then | |
9144 return Make_Null_Statement (Loc); | |
9145 | |
9146 else | |
9147 Cond := Empty; | |
9148 | |
9149 C := First_Non_Pragma (L); | |
9150 while Present (C) loop | |
9151 Field_Name := Chars (Defining_Identifier (C)); | |
9152 | |
9153 -- The tags must not be compared: they are not part of the value. | |
9154 -- Ditto for parent interfaces because their equality operator is | |
9155 -- abstract. | |
9156 | |
9157 -- Note also that in the following, we use Make_Identifier for | |
9158 -- the component names. Use of New_Occurrence_Of to identify the | |
9159 -- components would be incorrect because the wrong entities for | |
9160 -- discriminants could be picked up in the private type case. | |
9161 | |
9162 if Field_Name = Name_uParent | |
9163 and then Is_Interface (Etype (Defining_Identifier (C))) | |
9164 then | |
9165 null; | |
9166 | |
9167 elsif Field_Name /= Name_uTag then | |
9168 Evolve_Or_Else (Cond, | |
9169 Make_Op_Ne (Loc, | |
9170 Left_Opnd => | |
9171 Make_Selected_Component (Loc, | |
9172 Prefix => Make_Identifier (Loc, Name_X), | |
9173 Selector_Name => Make_Identifier (Loc, Field_Name)), | |
9174 | |
9175 Right_Opnd => | |
9176 Make_Selected_Component (Loc, | |
9177 Prefix => Make_Identifier (Loc, Name_Y), | |
9178 Selector_Name => Make_Identifier (Loc, Field_Name)))); | |
9179 end if; | |
9180 | |
9181 Next_Non_Pragma (C); | |
9182 end loop; | |
9183 | |
9184 if No (Cond) then | |
9185 return Make_Null_Statement (Loc); | |
9186 | |
9187 else | |
9188 return | |
9189 Make_Implicit_If_Statement (E, | |
9190 Condition => Cond, | |
9191 Then_Statements => New_List ( | |
9192 Make_Simple_Return_Statement (Loc, | |
9193 Expression => New_Occurrence_Of (Standard_False, Loc)))); | |
9194 end if; | |
9195 end if; | |
9196 end Make_Eq_If; | |
9197 | |
9198 ------------------- | |
9199 -- Make_Neq_Body -- | |
9200 ------------------- | |
9201 | |
9202 function Make_Neq_Body (Tag_Typ : Entity_Id) return Node_Id is | |
9203 | |
9204 function Is_Predefined_Neq_Renaming (Prim : Node_Id) return Boolean; | |
9205 -- Returns true if Prim is a renaming of an unresolved predefined | |
9206 -- inequality operation. | |
9207 | |
9208 -------------------------------- | |
9209 -- Is_Predefined_Neq_Renaming -- | |
9210 -------------------------------- | |
9211 | |
9212 function Is_Predefined_Neq_Renaming (Prim : Node_Id) return Boolean is | |
9213 begin | |
9214 return Chars (Prim) /= Name_Op_Ne | |
9215 and then Present (Alias (Prim)) | |
9216 and then Comes_From_Source (Prim) | |
9217 and then Is_Intrinsic_Subprogram (Alias (Prim)) | |
9218 and then Chars (Alias (Prim)) = Name_Op_Ne; | |
9219 end Is_Predefined_Neq_Renaming; | |
9220 | |
9221 -- Local variables | |
9222 | |
9223 Loc : constant Source_Ptr := Sloc (Parent (Tag_Typ)); | |
9224 Stmts : constant List_Id := New_List; | |
9225 Decl : Node_Id; | |
9226 Eq_Prim : Entity_Id; | |
9227 Left_Op : Entity_Id; | |
9228 Renaming_Prim : Entity_Id; | |
9229 Right_Op : Entity_Id; | |
9230 Target : Entity_Id; | |
9231 | |
9232 -- Start of processing for Make_Neq_Body | |
9233 | |
9234 begin | |
9235 -- For a call on a renaming of a dispatching subprogram that is | |
9236 -- overridden, if the overriding occurred before the renaming, then | |
9237 -- the body executed is that of the overriding declaration, even if the | |
9238 -- overriding declaration is not visible at the place of the renaming; | |
9239 -- otherwise, the inherited or predefined subprogram is called, see | |
9240 -- (RM 8.5.4(8)) | |
9241 | |
9242 -- Stage 1: Search for a renaming of the inequality primitive and also | |
9243 -- search for an overriding of the equality primitive located before the | |
9244 -- renaming declaration. | |
9245 | |
9246 declare | |
9247 Elmt : Elmt_Id; | |
9248 Prim : Node_Id; | |
9249 | |
9250 begin | |
9251 Eq_Prim := Empty; | |
9252 Renaming_Prim := Empty; | |
9253 | |
9254 Elmt := First_Elmt (Primitive_Operations (Tag_Typ)); | |
9255 while Present (Elmt) loop | |
9256 Prim := Node (Elmt); | |
9257 | |
9258 if Is_User_Defined_Equality (Prim) and then No (Alias (Prim)) then | |
9259 if No (Renaming_Prim) then | |
9260 pragma Assert (No (Eq_Prim)); | |
9261 Eq_Prim := Prim; | |
9262 end if; | |
9263 | |
9264 elsif Is_Predefined_Neq_Renaming (Prim) then | |
9265 Renaming_Prim := Prim; | |
9266 end if; | |
9267 | |
9268 Next_Elmt (Elmt); | |
9269 end loop; | |
9270 end; | |
9271 | |
9272 -- No further action needed if no renaming was found | |
9273 | |
9274 if No (Renaming_Prim) then | |
9275 return Empty; | |
9276 end if; | |
9277 | |
9278 -- Stage 2: Replace the renaming declaration by a subprogram declaration | |
9279 -- (required to add its body) | |
9280 | |
9281 Decl := Parent (Parent (Renaming_Prim)); | |
9282 Rewrite (Decl, | |
9283 Make_Subprogram_Declaration (Loc, | |
9284 Specification => Specification (Decl))); | |
9285 Set_Analyzed (Decl); | |
9286 | |
9287 -- Remove the decoration of intrinsic renaming subprogram | |
9288 | |
9289 Set_Is_Intrinsic_Subprogram (Renaming_Prim, False); | |
9290 Set_Convention (Renaming_Prim, Convention_Ada); | |
9291 Set_Alias (Renaming_Prim, Empty); | |
9292 Set_Has_Completion (Renaming_Prim, False); | |
9293 | |
9294 -- Stage 3: Build the corresponding body | |
9295 | |
9296 Left_Op := First_Formal (Renaming_Prim); | |
9297 Right_Op := Next_Formal (Left_Op); | |
9298 | |
9299 Decl := | |
9300 Predef_Spec_Or_Body (Loc, | |
9301 Tag_Typ => Tag_Typ, | |
9302 Name => Chars (Renaming_Prim), | |
9303 Profile => New_List ( | |
9304 Make_Parameter_Specification (Loc, | |
9305 Defining_Identifier => | |
9306 Make_Defining_Identifier (Loc, Chars (Left_Op)), | |
9307 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)), | |
9308 | |
9309 Make_Parameter_Specification (Loc, | |
9310 Defining_Identifier => | |
9311 Make_Defining_Identifier (Loc, Chars (Right_Op)), | |
9312 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))), | |
9313 | |
9314 Ret_Type => Standard_Boolean, | |
9315 For_Body => True); | |
9316 | |
9317 -- If the overriding of the equality primitive occurred before the | |
9318 -- renaming, then generate: | |
9319 | |
9320 -- function <Neq_Name> (X : Y : Typ) return Boolean is | |
9321 -- begin | |
9322 -- return not Oeq (X, Y); | |
9323 -- end; | |
9324 | |
9325 if Present (Eq_Prim) then | |
9326 Target := Eq_Prim; | |
9327 | |
9328 -- Otherwise build a nested subprogram which performs the predefined | |
9329 -- evaluation of the equality operator. That is, generate: | |
9330 | |
9331 -- function <Neq_Name> (X : Y : Typ) return Boolean is | |
9332 -- function Oeq (X : Y) return Boolean is | |
9333 -- begin | |
9334 -- <<body of default implementation>> | |
9335 -- end; | |
9336 -- begin | |
9337 -- return not Oeq (X, Y); | |
9338 -- end; | |
9339 | |
9340 else | |
9341 declare | |
9342 Local_Subp : Node_Id; | |
9343 begin | |
9344 Local_Subp := Make_Eq_Body (Tag_Typ, Name_Op_Eq); | |
9345 Set_Declarations (Decl, New_List (Local_Subp)); | |
9346 Target := Defining_Entity (Local_Subp); | |
9347 end; | |
9348 end if; | |
9349 | |
9350 Append_To (Stmts, | |
9351 Make_Simple_Return_Statement (Loc, | |
9352 Expression => | |
9353 Make_Op_Not (Loc, | |
9354 Make_Function_Call (Loc, | |
9355 Name => New_Occurrence_Of (Target, Loc), | |
9356 Parameter_Associations => New_List ( | |
9357 Make_Identifier (Loc, Chars (Left_Op)), | |
9358 Make_Identifier (Loc, Chars (Right_Op))))))); | |
9359 | |
9360 Set_Handled_Statement_Sequence | |
9361 (Decl, Make_Handled_Sequence_Of_Statements (Loc, Stmts)); | |
9362 return Decl; | |
9363 end Make_Neq_Body; | |
9364 | |
9365 ------------------------------- | |
9366 -- Make_Null_Procedure_Specs -- | |
9367 ------------------------------- | |
9368 | |
9369 function Make_Null_Procedure_Specs (Tag_Typ : Entity_Id) return List_Id is | |
9370 Decl_List : constant List_Id := New_List; | |
9371 Loc : constant Source_Ptr := Sloc (Tag_Typ); | |
9372 Formal : Entity_Id; | |
9373 Formal_List : List_Id; | |
9374 New_Param_Spec : Node_Id; | |
9375 Parent_Subp : Entity_Id; | |
9376 Prim_Elmt : Elmt_Id; | |
9377 Subp : Entity_Id; | |
9378 | |
9379 begin | |
9380 Prim_Elmt := First_Elmt (Primitive_Operations (Tag_Typ)); | |
9381 while Present (Prim_Elmt) loop | |
9382 Subp := Node (Prim_Elmt); | |
9383 | |
9384 -- If a null procedure inherited from an interface has not been | |
9385 -- overridden, then we build a null procedure declaration to | |
9386 -- override the inherited procedure. | |
9387 | |
9388 Parent_Subp := Alias (Subp); | |
9389 | |
9390 if Present (Parent_Subp) | |
9391 and then Is_Null_Interface_Primitive (Parent_Subp) | |
9392 then | |
9393 Formal_List := No_List; | |
9394 Formal := First_Formal (Subp); | |
9395 | |
9396 if Present (Formal) then | |
9397 Formal_List := New_List; | |
9398 | |
9399 while Present (Formal) loop | |
9400 | |
9401 -- Copy the parameter spec including default expressions | |
9402 | |
9403 New_Param_Spec := | |
9404 New_Copy_Tree (Parent (Formal), New_Sloc => Loc); | |
9405 | |
9406 -- Generate a new defining identifier for the new formal. | |
9407 -- required because New_Copy_Tree does not duplicate | |
9408 -- semantic fields (except itypes). | |
9409 | |
9410 Set_Defining_Identifier (New_Param_Spec, | |
9411 Make_Defining_Identifier (Sloc (Formal), | |
9412 Chars => Chars (Formal))); | |
9413 | |
9414 -- For controlling arguments we must change their | |
9415 -- parameter type to reference the tagged type (instead | |
9416 -- of the interface type) | |
9417 | |
9418 if Is_Controlling_Formal (Formal) then | |
9419 if Nkind (Parameter_Type (Parent (Formal))) = N_Identifier | |
9420 then | |
9421 Set_Parameter_Type (New_Param_Spec, | |
9422 New_Occurrence_Of (Tag_Typ, Loc)); | |
9423 | |
9424 else pragma Assert | |
9425 (Nkind (Parameter_Type (Parent (Formal))) = | |
9426 N_Access_Definition); | |
9427 Set_Subtype_Mark (Parameter_Type (New_Param_Spec), | |
9428 New_Occurrence_Of (Tag_Typ, Loc)); | |
9429 end if; | |
9430 end if; | |
9431 | |
9432 Append (New_Param_Spec, Formal_List); | |
9433 | |
9434 Next_Formal (Formal); | |
9435 end loop; | |
9436 end if; | |
9437 | |
9438 Append_To (Decl_List, | |
9439 Make_Subprogram_Declaration (Loc, | |
9440 Make_Procedure_Specification (Loc, | |
9441 Defining_Unit_Name => | |
9442 Make_Defining_Identifier (Loc, Chars (Subp)), | |
9443 Parameter_Specifications => Formal_List, | |
9444 Null_Present => True))); | |
9445 end if; | |
9446 | |
9447 Next_Elmt (Prim_Elmt); | |
9448 end loop; | |
9449 | |
9450 return Decl_List; | |
9451 end Make_Null_Procedure_Specs; | |
9452 | |
9453 ------------------------------------- | |
9454 -- Make_Predefined_Primitive_Specs -- | |
9455 ------------------------------------- | |
9456 | |
9457 procedure Make_Predefined_Primitive_Specs | |
9458 (Tag_Typ : Entity_Id; | |
9459 Predef_List : out List_Id; | |
9460 Renamed_Eq : out Entity_Id) | |
9461 is | |
9462 function Is_Predefined_Eq_Renaming (Prim : Node_Id) return Boolean; | |
9463 -- Returns true if Prim is a renaming of an unresolved predefined | |
9464 -- equality operation. | |
9465 | |
9466 ------------------------------- | |
9467 -- Is_Predefined_Eq_Renaming -- | |
9468 ------------------------------- | |
9469 | |
9470 function Is_Predefined_Eq_Renaming (Prim : Node_Id) return Boolean is | |
9471 begin | |
9472 return Chars (Prim) /= Name_Op_Eq | |
9473 and then Present (Alias (Prim)) | |
9474 and then Comes_From_Source (Prim) | |
9475 and then Is_Intrinsic_Subprogram (Alias (Prim)) | |
9476 and then Chars (Alias (Prim)) = Name_Op_Eq; | |
9477 end Is_Predefined_Eq_Renaming; | |
9478 | |
9479 -- Local variables | |
9480 | |
9481 Loc : constant Source_Ptr := Sloc (Tag_Typ); | |
9482 Res : constant List_Id := New_List; | |
9483 Eq_Name : Name_Id := Name_Op_Eq; | |
9484 Eq_Needed : Boolean; | |
9485 Eq_Spec : Node_Id; | |
9486 Prim : Elmt_Id; | |
9487 | |
9488 Has_Predef_Eq_Renaming : Boolean := False; | |
9489 -- Set to True if Tag_Typ has a primitive that renames the predefined | |
9490 -- equality operator. Used to implement (RM 8-5-4(8)). | |
9491 | |
9492 -- Start of processing for Make_Predefined_Primitive_Specs | |
9493 | |
9494 begin | |
9495 Renamed_Eq := Empty; | |
9496 | |
9497 -- Spec of _Size | |
9498 | |
9499 Append_To (Res, Predef_Spec_Or_Body (Loc, | |
9500 Tag_Typ => Tag_Typ, | |
9501 Name => Name_uSize, | |
9502 Profile => New_List ( | |
9503 Make_Parameter_Specification (Loc, | |
9504 Defining_Identifier => Make_Defining_Identifier (Loc, Name_X), | |
9505 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))), | |
9506 | |
9507 Ret_Type => Standard_Long_Long_Integer)); | |
9508 | |
9509 -- Specs for dispatching stream attributes | |
9510 | |
9511 declare | |
9512 Stream_Op_TSS_Names : | |
9513 constant array (Positive range <>) of TSS_Name_Type := | |
9514 (TSS_Stream_Read, | |
9515 TSS_Stream_Write, | |
9516 TSS_Stream_Input, | |
9517 TSS_Stream_Output); | |
9518 | |
9519 begin | |
9520 for Op in Stream_Op_TSS_Names'Range loop | |
9521 if Stream_Operation_OK (Tag_Typ, Stream_Op_TSS_Names (Op)) then | |
9522 Append_To (Res, | |
9523 Predef_Stream_Attr_Spec (Loc, Tag_Typ, | |
9524 Stream_Op_TSS_Names (Op))); | |
9525 end if; | |
9526 end loop; | |
9527 end; | |
9528 | |
9529 -- Spec of "=" is expanded if the type is not limited and if a user | |
9530 -- defined "=" was not already declared for the non-full view of a | |
9531 -- private extension | |
9532 | |
9533 if not Is_Limited_Type (Tag_Typ) then | |
9534 Eq_Needed := True; | |
9535 Prim := First_Elmt (Primitive_Operations (Tag_Typ)); | |
9536 while Present (Prim) loop | |
9537 | |
9538 -- If a primitive is encountered that renames the predefined | |
9539 -- equality operator before reaching any explicit equality | |
9540 -- primitive, then we still need to create a predefined equality | |
9541 -- function, because calls to it can occur via the renaming. A | |
9542 -- new name is created for the equality to avoid conflicting with | |
9543 -- any user-defined equality. (Note that this doesn't account for | |
9544 -- renamings of equality nested within subpackages???) | |
9545 | |
9546 if Is_Predefined_Eq_Renaming (Node (Prim)) then | |
9547 Has_Predef_Eq_Renaming := True; | |
9548 Eq_Name := New_External_Name (Chars (Node (Prim)), 'E'); | |
9549 | |
9550 -- User-defined equality | |
9551 | |
9552 elsif Is_User_Defined_Equality (Node (Prim)) then | |
9553 if No (Alias (Node (Prim))) | |
9554 or else Nkind (Unit_Declaration_Node (Node (Prim))) = | |
9555 N_Subprogram_Renaming_Declaration | |
9556 then | |
9557 Eq_Needed := False; | |
9558 exit; | |
9559 | |
9560 -- If the parent is not an interface type and has an abstract | |
9561 -- equality function explicitly defined in the sources, then | |
9562 -- the inherited equality is abstract as well, and no body can | |
9563 -- be created for it. | |
9564 | |
9565 elsif not Is_Interface (Etype (Tag_Typ)) | |
9566 and then Present (Alias (Node (Prim))) | |
9567 and then Comes_From_Source (Alias (Node (Prim))) | |
9568 and then Is_Abstract_Subprogram (Alias (Node (Prim))) | |
9569 then | |
9570 Eq_Needed := False; | |
9571 exit; | |
9572 | |
9573 -- If the type has an equality function corresponding with | |
9574 -- a primitive defined in an interface type, the inherited | |
9575 -- equality is abstract as well, and no body can be created | |
9576 -- for it. | |
9577 | |
9578 elsif Present (Alias (Node (Prim))) | |
9579 and then Comes_From_Source (Ultimate_Alias (Node (Prim))) | |
9580 and then | |
9581 Is_Interface | |
9582 (Find_Dispatching_Type (Ultimate_Alias (Node (Prim)))) | |
9583 then | |
9584 Eq_Needed := False; | |
9585 exit; | |
9586 end if; | |
9587 end if; | |
9588 | |
9589 Next_Elmt (Prim); | |
9590 end loop; | |
9591 | |
9592 -- If a renaming of predefined equality was found but there was no | |
9593 -- user-defined equality (so Eq_Needed is still true), then set the | |
9594 -- name back to Name_Op_Eq. But in the case where a user-defined | |
9595 -- equality was located after such a renaming, then the predefined | |
9596 -- equality function is still needed, so Eq_Needed must be set back | |
9597 -- to True. | |
9598 | |
9599 if Eq_Name /= Name_Op_Eq then | |
9600 if Eq_Needed then | |
9601 Eq_Name := Name_Op_Eq; | |
9602 else | |
9603 Eq_Needed := True; | |
9604 end if; | |
9605 end if; | |
9606 | |
9607 if Eq_Needed then | |
9608 Eq_Spec := Predef_Spec_Or_Body (Loc, | |
9609 Tag_Typ => Tag_Typ, | |
9610 Name => Eq_Name, | |
9611 Profile => New_List ( | |
9612 Make_Parameter_Specification (Loc, | |
9613 Defining_Identifier => | |
9614 Make_Defining_Identifier (Loc, Name_X), | |
9615 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)), | |
9616 | |
9617 Make_Parameter_Specification (Loc, | |
9618 Defining_Identifier => | |
9619 Make_Defining_Identifier (Loc, Name_Y), | |
9620 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))), | |
9621 Ret_Type => Standard_Boolean); | |
9622 Append_To (Res, Eq_Spec); | |
9623 | |
9624 if Has_Predef_Eq_Renaming then | |
9625 Renamed_Eq := Defining_Unit_Name (Specification (Eq_Spec)); | |
9626 | |
9627 Prim := First_Elmt (Primitive_Operations (Tag_Typ)); | |
9628 while Present (Prim) loop | |
9629 | |
9630 -- Any renamings of equality that appeared before an | |
9631 -- overriding equality must be updated to refer to the | |
9632 -- entity for the predefined equality, otherwise calls via | |
9633 -- the renaming would get incorrectly resolved to call the | |
9634 -- user-defined equality function. | |
9635 | |
9636 if Is_Predefined_Eq_Renaming (Node (Prim)) then | |
9637 Set_Alias (Node (Prim), Renamed_Eq); | |
9638 | |
9639 -- Exit upon encountering a user-defined equality | |
9640 | |
9641 elsif Chars (Node (Prim)) = Name_Op_Eq | |
9642 and then No (Alias (Node (Prim))) | |
9643 then | |
9644 exit; | |
9645 end if; | |
9646 | |
9647 Next_Elmt (Prim); | |
9648 end loop; | |
9649 end if; | |
9650 end if; | |
9651 | |
9652 -- Spec for dispatching assignment | |
9653 | |
9654 Append_To (Res, Predef_Spec_Or_Body (Loc, | |
9655 Tag_Typ => Tag_Typ, | |
9656 Name => Name_uAssign, | |
9657 Profile => New_List ( | |
9658 Make_Parameter_Specification (Loc, | |
9659 Defining_Identifier => Make_Defining_Identifier (Loc, Name_X), | |
9660 Out_Present => True, | |
9661 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)), | |
9662 | |
9663 Make_Parameter_Specification (Loc, | |
9664 Defining_Identifier => Make_Defining_Identifier (Loc, Name_Y), | |
9665 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))))); | |
9666 end if; | |
9667 | |
9668 -- Ada 2005: Generate declarations for the following primitive | |
9669 -- operations for limited interfaces and synchronized types that | |
9670 -- implement a limited interface. | |
9671 | |
9672 -- Disp_Asynchronous_Select | |
9673 -- Disp_Conditional_Select | |
9674 -- Disp_Get_Prim_Op_Kind | |
9675 -- Disp_Get_Task_Id | |
9676 -- Disp_Requeue | |
9677 -- Disp_Timed_Select | |
9678 | |
9679 -- Disable the generation of these bodies if No_Dispatching_Calls, | |
9680 -- Ravenscar or ZFP is active. | |
9681 | |
9682 if Ada_Version >= Ada_2005 | |
9683 and then not Restriction_Active (No_Dispatching_Calls) | |
9684 and then not Restriction_Active (No_Select_Statements) | |
9685 and then RTE_Available (RE_Select_Specific_Data) | |
9686 then | |
9687 -- These primitives are defined abstract in interface types | |
9688 | |
9689 if Is_Interface (Tag_Typ) | |
9690 and then Is_Limited_Record (Tag_Typ) | |
9691 then | |
9692 Append_To (Res, | |
9693 Make_Abstract_Subprogram_Declaration (Loc, | |
9694 Specification => | |
9695 Make_Disp_Asynchronous_Select_Spec (Tag_Typ))); | |
9696 | |
9697 Append_To (Res, | |
9698 Make_Abstract_Subprogram_Declaration (Loc, | |
9699 Specification => | |
9700 Make_Disp_Conditional_Select_Spec (Tag_Typ))); | |
9701 | |
9702 Append_To (Res, | |
9703 Make_Abstract_Subprogram_Declaration (Loc, | |
9704 Specification => | |
9705 Make_Disp_Get_Prim_Op_Kind_Spec (Tag_Typ))); | |
9706 | |
9707 Append_To (Res, | |
9708 Make_Abstract_Subprogram_Declaration (Loc, | |
9709 Specification => | |
9710 Make_Disp_Get_Task_Id_Spec (Tag_Typ))); | |
9711 | |
9712 Append_To (Res, | |
9713 Make_Abstract_Subprogram_Declaration (Loc, | |
9714 Specification => | |
9715 Make_Disp_Requeue_Spec (Tag_Typ))); | |
9716 | |
9717 Append_To (Res, | |
9718 Make_Abstract_Subprogram_Declaration (Loc, | |
9719 Specification => | |
9720 Make_Disp_Timed_Select_Spec (Tag_Typ))); | |
9721 | |
9722 -- If ancestor is an interface type, declare non-abstract primitives | |
9723 -- to override the abstract primitives of the interface type. | |
9724 | |
9725 -- In VM targets we define these primitives in all root tagged types | |
9726 -- that are not interface types. Done because in VM targets we don't | |
9727 -- have secondary dispatch tables and any derivation of Tag_Typ may | |
9728 -- cover limited interfaces (which always have these primitives since | |
9729 -- they may be ancestors of synchronized interface types). | |
9730 | |
9731 elsif (not Is_Interface (Tag_Typ) | |
9732 and then Is_Interface (Etype (Tag_Typ)) | |
9733 and then Is_Limited_Record (Etype (Tag_Typ))) | |
9734 or else | |
9735 (Is_Concurrent_Record_Type (Tag_Typ) | |
9736 and then Has_Interfaces (Tag_Typ)) | |
9737 or else | |
9738 (not Tagged_Type_Expansion | |
9739 and then not Is_Interface (Tag_Typ) | |
9740 and then Tag_Typ = Root_Type (Tag_Typ)) | |
9741 then | |
9742 Append_To (Res, | |
9743 Make_Subprogram_Declaration (Loc, | |
9744 Specification => | |
9745 Make_Disp_Asynchronous_Select_Spec (Tag_Typ))); | |
9746 | |
9747 Append_To (Res, | |
9748 Make_Subprogram_Declaration (Loc, | |
9749 Specification => | |
9750 Make_Disp_Conditional_Select_Spec (Tag_Typ))); | |
9751 | |
9752 Append_To (Res, | |
9753 Make_Subprogram_Declaration (Loc, | |
9754 Specification => | |
9755 Make_Disp_Get_Prim_Op_Kind_Spec (Tag_Typ))); | |
9756 | |
9757 Append_To (Res, | |
9758 Make_Subprogram_Declaration (Loc, | |
9759 Specification => | |
9760 Make_Disp_Get_Task_Id_Spec (Tag_Typ))); | |
9761 | |
9762 Append_To (Res, | |
9763 Make_Subprogram_Declaration (Loc, | |
9764 Specification => | |
9765 Make_Disp_Requeue_Spec (Tag_Typ))); | |
9766 | |
9767 Append_To (Res, | |
9768 Make_Subprogram_Declaration (Loc, | |
9769 Specification => | |
9770 Make_Disp_Timed_Select_Spec (Tag_Typ))); | |
9771 end if; | |
9772 end if; | |
9773 | |
9774 -- All tagged types receive their own Deep_Adjust and Deep_Finalize | |
9775 -- regardless of whether they are controlled or may contain controlled | |
9776 -- components. | |
9777 | |
9778 -- Do not generate the routines if finalization is disabled | |
9779 | |
9780 if Restriction_Active (No_Finalization) then | |
9781 null; | |
9782 | |
9783 else | |
9784 if not Is_Limited_Type (Tag_Typ) then | |
9785 Append_To (Res, Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust)); | |
9786 end if; | |
9787 | |
9788 Append_To (Res, Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize)); | |
9789 end if; | |
9790 | |
9791 Predef_List := Res; | |
9792 end Make_Predefined_Primitive_Specs; | |
9793 | |
9794 ------------------------- | |
9795 -- Make_Tag_Assignment -- | |
9796 ------------------------- | |
9797 | |
9798 function Make_Tag_Assignment (N : Node_Id) return Node_Id is | |
9799 Loc : constant Source_Ptr := Sloc (N); | |
9800 Def_If : constant Entity_Id := Defining_Identifier (N); | |
9801 Expr : constant Node_Id := Expression (N); | |
9802 Typ : constant Entity_Id := Etype (Def_If); | |
9803 Full_Typ : constant Entity_Id := Underlying_Type (Typ); | |
9804 New_Ref : Node_Id; | |
9805 | |
9806 begin | |
9807 -- This expansion activity is called during analysis, but cannot | |
9808 -- be applied in ASIS mode when other expansion is disabled. | |
9809 | |
9810 if Is_Tagged_Type (Typ) | |
9811 and then not Is_Class_Wide_Type (Typ) | |
9812 and then not Is_CPP_Class (Typ) | |
9813 and then Tagged_Type_Expansion | |
9814 and then Nkind (Expr) /= N_Aggregate | |
9815 and then not ASIS_Mode | |
9816 and then (Nkind (Expr) /= N_Qualified_Expression | |
9817 or else Nkind (Expression (Expr)) /= N_Aggregate) | |
9818 then | |
9819 New_Ref := | |
9820 Make_Selected_Component (Loc, | |
9821 Prefix => New_Occurrence_Of (Def_If, Loc), | |
9822 Selector_Name => | |
9823 New_Occurrence_Of (First_Tag_Component (Full_Typ), Loc)); | |
9824 Set_Assignment_OK (New_Ref); | |
9825 | |
9826 return | |
9827 Make_Assignment_Statement (Loc, | |
9828 Name => New_Ref, | |
9829 Expression => | |
9830 Unchecked_Convert_To (RTE (RE_Tag), | |
9831 New_Occurrence_Of (Node | |
9832 (First_Elmt (Access_Disp_Table (Full_Typ))), Loc))); | |
9833 else | |
9834 return Empty; | |
9835 end if; | |
9836 end Make_Tag_Assignment; | |
9837 | |
9838 --------------------------------- | |
9839 -- Needs_Simple_Initialization -- | |
9840 --------------------------------- | |
9841 | |
9842 function Needs_Simple_Initialization | |
9843 (T : Entity_Id; | |
9844 Consider_IS : Boolean := True) return Boolean | |
9845 is | |
9846 Consider_IS_NS : constant Boolean := | |
9847 Normalize_Scalars or (Initialize_Scalars and Consider_IS); | |
9848 | |
9849 begin | |
9850 -- Never need initialization if it is suppressed | |
9851 | |
9852 if Initialization_Suppressed (T) then | |
9853 return False; | |
9854 end if; | |
9855 | |
9856 -- Check for private type, in which case test applies to the underlying | |
9857 -- type of the private type. | |
9858 | |
9859 if Is_Private_Type (T) then | |
9860 declare | |
9861 RT : constant Entity_Id := Underlying_Type (T); | |
9862 begin | |
9863 if Present (RT) then | |
9864 return Needs_Simple_Initialization (RT); | |
9865 else | |
9866 return False; | |
9867 end if; | |
9868 end; | |
9869 | |
9870 -- Scalar type with Default_Value aspect requires initialization | |
9871 | |
9872 elsif Is_Scalar_Type (T) and then Has_Default_Aspect (T) then | |
9873 return True; | |
9874 | |
9875 -- Cases needing simple initialization are access types, and, if pragma | |
9876 -- Normalize_Scalars or Initialize_Scalars is in effect, then all scalar | |
9877 -- types. | |
9878 | |
9879 elsif Is_Access_Type (T) | |
9880 or else (Consider_IS_NS and then (Is_Scalar_Type (T))) | |
9881 then | |
9882 return True; | |
9883 | |
9884 -- If Initialize/Normalize_Scalars is in effect, string objects also | |
9885 -- need initialization, unless they are created in the course of | |
9886 -- expanding an aggregate (since in the latter case they will be | |
9887 -- filled with appropriate initializing values before they are used). | |
9888 | |
9889 elsif Consider_IS_NS | |
9890 and then Is_Standard_String_Type (T) | |
9891 and then | |
9892 (not Is_Itype (T) | |
9893 or else Nkind (Associated_Node_For_Itype (T)) /= N_Aggregate) | |
9894 then | |
9895 return True; | |
9896 | |
9897 else | |
9898 return False; | |
9899 end if; | |
9900 end Needs_Simple_Initialization; | |
9901 | |
9902 ---------------------- | |
9903 -- Predef_Deep_Spec -- | |
9904 ---------------------- | |
9905 | |
9906 function Predef_Deep_Spec | |
9907 (Loc : Source_Ptr; | |
9908 Tag_Typ : Entity_Id; | |
9909 Name : TSS_Name_Type; | |
9910 For_Body : Boolean := False) return Node_Id | |
9911 is | |
9912 Formals : List_Id; | |
9913 | |
9914 begin | |
9915 -- V : in out Tag_Typ | |
9916 | |
9917 Formals := New_List ( | |
9918 Make_Parameter_Specification (Loc, | |
9919 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V), | |
9920 In_Present => True, | |
9921 Out_Present => True, | |
9922 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))); | |
9923 | |
9924 -- F : Boolean := True | |
9925 | |
9926 if Name = TSS_Deep_Adjust | |
9927 or else Name = TSS_Deep_Finalize | |
9928 then | |
9929 Append_To (Formals, | |
9930 Make_Parameter_Specification (Loc, | |
9931 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F), | |
9932 Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc), | |
9933 Expression => New_Occurrence_Of (Standard_True, Loc))); | |
9934 end if; | |
9935 | |
9936 return | |
9937 Predef_Spec_Or_Body (Loc, | |
9938 Name => Make_TSS_Name (Tag_Typ, Name), | |
9939 Tag_Typ => Tag_Typ, | |
9940 Profile => Formals, | |
9941 For_Body => For_Body); | |
9942 | |
9943 exception | |
9944 when RE_Not_Available => | |
9945 return Empty; | |
9946 end Predef_Deep_Spec; | |
9947 | |
9948 ------------------------- | |
9949 -- Predef_Spec_Or_Body -- | |
9950 ------------------------- | |
9951 | |
9952 function Predef_Spec_Or_Body | |
9953 (Loc : Source_Ptr; | |
9954 Tag_Typ : Entity_Id; | |
9955 Name : Name_Id; | |
9956 Profile : List_Id; | |
9957 Ret_Type : Entity_Id := Empty; | |
9958 For_Body : Boolean := False) return Node_Id | |
9959 is | |
9960 Id : constant Entity_Id := Make_Defining_Identifier (Loc, Name); | |
9961 Spec : Node_Id; | |
9962 | |
9963 begin | |
9964 Set_Is_Public (Id, Is_Public (Tag_Typ)); | |
9965 | |
9966 -- The internal flag is set to mark these declarations because they have | |
9967 -- specific properties. First, they are primitives even if they are not | |
9968 -- defined in the type scope (the freezing point is not necessarily in | |
9969 -- the same scope). Second, the predefined equality can be overridden by | |
9970 -- a user-defined equality, no body will be generated in this case. | |
9971 | |
9972 Set_Is_Internal (Id); | |
9973 | |
9974 if not Debug_Generated_Code then | |
9975 Set_Debug_Info_Off (Id); | |
9976 end if; | |
9977 | |
9978 if No (Ret_Type) then | |
9979 Spec := | |
9980 Make_Procedure_Specification (Loc, | |
9981 Defining_Unit_Name => Id, | |
9982 Parameter_Specifications => Profile); | |
9983 else | |
9984 Spec := | |
9985 Make_Function_Specification (Loc, | |
9986 Defining_Unit_Name => Id, | |
9987 Parameter_Specifications => Profile, | |
9988 Result_Definition => New_Occurrence_Of (Ret_Type, Loc)); | |
9989 end if; | |
9990 | |
9991 if Is_Interface (Tag_Typ) then | |
9992 return Make_Abstract_Subprogram_Declaration (Loc, Spec); | |
9993 | |
9994 -- If body case, return empty subprogram body. Note that this is ill- | |
9995 -- formed, because there is not even a null statement, and certainly not | |
9996 -- a return in the function case. The caller is expected to do surgery | |
9997 -- on the body to add the appropriate stuff. | |
9998 | |
9999 elsif For_Body then | |
10000 return Make_Subprogram_Body (Loc, Spec, Empty_List, Empty); | |
10001 | |
10002 -- For the case of an Input attribute predefined for an abstract type, | |
10003 -- generate an abstract specification. This will never be called, but we | |
10004 -- need the slot allocated in the dispatching table so that attributes | |
10005 -- typ'Class'Input and typ'Class'Output will work properly. | |
10006 | |
10007 elsif Is_TSS (Name, TSS_Stream_Input) | |
10008 and then Is_Abstract_Type (Tag_Typ) | |
10009 then | |
10010 return Make_Abstract_Subprogram_Declaration (Loc, Spec); | |
10011 | |
10012 -- Normal spec case, where we return a subprogram declaration | |
10013 | |
10014 else | |
10015 return Make_Subprogram_Declaration (Loc, Spec); | |
10016 end if; | |
10017 end Predef_Spec_Or_Body; | |
10018 | |
10019 ----------------------------- | |
10020 -- Predef_Stream_Attr_Spec -- | |
10021 ----------------------------- | |
10022 | |
10023 function Predef_Stream_Attr_Spec | |
10024 (Loc : Source_Ptr; | |
10025 Tag_Typ : Entity_Id; | |
10026 Name : TSS_Name_Type; | |
10027 For_Body : Boolean := False) return Node_Id | |
10028 is | |
10029 Ret_Type : Entity_Id; | |
10030 | |
10031 begin | |
10032 if Name = TSS_Stream_Input then | |
10033 Ret_Type := Tag_Typ; | |
10034 else | |
10035 Ret_Type := Empty; | |
10036 end if; | |
10037 | |
10038 return | |
10039 Predef_Spec_Or_Body | |
10040 (Loc, | |
10041 Name => Make_TSS_Name (Tag_Typ, Name), | |
10042 Tag_Typ => Tag_Typ, | |
10043 Profile => Build_Stream_Attr_Profile (Loc, Tag_Typ, Name), | |
10044 Ret_Type => Ret_Type, | |
10045 For_Body => For_Body); | |
10046 end Predef_Stream_Attr_Spec; | |
10047 | |
10048 --------------------------------- | |
10049 -- Predefined_Primitive_Bodies -- | |
10050 --------------------------------- | |
10051 | |
10052 function Predefined_Primitive_Bodies | |
10053 (Tag_Typ : Entity_Id; | |
10054 Renamed_Eq : Entity_Id) return List_Id | |
10055 is | |
10056 Loc : constant Source_Ptr := Sloc (Tag_Typ); | |
10057 Res : constant List_Id := New_List; | |
10058 Adj_Call : Node_Id; | |
10059 Decl : Node_Id; | |
10060 Fin_Call : Node_Id; | |
10061 Prim : Elmt_Id; | |
10062 Eq_Needed : Boolean; | |
10063 Eq_Name : Name_Id; | |
10064 Ent : Entity_Id; | |
10065 | |
10066 pragma Warnings (Off, Ent); | |
10067 | |
10068 begin | |
10069 pragma Assert (not Is_Interface (Tag_Typ)); | |
10070 | |
10071 -- See if we have a predefined "=" operator | |
10072 | |
10073 if Present (Renamed_Eq) then | |
10074 Eq_Needed := True; | |
10075 Eq_Name := Chars (Renamed_Eq); | |
10076 | |
10077 -- If the parent is an interface type then it has defined all the | |
10078 -- predefined primitives abstract and we need to check if the type | |
10079 -- has some user defined "=" function which matches the profile of | |
10080 -- the Ada predefined equality operator to avoid generating it. | |
10081 | |
10082 elsif Is_Interface (Etype (Tag_Typ)) then | |
10083 Eq_Needed := True; | |
10084 Eq_Name := Name_Op_Eq; | |
10085 | |
10086 Prim := First_Elmt (Primitive_Operations (Tag_Typ)); | |
10087 while Present (Prim) loop | |
10088 if Chars (Node (Prim)) = Name_Op_Eq | |
10089 and then not Is_Internal (Node (Prim)) | |
10090 and then Present (First_Entity (Node (Prim))) | |
10091 | |
10092 -- The predefined equality primitive must have exactly two | |
10093 -- formals whose type is this tagged type | |
10094 | |
10095 and then Present (Last_Entity (Node (Prim))) | |
10096 and then Next_Entity (First_Entity (Node (Prim))) | |
10097 = Last_Entity (Node (Prim)) | |
10098 and then Etype (First_Entity (Node (Prim))) = Tag_Typ | |
10099 and then Etype (Last_Entity (Node (Prim))) = Tag_Typ | |
10100 then | |
10101 Eq_Needed := False; | |
10102 Eq_Name := No_Name; | |
10103 exit; | |
10104 end if; | |
10105 | |
10106 Next_Elmt (Prim); | |
10107 end loop; | |
10108 | |
10109 else | |
10110 Eq_Needed := False; | |
10111 Eq_Name := No_Name; | |
10112 | |
10113 Prim := First_Elmt (Primitive_Operations (Tag_Typ)); | |
10114 while Present (Prim) loop | |
10115 if Chars (Node (Prim)) = Name_Op_Eq | |
10116 and then Is_Internal (Node (Prim)) | |
10117 then | |
10118 Eq_Needed := True; | |
10119 Eq_Name := Name_Op_Eq; | |
10120 exit; | |
10121 end if; | |
10122 | |
10123 Next_Elmt (Prim); | |
10124 end loop; | |
10125 end if; | |
10126 | |
10127 -- Body of _Size | |
10128 | |
10129 Decl := Predef_Spec_Or_Body (Loc, | |
10130 Tag_Typ => Tag_Typ, | |
10131 Name => Name_uSize, | |
10132 Profile => New_List ( | |
10133 Make_Parameter_Specification (Loc, | |
10134 Defining_Identifier => Make_Defining_Identifier (Loc, Name_X), | |
10135 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))), | |
10136 | |
10137 Ret_Type => Standard_Long_Long_Integer, | |
10138 For_Body => True); | |
10139 | |
10140 Set_Handled_Statement_Sequence (Decl, | |
10141 Make_Handled_Sequence_Of_Statements (Loc, New_List ( | |
10142 Make_Simple_Return_Statement (Loc, | |
10143 Expression => | |
10144 Make_Attribute_Reference (Loc, | |
10145 Prefix => Make_Identifier (Loc, Name_X), | |
10146 Attribute_Name => Name_Size))))); | |
10147 | |
10148 Append_To (Res, Decl); | |
10149 | |
10150 -- Bodies for Dispatching stream IO routines. We need these only for | |
10151 -- non-limited types (in the limited case there is no dispatching). | |
10152 -- We also skip them if dispatching or finalization are not available | |
10153 -- or if stream operations are prohibited by restriction No_Streams or | |
10154 -- from use of pragma/aspect No_Tagged_Streams. | |
10155 | |
10156 if Stream_Operation_OK (Tag_Typ, TSS_Stream_Read) | |
10157 and then No (TSS (Tag_Typ, TSS_Stream_Read)) | |
10158 then | |
10159 Build_Record_Read_Procedure (Loc, Tag_Typ, Decl, Ent); | |
10160 Append_To (Res, Decl); | |
10161 end if; | |
10162 | |
10163 if Stream_Operation_OK (Tag_Typ, TSS_Stream_Write) | |
10164 and then No (TSS (Tag_Typ, TSS_Stream_Write)) | |
10165 then | |
10166 Build_Record_Write_Procedure (Loc, Tag_Typ, Decl, Ent); | |
10167 Append_To (Res, Decl); | |
10168 end if; | |
10169 | |
10170 -- Skip body of _Input for the abstract case, since the corresponding | |
10171 -- spec is abstract (see Predef_Spec_Or_Body). | |
10172 | |
10173 if not Is_Abstract_Type (Tag_Typ) | |
10174 and then Stream_Operation_OK (Tag_Typ, TSS_Stream_Input) | |
10175 and then No (TSS (Tag_Typ, TSS_Stream_Input)) | |
10176 then | |
10177 Build_Record_Or_Elementary_Input_Function | |
10178 (Loc, Tag_Typ, Decl, Ent); | |
10179 Append_To (Res, Decl); | |
10180 end if; | |
10181 | |
10182 if Stream_Operation_OK (Tag_Typ, TSS_Stream_Output) | |
10183 and then No (TSS (Tag_Typ, TSS_Stream_Output)) | |
10184 then | |
10185 Build_Record_Or_Elementary_Output_Procedure (Loc, Tag_Typ, Decl, Ent); | |
10186 Append_To (Res, Decl); | |
10187 end if; | |
10188 | |
10189 -- Ada 2005: Generate bodies for the following primitive operations for | |
10190 -- limited interfaces and synchronized types that implement a limited | |
10191 -- interface. | |
10192 | |
10193 -- disp_asynchronous_select | |
10194 -- disp_conditional_select | |
10195 -- disp_get_prim_op_kind | |
10196 -- disp_get_task_id | |
10197 -- disp_timed_select | |
10198 | |
10199 -- The interface versions will have null bodies | |
10200 | |
10201 -- Disable the generation of these bodies if No_Dispatching_Calls, | |
10202 -- Ravenscar or ZFP is active. | |
10203 | |
10204 -- In VM targets we define these primitives in all root tagged types | |
10205 -- that are not interface types. Done because in VM targets we don't | |
10206 -- have secondary dispatch tables and any derivation of Tag_Typ may | |
10207 -- cover limited interfaces (which always have these primitives since | |
10208 -- they may be ancestors of synchronized interface types). | |
10209 | |
10210 if Ada_Version >= Ada_2005 | |
10211 and then not Is_Interface (Tag_Typ) | |
10212 and then | |
10213 ((Is_Interface (Etype (Tag_Typ)) | |
10214 and then Is_Limited_Record (Etype (Tag_Typ))) | |
10215 or else | |
10216 (Is_Concurrent_Record_Type (Tag_Typ) | |
10217 and then Has_Interfaces (Tag_Typ)) | |
10218 or else | |
10219 (not Tagged_Type_Expansion | |
10220 and then Tag_Typ = Root_Type (Tag_Typ))) | |
10221 and then not Restriction_Active (No_Dispatching_Calls) | |
10222 and then not Restriction_Active (No_Select_Statements) | |
10223 and then RTE_Available (RE_Select_Specific_Data) | |
10224 then | |
10225 Append_To (Res, Make_Disp_Asynchronous_Select_Body (Tag_Typ)); | |
10226 Append_To (Res, Make_Disp_Conditional_Select_Body (Tag_Typ)); | |
10227 Append_To (Res, Make_Disp_Get_Prim_Op_Kind_Body (Tag_Typ)); | |
10228 Append_To (Res, Make_Disp_Get_Task_Id_Body (Tag_Typ)); | |
10229 Append_To (Res, Make_Disp_Requeue_Body (Tag_Typ)); | |
10230 Append_To (Res, Make_Disp_Timed_Select_Body (Tag_Typ)); | |
10231 end if; | |
10232 | |
10233 if not Is_Limited_Type (Tag_Typ) and then not Is_Interface (Tag_Typ) then | |
10234 | |
10235 -- Body for equality | |
10236 | |
10237 if Eq_Needed then | |
10238 Decl := Make_Eq_Body (Tag_Typ, Eq_Name); | |
10239 Append_To (Res, Decl); | |
10240 end if; | |
10241 | |
10242 -- Body for inequality (if required) | |
10243 | |
10244 Decl := Make_Neq_Body (Tag_Typ); | |
10245 | |
10246 if Present (Decl) then | |
10247 Append_To (Res, Decl); | |
10248 end if; | |
10249 | |
10250 -- Body for dispatching assignment | |
10251 | |
10252 Decl := | |
10253 Predef_Spec_Or_Body (Loc, | |
10254 Tag_Typ => Tag_Typ, | |
10255 Name => Name_uAssign, | |
10256 Profile => New_List ( | |
10257 Make_Parameter_Specification (Loc, | |
10258 Defining_Identifier => Make_Defining_Identifier (Loc, Name_X), | |
10259 Out_Present => True, | |
10260 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc)), | |
10261 | |
10262 Make_Parameter_Specification (Loc, | |
10263 Defining_Identifier => Make_Defining_Identifier (Loc, Name_Y), | |
10264 Parameter_Type => New_Occurrence_Of (Tag_Typ, Loc))), | |
10265 For_Body => True); | |
10266 | |
10267 Set_Handled_Statement_Sequence (Decl, | |
10268 Make_Handled_Sequence_Of_Statements (Loc, New_List ( | |
10269 Make_Assignment_Statement (Loc, | |
10270 Name => Make_Identifier (Loc, Name_X), | |
10271 Expression => Make_Identifier (Loc, Name_Y))))); | |
10272 | |
10273 Append_To (Res, Decl); | |
10274 end if; | |
10275 | |
10276 -- Generate empty bodies of routines Deep_Adjust and Deep_Finalize for | |
10277 -- tagged types which do not contain controlled components. | |
10278 | |
10279 -- Do not generate the routines if finalization is disabled | |
10280 | |
10281 if Restriction_Active (No_Finalization) then | |
10282 null; | |
10283 | |
10284 elsif not Has_Controlled_Component (Tag_Typ) then | |
10285 if not Is_Limited_Type (Tag_Typ) then | |
10286 Adj_Call := Empty; | |
10287 Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust, True); | |
10288 | |
10289 if Is_Controlled (Tag_Typ) then | |
10290 Adj_Call := | |
10291 Make_Adjust_Call ( | |
10292 Obj_Ref => Make_Identifier (Loc, Name_V), | |
10293 Typ => Tag_Typ); | |
10294 end if; | |
10295 | |
10296 if No (Adj_Call) then | |
10297 Adj_Call := Make_Null_Statement (Loc); | |
10298 end if; | |
10299 | |
10300 Set_Handled_Statement_Sequence (Decl, | |
10301 Make_Handled_Sequence_Of_Statements (Loc, | |
10302 Statements => New_List (Adj_Call))); | |
10303 | |
10304 Append_To (Res, Decl); | |
10305 end if; | |
10306 | |
10307 Fin_Call := Empty; | |
10308 Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize, True); | |
10309 | |
10310 if Is_Controlled (Tag_Typ) then | |
10311 Fin_Call := | |
10312 Make_Final_Call | |
10313 (Obj_Ref => Make_Identifier (Loc, Name_V), | |
10314 Typ => Tag_Typ); | |
10315 end if; | |
10316 | |
10317 if No (Fin_Call) then | |
10318 Fin_Call := Make_Null_Statement (Loc); | |
10319 end if; | |
10320 | |
10321 Set_Handled_Statement_Sequence (Decl, | |
10322 Make_Handled_Sequence_Of_Statements (Loc, | |
10323 Statements => New_List (Fin_Call))); | |
10324 | |
10325 Append_To (Res, Decl); | |
10326 end if; | |
10327 | |
10328 return Res; | |
10329 end Predefined_Primitive_Bodies; | |
10330 | |
10331 --------------------------------- | |
10332 -- Predefined_Primitive_Freeze -- | |
10333 --------------------------------- | |
10334 | |
10335 function Predefined_Primitive_Freeze | |
10336 (Tag_Typ : Entity_Id) return List_Id | |
10337 is | |
10338 Res : constant List_Id := New_List; | |
10339 Prim : Elmt_Id; | |
10340 Frnodes : List_Id; | |
10341 | |
10342 begin | |
10343 Prim := First_Elmt (Primitive_Operations (Tag_Typ)); | |
10344 while Present (Prim) loop | |
10345 if Is_Predefined_Dispatching_Operation (Node (Prim)) then | |
10346 Frnodes := Freeze_Entity (Node (Prim), Tag_Typ); | |
10347 | |
10348 if Present (Frnodes) then | |
10349 Append_List_To (Res, Frnodes); | |
10350 end if; | |
10351 end if; | |
10352 | |
10353 Next_Elmt (Prim); | |
10354 end loop; | |
10355 | |
10356 return Res; | |
10357 end Predefined_Primitive_Freeze; | |
10358 | |
10359 ------------------------- | |
10360 -- Stream_Operation_OK -- | |
10361 ------------------------- | |
10362 | |
10363 function Stream_Operation_OK | |
10364 (Typ : Entity_Id; | |
10365 Operation : TSS_Name_Type) return Boolean | |
10366 is | |
10367 Has_Predefined_Or_Specified_Stream_Attribute : Boolean := False; | |
10368 | |
10369 begin | |
10370 -- Special case of a limited type extension: a default implementation | |
10371 -- of the stream attributes Read or Write exists if that attribute | |
10372 -- has been specified or is available for an ancestor type; a default | |
10373 -- implementation of the attribute Output (resp. Input) exists if the | |
10374 -- attribute has been specified or Write (resp. Read) is available for | |
10375 -- an ancestor type. The last condition only applies under Ada 2005. | |
10376 | |
10377 if Is_Limited_Type (Typ) and then Is_Tagged_Type (Typ) then | |
10378 if Operation = TSS_Stream_Read then | |
10379 Has_Predefined_Or_Specified_Stream_Attribute := | |
10380 Has_Specified_Stream_Read (Typ); | |
10381 | |
10382 elsif Operation = TSS_Stream_Write then | |
10383 Has_Predefined_Or_Specified_Stream_Attribute := | |
10384 Has_Specified_Stream_Write (Typ); | |
10385 | |
10386 elsif Operation = TSS_Stream_Input then | |
10387 Has_Predefined_Or_Specified_Stream_Attribute := | |
10388 Has_Specified_Stream_Input (Typ) | |
10389 or else | |
10390 (Ada_Version >= Ada_2005 | |
10391 and then Stream_Operation_OK (Typ, TSS_Stream_Read)); | |
10392 | |
10393 elsif Operation = TSS_Stream_Output then | |
10394 Has_Predefined_Or_Specified_Stream_Attribute := | |
10395 Has_Specified_Stream_Output (Typ) | |
10396 or else | |
10397 (Ada_Version >= Ada_2005 | |
10398 and then Stream_Operation_OK (Typ, TSS_Stream_Write)); | |
10399 end if; | |
10400 | |
10401 -- Case of inherited TSS_Stream_Read or TSS_Stream_Write | |
10402 | |
10403 if not Has_Predefined_Or_Specified_Stream_Attribute | |
10404 and then Is_Derived_Type (Typ) | |
10405 and then (Operation = TSS_Stream_Read | |
10406 or else Operation = TSS_Stream_Write) | |
10407 then | |
10408 Has_Predefined_Or_Specified_Stream_Attribute := | |
10409 Present | |
10410 (Find_Inherited_TSS (Base_Type (Etype (Typ)), Operation)); | |
10411 end if; | |
10412 end if; | |
10413 | |
10414 -- If the type is not limited, or else is limited but the attribute is | |
10415 -- explicitly specified or is predefined for the type, then return True, | |
10416 -- unless other conditions prevail, such as restrictions prohibiting | |
10417 -- streams or dispatching operations. We also return True for limited | |
10418 -- interfaces, because they may be extended by nonlimited types and | |
10419 -- permit inheritance in this case (addresses cases where an abstract | |
10420 -- extension doesn't get 'Input declared, as per comments below, but | |
10421 -- 'Class'Input must still be allowed). Note that attempts to apply | |
10422 -- stream attributes to a limited interface or its class-wide type | |
10423 -- (or limited extensions thereof) will still get properly rejected | |
10424 -- by Check_Stream_Attribute. | |
10425 | |
10426 -- We exclude the Input operation from being a predefined subprogram in | |
10427 -- the case where the associated type is an abstract extension, because | |
10428 -- the attribute is not callable in that case, per 13.13.2(49/2). Also, | |
10429 -- we don't want an abstract version created because types derived from | |
10430 -- the abstract type may not even have Input available (for example if | |
10431 -- derived from a private view of the abstract type that doesn't have | |
10432 -- a visible Input). | |
10433 | |
10434 -- Do not generate stream routines for type Finalization_Master because | |
10435 -- a master may never appear in types and therefore cannot be read or | |
10436 -- written. | |
10437 | |
10438 return | |
10439 (not Is_Limited_Type (Typ) | |
10440 or else Is_Interface (Typ) | |
10441 or else Has_Predefined_Or_Specified_Stream_Attribute) | |
10442 and then | |
10443 (Operation /= TSS_Stream_Input | |
10444 or else not Is_Abstract_Type (Typ) | |
10445 or else not Is_Derived_Type (Typ)) | |
10446 and then not Has_Unknown_Discriminants (Typ) | |
10447 and then not | |
10448 (Is_Interface (Typ) | |
10449 and then | |
10450 (Is_Task_Interface (Typ) | |
10451 or else Is_Protected_Interface (Typ) | |
10452 or else Is_Synchronized_Interface (Typ))) | |
10453 and then not Restriction_Active (No_Streams) | |
10454 and then not Restriction_Active (No_Dispatch) | |
10455 and then No (No_Tagged_Streams_Pragma (Typ)) | |
10456 and then not No_Run_Time_Mode | |
10457 and then RTE_Available (RE_Tag) | |
10458 and then No (Type_Without_Stream_Operation (Typ)) | |
10459 and then RTE_Available (RE_Root_Stream_Type) | |
10460 and then not Is_RTE (Typ, RE_Finalization_Master); | |
10461 end Stream_Operation_OK; | |
10462 | |
10463 end Exp_Ch3; |