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