]> gcc.gnu.org Git - gcc.git/blob - gcc/cp/rtti.c
91th Cygnus<->FSF quick merge
[gcc.git] / gcc / cp / rtti.c
1 /* RunTime Type Identification
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
3 Mostly written by Jason Merrill (jason@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
23 #include "config.h"
24 #include "tree.h"
25 #include "cp-tree.h"
26 #include "flags.h"
27 #include "output.h"
28 #include "assert.h"
29
30 #ifndef INT_TYPE_SIZE
31 #define INT_TYPE_SIZE BITS_PER_WORD
32 #endif
33
34 extern tree define_function ();
35 extern tree build_t_desc_overload ();
36 extern struct obstack *permanent_obstack;
37
38 tree type_info_type_node;
39 tree tinfo_fn_id;
40 tree tinfo_fn_type;
41 \f
42 void
43 init_rtti_processing ()
44 {
45 type_info_type_node = xref_tag
46 (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
47 tinfo_fn_id = get_identifier ("__tf");
48 tinfo_fn_type = build_function_type
49 (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
50 void_list_node);
51 }
52
53 /* Given a pointer to an object with at least one virtual table
54 pointer somewhere, return a pointer to a possible sub-object that
55 has a virtual table pointer in it that is the vtable parent for
56 that sub-object. */
57
58 static tree
59 build_headof_sub (exp)
60 tree exp;
61 {
62 tree type = TREE_TYPE (TREE_TYPE (exp));
63 tree basetype = CLASSTYPE_RTTI (type);
64 tree binfo = get_binfo (basetype, type, 0);
65
66 exp = convert_pointer_to_real (binfo, exp);
67 return exp;
68 }
69
70 /* Given the expression EXP of type `class *', return the head of the
71 object pointed to by EXP with type cv void*, if the class has any
72 virtual functions (TYPE_VIRTUAL_P), else just return the
73 expression. */
74
75 static tree
76 build_headof (exp)
77 tree exp;
78 {
79 tree type = TREE_TYPE (exp);
80 tree aref;
81 tree offset;
82
83 if (TREE_CODE (type) != POINTER_TYPE)
84 {
85 error ("`headof' applied to non-pointer type");
86 return error_mark_node;
87 }
88 type = TREE_TYPE (type);
89
90 if (!TYPE_VIRTUAL_P (type))
91 return exp;
92
93 /* If we don't have rtti stuff, get to a sub-object that does. */
94 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
95 exp = build_headof_sub (exp);
96
97 /* We use this a couple of times below, protect it. */
98 exp = save_expr (exp);
99
100 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
101
102 if (flag_vtable_thunks)
103 offset = aref;
104 else
105 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
106
107 type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
108 TREE_THIS_VOLATILE (exp));
109 return build (PLUS_EXPR, type, exp,
110 convert (ptrdiff_type_node, offset));
111 }
112
113 /* Build a call to a generic entry point taking and returning void. */
114
115 static tree
116 call_void_fn (name)
117 char *name;
118 {
119 tree d = get_identifier (name);
120 tree type;
121
122 if (IDENTIFIER_GLOBAL_VALUE (d))
123 d = IDENTIFIER_GLOBAL_VALUE (d);
124 else
125 {
126 push_obstacks (&permanent_obstack, &permanent_obstack);
127
128 type = build_function_type (void_type_node, void_list_node);
129 d = build_lang_decl (FUNCTION_DECL, d, type);
130 DECL_EXTERNAL (d) = 1;
131 TREE_PUBLIC (d) = 1;
132 DECL_ARTIFICIAL (d) = 1;
133 pushdecl_top_level (d);
134 make_function_rtl (d);
135 assemble_external (d);
136
137 pop_obstacks ();
138 }
139
140 return build_call (d, void_type_node, NULL_TREE);
141 }
142
143 /* Get a bad_cast node for the program to throw...
144
145 See libstdc++/exception.cc for __throw_bad_cast */
146
147 static tree
148 throw_bad_cast ()
149 {
150 return call_void_fn ("__throw_bad_cast");
151 }
152
153 static tree
154 throw_bad_typeid ()
155 {
156 return call_void_fn ("__throw_bad_typeid");
157 }
158 \f
159 /* Return the type_info function associated with the expression EXP. If
160 EXP is a reference to a polymorphic class, return the dynamic type;
161 otherwise return the static type of the expression. */
162
163 tree
164 get_tinfo_fn_dynamic (exp)
165 tree exp;
166 {
167 tree type;
168
169 if (exp == error_mark_node)
170 return error_mark_node;
171
172 if (type_unknown_p (exp))
173 {
174 error ("typeid of overloaded function");
175 return error_mark_node;
176 }
177
178 type = TREE_TYPE (exp);
179
180 /* peel back references, so they match. */
181 if (TREE_CODE (type) == REFERENCE_TYPE)
182 type = TREE_TYPE (type);
183
184 /* Peel off cv qualifiers. */
185 type = TYPE_MAIN_VARIANT (type);
186
187 /* If exp is a reference to polymorphic type, get the real type_info. */
188 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
189 {
190 /* build reference to type_info from vtable. */
191 tree t;
192
193 if (! flag_rtti)
194 warning ("taking dynamic typeid of object without -frtti");
195
196 /* If we don't have rtti stuff, get to a sub-object that does. */
197 if (! CLASSTYPE_VFIELDS (type))
198 {
199 exp = build_unary_op (ADDR_EXPR, exp, 0);
200 exp = build_headof_sub (exp);
201 exp = build_indirect_ref (exp, NULL_PTR);
202 }
203
204 if (flag_vtable_thunks)
205 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
206 else
207 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
208 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
209 return t;
210 }
211
212 /* otherwise return the type_info for the static type of the expr. */
213 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
214 }
215
216 tree
217 build_typeid (exp)
218 tree exp;
219 {
220 exp = get_tinfo_fn_dynamic (exp);
221 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
222 return convert_from_reference (exp);
223 }
224
225 tree
226 build_x_typeid (exp)
227 tree exp;
228 {
229 tree cond = NULL_TREE;
230 tree type = TREE_TYPE (tinfo_fn_type);
231 int nonnull;
232
233 if (processing_template_decl)
234 return build_min_nt (TYPEID_EXPR, exp);
235
236 if (TREE_CODE (exp) == INDIRECT_REF
237 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
238 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
239 && ! resolves_to_fixed_type_p (exp, &nonnull)
240 && ! nonnull)
241 {
242 exp = stabilize_reference (exp);
243 cond = convert (boolean_type_node, TREE_OPERAND (exp, 0));
244 }
245
246 exp = get_tinfo_fn_dynamic (exp);
247
248 if (exp == error_mark_node)
249 return error_mark_node;
250
251 exp = build_call (exp, type, NULL_TREE);
252
253 if (cond)
254 {
255 tree bad = throw_bad_typeid ();
256
257 bad = build_compound_expr
258 (tree_cons (NULL_TREE, bad, build_tree_list
259 (NULL_TREE, convert (type, integer_zero_node))));
260 exp = build (COND_EXPR, type, cond, exp, bad);
261 }
262
263 return convert_from_reference (exp);
264 }
265
266 static tree
267 get_tinfo_var (type)
268 tree type;
269 {
270 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
271 tree tdecl, arrtype;
272 int size;
273
274 if (IDENTIFIER_GLOBAL_VALUE (tname))
275 return IDENTIFIER_GLOBAL_VALUE (tname);
276
277 /* Figure out how much space we need to allocate for the type_info object.
278 If our struct layout or the type_info classes are changed, this will
279 need to be modified. */
280 if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
281 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
282 else if (TREE_CODE (type) == POINTER_TYPE
283 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
284 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
285 size = 3 * POINTER_SIZE;
286 else if (IS_AGGR_TYPE (type))
287 {
288 if (CLASSTYPE_N_BASECLASSES (type) == 0)
289 size = 2 * POINTER_SIZE;
290 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
291 && (TREE_VIA_PUBLIC
292 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
293 size = 3 * POINTER_SIZE;
294 else
295 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
296 }
297 else
298 size = 2 * POINTER_SIZE;
299
300 push_obstacks (&permanent_obstack, &permanent_obstack);
301
302 /* The type for a character array of the appropriate size. */
303 arrtype = build_cplus_array_type
304 (unsigned_char_type_node,
305 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
306
307 tdecl = build_decl (VAR_DECL, tname, arrtype);
308 TREE_PUBLIC (tdecl) = 1;
309 DECL_EXTERNAL (tdecl) = 1;
310 DECL_ARTIFICIAL (tdecl) = 1;
311 pushdecl_top_level (tdecl);
312 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
313
314 pop_obstacks ();
315
316 return tdecl;
317 }
318
319 tree
320 get_tinfo_fn (type)
321 tree type;
322 {
323 tree name;
324 tree d;
325
326 if (TREE_CODE (type) == OFFSET_TYPE)
327 type = TREE_TYPE (type);
328 if (TREE_CODE (type) == METHOD_TYPE)
329 type = build_function_type (TREE_TYPE (type),
330 TREE_CHAIN (TYPE_ARG_TYPES (type)));
331
332 name = build_overload_with_type (tinfo_fn_id, type);
333
334 if (IDENTIFIER_GLOBAL_VALUE (name))
335 return IDENTIFIER_GLOBAL_VALUE (name);
336
337 push_obstacks (&permanent_obstack, &permanent_obstack);
338
339 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
340 DECL_EXTERNAL (d) = 1;
341 TREE_PUBLIC (d) = 1;
342 DECL_ARTIFICIAL (d) = 1;
343 DECL_NOT_REALLY_EXTERN (d) = 1;
344 DECL_MUTABLE_P (d) = 1;
345 TREE_TYPE (name) = copy_to_permanent (type);
346 pushdecl_top_level (d);
347 make_function_rtl (d);
348 assemble_external (d);
349 mark_inline_for_output (d);
350 if (at_eof)
351 import_export_decl (d);
352
353 pop_obstacks ();
354
355 return d;
356 }
357
358 static tree
359 get_typeid_1 (type)
360 tree type;
361 {
362 tree t = build_call
363 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
364 return convert_from_reference (t);
365 }
366
367 /* Return the type_info object for TYPE, creating it if necessary. */
368
369 tree
370 get_typeid (type)
371 tree type;
372 {
373 if (type == error_mark_node)
374 return error_mark_node;
375
376 if (processing_template_decl)
377 return build_min_nt (TYPEID_EXPR, type);
378
379 /* If the type of the type-id is a reference type, the result of the
380 typeid expression refers to a type_info object representing the
381 referenced type. */
382 if (TREE_CODE (type) == REFERENCE_TYPE)
383 type = TREE_TYPE (type);
384
385 /* The top-level cv-qualifiers of the lvalue expression or the type-id
386 that is the operand of typeid are always ignored. */
387 type = TYPE_MAIN_VARIANT (type);
388
389 return get_typeid_1 (type);
390 }
391
392 /* Check whether TEST is null before returning RESULT. If TEST is used in
393 RESULT, it must have previously had a save_expr applied to it. */
394
395 static tree
396 ifnonnull (test, result)
397 tree test, result;
398 {
399 return build (COND_EXPR, TREE_TYPE (result),
400 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
401 convert (TREE_TYPE (result), integer_zero_node),
402 result);
403 }
404
405 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
406 paper. */
407
408 tree
409 build_dynamic_cast (type, expr)
410 tree type, expr;
411 {
412 enum tree_code tc = TREE_CODE (type);
413 tree exprtype = TREE_TYPE (expr);
414 enum tree_code ec;
415 tree dcast_fn;
416
417 if (type == error_mark_node || expr == error_mark_node)
418 return error_mark_node;
419
420 if (processing_template_decl)
421 {
422 tree t = build_min (DYNAMIC_CAST_EXPR, type, expr);
423 return t;
424 }
425
426 assert (exprtype != NULL_TREE);
427 ec = TREE_CODE (exprtype);
428
429 switch (tc)
430 {
431 case POINTER_TYPE:
432 if (ec == REFERENCE_TYPE)
433 {
434 expr = convert_from_reference (expr);
435 exprtype = TREE_TYPE (expr);
436 ec = TREE_CODE (exprtype);
437 }
438 if (ec != POINTER_TYPE)
439 goto fail;
440 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
441 goto fail;
442 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
443 goto fail;
444 if (TREE_READONLY (TREE_TYPE (exprtype))
445 && ! TYPE_READONLY (TREE_TYPE (type)))
446 goto fail;
447 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
448 break;
449 /* else fall through */
450 case REFERENCE_TYPE:
451 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
452 goto fail;
453 if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
454 goto fail;
455 break;
456 /* else fall through */
457 default:
458 goto fail;
459 }
460
461 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
462 if (ec == RECORD_TYPE)
463 {
464 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
465 TREE_THIS_VOLATILE (expr));
466 exprtype = build_reference_type (exprtype);
467 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
468 LOOKUP_NORMAL, NULL_TREE);
469 ec = REFERENCE_TYPE;
470 }
471
472 if (tc == REFERENCE_TYPE)
473 {
474 if (ec != REFERENCE_TYPE)
475 goto fail;
476 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
477 goto fail;
478 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
479 goto fail;
480 if (TREE_READONLY (TREE_TYPE (exprtype))
481 && ! TYPE_READONLY (TREE_TYPE (type)))
482 goto fail;
483 }
484
485 /* If *type is an unambiguous accessible base class of *exprtype,
486 convert statically. */
487 {
488 int distance;
489 tree path;
490
491 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
492 &path);
493 if (distance >= 0)
494 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
495 }
496
497 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
498 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
499 {
500 tree expr1;
501 /* if TYPE is `void *', return pointer to complete object. */
502 if (tc == POINTER_TYPE
503 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
504 {
505 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
506 if (TREE_CODE (expr) == ADDR_EXPR
507 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
508 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
509 return build1 (NOP_EXPR, type, expr);
510
511 /* Since expr is used twice below, save it. */
512 expr = save_expr (expr);
513
514 expr1 = build_headof (expr);
515 if (TREE_TYPE (expr1) != type)
516 expr1 = build1 (NOP_EXPR, type, expr1);
517 return ifnonnull (expr, expr1);
518 }
519 else
520 {
521 tree retval;
522 tree result, td1, td2, td3, elems, expr2;
523
524 /* If we got here, we can't convert statically. Therefore,
525 dynamic_cast<D&>(b) (b an object) cannot succeed. */
526 if (ec == REFERENCE_TYPE)
527 {
528 if (TREE_CODE (expr) == VAR_DECL
529 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
530 {
531 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
532 expr, type);
533 return throw_bad_cast ();
534 }
535 }
536 /* Ditto for dynamic_cast<D*>(&b). */
537 else if (TREE_CODE (expr) == ADDR_EXPR)
538 {
539 tree op = TREE_OPERAND (expr, 0);
540 if (TREE_CODE (op) == VAR_DECL
541 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
542 {
543 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
544 expr, type);
545 retval = build_int_2 (0, 0);
546 TREE_TYPE (retval) = type;
547 return retval;
548 }
549 }
550
551 /* Since expr is used twice below, save it. */
552 expr = save_expr (expr);
553
554 expr1 = expr;
555 if (tc == REFERENCE_TYPE)
556 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
557
558 /* Build run-time conversion. */
559 expr2 = build_headof (expr1);
560
561 if (ec == POINTER_TYPE)
562 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
563 else
564 td1 = get_tinfo_fn_dynamic (expr);
565 td1 = decay_conversion (td1);
566
567 td2 = decay_conversion
568 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
569 td3 = decay_conversion
570 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
571
572 elems = tree_cons
573 (NULL_TREE, td1, tree_cons
574 (NULL_TREE, td2, tree_cons
575 (NULL_TREE, build_int_2 (1, 0), tree_cons
576 (NULL_TREE, expr2, tree_cons
577 (NULL_TREE, td3, tree_cons
578 (NULL_TREE, expr1, NULL_TREE))))));
579
580 dcast_fn = get_identifier ("__dynamic_cast");
581 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
582 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
583 else
584 {
585 tree tmp;
586
587 push_obstacks (&permanent_obstack, &permanent_obstack);
588 tmp = tree_cons
589 (NULL_TREE, TREE_TYPE (td1), tree_cons
590 (NULL_TREE, TREE_TYPE (td1), tree_cons
591 (NULL_TREE, integer_type_node, tree_cons
592 (NULL_TREE, ptr_type_node, tree_cons
593 (NULL_TREE, TREE_TYPE (td1), tree_cons
594 (NULL_TREE, ptr_type_node, void_list_node))))));
595 tmp = build_function_type (ptr_type_node, tmp);
596 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
597 DECL_EXTERNAL (dcast_fn) = 1;
598 TREE_PUBLIC (dcast_fn) = 1;
599 DECL_ARTIFICIAL (dcast_fn) = 1;
600 pushdecl_top_level (dcast_fn);
601 make_function_rtl (dcast_fn);
602 assemble_external (dcast_fn);
603 pop_obstacks ();
604 }
605
606 result = build_call
607 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
608
609 if (tc == REFERENCE_TYPE)
610 {
611 expr1 = throw_bad_cast ();
612 expr1 = build_compound_expr
613 (tree_cons (NULL_TREE, expr1,
614 build_tree_list (NULL_TREE, convert
615 (type, integer_zero_node))));
616 TREE_TYPE (expr1) = type;
617 result = save_expr (result);
618 return build (COND_EXPR, type, result, result, expr1);
619 }
620
621 /* Now back to the type we want from a void*. */
622 result = convert (type, result);
623 return ifnonnull (expr, result);
624 }
625 }
626
627 fail:
628 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
629 expr, exprtype, type);
630 return error_mark_node;
631 }
632 \f
633 /* Build and initialize various sorts of descriptors. Every descriptor
634 node has a name associated with it (the name created by mangling).
635 For this reason, we use the identifier as our access to the __*_desc
636 nodes, instead of sticking them directly in the types. Otherwise we
637 would burden all built-in types (and pointer types) with slots that
638 we don't necessarily want to use.
639
640 For each descriptor we build, we build a variable that contains
641 the descriptor's information. When we need this info at runtime,
642 all we need is access to these variables.
643
644 Note: these constructors always return the address of the descriptor
645 info, since that is simplest for their mutual interaction. */
646
647 extern tree const_string_type_node;
648
649 /* Build an initializer for a __si_type_info node. */
650
651 static void
652 expand_si_desc (tdecl, type)
653 tree tdecl;
654 tree type;
655 {
656 tree t, elems, fn;
657 char *name = build_overload_name (type, 1, 1);
658 tree name_string = combine_strings (build_string (strlen (name)+1, name));
659
660 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
661 expand_expr_stmt (get_typeid_1 (type));
662 t = decay_conversion (get_tinfo_var (type));
663 elems = tree_cons
664 (NULL_TREE, decay_conversion (tdecl), tree_cons
665 (NULL_TREE, decay_conversion (name_string), tree_cons
666 (NULL_TREE, t, NULL_TREE)));
667
668 fn = get_identifier ("__rtti_si");
669 if (IDENTIFIER_GLOBAL_VALUE (fn))
670 fn = IDENTIFIER_GLOBAL_VALUE (fn);
671 else
672 {
673 tree tmp;
674 push_obstacks (&permanent_obstack, &permanent_obstack);
675 tmp = tree_cons
676 (NULL_TREE, ptr_type_node, tree_cons
677 (NULL_TREE, const_string_type_node, tree_cons
678 (NULL_TREE, build_pointer_type (type_info_type_node),
679 void_list_node)));
680 tmp = build_function_type (void_type_node, tmp);
681
682 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
683 DECL_EXTERNAL (fn) = 1;
684 TREE_PUBLIC (fn) = 1;
685 DECL_ARTIFICIAL (fn) = 1;
686 pushdecl_top_level (fn);
687 make_function_rtl (fn);
688 assemble_external (fn);
689 pop_obstacks ();
690 }
691
692 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
693 expand_expr_stmt (fn);
694 }
695
696 /* Build an initializer for a __class_type_info node. */
697
698 static void
699 expand_class_desc (tdecl, type)
700 tree tdecl;
701 tree type;
702 {
703 tree name_string;
704 tree fn, tmp;
705 char *name;
706
707 int i = CLASSTYPE_N_BASECLASSES (type);
708 int base_cnt = 0;
709 tree binfos = TYPE_BINFO_BASETYPES (type);
710 #if 0
711 /* See code below that used these. */
712 tree vb = CLASSTYPE_VBASECLASSES (type);
713 int n_base = i;
714 #endif
715 tree base, elems, access, offset, isvir;
716 tree elt, elts = NULL_TREE;
717 static tree base_info_type_node;
718
719 if (base_info_type_node == NULL_TREE)
720 {
721 tree fields [4];
722
723 /* A reasonably close approximation of __class_type_info::base_info */
724
725 push_obstacks (&permanent_obstack, &permanent_obstack);
726 base_info_type_node = make_lang_type (RECORD_TYPE);
727
728 /* Actually const __user_type_info * */
729 fields [0] = build_lang_field_decl
730 (FIELD_DECL, NULL_TREE,
731 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
732 fields [1] = build_lang_field_decl
733 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
734 DECL_BIT_FIELD (fields[1]) = 1;
735 DECL_FIELD_SIZE (fields[1]) = 29;
736
737 fields [2] = build_lang_field_decl
738 (FIELD_DECL, NULL_TREE, boolean_type_node);
739 DECL_BIT_FIELD (fields[2]) = 1;
740 DECL_FIELD_SIZE (fields[2]) = 1;
741
742 /* Actually enum access */
743 fields [3] = build_lang_field_decl
744 (FIELD_DECL, NULL_TREE, integer_type_node);
745 DECL_BIT_FIELD (fields[3]) = 1;
746 DECL_FIELD_SIZE (fields[3]) = 2;
747
748 finish_builtin_type (base_info_type_node, "__base_info", fields,
749 3, ptr_type_node);
750 pop_obstacks ();
751 }
752
753 while (--i >= 0)
754 {
755 tree binfo = TREE_VEC_ELT (binfos, i);
756
757 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
758 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
759
760 if (TREE_VIA_VIRTUAL (binfo))
761 {
762 tree t = BINFO_TYPE (binfo);
763 char *name;
764 tree field;
765
766 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
767 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
768 field = lookup_field (type, get_identifier (name), 0, 0);
769 offset = size_binop (FLOOR_DIV_EXPR,
770 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
771 }
772 else
773 offset = BINFO_OFFSET (binfo);
774
775 if (TREE_VIA_PUBLIC (binfo))
776 access = access_public_node;
777 else if (TREE_VIA_PROTECTED (binfo))
778 access = access_protected_node;
779 else
780 access = access_private_node;
781 if (TREE_VIA_VIRTUAL (binfo))
782 isvir = boolean_true_node;
783 else
784 isvir = boolean_false_node;
785
786 elt = build
787 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
788 (NULL_TREE, base, tree_cons
789 (NULL_TREE, offset, tree_cons
790 (NULL_TREE, isvir, tree_cons
791 (NULL_TREE, access, NULL_TREE)))));
792 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
793 elts = tree_cons (NULL_TREE, elt, elts);
794 base_cnt++;
795 }
796 #if 0
797 i = n_base;
798 while (vb)
799 {
800 tree b;
801 access = access_public_node;
802 while (--i >= 0)
803 {
804 b = TREE_VEC_ELT (binfos, i);
805 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
806 {
807 if (TREE_VIA_PUBLIC (b))
808 access = access_public_node;
809 else if (TREE_VIA_PROTECTED (b))
810 access = access_protected_node;
811 else
812 access = access_private_node;
813 break;
814 }
815 }
816 base = build_t_desc (BINFO_TYPE (vb), 1);
817 offset = BINFO_OFFSET (vb);
818 isvir = build_int_2 (1, 0);
819
820 base_list = tree_cons (NULL_TREE, base, base_list);
821 isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
822 acc_list = tree_cons (NULL_TREE, access, acc_list);
823 off_list = tree_cons (NULL_TREE, offset, off_list);
824
825 base_cnt++;
826 vb = TREE_CHAIN (vb);
827 }
828 #endif
829
830 name = build_overload_name (type, 1, 1);
831 name_string = combine_strings (build_string (strlen (name)+1, name));
832
833 {
834 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
835 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
836 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
837 = TREE_STATIC (elts) = 1;
838 complete_array_type (arrtype, elts, 1);
839 }
840
841 elems = tree_cons
842 (NULL_TREE, decay_conversion (tdecl), tree_cons
843 (NULL_TREE, decay_conversion (name_string), tree_cons
844 (NULL_TREE, decay_conversion (elts), tree_cons
845 (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))));
846
847 fn = get_identifier ("__rtti_class");
848 if (IDENTIFIER_GLOBAL_VALUE (fn))
849 fn = IDENTIFIER_GLOBAL_VALUE (fn);
850 else
851 {
852 push_obstacks (&permanent_obstack, &permanent_obstack);
853 tmp = tree_cons
854 (NULL_TREE, ptr_type_node, tree_cons
855 (NULL_TREE, const_string_type_node, tree_cons
856 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
857 (NULL_TREE, sizetype, void_list_node))));
858 tmp = build_function_type (void_type_node, tmp);
859
860 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
861 DECL_EXTERNAL (fn) = 1;
862 TREE_PUBLIC (fn) = 1;
863 DECL_ARTIFICIAL (fn) = 1;
864 pushdecl_top_level (fn);
865 make_function_rtl (fn);
866 assemble_external (fn);
867 pop_obstacks ();
868 }
869
870 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
871 expand_expr_stmt (fn);
872 }
873
874 /* Build an initializer for a __pointer_type_info node. */
875
876 static void
877 expand_ptr_desc (tdecl, type)
878 tree tdecl;
879 tree type;
880 {
881 tree t, elems, fn;
882 char *name = build_overload_name (type, 1, 1);
883 tree name_string = combine_strings (build_string (strlen (name)+1, name));
884
885 type = TREE_TYPE (type);
886 expand_expr_stmt (get_typeid_1 (type));
887 t = decay_conversion (get_tinfo_var (type));
888 elems = tree_cons
889 (NULL_TREE, decay_conversion (tdecl), tree_cons
890 (NULL_TREE, decay_conversion (name_string), tree_cons
891 (NULL_TREE, t, NULL_TREE)));
892
893 fn = get_identifier ("__rtti_ptr");
894 if (IDENTIFIER_GLOBAL_VALUE (fn))
895 fn = IDENTIFIER_GLOBAL_VALUE (fn);
896 else
897 {
898 tree tmp;
899 push_obstacks (&permanent_obstack, &permanent_obstack);
900 tmp = tree_cons
901 (NULL_TREE, ptr_type_node, tree_cons
902 (NULL_TREE, const_string_type_node, tree_cons
903 (NULL_TREE, build_pointer_type (type_info_type_node),
904 void_list_node)));
905 tmp = build_function_type (void_type_node, tmp);
906
907 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
908 DECL_EXTERNAL (fn) = 1;
909 TREE_PUBLIC (fn) = 1;
910 DECL_ARTIFICIAL (fn) = 1;
911 pushdecl_top_level (fn);
912 make_function_rtl (fn);
913 assemble_external (fn);
914 pop_obstacks ();
915 }
916
917 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
918 expand_expr_stmt (fn);
919 }
920
921 /* Build an initializer for a __attr_type_info node. */
922
923 static void
924 expand_attr_desc (tdecl, type)
925 tree tdecl;
926 tree type;
927 {
928 tree elems, t, fn;
929 char *name = build_overload_name (type, 1, 1);
930 tree name_string = combine_strings (build_string (strlen (name)+1, name));
931 tree attrval = build_int_2
932 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
933
934 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
935 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
936 elems = tree_cons
937 (NULL_TREE, decay_conversion (tdecl), tree_cons
938 (NULL_TREE, decay_conversion (name_string), tree_cons
939 (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
940
941 fn = get_identifier ("__rtti_attr");
942 if (IDENTIFIER_GLOBAL_VALUE (fn))
943 fn = IDENTIFIER_GLOBAL_VALUE (fn);
944 else
945 {
946 tree tmp;
947 push_obstacks (&permanent_obstack, &permanent_obstack);
948 tmp = tree_cons
949 (NULL_TREE, ptr_type_node, tree_cons
950 (NULL_TREE, const_string_type_node, tree_cons
951 (NULL_TREE, integer_type_node, tree_cons
952 (NULL_TREE, build_pointer_type (type_info_type_node),
953 void_list_node))));
954 tmp = build_function_type (void_type_node, tmp);
955
956 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
957 DECL_EXTERNAL (fn) = 1;
958 TREE_PUBLIC (fn) = 1;
959 DECL_ARTIFICIAL (fn) = 1;
960 pushdecl_top_level (fn);
961 make_function_rtl (fn);
962 assemble_external (fn);
963 pop_obstacks ();
964 }
965
966 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
967 expand_expr_stmt (fn);
968 }
969
970 /* Build an initializer for a type_info node that just has a name. */
971
972 static void
973 expand_generic_desc (tdecl, type, fnname)
974 tree tdecl;
975 tree type;
976 char *fnname;
977 {
978 char *name = build_overload_name (type, 1, 1);
979 tree name_string = combine_strings (build_string (strlen (name)+1, name));
980 tree elems = tree_cons
981 (NULL_TREE, decay_conversion (tdecl), tree_cons
982 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
983
984 tree fn = get_identifier (fnname);
985 if (IDENTIFIER_GLOBAL_VALUE (fn))
986 fn = IDENTIFIER_GLOBAL_VALUE (fn);
987 else
988 {
989 tree tmp;
990 push_obstacks (&permanent_obstack, &permanent_obstack);
991 tmp = tree_cons
992 (NULL_TREE, ptr_type_node, tree_cons
993 (NULL_TREE, const_string_type_node, void_list_node));
994 tmp = build_function_type (void_type_node, tmp);
995
996 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
997 DECL_EXTERNAL (fn) = 1;
998 TREE_PUBLIC (fn) = 1;
999 DECL_ARTIFICIAL (fn) = 1;
1000 pushdecl_top_level (fn);
1001 make_function_rtl (fn);
1002 assemble_external (fn);
1003 pop_obstacks ();
1004 }
1005
1006 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1007 expand_expr_stmt (fn);
1008 }
1009
1010 /* Generate the code for a type_info initialization function.
1011 Note that we take advantage of the passage
1012
1013 5.2.7 Type identification [expr.typeid]
1014
1015 Whether or not the destructor is called for the type_info object at the
1016 end of the program is unspecified.
1017
1018 and don't bother to arrange for these objects to be destroyed. It
1019 doesn't matter, anyway, since the destructors don't do anything.
1020
1021 This must only be called from toplevel (i.e. from finish_file)! */
1022
1023 void
1024 synthesize_tinfo_fn (fndecl)
1025 tree fndecl;
1026 {
1027 tree type = TREE_TYPE (DECL_NAME (fndecl));
1028 tree tmp, addr;
1029
1030 tree tdecl = get_tinfo_var (type);
1031 DECL_EXTERNAL (tdecl) = 0;
1032 TREE_STATIC (tdecl) = 1;
1033 DECL_COMMON (tdecl) = 1;
1034 TREE_USED (tdecl) = 1;
1035 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1036 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1037
1038 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1039 store_parm_decls ();
1040 clear_last_expr ();
1041 push_momentary ();
1042
1043 /* If the first word of the array (the vtable) is non-zero, we've already
1044 initialized the object, so don't do it again. */
1045 addr = decay_conversion (tdecl);
1046 tmp = convert (build_pointer_type (ptr_type_node), addr);
1047 tmp = build_indirect_ref (tmp, 0);
1048 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1049 expand_start_cond (tmp, 0);
1050
1051 if (TREE_CODE (type) == FUNCTION_TYPE)
1052 expand_generic_desc (tdecl, type, "__rtti_func");
1053 else if (TREE_CODE (type) == ARRAY_TYPE)
1054 expand_generic_desc (tdecl, type, "__rtti_array");
1055 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1056 expand_attr_desc (tdecl, type);
1057 else if (TREE_CODE (type) == POINTER_TYPE)
1058 {
1059 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1060 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1061 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1062 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1063 else
1064 expand_ptr_desc (tdecl, type);
1065 }
1066 else if (TYPE_PTRMEMFUNC_P (type))
1067 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1068 else if (IS_AGGR_TYPE (type))
1069 {
1070 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1071 expand_generic_desc (tdecl, type, "__rtti_user");
1072 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1073 && (TREE_VIA_PUBLIC
1074 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1075 expand_si_desc (tdecl, type);
1076 else
1077 expand_class_desc (tdecl, type);
1078 }
1079 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1080 expand_generic_desc (tdecl, type, "__rtti_user");
1081 else
1082 my_friendly_abort (252);
1083
1084 expand_end_cond ();
1085
1086 /* OK, now return the type_info object. */
1087 tmp = convert (build_pointer_type (type_info_type_node), addr);
1088 tmp = build_indirect_ref (tmp, 0);
1089 c_expand_return (tmp);
1090 finish_function (lineno, 0, 0);
1091 }
1092
1093 #if 0
1094 /* This is the old dossier type descriptor generation code, it's much
1095 more extended than rtti. It's reserved for later use. */
1096 /* Build an initializer for a __t_desc node. So that we can take advantage
1097 of recursion, we accept NULL for TYPE.
1098 DEFINITION is greater than zero iff we must define the type descriptor
1099 (as opposed to merely referencing it). 1 means treat according to
1100 #pragma interface/#pragma implementation rules. 2 means define as
1101 global and public, no matter what. */
1102
1103 tree
1104 build_t_desc (type, definition)
1105 tree type;
1106 int definition;
1107 {
1108 tree tdecl;
1109 tree tname, name_string;
1110 tree elems, fields;
1111 tree parents, vbases, offsets, ivars, methods, target_type;
1112 int method_count = 0, field_count = 0;
1113
1114 if (type == NULL_TREE)
1115 return NULL_TREE;
1116
1117 tname = build_t_desc_overload (type);
1118 if (IDENTIFIER_AS_DESC (tname)
1119 && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1120 return IDENTIFIER_AS_DESC (tname);
1121
1122 tdecl = lookup_name (tname, 0);
1123 if (tdecl == NULL_TREE)
1124 {
1125 tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1126 DECL_EXTERNAL (tdecl) = 1;
1127 TREE_PUBLIC (tdecl) = 1;
1128 tdecl = pushdecl_top_level (tdecl);
1129 }
1130 /* If we previously defined it, return the defined result. */
1131 else if (definition && DECL_INITIAL (tdecl))
1132 return IDENTIFIER_AS_DESC (tname);
1133
1134 if (definition)
1135 {
1136 tree taggr = type;
1137 /* Let T* and T& be written only when T is written (if T is an aggr).
1138 We do this for const, but not for volatile, since volatile
1139 is rare and const is not. */
1140 if (!TYPE_VOLATILE (taggr)
1141 && (TREE_CODE (taggr) == POINTER_TYPE
1142 || TREE_CODE (taggr) == REFERENCE_TYPE)
1143 && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1144 taggr = TREE_TYPE (taggr);
1145
1146 /* If we know that we don't need to write out this type's
1147 vtable, then don't write out it's dossier. Somebody
1148 else will take care of that. */
1149 if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1150 {
1151 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1152 {
1153 TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1154 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1155 DECL_EXTERNAL (tdecl) = 0;
1156 }
1157 else
1158 {
1159 if (write_virtuals != 0)
1160 TREE_PUBLIC (tdecl) = 1;
1161 }
1162 }
1163 else
1164 {
1165 DECL_EXTERNAL (tdecl) = 0;
1166 TREE_PUBLIC (tdecl) = (definition > 1);
1167 }
1168 }
1169 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1170
1171 if (!definition || DECL_EXTERNAL (tdecl))
1172 {
1173 /* That's it! */
1174 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1175 return IDENTIFIER_AS_DESC (tname);
1176 }
1177
1178 /* Show that we are defining the t_desc for this type. */
1179 DECL_INITIAL (tdecl) = error_mark_node;
1180
1181 parents = build_tree_list (NULL_TREE, integer_zero_node);
1182 vbases = build_tree_list (NULL_TREE, integer_zero_node);
1183 offsets = build_tree_list (NULL_TREE, integer_zero_node);
1184 methods = NULL_TREE;
1185 ivars = NULL_TREE;
1186
1187 if (TYPE_LANG_SPECIFIC (type))
1188 {
1189 int i = CLASSTYPE_N_BASECLASSES (type);
1190 tree method_vec = CLASSTYPE_METHOD_VEC (type);
1191 tree *meth, *end;
1192 tree binfos = TYPE_BINFO_BASETYPES (type);
1193 tree vb = CLASSTYPE_VBASECLASSES (type);
1194
1195 while (--i >= 0)
1196 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1197
1198 while (vb)
1199 {
1200 vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1201 offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1202 vb = TREE_CHAIN (vb);
1203 }
1204
1205 if (method_vec)
1206 for (meth = TREE_VEC_END (method_vec),
1207 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1208 if (*meth)
1209 {
1210 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1211 method_count++;
1212 }
1213 }
1214
1215 if (IS_AGGR_TYPE (type))
1216 {
1217 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1218 if (TREE_CODE (fields) == FIELD_DECL
1219 || TREE_CODE (fields) == VAR_DECL)
1220 {
1221 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1222 field_count++;
1223 }
1224 ivars = nreverse (ivars);
1225 }
1226
1227 parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1228 vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1229 offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1230 if (methods == NULL_TREE)
1231 methods = null_pointer_node;
1232 else
1233 methods = build_unary_op (ADDR_EXPR,
1234 finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1235 0);
1236 if (ivars == NULL_TREE)
1237 ivars = null_pointer_node;
1238 else
1239 ivars = build_unary_op (ADDR_EXPR,
1240 finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1241 0);
1242 if (TREE_TYPE (type))
1243 target_type = build_t_desc (TREE_TYPE (type), definition);
1244 else
1245 target_type = integer_zero_node;
1246
1247 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1248
1249 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1250 tree_cons (NULL_TREE,
1251 TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1252 /* really should use bitfield initialization here. */
1253 tree_cons (NULL_TREE, integer_zero_node,
1254 tree_cons (NULL_TREE, target_type,
1255 tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1256 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1257 tree_cons (NULL_TREE, ivars,
1258 tree_cons (NULL_TREE, methods,
1259 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1260 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1261 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1262 return build_generic_desc (tdecl, elems);
1263 }
1264
1265 /* Build an initializer for a __i_desc node. */
1266
1267 tree
1268 build_i_desc (decl)
1269 tree decl;
1270 {
1271 tree elems, name_string;
1272 tree taggr;
1273
1274 name_string = DECL_NAME (decl);
1275 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1276
1277 /* Now decide whether this ivar should cause it's type to get
1278 def'd or ref'd in this file. If the type we are looking at
1279 has a proxy definition, we look at the proxy (i.e., a
1280 `foo *' is equivalent to a `foo'). */
1281 taggr = TREE_TYPE (decl);
1282
1283 if ((TREE_CODE (taggr) == POINTER_TYPE
1284 || TREE_CODE (taggr) == REFERENCE_TYPE)
1285 && TYPE_VOLATILE (taggr) == 0)
1286 taggr = TREE_TYPE (taggr);
1287
1288 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1289 tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1290 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1291 ! IS_AGGR_TYPE (taggr)))));
1292 taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1293 TREE_CONSTANT (taggr) = 1;
1294 TREE_STATIC (taggr) = 1;
1295 TREE_READONLY (taggr) = 1;
1296 return taggr;
1297 }
1298
1299 /* Build an initializer for a __m_desc node. */
1300
1301 tree
1302 build_m_desc (decl)
1303 tree decl;
1304 {
1305 tree taggr, elems, name_string;
1306 tree parm_count, req_count, vindex, vcontext;
1307 tree parms;
1308 int p_count, r_count;
1309 tree parm_types = NULL_TREE;
1310
1311 for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1312 parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1313 {
1314 taggr = TREE_VALUE (parms);
1315 if ((TREE_CODE (taggr) == POINTER_TYPE
1316 || TREE_CODE (taggr) == REFERENCE_TYPE)
1317 && TYPE_VOLATILE (taggr) == 0)
1318 taggr = TREE_TYPE (taggr);
1319
1320 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1321 ! IS_AGGR_TYPE (taggr)),
1322 parm_types);
1323 if (TREE_PURPOSE (parms) == NULL_TREE)
1324 r_count++;
1325 }
1326
1327 parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1328 nreverse (parm_types), 0);
1329 parm_count = build_int_2 (p_count, 0);
1330 req_count = build_int_2 (r_count, 0);
1331
1332 if (DECL_VINDEX (decl))
1333 vindex = DECL_VINDEX (decl);
1334 else
1335 vindex = integer_zero_node;
1336 if (DECL_CONTEXT (decl)
1337 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1338 vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1339 else
1340 vcontext = integer_zero_node;
1341 name_string = DECL_NAME (decl);
1342 if (name_string == NULL)
1343 name_string = DECL_ASSEMBLER_NAME (decl);
1344 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1345
1346 /* Now decide whether the return type of this mvar
1347 should cause it's type to get def'd or ref'd in this file.
1348 If the type we are looking at has a proxy definition,
1349 we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
1350 taggr = TREE_TYPE (TREE_TYPE (decl));
1351
1352 if ((TREE_CODE (taggr) == POINTER_TYPE
1353 || TREE_CODE (taggr) == REFERENCE_TYPE)
1354 && TYPE_VOLATILE (taggr) == 0)
1355 taggr = TREE_TYPE (taggr);
1356
1357 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1358 tree_cons (NULL_TREE, vindex,
1359 tree_cons (NULL_TREE, vcontext,
1360 tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1361 ! IS_AGGR_TYPE (taggr)),
1362 tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
1363 tree_cons (NULL_TREE, parm_count,
1364 tree_cons (NULL_TREE, req_count,
1365 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1366
1367 taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1368 TREE_CONSTANT (taggr) = 1;
1369 TREE_STATIC (taggr) = 1;
1370 TREE_READONLY (taggr) = 1;
1371 return taggr;
1372 }
1373 #endif /* dossier */
This page took 0.089794 seconds and 5 git commands to generate.