]> gcc.gnu.org Git - gcc.git/blob - gcc/cp/rtti.c
90th 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 the type of the type-id is a reference type, the result of the
377 typeid expression refers to a type_info object representing the
378 referenced type. */
379 if (TREE_CODE (type) == REFERENCE_TYPE)
380 type = TREE_TYPE (type);
381
382 /* The top-level cv-qualifiers of the lvalue expression or the type-id
383 that is the operand of typeid are always ignored. */
384 type = TYPE_MAIN_VARIANT (type);
385
386 return get_typeid_1 (type);
387 }
388
389 /* Check whether TEST is null before returning RESULT. If TEST is used in
390 RESULT, it must have previously had a save_expr applied to it. */
391
392 static tree
393 ifnonnull (test, result)
394 tree test, result;
395 {
396 return build (COND_EXPR, TREE_TYPE (result),
397 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
398 convert (TREE_TYPE (result), integer_zero_node),
399 result);
400 }
401
402 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
403 paper. */
404
405 tree
406 build_dynamic_cast (type, expr)
407 tree type, expr;
408 {
409 enum tree_code tc = TREE_CODE (type);
410 tree exprtype = TREE_TYPE (expr);
411 enum tree_code ec;
412 tree dcast_fn;
413
414 if (type == error_mark_node || expr == error_mark_node)
415 return error_mark_node;
416
417 if (processing_template_decl)
418 {
419 tree t = build_min (DYNAMIC_CAST_EXPR, type, expr);
420 return t;
421 }
422
423 assert (exprtype != NULL_TREE);
424 ec = TREE_CODE (exprtype);
425
426 switch (tc)
427 {
428 case POINTER_TYPE:
429 if (ec == REFERENCE_TYPE)
430 {
431 expr = convert_from_reference (expr);
432 exprtype = TREE_TYPE (expr);
433 ec = TREE_CODE (exprtype);
434 }
435 if (ec != POINTER_TYPE)
436 goto fail;
437 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
438 goto fail;
439 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
440 goto fail;
441 if (TREE_READONLY (TREE_TYPE (exprtype)) &&
442 ! TYPE_READONLY (TREE_TYPE (type)))
443 goto fail;
444 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
445 break;
446 /* else fall through */
447 case REFERENCE_TYPE:
448 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
449 goto fail;
450 if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
451 goto fail;
452 break;
453 /* else fall through */
454 default:
455 goto fail;
456 }
457
458 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
459 if (ec == RECORD_TYPE)
460 {
461 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
462 TREE_THIS_VOLATILE (expr));
463 exprtype = build_reference_type (exprtype);
464 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
465 LOOKUP_NORMAL, NULL_TREE);
466 ec = REFERENCE_TYPE;
467 }
468
469 if (tc == REFERENCE_TYPE)
470 {
471 if (ec != REFERENCE_TYPE)
472 goto fail;
473 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
474 goto fail;
475 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
476 goto fail;
477 if (TREE_READONLY (TREE_TYPE (exprtype)) &&
478 ! TYPE_READONLY (TREE_TYPE (type)))
479 goto fail;
480 }
481
482 /* If *type is an unambiguous accessible base class of *exprtype,
483 convert statically. */
484 {
485 int distance;
486 tree path;
487
488 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
489 &path);
490 if (distance >= 0)
491 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
492 }
493
494 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
495 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
496 {
497 tree expr1;
498 /* if TYPE is `void *', return pointer to complete object. */
499 if (tc == POINTER_TYPE
500 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
501 {
502 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
503 if (TREE_CODE (expr) == ADDR_EXPR
504 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
505 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
506 return build1 (NOP_EXPR, type, expr);
507
508 /* Since expr is used twice below, save it. */
509 expr = save_expr (expr);
510
511 expr1 = build_headof (expr);
512 if (TREE_TYPE (expr1) != type)
513 expr1 = build1 (NOP_EXPR, type, expr1);
514 return ifnonnull (expr, expr1);
515 }
516 else
517 {
518 tree retval;
519 tree result, td1, td2, td3, elems, expr2;
520
521 /* If we got here, we can't convert statically. Therefore,
522 dynamic_cast<D&>(b) (b an object) cannot succeed. */
523 if (ec == REFERENCE_TYPE)
524 {
525 if (TREE_CODE (expr) == VAR_DECL
526 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
527 {
528 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
529 expr, type);
530 return throw_bad_cast ();
531 }
532 }
533 /* Ditto for dynamic_cast<D*>(&b). */
534 else if (TREE_CODE (expr) == ADDR_EXPR)
535 {
536 tree op = TREE_OPERAND (expr, 0);
537 if (TREE_CODE (op) == VAR_DECL
538 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
539 {
540 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
541 expr, type);
542 retval = build_int_2 (0, 0);
543 TREE_TYPE (retval) = type;
544 return retval;
545 }
546 }
547
548 /* Since expr is used twice below, save it. */
549 expr = save_expr (expr);
550
551 expr1 = expr;
552 if (tc == REFERENCE_TYPE)
553 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
554
555 /* Build run-time conversion. */
556 expr2 = build_headof (expr1);
557
558 if (ec == POINTER_TYPE)
559 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
560 else
561 td1 = get_tinfo_fn_dynamic (expr);
562 td1 = decay_conversion (td1);
563
564 td2 = decay_conversion
565 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
566 td3 = decay_conversion
567 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
568
569 elems = tree_cons
570 (NULL_TREE, td1, tree_cons
571 (NULL_TREE, td2, tree_cons
572 (NULL_TREE, build_int_2 (1, 0), tree_cons
573 (NULL_TREE, expr2, tree_cons
574 (NULL_TREE, td3, tree_cons
575 (NULL_TREE, expr1, NULL_TREE))))));
576
577 dcast_fn = get_identifier ("__dynamic_cast");
578 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
579 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
580 else
581 {
582 tree tmp;
583
584 push_obstacks (&permanent_obstack, &permanent_obstack);
585 tmp = tree_cons
586 (NULL_TREE, TREE_TYPE (td1), tree_cons
587 (NULL_TREE, TREE_TYPE (td1), tree_cons
588 (NULL_TREE, integer_type_node, tree_cons
589 (NULL_TREE, ptr_type_node, tree_cons
590 (NULL_TREE, TREE_TYPE (td1), tree_cons
591 (NULL_TREE, ptr_type_node, void_list_node))))));
592 tmp = build_function_type (ptr_type_node, tmp);
593 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
594 DECL_EXTERNAL (dcast_fn) = 1;
595 TREE_PUBLIC (dcast_fn) = 1;
596 DECL_ARTIFICIAL (dcast_fn) = 1;
597 pushdecl_top_level (dcast_fn);
598 make_function_rtl (dcast_fn);
599 assemble_external (dcast_fn);
600 pop_obstacks ();
601 }
602
603 result = build_call
604 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
605
606 if (tc == REFERENCE_TYPE)
607 {
608 expr1 = throw_bad_cast ();
609 expr1 = build_compound_expr
610 (tree_cons (NULL_TREE, expr1,
611 build_tree_list (NULL_TREE, convert
612 (type, integer_zero_node))));
613 TREE_TYPE (expr1) = type;
614 result = save_expr (result);
615 return build (COND_EXPR, type, result, result, expr1);
616 }
617
618 /* Now back to the type we want from a void*. */
619 result = convert (type, result);
620 return ifnonnull (expr, result);
621 }
622 }
623
624 fail:
625 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
626 expr, exprtype, type);
627 return error_mark_node;
628 }
629 \f
630 /* Build and initialize various sorts of descriptors. Every descriptor
631 node has a name associated with it (the name created by mangling).
632 For this reason, we use the identifier as our access to the __*_desc
633 nodes, instead of sticking them directly in the types. Otherwise we
634 would burden all built-in types (and pointer types) with slots that
635 we don't necessarily want to use.
636
637 For each descriptor we build, we build a variable that contains
638 the descriptor's information. When we need this info at runtime,
639 all we need is access to these variables.
640
641 Note: these constructors always return the address of the descriptor
642 info, since that is simplest for their mutual interaction. */
643
644 extern tree const_string_type_node;
645
646 /* Build an initializer for a __si_type_info node. */
647
648 static void
649 expand_si_desc (tdecl, type)
650 tree tdecl;
651 tree type;
652 {
653 tree t, elems, fn;
654 char *name = build_overload_name (type, 1, 1);
655 tree name_string = combine_strings (build_string (strlen (name), name));
656
657 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
658 expand_expr_stmt (get_typeid_1 (type));
659 t = decay_conversion (get_tinfo_var (type));
660 elems = tree_cons
661 (NULL_TREE, decay_conversion (tdecl), tree_cons
662 (NULL_TREE, decay_conversion (name_string), tree_cons
663 (NULL_TREE, t, NULL_TREE)));
664
665 fn = get_identifier ("__rtti_si");
666 if (IDENTIFIER_GLOBAL_VALUE (fn))
667 fn = IDENTIFIER_GLOBAL_VALUE (fn);
668 else
669 {
670 tree tmp;
671 push_obstacks (&permanent_obstack, &permanent_obstack);
672 tmp = tree_cons
673 (NULL_TREE, ptr_type_node, tree_cons
674 (NULL_TREE, const_string_type_node, tree_cons
675 (NULL_TREE, build_pointer_type (type_info_type_node),
676 void_list_node)));
677 tmp = build_function_type (void_type_node, tmp);
678
679 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
680 DECL_EXTERNAL (fn) = 1;
681 TREE_PUBLIC (fn) = 1;
682 DECL_ARTIFICIAL (fn) = 1;
683 pushdecl_top_level (fn);
684 make_function_rtl (fn);
685 assemble_external (fn);
686 pop_obstacks ();
687 }
688
689 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
690 expand_expr_stmt (fn);
691 }
692
693 /* Build an initializer for a __class_type_info node. */
694
695 static void
696 expand_class_desc (tdecl, type)
697 tree tdecl;
698 tree type;
699 {
700 tree name_string;
701 tree fn, tmp;
702 char *name;
703
704 int i = CLASSTYPE_N_BASECLASSES (type);
705 int base_cnt = 0;
706 tree binfos = TYPE_BINFO_BASETYPES (type);
707 #if 0
708 /* See code below that used these. */
709 tree vb = CLASSTYPE_VBASECLASSES (type);
710 int n_base = i;
711 #endif
712 tree base, elems, access, offset, isvir;
713 tree elt, elts = NULL_TREE;
714 static tree base_info_type_node;
715
716 if (base_info_type_node == NULL_TREE)
717 {
718 tree fields [4];
719
720 /* A reasonably close approximation of __class_type_info::base_info */
721
722 push_obstacks (&permanent_obstack, &permanent_obstack);
723 base_info_type_node = make_lang_type (RECORD_TYPE);
724
725 /* Actually const __user_type_info * */
726 fields [0] = build_lang_field_decl
727 (FIELD_DECL, NULL_TREE,
728 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
729 fields [1] = build_lang_field_decl
730 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
731 DECL_BIT_FIELD (fields[1]) = 1;
732 DECL_FIELD_SIZE (fields[1]) = 29;
733
734 fields [2] = build_lang_field_decl
735 (FIELD_DECL, NULL_TREE, boolean_type_node);
736 DECL_BIT_FIELD (fields[2]) = 1;
737 DECL_FIELD_SIZE (fields[2]) = 1;
738
739 /* Actually enum access */
740 fields [3] = build_lang_field_decl
741 (FIELD_DECL, NULL_TREE, integer_type_node);
742 DECL_BIT_FIELD (fields[3]) = 1;
743 DECL_FIELD_SIZE (fields[3]) = 2;
744
745 finish_builtin_type (base_info_type_node, "__base_info", fields,
746 3, ptr_type_node);
747 pop_obstacks ();
748 }
749
750 while (--i >= 0)
751 {
752 tree binfo = TREE_VEC_ELT (binfos, i);
753
754 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
755 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
756
757 if (TREE_VIA_VIRTUAL (binfo))
758 {
759 tree t = BINFO_TYPE (binfo);
760 char *name;
761 tree field;
762
763 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
764 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
765 field = lookup_field (type, get_identifier (name), 0, 0);
766 offset = size_binop (FLOOR_DIV_EXPR,
767 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
768 }
769 else
770 offset = BINFO_OFFSET (binfo);
771
772 if (TREE_VIA_PUBLIC (binfo))
773 access = access_public_node;
774 else if (TREE_VIA_PROTECTED (binfo))
775 access = access_protected_node;
776 else
777 access = access_private_node;
778 if (TREE_VIA_VIRTUAL (binfo))
779 isvir = boolean_true_node;
780 else
781 isvir = boolean_false_node;
782
783 elt = build
784 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
785 (NULL_TREE, base, tree_cons
786 (NULL_TREE, offset, tree_cons
787 (NULL_TREE, isvir, tree_cons
788 (NULL_TREE, access, NULL_TREE)))));
789 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
790 elts = tree_cons (NULL_TREE, elt, elts);
791 base_cnt++;
792 }
793 #if 0
794 i = n_base;
795 while (vb)
796 {
797 tree b;
798 access = access_public_node;
799 while (--i >= 0)
800 {
801 b = TREE_VEC_ELT (binfos, i);
802 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
803 {
804 if (TREE_VIA_PUBLIC (b))
805 access = access_public_node;
806 else if (TREE_VIA_PROTECTED (b))
807 access = access_protected_node;
808 else
809 access = access_private_node;
810 break;
811 }
812 }
813 base = build_t_desc (BINFO_TYPE (vb), 1);
814 offset = BINFO_OFFSET (vb);
815 isvir = build_int_2 (1, 0);
816
817 base_list = tree_cons (NULL_TREE, base, base_list);
818 isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
819 acc_list = tree_cons (NULL_TREE, access, acc_list);
820 off_list = tree_cons (NULL_TREE, offset, off_list);
821
822 base_cnt++;
823 vb = TREE_CHAIN (vb);
824 }
825 #endif
826
827 name = build_overload_name (type, 1, 1);
828 name_string = combine_strings (build_string (strlen (name), name));
829
830 {
831 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
832 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
833 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts) =
834 TREE_STATIC (elts) = 1;
835 complete_array_type (arrtype, elts, 1);
836 }
837
838 elems = tree_cons
839 (NULL_TREE, decay_conversion (tdecl), tree_cons
840 (NULL_TREE, decay_conversion (name_string), tree_cons
841 (NULL_TREE, decay_conversion (elts), tree_cons
842 (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))));
843
844 fn = get_identifier ("__rtti_class");
845 if (IDENTIFIER_GLOBAL_VALUE (fn))
846 fn = IDENTIFIER_GLOBAL_VALUE (fn);
847 else
848 {
849 push_obstacks (&permanent_obstack, &permanent_obstack);
850 tmp = tree_cons
851 (NULL_TREE, ptr_type_node, tree_cons
852 (NULL_TREE, const_string_type_node, tree_cons
853 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
854 (NULL_TREE, sizetype, void_list_node))));
855 tmp = build_function_type (void_type_node, tmp);
856
857 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
858 DECL_EXTERNAL (fn) = 1;
859 TREE_PUBLIC (fn) = 1;
860 DECL_ARTIFICIAL (fn) = 1;
861 pushdecl_top_level (fn);
862 make_function_rtl (fn);
863 assemble_external (fn);
864 pop_obstacks ();
865 }
866
867 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
868 expand_expr_stmt (fn);
869 }
870
871 /* Build an initializer for a __pointer_type_info node. */
872
873 static void
874 expand_ptr_desc (tdecl, type)
875 tree tdecl;
876 tree type;
877 {
878 tree t, elems, fn;
879 char *name = build_overload_name (type, 1, 1);
880 tree name_string = combine_strings (build_string (strlen (name), name));
881
882 type = TREE_TYPE (type);
883 expand_expr_stmt (get_typeid_1 (type));
884 t = decay_conversion (get_tinfo_var (type));
885 elems = tree_cons
886 (NULL_TREE, decay_conversion (tdecl), tree_cons
887 (NULL_TREE, decay_conversion (name_string), tree_cons
888 (NULL_TREE, t, NULL_TREE)));
889
890 fn = get_identifier ("__rtti_ptr");
891 if (IDENTIFIER_GLOBAL_VALUE (fn))
892 fn = IDENTIFIER_GLOBAL_VALUE (fn);
893 else
894 {
895 tree tmp;
896 push_obstacks (&permanent_obstack, &permanent_obstack);
897 tmp = tree_cons
898 (NULL_TREE, ptr_type_node, tree_cons
899 (NULL_TREE, const_string_type_node, tree_cons
900 (NULL_TREE, build_pointer_type (type_info_type_node),
901 void_list_node)));
902 tmp = build_function_type (void_type_node, tmp);
903
904 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
905 DECL_EXTERNAL (fn) = 1;
906 TREE_PUBLIC (fn) = 1;
907 DECL_ARTIFICIAL (fn) = 1;
908 pushdecl_top_level (fn);
909 make_function_rtl (fn);
910 assemble_external (fn);
911 pop_obstacks ();
912 }
913
914 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
915 expand_expr_stmt (fn);
916 }
917
918 /* Build an initializer for a __attr_type_info node. */
919
920 static void
921 expand_attr_desc (tdecl, type)
922 tree tdecl;
923 tree type;
924 {
925 tree elems, t, fn;
926 char *name = build_overload_name (type, 1, 1);
927 tree name_string = combine_strings (build_string (strlen (name), name));
928 tree attrval = build_int_2
929 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
930
931 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
932 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
933 elems = tree_cons
934 (NULL_TREE, decay_conversion (tdecl), tree_cons
935 (NULL_TREE, decay_conversion (name_string), tree_cons
936 (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
937
938 fn = get_identifier ("__rtti_attr");
939 if (IDENTIFIER_GLOBAL_VALUE (fn))
940 fn = IDENTIFIER_GLOBAL_VALUE (fn);
941 else
942 {
943 tree tmp;
944 push_obstacks (&permanent_obstack, &permanent_obstack);
945 tmp = tree_cons
946 (NULL_TREE, ptr_type_node, tree_cons
947 (NULL_TREE, const_string_type_node, tree_cons
948 (NULL_TREE, integer_type_node, tree_cons
949 (NULL_TREE, build_pointer_type (type_info_type_node),
950 void_list_node))));
951 tmp = build_function_type (void_type_node, tmp);
952
953 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
954 DECL_EXTERNAL (fn) = 1;
955 TREE_PUBLIC (fn) = 1;
956 DECL_ARTIFICIAL (fn) = 1;
957 pushdecl_top_level (fn);
958 make_function_rtl (fn);
959 assemble_external (fn);
960 pop_obstacks ();
961 }
962
963 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
964 expand_expr_stmt (fn);
965 }
966
967 /* Build an initializer for a type_info node that just has a name. */
968
969 static void
970 expand_generic_desc (tdecl, type, fnname)
971 tree tdecl;
972 tree type;
973 char *fnname;
974 {
975 char *name = build_overload_name (type, 1, 1);
976 tree name_string = combine_strings (build_string (strlen (name), name));
977 tree elems = tree_cons
978 (NULL_TREE, decay_conversion (tdecl), tree_cons
979 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
980
981 tree fn = get_identifier (fnname);
982 if (IDENTIFIER_GLOBAL_VALUE (fn))
983 fn = IDENTIFIER_GLOBAL_VALUE (fn);
984 else
985 {
986 tree tmp;
987 push_obstacks (&permanent_obstack, &permanent_obstack);
988 tmp = tree_cons
989 (NULL_TREE, ptr_type_node, tree_cons
990 (NULL_TREE, const_string_type_node, void_list_node));
991 tmp = build_function_type (void_type_node, tmp);
992
993 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
994 DECL_EXTERNAL (fn) = 1;
995 TREE_PUBLIC (fn) = 1;
996 DECL_ARTIFICIAL (fn) = 1;
997 pushdecl_top_level (fn);
998 make_function_rtl (fn);
999 assemble_external (fn);
1000 pop_obstacks ();
1001 }
1002
1003 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1004 expand_expr_stmt (fn);
1005 }
1006
1007 /* Generate the code for a type_info initialization function.
1008 Note that we take advantage of the passage
1009
1010 5.2.7 Type identification [expr.typeid]
1011
1012 Whether or not the destructor is called for the type_info object at the
1013 end of the program is unspecified.
1014
1015 and don't bother to arrange for these objects to be destroyed. It
1016 doesn't matter, anyway, since the destructors don't do anything.
1017
1018 This must only be called from toplevel (i.e. from finish_file)! */
1019
1020 void
1021 synthesize_tinfo_fn (fndecl)
1022 tree fndecl;
1023 {
1024 tree type = TREE_TYPE (DECL_NAME (fndecl));
1025 tree tmp, addr;
1026
1027 tree tdecl = get_tinfo_var (type);
1028 DECL_EXTERNAL (tdecl) = 0;
1029 TREE_STATIC (tdecl) = 1;
1030 DECL_COMMON (tdecl) = 1;
1031 TREE_USED (tdecl) = 1;
1032 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1033 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1034
1035 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1036 store_parm_decls ();
1037 clear_last_expr ();
1038 push_momentary ();
1039
1040 /* If the first word of the array (the vtable) is non-zero, we've already
1041 initialized the object, so don't do it again. */
1042 addr = decay_conversion (tdecl);
1043 tmp = convert (build_pointer_type (ptr_type_node), addr);
1044 tmp = build_indirect_ref (tmp, 0);
1045 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1046 expand_start_cond (tmp, 0);
1047
1048 if (TREE_CODE (type) == FUNCTION_TYPE)
1049 expand_generic_desc (tdecl, type, "__rtti_func");
1050 else if (TREE_CODE (type) == ARRAY_TYPE)
1051 expand_generic_desc (tdecl, type, "__rtti_array");
1052 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1053 expand_attr_desc (tdecl, type);
1054 else if (TREE_CODE (type) == POINTER_TYPE)
1055 {
1056 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1057 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1058 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1059 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1060 else
1061 expand_ptr_desc (tdecl, type);
1062 }
1063 else if (TYPE_PTRMEMFUNC_P (type))
1064 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1065 else if (IS_AGGR_TYPE (type))
1066 {
1067 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1068 expand_generic_desc (tdecl, type, "__rtti_user");
1069 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1070 && (TREE_VIA_PUBLIC
1071 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1072 expand_si_desc (tdecl, type);
1073 else
1074 expand_class_desc (tdecl, type);
1075 }
1076 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1077 expand_generic_desc (tdecl, type, "__rtti_user");
1078 else
1079 my_friendly_abort (252);
1080
1081 expand_end_cond ();
1082
1083 /* OK, now return the type_info object. */
1084 tmp = convert (build_pointer_type (type_info_type_node), addr);
1085 tmp = build_indirect_ref (tmp, 0);
1086 c_expand_return (tmp);
1087 finish_function (lineno, 0, 0);
1088 }
1089
1090 #if 0
1091 /* This is the old dossier type descriptor generation code, it's much
1092 more extended than rtti. It's reserved for later use. */
1093 /* Build an initializer for a __t_desc node. So that we can take advantage
1094 of recursion, we accept NULL for TYPE.
1095 DEFINITION is greater than zero iff we must define the type descriptor
1096 (as opposed to merely referencing it). 1 means treat according to
1097 #pragma interface/#pragma implementation rules. 2 means define as
1098 global and public, no matter what. */
1099
1100 tree
1101 build_t_desc (type, definition)
1102 tree type;
1103 int definition;
1104 {
1105 tree tdecl;
1106 tree tname, name_string;
1107 tree elems, fields;
1108 tree parents, vbases, offsets, ivars, methods, target_type;
1109 int method_count = 0, field_count = 0;
1110
1111 if (type == NULL_TREE)
1112 return NULL_TREE;
1113
1114 tname = build_t_desc_overload (type);
1115 if (IDENTIFIER_AS_DESC (tname)
1116 && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1117 return IDENTIFIER_AS_DESC (tname);
1118
1119 tdecl = lookup_name (tname, 0);
1120 if (tdecl == NULL_TREE)
1121 {
1122 tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1123 DECL_EXTERNAL (tdecl) = 1;
1124 TREE_PUBLIC (tdecl) = 1;
1125 tdecl = pushdecl_top_level (tdecl);
1126 }
1127 /* If we previously defined it, return the defined result. */
1128 else if (definition && DECL_INITIAL (tdecl))
1129 return IDENTIFIER_AS_DESC (tname);
1130
1131 if (definition)
1132 {
1133 tree taggr = type;
1134 /* Let T* and T& be written only when T is written (if T is an aggr).
1135 We do this for const, but not for volatile, since volatile
1136 is rare and const is not. */
1137 if (!TYPE_VOLATILE (taggr)
1138 && (TREE_CODE (taggr) == POINTER_TYPE
1139 || TREE_CODE (taggr) == REFERENCE_TYPE)
1140 && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1141 taggr = TREE_TYPE (taggr);
1142
1143 /* If we know that we don't need to write out this type's
1144 vtable, then don't write out it's dossier. Somebody
1145 else will take care of that. */
1146 if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1147 {
1148 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1149 {
1150 TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1151 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1152 DECL_EXTERNAL (tdecl) = 0;
1153 }
1154 else
1155 {
1156 if (write_virtuals != 0)
1157 TREE_PUBLIC (tdecl) = 1;
1158 }
1159 }
1160 else
1161 {
1162 DECL_EXTERNAL (tdecl) = 0;
1163 TREE_PUBLIC (tdecl) = (definition > 1);
1164 }
1165 }
1166 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1167
1168 if (!definition || DECL_EXTERNAL (tdecl))
1169 {
1170 /* That's it! */
1171 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1172 return IDENTIFIER_AS_DESC (tname);
1173 }
1174
1175 /* Show that we are defining the t_desc for this type. */
1176 DECL_INITIAL (tdecl) = error_mark_node;
1177
1178 parents = build_tree_list (NULL_TREE, integer_zero_node);
1179 vbases = build_tree_list (NULL_TREE, integer_zero_node);
1180 offsets = build_tree_list (NULL_TREE, integer_zero_node);
1181 methods = NULL_TREE;
1182 ivars = NULL_TREE;
1183
1184 if (TYPE_LANG_SPECIFIC (type))
1185 {
1186 int i = CLASSTYPE_N_BASECLASSES (type);
1187 tree method_vec = CLASSTYPE_METHOD_VEC (type);
1188 tree *meth, *end;
1189 tree binfos = TYPE_BINFO_BASETYPES (type);
1190 tree vb = CLASSTYPE_VBASECLASSES (type);
1191
1192 while (--i >= 0)
1193 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1194
1195 while (vb)
1196 {
1197 vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1198 offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1199 vb = TREE_CHAIN (vb);
1200 }
1201
1202 if (method_vec)
1203 for (meth = TREE_VEC_END (method_vec),
1204 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1205 if (*meth)
1206 {
1207 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1208 method_count++;
1209 }
1210 }
1211
1212 if (IS_AGGR_TYPE (type))
1213 {
1214 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1215 if (TREE_CODE (fields) == FIELD_DECL
1216 || TREE_CODE (fields) == VAR_DECL)
1217 {
1218 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1219 field_count++;
1220 }
1221 ivars = nreverse (ivars);
1222 }
1223
1224 parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1225 vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1226 offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1227 if (methods == NULL_TREE)
1228 methods = null_pointer_node;
1229 else
1230 methods = build_unary_op (ADDR_EXPR,
1231 finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1232 0);
1233 if (ivars == NULL_TREE)
1234 ivars = null_pointer_node;
1235 else
1236 ivars = build_unary_op (ADDR_EXPR,
1237 finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1238 0);
1239 if (TREE_TYPE (type))
1240 target_type = build_t_desc (TREE_TYPE (type), definition);
1241 else
1242 target_type = integer_zero_node;
1243
1244 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1245
1246 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1247 tree_cons (NULL_TREE,
1248 TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1249 /* really should use bitfield initialization here. */
1250 tree_cons (NULL_TREE, integer_zero_node,
1251 tree_cons (NULL_TREE, target_type,
1252 tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1253 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1254 tree_cons (NULL_TREE, ivars,
1255 tree_cons (NULL_TREE, methods,
1256 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1257 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1258 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1259 return build_generic_desc (tdecl, elems);
1260 }
1261
1262 /* Build an initializer for a __i_desc node. */
1263
1264 tree
1265 build_i_desc (decl)
1266 tree decl;
1267 {
1268 tree elems, name_string;
1269 tree taggr;
1270
1271 name_string = DECL_NAME (decl);
1272 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1273
1274 /* Now decide whether this ivar should cause it's type to get
1275 def'd or ref'd in this file. If the type we are looking at
1276 has a proxy definition, we look at the proxy (i.e., a
1277 `foo *' is equivalent to a `foo'). */
1278 taggr = TREE_TYPE (decl);
1279
1280 if ((TREE_CODE (taggr) == POINTER_TYPE
1281 || TREE_CODE (taggr) == REFERENCE_TYPE)
1282 && TYPE_VOLATILE (taggr) == 0)
1283 taggr = TREE_TYPE (taggr);
1284
1285 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1286 tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1287 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1288 ! IS_AGGR_TYPE (taggr)))));
1289 taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1290 TREE_CONSTANT (taggr) = 1;
1291 TREE_STATIC (taggr) = 1;
1292 TREE_READONLY (taggr) = 1;
1293 return taggr;
1294 }
1295
1296 /* Build an initializer for a __m_desc node. */
1297
1298 tree
1299 build_m_desc (decl)
1300 tree decl;
1301 {
1302 tree taggr, elems, name_string;
1303 tree parm_count, req_count, vindex, vcontext;
1304 tree parms;
1305 int p_count, r_count;
1306 tree parm_types = NULL_TREE;
1307
1308 for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1309 parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1310 {
1311 taggr = TREE_VALUE (parms);
1312 if ((TREE_CODE (taggr) == POINTER_TYPE
1313 || TREE_CODE (taggr) == REFERENCE_TYPE)
1314 && TYPE_VOLATILE (taggr) == 0)
1315 taggr = TREE_TYPE (taggr);
1316
1317 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1318 ! IS_AGGR_TYPE (taggr)),
1319 parm_types);
1320 if (TREE_PURPOSE (parms) == NULL_TREE)
1321 r_count++;
1322 }
1323
1324 parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1325 nreverse (parm_types), 0);
1326 parm_count = build_int_2 (p_count, 0);
1327 req_count = build_int_2 (r_count, 0);
1328
1329 if (DECL_VINDEX (decl))
1330 vindex = DECL_VINDEX (decl);
1331 else
1332 vindex = integer_zero_node;
1333 if (DECL_CONTEXT (decl)
1334 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1335 vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1336 else
1337 vcontext = integer_zero_node;
1338 name_string = DECL_NAME (decl);
1339 if (name_string == NULL)
1340 name_string = DECL_ASSEMBLER_NAME (decl);
1341 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1342
1343 /* Now decide whether the return type of this mvar
1344 should cause it's type to get def'd or ref'd in this file.
1345 If the type we are looking at has a proxy definition,
1346 we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
1347 taggr = TREE_TYPE (TREE_TYPE (decl));
1348
1349 if ((TREE_CODE (taggr) == POINTER_TYPE
1350 || TREE_CODE (taggr) == REFERENCE_TYPE)
1351 && TYPE_VOLATILE (taggr) == 0)
1352 taggr = TREE_TYPE (taggr);
1353
1354 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1355 tree_cons (NULL_TREE, vindex,
1356 tree_cons (NULL_TREE, vcontext,
1357 tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1358 ! IS_AGGR_TYPE (taggr)),
1359 tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
1360 tree_cons (NULL_TREE, parm_count,
1361 tree_cons (NULL_TREE, req_count,
1362 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1363
1364 taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1365 TREE_CONSTANT (taggr) = 1;
1366 TREE_STATIC (taggr) = 1;
1367 TREE_READONLY (taggr) = 1;
1368 return taggr;
1369 }
1370 #endif /* dossier */
This page took 0.097213 seconds and 5 git commands to generate.