* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / ada / exp_ch13.adb
blob6e57f3beb77f32495aa15d3b3915dcfaccf458f3
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 1 3 --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.76 $
10 -- --
11 -- Copyright (C) 1992-2001, Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 -- --
27 ------------------------------------------------------------------------------
29 with Atree; use Atree;
30 with Einfo; use Einfo;
31 with Exp_Ch3; use Exp_Ch3;
32 with Exp_Ch6; use Exp_Ch6;
33 with Exp_Imgv; use Exp_Imgv;
34 with Exp_Util; use Exp_Util;
35 with Nlists; use Nlists;
36 with Nmake; use Nmake;
37 with Rtsfind; use Rtsfind;
38 with Sem; use Sem;
39 with Sem_Ch7; use Sem_Ch7;
40 with Sem_Ch8; use Sem_Ch8;
41 with Sem_Eval; use Sem_Eval;
42 with Sem_Util; use Sem_Util;
43 with Sinfo; use Sinfo;
44 with Snames; use Snames;
45 with Stand; use Stand;
46 with Stringt; use Stringt;
47 with Tbuild; use Tbuild;
48 with Uintp; use Uintp;
50 package body Exp_Ch13 is
52 ------------------------------------------
53 -- Expand_N_Attribute_Definition_Clause --
54 ------------------------------------------
56 -- Expansion action depends on attribute involved
58 procedure Expand_N_Attribute_Definition_Clause (N : Node_Id) is
59 Loc : constant Source_Ptr := Sloc (N);
60 Exp : constant Node_Id := Expression (N);
61 Ent : Entity_Id;
62 V : Node_Id;
64 begin
65 Ent := Entity (Name (N));
67 if Is_Type (Ent) then
68 Ent := Underlying_Type (Ent);
69 end if;
71 case Get_Attribute_Id (Chars (N)) is
73 -------------
74 -- Address --
75 -------------
77 when Attribute_Address =>
79 -- If there is an initialization which did not come from
80 -- the source program, then it is an artifact of our
81 -- expansion, and we suppress it. The case we are most
82 -- concerned about here is the initialization of a packed
83 -- array to all false, which seems inappropriate for a
84 -- variable to which an address clause is applied. The
85 -- expression may itself have been rewritten if the type is a
86 -- packed array, so we need to examine whether the original
87 -- node is in the source.
89 declare
90 Decl : constant Node_Id := Declaration_Node (Ent);
92 begin
93 if Nkind (Decl) = N_Object_Declaration
94 and then Present (Expression (Decl))
95 and then
96 not Comes_From_Source (Original_Node (Expression (Decl)))
97 then
98 Set_Expression (Decl, Empty);
99 end if;
100 end;
102 ---------------
103 -- Alignment --
104 ---------------
106 when Attribute_Alignment =>
108 -- As required by Gigi, we guarantee that the operand is an
109 -- integer literal (this simplifies things in Gigi).
111 if Nkind (Exp) /= N_Integer_Literal then
112 Rewrite
113 (Exp, Make_Integer_Literal (Loc, Expr_Value (Exp)));
114 end if;
116 ------------------
117 -- External_Tag --
118 ------------------
120 -- For the rep clause "for x'external_tag use y" generate:
122 -- xV : constant string := y;
123 -- Set_External_Tag (x'tag, xV'Address);
124 -- Register_Tag (x'tag);
126 -- note that register_tag has been delayed up to now because
127 -- the external_tag must be set before resistering.
129 when Attribute_External_Tag => External_Tag : declare
130 E : Entity_Id;
131 Old_Val : String_Id := Strval (Expr_Value_S (Exp));
132 New_Val : String_Id;
134 begin
135 -- Create a new nul terminated string if it is not already
137 if String_Length (Old_Val) > 0
138 and then Get_String_Char (Old_Val, String_Length (Old_Val)) = 0
139 then
140 New_Val := Old_Val;
141 else
142 Start_String (Old_Val);
143 Store_String_Char (Get_Char_Code (ASCII.NUL));
144 New_Val := End_String;
145 end if;
147 E :=
148 Make_Defining_Identifier (Loc,
149 New_External_Name (Chars (Ent), 'A'));
151 Insert_Action (N,
152 Make_Object_Declaration (Loc,
153 Defining_Identifier => E,
154 Constant_Present => True,
155 Object_Definition =>
156 New_Reference_To (Standard_String, Loc),
157 Expression =>
158 Make_String_Literal (Loc, Strval => New_Val)));
160 Insert_Actions (N, New_List (
161 Make_Procedure_Call_Statement (Loc,
162 Name => New_Reference_To (RTE (RE_Set_External_Tag), Loc),
163 Parameter_Associations => New_List (
164 Make_Attribute_Reference (Loc,
165 Attribute_Name => Name_Tag,
166 Prefix => New_Occurrence_Of (Ent, Loc)),
168 Make_Attribute_Reference (Loc,
169 Attribute_Name => Name_Address,
170 Prefix => New_Occurrence_Of (E, Loc)))),
172 Make_Procedure_Call_Statement (Loc,
173 Name => New_Reference_To (RTE (RE_Register_Tag), Loc),
174 Parameter_Associations => New_List (
175 Make_Attribute_Reference (Loc,
176 Attribute_Name => Name_Tag,
177 Prefix => New_Occurrence_Of (Ent, Loc))))));
178 end External_Tag;
180 ------------------
181 -- Storage_Size --
182 ------------------
184 when Attribute_Storage_Size =>
186 -- If the type is a task type, then assign the value of the
187 -- storage size to the Size variable associated with the task.
188 -- task_typeZ := expression
190 if Ekind (Ent) = E_Task_Type then
191 Insert_Action (N,
192 Make_Assignment_Statement (Loc,
193 Name => New_Reference_To (Storage_Size_Variable (Ent), Loc),
194 Expression =>
195 Convert_To (RTE (RE_Size_Type), Expression (N))));
197 -- For Storage_Size for an access type, create a variable to hold
198 -- the value of the specified size with name typeV and expand an
199 -- assignment statement to initialze this value.
201 elsif Is_Access_Type (Ent) then
203 V := Make_Defining_Identifier (Loc,
204 New_External_Name (Chars (Ent), 'V'));
206 Insert_Action (N,
207 Make_Object_Declaration (Loc,
208 Defining_Identifier => V,
209 Object_Definition =>
210 New_Reference_To (RTE (RE_Storage_Offset), Loc),
211 Expression =>
212 Convert_To (RTE (RE_Storage_Offset), Expression (N))));
214 Set_Storage_Size_Variable (Ent, Entity_Id (V));
215 end if;
217 -- Other attributes require no expansion
219 when others =>
220 null;
222 end case;
224 end Expand_N_Attribute_Definition_Clause;
226 ----------------------------
227 -- Expand_N_Freeze_Entity --
228 ----------------------------
230 procedure Expand_N_Freeze_Entity (N : Node_Id) is
231 E : constant Entity_Id := Entity (N);
232 E_Scope : Entity_Id;
233 S : Entity_Id;
234 In_Other_Scope : Boolean;
235 In_Outer_Scope : Boolean;
236 Decl : Node_Id;
238 begin
239 if not Is_Type (E) and then not Is_Subprogram (E) then
240 return;
241 end if;
243 E_Scope := Scope (E);
245 -- If we are freezing entities defined in protected types, they
246 -- belong in the enclosing scope, given that the original type
247 -- has been expanded away. The same is true for entities in task types,
248 -- in particular the parameter records of entries (Entities in bodies
249 -- are all frozen within the body). If we are in the task body, this
250 -- is a proper scope.
252 if Ekind (E_Scope) = E_Protected_Type
253 or else (Ekind (E_Scope) = E_Task_Type
254 and then not Has_Completion (E_Scope))
255 then
256 E_Scope := Scope (E_Scope);
257 end if;
259 S := Current_Scope;
260 while S /= Standard_Standard and then S /= E_Scope loop
261 S := Scope (S);
262 end loop;
264 In_Other_Scope := not (S = E_Scope);
265 In_Outer_Scope := (not In_Other_Scope) and then (S /= Current_Scope);
267 -- If the entity being frozen is defined in a scope that is not
268 -- currently on the scope stack, we must establish the proper
269 -- visibility before freezing the entity and related subprograms.
271 if In_Other_Scope then
272 New_Scope (E_Scope);
273 Install_Visible_Declarations (E_Scope);
275 if Ekind (E_Scope) = E_Package or else
276 Ekind (E_Scope) = E_Generic_Package or else
277 Is_Protected_Type (E_Scope) or else
278 Is_Task_Type (E_Scope)
279 then
280 Install_Private_Declarations (E_Scope);
281 end if;
283 -- If the entity is in an outer scope, then that scope needs to
284 -- temporarily become the current scope so that operations created
285 -- during type freezing will be declared in the right scope and
286 -- can properly override any corresponding inherited operations.
288 elsif In_Outer_Scope then
289 New_Scope (E_Scope);
290 end if;
292 -- If type, freeze the type
294 if Is_Type (E) then
295 Freeze_Type (N);
297 -- And for enumeration type, build the enumeration tables
299 if Is_Enumeration_Type (E) then
300 Build_Enumeration_Image_Tables (E, N);
301 end if;
303 -- If subprogram, freeze the subprogram
305 elsif Is_Subprogram (E) then
306 Freeze_Subprogram (N);
308 -- No other entities require any front end freeze actions
310 else
311 null;
312 end if;
314 -- Analyze actions generated by freezing. The init_proc contains
315 -- source expressions that may raise constraint_error, and the
316 -- assignment procedure for complex types needs checks on individual
317 -- component assignments, but all other freezing actions should be
318 -- compiled with all checks off.
320 if Present (Actions (N)) then
321 Decl := First (Actions (N));
323 while Present (Decl) loop
325 if Nkind (Decl) = N_Subprogram_Body
326 and then (Chars (Defining_Entity (Decl)) = Name_uInit_Proc
327 or else Chars (Defining_Entity (Decl)) = Name_uAssign)
328 then
329 Analyze (Decl);
331 -- A subprogram body created for a renaming_as_body completes
332 -- a previous declaration, which may be in a different scope.
333 -- Establish the proper scope before analysis.
335 elsif Nkind (Decl) = N_Subprogram_Body
336 and then Present (Corresponding_Spec (Decl))
337 and then Scope (Corresponding_Spec (Decl)) /= Current_Scope
338 then
339 New_Scope (Scope (Corresponding_Spec (Decl)));
340 Analyze (Decl, Suppress => All_Checks);
341 Pop_Scope;
343 else
344 Analyze (Decl, Suppress => All_Checks);
345 end if;
347 Next (Decl);
348 end loop;
349 end if;
351 if In_Other_Scope then
352 if Ekind (Current_Scope) = E_Package then
353 End_Package_Scope (E_Scope);
354 else
355 End_Scope;
356 end if;
358 elsif In_Outer_Scope then
359 Pop_Scope;
360 end if;
361 end Expand_N_Freeze_Entity;
363 -------------------------------------------
364 -- Expand_N_Record_Representation_Clause --
365 -------------------------------------------
367 -- The only expansion required is for the case of a mod clause present,
368 -- which is removed, and translated into an alignment representation
369 -- clause inserted immediately after the record rep clause with any
370 -- initial pragmas inserted at the start of the component clause list.
372 procedure Expand_N_Record_Representation_Clause (N : Node_Id) is
373 Loc : constant Source_Ptr := Sloc (N);
374 Rectype : constant Entity_Id := Entity (Identifier (N));
375 Mod_Val : Uint;
376 Citems : List_Id;
377 Repitem : Node_Id;
378 AtM_Nod : Node_Id;
380 begin
381 if Present (Mod_Clause (N)) then
382 Mod_Val := Expr_Value (Expression (Mod_Clause (N)));
383 Citems := Pragmas_Before (Mod_Clause (N));
385 if Present (Citems) then
386 Append_List_To (Citems, Component_Clauses (N));
387 Set_Component_Clauses (N, Citems);
388 end if;
390 AtM_Nod :=
391 Make_Attribute_Definition_Clause (Loc,
392 Name => New_Reference_To (Base_Type (Rectype), Loc),
393 Chars => Name_Alignment,
394 Expression => Make_Integer_Literal (Loc, Mod_Val));
396 Set_From_At_Mod (AtM_Nod);
397 Insert_After (N, AtM_Nod);
398 Set_Mod_Clause (N, Empty);
399 end if;
401 -- If the record representation clause has no components, then
402 -- completely remove it. Note that we also have to remove
403 -- ourself from the Rep Item list.
405 if Is_Empty_List (Component_Clauses (N)) then
406 if First_Rep_Item (Rectype) = N then
407 Set_First_Rep_Item (Rectype, Next_Rep_Item (N));
408 else
409 Repitem := First_Rep_Item (Rectype);
410 while Present (Next_Rep_Item (Repitem)) loop
411 if Next_Rep_Item (Repitem) = N then
412 Set_Next_Rep_Item (Repitem, Next_Rep_Item (N));
413 exit;
414 end if;
416 Next_Rep_Item (Repitem);
417 end loop;
418 end if;
420 Rewrite (N,
421 Make_Null_Statement (Loc));
422 end if;
423 end Expand_N_Record_Representation_Clause;
425 end Exp_Ch13;