annotate gcc/ada/exp_ch13.adb @ 143:76e1cf5455ef

add cbc_gc test
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 19:24:05 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT COMPILER COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- E X P _ C H 1 3 --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
kono
parents:
diff changeset
17 -- for more details. You should have received a copy of the GNU General --
kono
parents:
diff changeset
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
kono
parents:
diff changeset
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
kono
parents:
diff changeset
20 -- --
kono
parents:
diff changeset
21 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
23 -- --
kono
parents:
diff changeset
24 ------------------------------------------------------------------------------
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 with Atree; use Atree;
kono
parents:
diff changeset
27 with Checks; use Checks;
kono
parents:
diff changeset
28 with Einfo; use Einfo;
kono
parents:
diff changeset
29 with Exp_Ch3; use Exp_Ch3;
kono
parents:
diff changeset
30 with Exp_Ch6;
kono
parents:
diff changeset
31 with Exp_Imgv; use Exp_Imgv;
kono
parents:
diff changeset
32 with Exp_Tss; use Exp_Tss;
kono
parents:
diff changeset
33 with Exp_Util; use Exp_Util;
kono
parents:
diff changeset
34 with Freeze; use Freeze;
kono
parents:
diff changeset
35 with Namet; use Namet;
kono
parents:
diff changeset
36 with Nlists; use Nlists;
kono
parents:
diff changeset
37 with Nmake; use Nmake;
kono
parents:
diff changeset
38 with Opt; use Opt;
kono
parents:
diff changeset
39 with Restrict; use Restrict;
kono
parents:
diff changeset
40 with Rident; use Rident;
kono
parents:
diff changeset
41 with Rtsfind; use Rtsfind;
kono
parents:
diff changeset
42 with Sem; use Sem;
kono
parents:
diff changeset
43 with Sem_Aux; use Sem_Aux;
kono
parents:
diff changeset
44 with Sem_Ch7; use Sem_Ch7;
kono
parents:
diff changeset
45 with Sem_Ch8; use Sem_Ch8;
kono
parents:
diff changeset
46 with Sem_Eval; use Sem_Eval;
kono
parents:
diff changeset
47 with Sem_Util; use Sem_Util;
kono
parents:
diff changeset
48 with Sinfo; use Sinfo;
kono
parents:
diff changeset
49 with Snames; use Snames;
kono
parents:
diff changeset
50 with Tbuild; use Tbuild;
kono
parents:
diff changeset
51 with Uintp; use Uintp;
kono
parents:
diff changeset
52 with Validsw; use Validsw;
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 package body Exp_Ch13 is
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 ------------------------------------------
kono
parents:
diff changeset
57 -- Expand_N_Attribute_Definition_Clause --
kono
parents:
diff changeset
58 ------------------------------------------
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 -- Expansion action depends on attribute involved
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 procedure Expand_N_Attribute_Definition_Clause (N : Node_Id) is
kono
parents:
diff changeset
63 Loc : constant Source_Ptr := Sloc (N);
kono
parents:
diff changeset
64 Exp : constant Node_Id := Expression (N);
kono
parents:
diff changeset
65 Ent : Entity_Id;
kono
parents:
diff changeset
66 V : Node_Id;
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 begin
kono
parents:
diff changeset
69 Ent := Entity (Name (N));
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 if Is_Type (Ent) then
kono
parents:
diff changeset
72 Ent := Underlying_Type (Ent);
kono
parents:
diff changeset
73 end if;
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 case Get_Attribute_Id (Chars (N)) is
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 -------------
kono
parents:
diff changeset
78 -- Address --
kono
parents:
diff changeset
79 -------------
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 when Attribute_Address =>
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 -- If there is an initialization which did not come from the
kono
parents:
diff changeset
84 -- source program, then it is an artifact of our expansion, and we
kono
parents:
diff changeset
85 -- suppress it. The case we are most concerned about here is the
kono
parents:
diff changeset
86 -- initialization of a packed array to all false, which seems
kono
parents:
diff changeset
87 -- inappropriate for variable to which an address clause is
kono
parents:
diff changeset
88 -- applied. The expression may itself have been rewritten if the
kono
parents:
diff changeset
89 -- type is packed array, so we need to examine whether the
kono
parents:
diff changeset
90 -- original node is in the source. An exception though is the case
kono
parents:
diff changeset
91 -- of an access variable which is default initialized to null, and
kono
parents:
diff changeset
92 -- such initialization is retained.
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 -- Furthermore, if the initialization is the equivalent aggregate
kono
parents:
diff changeset
95 -- of the type initialization procedure, it replaces an implicit
kono
parents:
diff changeset
96 -- call to the init proc, and must be respected. Note that for
kono
parents:
diff changeset
97 -- packed types we do not build equivalent aggregates.
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 -- Also, if Init_Or_Norm_Scalars applies, then we need to retain
kono
parents:
diff changeset
100 -- any default initialization for objects of scalar types and
kono
parents:
diff changeset
101 -- types with scalar components. Normally a composite type will
kono
parents:
diff changeset
102 -- have an init_proc in the presence of Init_Or_Norm_Scalars,
kono
parents:
diff changeset
103 -- so when that flag is set we have just have to do a test for
kono
parents:
diff changeset
104 -- scalar and string types (the predefined string types such as
kono
parents:
diff changeset
105 -- String and Wide_String don't have an init_proc).
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 declare
kono
parents:
diff changeset
108 Decl : constant Node_Id := Declaration_Node (Ent);
kono
parents:
diff changeset
109 Typ : constant Entity_Id := Etype (Ent);
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 begin
kono
parents:
diff changeset
112 if Nkind (Decl) = N_Object_Declaration
kono
parents:
diff changeset
113 and then Present (Expression (Decl))
kono
parents:
diff changeset
114 and then Nkind (Expression (Decl)) /= N_Null
kono
parents:
diff changeset
115 and then
kono
parents:
diff changeset
116 not Comes_From_Source (Original_Node (Expression (Decl)))
kono
parents:
diff changeset
117 then
kono
parents:
diff changeset
118 if Present (Base_Init_Proc (Typ))
kono
parents:
diff changeset
119 and then
kono
parents:
diff changeset
120 Present (Static_Initialization (Base_Init_Proc (Typ)))
kono
parents:
diff changeset
121 then
kono
parents:
diff changeset
122 null;
kono
parents:
diff changeset
123
kono
parents:
diff changeset
124 elsif Init_Or_Norm_Scalars
kono
parents:
diff changeset
125 and then (Is_Scalar_Type (Typ)
kono
parents:
diff changeset
126 or else Is_String_Type (Typ))
kono
parents:
diff changeset
127 then
kono
parents:
diff changeset
128 null;
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 else
kono
parents:
diff changeset
131 Set_Expression (Decl, Empty);
kono
parents:
diff changeset
132 end if;
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 -- An object declaration to which an address clause applies
kono
parents:
diff changeset
135 -- has a delayed freeze, but the address expression itself
kono
parents:
diff changeset
136 -- must be elaborated at the point it appears. If the object
kono
parents:
diff changeset
137 -- is controlled, additional checks apply elsewhere.
kono
parents:
diff changeset
138 -- If the attribute comes from an aspect specification it
kono
parents:
diff changeset
139 -- is being elaborated at the freeze point and side effects
kono
parents:
diff changeset
140 -- need not be removed (and shouldn't, if the expression
kono
parents:
diff changeset
141 -- depends on other entities that have delayed freeze).
kono
parents:
diff changeset
142 -- This is another consequence of the delayed analysis of
kono
parents:
diff changeset
143 -- aspects, and a real semantic difference.
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 elsif Nkind (Decl) = N_Object_Declaration
kono
parents:
diff changeset
146 and then not Needs_Constant_Address (Decl, Typ)
kono
parents:
diff changeset
147 and then not From_Aspect_Specification (N)
kono
parents:
diff changeset
148 then
kono
parents:
diff changeset
149 Remove_Side_Effects (Exp);
kono
parents:
diff changeset
150 end if;
kono
parents:
diff changeset
151 end;
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 ---------------
kono
parents:
diff changeset
154 -- Alignment --
kono
parents:
diff changeset
155 ---------------
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 when Attribute_Alignment =>
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 -- As required by Gigi, we guarantee that the operand is an
kono
parents:
diff changeset
160 -- integer literal (this simplifies things in Gigi).
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 if Nkind (Exp) /= N_Integer_Literal then
kono
parents:
diff changeset
163 Rewrite (Exp, Make_Integer_Literal (Loc, Expr_Value (Exp)));
kono
parents:
diff changeset
164 end if;
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166 -- A complex case arises if the alignment clause applies to an
kono
parents:
diff changeset
167 -- unconstrained object initialized with a function call. The
kono
parents:
diff changeset
168 -- result of the call is placed on the secondary stack, and the
kono
parents:
diff changeset
169 -- declaration is rewritten as a renaming of a dereference, which
kono
parents:
diff changeset
170 -- fails expansion. We must introduce a temporary and assign its
kono
parents:
diff changeset
171 -- value to the existing entity.
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 if Nkind (Parent (Ent)) = N_Object_Renaming_Declaration
kono
parents:
diff changeset
174 and then not Is_Entity_Name (Renamed_Object (Ent))
kono
parents:
diff changeset
175 then
kono
parents:
diff changeset
176 declare
kono
parents:
diff changeset
177 Decl : constant Node_Id := Parent (Ent);
kono
parents:
diff changeset
178 Loc : constant Source_Ptr := Sloc (N);
kono
parents:
diff changeset
179 Temp : constant Entity_Id := Make_Temporary (Loc, 'T');
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 New_Decl : Node_Id;
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 begin
kono
parents:
diff changeset
184 -- Replace entity with temporary and reanalyze
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 Set_Defining_Identifier (Decl, Temp);
kono
parents:
diff changeset
187 Set_Analyzed (Decl, False);
kono
parents:
diff changeset
188 Analyze (Decl);
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 -- Introduce new declaration for entity but do not reanalyze
kono
parents:
diff changeset
191 -- because entity is already in scope. Type and expression
kono
parents:
diff changeset
192 -- are already resolved.
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 New_Decl :=
kono
parents:
diff changeset
195 Make_Object_Declaration (Loc,
kono
parents:
diff changeset
196 Defining_Identifier => Ent,
kono
parents:
diff changeset
197 Object_Definition =>
kono
parents:
diff changeset
198 New_Occurrence_Of (Etype (Ent), Loc),
kono
parents:
diff changeset
199 Expression => New_Occurrence_Of (Temp, Loc));
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 Set_Renamed_Object (Ent, Empty);
kono
parents:
diff changeset
202 Insert_After (Decl, New_Decl);
kono
parents:
diff changeset
203 Set_Analyzed (Decl);
kono
parents:
diff changeset
204 end;
kono
parents:
diff changeset
205 end if;
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 ------------------
kono
parents:
diff changeset
208 -- Storage_Size --
kono
parents:
diff changeset
209 ------------------
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 when Attribute_Storage_Size =>
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 -- If the type is a task type, then assign the value of the
kono
parents:
diff changeset
214 -- storage size to the Size variable associated with the task.
kono
parents:
diff changeset
215 -- Insert the assignment right after the declaration of the Size
kono
parents:
diff changeset
216 -- variable.
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 -- Generate:
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 -- task_typeZ := expression
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 if Ekind (Ent) = E_Task_Type then
kono
parents:
diff changeset
223 declare
kono
parents:
diff changeset
224 Assign : Node_Id;
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 begin
kono
parents:
diff changeset
227 Assign :=
kono
parents:
diff changeset
228 Make_Assignment_Statement (Loc,
kono
parents:
diff changeset
229 Name =>
kono
parents:
diff changeset
230 New_Occurrence_Of (Storage_Size_Variable (Ent), Loc),
kono
parents:
diff changeset
231 Expression =>
kono
parents:
diff changeset
232 Convert_To (RTE (RE_Size_Type), Expression (N)));
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 -- If the clause is not generated by an aspect, insert
kono
parents:
diff changeset
235 -- the assignment here. Freezing rules ensure that this
kono
parents:
diff changeset
236 -- is safe, or clause will have been rejected already.
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 if Is_List_Member (N) then
kono
parents:
diff changeset
239 Insert_After (N, Assign);
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 -- Otherwise, insert assignment after task declaration.
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 else
kono
parents:
diff changeset
244 Insert_After
kono
parents:
diff changeset
245 (Parent (Storage_Size_Variable (Entity (N))), Assign);
kono
parents:
diff changeset
246 end if;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 Analyze (Assign);
kono
parents:
diff changeset
249 end;
kono
parents:
diff changeset
250
kono
parents:
diff changeset
251 -- For Storage_Size for an access type, create a variable to hold
kono
parents:
diff changeset
252 -- the value of the specified size with name typeV and expand an
kono
parents:
diff changeset
253 -- assignment statement to initialize this value.
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 elsif Is_Access_Type (Ent) then
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 -- We don't need the variable for a storage size of zero
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 if not No_Pool_Assigned (Ent) then
kono
parents:
diff changeset
260 V :=
kono
parents:
diff changeset
261 Make_Defining_Identifier (Loc,
kono
parents:
diff changeset
262 Chars => New_External_Name (Chars (Ent), 'V'));
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 -- Insert the declaration of the object
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 Insert_Action (N,
kono
parents:
diff changeset
267 Make_Object_Declaration (Loc,
kono
parents:
diff changeset
268 Defining_Identifier => V,
kono
parents:
diff changeset
269 Object_Definition =>
kono
parents:
diff changeset
270 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc),
kono
parents:
diff changeset
271 Expression =>
kono
parents:
diff changeset
272 Convert_To (RTE (RE_Storage_Offset), Expression (N))));
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 Set_Storage_Size_Variable (Ent, Entity_Id (V));
kono
parents:
diff changeset
275 end if;
kono
parents:
diff changeset
276 end if;
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 -- Other attributes require no expansion
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 when others =>
kono
parents:
diff changeset
281 null;
kono
parents:
diff changeset
282 end case;
kono
parents:
diff changeset
283 end Expand_N_Attribute_Definition_Clause;
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 -----------------------------
kono
parents:
diff changeset
286 -- Expand_N_Free_Statement --
kono
parents:
diff changeset
287 -----------------------------
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 procedure Expand_N_Free_Statement (N : Node_Id) is
kono
parents:
diff changeset
290 Expr : constant Node_Id := Expression (N);
kono
parents:
diff changeset
291 Typ : Entity_Id;
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 begin
kono
parents:
diff changeset
294 -- Certain run-time configurations and targets do not provide support
kono
parents:
diff changeset
295 -- for controlled types.
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 if Restriction_Active (No_Finalization) then
kono
parents:
diff changeset
298 return;
kono
parents:
diff changeset
299 end if;
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 -- Use the base type to perform the check for finalization master
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 Typ := Etype (Expr);
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 if Ekind (Typ) = E_Access_Subtype then
kono
parents:
diff changeset
306 Typ := Etype (Typ);
kono
parents:
diff changeset
307 end if;
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 -- Handle private access types
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 if Is_Private_Type (Typ)
kono
parents:
diff changeset
312 and then Present (Full_View (Typ))
kono
parents:
diff changeset
313 then
kono
parents:
diff changeset
314 Typ := Full_View (Typ);
kono
parents:
diff changeset
315 end if;
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 -- Do not create a custom Deallocate when freeing an object with
kono
parents:
diff changeset
318 -- suppressed finalization. In such cases the object is never attached
kono
parents:
diff changeset
319 -- to a master, so it does not need to be detached. Use a regular free
kono
parents:
diff changeset
320 -- statement instead.
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 if No (Finalization_Master (Typ)) then
kono
parents:
diff changeset
323 return;
kono
parents:
diff changeset
324 end if;
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 -- Use a temporary to store the result of a complex expression. Perform
kono
parents:
diff changeset
327 -- the following transformation:
kono
parents:
diff changeset
328 --
kono
parents:
diff changeset
329 -- Free (Complex_Expression);
kono
parents:
diff changeset
330 --
kono
parents:
diff changeset
331 -- Temp : constant Type_Of_Expression := Complex_Expression;
kono
parents:
diff changeset
332 -- Free (Temp);
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 if Nkind (Expr) /= N_Identifier then
kono
parents:
diff changeset
335 declare
kono
parents:
diff changeset
336 Expr_Typ : constant Entity_Id := Etype (Expr);
kono
parents:
diff changeset
337 Loc : constant Source_Ptr := Sloc (N);
kono
parents:
diff changeset
338 New_Expr : Node_Id;
kono
parents:
diff changeset
339 Temp_Id : Entity_Id;
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 begin
kono
parents:
diff changeset
342 Temp_Id := Make_Temporary (Loc, 'T');
kono
parents:
diff changeset
343 Insert_Action (N,
kono
parents:
diff changeset
344 Make_Object_Declaration (Loc,
kono
parents:
diff changeset
345 Defining_Identifier => Temp_Id,
kono
parents:
diff changeset
346 Object_Definition => New_Occurrence_Of (Expr_Typ, Loc),
kono
parents:
diff changeset
347 Expression => Relocate_Node (Expr)));
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 New_Expr := New_Occurrence_Of (Temp_Id, Loc);
kono
parents:
diff changeset
350 Set_Etype (New_Expr, Expr_Typ);
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 Set_Expression (N, New_Expr);
kono
parents:
diff changeset
353 end;
kono
parents:
diff changeset
354 end if;
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 -- Create a custom Deallocate for a controlled object. This routine
kono
parents:
diff changeset
357 -- ensures that the hidden list header will be deallocated along with
kono
parents:
diff changeset
358 -- the actual object.
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 Build_Allocate_Deallocate_Proc (N, Is_Allocate => False);
kono
parents:
diff changeset
361 end Expand_N_Free_Statement;
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 ----------------------------
kono
parents:
diff changeset
364 -- Expand_N_Freeze_Entity --
kono
parents:
diff changeset
365 ----------------------------
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 procedure Expand_N_Freeze_Entity (N : Node_Id) is
kono
parents:
diff changeset
368 E : constant Entity_Id := Entity (N);
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 Decl : Node_Id;
kono
parents:
diff changeset
371 Delete : Boolean := False;
kono
parents:
diff changeset
372 E_Scope : Entity_Id;
kono
parents:
diff changeset
373 In_Other_Scope : Boolean;
kono
parents:
diff changeset
374 In_Outer_Scope : Boolean;
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 begin
kono
parents:
diff changeset
377 -- If there are delayed aspect specifications, we insert them just
kono
parents:
diff changeset
378 -- before the freeze node. They are already analyzed so we don't need
kono
parents:
diff changeset
379 -- to reanalyze them (they were analyzed before the type was frozen),
kono
parents:
diff changeset
380 -- but we want them in the tree for the back end, and so that the
kono
parents:
diff changeset
381 -- listing from sprint is clearer on where these occur logically.
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 if Has_Delayed_Aspects (E) then
kono
parents:
diff changeset
384 declare
kono
parents:
diff changeset
385 Aitem : Node_Id;
kono
parents:
diff changeset
386 Ritem : Node_Id;
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 begin
kono
parents:
diff changeset
389 -- Look for aspect specs for this entity
kono
parents:
diff changeset
390
kono
parents:
diff changeset
391 Ritem := First_Rep_Item (E);
kono
parents:
diff changeset
392 while Present (Ritem) loop
kono
parents:
diff changeset
393 if Nkind (Ritem) = N_Aspect_Specification
kono
parents:
diff changeset
394 and then Entity (Ritem) = E
kono
parents:
diff changeset
395 then
kono
parents:
diff changeset
396 Aitem := Aspect_Rep_Item (Ritem);
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 -- Skip this for aspects (e.g. Current_Value) for which
kono
parents:
diff changeset
399 -- there is no corresponding pragma or attribute.
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 if Present (Aitem)
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 -- Also skip if we have a null statement rather than a
kono
parents:
diff changeset
404 -- delayed aspect (this happens when we are ignoring rep
kono
parents:
diff changeset
405 -- items from use of the -gnatI switch).
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 and then Nkind (Aitem) /= N_Null_Statement
kono
parents:
diff changeset
408 then
kono
parents:
diff changeset
409 pragma Assert (Is_Delayed_Aspect (Aitem));
kono
parents:
diff changeset
410 Insert_Before (N, Aitem);
kono
parents:
diff changeset
411 end if;
kono
parents:
diff changeset
412 end if;
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 Next_Rep_Item (Ritem);
kono
parents:
diff changeset
415 end loop;
kono
parents:
diff changeset
416 end;
kono
parents:
diff changeset
417 end if;
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 -- Processing for objects
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 if Is_Object (E) then
kono
parents:
diff changeset
422 if Present (Address_Clause (E)) then
kono
parents:
diff changeset
423 Apply_Address_Clause_Check (E, N);
kono
parents:
diff changeset
424 end if;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 -- Analyze actions in freeze node, if any
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 if Present (Actions (N)) then
kono
parents:
diff changeset
429 declare
kono
parents:
diff changeset
430 Act : Node_Id;
kono
parents:
diff changeset
431 begin
kono
parents:
diff changeset
432 Act := First (Actions (N));
kono
parents:
diff changeset
433 while Present (Act) loop
kono
parents:
diff changeset
434 Analyze (Act);
kono
parents:
diff changeset
435 Next (Act);
kono
parents:
diff changeset
436 end loop;
kono
parents:
diff changeset
437 end;
kono
parents:
diff changeset
438 end if;
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 -- If initialization statements have been captured in a compound
kono
parents:
diff changeset
441 -- statement, insert them back into the tree now.
kono
parents:
diff changeset
442
kono
parents:
diff changeset
443 Explode_Initialization_Compound_Statement (E);
kono
parents:
diff changeset
444 return;
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446 -- Only other items requiring any front end action are types and
kono
parents:
diff changeset
447 -- subprograms.
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 elsif not Is_Type (E) and then not Is_Subprogram (E) then
kono
parents:
diff changeset
450 return;
kono
parents:
diff changeset
451 end if;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 -- Here E is a type or a subprogram
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 E_Scope := Scope (E);
kono
parents:
diff changeset
456
kono
parents:
diff changeset
457 -- This is an error protection against previous errors
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 if No (E_Scope) then
kono
parents:
diff changeset
460 Check_Error_Detected;
kono
parents:
diff changeset
461 return;
kono
parents:
diff changeset
462 end if;
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 -- The entity may be a subtype declared for a constrained record
kono
parents:
diff changeset
465 -- component, in which case the relevant scope is the scope of
kono
parents:
diff changeset
466 -- the record. This happens for class-wide subtypes created for
kono
parents:
diff changeset
467 -- a constrained type extension with inherited discriminants.
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 if Is_Type (E_Scope)
kono
parents:
diff changeset
470 and then Ekind (E_Scope) not in Concurrent_Kind
kono
parents:
diff changeset
471 then
kono
parents:
diff changeset
472 E_Scope := Scope (E_Scope);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
473
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
474 -- The entity may be a subtype declared for an iterator
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
475
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
476 elsif Ekind (E_Scope) = E_Loop then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
477 E_Scope := Scope (E_Scope);
111
kono
parents:
diff changeset
478 end if;
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 -- Remember that we are processing a freezing entity and its freezing
kono
parents:
diff changeset
481 -- nodes. This flag (non-zero = set) is used to avoid the need of
kono
parents:
diff changeset
482 -- climbing through the tree while processing the freezing actions (ie.
kono
parents:
diff changeset
483 -- to avoid generating spurious warnings or to avoid killing constant
kono
parents:
diff changeset
484 -- indications while processing the code associated with freezing
kono
parents:
diff changeset
485 -- actions). We use a counter to deal with nesting.
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 Inside_Freezing_Actions := Inside_Freezing_Actions + 1;
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 -- If we are freezing entities defined in protected types, they belong
kono
parents:
diff changeset
490 -- in the enclosing scope, given that the original type has been
kono
parents:
diff changeset
491 -- expanded away. The same is true for entities in task types, in
kono
parents:
diff changeset
492 -- particular the parameter records of entries (Entities in bodies are
kono
parents:
diff changeset
493 -- all frozen within the body). If we are in the task body, this is a
kono
parents:
diff changeset
494 -- proper scope. If we are within a subprogram body, the proper scope
kono
parents:
diff changeset
495 -- is the corresponding spec. This may happen for itypes generated in
kono
parents:
diff changeset
496 -- the bodies of protected operations.
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 if Ekind (E_Scope) = E_Protected_Type
kono
parents:
diff changeset
499 or else (Ekind (E_Scope) = E_Task_Type
kono
parents:
diff changeset
500 and then not Has_Completion (E_Scope))
kono
parents:
diff changeset
501 then
kono
parents:
diff changeset
502 E_Scope := Scope (E_Scope);
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 elsif Ekind (E_Scope) = E_Subprogram_Body then
kono
parents:
diff changeset
505 E_Scope := Corresponding_Spec (Unit_Declaration_Node (E_Scope));
kono
parents:
diff changeset
506 end if;
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 -- If the scope of the entity is in open scopes, it is the current one
kono
parents:
diff changeset
509 -- or an enclosing one, including a loop, a block, or a subprogram.
kono
parents:
diff changeset
510
kono
parents:
diff changeset
511 if In_Open_Scopes (E_Scope) then
kono
parents:
diff changeset
512 In_Other_Scope := False;
kono
parents:
diff changeset
513 In_Outer_Scope := E_Scope /= Current_Scope;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 -- Otherwise it is a local package or a different compilation unit
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 else
kono
parents:
diff changeset
518 In_Other_Scope := True;
kono
parents:
diff changeset
519 In_Outer_Scope := False;
kono
parents:
diff changeset
520 end if;
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 -- If the entity being frozen is defined in a scope that is not
kono
parents:
diff changeset
523 -- currently on the scope stack, we must establish the proper
kono
parents:
diff changeset
524 -- visibility before freezing the entity and related subprograms.
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 if In_Other_Scope then
kono
parents:
diff changeset
527 Push_Scope (E_Scope);
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 -- Finalizers are little odd in terms of freezing. The spec of the
kono
parents:
diff changeset
530 -- procedure appears in the declarations while the body appears in
kono
parents:
diff changeset
531 -- the statement part of a single construct. Since the finalizer must
kono
parents:
diff changeset
532 -- be called by the At_End handler of the construct, the spec is
kono
parents:
diff changeset
533 -- manually frozen right after its declaration. The only side effect
kono
parents:
diff changeset
534 -- of this action appears in contexts where the construct is not in
kono
parents:
diff changeset
535 -- its final resting place. These contexts are:
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 -- * Entry bodies - The declarations and statements are moved to
kono
parents:
diff changeset
538 -- the procedure equivalen of the entry.
kono
parents:
diff changeset
539 -- * Protected subprograms - The declarations and statements are
kono
parents:
diff changeset
540 -- moved to the non-protected version of the subprogram.
kono
parents:
diff changeset
541 -- * Task bodies - The declarations and statements are moved to the
kono
parents:
diff changeset
542 -- task body procedure.
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 -- Visible declarations do not need to be installed in these three
kono
parents:
diff changeset
545 -- cases since it does not make semantic sense to do so. All entities
kono
parents:
diff changeset
546 -- referenced by a finalizer are visible and already resolved, plus
kono
parents:
diff changeset
547 -- the enclosing scope may not have visible declarations at all.
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 if Ekind (E) = E_Procedure
kono
parents:
diff changeset
550 and then Is_Finalizer (E)
kono
parents:
diff changeset
551 and then
kono
parents:
diff changeset
552 (Is_Entry (E_Scope)
kono
parents:
diff changeset
553 or else (Is_Subprogram (E_Scope)
kono
parents:
diff changeset
554 and then Is_Protected_Type (Scope (E_Scope)))
kono
parents:
diff changeset
555 or else Is_Task_Type (E_Scope))
kono
parents:
diff changeset
556 then
kono
parents:
diff changeset
557 null;
kono
parents:
diff changeset
558 else
kono
parents:
diff changeset
559 Install_Visible_Declarations (E_Scope);
kono
parents:
diff changeset
560 end if;
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 if Is_Package_Or_Generic_Package (E_Scope) or else
kono
parents:
diff changeset
563 Is_Protected_Type (E_Scope) or else
kono
parents:
diff changeset
564 Is_Task_Type (E_Scope)
kono
parents:
diff changeset
565 then
kono
parents:
diff changeset
566 Install_Private_Declarations (E_Scope);
kono
parents:
diff changeset
567 end if;
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 -- If the entity is in an outer scope, then that scope needs to
kono
parents:
diff changeset
570 -- temporarily become the current scope so that operations created
kono
parents:
diff changeset
571 -- during type freezing will be declared in the right scope and
kono
parents:
diff changeset
572 -- can properly override any corresponding inherited operations.
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 elsif In_Outer_Scope then
kono
parents:
diff changeset
575 Push_Scope (E_Scope);
kono
parents:
diff changeset
576 end if;
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 -- If type, freeze the type
kono
parents:
diff changeset
579
kono
parents:
diff changeset
580 if Is_Type (E) then
kono
parents:
diff changeset
581 Delete := Freeze_Type (N);
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 -- And for enumeration type, build the enumeration tables
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 if Is_Enumeration_Type (E) then
kono
parents:
diff changeset
586 Build_Enumeration_Image_Tables (E, N);
kono
parents:
diff changeset
587 end if;
kono
parents:
diff changeset
588
kono
parents:
diff changeset
589 -- If subprogram, freeze the subprogram
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 elsif Is_Subprogram (E) then
kono
parents:
diff changeset
592 Exp_Ch6.Freeze_Subprogram (N);
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 -- Ada 2005 (AI-251): Remove the freezing node associated with the
kono
parents:
diff changeset
595 -- entities internally used by the frontend to register primitives
kono
parents:
diff changeset
596 -- covering abstract interfaces. The call to Freeze_Subprogram has
kono
parents:
diff changeset
597 -- already expanded the code that fills the corresponding entry in
kono
parents:
diff changeset
598 -- its secondary dispatch table and therefore the code generator
kono
parents:
diff changeset
599 -- has nothing else to do with this freezing node.
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 Delete := Present (Interface_Alias (E));
kono
parents:
diff changeset
602 end if;
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 -- Analyze actions generated by freezing. The init_proc contains source
kono
parents:
diff changeset
605 -- expressions that may raise Constraint_Error, and the assignment
kono
parents:
diff changeset
606 -- procedure for complex types needs checks on individual component
kono
parents:
diff changeset
607 -- assignments, but all other freezing actions should be compiled with
kono
parents:
diff changeset
608 -- all checks off.
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 if Present (Actions (N)) then
kono
parents:
diff changeset
611 Decl := First (Actions (N));
kono
parents:
diff changeset
612 while Present (Decl) loop
kono
parents:
diff changeset
613 if Nkind (Decl) = N_Subprogram_Body
kono
parents:
diff changeset
614 and then (Is_Init_Proc (Defining_Entity (Decl))
kono
parents:
diff changeset
615 or else
kono
parents:
diff changeset
616 Chars (Defining_Entity (Decl)) = Name_uAssign)
kono
parents:
diff changeset
617 then
kono
parents:
diff changeset
618 Analyze (Decl);
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 -- A subprogram body created for a renaming_as_body completes
kono
parents:
diff changeset
621 -- a previous declaration, which may be in a different scope.
kono
parents:
diff changeset
622 -- Establish the proper scope before analysis.
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 elsif Nkind (Decl) = N_Subprogram_Body
kono
parents:
diff changeset
625 and then Present (Corresponding_Spec (Decl))
kono
parents:
diff changeset
626 and then Scope (Corresponding_Spec (Decl)) /= Current_Scope
kono
parents:
diff changeset
627 then
kono
parents:
diff changeset
628 Push_Scope (Scope (Corresponding_Spec (Decl)));
kono
parents:
diff changeset
629 Analyze (Decl, Suppress => All_Checks);
kono
parents:
diff changeset
630 Pop_Scope;
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 -- We treat generated equality specially, if validity checks are
kono
parents:
diff changeset
633 -- enabled, in order to detect components default-initialized
kono
parents:
diff changeset
634 -- with invalid values.
kono
parents:
diff changeset
635
kono
parents:
diff changeset
636 elsif Nkind (Decl) = N_Subprogram_Body
kono
parents:
diff changeset
637 and then Chars (Defining_Entity (Decl)) = Name_Op_Eq
kono
parents:
diff changeset
638 and then Validity_Checks_On
kono
parents:
diff changeset
639 and then Initialize_Scalars
kono
parents:
diff changeset
640 then
kono
parents:
diff changeset
641 declare
kono
parents:
diff changeset
642 Save_Force : constant Boolean := Force_Validity_Checks;
kono
parents:
diff changeset
643 begin
kono
parents:
diff changeset
644 Force_Validity_Checks := True;
kono
parents:
diff changeset
645 Analyze (Decl);
kono
parents:
diff changeset
646 Force_Validity_Checks := Save_Force;
kono
parents:
diff changeset
647 end;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 -- All other freezing actions
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 else
kono
parents:
diff changeset
652 Analyze (Decl, Suppress => All_Checks);
kono
parents:
diff changeset
653 end if;
kono
parents:
diff changeset
654
kono
parents:
diff changeset
655 Next (Decl);
kono
parents:
diff changeset
656 end loop;
kono
parents:
diff changeset
657 end if;
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 -- If we are to delete this N_Freeze_Entity, do so by rewriting so that
kono
parents:
diff changeset
660 -- a loop on all nodes being inserted will work propertly.
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 if Delete then
kono
parents:
diff changeset
663 Rewrite (N, Make_Null_Statement (Sloc (N)));
kono
parents:
diff changeset
664 end if;
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666 -- Pop scope if we installed one for the analysis
kono
parents:
diff changeset
667
kono
parents:
diff changeset
668 if In_Other_Scope then
kono
parents:
diff changeset
669 if Ekind (Current_Scope) = E_Package then
kono
parents:
diff changeset
670 End_Package_Scope (E_Scope);
kono
parents:
diff changeset
671 else
kono
parents:
diff changeset
672 End_Scope;
kono
parents:
diff changeset
673 end if;
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 elsif In_Outer_Scope then
kono
parents:
diff changeset
676 Pop_Scope;
kono
parents:
diff changeset
677 end if;
kono
parents:
diff changeset
678
kono
parents:
diff changeset
679 -- Restore previous value of the nesting-level counter that records
kono
parents:
diff changeset
680 -- whether we are inside a (possibly nested) call to this procedure.
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 Inside_Freezing_Actions := Inside_Freezing_Actions - 1;
kono
parents:
diff changeset
683 end Expand_N_Freeze_Entity;
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 -------------------------------------------
kono
parents:
diff changeset
686 -- Expand_N_Record_Representation_Clause --
kono
parents:
diff changeset
687 -------------------------------------------
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 -- The only expansion required is for the case of a mod clause present,
kono
parents:
diff changeset
690 -- which is removed, and translated into an alignment representation
kono
parents:
diff changeset
691 -- clause inserted immediately after the record rep clause with any
kono
parents:
diff changeset
692 -- initial pragmas inserted at the start of the component clause list.
kono
parents:
diff changeset
693
kono
parents:
diff changeset
694 procedure Expand_N_Record_Representation_Clause (N : Node_Id) is
kono
parents:
diff changeset
695 Loc : constant Source_Ptr := Sloc (N);
kono
parents:
diff changeset
696 Rectype : constant Entity_Id := Entity (Identifier (N));
kono
parents:
diff changeset
697 Mod_Val : Uint;
kono
parents:
diff changeset
698 Citems : List_Id;
kono
parents:
diff changeset
699 Repitem : Node_Id;
kono
parents:
diff changeset
700 AtM_Nod : Node_Id;
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 begin
kono
parents:
diff changeset
703 if Present (Mod_Clause (N)) and then not Ignore_Rep_Clauses then
kono
parents:
diff changeset
704 Mod_Val := Expr_Value (Expression (Mod_Clause (N)));
kono
parents:
diff changeset
705 Citems := Pragmas_Before (Mod_Clause (N));
kono
parents:
diff changeset
706
kono
parents:
diff changeset
707 if Present (Citems) then
kono
parents:
diff changeset
708 Append_List_To (Citems, Component_Clauses (N));
kono
parents:
diff changeset
709 Set_Component_Clauses (N, Citems);
kono
parents:
diff changeset
710 end if;
kono
parents:
diff changeset
711
kono
parents:
diff changeset
712 AtM_Nod :=
kono
parents:
diff changeset
713 Make_Attribute_Definition_Clause (Loc,
kono
parents:
diff changeset
714 Name => New_Occurrence_Of (Base_Type (Rectype), Loc),
kono
parents:
diff changeset
715 Chars => Name_Alignment,
kono
parents:
diff changeset
716 Expression => Make_Integer_Literal (Loc, Mod_Val));
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 Set_From_At_Mod (AtM_Nod);
kono
parents:
diff changeset
719 Insert_After (N, AtM_Nod);
kono
parents:
diff changeset
720 Set_Mod_Clause (N, Empty);
kono
parents:
diff changeset
721 end if;
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 -- If the record representation clause has no components, then
kono
parents:
diff changeset
724 -- completely remove it. Note that we also have to remove
kono
parents:
diff changeset
725 -- ourself from the Rep Item list.
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 if Is_Empty_List (Component_Clauses (N)) then
kono
parents:
diff changeset
728 if First_Rep_Item (Rectype) = N then
kono
parents:
diff changeset
729 Set_First_Rep_Item (Rectype, Next_Rep_Item (N));
kono
parents:
diff changeset
730 else
kono
parents:
diff changeset
731 Repitem := First_Rep_Item (Rectype);
kono
parents:
diff changeset
732 while Present (Next_Rep_Item (Repitem)) loop
kono
parents:
diff changeset
733 if Next_Rep_Item (Repitem) = N then
kono
parents:
diff changeset
734 Set_Next_Rep_Item (Repitem, Next_Rep_Item (N));
kono
parents:
diff changeset
735 exit;
kono
parents:
diff changeset
736 end if;
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 Next_Rep_Item (Repitem);
kono
parents:
diff changeset
739 end loop;
kono
parents:
diff changeset
740 end if;
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 Rewrite (N,
kono
parents:
diff changeset
743 Make_Null_Statement (Loc));
kono
parents:
diff changeset
744 end if;
kono
parents:
diff changeset
745 end Expand_N_Record_Representation_Clause;
kono
parents:
diff changeset
746
kono
parents:
diff changeset
747 end Exp_Ch13;