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