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