]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/rtti.c
90th Cygnus<->FSF quick merge
[gcc.git] / gcc / cp / rtti.c
CommitLineData
84a43794
MS
1/* RunTime Type Identification
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
6b5fbb55 3 Mostly written by Jason Merrill (jason@cygnus.com).
84a43794
MS
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, 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"
c11b6f21 28#include "assert.h"
84a43794 29
5156628f
MS
30#ifndef INT_TYPE_SIZE
31#define INT_TYPE_SIZE BITS_PER_WORD
32#endif
33
84a43794
MS
34extern tree define_function ();
35extern tree build_t_desc_overload ();
36extern struct obstack *permanent_obstack;
37
6b5fbb55
MS
38tree type_info_type_node;
39tree tinfo_fn_id;
40tree tinfo_fn_type;
84a43794 41\f
6b5fbb55
MS
42void
43init_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. */
e92cc029 57
6b5fbb55
MS
58static tree
59build_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. */
e92cc029 74
5566b478 75static tree
84a43794
MS
76build_headof (exp)
77 tree exp;
78{
79 tree type = TREE_TYPE (exp);
6b5fbb55 80 tree aref;
de22184b 81 tree offset;
84a43794
MS
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
6b5fbb55 90 if (!TYPE_VIRTUAL_P (type))
84a43794
MS
91 return exp;
92
6b5fbb55
MS
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);
84a43794
MS
101
102 if (flag_vtable_thunks)
6b5fbb55 103 offset = aref;
84a43794 104 else
6b5fbb55 105 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
84a43794
MS
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}
5156628f
MS
112
113/* Build a call to a generic entry point taking and returning void. */
114
115static tree
116call_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
147static tree
148throw_bad_cast ()
149{
150 return call_void_fn ("__throw_bad_cast");
151}
152
153static tree
154throw_bad_typeid ()
155{
156 return call_void_fn ("__throw_bad_typeid");
157}
84a43794 158\f
5156628f
MS
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. */
e92cc029 162
84a43794 163tree
5156628f 164get_tinfo_fn_dynamic (exp)
84a43794
MS
165 tree exp;
166{
167 tree type;
168
84a43794
MS
169 if (exp == error_mark_node)
170 return error_mark_node;
171
9a3b49ac
MS
172 if (type_unknown_p (exp))
173 {
174 error ("typeid of overloaded function");
175 return error_mark_node;
176 }
177
84a43794
MS
178 type = TREE_TYPE (exp);
179
e92cc029 180 /* peel back references, so they match. */
84a43794
MS
181 if (TREE_CODE (type) == REFERENCE_TYPE)
182 type = TREE_TYPE (type);
183
e92cc029 184 /* Peel off cv qualifiers. */
84a43794
MS
185 type = TYPE_MAIN_VARIANT (type);
186
84a43794 187 /* If exp is a reference to polymorphic type, get the real type_info. */
5156628f 188 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
84a43794
MS
189 {
190 /* build reference to type_info from vtable. */
191 tree t;
192
6b5fbb55
MS
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. */
5156628f 197 if (! CLASSTYPE_VFIELDS (type))
6b5fbb55
MS
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
84a43794 204 if (flag_vtable_thunks)
6b5fbb55 205 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
84a43794 206 else
6b5fbb55
MS
207 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
208 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
5156628f 209 return t;
84a43794
MS
210 }
211
212 /* otherwise return the type_info for the static type of the expr. */
5156628f
MS
213 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
214}
215
216tree
217build_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
225tree
226build_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);
9a3b49ac
MS
247
248 if (exp == error_mark_node)
249 return error_mark_node;
250
5156628f
MS
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);
84a43794
MS
264}
265
824b9a4c 266static tree
6b5fbb55
MS
267get_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))
5156628f 281 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
6b5fbb55
MS
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
5156628f 295 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
6b5fbb55
MS
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
319tree
320get_tinfo_fn (type)
321 tree type;
322{
9a3b49ac 323 tree name;
6b5fbb55
MS
324 tree d;
325
9a3b49ac
MS
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
6b5fbb55
MS
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;
9a3b49ac 345 TREE_TYPE (name) = copy_to_permanent (type);
6b5fbb55
MS
346 pushdecl_top_level (d);
347 make_function_rtl (d);
67d743fe 348 assemble_external (d);
6b5fbb55
MS
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
824b9a4c 358static tree
6b5fbb55
MS
359get_typeid_1 (type)
360 tree type;
361{
5156628f
MS
362 tree t = build_call
363 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
6b5fbb55
MS
364 return convert_from_reference (t);
365}
366
84a43794 367/* Return the type_info object for TYPE, creating it if necessary. */
e92cc029 368
84a43794
MS
369tree
370get_typeid (type)
371 tree type;
372{
84a43794
MS
373 if (type == error_mark_node)
374 return error_mark_node;
375
6b5fbb55
MS
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. */
84a43794
MS
379 if (TREE_CODE (type) == REFERENCE_TYPE)
380 type = TREE_TYPE (type);
381
6b5fbb55 382 /* The top-level cv-qualifiers of the lvalue expression or the type-id
e92cc029 383 that is the operand of typeid are always ignored. */
6b5fbb55 384 type = TYPE_MAIN_VARIANT (type);
84a43794 385
6b5fbb55 386 return get_typeid_1 (type);
84a43794
MS
387}
388
a80e4195
MS
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
824b9a4c 392static tree
e92cc029 393ifnonnull (test, result)
a80e4195
MS
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
84a43794
MS
402/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
403 paper. */
6b5fbb55 404
84a43794
MS
405tree
406build_dynamic_cast (type, expr)
407 tree type, expr;
408{
409 enum tree_code tc = TREE_CODE (type);
410 tree exprtype = TREE_TYPE (expr);
c11b6f21 411 enum tree_code ec;
6b5fbb55 412 tree dcast_fn;
84a43794
MS
413
414 if (type == error_mark_node || expr == error_mark_node)
415 return error_mark_node;
416
5156628f 417 if (processing_template_decl)
e92cc029
MS
418 {
419 tree t = build_min (DYNAMIC_CAST_EXPR, type, expr);
420 return t;
421 }
422
c11b6f21
MS
423 assert (exprtype != NULL_TREE);
424 ec = TREE_CODE (exprtype);
425
84a43794
MS
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;
cdf5b885 439 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
84a43794
MS
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:
cdf5b885
MS
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;
84a43794
MS
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;
cdf5b885 475 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
84a43794
MS
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 {
a80e4195 497 tree expr1;
84a43794
MS
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
a80e4195
MS
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);
84a43794
MS
515 }
516 else
517 {
518 tree retval;
a80e4195 519 tree result, td1, td2, td3, elems, expr2;
84a43794
MS
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);
6b5fbb55 530 return throw_bad_cast ();
84a43794
MS
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
6b5fbb55
MS
548 /* Since expr is used twice below, save it. */
549 expr = save_expr (expr);
550
84a43794
MS
551 expr1 = expr;
552 if (tc == REFERENCE_TYPE)
553 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
554
555 /* Build run-time conversion. */
6b5fbb55 556 expr2 = build_headof (expr1);
84a43794
MS
557
558 if (ec == POINTER_TYPE)
5156628f 559 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
84a43794 560 else
5156628f
MS
561 td1 = get_tinfo_fn_dynamic (expr);
562 td1 = decay_conversion (td1);
84a43794 563
5156628f
MS
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))));
6b5fbb55
MS
568
569 elems = tree_cons
5156628f
MS
570 (NULL_TREE, td1, tree_cons
571 (NULL_TREE, td2, tree_cons
6b5fbb55
MS
572 (NULL_TREE, build_int_2 (1, 0), tree_cons
573 (NULL_TREE, expr2, tree_cons
5156628f 574 (NULL_TREE, td3, tree_cons
6b5fbb55
MS
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);
6b5fbb55 585 tmp = tree_cons
5156628f
MS
586 (NULL_TREE, TREE_TYPE (td1), tree_cons
587 (NULL_TREE, TREE_TYPE (td1), tree_cons
6b5fbb55
MS
588 (NULL_TREE, integer_type_node, tree_cons
589 (NULL_TREE, ptr_type_node, tree_cons
5156628f 590 (NULL_TREE, TREE_TYPE (td1), tree_cons
6b5fbb55
MS
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);
67d743fe 599 assemble_external (dcast_fn);
6b5fbb55
MS
600 pop_obstacks ();
601 }
602
5156628f
MS
603 result = build_call
604 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
84a43794
MS
605
606 if (tc == REFERENCE_TYPE)
607 {
6b5fbb55 608 expr1 = throw_bad_cast ();
5156628f
MS
609 expr1 = build_compound_expr
610 (tree_cons (NULL_TREE, expr1,
611 build_tree_list (NULL_TREE, convert
612 (type, integer_zero_node))));
84a43794
MS
613 TREE_TYPE (expr1) = type;
614 result = save_expr (result);
615 return build (COND_EXPR, type, result, result, expr1);
616 }
617
e92cc029 618 /* Now back to the type we want from a void*. */
84a43794 619 result = convert (type, result);
a80e4195 620 return ifnonnull (expr, result);
84a43794
MS
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
6b5fbb55 644extern tree const_string_type_node;
84a43794 645
6b5fbb55 646/* Build an initializer for a __si_type_info node. */
84a43794 647
6b5fbb55
MS
648static void
649expand_si_desc (tdecl, type)
84a43794
MS
650 tree tdecl;
651 tree type;
652{
6b5fbb55
MS
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);
84a43794
MS
668 else
669 {
6b5fbb55
MS
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);
67d743fe 685 assemble_external (fn);
6b5fbb55 686 pop_obstacks ();
84a43794
MS
687 }
688
5156628f 689 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
6b5fbb55 690 expand_expr_stmt (fn);
84a43794
MS
691}
692
e92cc029 693/* Build an initializer for a __class_type_info node. */
6b5fbb55
MS
694
695static void
696expand_class_desc (tdecl, type)
84a43794
MS
697 tree tdecl;
698 tree type;
699{
84a43794 700 tree name_string;
6b5fbb55
MS
701 tree fn, tmp;
702 char *name;
84a43794
MS
703
704 int i = CLASSTYPE_N_BASECLASSES (type);
84a43794
MS
705 int base_cnt = 0;
706 tree binfos = TYPE_BINFO_BASETYPES (type);
5566b478
MS
707#if 0
708 /* See code below that used these. */
84a43794 709 tree vb = CLASSTYPE_VBASECLASSES (type);
5566b478
MS
710 int n_base = i;
711#endif
84a43794 712 tree base, elems, access, offset, isvir;
6b5fbb55
MS
713 tree elt, elts = NULL_TREE;
714 static tree base_info_type_node;
84a43794 715
6b5fbb55 716 if (base_info_type_node == NULL_TREE)
84a43794 717 {
6b5fbb55
MS
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
5156628f 730 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
6b5fbb55
MS
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 ();
84a43794
MS
748 }
749
84a43794
MS
750 while (--i >= 0)
751 {
752 tree binfo = TREE_VEC_ELT (binfos, i);
753
6b5fbb55
MS
754 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
755 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
756
84a43794
MS
757 if (TREE_VIA_VIRTUAL (binfo))
758 {
759 tree t = BINFO_TYPE (binfo);
760 char *name;
761 tree field;
84a43794
MS
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))
6b5fbb55 773 access = access_public_node;
84a43794 774 else if (TREE_VIA_PROTECTED (binfo))
6b5fbb55 775 access = access_protected_node;
84a43794 776 else
6b5fbb55 777 access = access_private_node;
84a43794 778 if (TREE_VIA_VIRTUAL (binfo))
6b5fbb55 779 isvir = boolean_true_node;
84a43794 780 else
6b5fbb55
MS
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);
84a43794
MS
791 base_cnt++;
792 }
793#if 0
794 i = n_base;
795 while (vb)
796 {
797 tree b;
6b5fbb55 798 access = access_public_node;
84a43794
MS
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))
6b5fbb55 805 access = access_public_node;
84a43794 806 else if (TREE_VIA_PROTECTED (b))
6b5fbb55 807 access = access_protected_node;
84a43794 808 else
6b5fbb55 809 access = access_private_node;
84a43794
MS
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
84a43794 826
6b5fbb55
MS
827 name = build_overload_name (type, 1, 1);
828 name_string = combine_strings (build_string (strlen (name), name));
84a43794 829
6b5fbb55
MS
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 }
84a43794 837
6b5fbb55
MS
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))));
84a43794 843
6b5fbb55
MS
844 fn = get_identifier ("__rtti_class");
845 if (IDENTIFIER_GLOBAL_VALUE (fn))
846 fn = IDENTIFIER_GLOBAL_VALUE (fn);
84a43794
MS
847 else
848 {
6b5fbb55
MS
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);
67d743fe 863 assemble_external (fn);
6b5fbb55 864 pop_obstacks ();
84a43794 865 }
84a43794 866
5156628f 867 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
6b5fbb55 868 expand_expr_stmt (fn);
84a43794
MS
869}
870
6b5fbb55 871/* Build an initializer for a __pointer_type_info node. */
e92cc029 872
6b5fbb55
MS
873static void
874expand_ptr_desc (tdecl, type)
84a43794
MS
875 tree tdecl;
876 tree type;
877{
6b5fbb55
MS
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);
67d743fe 910 assemble_external (fn);
6b5fbb55
MS
911 pop_obstacks ();
912 }
913
5156628f 914 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
6b5fbb55 915 expand_expr_stmt (fn);
84a43794
MS
916}
917
6b5fbb55 918/* Build an initializer for a __attr_type_info node. */
84a43794
MS
919
920static void
6b5fbb55
MS
921expand_attr_desc (tdecl, type)
922 tree tdecl;
84a43794
MS
923 tree type;
924{
6b5fbb55
MS
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);
67d743fe 959 assemble_external (fn);
6b5fbb55
MS
960 pop_obstacks ();
961 }
84a43794 962
5156628f 963 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
6b5fbb55 964 expand_expr_stmt (fn);
84a43794
MS
965}
966
6b5fbb55 967/* Build an initializer for a type_info node that just has a name. */
84a43794 968
6b5fbb55
MS
969static void
970expand_generic_desc (tdecl, type, fnname)
971 tree tdecl;
84a43794 972 tree type;
6b5fbb55 973 char *fnname;
84a43794 974{
6b5fbb55
MS
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
84a43794 985 {
6b5fbb55
MS
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);
67d743fe 999 assemble_external (fn);
6b5fbb55 1000 pop_obstacks ();
84a43794 1001 }
84a43794 1002
5156628f 1003 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
6b5fbb55
MS
1004 expand_expr_stmt (fn);
1005}
84a43794 1006
6b5fbb55
MS
1007/* Generate the code for a type_info initialization function.
1008 Note that we take advantage of the passage
84a43794 1009
6b5fbb55
MS
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.
84a43794 1014
6b5fbb55
MS
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)! */
84a43794 1019
6b5fbb55
MS
1020void
1021synthesize_tinfo_fn (fndecl)
1022 tree fndecl;
1023{
1024 tree type = TREE_TYPE (DECL_NAME (fndecl));
1025 tree tmp, addr;
84a43794 1026
6b5fbb55
MS
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
c11b6f21 1035 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
6b5fbb55
MS
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);
84a43794 1047
5156628f
MS
1048 if (TREE_CODE (type) == FUNCTION_TYPE)
1049 expand_generic_desc (tdecl, type, "__rtti_func");
84a43794 1050 else if (TREE_CODE (type) == ARRAY_TYPE)
6b5fbb55 1051 expand_generic_desc (tdecl, type, "__rtti_array");
5156628f
MS
1052 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1053 expand_attr_desc (tdecl, type);
84a43794
MS
1054 else if (TREE_CODE (type) == POINTER_TYPE)
1055 {
1056 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
6b5fbb55
MS
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");
84a43794 1060 else
6b5fbb55 1061 expand_ptr_desc (tdecl, type);
84a43794 1062 }
6b5fbb55
MS
1063 else if (TYPE_PTRMEMFUNC_P (type))
1064 expand_generic_desc (tdecl, type, "__rtti_ptmf");
84a43794
MS
1065 else if (IS_AGGR_TYPE (type))
1066 {
6b5fbb55
MS
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);
84a43794 1073 else
6b5fbb55 1074 expand_class_desc (tdecl, type);
84a43794 1075 }
6b5fbb55
MS
1076 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1077 expand_generic_desc (tdecl, type, "__rtti_user");
6b5fbb55
MS
1078 else
1079 my_friendly_abort (252);
84a43794 1080
6b5fbb55
MS
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);
84a43794
MS
1088}
1089
1090#if 0
1091/* This is the old dossier type descriptor generation code, it's much
e92cc029 1092 more extended than rtti. It's reserved for later use. */
84a43794
MS
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. */
e92cc029 1099
84a43794
MS
1100tree
1101build_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. */
e92cc029 1263
84a43794
MS
1264tree
1265build_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. */
e92cc029 1297
84a43794
MS
1298tree
1299build_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)),
faf5394a 1359 tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
84a43794
MS
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.222507 seconds and 5 git commands to generate.