]>
Commit | Line | Data |
---|---|---|
84a43794 | 1 | /* RunTime Type Identification |
a7189b49 | 2 | Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 |
fed3cef0 | 3 | Free Software Foundation, Inc. |
6b5fbb55 | 4 | Mostly written by Jason Merrill (jason@cygnus.com). |
84a43794 | 5 | |
f5adbb8d | 6 | This file is part of GCC. |
84a43794 | 7 | |
f5adbb8d | 8 | GCC is free software; you can redistribute it and/or modify |
84a43794 MS |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2, or (at your option) | |
11 | any later version. | |
12 | ||
f5adbb8d | 13 | GCC is distributed in the hope that it will be useful, |
84a43794 MS |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
f5adbb8d | 19 | along with GCC; see the file COPYING. If not, write to |
84a43794 MS |
20 | the Free Software Foundation, 59 Temple Place - Suite 330, |
21 | Boston, MA 02111-1307, USA. */ | |
22 | ||
23 | ||
24 | #include "config.h" | |
8d052bc7 | 25 | #include "system.h" |
4977bab6 ZW |
26 | #include "coretypes.h" |
27 | #include "tm.h" | |
84a43794 MS |
28 | #include "tree.h" |
29 | #include "cp-tree.h" | |
30 | #include "flags.h" | |
31 | #include "output.h" | |
c11b6f21 | 32 | #include "assert.h" |
54f92bfb | 33 | #include "toplev.h" |
5156628f | 34 | |
d689a8f1 NS |
35 | /* C++ returns type information to the user in struct type_info |
36 | objects. We also use type information to implement dynamic_cast and | |
37 | exception handlers. Type information for a particular type is | |
38 | indicated with an ABI defined structure derived from type_info. | |
39 | This would all be very straight forward, but for the fact that the | |
40 | runtime library provides the definitions of the type_info structure | |
41 | and the ABI defined derived classes. We cannot build declarations | |
42 | of them directly in the compiler, but we need to layout objects of | |
43 | their type. Somewhere we have to lie. | |
44 | ||
45 | We define layout compatible POD-structs with compiler-defined names | |
46 | and generate the appropriate initializations for them (complete | |
47 | with explicit mention of their vtable). When we have to provide a | |
48 | type_info to the user we reinterpret_cast the internal compiler | |
49 | type to type_info. A well formed program can only explicitly refer | |
50 | to the type_infos of complete types (& cv void). However, we chain | |
51 | pointer type_infos to the pointed-to-type, and that can be | |
52 | incomplete. We only need the addresses of such incomplete | |
53 | type_info objects for static initialization. | |
54 | ||
55 | The type information VAR_DECL of a type is held on the | |
56 | IDENTIFIER_GLOBAL_VALUE of the type's mangled name. That VAR_DECL | |
57 | will be the internal type. It will usually have the correct | |
58 | internal type reflecting the kind of type it represents (pointer, | |
59 | array, function, class, inherited class, etc). When the type it | |
60 | represents is incomplete, it will have the internal type | |
61 | corresponding to type_info. That will only happen at the end of | |
62 | translation, when we are emitting the type info objects. */ | |
63 | ||
7267d692 NS |
64 | /* Accessors for the type_info objects. We need to remember several things |
65 | about each of the type_info types. The global tree nodes such as | |
66 | bltn_desc_type_node are TREE_LISTs, and these macros are used to access | |
c6002625 KH |
67 | the required information. */ |
68 | /* The RECORD_TYPE of a type_info derived class. */ | |
7267d692 | 69 | #define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE) |
d689a8f1 | 70 | /* The VAR_DECL of the vtable for the type_info derived class. |
c6002625 | 71 | This is only filled in at the end of the translation. */ |
7267d692 | 72 | #define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE) |
c6002625 | 73 | /* The IDENTIFIER_NODE naming the real class. */ |
d689a8f1 | 74 | #define TINFO_REAL_NAME(NODE) TREE_PURPOSE (NODE) |
84a43794 | 75 | |
a260bce6 MA |
76 | /* A varray of all tinfo decls that haven't yet been emitted. */ |
77 | varray_type unemitted_tinfo_decls; | |
78 | ||
cec57f72 NN |
79 | static tree build_headof (tree); |
80 | static tree ifnonnull (tree, tree); | |
81 | static tree tinfo_name (tree); | |
82 | static tree build_dynamic_cast_1 (tree, tree); | |
83 | static tree throw_bad_cast (void); | |
84 | static tree throw_bad_typeid (void); | |
85 | static tree get_tinfo_decl_dynamic (tree); | |
86 | static tree get_tinfo_ptr (tree); | |
87 | static bool typeid_ok_p (void); | |
88 | static int qualifier_flags (tree); | |
848eed92 | 89 | static bool target_incomplete_p (tree); |
cec57f72 NN |
90 | static tree tinfo_base_init (tree, tree); |
91 | static tree generic_initializer (tree, tree); | |
848eed92 GDR |
92 | static tree ptr_initializer (tree, tree, bool *); |
93 | static tree ptm_initializer (tree, tree, bool *); | |
cec57f72 NN |
94 | static tree dfs_class_hint_mark (tree, void *); |
95 | static tree dfs_class_hint_unmark (tree, void *); | |
96 | static int class_hint_flags (tree); | |
97 | static tree class_initializer (tree, tree, tree); | |
98 | static tree create_pseudo_type_info (const char *, int, ...); | |
99 | static tree get_pseudo_ti_init (tree, tree, bool *); | |
100 | static tree get_pseudo_ti_desc (tree); | |
101 | static void create_tinfo_types (void); | |
848eed92 | 102 | static bool typeinfo_in_lib_p (tree); |
cec57f72 | 103 | static bool unemitted_tinfo_decl_p (tree); |
7267d692 NS |
104 | |
105 | static int doing_runtime = 0; | |
84a43794 | 106 | \f |
d689a8f1 NS |
107 | |
108 | /* Declare language defined type_info type and a pointer to const | |
109 | type_info. This is incomplete here, and will be completed when | |
110 | the user #includes <typeinfo>. There are language defined | |
111 | restrictions on what can be done until that is included. Create | |
112 | the internal versions of the ABI types. */ | |
113 | ||
6b5fbb55 | 114 | void |
848eed92 | 115 | init_rtti_processing (void) |
6b5fbb55 | 116 | { |
a723baf1 MM |
117 | tree const_type_info_type; |
118 | ||
1dbb6023 | 119 | push_namespace (std_identifier); |
88e5899c MM |
120 | type_info_type_node |
121 | = xref_tag (class_type, get_identifier ("type_info"), | |
122 | /*attributes=*/NULL_TREE, 1); | |
1dbb6023 | 123 | pop_namespace (); |
a723baf1 MM |
124 | const_type_info_type = build_qualified_type (type_info_type_node, |
125 | TYPE_QUAL_CONST); | |
126 | type_info_ptr_type = build_pointer_type (const_type_info_type); | |
127 | type_info_ref_type = build_reference_type (const_type_info_type); | |
d689a8f1 | 128 | |
a260bce6 MA |
129 | VARRAY_TREE_INIT (unemitted_tinfo_decls, 10, "RTTI decls"); |
130 | ||
d689a8f1 | 131 | create_tinfo_types (); |
6b5fbb55 MS |
132 | } |
133 | ||
6b5fbb55 MS |
134 | /* Given the expression EXP of type `class *', return the head of the |
135 | object pointed to by EXP with type cv void*, if the class has any | |
4c6b7393 | 136 | virtual functions (TYPE_POLYMORPHIC_P), else just return the |
6b5fbb55 | 137 | expression. */ |
e92cc029 | 138 | |
5566b478 | 139 | static tree |
848eed92 | 140 | build_headof (tree exp) |
84a43794 MS |
141 | { |
142 | tree type = TREE_TYPE (exp); | |
de22184b | 143 | tree offset; |
da3d4dfa | 144 | tree index; |
84a43794 | 145 | |
e5f614d7 | 146 | my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112); |
84a43794 MS |
147 | type = TREE_TYPE (type); |
148 | ||
4c6b7393 | 149 | if (!TYPE_POLYMORPHIC_P (type)) |
84a43794 MS |
150 | return exp; |
151 | ||
6b5fbb55 MS |
152 | /* We use this a couple of times below, protect it. */ |
153 | exp = save_expr (exp); | |
154 | ||
3461fba7 | 155 | /* The offset-to-top field is at index -2 from the vptr. */ |
a6f5e048 | 156 | index = build_int_2 (-2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1); |
da3d4dfa | 157 | |
c4372ef4 | 158 | offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index); |
84a43794 | 159 | |
91063b51 | 160 | type = build_qualified_type (ptr_type_node, |
89d684bb | 161 | cp_type_quals (TREE_TYPE (exp))); |
84a43794 | 162 | return build (PLUS_EXPR, type, exp, |
37c46b43 | 163 | cp_convert (ptrdiff_type_node, offset)); |
84a43794 | 164 | } |
5156628f | 165 | |
5156628f MS |
166 | /* Get a bad_cast node for the program to throw... |
167 | ||
168 | See libstdc++/exception.cc for __throw_bad_cast */ | |
169 | ||
170 | static tree | |
848eed92 | 171 | throw_bad_cast (void) |
5156628f | 172 | { |
1f84ec23 | 173 | tree fn = get_identifier ("__cxa_bad_cast"); |
0c11ada6 JM |
174 | if (IDENTIFIER_GLOBAL_VALUE (fn)) |
175 | fn = IDENTIFIER_GLOBAL_VALUE (fn); | |
176 | else | |
cf74fb86 JM |
177 | fn = push_throw_library_fn (fn, build_function_type (ptr_type_node, |
178 | void_list_node)); | |
059fa5e7 | 179 | |
b2dd096b | 180 | return build_cxx_call (fn, NULL_TREE, NULL_TREE); |
5156628f MS |
181 | } |
182 | ||
2050a1bb MM |
183 | /* Return an expression for "__cxa_bad_typeid()". The expression |
184 | returned is an lvalue of type "const std::type_info". */ | |
185 | ||
5156628f | 186 | static tree |
848eed92 | 187 | throw_bad_typeid (void) |
5156628f | 188 | { |
1f84ec23 | 189 | tree fn = get_identifier ("__cxa_bad_typeid"); |
0c11ada6 JM |
190 | if (IDENTIFIER_GLOBAL_VALUE (fn)) |
191 | fn = IDENTIFIER_GLOBAL_VALUE (fn); | |
192 | else | |
cf74fb86 JM |
193 | { |
194 | tree t = build_qualified_type (type_info_type_node, TYPE_QUAL_CONST); | |
195 | t = build_function_type (build_reference_type (t), void_list_node); | |
196 | fn = push_throw_library_fn (fn, t); | |
197 | } | |
059fa5e7 | 198 | |
6adb9463 | 199 | return convert_from_reference (build_cxx_call (fn, NULL_TREE, NULL_TREE)); |
5156628f | 200 | } |
84a43794 | 201 | \f |
2050a1bb MM |
202 | /* Return an lvalue expression whose type is "const std::type_info" |
203 | and whose value indicates the type of the expression EXP. If EXP | |
204 | is a reference to a polymorphic class, return the dynamic type; | |
5156628f | 205 | otherwise return the static type of the expression. */ |
e92cc029 | 206 | |
e5f614d7 | 207 | static tree |
848eed92 | 208 | get_tinfo_decl_dynamic (tree exp) |
84a43794 MS |
209 | { |
210 | tree type; | |
2050a1bb | 211 | tree t; |
e5f614d7 | 212 | |
84a43794 MS |
213 | if (exp == error_mark_node) |
214 | return error_mark_node; | |
215 | ||
216 | type = TREE_TYPE (exp); | |
217 | ||
e92cc029 | 218 | /* peel back references, so they match. */ |
84a43794 MS |
219 | if (TREE_CODE (type) == REFERENCE_TYPE) |
220 | type = TREE_TYPE (type); | |
221 | ||
e92cc029 | 222 | /* Peel off cv qualifiers. */ |
84a43794 | 223 | type = TYPE_MAIN_VARIANT (type); |
e5f614d7 | 224 | |
b72801e2 | 225 | if (!VOID_TYPE_P (type)) |
e5f614d7 NS |
226 | type = complete_type_or_else (type, exp); |
227 | ||
228 | if (!type) | |
229 | return error_mark_node; | |
6a8f78d5 | 230 | |
84a43794 | 231 | /* If exp is a reference to polymorphic type, get the real type_info. */ |
4c6b7393 | 232 | if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0)) |
84a43794 MS |
233 | { |
234 | /* build reference to type_info from vtable. */ | |
da3d4dfa | 235 | tree index; |
84a43794 | 236 | |
8fa33dfa | 237 | /* The RTTI information is at index -1. */ |
a6f5e048 | 238 | index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1); |
b5d1cbd2 | 239 | t = build_vtbl_ref (exp, index); |
d689a8f1 | 240 | TREE_TYPE (t) = type_info_ptr_type; |
84a43794 | 241 | } |
2050a1bb MM |
242 | else |
243 | /* Otherwise return the type_info for the static type of the expr. */ | |
244 | t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type)); | |
84a43794 | 245 | |
2050a1bb | 246 | return build_indirect_ref (t, NULL); |
5156628f MS |
247 | } |
248 | ||
7f54a851 | 249 | static bool |
848eed92 | 250 | typeid_ok_p (void) |
5156628f | 251 | { |
f915e937 NS |
252 | if (! flag_rtti) |
253 | { | |
254 | error ("cannot use typeid with -fno-rtti"); | |
7f54a851 | 255 | return false; |
f915e937 NS |
256 | } |
257 | ||
d0f062fb | 258 | if (!COMPLETE_TYPE_P (type_info_type_node)) |
6a8f78d5 JM |
259 | { |
260 | error ("must #include <typeinfo> before using typeid"); | |
7f54a851 | 261 | return false; |
6a8f78d5 JM |
262 | } |
263 | ||
7f54a851 NS |
264 | return true; |
265 | } | |
266 | ||
2050a1bb MM |
267 | /* Return an expression for "typeid(EXP)". The expression returned is |
268 | an lvalue of type "const std::type_info". */ | |
269 | ||
7f54a851 | 270 | tree |
848eed92 | 271 | build_typeid (tree exp) |
7f54a851 NS |
272 | { |
273 | tree cond = NULL_TREE; | |
274 | int nonnull = 0; | |
275 | ||
276 | if (exp == error_mark_node || !typeid_ok_p ()) | |
277 | return error_mark_node; | |
278 | ||
5156628f | 279 | if (processing_template_decl) |
a723baf1 | 280 | return build_min (TYPEID_EXPR, type_info_ref_type, exp); |
5156628f MS |
281 | |
282 | if (TREE_CODE (exp) == INDIRECT_REF | |
283 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE | |
4c6b7393 | 284 | && TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) |
5156628f MS |
285 | && ! resolves_to_fixed_type_p (exp, &nonnull) |
286 | && ! nonnull) | |
287 | { | |
288 | exp = stabilize_reference (exp); | |
37c46b43 | 289 | cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); |
5156628f MS |
290 | } |
291 | ||
e5f614d7 | 292 | exp = get_tinfo_decl_dynamic (exp); |
9a3b49ac MS |
293 | |
294 | if (exp == error_mark_node) | |
295 | return error_mark_node; | |
296 | ||
5156628f MS |
297 | if (cond) |
298 | { | |
299 | tree bad = throw_bad_typeid (); | |
300 | ||
e5f614d7 | 301 | exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad); |
5156628f MS |
302 | } |
303 | ||
2050a1bb | 304 | return exp; |
84a43794 MS |
305 | } |
306 | ||
db1147b2 NS |
307 | /* Generate the NTBS name of a type. */ |
308 | static tree | |
848eed92 | 309 | tinfo_name (tree type) |
db1147b2 | 310 | { |
1f6e1acc AS |
311 | const char *name; |
312 | tree name_string; | |
313 | ||
1f84ec23 | 314 | name = mangle_type_string (type); |
b84a3874 | 315 | name_string = fix_string_type (build_string (strlen (name) + 1, name)); |
db1147b2 NS |
316 | return name_string; |
317 | } | |
318 | ||
d689a8f1 NS |
319 | /* Return a VAR_DECL for the internal ABI defined type_info object for |
320 | TYPE. You must arrange that the decl is mark_used, if actually use | |
321 | it --- decls in vtables are only used if the vtable is output. */ | |
794d4a61 | 322 | |
6b5fbb55 | 323 | tree |
848eed92 | 324 | get_tinfo_decl (tree type) |
6b5fbb55 | 325 | { |
9a3b49ac | 326 | tree name; |
6b5fbb55 MS |
327 | tree d; |
328 | ||
0c918ce5 MM |
329 | if (COMPLETE_TYPE_P (type) |
330 | && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) | |
331 | { | |
33bd39a2 | 332 | error ("cannot create type information for type `%T' because its size is variable", |
d689a8f1 | 333 | type); |
0c918ce5 MM |
334 | return error_mark_node; |
335 | } | |
336 | ||
9a3b49ac MS |
337 | if (TREE_CODE (type) == OFFSET_TYPE) |
338 | type = TREE_TYPE (type); | |
339 | if (TREE_CODE (type) == METHOD_TYPE) | |
340 | type = build_function_type (TREE_TYPE (type), | |
341 | TREE_CHAIN (TYPE_ARG_TYPES (type))); | |
342 | ||
a82d6da5 MM |
343 | /* For a class type, the variable is cached in the type node |
344 | itself. */ | |
345 | if (CLASS_TYPE_P (type)) | |
346 | { | |
347 | d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)); | |
348 | if (d) | |
349 | return d; | |
350 | } | |
351 | ||
1f84ec23 | 352 | name = mangle_typeinfo_for_type (type); |
669ec2b4 | 353 | |
7267d692 | 354 | d = IDENTIFIER_GLOBAL_VALUE (name); |
d689a8f1 | 355 | if (!d) |
7267d692 | 356 | { |
d689a8f1 NS |
357 | tree var_desc = get_pseudo_ti_desc (type); |
358 | ||
359 | d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc)); | |
7267d692 NS |
360 | |
361 | DECL_ARTIFICIAL (d) = 1; | |
7267d692 NS |
362 | TREE_READONLY (d) = 1; |
363 | TREE_STATIC (d) = 1; | |
364 | DECL_EXTERNAL (d) = 1; | |
92643fea | 365 | SET_DECL_ASSEMBLER_NAME (d, name); |
58f05188 | 366 | DECL_COMDAT (d) = 1; |
67f7c391 | 367 | |
170b020f | 368 | pushdecl_top_level_and_finish (d, NULL_TREE); |
d689a8f1 | 369 | |
a82d6da5 MM |
370 | if (CLASS_TYPE_P (type)) |
371 | CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; | |
372 | ||
7267d692 NS |
373 | /* Remember the type it is for. */ |
374 | TREE_TYPE (name) = type; | |
a260bce6 MA |
375 | |
376 | /* Add decl to the global array of tinfo decls. */ | |
377 | my_friendly_assert (unemitted_tinfo_decls != 0, 20030312); | |
378 | VARRAY_PUSH_TREE (unemitted_tinfo_decls, d); | |
7267d692 | 379 | } |
d689a8f1 | 380 | |
6b5fbb55 MS |
381 | return d; |
382 | } | |
383 | ||
d689a8f1 NS |
384 | /* Return a pointer to a type_info object describing TYPE, suitably |
385 | cast to the language defined type. */ | |
386 | ||
387 | static tree | |
848eed92 | 388 | get_tinfo_ptr (tree type) |
d689a8f1 | 389 | { |
bb4f6e6b JH |
390 | tree decl = get_tinfo_decl (type); |
391 | ||
392 | mark_used (decl); | |
3d938426 | 393 | return build_nop (type_info_ptr_type, |
bb4f6e6b | 394 | build_address (decl)); |
d689a8f1 NS |
395 | } |
396 | ||
e5f614d7 | 397 | /* Return the type_info object for TYPE. */ |
e92cc029 | 398 | |
84a43794 | 399 | tree |
848eed92 | 400 | get_typeid (tree type) |
84a43794 | 401 | { |
7f54a851 | 402 | if (type == error_mark_node || !typeid_ok_p ()) |
84a43794 | 403 | return error_mark_node; |
6a8f78d5 | 404 | |
e9f32eb5 | 405 | if (processing_template_decl) |
a723baf1 | 406 | return build_min (TYPEID_EXPR, type_info_ref_type, type); |
e9f32eb5 | 407 | |
6b5fbb55 MS |
408 | /* If the type of the type-id is a reference type, the result of the |
409 | typeid expression refers to a type_info object representing the | |
410 | referenced type. */ | |
84a43794 MS |
411 | if (TREE_CODE (type) == REFERENCE_TYPE) |
412 | type = TREE_TYPE (type); | |
413 | ||
6b5fbb55 | 414 | /* The top-level cv-qualifiers of the lvalue expression or the type-id |
e92cc029 | 415 | that is the operand of typeid are always ignored. */ |
6b5fbb55 | 416 | type = TYPE_MAIN_VARIANT (type); |
84a43794 | 417 | |
b72801e2 | 418 | if (!VOID_TYPE_P (type)) |
e5f614d7 NS |
419 | type = complete_type_or_else (type, NULL_TREE); |
420 | ||
421 | if (!type) | |
422 | return error_mark_node; | |
6a8f78d5 | 423 | |
d689a8f1 | 424 | return build_indirect_ref (get_tinfo_ptr (type), NULL); |
84a43794 MS |
425 | } |
426 | ||
a80e4195 MS |
427 | /* Check whether TEST is null before returning RESULT. If TEST is used in |
428 | RESULT, it must have previously had a save_expr applied to it. */ | |
429 | ||
824b9a4c | 430 | static tree |
848eed92 | 431 | ifnonnull (tree test, tree result) |
a80e4195 MS |
432 | { |
433 | return build (COND_EXPR, TREE_TYPE (result), | |
434 | build (EQ_EXPR, boolean_type_node, test, integer_zero_node), | |
37c46b43 | 435 | cp_convert (TREE_TYPE (result), integer_zero_node), |
a80e4195 MS |
436 | result); |
437 | } | |
438 | ||
84a43794 MS |
439 | /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working |
440 | paper. */ | |
6b5fbb55 | 441 | |
42976354 | 442 | static tree |
848eed92 | 443 | build_dynamic_cast_1 (tree type, tree expr) |
84a43794 MS |
444 | { |
445 | enum tree_code tc = TREE_CODE (type); | |
2bdb0643 | 446 | tree exprtype = TREE_TYPE (expr); |
6b5fbb55 | 447 | tree dcast_fn; |
6a8f78d5 | 448 | tree old_expr = expr; |
c2e407f1 | 449 | const char *errstr = NULL; |
84a43794 | 450 | |
64b83f2a SG |
451 | /* T shall be a pointer or reference to a complete class type, or |
452 | `pointer to cv void''. */ | |
84a43794 MS |
453 | switch (tc) |
454 | { | |
455 | case POINTER_TYPE: | |
64b83f2a | 456 | if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE) |
84a43794 | 457 | break; |
84a43794 | 458 | case REFERENCE_TYPE: |
64b83f2a SG |
459 | if (! IS_AGGR_TYPE (TREE_TYPE (type))) |
460 | { | |
461 | errstr = "target is not pointer or reference to class"; | |
462 | goto fail; | |
463 | } | |
d0f062fb | 464 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type)))) |
64b83f2a SG |
465 | { |
466 | errstr = "target is not pointer or reference to complete type"; | |
467 | goto fail; | |
468 | } | |
cdf5b885 | 469 | break; |
64b83f2a | 470 | |
84a43794 | 471 | default: |
64b83f2a | 472 | errstr = "target is not pointer or reference"; |
84a43794 MS |
473 | goto fail; |
474 | } | |
475 | ||
64b83f2a | 476 | if (TREE_CODE (expr) == OFFSET_REF) |
2bdb0643 JM |
477 | { |
478 | expr = resolve_offset_ref (expr); | |
479 | exprtype = TREE_TYPE (expr); | |
480 | } | |
64b83f2a SG |
481 | |
482 | if (tc == POINTER_TYPE) | |
483 | expr = convert_from_reference (expr); | |
484 | else if (TREE_CODE (exprtype) != REFERENCE_TYPE) | |
84a43794 | 485 | { |
64b83f2a | 486 | /* Apply trivial conversion T -> T& for dereferenced ptrs. */ |
84a43794 MS |
487 | exprtype = build_reference_type (exprtype); |
488 | expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, | |
489 | LOOKUP_NORMAL, NULL_TREE); | |
84a43794 MS |
490 | } |
491 | ||
64b83f2a SG |
492 | exprtype = TREE_TYPE (expr); |
493 | ||
494 | if (tc == POINTER_TYPE) | |
84a43794 | 495 | { |
64b83f2a SG |
496 | /* If T is a pointer type, v shall be an rvalue of a pointer to |
497 | complete class type, and the result is an rvalue of type T. */ | |
498 | ||
499 | if (TREE_CODE (exprtype) != POINTER_TYPE) | |
500 | { | |
501 | errstr = "source is not a pointer"; | |
502 | goto fail; | |
503 | } | |
504 | if (! IS_AGGR_TYPE (TREE_TYPE (exprtype))) | |
505 | { | |
506 | errstr = "source is not a pointer to class"; | |
507 | goto fail; | |
508 | } | |
d0f062fb | 509 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype)))) |
64b83f2a SG |
510 | { |
511 | errstr = "source is a pointer to incomplete type"; | |
512 | goto fail; | |
513 | } | |
514 | } | |
515 | else | |
516 | { | |
517 | /* T is a reference type, v shall be an lvalue of a complete class | |
518 | type, and the result is an lvalue of the type referred to by T. */ | |
519 | ||
520 | if (! IS_AGGR_TYPE (TREE_TYPE (exprtype))) | |
521 | { | |
522 | errstr = "source is not of class type"; | |
523 | goto fail; | |
524 | } | |
d0f062fb | 525 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype)))) |
64b83f2a SG |
526 | { |
527 | errstr = "source is of incomplete class type"; | |
528 | goto fail; | |
529 | } | |
530 | ||
531 | } | |
532 | ||
533 | /* The dynamic_cast operator shall not cast away constness. */ | |
534 | if (!at_least_as_qualified_p (TREE_TYPE (type), | |
535 | TREE_TYPE (exprtype))) | |
536 | { | |
537 | errstr = "conversion casts away constness"; | |
538 | goto fail; | |
84a43794 MS |
539 | } |
540 | ||
541 | /* If *type is an unambiguous accessible base class of *exprtype, | |
542 | convert statically. */ | |
543 | { | |
338d90b8 | 544 | tree binfo; |
84a43794 | 545 | |
338d90b8 NS |
546 | binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type), |
547 | ba_not_special, NULL); | |
6a8f78d5 | 548 | |
338d90b8 | 549 | if (binfo) |
6a8f78d5 | 550 | { |
338d90b8 NS |
551 | expr = build_base_path (PLUS_EXPR, convert_from_reference (expr), |
552 | binfo, 0); | |
2bdb0643 JM |
553 | if (TREE_CODE (exprtype) == POINTER_TYPE) |
554 | expr = non_lvalue (expr); | |
555 | return expr; | |
556 | } | |
84a43794 MS |
557 | } |
558 | ||
559 | /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ | |
4c6b7393 | 560 | if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype))) |
84a43794 | 561 | { |
a80e4195 | 562 | tree expr1; |
84a43794 | 563 | /* if TYPE is `void *', return pointer to complete object. */ |
b72801e2 | 564 | if (tc == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (type))) |
84a43794 MS |
565 | { |
566 | /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ | |
567 | if (TREE_CODE (expr) == ADDR_EXPR | |
568 | && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL | |
569 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) | |
570 | return build1 (NOP_EXPR, type, expr); | |
571 | ||
a80e4195 MS |
572 | /* Since expr is used twice below, save it. */ |
573 | expr = save_expr (expr); | |
574 | ||
575 | expr1 = build_headof (expr); | |
576 | if (TREE_TYPE (expr1) != type) | |
577 | expr1 = build1 (NOP_EXPR, type, expr1); | |
578 | return ifnonnull (expr, expr1); | |
84a43794 MS |
579 | } |
580 | else | |
581 | { | |
582 | tree retval; | |
7267d692 | 583 | tree result, td2, td3, elems; |
4a9e5c67 | 584 | tree static_type, target_type, boff; |
84a43794 MS |
585 | |
586 | /* If we got here, we can't convert statically. Therefore, | |
587 | dynamic_cast<D&>(b) (b an object) cannot succeed. */ | |
64b83f2a | 588 | if (tc == REFERENCE_TYPE) |
84a43794 | 589 | { |
6a8f78d5 JM |
590 | if (TREE_CODE (old_expr) == VAR_DECL |
591 | && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) | |
84a43794 | 592 | { |
059fa5e7 | 593 | tree expr = throw_bad_cast (); |
33bd39a2 | 594 | warning ("dynamic_cast of `%#D' to `%#T' can never succeed", |
6a8f78d5 | 595 | old_expr, type); |
059fa5e7 NS |
596 | /* Bash it to the expected type. */ |
597 | TREE_TYPE (expr) = type; | |
598 | return expr; | |
84a43794 MS |
599 | } |
600 | } | |
601 | /* Ditto for dynamic_cast<D*>(&b). */ | |
602 | else if (TREE_CODE (expr) == ADDR_EXPR) | |
603 | { | |
604 | tree op = TREE_OPERAND (expr, 0); | |
605 | if (TREE_CODE (op) == VAR_DECL | |
606 | && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) | |
607 | { | |
33bd39a2 | 608 | warning ("dynamic_cast of `%#D' to `%#T' can never succeed", |
ecfafc1c | 609 | op, type); |
84a43794 MS |
610 | retval = build_int_2 (0, 0); |
611 | TREE_TYPE (retval) = type; | |
612 | return retval; | |
613 | } | |
614 | } | |
615 | ||
7267d692 NS |
616 | target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); |
617 | static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); | |
bb4f6e6b JH |
618 | td2 = get_tinfo_decl (target_type); |
619 | mark_used (td2); | |
620 | td2 = build_unary_op (ADDR_EXPR, td2, 0); | |
621 | td3 = get_tinfo_decl (static_type); | |
622 | mark_used (td3); | |
623 | td3 = build_unary_op (ADDR_EXPR, td3, 0); | |
7267d692 NS |
624 | |
625 | /* Determine how T and V are related. */ | |
626 | boff = get_dynamic_cast_base_type (static_type, target_type); | |
627 | ||
6b5fbb55 MS |
628 | /* Since expr is used twice below, save it. */ |
629 | expr = save_expr (expr); | |
630 | ||
84a43794 MS |
631 | expr1 = expr; |
632 | if (tc == REFERENCE_TYPE) | |
633 | expr1 = build_unary_op (ADDR_EXPR, expr1, 0); | |
634 | ||
8fa33dfa MM |
635 | elems = tree_cons |
636 | (NULL_TREE, expr1, tree_cons | |
637 | (NULL_TREE, td3, tree_cons | |
638 | (NULL_TREE, td2, tree_cons | |
639 | (NULL_TREE, boff, NULL_TREE)))); | |
6b5fbb55 | 640 | |
059fa5e7 NS |
641 | dcast_fn = dynamic_cast_node; |
642 | if (!dcast_fn) | |
6b5fbb55 MS |
643 | { |
644 | tree tmp; | |
7267d692 | 645 | tree tinfo_ptr; |
8fa33dfa | 646 | tree ns = abi_node; |
7267d692 NS |
647 | const char *name; |
648 | ||
2854d3c6 | 649 | push_nested_namespace (ns); |
88e5899c | 650 | tinfo_ptr = xref_tag (class_type, |
8fa33dfa | 651 | get_identifier ("__class_type_info"), |
88e5899c | 652 | /*attributes=*/NULL_TREE, |
8fa33dfa MM |
653 | 1); |
654 | ||
655 | tinfo_ptr = build_pointer_type | |
656 | (build_qualified_type | |
657 | (tinfo_ptr, TYPE_QUAL_CONST)); | |
658 | name = "__dynamic_cast"; | |
659 | tmp = tree_cons | |
660 | (NULL_TREE, const_ptr_type_node, tree_cons | |
661 | (NULL_TREE, tinfo_ptr, tree_cons | |
662 | (NULL_TREE, tinfo_ptr, tree_cons | |
663 | (NULL_TREE, ptrdiff_type_node, void_list_node)))); | |
6b5fbb55 | 664 | tmp = build_function_type (ptr_type_node, tmp); |
7e8dad18 | 665 | dcast_fn = build_library_fn_ptr (name, tmp); |
7267d692 NS |
666 | pop_nested_namespace (ns); |
667 | dynamic_cast_node = dcast_fn; | |
6b5fbb55 | 668 | } |
b2dd096b | 669 | result = build_cxx_call (dcast_fn, elems, elems); |
84a43794 MS |
670 | |
671 | if (tc == REFERENCE_TYPE) | |
672 | { | |
7267d692 NS |
673 | tree bad = throw_bad_cast (); |
674 | ||
84a43794 | 675 | result = save_expr (result); |
7267d692 | 676 | return build (COND_EXPR, type, result, result, bad); |
84a43794 MS |
677 | } |
678 | ||
e92cc029 | 679 | /* Now back to the type we want from a void*. */ |
37c46b43 | 680 | result = cp_convert (type, result); |
a80e4195 | 681 | return ifnonnull (expr, result); |
84a43794 MS |
682 | } |
683 | } | |
64b83f2a SG |
684 | else |
685 | errstr = "source type is not polymorphic"; | |
0f4d5c1c | 686 | |
84a43794 | 687 | fail: |
33bd39a2 | 688 | error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T' (%s)", |
64b83f2a | 689 | expr, exprtype, type, errstr); |
84a43794 MS |
690 | return error_mark_node; |
691 | } | |
42976354 BK |
692 | |
693 | tree | |
848eed92 | 694 | build_dynamic_cast (tree type, tree expr) |
42976354 | 695 | { |
328d03d7 JM |
696 | if (type == error_mark_node || expr == error_mark_node) |
697 | return error_mark_node; | |
698 | ||
699 | if (processing_template_decl) | |
2a1e9fdd | 700 | return build_min (DYNAMIC_CAST_EXPR, type, expr); |
328d03d7 | 701 | |
42976354 BK |
702 | return convert_from_reference (build_dynamic_cast_1 (type, expr)); |
703 | } | |
84a43794 | 704 | \f |
7267d692 NS |
705 | /* Return the runtime bit mask encoding the qualifiers of TYPE. */ |
706 | ||
707 | static int | |
848eed92 | 708 | qualifier_flags (tree type) |
7267d692 NS |
709 | { |
710 | int flags = 0; | |
05abed76 | 711 | int quals = cp_type_quals (type); |
7267d692 NS |
712 | |
713 | if (quals & TYPE_QUAL_CONST) | |
714 | flags |= 1; | |
715 | if (quals & TYPE_QUAL_VOLATILE) | |
716 | flags |= 2; | |
6d61f400 NS |
717 | if (quals & TYPE_QUAL_RESTRICT) |
718 | flags |= 4; | |
7267d692 NS |
719 | return flags; |
720 | } | |
721 | ||
848eed92 | 722 | /* Return true, if the pointer chain TYPE ends at an incomplete type, or |
0a240972 NS |
723 | contains a pointer to member of an incomplete class. */ |
724 | ||
848eed92 GDR |
725 | static bool |
726 | target_incomplete_p (tree type) | |
0a240972 NS |
727 | { |
728 | while (TREE_CODE (type) == POINTER_TYPE) | |
729 | if (TYPE_PTRMEM_P (type)) | |
730 | { | |
731 | if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))) | |
848eed92 | 732 | return true; |
0a240972 NS |
733 | type = TYPE_PTRMEM_POINTED_TO_TYPE (type); |
734 | } | |
735 | else | |
736 | type = TREE_TYPE (type); | |
737 | if (!COMPLETE_OR_VOID_TYPE_P (type)) | |
848eed92 | 738 | return true; |
0a240972 | 739 | |
848eed92 | 740 | return false; |
0a240972 NS |
741 | } |
742 | ||
7267d692 | 743 | /* Return a CONSTRUCTOR for the common part of the type_info objects. This |
0a240972 NS |
744 | is the vtable pointer and NTBS name. The NTBS name is emitted as a |
745 | comdat const char array, so it becomes a unique key for the type. Generate | |
746 | and emit that VAR_DECL here. (We can't always emit the type_info itself | |
747 | as comdat, because of pointers to incomplete.) */ | |
7267d692 NS |
748 | |
749 | static tree | |
848eed92 | 750 | tinfo_base_init (tree desc, tree target) |
7267d692 | 751 | { |
7267d692 | 752 | tree init = NULL_TREE; |
0a240972 | 753 | tree name_decl; |
d689a8f1 | 754 | tree vtable_ptr; |
0a240972 NS |
755 | |
756 | { | |
1f6e1acc AS |
757 | tree name_name; |
758 | ||
0a240972 | 759 | /* Generate the NTBS array variable. */ |
0a240972 NS |
760 | tree name_type = build_cplus_array_type |
761 | (build_qualified_type (char_type_node, TYPE_QUAL_CONST), | |
762 | NULL_TREE); | |
763 | tree name_string = tinfo_name (target); | |
1f6e1acc | 764 | |
1f84ec23 | 765 | name_name = mangle_typeinfo_string_for_type (target); |
0a240972 NS |
766 | name_decl = build_lang_decl (VAR_DECL, name_name, name_type); |
767 | ||
768 | DECL_ARTIFICIAL (name_decl) = 1; | |
769 | TREE_READONLY (name_decl) = 1; | |
770 | TREE_STATIC (name_decl) = 1; | |
771 | DECL_EXTERNAL (name_decl) = 0; | |
772 | TREE_PUBLIC (name_decl) = 1; | |
773 | comdat_linkage (name_decl); | |
3461fba7 NS |
774 | /* External name of the string containing the type's name has a |
775 | special name. */ | |
92643fea MM |
776 | SET_DECL_ASSEMBLER_NAME (name_decl, |
777 | mangle_typeinfo_string_for_type (target)); | |
0a240972 | 778 | DECL_INITIAL (name_decl) = name_string; |
bb4f6e6b | 779 | mark_used (name_decl); |
170b020f | 780 | pushdecl_top_level_and_finish (name_decl, name_string); |
0a240972 | 781 | } |
d689a8f1 NS |
782 | |
783 | vtable_ptr = TINFO_VTABLE_DECL (desc); | |
784 | if (!vtable_ptr) | |
7267d692 | 785 | { |
d689a8f1 NS |
786 | tree real_type; |
787 | ||
788 | push_nested_namespace (abi_node); | |
789 | real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), | |
790 | /*attributes=*/NULL_TREE, 1); | |
791 | pop_nested_namespace (abi_node); | |
792 | ||
793 | if (!COMPLETE_TYPE_P (real_type)) | |
794 | { | |
795 | /* We never saw a definition of this type, so we need to | |
796 | tell the compiler that this is an exported class, as | |
797 | indeed all of the __*_type_info classes are. */ | |
798 | SET_CLASSTYPE_INTERFACE_KNOWN (real_type); | |
799 | CLASSTYPE_INTERFACE_ONLY (real_type) = 1; | |
800 | } | |
801 | ||
802 | vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); | |
803 | vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); | |
804 | ||
805 | /* We need to point into the middle of the vtable. */ | |
806 | vtable_ptr = build | |
807 | (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, | |
808 | size_binop (MULT_EXPR, | |
809 | size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), | |
810 | TYPE_SIZE_UNIT (vtable_entry_type))); | |
811 | TREE_CONSTANT (vtable_ptr) = 1; | |
812 | ||
813 | TINFO_VTABLE_DECL (desc) = vtable_ptr; | |
7267d692 | 814 | } |
d689a8f1 NS |
815 | |
816 | init = tree_cons (NULL_TREE, vtable_ptr, init); | |
7267d692 | 817 | |
0a240972 | 818 | init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); |
7267d692 | 819 | |
dcf92453 | 820 | init = build_constructor (NULL_TREE, nreverse (init)); |
7267d692 NS |
821 | TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1; |
822 | init = tree_cons (NULL_TREE, init, NULL_TREE); | |
823 | ||
824 | return init; | |
825 | } | |
826 | ||
827 | /* Return the CONSTRUCTOR expr for a type_info of TYPE. DESC provides the | |
828 | information about the particular type_info derivation, which adds no | |
829 | additional fields to the type_info base. */ | |
830 | ||
831 | static tree | |
848eed92 | 832 | generic_initializer (tree desc, tree target) |
7267d692 NS |
833 | { |
834 | tree init = tinfo_base_init (desc, target); | |
835 | ||
dcf92453 | 836 | init = build_constructor (NULL_TREE, init); |
7267d692 NS |
837 | TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1; |
838 | return init; | |
839 | } | |
840 | ||
1f4cb92b | 841 | /* Return the CONSTRUCTOR expr for a type_info of pointer TYPE. |
7267d692 NS |
842 | DESC provides information about the particular type_info derivation, |
843 | which adds target type and qualifier flags members to the type_info base. */ | |
844 | ||
845 | static tree | |
848eed92 | 846 | ptr_initializer (tree desc, tree target, bool *non_public_ptr) |
7267d692 NS |
847 | { |
848 | tree init = tinfo_base_init (desc, target); | |
849 | tree to = TREE_TYPE (target); | |
850 | int flags = qualifier_flags (to); | |
848eed92 | 851 | bool incomplete = target_incomplete_p (to); |
7267d692 | 852 | |
0a240972 NS |
853 | if (incomplete) |
854 | { | |
855 | flags |= 8; | |
848eed92 | 856 | *non_public_ptr = true; |
0a240972 | 857 | } |
7267d692 NS |
858 | init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init); |
859 | init = tree_cons (NULL_TREE, | |
d689a8f1 | 860 | get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), |
7267d692 NS |
861 | init); |
862 | ||
dcf92453 | 863 | init = build_constructor (NULL_TREE, nreverse (init)); |
7267d692 NS |
864 | TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1; |
865 | return init; | |
866 | } | |
867 | ||
1f4cb92b | 868 | /* Return the CONSTRUCTOR expr for a type_info of pointer to member data TYPE. |
7267d692 | 869 | DESC provides information about the particular type_info derivation, |
0a240972 NS |
870 | which adds class, target type and qualifier flags members to the type_info |
871 | base. */ | |
7267d692 NS |
872 | |
873 | static tree | |
848eed92 | 874 | ptm_initializer (tree desc, tree target, bool *non_public_ptr) |
7267d692 NS |
875 | { |
876 | tree init = tinfo_base_init (desc, target); | |
877 | tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target); | |
878 | tree klass = TYPE_PTRMEM_CLASS_TYPE (target); | |
879 | int flags = qualifier_flags (to); | |
848eed92 | 880 | bool incomplete = target_incomplete_p (to); |
7267d692 | 881 | |
0a240972 NS |
882 | if (incomplete) |
883 | { | |
884 | flags |= 0x8; | |
848eed92 | 885 | *non_public_ptr = true; |
0a240972 NS |
886 | } |
887 | if (!COMPLETE_TYPE_P (klass)) | |
1b846ccc NS |
888 | { |
889 | flags |= 0x10; | |
848eed92 | 890 | *non_public_ptr = true; |
1b846ccc | 891 | } |
6d61f400 | 892 | init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init); |
7267d692 | 893 | init = tree_cons (NULL_TREE, |
d689a8f1 | 894 | get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), |
7267d692 | 895 | init); |
6d61f400 | 896 | init = tree_cons (NULL_TREE, |
d689a8f1 NS |
897 | get_tinfo_ptr (klass), |
898 | init); | |
7267d692 | 899 | |
dcf92453 | 900 | init = build_constructor (NULL_TREE, nreverse (init)); |
7267d692 NS |
901 | TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1; |
902 | return init; | |
903 | } | |
904 | ||
6dfc58ed NS |
905 | /* Check base BINFO to set hint flags in *DATA, which is really an int. |
906 | We use CLASSTYPE_MARKED to tag types we've found as non-virtual bases and | |
907 | CLASSTYPE_MARKED2 to tag those which are virtual bases. Remember it is | |
908 | possible for a type to be both a virtual and non-virtual base. */ | |
909 | ||
910 | static tree | |
848eed92 | 911 | dfs_class_hint_mark (tree binfo, void *data) |
6dfc58ed NS |
912 | { |
913 | tree basetype = BINFO_TYPE (binfo); | |
914 | int *hint = (int *) data; | |
915 | ||
916 | if (TREE_VIA_VIRTUAL (binfo)) | |
917 | { | |
918 | if (CLASSTYPE_MARKED (basetype)) | |
919 | *hint |= 1; | |
920 | if (CLASSTYPE_MARKED2 (basetype)) | |
921 | *hint |= 2; | |
922 | SET_CLASSTYPE_MARKED2 (basetype); | |
923 | } | |
924 | else | |
925 | { | |
926 | if (CLASSTYPE_MARKED (basetype) || CLASSTYPE_MARKED2 (basetype)) | |
927 | *hint |= 1; | |
928 | SET_CLASSTYPE_MARKED (basetype); | |
929 | } | |
6dfc58ed | 930 | return NULL_TREE; |
de94b46c | 931 | } |
6dfc58ed | 932 | |
c6002625 | 933 | /* Clear the base's dfs marks, after searching for duplicate bases. */ |
6dfc58ed NS |
934 | |
935 | static tree | |
848eed92 | 936 | dfs_class_hint_unmark (tree binfo, void *data ATTRIBUTE_UNUSED) |
6dfc58ed NS |
937 | { |
938 | tree basetype = BINFO_TYPE (binfo); | |
939 | ||
940 | CLEAR_CLASSTYPE_MARKED (basetype); | |
941 | CLEAR_CLASSTYPE_MARKED2 (basetype); | |
942 | return NULL_TREE; | |
943 | } | |
944 | ||
aba649ba | 945 | /* Determine the hint flags describing the features of a class's hierarchy. */ |
7267d692 NS |
946 | |
947 | static int | |
848eed92 | 948 | class_hint_flags (tree type) |
7267d692 NS |
949 | { |
950 | int hint_flags = 0; | |
6dfc58ed NS |
951 | |
952 | dfs_walk (TYPE_BINFO (type), dfs_class_hint_mark, NULL, &hint_flags); | |
953 | dfs_walk (TYPE_BINFO (type), dfs_class_hint_unmark, NULL, NULL); | |
7267d692 NS |
954 | |
955 | return hint_flags; | |
956 | } | |
957 | ||
958 | /* Return the CONSTRUCTOR expr for a type_info of class TYPE. | |
959 | DESC provides information about the particular __class_type_info derivation, | |
960 | which adds hint flags and TRAIL initializers to the type_info base. */ | |
961 | ||
962 | static tree | |
848eed92 | 963 | class_initializer (tree desc, tree target, tree trail) |
7267d692 NS |
964 | { |
965 | tree init = tinfo_base_init (desc, target); | |
7267d692 | 966 | |
7267d692 | 967 | TREE_CHAIN (init) = trail; |
dcf92453 | 968 | init = build_constructor (NULL_TREE, init); |
7267d692 NS |
969 | TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1; |
970 | return init; | |
971 | } | |
972 | ||
848eed92 | 973 | /* Returns true if the typeinfo for type should be placed in |
97458258 MM |
974 | the runtime library. */ |
975 | ||
848eed92 GDR |
976 | static bool |
977 | typeinfo_in_lib_p (tree type) | |
97458258 MM |
978 | { |
979 | /* The typeinfo objects for `T*' and `const T*' are in the runtime | |
980 | library for simple types T. */ | |
981 | if (TREE_CODE (type) == POINTER_TYPE | |
89d684bb BM |
982 | && (cp_type_quals (TREE_TYPE (type)) == TYPE_QUAL_CONST |
983 | || cp_type_quals (TREE_TYPE (type)) == TYPE_UNQUALIFIED)) | |
97458258 MM |
984 | type = TREE_TYPE (type); |
985 | ||
986 | switch (TREE_CODE (type)) | |
987 | { | |
988 | case INTEGER_TYPE: | |
989 | case BOOLEAN_TYPE: | |
990 | case CHAR_TYPE: | |
991 | case REAL_TYPE: | |
992 | case VOID_TYPE: | |
848eed92 | 993 | return true; |
97458258 MM |
994 | |
995 | default: | |
848eed92 | 996 | return false; |
97458258 MM |
997 | } |
998 | } | |
999 | ||
d689a8f1 | 1000 | /* Generate the initializer for the type info describing |
838dfd8a | 1001 | TYPE. VAR_DESC is a . NON_PUBLIC_P is set nonzero, if the VAR_DECL |
d689a8f1 NS |
1002 | should not be exported from this object file. This should only be |
1003 | called at the end of translation, when we know that no further | |
1004 | types will be completed. */ | |
7267d692 NS |
1005 | |
1006 | static tree | |
848eed92 | 1007 | get_pseudo_ti_init (tree type, tree var_desc, bool *non_public_p) |
7267d692 | 1008 | { |
d689a8f1 NS |
1009 | my_friendly_assert (at_eof, 20021120); |
1010 | switch (TREE_CODE (type)) | |
7267d692 NS |
1011 | { |
1012 | case POINTER_TYPE: | |
d689a8f1 NS |
1013 | if (TYPE_PTRMEM_P (type)) |
1014 | return ptm_initializer (var_desc, type, non_public_p); | |
7267d692 | 1015 | else |
d689a8f1 | 1016 | return ptr_initializer (var_desc, type, non_public_p); |
7267d692 | 1017 | break; |
7267d692 | 1018 | case ENUMERAL_TYPE: |
d689a8f1 | 1019 | return generic_initializer (var_desc, type); |
7267d692 NS |
1020 | break; |
1021 | case FUNCTION_TYPE: | |
d689a8f1 | 1022 | return generic_initializer (var_desc, type); |
7267d692 NS |
1023 | break; |
1024 | case ARRAY_TYPE: | |
d689a8f1 | 1025 | return generic_initializer (var_desc, type); |
7267d692 NS |
1026 | break; |
1027 | case UNION_TYPE: | |
1028 | case RECORD_TYPE: | |
d689a8f1 NS |
1029 | if (TYPE_PTRMEMFUNC_P (type)) |
1030 | return ptm_initializer (var_desc, type, non_public_p); | |
1031 | else if (var_desc == class_desc_type_node) | |
387769ed | 1032 | { |
d689a8f1 NS |
1033 | if (!COMPLETE_TYPE_P (type)) |
1034 | /* Emit a non-public class_type_info. */ | |
848eed92 | 1035 | *non_public_p = true; |
d689a8f1 | 1036 | return class_initializer (var_desc, type, NULL_TREE); |
7267d692 | 1037 | } |
d689a8f1 NS |
1038 | else if (var_desc == si_class_desc_type_node) |
1039 | { | |
1040 | tree base_binfos = BINFO_BASETYPES (TYPE_BINFO (type)); | |
1041 | tree base_binfo = TREE_VEC_ELT (base_binfos, 0); | |
1042 | tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo)); | |
1043 | tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE); | |
1044 | ||
1045 | return class_initializer (var_desc, type, base_inits); | |
1046 | } | |
7267d692 NS |
1047 | else |
1048 | { | |
d689a8f1 NS |
1049 | int hint = class_hint_flags (type); |
1050 | tree binfo = TYPE_BINFO (type); | |
7267d692 NS |
1051 | int nbases = BINFO_N_BASETYPES (binfo); |
1052 | tree base_binfos = BINFO_BASETYPES (binfo); | |
dbbf88d1 | 1053 | tree base_accesses = BINFO_BASEACCESSES (binfo); |
7267d692 | 1054 | tree base_inits = NULL_TREE; |
7267d692 NS |
1055 | int ix; |
1056 | ||
1057 | /* Generate the base information initializer. */ | |
1058 | for (ix = nbases; ix--;) | |
1059 | { | |
1060 | tree base_binfo = TREE_VEC_ELT (base_binfos, ix); | |
1061 | tree base_init = NULL_TREE; | |
1062 | int flags = 0; | |
1063 | tree tinfo; | |
1064 | tree offset; | |
1065 | ||
dbbf88d1 | 1066 | if (TREE_VEC_ELT (base_accesses, ix) == access_public_node) |
7267d692 | 1067 | flags |= 2; |
d689a8f1 | 1068 | tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo)); |
7f54a851 NS |
1069 | if (TREE_VIA_VIRTUAL (base_binfo)) |
1070 | { | |
1071 | /* We store the vtable offset at which the virtual | |
1072 | base offset can be found. */ | |
dbbf88d1 | 1073 | offset = BINFO_VPTR_FIELD (base_binfo); |
7f54a851 NS |
1074 | offset = convert (sizetype, offset); |
1075 | flags |= 1; | |
1076 | } | |
1077 | else | |
1078 | offset = BINFO_OFFSET (base_binfo); | |
7267d692 | 1079 | |
068feaa9 | 1080 | /* combine offset and flags into one field */ |
ab76ca54 MM |
1081 | offset = cp_build_binary_op (LSHIFT_EXPR, offset, |
1082 | build_int_2 (8, 0)); | |
1083 | offset = cp_build_binary_op (BIT_IOR_EXPR, offset, | |
1084 | build_int_2 (flags, 0)); | |
7267d692 NS |
1085 | base_init = tree_cons (NULL_TREE, offset, base_init); |
1086 | base_init = tree_cons (NULL_TREE, tinfo, base_init); | |
dcf92453 | 1087 | base_init = build_constructor (NULL_TREE, base_init); |
8e3df2de | 1088 | TREE_HAS_CONSTRUCTOR (base_init) = 1; |
7267d692 NS |
1089 | base_inits = tree_cons (NULL_TREE, base_init, base_inits); |
1090 | } | |
dcf92453 | 1091 | base_inits = build_constructor (NULL_TREE, base_inits); |
8e3df2de | 1092 | TREE_HAS_CONSTRUCTOR (base_inits) = 1; |
d689a8f1 NS |
1093 | base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); |
1094 | /* Prepend the number of bases. */ | |
1095 | base_inits = tree_cons (NULL_TREE, | |
1096 | build_int_2 (nbases, 0), base_inits); | |
c6002625 | 1097 | /* Prepend the hint flags. */ |
d689a8f1 NS |
1098 | base_inits = tree_cons (NULL_TREE, |
1099 | build_int_2 (hint, 0), base_inits); | |
1100 | ||
1101 | return class_initializer (var_desc, type, base_inits); | |
7267d692 NS |
1102 | } |
1103 | break; | |
97458258 | 1104 | |
7267d692 | 1105 | default: |
d689a8f1 | 1106 | return generic_initializer (var_desc, type); |
7267d692 | 1107 | } |
7267d692 NS |
1108 | } |
1109 | ||
1110 | /* Generate the RECORD_TYPE containing the data layout of a type_info | |
1111 | derivative as used by the runtime. This layout must be consistent with | |
1112 | that defined in the runtime support. Also generate the VAR_DECL for the | |
1113 | type's vtable. We explicitly manage the vtable member, and name it for | |
1114 | real type as used in the runtime. The RECORD type has a different name, | |
1115 | to avoid collisions. Return a TREE_LIST who's TINFO_PSEUDO_TYPE | |
d689a8f1 NS |
1116 | is the generated type and TINFO_VTABLE_NAME is the name of the |
1117 | vtable. We have to delay generating the VAR_DECL of the vtable | |
1118 | until the end of the translation, when we'll have seen the library | |
1119 | definition, if there was one. | |
7267d692 NS |
1120 | |
1121 | REAL_NAME is the runtime's name of the type. Trailing arguments are | |
1122 | additional FIELD_DECL's for the structure. The final argument must be | |
1123 | NULL. */ | |
1124 | ||
1125 | static tree | |
848eed92 | 1126 | create_pseudo_type_info (const char *real_name, int ident, ...) |
7267d692 | 1127 | { |
d689a8f1 | 1128 | tree pseudo_type; |
7267d692 | 1129 | char *pseudo_name; |
4977bab6 | 1130 | tree fields; |
7267d692 NS |
1131 | tree field_decl; |
1132 | tree result; | |
e34d07f2 | 1133 | va_list ap; |
7a75edb7 | 1134 | |
e34d07f2 | 1135 | va_start (ap, ident); |
7267d692 | 1136 | |
c6002625 | 1137 | /* Generate the pseudo type name. */ |
7267d692 NS |
1138 | pseudo_name = (char *)alloca (strlen (real_name) + 30); |
1139 | strcpy (pseudo_name, real_name); | |
1140 | strcat (pseudo_name, "_pseudo"); | |
1141 | if (ident) | |
1142 | sprintf (pseudo_name + strlen (pseudo_name), "%d", ident); | |
1143 | ||
c6002625 | 1144 | /* First field is the pseudo type_info base class. */ |
4977bab6 | 1145 | fields = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node); |
7267d692 NS |
1146 | |
1147 | /* Now add the derived fields. */ | |
4977bab6 ZW |
1148 | while ((field_decl = va_arg (ap, tree))) |
1149 | { | |
1150 | TREE_CHAIN (field_decl) = fields; | |
1151 | fields = field_decl; | |
1152 | } | |
7267d692 | 1153 | |
c6002625 | 1154 | /* Create the pseudo type. */ |
7267d692 | 1155 | pseudo_type = make_aggr_type (RECORD_TYPE); |
4977bab6 | 1156 | finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); |
8e3df2de | 1157 | CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; |
7a75edb7 | 1158 | |
7267d692 | 1159 | result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); |
d689a8f1 NS |
1160 | TINFO_REAL_NAME (result) = get_identifier (real_name); |
1161 | TINFO_PSEUDO_TYPE (result) = | |
1162 | cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); | |
7267d692 | 1163 | |
e34d07f2 | 1164 | va_end (ap); |
7267d692 NS |
1165 | return result; |
1166 | } | |
1167 | ||
d689a8f1 NS |
1168 | /* Return a pseudo type info type node used to describe TYPE. TYPE |
1169 | must be a complete type (or cv void), except at the end of the | |
1170 | translation unit. */ | |
7267d692 NS |
1171 | |
1172 | static tree | |
848eed92 | 1173 | get_pseudo_ti_desc (tree type) |
7267d692 | 1174 | { |
d689a8f1 | 1175 | switch (TREE_CODE (type)) |
7267d692 | 1176 | { |
d689a8f1 NS |
1177 | case POINTER_TYPE: |
1178 | return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node; | |
1179 | case ENUMERAL_TYPE: | |
1180 | return enum_desc_type_node; | |
1181 | case FUNCTION_TYPE: | |
1182 | return func_desc_type_node; | |
1183 | case ARRAY_TYPE: | |
1184 | return ary_desc_type_node; | |
1185 | case UNION_TYPE: | |
1186 | case RECORD_TYPE: | |
1187 | if (TYPE_PTRMEMFUNC_P (type)) | |
1188 | return ptm_desc_type_node; | |
1189 | else if (!COMPLETE_TYPE_P (type)) | |
1190 | { | |
5aa3396c JM |
1191 | if (!at_eof) |
1192 | cxx_incomplete_type_error (NULL_TREE, type); | |
d689a8f1 NS |
1193 | return class_desc_type_node; |
1194 | } | |
1195 | else if (!CLASSTYPE_N_BASECLASSES (type)) | |
1196 | return class_desc_type_node; | |
1197 | else | |
1198 | { | |
dbbf88d1 NS |
1199 | tree binfo = TYPE_BINFO (type); |
1200 | tree base_binfos = BINFO_BASETYPES (binfo); | |
1201 | tree base_accesses = BINFO_BASEACCESSES (binfo); | |
1202 | tree base_binfo = TREE_VEC_ELT (base_binfos, 0); | |
1203 | int num_bases = TREE_VEC_LENGTH (base_binfos); | |
d689a8f1 NS |
1204 | |
1205 | if (num_bases == 1 | |
dbbf88d1 | 1206 | && TREE_VEC_ELT (base_accesses, 0) == access_public_node |
d689a8f1 NS |
1207 | && !TREE_VIA_VIRTUAL (base_binfo) |
1208 | && integer_zerop (BINFO_OFFSET (base_binfo))) | |
c6002625 | 1209 | /* single non-virtual public. */ |
d689a8f1 NS |
1210 | return si_class_desc_type_node; |
1211 | else | |
1212 | { | |
1213 | tree var_desc; | |
1214 | tree array_domain, base_array; | |
1215 | ||
1216 | if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases) | |
1217 | { | |
1218 | int ix; | |
1219 | tree extend = make_tree_vec (num_bases + 5); | |
1220 | ||
1221 | for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;) | |
1222 | TREE_VEC_ELT (extend, ix) | |
1223 | = TREE_VEC_ELT (vmi_class_desc_type_node, ix); | |
1224 | vmi_class_desc_type_node = extend; | |
1225 | } | |
1226 | var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases); | |
1227 | if (var_desc) | |
1228 | return var_desc; | |
7267d692 | 1229 | |
5dae1114 MM |
1230 | /* Create the array of __base_class_type_info entries. |
1231 | G++ 3.2 allocated an array that had one too many | |
1232 | entries, and then filled that extra entries with | |
1233 | zeros. */ | |
1234 | if (abi_version_at_least (2)) | |
1235 | array_domain = build_index_type (size_int (num_bases - 1)); | |
1236 | else | |
1237 | array_domain = build_index_type (size_int (num_bases)); | |
d689a8f1 NS |
1238 | base_array = |
1239 | build_array_type (base_desc_type_node, array_domain); | |
1240 | ||
1241 | push_nested_namespace (abi_node); | |
1242 | var_desc = create_pseudo_type_info | |
1243 | ("__vmi_class_type_info", num_bases, | |
1244 | build_decl (FIELD_DECL, NULL_TREE, integer_type_node), | |
1245 | build_decl (FIELD_DECL, NULL_TREE, integer_type_node), | |
1246 | build_decl (FIELD_DECL, NULL_TREE, base_array), | |
1247 | NULL); | |
1248 | pop_nested_namespace (abi_node); | |
1249 | ||
1250 | TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc; | |
1251 | return var_desc; | |
1252 | } | |
1253 | } | |
1254 | default: | |
1255 | return bltn_desc_type_node; | |
1256 | } | |
7267d692 NS |
1257 | } |
1258 | ||
1259 | /* Make sure the required builtin types exist for generating the type_info | |
1260 | varable definitions. */ | |
1261 | ||
1262 | static void | |
848eed92 | 1263 | create_tinfo_types (void) |
7267d692 | 1264 | { |
d689a8f1 | 1265 | my_friendly_assert (!ti_desc_type_node, 20020609); |
7267d692 | 1266 | |
d689a8f1 | 1267 | push_nested_namespace (abi_node); |
7267d692 NS |
1268 | |
1269 | /* Create the internal type_info structure. This is used as a base for | |
1270 | the other structures. */ | |
1271 | { | |
4977bab6 | 1272 | tree field, fields; |
7267d692 NS |
1273 | |
1274 | ti_desc_type_node = make_aggr_type (RECORD_TYPE); | |
4977bab6 ZW |
1275 | field = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node); |
1276 | fields = field; | |
1277 | ||
1278 | field = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node); | |
1279 | TREE_CHAIN (field) = fields; | |
1280 | fields = field; | |
1281 | ||
1282 | finish_builtin_struct (ti_desc_type_node, "__type_info_pseudo", | |
1283 | fields, NULL_TREE); | |
7267d692 NS |
1284 | TYPE_HAS_CONSTRUCTOR (ti_desc_type_node) = 1; |
1285 | } | |
1286 | ||
1287 | /* Fundamental type_info */ | |
1288 | bltn_desc_type_node = create_pseudo_type_info | |
1289 | ("__fundamental_type_info", 0, | |
1290 | NULL); | |
1291 | ||
c6002625 | 1292 | /* Array, function and enum type_info. No additional fields. */ |
7267d692 NS |
1293 | ary_desc_type_node = create_pseudo_type_info |
1294 | ("__array_type_info", 0, | |
1295 | NULL); | |
1296 | func_desc_type_node = create_pseudo_type_info | |
1297 | ("__function_type_info", 0, | |
1298 | NULL); | |
1299 | enum_desc_type_node = create_pseudo_type_info | |
1300 | ("__enum_type_info", 0, | |
1301 | NULL); | |
1302 | ||
1303 | /* Class type_info. Add a flags field. */ | |
1304 | class_desc_type_node = create_pseudo_type_info | |
1305 | ("__class_type_info", 0, | |
7267d692 NS |
1306 | NULL); |
1307 | ||
6d61f400 NS |
1308 | /* Single public non-virtual base class. Add pointer to base class. |
1309 | This is really a descendant of __class_type_info. */ | |
7267d692 NS |
1310 | si_class_desc_type_node = create_pseudo_type_info |
1311 | ("__si_class_type_info", 0, | |
d689a8f1 | 1312 | build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), |
7267d692 NS |
1313 | NULL); |
1314 | ||
1315 | /* Base class internal helper. Pointer to base type, offset to base, | |
c6002625 | 1316 | flags. */ |
7267d692 | 1317 | { |
4977bab6 ZW |
1318 | tree field, fields; |
1319 | ||
1320 | field = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type); | |
1321 | fields = field; | |
7267d692 | 1322 | |
4977bab6 ZW |
1323 | field = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]); |
1324 | TREE_CHAIN (field) = fields; | |
1325 | fields = field; | |
1326 | ||
7267d692 | 1327 | base_desc_type_node = make_aggr_type (RECORD_TYPE); |
4977bab6 ZW |
1328 | finish_builtin_struct (base_desc_type_node, "__base_class_type_info_pseudo", |
1329 | fields, NULL_TREE); | |
7267d692 NS |
1330 | TYPE_HAS_CONSTRUCTOR (base_desc_type_node) = 1; |
1331 | } | |
1332 | ||
c6002625 | 1333 | /* General hierarchy is created as necessary in this vector. */ |
7267d692 NS |
1334 | vmi_class_desc_type_node = make_tree_vec (10); |
1335 | ||
387769ed NS |
1336 | /* Pointer type_info. Adds two fields, qualification mask |
1337 | and pointer to the pointed to type. This is really a descendant of | |
c6002625 | 1338 | __pbase_type_info. */ |
387769ed NS |
1339 | ptr_desc_type_node = create_pseudo_type_info |
1340 | ("__pointer_type_info", 0, | |
1341 | build_decl (FIELD_DECL, NULL_TREE, integer_type_node), | |
d689a8f1 | 1342 | build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), |
387769ed NS |
1343 | NULL); |
1344 | ||
6d61f400 NS |
1345 | /* Pointer to member data type_info. Add qualifications flags, |
1346 | pointer to the member's type info and pointer to the class. | |
387769ed NS |
1347 | This is really a descendant of __pbase_type_info. */ |
1348 | ptm_desc_type_node = create_pseudo_type_info | |
f03eebe3 | 1349 | ("__pointer_to_member_type_info", 0, |
721c3b42 | 1350 | build_decl (FIELD_DECL, NULL_TREE, integer_type_node), |
d689a8f1 NS |
1351 | build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), |
1352 | build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), | |
7267d692 NS |
1353 | NULL); |
1354 | ||
2854d3c6 | 1355 | pop_nested_namespace (abi_node); |
7267d692 NS |
1356 | } |
1357 | ||
1358 | /* Emit the type_info descriptors which are guaranteed to be in the runtime | |
1359 | support. Generating them here guarantees consistency with the other | |
1360 | structures. We use the following heuristic to determine when the runtime | |
7f54a851 | 1361 | is being generated. If std::__fundamental_type_info is defined, and its |
7267d692 NS |
1362 | destructor is defined, then the runtime is being built. */ |
1363 | ||
1364 | void | |
848eed92 | 1365 | emit_support_tinfos (void) |
7267d692 NS |
1366 | { |
1367 | static tree *const fundamentals[] = | |
1368 | { | |
1369 | &void_type_node, | |
1370 | &boolean_type_node, | |
1371 | &wchar_type_node, | |
7267d692 NS |
1372 | &char_type_node, &signed_char_type_node, &unsigned_char_type_node, |
1373 | &short_integer_type_node, &short_unsigned_type_node, | |
1374 | &integer_type_node, &unsigned_type_node, | |
1375 | &long_integer_type_node, &long_unsigned_type_node, | |
1376 | &long_long_integer_type_node, &long_long_unsigned_type_node, | |
1377 | &float_type_node, &double_type_node, &long_double_type_node, | |
7267d692 NS |
1378 | 0 |
1379 | }; | |
1380 | int ix; | |
1381 | tree bltn_type, dtor; | |
1382 | ||
2854d3c6 | 1383 | push_nested_namespace (abi_node); |
88e5899c MM |
1384 | bltn_type = xref_tag (class_type, |
1385 | get_identifier ("__fundamental_type_info"), | |
1386 | /*attributes=*/NULL_TREE, | |
1387 | 1); | |
2854d3c6 | 1388 | pop_nested_namespace (abi_node); |
d0f062fb | 1389 | if (!COMPLETE_TYPE_P (bltn_type)) |
7267d692 NS |
1390 | return; |
1391 | dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (bltn_type), 1); | |
1392 | if (DECL_EXTERNAL (dtor)) | |
1393 | return; | |
1394 | doing_runtime = 1; | |
1395 | for (ix = 0; fundamentals[ix]; ix++) | |
1396 | { | |
1397 | tree bltn = *fundamentals[ix]; | |
1398 | tree bltn_ptr = build_pointer_type (bltn); | |
1399 | tree bltn_const_ptr = build_pointer_type | |
1400 | (build_qualified_type (bltn, TYPE_QUAL_CONST)); | |
1401 | tree tinfo; | |
1402 | ||
1403 | tinfo = get_tinfo_decl (bltn); | |
1404 | TREE_USED (tinfo) = 1; | |
1405 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; | |
1406 | ||
1407 | tinfo = get_tinfo_decl (bltn_ptr); | |
1408 | TREE_USED (tinfo) = 1; | |
1409 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; | |
1410 | ||
1411 | tinfo = get_tinfo_decl (bltn_const_ptr); | |
1412 | TREE_USED (tinfo) = 1; | |
1413 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; | |
1414 | } | |
1415 | } | |
1416 | ||
848eed92 | 1417 | /* Return true, iff T is a type_info variable which has not had a |
7267d692 NS |
1418 | definition emitted for it. */ |
1419 | ||
a260bce6 MA |
1420 | static bool |
1421 | unemitted_tinfo_decl_p (tree t) | |
7267d692 | 1422 | { |
d689a8f1 NS |
1423 | if (/* It's a var decl */ |
1424 | TREE_CODE (t) == VAR_DECL | |
0ca7178c JM |
1425 | /* which has a name */ |
1426 | && DECL_NAME (t) | |
1427 | /* whose name points back to itself */ | |
d689a8f1 | 1428 | && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t |
03357c23 | 1429 | /* whose name's type is non-null */ |
d689a8f1 | 1430 | && TREE_TYPE (DECL_NAME (t)) |
03357c23 | 1431 | /* and whose type is a struct */ |
d689a8f1 | 1432 | && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE |
03357c23 NS |
1433 | /* with a field */ |
1434 | && TYPE_FIELDS (TREE_TYPE (t)) | |
1435 | /* which is our pseudo type info */ | |
d689a8f1 | 1436 | && TREE_TYPE (TYPE_FIELDS (TREE_TYPE (t))) == ti_desc_type_node) |
848eed92 GDR |
1437 | return true; |
1438 | return false; | |
7267d692 NS |
1439 | } |
1440 | ||
d689a8f1 NS |
1441 | /* Finish a type info decl. DECL_PTR is a pointer to an unemitted |
1442 | tinfo decl. Determine whether it needs emitting, and if so | |
1443 | generate the initializer. */ | |
7267d692 | 1444 | |
848eed92 | 1445 | bool |
a260bce6 | 1446 | emit_tinfo_decl (tree decl) |
7267d692 | 1447 | { |
d689a8f1 | 1448 | tree type = TREE_TYPE (DECL_NAME (decl)); |
848eed92 | 1449 | bool non_public; |
c6f553d1 | 1450 | int in_library = typeinfo_in_lib_p (type); |
d689a8f1 | 1451 | tree var_desc, var_init; |
a260bce6 MA |
1452 | |
1453 | my_friendly_assert (unemitted_tinfo_decl_p (decl), 20030307); | |
7267d692 | 1454 | |
c6f553d1 | 1455 | import_export_tinfo (decl, type, in_library); |
d689a8f1 | 1456 | if (DECL_REALLY_EXTERN (decl) || !DECL_NEEDED_P (decl)) |
848eed92 | 1457 | return false; |
ff48be5c | 1458 | |
c6f553d1 | 1459 | if (!doing_runtime && in_library) |
848eed92 | 1460 | return false; |
ff48be5c | 1461 | |
848eed92 | 1462 | non_public = false; |
d689a8f1 NS |
1463 | var_desc = get_pseudo_ti_desc (type); |
1464 | var_init = get_pseudo_ti_init (type, var_desc, &non_public); | |
c6f553d1 | 1465 | |
d689a8f1 NS |
1466 | DECL_EXTERNAL (decl) = 0; |
1467 | TREE_PUBLIC (decl) = !non_public; | |
c6f553d1 NS |
1468 | if (non_public) |
1469 | DECL_COMDAT (decl) = 0; | |
1470 | ||
d689a8f1 | 1471 | DECL_INITIAL (decl) = var_init; |
bb4f6e6b | 1472 | mark_used (decl); |
d689a8f1 | 1473 | cp_finish_decl (decl, var_init, NULL_TREE, 0); |
c6002625 | 1474 | /* cp_finish_decl will have dealt with linkage. */ |
d689a8f1 NS |
1475 | |
1476 | /* Say we've dealt with it. */ | |
1477 | TREE_TYPE (DECL_NAME (decl)) = NULL_TREE; | |
1478 | ||
848eed92 | 1479 | return true; |
7267d692 | 1480 | } |