1 | /* Language-dependent node constructors for parse phase of GNU compiler. |
---|
2 | Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc. |
---|
3 | Hacked by Michael Tiemann (tiemann@cygnus.com) |
---|
4 | |
---|
5 | This file is part of GNU CC. |
---|
6 | |
---|
7 | GNU CC is free software; you can redistribute it and/or modify |
---|
8 | it under the terms of the GNU General Public License as published by |
---|
9 | the Free Software Foundation; either version 2, or (at your option) |
---|
10 | any later version. |
---|
11 | |
---|
12 | GNU CC is distributed in the hope that it will be useful, |
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | GNU General Public License for more details. |
---|
16 | |
---|
17 | You should have received a copy of the GNU General Public License |
---|
18 | along with GNU CC; see the file COPYING. If not, write to |
---|
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
20 | Boston, MA 02111-1307, USA. */ |
---|
21 | |
---|
22 | #include "config.h" |
---|
23 | #include <stdio.h> |
---|
24 | #include "obstack.h" |
---|
25 | #include "tree.h" |
---|
26 | #include "cp-tree.h" |
---|
27 | #include "flags.h" |
---|
28 | #include "rtl.h" |
---|
29 | |
---|
30 | #define CEIL(x,y) (((x) + (y) - 1) / (y)) |
---|
31 | |
---|
32 | /* Return nonzero if REF is an lvalue valid for this language. |
---|
33 | Lvalues can be assigned, unless they have TREE_READONLY. |
---|
34 | Lvalues can have their address taken, unless they have DECL_REGISTER. */ |
---|
35 | |
---|
36 | int |
---|
37 | real_lvalue_p (ref) |
---|
38 | tree ref; |
---|
39 | { |
---|
40 | if (! language_lvalue_valid (ref)) |
---|
41 | return 0; |
---|
42 | |
---|
43 | if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) |
---|
44 | return 1; |
---|
45 | |
---|
46 | if (ref == current_class_decl && flag_this_is_variable <= 0) |
---|
47 | return 0; |
---|
48 | |
---|
49 | switch (TREE_CODE (ref)) |
---|
50 | { |
---|
51 | /* preincrements and predecrements are valid lvals, provided |
---|
52 | what they refer to are valid lvals. */ |
---|
53 | case PREINCREMENT_EXPR: |
---|
54 | case PREDECREMENT_EXPR: |
---|
55 | case COMPONENT_REF: |
---|
56 | case SAVE_EXPR: |
---|
57 | return real_lvalue_p (TREE_OPERAND (ref, 0)); |
---|
58 | |
---|
59 | case STRING_CST: |
---|
60 | return 1; |
---|
61 | |
---|
62 | case VAR_DECL: |
---|
63 | if (TREE_READONLY (ref) && ! TREE_STATIC (ref) |
---|
64 | && DECL_LANG_SPECIFIC (ref) |
---|
65 | && DECL_IN_AGGR_P (ref)) |
---|
66 | return 0; |
---|
67 | case INDIRECT_REF: |
---|
68 | case ARRAY_REF: |
---|
69 | case PARM_DECL: |
---|
70 | case RESULT_DECL: |
---|
71 | case ERROR_MARK: |
---|
72 | if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE |
---|
73 | && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) |
---|
74 | return 1; |
---|
75 | break; |
---|
76 | |
---|
77 | case WITH_CLEANUP_EXPR: |
---|
78 | return real_lvalue_p (TREE_OPERAND (ref, 0)); |
---|
79 | |
---|
80 | /* A currently unresolved scope ref. */ |
---|
81 | case SCOPE_REF: |
---|
82 | my_friendly_abort (103); |
---|
83 | case OFFSET_REF: |
---|
84 | if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) |
---|
85 | return 1; |
---|
86 | return real_lvalue_p (TREE_OPERAND (ref, 0)) |
---|
87 | && real_lvalue_p (TREE_OPERAND (ref, 1)); |
---|
88 | break; |
---|
89 | |
---|
90 | case COND_EXPR: |
---|
91 | return (real_lvalue_p (TREE_OPERAND (ref, 1)) |
---|
92 | && real_lvalue_p (TREE_OPERAND (ref, 2))); |
---|
93 | |
---|
94 | case MODIFY_EXPR: |
---|
95 | return 1; |
---|
96 | |
---|
97 | case COMPOUND_EXPR: |
---|
98 | return real_lvalue_p (TREE_OPERAND (ref, 1)); |
---|
99 | |
---|
100 | case MAX_EXPR: |
---|
101 | case MIN_EXPR: |
---|
102 | return (real_lvalue_p (TREE_OPERAND (ref, 0)) |
---|
103 | && real_lvalue_p (TREE_OPERAND (ref, 1))); |
---|
104 | } |
---|
105 | |
---|
106 | return 0; |
---|
107 | } |
---|
108 | |
---|
109 | int |
---|
110 | lvalue_p (ref) |
---|
111 | tree ref; |
---|
112 | { |
---|
113 | if (! language_lvalue_valid (ref)) |
---|
114 | return 0; |
---|
115 | |
---|
116 | if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) |
---|
117 | return 1; |
---|
118 | |
---|
119 | if (ref == current_class_decl && flag_this_is_variable <= 0) |
---|
120 | return 0; |
---|
121 | |
---|
122 | switch (TREE_CODE (ref)) |
---|
123 | { |
---|
124 | /* preincrements and predecrements are valid lvals, provided |
---|
125 | what they refer to are valid lvals. */ |
---|
126 | case PREINCREMENT_EXPR: |
---|
127 | case PREDECREMENT_EXPR: |
---|
128 | case COMPONENT_REF: |
---|
129 | case SAVE_EXPR: |
---|
130 | return lvalue_p (TREE_OPERAND (ref, 0)); |
---|
131 | |
---|
132 | case STRING_CST: |
---|
133 | return 1; |
---|
134 | |
---|
135 | case VAR_DECL: |
---|
136 | if (TREE_READONLY (ref) && ! TREE_STATIC (ref) |
---|
137 | && DECL_LANG_SPECIFIC (ref) |
---|
138 | && DECL_IN_AGGR_P (ref)) |
---|
139 | return 0; |
---|
140 | case INDIRECT_REF: |
---|
141 | case ARRAY_REF: |
---|
142 | case PARM_DECL: |
---|
143 | case RESULT_DECL: |
---|
144 | case ERROR_MARK: |
---|
145 | if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE |
---|
146 | && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) |
---|
147 | return 1; |
---|
148 | break; |
---|
149 | |
---|
150 | case WITH_CLEANUP_EXPR: |
---|
151 | return lvalue_p (TREE_OPERAND (ref, 0)); |
---|
152 | |
---|
153 | case TARGET_EXPR: |
---|
154 | return 1; |
---|
155 | |
---|
156 | case CALL_EXPR: |
---|
157 | if (IS_AGGR_TYPE (TREE_TYPE (ref))) |
---|
158 | return 1; |
---|
159 | break; |
---|
160 | |
---|
161 | /* A currently unresolved scope ref. */ |
---|
162 | case SCOPE_REF: |
---|
163 | my_friendly_abort (103); |
---|
164 | case OFFSET_REF: |
---|
165 | if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) |
---|
166 | return 1; |
---|
167 | return lvalue_p (TREE_OPERAND (ref, 0)) |
---|
168 | && lvalue_p (TREE_OPERAND (ref, 1)); |
---|
169 | break; |
---|
170 | |
---|
171 | case COND_EXPR: |
---|
172 | return (lvalue_p (TREE_OPERAND (ref, 1)) |
---|
173 | && lvalue_p (TREE_OPERAND (ref, 2))); |
---|
174 | |
---|
175 | case MODIFY_EXPR: |
---|
176 | return 1; |
---|
177 | |
---|
178 | case COMPOUND_EXPR: |
---|
179 | return lvalue_p (TREE_OPERAND (ref, 1)); |
---|
180 | |
---|
181 | case MAX_EXPR: |
---|
182 | case MIN_EXPR: |
---|
183 | return (lvalue_p (TREE_OPERAND (ref, 0)) |
---|
184 | && lvalue_p (TREE_OPERAND (ref, 1))); |
---|
185 | } |
---|
186 | |
---|
187 | return 0; |
---|
188 | } |
---|
189 | |
---|
190 | /* Return nonzero if REF is an lvalue valid for this language; |
---|
191 | otherwise, print an error message and return zero. */ |
---|
192 | |
---|
193 | int |
---|
194 | lvalue_or_else (ref, string) |
---|
195 | tree ref; |
---|
196 | char *string; |
---|
197 | { |
---|
198 | int win = lvalue_p (ref); |
---|
199 | if (! win) |
---|
200 | error ("non-lvalue in %s", string); |
---|
201 | return win; |
---|
202 | } |
---|
203 | |
---|
204 | /* INIT is a CALL_EXPR which needs info about its target. |
---|
205 | TYPE is the type that this initialization should appear to have. |
---|
206 | |
---|
207 | Build an encapsulation of the initialization to perform |
---|
208 | and return it so that it can be processed by language-independent |
---|
209 | and language-specific expression expanders. |
---|
210 | |
---|
211 | If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression. |
---|
212 | Otherwise, cleanups are not built here. For example, when building |
---|
213 | an initialization for a stack slot, since the called function handles |
---|
214 | the cleanup, we would not want to do it here. */ |
---|
215 | tree |
---|
216 | build_cplus_new (type, init, with_cleanup_p) |
---|
217 | tree type; |
---|
218 | tree init; |
---|
219 | int with_cleanup_p; |
---|
220 | { |
---|
221 | tree slot; |
---|
222 | tree rval; |
---|
223 | |
---|
224 | slot = build (VAR_DECL, type); |
---|
225 | layout_decl (slot, 0); |
---|
226 | rval = build (NEW_EXPR, type, |
---|
227 | TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); |
---|
228 | TREE_SIDE_EFFECTS (rval) = 1; |
---|
229 | TREE_ADDRESSABLE (rval) = 1; |
---|
230 | rval = build (TARGET_EXPR, type, slot, rval, 0); |
---|
231 | TREE_SIDE_EFFECTS (rval) = 1; |
---|
232 | TREE_ADDRESSABLE (rval) = 1; |
---|
233 | |
---|
234 | #if 0 |
---|
235 | if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type)) |
---|
236 | { |
---|
237 | TREE_OPERAND (rval, 2) = error_mark_node; |
---|
238 | rval = build (WITH_CLEANUP_EXPR, type, rval, 0, |
---|
239 | build_delete (build_pointer_type (type), |
---|
240 | build_unary_op (ADDR_EXPR, slot, 0), |
---|
241 | integer_two_node, |
---|
242 | LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0)); |
---|
243 | TREE_SIDE_EFFECTS (rval) = 1; |
---|
244 | TREE_ADDRESSABLE (rval) = 1; |
---|
245 | } |
---|
246 | #endif |
---|
247 | return rval; |
---|
248 | } |
---|
249 | |
---|
250 | /* Recursively search EXP for CALL_EXPRs that need cleanups and replace |
---|
251 | these CALL_EXPRs with tree nodes that will perform the cleanups. */ |
---|
252 | |
---|
253 | tree |
---|
254 | break_out_cleanups (exp) |
---|
255 | tree exp; |
---|
256 | { |
---|
257 | tree tmp = exp; |
---|
258 | |
---|
259 | if (TREE_CODE (tmp) == CALL_EXPR |
---|
260 | && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp))) |
---|
261 | return build_cplus_new (TREE_TYPE (tmp), tmp, 1); |
---|
262 | |
---|
263 | while (TREE_CODE (tmp) == NOP_EXPR |
---|
264 | || TREE_CODE (tmp) == CONVERT_EXPR |
---|
265 | || TREE_CODE (tmp) == NON_LVALUE_EXPR) |
---|
266 | { |
---|
267 | if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR |
---|
268 | && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0)))) |
---|
269 | { |
---|
270 | TREE_OPERAND (tmp, 0) |
---|
271 | = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)), |
---|
272 | TREE_OPERAND (tmp, 0), 1); |
---|
273 | break; |
---|
274 | } |
---|
275 | else |
---|
276 | tmp = TREE_OPERAND (tmp, 0); |
---|
277 | } |
---|
278 | return exp; |
---|
279 | } |
---|
280 | |
---|
281 | /* Recursively perform a preorder search EXP for CALL_EXPRs, making |
---|
282 | copies where they are found. Returns a deep copy all nodes transitively |
---|
283 | containing CALL_EXPRs. */ |
---|
284 | |
---|
285 | tree |
---|
286 | break_out_calls (exp) |
---|
287 | tree exp; |
---|
288 | { |
---|
289 | register tree t1, t2; |
---|
290 | register enum tree_code code; |
---|
291 | register int changed = 0; |
---|
292 | register int i; |
---|
293 | |
---|
294 | if (exp == NULL_TREE) |
---|
295 | return exp; |
---|
296 | |
---|
297 | code = TREE_CODE (exp); |
---|
298 | |
---|
299 | if (code == CALL_EXPR) |
---|
300 | return copy_node (exp); |
---|
301 | |
---|
302 | /* Don't try and defeat a save_expr, as it should only be done once. */ |
---|
303 | if (code == SAVE_EXPR) |
---|
304 | return exp; |
---|
305 | |
---|
306 | switch (TREE_CODE_CLASS (code)) |
---|
307 | { |
---|
308 | default: |
---|
309 | abort (); |
---|
310 | |
---|
311 | case 'c': /* a constant */ |
---|
312 | case 't': /* a type node */ |
---|
313 | case 'x': /* something random, like an identifier or an ERROR_MARK. */ |
---|
314 | return exp; |
---|
315 | |
---|
316 | case 'd': /* A decl node */ |
---|
317 | #if 0 /* This is bogus. jason 9/21/94 */ |
---|
318 | |
---|
319 | t1 = break_out_calls (DECL_INITIAL (exp)); |
---|
320 | if (t1 != DECL_INITIAL (exp)) |
---|
321 | { |
---|
322 | exp = copy_node (exp); |
---|
323 | DECL_INITIAL (exp) = t1; |
---|
324 | } |
---|
325 | #endif |
---|
326 | return exp; |
---|
327 | |
---|
328 | case 'b': /* A block node */ |
---|
329 | { |
---|
330 | /* Don't know how to handle these correctly yet. Must do a |
---|
331 | break_out_calls on all DECL_INITIAL values for local variables, |
---|
332 | and also break_out_calls on all sub-blocks and sub-statements. */ |
---|
333 | abort (); |
---|
334 | } |
---|
335 | return exp; |
---|
336 | |
---|
337 | case 'e': /* an expression */ |
---|
338 | case 'r': /* a reference */ |
---|
339 | case 's': /* an expression with side effects */ |
---|
340 | for (i = tree_code_length[(int) code] - 1; i >= 0; i--) |
---|
341 | { |
---|
342 | t1 = break_out_calls (TREE_OPERAND (exp, i)); |
---|
343 | if (t1 != TREE_OPERAND (exp, i)) |
---|
344 | { |
---|
345 | exp = copy_node (exp); |
---|
346 | TREE_OPERAND (exp, i) = t1; |
---|
347 | } |
---|
348 | } |
---|
349 | return exp; |
---|
350 | |
---|
351 | case '<': /* a comparison expression */ |
---|
352 | case '2': /* a binary arithmetic expression */ |
---|
353 | t2 = break_out_calls (TREE_OPERAND (exp, 1)); |
---|
354 | if (t2 != TREE_OPERAND (exp, 1)) |
---|
355 | changed = 1; |
---|
356 | case '1': /* a unary arithmetic expression */ |
---|
357 | t1 = break_out_calls (TREE_OPERAND (exp, 0)); |
---|
358 | if (t1 != TREE_OPERAND (exp, 0)) |
---|
359 | changed = 1; |
---|
360 | if (changed) |
---|
361 | { |
---|
362 | if (tree_code_length[(int) code] == 1) |
---|
363 | return build1 (code, TREE_TYPE (exp), t1); |
---|
364 | else |
---|
365 | return build (code, TREE_TYPE (exp), t1, t2); |
---|
366 | } |
---|
367 | return exp; |
---|
368 | } |
---|
369 | |
---|
370 | } |
---|
371 | |
---|
372 | extern struct obstack *current_obstack; |
---|
373 | extern struct obstack permanent_obstack, class_obstack; |
---|
374 | extern struct obstack *saveable_obstack; |
---|
375 | |
---|
376 | /* Here is how primitive or already-canonicalized types' hash |
---|
377 | codes are made. MUST BE CONSISTENT WITH tree.c !!! */ |
---|
378 | #define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777) |
---|
379 | |
---|
380 | /* Construct, lay out and return the type of methods belonging to class |
---|
381 | BASETYPE and whose arguments are described by ARGTYPES and whose values |
---|
382 | are described by RETTYPE. If each type exists already, reuse it. */ |
---|
383 | tree |
---|
384 | build_cplus_method_type (basetype, rettype, argtypes) |
---|
385 | tree basetype, rettype, argtypes; |
---|
386 | { |
---|
387 | register tree t; |
---|
388 | tree ptype; |
---|
389 | int hashcode; |
---|
390 | |
---|
391 | /* Make a node of the sort we want. */ |
---|
392 | t = make_node (METHOD_TYPE); |
---|
393 | |
---|
394 | TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); |
---|
395 | TREE_TYPE (t) = rettype; |
---|
396 | if (IS_SIGNATURE (basetype)) |
---|
397 | ptype = build_signature_pointer_type (TYPE_MAIN_VARIANT (basetype), |
---|
398 | TYPE_READONLY (basetype), |
---|
399 | TYPE_VOLATILE (basetype)); |
---|
400 | else |
---|
401 | ptype = build_pointer_type (basetype); |
---|
402 | |
---|
403 | /* The actual arglist for this function includes a "hidden" argument |
---|
404 | which is "this". Put it into the list of argument types. */ |
---|
405 | |
---|
406 | argtypes = tree_cons (NULL_TREE, ptype, argtypes); |
---|
407 | TYPE_ARG_TYPES (t) = argtypes; |
---|
408 | TREE_SIDE_EFFECTS (argtypes) = 1; /* Mark first argtype as "artificial". */ |
---|
409 | |
---|
410 | /* If we already have such a type, use the old one and free this one. |
---|
411 | Note that it also frees up the above cons cell if found. */ |
---|
412 | hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes); |
---|
413 | t = type_hash_canon (hashcode, t); |
---|
414 | |
---|
415 | if (TYPE_SIZE (t) == 0) |
---|
416 | layout_type (t); |
---|
417 | |
---|
418 | return t; |
---|
419 | } |
---|
420 | |
---|
421 | tree |
---|
422 | build_cplus_staticfn_type (basetype, rettype, argtypes) |
---|
423 | tree basetype, rettype, argtypes; |
---|
424 | { |
---|
425 | register tree t; |
---|
426 | int hashcode; |
---|
427 | |
---|
428 | /* Make a node of the sort we want. */ |
---|
429 | t = make_node (FUNCTION_TYPE); |
---|
430 | |
---|
431 | TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); |
---|
432 | TREE_TYPE (t) = rettype; |
---|
433 | |
---|
434 | TYPE_ARG_TYPES (t) = argtypes; |
---|
435 | |
---|
436 | /* If we already have such a type, use the old one and free this one. |
---|
437 | Note that it also frees up the above cons cell if found. */ |
---|
438 | hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes); |
---|
439 | t = type_hash_canon (hashcode, t); |
---|
440 | |
---|
441 | if (TYPE_SIZE (t) == 0) |
---|
442 | layout_type (t); |
---|
443 | |
---|
444 | return t; |
---|
445 | } |
---|
446 | |
---|
447 | tree |
---|
448 | build_cplus_array_type (elt_type, index_type) |
---|
449 | tree elt_type; |
---|
450 | tree index_type; |
---|
451 | { |
---|
452 | register struct obstack *ambient_obstack = current_obstack; |
---|
453 | register struct obstack *ambient_saveable_obstack = saveable_obstack; |
---|
454 | tree t; |
---|
455 | |
---|
456 | /* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent, |
---|
457 | make this permanent too. */ |
---|
458 | if (TREE_PERMANENT (elt_type) |
---|
459 | && (index_type == 0 || TREE_PERMANENT (index_type))) |
---|
460 | { |
---|
461 | current_obstack = &permanent_obstack; |
---|
462 | saveable_obstack = &permanent_obstack; |
---|
463 | } |
---|
464 | |
---|
465 | t = build_array_type (elt_type, index_type); |
---|
466 | |
---|
467 | /* Push these needs up so that initialization takes place |
---|
468 | more easily. */ |
---|
469 | TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type)); |
---|
470 | TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type)); |
---|
471 | current_obstack = ambient_obstack; |
---|
472 | saveable_obstack = ambient_saveable_obstack; |
---|
473 | return t; |
---|
474 | } |
---|
475 | |
---|
476 | /* Make a variant type in the proper way for C/C++, propagating qualifiers |
---|
477 | down to the element type of an array. */ |
---|
478 | |
---|
479 | tree |
---|
480 | cp_build_type_variant (type, constp, volatilep) |
---|
481 | tree type; |
---|
482 | int constp, volatilep; |
---|
483 | { |
---|
484 | if (TREE_CODE (type) == ARRAY_TYPE) |
---|
485 | { |
---|
486 | tree real_main_variant = TYPE_MAIN_VARIANT (type); |
---|
487 | |
---|
488 | push_obstacks (TYPE_OBSTACK (real_main_variant), |
---|
489 | TYPE_OBSTACK (real_main_variant)); |
---|
490 | type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type), |
---|
491 | constp, volatilep), |
---|
492 | TYPE_DOMAIN (type)); |
---|
493 | |
---|
494 | /* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not, |
---|
495 | make a copy. (TYPE might have come from the hash table and |
---|
496 | REAL_MAIN_VARIANT might be in some function's obstack.) */ |
---|
497 | |
---|
498 | if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant)) |
---|
499 | { |
---|
500 | type = copy_node (type); |
---|
501 | TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0; |
---|
502 | } |
---|
503 | |
---|
504 | TYPE_MAIN_VARIANT (type) = real_main_variant; |
---|
505 | pop_obstacks (); |
---|
506 | } |
---|
507 | return build_type_variant (type, constp, volatilep); |
---|
508 | } |
---|
509 | |
---|
510 | /* Add OFFSET to all base types of T. |
---|
511 | |
---|
512 | OFFSET, which is a type offset, is number of bytes. |
---|
513 | |
---|
514 | Note that we don't have to worry about having two paths to the |
---|
515 | same base type, since this type owns its association list. */ |
---|
516 | void |
---|
517 | propagate_binfo_offsets (binfo, offset) |
---|
518 | tree binfo; |
---|
519 | tree offset; |
---|
520 | { |
---|
521 | tree binfos = BINFO_BASETYPES (binfo); |
---|
522 | int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; |
---|
523 | |
---|
524 | for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) |
---|
525 | { |
---|
526 | tree base_binfo = TREE_VEC_ELT (binfos, i); |
---|
527 | |
---|
528 | if (TREE_VIA_VIRTUAL (base_binfo)) |
---|
529 | i += 1; |
---|
530 | else |
---|
531 | { |
---|
532 | int j; |
---|
533 | tree base_binfos = BINFO_BASETYPES (base_binfo); |
---|
534 | tree delta; |
---|
535 | |
---|
536 | for (j = i+1; j < n_baselinks; j++) |
---|
537 | if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) |
---|
538 | { |
---|
539 | /* The next basetype offset must take into account the space |
---|
540 | between the classes, not just the size of each class. */ |
---|
541 | delta = size_binop (MINUS_EXPR, |
---|
542 | BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), |
---|
543 | BINFO_OFFSET (base_binfo)); |
---|
544 | break; |
---|
545 | } |
---|
546 | |
---|
547 | #if 0 |
---|
548 | if (BINFO_OFFSET_ZEROP (base_binfo)) |
---|
549 | BINFO_OFFSET (base_binfo) = offset; |
---|
550 | else |
---|
551 | BINFO_OFFSET (base_binfo) |
---|
552 | = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset); |
---|
553 | #else |
---|
554 | BINFO_OFFSET (base_binfo) = offset; |
---|
555 | #endif |
---|
556 | if (base_binfos) |
---|
557 | { |
---|
558 | int k; |
---|
559 | tree chain = NULL_TREE; |
---|
560 | |
---|
561 | /* Now unshare the structure beneath BASE_BINFO. */ |
---|
562 | for (k = TREE_VEC_LENGTH (base_binfos)-1; |
---|
563 | k >= 0; k--) |
---|
564 | { |
---|
565 | tree base_base_binfo = TREE_VEC_ELT (base_binfos, k); |
---|
566 | if (! TREE_VIA_VIRTUAL (base_base_binfo)) |
---|
567 | TREE_VEC_ELT (base_binfos, k) |
---|
568 | = make_binfo (BINFO_OFFSET (base_base_binfo), |
---|
569 | base_base_binfo, |
---|
570 | BINFO_VTABLE (base_base_binfo), |
---|
571 | BINFO_VIRTUALS (base_base_binfo), |
---|
572 | chain); |
---|
573 | chain = TREE_VEC_ELT (base_binfos, k); |
---|
574 | TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); |
---|
575 | TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); |
---|
576 | BINFO_INHERITANCE_CHAIN (chain) = base_binfo; |
---|
577 | } |
---|
578 | /* Now propagate the offset to the base types. */ |
---|
579 | propagate_binfo_offsets (base_binfo, offset); |
---|
580 | } |
---|
581 | |
---|
582 | /* Go to our next class that counts for offset propagation. */ |
---|
583 | i = j; |
---|
584 | if (i < n_baselinks) |
---|
585 | offset = size_binop (PLUS_EXPR, offset, delta); |
---|
586 | } |
---|
587 | } |
---|
588 | } |
---|
589 | |
---|
590 | /* Compute the actual offsets that our virtual base classes |
---|
591 | will have *for this type*. This must be performed after |
---|
592 | the fields are laid out, since virtual baseclasses must |
---|
593 | lay down at the end of the record. |
---|
594 | |
---|
595 | Returns the maximum number of virtual functions any of the virtual |
---|
596 | baseclasses provide. */ |
---|
597 | int |
---|
598 | layout_vbasetypes (rec, max) |
---|
599 | tree rec; |
---|
600 | int max; |
---|
601 | { |
---|
602 | /* Get all the virtual base types that this type uses. |
---|
603 | The TREE_VALUE slot holds the virtual baseclass type. */ |
---|
604 | tree vbase_types = get_vbase_types (rec); |
---|
605 | |
---|
606 | #ifdef STRUCTURE_SIZE_BOUNDARY |
---|
607 | unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); |
---|
608 | #else |
---|
609 | unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); |
---|
610 | #endif |
---|
611 | int desired_align; |
---|
612 | |
---|
613 | /* Record size so far is CONST_SIZE + VAR_SIZE bits, |
---|
614 | where CONST_SIZE is an integer |
---|
615 | and VAR_SIZE is a tree expression. |
---|
616 | If VAR_SIZE is null, the size is just CONST_SIZE. |
---|
617 | Naturally we try to avoid using VAR_SIZE. */ |
---|
618 | register unsigned const_size = 0; |
---|
619 | register tree var_size = 0; |
---|
620 | int nonvirtual_const_size; |
---|
621 | tree nonvirtual_var_size; |
---|
622 | |
---|
623 | CLASSTYPE_VBASECLASSES (rec) = vbase_types; |
---|
624 | |
---|
625 | if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST) |
---|
626 | const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec)); |
---|
627 | else |
---|
628 | var_size = TYPE_SIZE (rec); |
---|
629 | |
---|
630 | nonvirtual_const_size = const_size; |
---|
631 | nonvirtual_var_size = var_size; |
---|
632 | |
---|
633 | while (vbase_types) |
---|
634 | { |
---|
635 | tree basetype = BINFO_TYPE (vbase_types); |
---|
636 | tree offset; |
---|
637 | |
---|
638 | desired_align = TYPE_ALIGN (basetype); |
---|
639 | record_align = MAX (record_align, desired_align); |
---|
640 | |
---|
641 | if (const_size == 0) |
---|
642 | offset = integer_zero_node; |
---|
643 | else |
---|
644 | { |
---|
645 | /* Give each virtual base type the alignment it wants. */ |
---|
646 | const_size = CEIL (const_size, TYPE_ALIGN (basetype)) |
---|
647 | * TYPE_ALIGN (basetype); |
---|
648 | offset = size_int (CEIL (const_size, BITS_PER_UNIT)); |
---|
649 | } |
---|
650 | |
---|
651 | if (CLASSTYPE_VSIZE (basetype) > max) |
---|
652 | max = CLASSTYPE_VSIZE (basetype); |
---|
653 | BINFO_OFFSET (vbase_types) = offset; |
---|
654 | |
---|
655 | if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST) |
---|
656 | { |
---|
657 | /* Every virtual baseclass takes a least a UNIT, so that we can |
---|
658 | take it's address and get something different for each base. */ |
---|
659 | const_size += MAX (BITS_PER_UNIT, |
---|
660 | TREE_INT_CST_LOW (TYPE_SIZE (basetype)) |
---|
661 | - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); |
---|
662 | } |
---|
663 | else if (var_size == 0) |
---|
664 | var_size = TYPE_SIZE (basetype); |
---|
665 | else |
---|
666 | var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype)); |
---|
667 | |
---|
668 | vbase_types = TREE_CHAIN (vbase_types); |
---|
669 | } |
---|
670 | |
---|
671 | if (const_size) |
---|
672 | { |
---|
673 | /* Because a virtual base might take a single byte above, |
---|
674 | we have to re-adjust the total size to make sure it it |
---|
675 | a multiple of the alignment. */ |
---|
676 | /* Give the whole object the alignment it wants. */ |
---|
677 | const_size = CEIL (const_size, record_align) * record_align; |
---|
678 | } |
---|
679 | |
---|
680 | /* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN |
---|
681 | here, as that is for this class, without any virtual base classes. */ |
---|
682 | TYPE_ALIGN (rec) = record_align; |
---|
683 | if (const_size != nonvirtual_const_size) |
---|
684 | { |
---|
685 | CLASSTYPE_VBASE_SIZE (rec) |
---|
686 | = size_int (const_size - nonvirtual_const_size); |
---|
687 | TYPE_SIZE (rec) = size_int (const_size); |
---|
688 | } |
---|
689 | |
---|
690 | /* Now propagate offset information throughout the lattice |
---|
691 | under the vbase type. */ |
---|
692 | for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types; |
---|
693 | vbase_types = TREE_CHAIN (vbase_types)) |
---|
694 | { |
---|
695 | tree base_binfos = BINFO_BASETYPES (vbase_types); |
---|
696 | |
---|
697 | BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); |
---|
698 | |
---|
699 | if (base_binfos) |
---|
700 | { |
---|
701 | tree chain = NULL_TREE; |
---|
702 | int j; |
---|
703 | /* Now unshare the structure beneath BASE_BINFO. */ |
---|
704 | |
---|
705 | for (j = TREE_VEC_LENGTH (base_binfos)-1; |
---|
706 | j >= 0; j--) |
---|
707 | { |
---|
708 | tree base_base_binfo = TREE_VEC_ELT (base_binfos, j); |
---|
709 | if (! TREE_VIA_VIRTUAL (base_base_binfo)) |
---|
710 | TREE_VEC_ELT (base_binfos, j) |
---|
711 | = make_binfo (BINFO_OFFSET (base_base_binfo), |
---|
712 | base_base_binfo, |
---|
713 | BINFO_VTABLE (base_base_binfo), |
---|
714 | BINFO_VIRTUALS (base_base_binfo), |
---|
715 | chain); |
---|
716 | chain = TREE_VEC_ELT (base_binfos, j); |
---|
717 | TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); |
---|
718 | TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); |
---|
719 | BINFO_INHERITANCE_CHAIN (chain) = vbase_types; |
---|
720 | } |
---|
721 | |
---|
722 | propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); |
---|
723 | } |
---|
724 | } |
---|
725 | |
---|
726 | return max; |
---|
727 | } |
---|
728 | |
---|
729 | /* Lay out the base types of a record type, REC. |
---|
730 | Tentatively set the size and alignment of REC |
---|
731 | according to the base types alone. |
---|
732 | |
---|
733 | Offsets for immediate nonvirtual baseclasses are also computed here. |
---|
734 | |
---|
735 | TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine |
---|
736 | creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS. |
---|
737 | |
---|
738 | Returns list of virtual base classes in a FIELD_DECL chain. */ |
---|
739 | tree |
---|
740 | layout_basetypes (rec, binfos) |
---|
741 | tree rec, binfos; |
---|
742 | { |
---|
743 | /* Chain to hold all the new FIELD_DECLs which point at virtual |
---|
744 | base classes. */ |
---|
745 | tree vbase_decls = NULL_TREE; |
---|
746 | |
---|
747 | #ifdef STRUCTURE_SIZE_BOUNDARY |
---|
748 | unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); |
---|
749 | #else |
---|
750 | unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); |
---|
751 | #endif |
---|
752 | |
---|
753 | /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is |
---|
754 | an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null, |
---|
755 | the size is just CONST_SIZE. Naturally we try to avoid using |
---|
756 | VAR_SIZE. And so far, we've been successful. */ |
---|
757 | #if 0 |
---|
758 | register tree var_size = 0; |
---|
759 | #endif |
---|
760 | |
---|
761 | register unsigned const_size = 0; |
---|
762 | int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; |
---|
763 | |
---|
764 | /* Handle basetypes almost like fields, but record their |
---|
765 | offsets differently. */ |
---|
766 | |
---|
767 | for (i = 0; i < n_baseclasses; i++) |
---|
768 | { |
---|
769 | int inc, desired_align, int_vbase_size; |
---|
770 | register tree base_binfo = TREE_VEC_ELT (binfos, i); |
---|
771 | register tree basetype = BINFO_TYPE (base_binfo); |
---|
772 | tree decl, offset; |
---|
773 | |
---|
774 | if (TYPE_SIZE (basetype) == 0) |
---|
775 | { |
---|
776 | #if 0 |
---|
777 | /* This error is now reported in xref_tag, thus giving better |
---|
778 | location information. */ |
---|
779 | error_with_aggr_type (base_binfo, |
---|
780 | "base class `%s' has incomplete type"); |
---|
781 | |
---|
782 | TREE_VIA_PUBLIC (base_binfo) = 1; |
---|
783 | TREE_VIA_PROTECTED (base_binfo) = 0; |
---|
784 | TREE_VIA_VIRTUAL (base_binfo) = 0; |
---|
785 | |
---|
786 | /* Should handle this better so that |
---|
787 | |
---|
788 | class A; |
---|
789 | class B: private A { virtual void F(); }; |
---|
790 | |
---|
791 | does not dump core when compiled. */ |
---|
792 | my_friendly_abort (121); |
---|
793 | #endif |
---|
794 | continue; |
---|
795 | } |
---|
796 | |
---|
797 | /* All basetypes are recorded in the association list of the |
---|
798 | derived type. */ |
---|
799 | |
---|
800 | if (TREE_VIA_VIRTUAL (base_binfo)) |
---|
801 | { |
---|
802 | int j; |
---|
803 | char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype) |
---|
804 | + sizeof (VBASE_NAME) + 1); |
---|
805 | |
---|
806 | /* The offset for a virtual base class is only used in computing |
---|
807 | virtual function tables and for initializing virtual base |
---|
808 | pointers. It is built once `get_vbase_types' is called. */ |
---|
809 | |
---|
810 | /* If this basetype can come from another vbase pointer |
---|
811 | without an additional indirection, we will share |
---|
812 | that pointer. If an indirection is involved, we |
---|
813 | make our own pointer. */ |
---|
814 | for (j = 0; j < n_baseclasses; j++) |
---|
815 | { |
---|
816 | tree other_base_binfo = TREE_VEC_ELT (binfos, j); |
---|
817 | if (! TREE_VIA_VIRTUAL (other_base_binfo) |
---|
818 | && binfo_member (basetype, |
---|
819 | CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_base_binfo)))) |
---|
820 | goto got_it; |
---|
821 | } |
---|
822 | sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); |
---|
823 | decl = build_lang_decl (FIELD_DECL, get_identifier (name), |
---|
824 | build_pointer_type (basetype)); |
---|
825 | /* If you change any of the below, take a look at all the |
---|
826 | other VFIELD_BASEs and VTABLE_BASEs in the code, and change |
---|
827 | them too. */ |
---|
828 | DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE); |
---|
829 | DECL_VIRTUAL_P (decl) = 1; |
---|
830 | DECL_FIELD_CONTEXT (decl) = rec; |
---|
831 | DECL_CLASS_CONTEXT (decl) = rec; |
---|
832 | DECL_FCONTEXT (decl) = basetype; |
---|
833 | DECL_SAVED_INSNS (decl) = NULL_RTX; |
---|
834 | DECL_FIELD_SIZE (decl) = 0; |
---|
835 | DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node); |
---|
836 | TREE_CHAIN (decl) = vbase_decls; |
---|
837 | BINFO_VPTR_FIELD (base_binfo) = decl; |
---|
838 | vbase_decls = decl; |
---|
839 | |
---|
840 | if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) |
---|
841 | && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) |
---|
842 | { |
---|
843 | warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), |
---|
844 | "destructor `%s' non-virtual"); |
---|
845 | warning ("in inheritance relationship `%s: virtual %s'", |
---|
846 | TYPE_NAME_STRING (rec), |
---|
847 | TYPE_NAME_STRING (basetype)); |
---|
848 | } |
---|
849 | got_it: |
---|
850 | /* The space this decl occupies has already been accounted for. */ |
---|
851 | continue; |
---|
852 | } |
---|
853 | |
---|
854 | if (const_size == 0) |
---|
855 | offset = integer_zero_node; |
---|
856 | else |
---|
857 | { |
---|
858 | /* Give each base type the alignment it wants. */ |
---|
859 | const_size = CEIL (const_size, TYPE_ALIGN (basetype)) |
---|
860 | * TYPE_ALIGN (basetype); |
---|
861 | offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); |
---|
862 | |
---|
863 | #if 0 |
---|
864 | /* bpk: Disabled this check until someone is willing to |
---|
865 | claim it as theirs and explain exactly what circumstances |
---|
866 | warrant the warning. */ |
---|
867 | if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) |
---|
868 | && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) |
---|
869 | { |
---|
870 | warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), |
---|
871 | "destructor `%s' non-virtual"); |
---|
872 | warning ("in inheritance relationship `%s:%s %s'", |
---|
873 | TYPE_NAME_STRING (rec), |
---|
874 | TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "", |
---|
875 | TYPE_NAME_STRING (basetype)); |
---|
876 | } |
---|
877 | #endif |
---|
878 | } |
---|
879 | BINFO_OFFSET (base_binfo) = offset; |
---|
880 | if (CLASSTYPE_VSIZE (basetype)) |
---|
881 | { |
---|
882 | BINFO_VTABLE (base_binfo) = TYPE_BINFO_VTABLE (basetype); |
---|
883 | BINFO_VIRTUALS (base_binfo) = TYPE_BINFO_VIRTUALS (basetype); |
---|
884 | } |
---|
885 | TREE_CHAIN (base_binfo) = TYPE_BINFO (rec); |
---|
886 | TYPE_BINFO (rec) = base_binfo; |
---|
887 | |
---|
888 | /* Add only the amount of storage not present in |
---|
889 | the virtual baseclasses. */ |
---|
890 | |
---|
891 | int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)); |
---|
892 | if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size) |
---|
893 | { |
---|
894 | inc = MAX (record_align, |
---|
895 | (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) |
---|
896 | - int_vbase_size)); |
---|
897 | |
---|
898 | /* Record must have at least as much alignment as any field. */ |
---|
899 | desired_align = TYPE_ALIGN (basetype); |
---|
900 | record_align = MAX (record_align, desired_align); |
---|
901 | |
---|
902 | const_size += inc; |
---|
903 | } |
---|
904 | } |
---|
905 | |
---|
906 | if (const_size) |
---|
907 | CLASSTYPE_SIZE (rec) = size_int (const_size); |
---|
908 | else |
---|
909 | CLASSTYPE_SIZE (rec) = integer_zero_node; |
---|
910 | CLASSTYPE_ALIGN (rec) = record_align; |
---|
911 | |
---|
912 | return vbase_decls; |
---|
913 | } |
---|
914 | |
---|
915 | /* Hashing of lists so that we don't make duplicates. |
---|
916 | The entry point is `list_hash_canon'. */ |
---|
917 | |
---|
918 | /* Each hash table slot is a bucket containing a chain |
---|
919 | of these structures. */ |
---|
920 | |
---|
921 | struct list_hash |
---|
922 | { |
---|
923 | struct list_hash *next; /* Next structure in the bucket. */ |
---|
924 | int hashcode; /* Hash code of this list. */ |
---|
925 | tree list; /* The list recorded here. */ |
---|
926 | }; |
---|
927 | |
---|
928 | /* Now here is the hash table. When recording a list, it is added |
---|
929 | to the slot whose index is the hash code mod the table size. |
---|
930 | Note that the hash table is used for several kinds of lists. |
---|
931 | While all these live in the same table, they are completely independent, |
---|
932 | and the hash code is computed differently for each of these. */ |
---|
933 | |
---|
934 | #define TYPE_HASH_SIZE 59 |
---|
935 | struct list_hash *list_hash_table[TYPE_HASH_SIZE]; |
---|
936 | |
---|
937 | /* Compute a hash code for a list (chain of TREE_LIST nodes |
---|
938 | with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the |
---|
939 | TREE_COMMON slots), by adding the hash codes of the individual entries. */ |
---|
940 | |
---|
941 | int |
---|
942 | list_hash (list) |
---|
943 | tree list; |
---|
944 | { |
---|
945 | register int hashcode = 0; |
---|
946 | |
---|
947 | if (TREE_CHAIN (list)) |
---|
948 | hashcode += TYPE_HASH (TREE_CHAIN (list)); |
---|
949 | |
---|
950 | if (TREE_VALUE (list)) |
---|
951 | hashcode += TYPE_HASH (TREE_VALUE (list)); |
---|
952 | else |
---|
953 | hashcode += 1007; |
---|
954 | if (TREE_PURPOSE (list)) |
---|
955 | hashcode += TYPE_HASH (TREE_PURPOSE (list)); |
---|
956 | else |
---|
957 | hashcode += 1009; |
---|
958 | return hashcode; |
---|
959 | } |
---|
960 | |
---|
961 | /* Look in the type hash table for a type isomorphic to TYPE. |
---|
962 | If one is found, return it. Otherwise return 0. */ |
---|
963 | |
---|
964 | tree |
---|
965 | list_hash_lookup (hashcode, list) |
---|
966 | int hashcode; |
---|
967 | tree list; |
---|
968 | { |
---|
969 | register struct list_hash *h; |
---|
970 | for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) |
---|
971 | if (h->hashcode == hashcode |
---|
972 | && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list) |
---|
973 | && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list) |
---|
974 | && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list) |
---|
975 | && TREE_PURPOSE (h->list) == TREE_PURPOSE (list) |
---|
976 | && TREE_VALUE (h->list) == TREE_VALUE (list) |
---|
977 | && TREE_CHAIN (h->list) == TREE_CHAIN (list)) |
---|
978 | { |
---|
979 | my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299); |
---|
980 | return h->list; |
---|
981 | } |
---|
982 | return 0; |
---|
983 | } |
---|
984 | |
---|
985 | /* Add an entry to the list-hash-table |
---|
986 | for a list TYPE whose hash code is HASHCODE. */ |
---|
987 | |
---|
988 | void |
---|
989 | list_hash_add (hashcode, list) |
---|
990 | int hashcode; |
---|
991 | tree list; |
---|
992 | { |
---|
993 | register struct list_hash *h; |
---|
994 | |
---|
995 | h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash)); |
---|
996 | h->hashcode = hashcode; |
---|
997 | h->list = list; |
---|
998 | h->next = list_hash_table[hashcode % TYPE_HASH_SIZE]; |
---|
999 | list_hash_table[hashcode % TYPE_HASH_SIZE] = h; |
---|
1000 | } |
---|
1001 | |
---|
1002 | /* Given TYPE, and HASHCODE its hash code, return the canonical |
---|
1003 | object for an identical list if one already exists. |
---|
1004 | Otherwise, return TYPE, and record it as the canonical object |
---|
1005 | if it is a permanent object. |
---|
1006 | |
---|
1007 | To use this function, first create a list of the sort you want. |
---|
1008 | Then compute its hash code from the fields of the list that |
---|
1009 | make it different from other similar lists. |
---|
1010 | Then call this function and use the value. |
---|
1011 | This function frees the list you pass in if it is a duplicate. */ |
---|
1012 | |
---|
1013 | /* Set to 1 to debug without canonicalization. Never set by program. */ |
---|
1014 | static int debug_no_list_hash = 0; |
---|
1015 | |
---|
1016 | tree |
---|
1017 | list_hash_canon (hashcode, list) |
---|
1018 | int hashcode; |
---|
1019 | tree list; |
---|
1020 | { |
---|
1021 | tree t1; |
---|
1022 | |
---|
1023 | if (debug_no_list_hash) |
---|
1024 | return list; |
---|
1025 | |
---|
1026 | t1 = list_hash_lookup (hashcode, list); |
---|
1027 | if (t1 != 0) |
---|
1028 | { |
---|
1029 | obstack_free (&class_obstack, list); |
---|
1030 | return t1; |
---|
1031 | } |
---|
1032 | |
---|
1033 | /* If this is a new list, record it for later reuse. */ |
---|
1034 | list_hash_add (hashcode, list); |
---|
1035 | |
---|
1036 | return list; |
---|
1037 | } |
---|
1038 | |
---|
1039 | tree |
---|
1040 | hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain) |
---|
1041 | int via_public, via_virtual, via_protected; |
---|
1042 | tree purpose, value, chain; |
---|
1043 | { |
---|
1044 | struct obstack *ambient_obstack = current_obstack; |
---|
1045 | tree t; |
---|
1046 | int hashcode; |
---|
1047 | |
---|
1048 | current_obstack = &class_obstack; |
---|
1049 | t = tree_cons (purpose, value, chain); |
---|
1050 | TREE_VIA_PUBLIC (t) = via_public; |
---|
1051 | TREE_VIA_PROTECTED (t) = via_protected; |
---|
1052 | TREE_VIA_VIRTUAL (t) = via_virtual; |
---|
1053 | hashcode = list_hash (t); |
---|
1054 | t = list_hash_canon (hashcode, t); |
---|
1055 | current_obstack = ambient_obstack; |
---|
1056 | return t; |
---|
1057 | } |
---|
1058 | |
---|
1059 | /* Constructor for hashed lists. */ |
---|
1060 | tree |
---|
1061 | hash_tree_chain (value, chain) |
---|
1062 | tree value, chain; |
---|
1063 | { |
---|
1064 | struct obstack *ambient_obstack = current_obstack; |
---|
1065 | tree t; |
---|
1066 | int hashcode; |
---|
1067 | |
---|
1068 | current_obstack = &class_obstack; |
---|
1069 | t = tree_cons (NULL_TREE, value, chain); |
---|
1070 | hashcode = list_hash (t); |
---|
1071 | t = list_hash_canon (hashcode, t); |
---|
1072 | current_obstack = ambient_obstack; |
---|
1073 | return t; |
---|
1074 | } |
---|
1075 | |
---|
1076 | /* Similar, but used for concatenating two lists. */ |
---|
1077 | tree |
---|
1078 | hash_chainon (list1, list2) |
---|
1079 | tree list1, list2; |
---|
1080 | { |
---|
1081 | if (list2 == 0) |
---|
1082 | return list1; |
---|
1083 | if (list1 == 0) |
---|
1084 | return list2; |
---|
1085 | if (TREE_CHAIN (list1) == NULL_TREE) |
---|
1086 | return hash_tree_chain (TREE_VALUE (list1), list2); |
---|
1087 | return hash_tree_chain (TREE_VALUE (list1), |
---|
1088 | hash_chainon (TREE_CHAIN (list1), list2)); |
---|
1089 | } |
---|
1090 | |
---|
1091 | static tree |
---|
1092 | get_identifier_list (value) |
---|
1093 | tree value; |
---|
1094 | { |
---|
1095 | tree list = IDENTIFIER_AS_LIST (value); |
---|
1096 | if (list != NULL_TREE |
---|
1097 | && (TREE_CODE (list) != TREE_LIST |
---|
1098 | || TREE_VALUE (list) != value)) |
---|
1099 | list = NULL_TREE; |
---|
1100 | else if (IDENTIFIER_HAS_TYPE_VALUE (value) |
---|
1101 | && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE |
---|
1102 | && IDENTIFIER_TYPE_VALUE (value) |
---|
1103 | == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value))) |
---|
1104 | { |
---|
1105 | tree type = IDENTIFIER_TYPE_VALUE (value); |
---|
1106 | |
---|
1107 | if (TYPE_PTRMEMFUNC_P (type)) |
---|
1108 | list = NULL_TREE; |
---|
1109 | else if (type == current_class_type) |
---|
1110 | /* Don't mess up the constructor name. */ |
---|
1111 | list = tree_cons (NULL_TREE, value, NULL_TREE); |
---|
1112 | else |
---|
1113 | { |
---|
1114 | register tree id; |
---|
1115 | /* This will return the correct thing for regular types, |
---|
1116 | nested types, and templates. Yay! */ |
---|
1117 | if (TYPE_NESTED_NAME (type)) |
---|
1118 | id = TYPE_NESTED_NAME (type); |
---|
1119 | else |
---|
1120 | id = TYPE_IDENTIFIER (type); |
---|
1121 | |
---|
1122 | if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) |
---|
1123 | CLASSTYPE_ID_AS_LIST (type) |
---|
1124 | = perm_tree_cons (NULL_TREE, id, NULL_TREE); |
---|
1125 | list = CLASSTYPE_ID_AS_LIST (type); |
---|
1126 | } |
---|
1127 | } |
---|
1128 | return list; |
---|
1129 | } |
---|
1130 | |
---|
1131 | tree |
---|
1132 | get_decl_list (value) |
---|
1133 | tree value; |
---|
1134 | { |
---|
1135 | tree list = NULL_TREE; |
---|
1136 | |
---|
1137 | if (TREE_CODE (value) == IDENTIFIER_NODE) |
---|
1138 | list = get_identifier_list (value); |
---|
1139 | else if (TREE_CODE (value) == RECORD_TYPE |
---|
1140 | && TYPE_LANG_SPECIFIC (value)) |
---|
1141 | list = CLASSTYPE_AS_LIST (value); |
---|
1142 | |
---|
1143 | if (list != NULL_TREE) |
---|
1144 | { |
---|
1145 | my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301); |
---|
1146 | return list; |
---|
1147 | } |
---|
1148 | |
---|
1149 | return build_decl_list (NULL_TREE, value); |
---|
1150 | } |
---|
1151 | |
---|
1152 | /* Look in the type hash table for a type isomorphic to |
---|
1153 | `build_tree_list (NULL_TREE, VALUE)'. |
---|
1154 | If one is found, return it. Otherwise return 0. */ |
---|
1155 | |
---|
1156 | tree |
---|
1157 | list_hash_lookup_or_cons (value) |
---|
1158 | tree value; |
---|
1159 | { |
---|
1160 | register int hashcode = TYPE_HASH (value); |
---|
1161 | register struct list_hash *h; |
---|
1162 | struct obstack *ambient_obstack; |
---|
1163 | tree list = NULL_TREE; |
---|
1164 | |
---|
1165 | if (TREE_CODE (value) == IDENTIFIER_NODE) |
---|
1166 | list = get_identifier_list (value); |
---|
1167 | else if (TREE_CODE (value) == TYPE_DECL |
---|
1168 | && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE |
---|
1169 | && TYPE_LANG_SPECIFIC (TREE_TYPE (value))) |
---|
1170 | list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value)); |
---|
1171 | else if (TREE_CODE (value) == RECORD_TYPE |
---|
1172 | && TYPE_LANG_SPECIFIC (value)) |
---|
1173 | list = CLASSTYPE_AS_LIST (value); |
---|
1174 | |
---|
1175 | if (list != NULL_TREE) |
---|
1176 | { |
---|
1177 | my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302); |
---|
1178 | return list; |
---|
1179 | } |
---|
1180 | |
---|
1181 | if (debug_no_list_hash) |
---|
1182 | return hash_tree_chain (value, NULL_TREE); |
---|
1183 | |
---|
1184 | for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) |
---|
1185 | if (h->hashcode == hashcode |
---|
1186 | && TREE_VIA_VIRTUAL (h->list) == 0 |
---|
1187 | && TREE_VIA_PUBLIC (h->list) == 0 |
---|
1188 | && TREE_VIA_PROTECTED (h->list) == 0 |
---|
1189 | && TREE_PURPOSE (h->list) == 0 |
---|
1190 | && TREE_VALUE (h->list) == value) |
---|
1191 | { |
---|
1192 | my_friendly_assert (TREE_TYPE (h->list) == 0, 303); |
---|
1193 | my_friendly_assert (TREE_CHAIN (h->list) == 0, 304); |
---|
1194 | return h->list; |
---|
1195 | } |
---|
1196 | |
---|
1197 | ambient_obstack = current_obstack; |
---|
1198 | current_obstack = &class_obstack; |
---|
1199 | list = build_tree_list (NULL_TREE, value); |
---|
1200 | list_hash_add (hashcode, list); |
---|
1201 | current_obstack = ambient_obstack; |
---|
1202 | return list; |
---|
1203 | } |
---|
1204 | |
---|
1205 | /* Build an association between TYPE and some parameters: |
---|
1206 | |
---|
1207 | OFFSET is the offset added to `this' to convert it to a pointer |
---|
1208 | of type `TYPE *' |
---|
1209 | |
---|
1210 | BINFO is the base binfo to use, if we are deriving from one. This |
---|
1211 | is necessary, as we want specialized parent binfos from base |
---|
1212 | classes, so that the VTABLE_NAMEs of bases are for the most derived |
---|
1213 | type, instead of of the simple type. |
---|
1214 | |
---|
1215 | VTABLE is the virtual function table with which to initialize |
---|
1216 | sub-objects of type TYPE. |
---|
1217 | |
---|
1218 | VIRTUALS are the virtual functions sitting in VTABLE. |
---|
1219 | |
---|
1220 | CHAIN are more associations we must retain. */ |
---|
1221 | |
---|
1222 | tree |
---|
1223 | make_binfo (offset, binfo, vtable, virtuals, chain) |
---|
1224 | tree offset, binfo; |
---|
1225 | tree vtable, virtuals; |
---|
1226 | tree chain; |
---|
1227 | { |
---|
1228 | tree new_binfo = make_tree_vec (6); |
---|
1229 | tree type; |
---|
1230 | |
---|
1231 | if (TREE_CODE (binfo) == TREE_VEC) |
---|
1232 | type = BINFO_TYPE (binfo); |
---|
1233 | else |
---|
1234 | { |
---|
1235 | type = binfo; |
---|
1236 | binfo = TYPE_BINFO (binfo); |
---|
1237 | } |
---|
1238 | |
---|
1239 | TREE_CHAIN (new_binfo) = chain; |
---|
1240 | if (chain) |
---|
1241 | TREE_USED (new_binfo) = TREE_USED (chain); |
---|
1242 | |
---|
1243 | TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type); |
---|
1244 | BINFO_OFFSET (new_binfo) = offset; |
---|
1245 | BINFO_VTABLE (new_binfo) = vtable; |
---|
1246 | BINFO_VIRTUALS (new_binfo) = virtuals; |
---|
1247 | BINFO_VPTR_FIELD (new_binfo) = NULL_TREE; |
---|
1248 | |
---|
1249 | if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE) |
---|
1250 | BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo)); |
---|
1251 | return new_binfo; |
---|
1252 | } |
---|
1253 | |
---|
1254 | /* Return the binfo value for ELEM in TYPE. */ |
---|
1255 | |
---|
1256 | tree |
---|
1257 | binfo_value (elem, type) |
---|
1258 | tree elem; |
---|
1259 | tree type; |
---|
1260 | { |
---|
1261 | if (get_base_distance (elem, type, 0, (tree *)0) == -2) |
---|
1262 | compiler_error ("base class `%s' ambiguous in binfo_value", |
---|
1263 | TYPE_NAME_STRING (elem)); |
---|
1264 | if (elem == type) |
---|
1265 | return TYPE_BINFO (type); |
---|
1266 | if (TREE_CODE (elem) == RECORD_TYPE && TYPE_BINFO (elem) == type) |
---|
1267 | return type; |
---|
1268 | return get_binfo (elem, type, 0); |
---|
1269 | } |
---|
1270 | |
---|
1271 | tree |
---|
1272 | reverse_path (path) |
---|
1273 | tree path; |
---|
1274 | { |
---|
1275 | register tree prev = 0, tmp, next; |
---|
1276 | for (tmp = path; tmp; tmp = next) |
---|
1277 | { |
---|
1278 | next = BINFO_INHERITANCE_CHAIN (tmp); |
---|
1279 | BINFO_INHERITANCE_CHAIN (tmp) = prev; |
---|
1280 | prev = tmp; |
---|
1281 | } |
---|
1282 | return prev; |
---|
1283 | } |
---|
1284 | |
---|
1285 | tree |
---|
1286 | virtual_member (elem, list) |
---|
1287 | tree elem; |
---|
1288 | tree list; |
---|
1289 | { |
---|
1290 | tree t; |
---|
1291 | tree rval, nval; |
---|
1292 | |
---|
1293 | for (t = list; t; t = TREE_CHAIN (t)) |
---|
1294 | if (elem == BINFO_TYPE (t)) |
---|
1295 | return t; |
---|
1296 | rval = 0; |
---|
1297 | for (t = list; t; t = TREE_CHAIN (t)) |
---|
1298 | { |
---|
1299 | tree binfos = BINFO_BASETYPES (t); |
---|
1300 | int i; |
---|
1301 | |
---|
1302 | if (binfos != NULL_TREE) |
---|
1303 | for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) |
---|
1304 | { |
---|
1305 | nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i))); |
---|
1306 | if (nval) |
---|
1307 | { |
---|
1308 | if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) |
---|
1309 | my_friendly_abort (104); |
---|
1310 | rval = nval; |
---|
1311 | } |
---|
1312 | } |
---|
1313 | } |
---|
1314 | return rval; |
---|
1315 | } |
---|
1316 | |
---|
1317 | void |
---|
1318 | debug_binfo (elem) |
---|
1319 | tree elem; |
---|
1320 | { |
---|
1321 | unsigned HOST_WIDE_INT n; |
---|
1322 | tree virtuals; |
---|
1323 | |
---|
1324 | fprintf (stderr, "type \"%s\"; offset = %d\n", |
---|
1325 | TYPE_NAME_STRING (BINFO_TYPE (elem)), |
---|
1326 | TREE_INT_CST_LOW (BINFO_OFFSET (elem))); |
---|
1327 | fprintf (stderr, "vtable type:\n"); |
---|
1328 | debug_tree (BINFO_TYPE (elem)); |
---|
1329 | if (BINFO_VTABLE (elem)) |
---|
1330 | fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); |
---|
1331 | else |
---|
1332 | fprintf (stderr, "no vtable decl yet\n"); |
---|
1333 | fprintf (stderr, "virtuals:\n"); |
---|
1334 | virtuals = BINFO_VIRTUALS (elem); |
---|
1335 | |
---|
1336 | n = skip_rtti_stuff (&virtuals); |
---|
1337 | |
---|
1338 | while (virtuals) |
---|
1339 | { |
---|
1340 | tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); |
---|
1341 | fprintf (stderr, "%s [%d =? %d]\n", |
---|
1342 | IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), |
---|
1343 | n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); |
---|
1344 | ++n; |
---|
1345 | virtuals = TREE_CHAIN (virtuals); |
---|
1346 | } |
---|
1347 | } |
---|
1348 | |
---|
1349 | /* Return the length of a chain of nodes chained through DECL_CHAIN. |
---|
1350 | We expect a null pointer to mark the end of the chain. |
---|
1351 | This is the Lisp primitive `length'. */ |
---|
1352 | |
---|
1353 | int |
---|
1354 | decl_list_length (t) |
---|
1355 | tree t; |
---|
1356 | { |
---|
1357 | register tree tail; |
---|
1358 | register int len = 0; |
---|
1359 | |
---|
1360 | my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL |
---|
1361 | || TREE_CODE (t) == TEMPLATE_DECL, 300); |
---|
1362 | for (tail = t; tail; tail = DECL_CHAIN (tail)) |
---|
1363 | len++; |
---|
1364 | |
---|
1365 | return len; |
---|
1366 | } |
---|
1367 | |
---|
1368 | int |
---|
1369 | count_functions (t) |
---|
1370 | tree t; |
---|
1371 | { |
---|
1372 | if (TREE_CODE (t) == FUNCTION_DECL) |
---|
1373 | return 1; |
---|
1374 | else if (TREE_CODE (t) == TREE_LIST) |
---|
1375 | return decl_list_length (TREE_VALUE (t)); |
---|
1376 | |
---|
1377 | my_friendly_abort (359); |
---|
1378 | return 0; |
---|
1379 | } |
---|
1380 | |
---|
1381 | /* Like value_member, but for DECL_CHAINs. */ |
---|
1382 | tree |
---|
1383 | decl_value_member (elem, list) |
---|
1384 | tree elem, list; |
---|
1385 | { |
---|
1386 | while (list) |
---|
1387 | { |
---|
1388 | if (elem == list) |
---|
1389 | return list; |
---|
1390 | list = DECL_CHAIN (list); |
---|
1391 | } |
---|
1392 | return NULL_TREE; |
---|
1393 | } |
---|
1394 | |
---|
1395 | int |
---|
1396 | is_overloaded_fn (x) |
---|
1397 | tree x; |
---|
1398 | { |
---|
1399 | if (TREE_CODE (x) == FUNCTION_DECL) |
---|
1400 | return 1; |
---|
1401 | |
---|
1402 | if (TREE_CODE (x) == TREE_LIST |
---|
1403 | && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL |
---|
1404 | || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL)) |
---|
1405 | return 1; |
---|
1406 | |
---|
1407 | return 0; |
---|
1408 | } |
---|
1409 | |
---|
1410 | int |
---|
1411 | really_overloaded_fn (x) |
---|
1412 | tree x; |
---|
1413 | { |
---|
1414 | if (TREE_CODE (x) == TREE_LIST |
---|
1415 | && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL |
---|
1416 | || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL)) |
---|
1417 | return 1; |
---|
1418 | |
---|
1419 | return 0; |
---|
1420 | } |
---|
1421 | |
---|
1422 | tree |
---|
1423 | get_first_fn (from) |
---|
1424 | tree from; |
---|
1425 | { |
---|
1426 | if (TREE_CODE (from) == FUNCTION_DECL) |
---|
1427 | return from; |
---|
1428 | |
---|
1429 | my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9); |
---|
1430 | |
---|
1431 | return TREE_VALUE (from); |
---|
1432 | } |
---|
1433 | |
---|
1434 | tree |
---|
1435 | fnaddr_from_vtable_entry (entry) |
---|
1436 | tree entry; |
---|
1437 | { |
---|
1438 | if (flag_vtable_thunks) |
---|
1439 | { |
---|
1440 | tree func = entry; |
---|
1441 | if (TREE_CODE (func) == ADDR_EXPR) |
---|
1442 | func = TREE_OPERAND (func, 0); |
---|
1443 | if (TREE_CODE (func) == THUNK_DECL) |
---|
1444 | return DECL_INITIAL (func); |
---|
1445 | else |
---|
1446 | return entry; |
---|
1447 | } |
---|
1448 | else |
---|
1449 | return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))); |
---|
1450 | } |
---|
1451 | |
---|
1452 | void |
---|
1453 | set_fnaddr_from_vtable_entry (entry, value) |
---|
1454 | tree entry, value; |
---|
1455 | { |
---|
1456 | if (flag_vtable_thunks) |
---|
1457 | abort (); |
---|
1458 | else |
---|
1459 | TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value; |
---|
1460 | } |
---|
1461 | |
---|
1462 | tree |
---|
1463 | function_arg_chain (t) |
---|
1464 | tree t; |
---|
1465 | { |
---|
1466 | return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t))); |
---|
1467 | } |
---|
1468 | |
---|
1469 | int |
---|
1470 | promotes_to_aggr_type (t, code) |
---|
1471 | tree t; |
---|
1472 | enum tree_code code; |
---|
1473 | { |
---|
1474 | if (TREE_CODE (t) == code) |
---|
1475 | t = TREE_TYPE (t); |
---|
1476 | return IS_AGGR_TYPE (t); |
---|
1477 | } |
---|
1478 | |
---|
1479 | int |
---|
1480 | is_aggr_type_2 (t1, t2) |
---|
1481 | tree t1, t2; |
---|
1482 | { |
---|
1483 | if (TREE_CODE (t1) != TREE_CODE (t2)) |
---|
1484 | return 0; |
---|
1485 | return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2); |
---|
1486 | } |
---|
1487 | |
---|
1488 | /* Give message using types TYPE1 and TYPE2 as arguments. |
---|
1489 | PFN is the function which will print the message; |
---|
1490 | S is the format string for PFN to use. */ |
---|
1491 | void |
---|
1492 | message_2_types (pfn, s, type1, type2) |
---|
1493 | void (*pfn) (); |
---|
1494 | char *s; |
---|
1495 | tree type1, type2; |
---|
1496 | { |
---|
1497 | tree name1 = TYPE_NAME (type1); |
---|
1498 | tree name2 = TYPE_NAME (type2); |
---|
1499 | if (TREE_CODE (name1) == TYPE_DECL) |
---|
1500 | name1 = DECL_NAME (name1); |
---|
1501 | if (TREE_CODE (name2) == TYPE_DECL) |
---|
1502 | name2 = DECL_NAME (name2); |
---|
1503 | (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2)); |
---|
1504 | } |
---|
1505 | |
---|
1506 | #define PRINT_RING_SIZE 4 |
---|
1507 | |
---|
1508 | char * |
---|
1509 | lang_printable_name (decl) |
---|
1510 | tree decl; |
---|
1511 | { |
---|
1512 | static tree decl_ring[PRINT_RING_SIZE]; |
---|
1513 | static char *print_ring[PRINT_RING_SIZE]; |
---|
1514 | static int ring_counter; |
---|
1515 | int i; |
---|
1516 | |
---|
1517 | /* Only cache functions. */ |
---|
1518 | if (TREE_CODE (decl) != FUNCTION_DECL |
---|
1519 | || DECL_LANG_SPECIFIC (decl) == 0) |
---|
1520 | return decl_as_string (decl, 1); |
---|
1521 | |
---|
1522 | /* See if this print name is lying around. */ |
---|
1523 | for (i = 0; i < PRINT_RING_SIZE; i++) |
---|
1524 | if (decl_ring[i] == decl) |
---|
1525 | /* yes, so return it. */ |
---|
1526 | return print_ring[i]; |
---|
1527 | |
---|
1528 | if (++ring_counter == PRINT_RING_SIZE) |
---|
1529 | ring_counter = 0; |
---|
1530 | |
---|
1531 | if (current_function_decl != NULL_TREE) |
---|
1532 | { |
---|
1533 | if (decl_ring[ring_counter] == current_function_decl) |
---|
1534 | ring_counter += 1; |
---|
1535 | if (ring_counter == PRINT_RING_SIZE) |
---|
1536 | ring_counter = 0; |
---|
1537 | if (decl_ring[ring_counter] == current_function_decl) |
---|
1538 | my_friendly_abort (106); |
---|
1539 | } |
---|
1540 | |
---|
1541 | if (print_ring[ring_counter]) |
---|
1542 | free (print_ring[ring_counter]); |
---|
1543 | |
---|
1544 | { |
---|
1545 | int print_ret_type_p |
---|
1546 | = (!DECL_CONSTRUCTOR_P (decl) |
---|
1547 | && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); |
---|
1548 | |
---|
1549 | char *name = (char *)decl_as_string (decl, print_ret_type_p); |
---|
1550 | print_ring[ring_counter] = (char *)malloc (strlen (name) + 1); |
---|
1551 | strcpy (print_ring[ring_counter], name); |
---|
1552 | decl_ring[ring_counter] = decl; |
---|
1553 | } |
---|
1554 | return print_ring[ring_counter]; |
---|
1555 | } |
---|
1556 | |
---|
1557 | /* Comparison function for sorting identifiers in RAISES lists. |
---|
1558 | Note that because IDENTIFIER_NODEs are unique, we can sort |
---|
1559 | them by address, saving an indirection. */ |
---|
1560 | static int |
---|
1561 | id_cmp (p1, p2) |
---|
1562 | tree *p1, *p2; |
---|
1563 | { |
---|
1564 | return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2); |
---|
1565 | } |
---|
1566 | |
---|
1567 | /* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions |
---|
1568 | listed in RAISES. */ |
---|
1569 | tree |
---|
1570 | build_exception_variant (type, raises) |
---|
1571 | tree type; |
---|
1572 | tree raises; |
---|
1573 | { |
---|
1574 | int i; |
---|
1575 | tree v = TYPE_MAIN_VARIANT (type); |
---|
1576 | tree t, t2, cname; |
---|
1577 | tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree)); |
---|
1578 | int constp = TYPE_READONLY (type); |
---|
1579 | int volatilep = TYPE_VOLATILE (type); |
---|
1580 | |
---|
1581 | for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v)) |
---|
1582 | { |
---|
1583 | if (TYPE_READONLY (v) != constp |
---|
1584 | || TYPE_VOLATILE (v) != volatilep) |
---|
1585 | continue; |
---|
1586 | |
---|
1587 | /* @@ This should do set equality, not exact match. */ |
---|
1588 | if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises)) |
---|
1589 | /* List of exceptions raised matches previously found list. |
---|
1590 | |
---|
1591 | @@ Nice to free up storage used in consing up the |
---|
1592 | @@ list of exceptions raised. */ |
---|
1593 | return v; |
---|
1594 | } |
---|
1595 | |
---|
1596 | /* Need to build a new variant. */ |
---|
1597 | v = copy_node (type); |
---|
1598 | TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type); |
---|
1599 | TYPE_NEXT_VARIANT (type) = v; |
---|
1600 | if (raises && ! TREE_PERMANENT (raises)) |
---|
1601 | { |
---|
1602 | push_obstacks_nochange (); |
---|
1603 | end_temporary_allocation (); |
---|
1604 | raises = copy_list (raises); |
---|
1605 | pop_obstacks (); |
---|
1606 | } |
---|
1607 | TYPE_RAISES_EXCEPTIONS (v) = raises; |
---|
1608 | return v; |
---|
1609 | } |
---|
1610 | |
---|
1611 | /* Subroutine of copy_to_permanent |
---|
1612 | |
---|
1613 | Assuming T is a node build bottom-up, make it all exist on |
---|
1614 | permanent obstack, if it is not permanent already. */ |
---|
1615 | |
---|
1616 | tree |
---|
1617 | mapcar (t, func) |
---|
1618 | tree t; |
---|
1619 | tree (*func)(); |
---|
1620 | { |
---|
1621 | enum tree_code code; |
---|
1622 | tree tmp; |
---|
1623 | |
---|
1624 | if (t == NULL_TREE) |
---|
1625 | return t; |
---|
1626 | |
---|
1627 | if (tmp = func (t), tmp != NULL_TREE) |
---|
1628 | return tmp; |
---|
1629 | |
---|
1630 | switch (code = TREE_CODE (t)) |
---|
1631 | { |
---|
1632 | case ERROR_MARK: |
---|
1633 | return error_mark_node; |
---|
1634 | |
---|
1635 | case VAR_DECL: |
---|
1636 | case FUNCTION_DECL: |
---|
1637 | case CONST_DECL: |
---|
1638 | break; |
---|
1639 | |
---|
1640 | case PARM_DECL: |
---|
1641 | { |
---|
1642 | tree chain = TREE_CHAIN (t); |
---|
1643 | t = copy_node (t); |
---|
1644 | TREE_CHAIN (t) = mapcar (chain, func); |
---|
1645 | TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); |
---|
1646 | DECL_INITIAL (t) = mapcar (DECL_INITIAL (t), func); |
---|
1647 | DECL_SIZE (t) = mapcar (DECL_SIZE (t), func); |
---|
1648 | return t; |
---|
1649 | } |
---|
1650 | |
---|
1651 | case TREE_LIST: |
---|
1652 | { |
---|
1653 | tree chain = TREE_CHAIN (t); |
---|
1654 | t = copy_node (t); |
---|
1655 | TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func); |
---|
1656 | TREE_VALUE (t) = mapcar (TREE_VALUE (t), func); |
---|
1657 | TREE_CHAIN (t) = mapcar (chain, func); |
---|
1658 | return t; |
---|
1659 | } |
---|
1660 | |
---|
1661 | case TREE_VEC: |
---|
1662 | { |
---|
1663 | int len = TREE_VEC_LENGTH (t); |
---|
1664 | |
---|
1665 | t = copy_node (t); |
---|
1666 | while (len--) |
---|
1667 | TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func); |
---|
1668 | return t; |
---|
1669 | } |
---|
1670 | |
---|
1671 | case INTEGER_CST: |
---|
1672 | case REAL_CST: |
---|
1673 | case STRING_CST: |
---|
1674 | return copy_node (t); |
---|
1675 | |
---|
1676 | case COND_EXPR: |
---|
1677 | case TARGET_EXPR: |
---|
1678 | case NEW_EXPR: |
---|
1679 | t = copy_node (t); |
---|
1680 | TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); |
---|
1681 | TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); |
---|
1682 | TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); |
---|
1683 | return t; |
---|
1684 | |
---|
1685 | case SAVE_EXPR: |
---|
1686 | t = copy_node (t); |
---|
1687 | TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); |
---|
1688 | return t; |
---|
1689 | |
---|
1690 | case MODIFY_EXPR: |
---|
1691 | case PLUS_EXPR: |
---|
1692 | case MINUS_EXPR: |
---|
1693 | case MULT_EXPR: |
---|
1694 | case TRUNC_DIV_EXPR: |
---|
1695 | case TRUNC_MOD_EXPR: |
---|
1696 | case MIN_EXPR: |
---|
1697 | case MAX_EXPR: |
---|
1698 | case LSHIFT_EXPR: |
---|
1699 | case RSHIFT_EXPR: |
---|
1700 | case BIT_IOR_EXPR: |
---|
1701 | case BIT_XOR_EXPR: |
---|
1702 | case BIT_AND_EXPR: |
---|
1703 | case BIT_ANDTC_EXPR: |
---|
1704 | case TRUTH_ANDIF_EXPR: |
---|
1705 | case TRUTH_ORIF_EXPR: |
---|
1706 | case LT_EXPR: |
---|
1707 | case LE_EXPR: |
---|
1708 | case GT_EXPR: |
---|
1709 | case GE_EXPR: |
---|
1710 | case EQ_EXPR: |
---|
1711 | case NE_EXPR: |
---|
1712 | case CEIL_DIV_EXPR: |
---|
1713 | case FLOOR_DIV_EXPR: |
---|
1714 | case ROUND_DIV_EXPR: |
---|
1715 | case CEIL_MOD_EXPR: |
---|
1716 | case FLOOR_MOD_EXPR: |
---|
1717 | case ROUND_MOD_EXPR: |
---|
1718 | case COMPOUND_EXPR: |
---|
1719 | case PREDECREMENT_EXPR: |
---|
1720 | case PREINCREMENT_EXPR: |
---|
1721 | case POSTDECREMENT_EXPR: |
---|
1722 | case POSTINCREMENT_EXPR: |
---|
1723 | case CALL_EXPR: |
---|
1724 | t = copy_node (t); |
---|
1725 | TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); |
---|
1726 | TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); |
---|
1727 | return t; |
---|
1728 | |
---|
1729 | case CONVERT_EXPR: |
---|
1730 | case ADDR_EXPR: |
---|
1731 | case INDIRECT_REF: |
---|
1732 | case NEGATE_EXPR: |
---|
1733 | case BIT_NOT_EXPR: |
---|
1734 | case TRUTH_NOT_EXPR: |
---|
1735 | case NOP_EXPR: |
---|
1736 | case COMPONENT_REF: |
---|
1737 | t = copy_node (t); |
---|
1738 | TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); |
---|
1739 | return t; |
---|
1740 | |
---|
1741 | case POINTER_TYPE: |
---|
1742 | return build_pointer_type (mapcar (TREE_TYPE (t), func)); |
---|
1743 | case REFERENCE_TYPE: |
---|
1744 | return build_reference_type (mapcar (TREE_TYPE (t), func)); |
---|
1745 | case FUNCTION_TYPE: |
---|
1746 | return build_function_type (mapcar (TREE_TYPE (t), func), |
---|
1747 | mapcar (TYPE_ARG_TYPES (t), func)); |
---|
1748 | case ARRAY_TYPE: |
---|
1749 | return build_array_type (mapcar (TREE_TYPE (t), func), |
---|
1750 | mapcar (TYPE_DOMAIN (t), func)); |
---|
1751 | case INTEGER_TYPE: |
---|
1752 | return build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); |
---|
1753 | |
---|
1754 | case OFFSET_TYPE: |
---|
1755 | return build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func), |
---|
1756 | mapcar (TREE_TYPE (t), func)); |
---|
1757 | case METHOD_TYPE: |
---|
1758 | return build_method_type |
---|
1759 | (mapcar (TYPE_METHOD_BASETYPE (t), func), |
---|
1760 | build_function_type |
---|
1761 | (mapcar (TREE_TYPE (t), func), |
---|
1762 | mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func))); |
---|
1763 | |
---|
1764 | case RECORD_TYPE: |
---|
1765 | if (TYPE_PTRMEMFUNC_P (t)) |
---|
1766 | return build_ptrmemfunc_type |
---|
1767 | (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); |
---|
1768 | /* else fall through */ |
---|
1769 | |
---|
1770 | /* This list is incomplete, but should suffice for now. |
---|
1771 | It is very important that `sorry' does not call |
---|
1772 | `report_error_function'. That could cause an infinite loop. */ |
---|
1773 | default: |
---|
1774 | sorry ("initializer contains unrecognized tree code"); |
---|
1775 | return error_mark_node; |
---|
1776 | |
---|
1777 | } |
---|
1778 | my_friendly_abort (107); |
---|
1779 | /* NOTREACHED */ |
---|
1780 | return NULL_TREE; |
---|
1781 | } |
---|
1782 | |
---|
1783 | static tree |
---|
1784 | perm_manip (t) |
---|
1785 | tree t; |
---|
1786 | { |
---|
1787 | if (TREE_PERMANENT (t)) |
---|
1788 | return t; |
---|
1789 | return NULL_TREE; |
---|
1790 | } |
---|
1791 | |
---|
1792 | /* Assuming T is a node built bottom-up, make it all exist on |
---|
1793 | permanent obstack, if it is not permanent already. */ |
---|
1794 | tree |
---|
1795 | copy_to_permanent (t) |
---|
1796 | tree t; |
---|
1797 | { |
---|
1798 | register struct obstack *ambient_obstack = current_obstack; |
---|
1799 | register struct obstack *ambient_saveable_obstack = saveable_obstack; |
---|
1800 | int resume; |
---|
1801 | |
---|
1802 | if (t == NULL_TREE || TREE_PERMANENT (t)) |
---|
1803 | return t; |
---|
1804 | |
---|
1805 | saveable_obstack = &permanent_obstack; |
---|
1806 | current_obstack = saveable_obstack; |
---|
1807 | resume = suspend_momentary (); |
---|
1808 | |
---|
1809 | t = mapcar (t, perm_manip); |
---|
1810 | |
---|
1811 | resume_momentary (resume); |
---|
1812 | current_obstack = ambient_obstack; |
---|
1813 | saveable_obstack = ambient_saveable_obstack; |
---|
1814 | |
---|
1815 | return t; |
---|
1816 | } |
---|
1817 | |
---|
1818 | void |
---|
1819 | print_lang_statistics () |
---|
1820 | { |
---|
1821 | extern struct obstack maybepermanent_obstack; |
---|
1822 | print_obstack_statistics ("class_obstack", &class_obstack); |
---|
1823 | print_obstack_statistics ("permanent_obstack", &permanent_obstack); |
---|
1824 | print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack); |
---|
1825 | print_search_statistics (); |
---|
1826 | print_class_statistics (); |
---|
1827 | } |
---|
1828 | |
---|
1829 | /* This is used by the `assert' macro. It is provided in libgcc.a, |
---|
1830 | which `cc' doesn't know how to link. Note that the C++ front-end |
---|
1831 | no longer actually uses the `assert' macro (instead, it calls |
---|
1832 | my_friendly_assert). But all of the back-end files still need this. */ |
---|
1833 | void |
---|
1834 | __eprintf (string, expression, line, filename) |
---|
1835 | #ifdef __STDC__ |
---|
1836 | const char *string; |
---|
1837 | const char *expression; |
---|
1838 | unsigned line; |
---|
1839 | const char *filename; |
---|
1840 | #else |
---|
1841 | char *string; |
---|
1842 | char *expression; |
---|
1843 | unsigned line; |
---|
1844 | char *filename; |
---|
1845 | #endif |
---|
1846 | { |
---|
1847 | fprintf (stderr, string, expression, line, filename); |
---|
1848 | fflush (stderr); |
---|
1849 | abort (); |
---|
1850 | } |
---|
1851 | |
---|
1852 | /* Return, as an INTEGER_CST node, the number of elements for |
---|
1853 | TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */ |
---|
1854 | |
---|
1855 | tree |
---|
1856 | array_type_nelts_top (type) |
---|
1857 | tree type; |
---|
1858 | { |
---|
1859 | return fold (build (PLUS_EXPR, sizetype, |
---|
1860 | array_type_nelts (type), |
---|
1861 | integer_one_node)); |
---|
1862 | } |
---|
1863 | |
---|
1864 | /* Return, as an INTEGER_CST node, the number of elements for |
---|
1865 | TYPE (which is an ARRAY_TYPE). This one is a recursive count of all |
---|
1866 | ARRAY_TYPEs that are clumped together. */ |
---|
1867 | |
---|
1868 | tree |
---|
1869 | array_type_nelts_total (type) |
---|
1870 | tree type; |
---|
1871 | { |
---|
1872 | tree sz = array_type_nelts_top (type); |
---|
1873 | type = TREE_TYPE (type); |
---|
1874 | while (TREE_CODE (type) == ARRAY_TYPE) |
---|
1875 | { |
---|
1876 | tree n = array_type_nelts_top (type); |
---|
1877 | sz = fold (build (MULT_EXPR, sizetype, sz, n)); |
---|
1878 | type = TREE_TYPE (type); |
---|
1879 | } |
---|
1880 | return sz; |
---|
1881 | } |
---|
1882 | |
---|
1883 | static |
---|
1884 | tree |
---|
1885 | bot_manip (t) |
---|
1886 | tree t; |
---|
1887 | { |
---|
1888 | if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t)) |
---|
1889 | return t; |
---|
1890 | else if (TREE_CODE (t) == TARGET_EXPR) |
---|
1891 | return build_cplus_new (TREE_TYPE (t), |
---|
1892 | break_out_target_exprs (TREE_OPERAND (t, 1)), 0); |
---|
1893 | return NULL_TREE; |
---|
1894 | } |
---|
1895 | |
---|
1896 | /* Actually, we'll just clean out the target exprs for the moment. */ |
---|
1897 | tree |
---|
1898 | break_out_target_exprs (t) |
---|
1899 | tree t; |
---|
1900 | { |
---|
1901 | return mapcar (t, bot_manip); |
---|
1902 | } |
---|
1903 | |
---|
1904 | tree |
---|
1905 | unsave_expr (expr) |
---|
1906 | tree expr; |
---|
1907 | { |
---|
1908 | tree t; |
---|
1909 | |
---|
1910 | t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr); |
---|
1911 | TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr); |
---|
1912 | return t; |
---|
1913 | } |
---|
1914 | |
---|
1915 | /* Modify a tree in place so that all the evaluate only once things |
---|
1916 | are cleared out. Return the EXPR given. */ |
---|
1917 | tree |
---|
1918 | unsave_expr_now (expr) |
---|
1919 | tree expr; |
---|
1920 | { |
---|
1921 | enum tree_code code; |
---|
1922 | register int i; |
---|
1923 | |
---|
1924 | if (expr == NULL_TREE) |
---|
1925 | return expr; |
---|
1926 | |
---|
1927 | code = TREE_CODE (expr); |
---|
1928 | switch (code) |
---|
1929 | { |
---|
1930 | case SAVE_EXPR: |
---|
1931 | SAVE_EXPR_RTL (expr) = NULL_RTX; |
---|
1932 | break; |
---|
1933 | |
---|
1934 | case TARGET_EXPR: |
---|
1935 | sorry ("TARGET_EXPR reused inside UNSAVE_EXPR"); |
---|
1936 | break; |
---|
1937 | |
---|
1938 | case RTL_EXPR: |
---|
1939 | warning ("RTL_EXPR reused inside UNSAVE_EXPR"); |
---|
1940 | RTL_EXPR_SEQUENCE (expr) = NULL_RTX; |
---|
1941 | break; |
---|
1942 | |
---|
1943 | case CALL_EXPR: |
---|
1944 | CALL_EXPR_RTL (expr) = NULL_RTX; |
---|
1945 | if (TREE_OPERAND (expr, 1) |
---|
1946 | && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST) |
---|
1947 | { |
---|
1948 | tree exp = TREE_OPERAND (expr, 1); |
---|
1949 | while (exp) |
---|
1950 | { |
---|
1951 | unsave_expr_now (TREE_VALUE (exp)); |
---|
1952 | exp = TREE_CHAIN (exp); |
---|
1953 | } |
---|
1954 | } |
---|
1955 | break; |
---|
1956 | |
---|
1957 | case WITH_CLEANUP_EXPR: |
---|
1958 | warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR"); |
---|
1959 | RTL_EXPR_RTL (expr) = NULL_RTX; |
---|
1960 | break; |
---|
1961 | } |
---|
1962 | |
---|
1963 | switch (TREE_CODE_CLASS (code)) |
---|
1964 | { |
---|
1965 | case 'c': /* a constant */ |
---|
1966 | case 't': /* a type node */ |
---|
1967 | case 'x': /* something random, like an identifier or an ERROR_MARK. */ |
---|
1968 | case 'd': /* A decl node */ |
---|
1969 | case 'b': /* A block node */ |
---|
1970 | return expr; |
---|
1971 | |
---|
1972 | case 'e': /* an expression */ |
---|
1973 | case 'r': /* a reference */ |
---|
1974 | case 's': /* an expression with side effects */ |
---|
1975 | case '<': /* a comparison expression */ |
---|
1976 | case '2': /* a binary arithmetic expression */ |
---|
1977 | case '1': /* a unary arithmetic expression */ |
---|
1978 | for (i = tree_code_length[(int) code] - 1; i >= 0; i--) |
---|
1979 | unsave_expr_now (TREE_OPERAND (expr, i)); |
---|
1980 | return expr; |
---|
1981 | |
---|
1982 | default: |
---|
1983 | my_friendly_abort (999); |
---|
1984 | } |
---|
1985 | } |
---|
1986 | |
---|
1987 | /* Since cleanup may have SAVE_EXPRs in it, we protect it with an |
---|
1988 | UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups |
---|
1989 | by itself. */ |
---|
1990 | int |
---|
1991 | cp_expand_decl_cleanup (decl, cleanup) |
---|
1992 | tree decl, cleanup; |
---|
1993 | { |
---|
1994 | return expand_decl_cleanup (decl, unsave_expr (cleanup)); |
---|
1995 | } |
---|