X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Frtti.c;h=3fb6d11c0ce9b03a69a285556377e672539472c1;hb=f018965cc0bdfda6a7d8484744ca0a028e05bf50;hp=54d82c7165ebb9bd7cba2d5adaf5a759b654ef74;hpb=cc52f165509d9835f5bf10853b4e40a23ee75889;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 54d82c7165e..3fb6d11c0ce 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1,6 +1,6 @@ /* RunTime Type Identification Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005 + 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Mostly written by Jason Merrill (jason@cygnus.com). @@ -8,7 +8,7 @@ This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, @@ -17,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -32,6 +31,8 @@ Boston, MA 02110-1301, USA. */ #include "assert.h" #include "toplev.h" #include "convert.h" +#include "target.h" +#include "c-pragma.h" /* C++ returns type information to the user in struct type_info objects. We also use type information to implement dynamic_cast and @@ -63,8 +64,7 @@ Boston, MA 02110-1301, USA. */ translation, when we are emitting the type info objects. */ /* Auxiliary data we hold for each type_info derived object we need. */ -typedef struct tinfo_s GTY (()) -{ +typedef struct GTY (()) tinfo_s { tree type; /* The RECORD_TYPE for this type_info object */ tree vtable; /* The VAR_DECL of the vtable. Only filled at end of @@ -79,7 +79,7 @@ DEF_VEC_ALLOC_O(tinfo_s,gc); typedef enum tinfo_kind { - TK_TYPE_INFO_TYPE, /* std::type_info */ + TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */ TK_BASE_TYPE, /* abi::__base_class_type_info */ TK_BUILTIN_TYPE, /* abi::__fundamental_type_info */ TK_ARRAY_TYPE, /* abi::__array_type_info */ @@ -89,8 +89,8 @@ typedef enum tinfo_kind TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */ TK_CLASS_TYPE, /* abi::__class_type_info */ TK_SI_CLASS_TYPE, /* abi::__si_class_type_info */ - TK_FIXED /* end of fixed descriptors. */ - /* ... abi::__vmi_type_info */ + TK_FIXED /* end of fixed descriptors. */ + /* ... abi::__vmi_type_info */ } tinfo_kind; /* A vector of all tinfo decls that haven't yet been emitted. */ @@ -101,10 +101,9 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree build_headof (tree); static tree ifnonnull (tree, tree); -static tree tinfo_name (tree); -static tree build_dynamic_cast_1 (tree, tree); +static tree tinfo_name (tree, bool); +static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); static tree throw_bad_typeid (void); static tree get_tinfo_decl_dynamic (tree); @@ -125,6 +124,19 @@ static bool typeinfo_in_lib_p (tree); static int doing_runtime = 0; +static void +push_abi_namespace (void) +{ + push_nested_namespace (abi_node); + push_visibility ("default", 2); +} + +static void +pop_abi_namespace (void) +{ + pop_visibility (2); + pop_nested_namespace (abi_node); +} /* Declare language defined type_info type and a pointer to const type_info. This is incomplete here, and will be completed when @@ -155,7 +167,7 @@ init_rtti_processing (void) virtual functions (TYPE_POLYMORPHIC_P), else just return the expression. */ -static tree +tree build_headof (tree exp) { tree type = TREE_TYPE (exp); @@ -175,12 +187,14 @@ build_headof (tree exp) index = build_int_cst (NULL_TREE, -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); - offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index); + offset = build_vtbl_ref (cp_build_indirect_ref (exp, NULL, + tf_warning_or_error), + index); type = build_qualified_type (ptr_type_node, cp_type_quals (TREE_TYPE (exp))); - return build2 (PLUS_EXPR, type, exp, - convert_to_integer (ptrdiff_type_node, offset)); + return build2 (POINTER_PLUS_EXPR, type, exp, + convert_to_integer (sizetype, offset)); } /* Get a bad_cast node for the program to throw... @@ -195,7 +209,7 @@ throw_bad_cast (void) fn = push_throw_library_fn (fn, build_function_type (ptr_type_node, void_list_node)); - return build_cxx_call (fn, NULL_TREE); + return build_cxx_call (fn, 0, NULL); } /* Return an expression for "__cxa_bad_typeid()". The expression @@ -214,7 +228,7 @@ throw_bad_typeid (void) fn = push_throw_library_fn (fn, t); } - return build_cxx_call (fn, NULL_TREE); + return build_cxx_call (fn, 0, NULL); } /* Return an lvalue expression whose type is "const std::type_info" @@ -228,7 +242,7 @@ get_tinfo_decl_dynamic (tree exp) tree type; tree t; - if (exp == error_mark_node) + if (error_operand_p (exp)) return error_mark_node; /* peel back references, so they match. */ @@ -237,7 +251,8 @@ get_tinfo_decl_dynamic (tree exp) /* Peel off cv qualifiers. */ type = TYPE_MAIN_VARIANT (type); - if (!VOID_TYPE_P (type)) + /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics. */ + if (CLASS_TYPE_P (type) || TREE_CODE (type) == UNKNOWN_TYPE) type = complete_type_or_else (type, exp); if (!type) @@ -259,12 +274,14 @@ get_tinfo_decl_dynamic (tree exp) /* Otherwise return the type_info for the static type of the expr. */ t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type)); - return build_indirect_ref (t, NULL); + return cp_build_indirect_ref (t, NULL, tf_warning_or_error); } static bool typeid_ok_p (void) { + tree pseudo_type_info, type_info_type; + if (! flag_rtti) { error ("cannot use typeid with -fno-rtti"); @@ -277,6 +294,18 @@ typeid_ok_p (void) return false; } + pseudo_type_info + = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE)->type; + type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node); + + /* Make sure abi::__type_info_pseudo has the same alias set + as std::type_info. */ + if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info)) + TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type); + else + gcc_assert (TYPE_ALIAS_SET (pseudo_type_info) + == get_alias_set (type_info_type)); + return true; } @@ -320,16 +349,30 @@ build_typeid (tree exp) return exp; } -/* Generate the NTBS name of a type. */ +/* Generate the NTBS name of a type. If MARK_PRIVATE, put a '*' in front so that + comparisons will be done by pointer rather than string comparison. */ static tree -tinfo_name (tree type) +tinfo_name (tree type, bool mark_private) { const char *name; + int length; tree name_string; name = mangle_type_string (type); - name_string = fix_string_type (build_string (strlen (name) + 1, name)); - return name_string; + length = strlen (name); + + if (mark_private) + { + /* Inject '*' at beginning of name to force pointer comparison. */ + char* buf = (char*) XALLOCAVEC (char, length + 2); + buf[0] = '*'; + memcpy (buf + 1, name, length + 1); + name_string = build_string (length + 2, buf); + } + else + name_string = build_string (length + 1, name); + + return fix_string_type (name_string); } /* Return a VAR_DECL for the internal ABI defined type_info object for @@ -342,11 +385,10 @@ get_tinfo_decl (tree type) tree name; tree d; - if (COMPLETE_TYPE_P (type) - && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + if (variably_modified_type_p (type, /*fn=*/NULL_TREE)) { error ("cannot create type information for type %qT because " - "its size is variable", + "it involves types of variable size", type); return error_mark_node; } @@ -385,10 +427,11 @@ get_tinfo_decl (tree type) define it later if we need to do so. */ DECL_EXTERNAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; + set_linkage_according_to_type (type, d); + + d = pushdecl_top_level_and_finish (d, NULL_TREE); if (CLASS_TYPE_P (type)) CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; - set_linkage_according_to_type (type, d); - pushdecl_top_level_and_finish (d, NULL_TREE); /* Add decl to the global array of tinfo decls. */ VEC_safe_push (tree, gc, unemitted_tinfo_decls, d); @@ -430,13 +473,15 @@ get_typeid (tree type) that is the operand of typeid are always ignored. */ type = TYPE_MAIN_VARIANT (type); - if (!VOID_TYPE_P (type)) + /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics. */ + if (CLASS_TYPE_P (type) || TREE_CODE (type) == UNKNOWN_TYPE) type = complete_type_or_else (type, NULL_TREE); if (!type) return error_mark_node; - return build_indirect_ref (get_tinfo_ptr (type), NULL); + return cp_build_indirect_ref (get_tinfo_ptr (type), NULL, + tf_warning_or_error); } /* Check whether TEST is null before returning RESULT. If TEST is used in @@ -456,7 +501,7 @@ ifnonnull (tree test, tree result) paper. */ static tree -build_dynamic_cast_1 (tree type, tree expr) +build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) { enum tree_code tc = TREE_CODE (type); tree exprtype = TREE_TYPE (expr); @@ -464,6 +509,9 @@ build_dynamic_cast_1 (tree type, tree expr) tree old_expr = expr; const char *errstr = NULL; + /* Save casted types in the function's used types hash table. */ + used_types_insert (type); + /* T shall be a pointer or reference to a complete class type, or `pointer to cv void''. */ switch (tc) @@ -473,7 +521,7 @@ build_dynamic_cast_1 (tree type, tree expr) break; /* Fall through. */ case REFERENCE_TYPE: - if (! IS_AGGR_TYPE (TREE_TYPE (type))) + if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (type))) { errstr = "target is not pointer or reference to class"; goto fail; @@ -500,7 +548,7 @@ build_dynamic_cast_1 (tree type, tree expr) errstr = "source is not a pointer"; goto fail; } - if (! IS_AGGR_TYPE (TREE_TYPE (exprtype))) + if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype))) { errstr = "source is not a pointer to class"; goto fail; @@ -513,15 +561,12 @@ build_dynamic_cast_1 (tree type, tree expr) } else { - /* Apply trivial conversion T -> T& for dereferenced ptrs. */ exprtype = build_reference_type (exprtype); - expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); /* T is a reference type, v shall be an lvalue of a complete class type, and the result is an lvalue of the type referred to by T. */ - if (! IS_AGGR_TYPE (TREE_TYPE (exprtype))) + if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype))) { errstr = "source is not of class type"; goto fail; @@ -532,6 +577,9 @@ build_dynamic_cast_1 (tree type, tree expr) goto fail; } + /* Apply trivial conversion T -> T& for dereferenced ptrs. */ + expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, + LOOKUP_NORMAL, NULL_TREE); } /* The dynamic_cast operator shall not cast away constness. */ @@ -584,7 +632,8 @@ build_dynamic_cast_1 (tree type, tree expr) else { tree retval; - tree result, td2, td3, elems; + tree result, td2, td3; + tree elems[4]; tree static_type, target_type, boff; /* If we got here, we can't convert statically. Therefore, @@ -595,8 +644,9 @@ build_dynamic_cast_1 (tree type, tree expr) && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) { tree expr = throw_bad_cast (); - warning (0, "dynamic_cast of %q#D to %q#T can never succeed", - old_expr, type); + if (complain & tf_warning) + warning (0, "dynamic_cast of %q#D to %q#T can never succeed", + old_expr, type); /* Bash it to the expected type. */ TREE_TYPE (expr) = type; return expr; @@ -609,21 +659,30 @@ build_dynamic_cast_1 (tree type, tree expr) if (TREE_CODE (op) == VAR_DECL && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) { - warning (0, "dynamic_cast of %q#D to %q#T can never succeed", - op, type); + if (complain & tf_warning) + warning (0, "dynamic_cast of %q#D to %q#T can never succeed", + op, type); retval = build_int_cst (type, 0); return retval; } } + /* Use of dynamic_cast when -fno-rtti is prohibited. */ + if (!flag_rtti) + { + if (complain & tf_error) + error ("% not permitted with -fno-rtti"); + return error_mark_node; + } + target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); td2 = get_tinfo_decl (target_type); mark_used (td2); - td2 = build_unary_op (ADDR_EXPR, td2, 0); + td2 = cp_build_unary_op (ADDR_EXPR, td2, 0, complain); td3 = get_tinfo_decl (static_type); mark_used (td3); - td3 = build_unary_op (ADDR_EXPR, td3, 0); + td3 = cp_build_unary_op (ADDR_EXPR, td3, 0, complain); /* Determine how T and V are related. */ boff = dcast_base_hint (static_type, target_type); @@ -633,23 +692,21 @@ build_dynamic_cast_1 (tree type, tree expr) expr1 = expr; if (tc == REFERENCE_TYPE) - expr1 = build_unary_op (ADDR_EXPR, expr1, 0); + expr1 = cp_build_unary_op (ADDR_EXPR, expr1, 0, complain); - elems = tree_cons - (NULL_TREE, expr1, tree_cons - (NULL_TREE, td3, tree_cons - (NULL_TREE, td2, tree_cons - (NULL_TREE, boff, NULL_TREE)))); + elems[0] = expr1; + elems[1] = td3; + elems[2] = td2; + elems[3] = boff; dcast_fn = dynamic_cast_node; if (!dcast_fn) { tree tmp; tree tinfo_ptr; - tree ns = abi_node; const char *name; - push_nested_namespace (ns); + push_abi_namespace (); tinfo_ptr = xref_tag (class_type, get_identifier ("__class_type_info"), /*tag_scope=*/ts_current, false); @@ -665,18 +722,22 @@ build_dynamic_cast_1 (tree type, tree expr) (NULL_TREE, ptrdiff_type_node, void_list_node)))); tmp = build_function_type (ptr_type_node, tmp); dcast_fn = build_library_fn_ptr (name, tmp); - DECL_IS_PURE (dcast_fn) = 1; - pop_nested_namespace (ns); + DECL_PURE_P (dcast_fn) = 1; + pop_abi_namespace (); dynamic_cast_node = dcast_fn; } - result = build_cxx_call (dcast_fn, elems); + result = build_cxx_call (dcast_fn, 4, elems); if (tc == REFERENCE_TYPE) { tree bad = throw_bad_cast (); + tree neq; result = save_expr (result); - return build3 (COND_EXPR, type, result, result, bad); + neq = c_common_truthvalue_conversion (input_location, result); + return cp_convert (type, + build3 (COND_EXPR, TREE_TYPE (result), + neq, result, bad)); } /* Now back to the type we want from a void*. */ @@ -688,33 +749,26 @@ build_dynamic_cast_1 (tree type, tree expr) errstr = "source type is not polymorphic"; fail: - error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)", - expr, exprtype, type, errstr); + if (complain & tf_error) + error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)", + expr, exprtype, type, errstr); return error_mark_node; } tree -build_dynamic_cast (tree type, tree expr) +build_dynamic_cast (tree type, tree expr, tsubst_flags_t complain) { if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - /* Use of dynamic_cast when -fno-rtti is prohibited. */ - if (!flag_rtti) - { - error ("% not permitted with -fno-rtti"); - return error_mark_node; - } - if (processing_template_decl) { expr = build_min (DYNAMIC_CAST_EXPR, type, expr); TREE_SIDE_EFFECTS (expr) = 1; - - return expr; + return convert_from_reference (expr); } - return convert_from_reference (build_dynamic_cast_1 (type, expr)); + return convert_from_reference (build_dynamic_cast_1 (type, expr, complain)); } /* Return the runtime bit mask encoding the qualifiers of TYPE. */ @@ -799,13 +853,12 @@ tinfo_base_init (tinfo_s *ti, tree target) tree vtable_ptr; { - tree name_name; + tree name_name, name_string; /* Generate the NTBS array variable. */ tree name_type = build_cplus_array_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST), NULL_TREE); - tree name_string = tinfo_name (target); /* Determine the name of the variable -- and remember with which type it is associated. */ @@ -820,14 +873,9 @@ tinfo_base_init (tinfo_s *ti, tree target) TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; DECL_TINFO_P (name_decl) = 1; - if (involves_incomplete_p (target)) - { - TREE_PUBLIC (name_decl) = 0; - DECL_INTERFACE_KNOWN (name_decl) = 1; - } - else - set_linkage_according_to_type (target, name_decl); + set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); + name_string = tinfo_name (target, !TREE_PUBLIC (name_decl)); DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); @@ -837,10 +885,10 @@ tinfo_base_init (tinfo_s *ti, tree target) if (!vtable_ptr) { tree real_type; - push_nested_namespace (abi_node); + push_abi_namespace (); real_type = xref_tag (class_type, ti->name, /*tag_scope=*/ts_current, false); - pop_nested_namespace (abi_node); + pop_abi_namespace (); if (!COMPLETE_TYPE_P (real_type)) { @@ -852,15 +900,16 @@ tinfo_base_init (tinfo_s *ti, tree target) } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); - vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); + vtable_ptr = cp_build_unary_op (ADDR_EXPR, vtable_ptr, 0, + tf_warning_or_error); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 - (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, + (POINTER_PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, size_binop (MULT_EXPR, size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), TYPE_SIZE_UNIT (vtable_entry_type))); - + ti->vtable = vtable_ptr; } @@ -868,9 +917,8 @@ tinfo_base_init (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); @@ -885,10 +933,9 @@ static tree generic_initializer (tinfo_s *ti, tree target) { tree init = tinfo_base_init (ti, target); - - init = build_constructor_from_list (NULL_TREE, init); + + init = build_constructor_from_list (init_list_type_node, init); TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; } @@ -912,9 +959,8 @@ ptr_initializer (tinfo_s *ti, tree target) get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; } @@ -944,10 +990,9 @@ ptm_initializer (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, get_tinfo_ptr (klass), init); - - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; } @@ -962,9 +1007,8 @@ class_initializer (tinfo_s *ti, tree target, tree trail) tree init = tinfo_base_init (ti, target); TREE_CHAIN (init) = trail; - init = build_constructor_from_list (NULL_TREE, init); + init = build_constructor_from_list (init_list_type_node, init); TREE_CONSTANT (init) = 1; - TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; } @@ -986,7 +1030,6 @@ typeinfo_in_lib_p (tree type) { case INTEGER_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: case REAL_TYPE: case VOID_TYPE: return true; @@ -1003,16 +1046,16 @@ static tree get_pseudo_ti_init (tree type, unsigned tk_index) { tinfo_s *ti = VEC_index (tinfo_s, tinfo_descs, tk_index); - + gcc_assert (at_eof); switch (tk_index) { case TK_POINTER_MEMBER_TYPE: return ptm_initializer (ti, type); - + case TK_POINTER_TYPE: return ptr_initializer (ti, type); - + case TK_BUILTIN_TYPE: case TK_ENUMERAL_TYPE: case TK_FUNCTION_TYPE: @@ -1040,11 +1083,12 @@ get_pseudo_ti_init (tree type, unsigned tk_index) tree binfo = TYPE_BINFO (type); int nbases = BINFO_N_BASE_BINFOS (binfo); VEC(tree,gc) *base_accesses = BINFO_BASE_ACCESSES (binfo); + tree offset_type = integer_types[itk_long]; tree base_inits = NULL_TREE; int ix; - + gcc_assert (tk_index >= TK_FIXED); - + /* Generate the base information initializer. */ for (ix = nbases; ix--;) { @@ -1053,32 +1097,34 @@ get_pseudo_ti_init (tree type, unsigned tk_index) int flags = 0; tree tinfo; tree offset; - + if (VEC_index (tree, base_accesses, ix) == access_public_node) flags |= 2; tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo)); if (BINFO_VIRTUAL_P (base_binfo)) { /* We store the vtable offset at which the virtual - base offset can be found. */ + base offset can be found. */ offset = BINFO_VPTR_FIELD (base_binfo); - offset = convert (sizetype, offset); flags |= 1; } else offset = BINFO_OFFSET (base_binfo); - + /* Combine offset and flags into one field. */ - offset = cp_build_binary_op (LSHIFT_EXPR, offset, - build_int_cst (NULL_TREE, 8)); - offset = cp_build_binary_op (BIT_IOR_EXPR, offset, - build_int_cst (NULL_TREE, flags)); + offset = fold_convert (offset_type, offset); + offset = fold_build2_loc (input_location, + LSHIFT_EXPR, offset_type, offset, + build_int_cst (offset_type, 8)); + offset = fold_build2_loc (input_location, + BIT_IOR_EXPR, offset_type, offset, + build_int_cst (offset_type, flags)); base_init = tree_cons (NULL_TREE, offset, base_init); base_init = tree_cons (NULL_TREE, tinfo, base_init); - base_init = build_constructor_from_list (NULL_TREE, base_init); + base_init = build_constructor_from_list (init_list_type_node, base_init); base_inits = tree_cons (NULL_TREE, base_init, base_inits); } - base_inits = build_constructor_from_list (NULL_TREE, base_inits); + base_inits = build_constructor_from_list (init_list_type_node, base_inits); base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); /* Prepend the number of bases. */ base_inits = tree_cons (NULL_TREE, @@ -1131,7 +1177,8 @@ create_pseudo_type_info (int tk, const char *real_name, ...) sprintf (pseudo_name + strlen (pseudo_name), "%d", tk - TK_FIXED); /* First field is the pseudo type_info base class. */ - fields = build_decl (FIELD_DECL, NULL_TREE, + fields = build_decl (input_location, + FIELD_DECL, NULL_TREE, VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE)->type); @@ -1143,7 +1190,7 @@ create_pseudo_type_info (int tk, const char *real_name, ...) } /* Create the pseudo type. */ - pseudo_type = make_aggr_type (RECORD_TYPE); + pseudo_type = make_class_type (RECORD_TYPE); finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; @@ -1152,6 +1199,10 @@ create_pseudo_type_info (int tk, const char *real_name, ...) ti->name = get_identifier (real_name); ti->vtable = NULL_TREE; + /* Pretend this is public so determine_visibility doesn't give vtables + internal linkage. */ + TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1; + va_end (ap); } @@ -1163,29 +1214,29 @@ static unsigned get_pseudo_ti_index (tree type) { unsigned ix; - + switch (TREE_CODE (type)) { case OFFSET_TYPE: ix = TK_POINTER_MEMBER_TYPE; break; - + case POINTER_TYPE: ix = TK_POINTER_TYPE; break; - + case ENUMERAL_TYPE: ix = TK_ENUMERAL_TYPE; break; - + case FUNCTION_TYPE: ix = TK_FUNCTION_TYPE; break; - + case ARRAY_TYPE: ix = TK_ARRAY_TYPE; break; - + case UNION_TYPE: case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (type)) @@ -1231,7 +1282,7 @@ get_pseudo_ti_index (tree type) { /* too short, extend. */ unsigned len = VEC_length (tinfo_s, tinfo_descs); - + VEC_safe_grow (tinfo_s, gc, tinfo_descs, ix + 1); while (VEC_iterate (tinfo_s, tinfo_descs, len++, ti)) ti->type = ti->vtable = ti->name = NULL_TREE; @@ -1253,14 +1304,17 @@ get_pseudo_ti_index (tree type) TK_BASE_TYPE)->type, array_domain); - push_nested_namespace (abi_node); + push_abi_namespace (); create_pseudo_type_info (ix, "__vmi_class_type_info", - build_decl (FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (FIELD_DECL, NULL_TREE, base_array), + build_decl (input_location, + FIELD_DECL, NULL_TREE, integer_type_node), + build_decl (input_location, + FIELD_DECL, NULL_TREE, integer_type_node), + build_decl (input_location, + FIELD_DECL, NULL_TREE, base_array), NULL); - pop_nested_namespace (abi_node); + pop_abi_namespace (); break; } } @@ -1278,32 +1332,33 @@ static void create_tinfo_types (void) { tinfo_s *ti; - + gcc_assert (!tinfo_descs); VEC_safe_grow (tinfo_s, gc, tinfo_descs, TK_FIXED); - - push_nested_namespace (abi_node); + + push_abi_namespace (); /* Create the internal type_info structure. This is used as a base for the other structures. */ { tree field, fields; - field = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node); + field = build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, const_ptr_type_node); fields = field; - field = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node); + field = build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, const_string_type_node); TREE_CHAIN (field) = fields; fields = field; ti = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE); - ti->type = make_aggr_type (RECORD_TYPE); + ti->type = make_class_type (RECORD_TYPE); ti->vtable = NULL_TREE; ti->name = NULL_TREE; finish_builtin_struct (ti->type, "__type_info_pseudo", fields, NULL_TREE); - TYPE_HAS_CONSTRUCTOR (ti->type) = 1; } /* Fundamental type_info */ @@ -1313,44 +1368,48 @@ create_tinfo_types (void) create_pseudo_type_info (TK_ARRAY_TYPE, "__array_type_info", NULL); create_pseudo_type_info (TK_FUNCTION_TYPE, "__function_type_info", NULL); create_pseudo_type_info (TK_ENUMERAL_TYPE, "__enum_type_info", NULL); - + /* Class type_info. No additional fields. */ create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL); - - /* Single public non-virtual base class. Add pointer to base class. + + /* Single public non-virtual base class. Add pointer to base class. This is really a descendant of __class_type_info. */ create_pseudo_type_info (TK_SI_CLASS_TYPE, "__si_class_type_info", - build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), - NULL); + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, type_info_ptr_type), + NULL); /* Base class internal helper. Pointer to base type, offset to base, flags. */ { tree field, fields; - field = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type); + field = build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, type_info_ptr_type); fields = field; - field = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]); + field = build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, integer_types[itk_long]); TREE_CHAIN (field) = fields; fields = field; - + ti = VEC_index (tinfo_s, tinfo_descs, TK_BASE_TYPE); - - ti->type = make_aggr_type (RECORD_TYPE); + + ti->type = make_class_type (RECORD_TYPE); ti->vtable = NULL_TREE; ti->name = NULL_TREE; finish_builtin_struct (ti->type, "__base_class_type_info_pseudo", fields, NULL_TREE); - TYPE_HAS_CONSTRUCTOR (ti->type) = 1; } /* Pointer type_info. Adds two fields, qualification mask and pointer to the pointed to type. This is really a descendant of __pbase_type_info. */ create_pseudo_type_info (TK_POINTER_TYPE, "__pointer_type_info", - build_decl (FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, integer_type_node), + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, type_info_ptr_type), NULL); /* Pointer to member data type_info. Add qualifications flags, @@ -1358,12 +1417,15 @@ create_tinfo_types (void) This is really a descendant of __pbase_type_info. */ create_pseudo_type_info (TK_POINTER_MEMBER_TYPE, "__pointer_to_member_type_info", - build_decl (FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), - build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type), - NULL); - - pop_nested_namespace (abi_node); + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, integer_type_node), + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, type_info_ptr_type), + build_decl (BUILTINS_LOCATION, + FIELD_DECL, NULL_TREE, type_info_ptr_type), + NULL); + + pop_abi_namespace (); } /* Emit the type_info descriptors which are guaranteed to be in the runtime @@ -1379,7 +1441,7 @@ emit_support_tinfos (void) { &void_type_node, &boolean_type_node, - &wchar_type_node, + &wchar_type_node, &char16_type_node, &char32_type_node, &char_type_node, &signed_char_type_node, &unsigned_char_type_node, &short_integer_type_node, &short_unsigned_type_node, &integer_type_node, &unsigned_type_node, @@ -1391,11 +1453,11 @@ emit_support_tinfos (void) int ix; tree bltn_type, dtor; - push_nested_namespace (abi_node); + push_abi_namespace (); bltn_type = xref_tag (class_type, get_identifier ("__fundamental_type_info"), /*tag_scope=*/ts_current, false); - pop_nested_namespace (abi_node); + pop_abi_namespace (); if (!COMPLETE_TYPE_P (bltn_type)) return; dtor = CLASSTYPE_DESTRUCTORS (bltn_type); @@ -1426,8 +1488,11 @@ emit_support_tinfos (void) comdat_linkage for details.) Since we want these objects to have external linkage so that copies do not have to be emitted in code outside the runtime library, we make them - non-COMDAT here. */ - if (!flag_weak) + non-COMDAT here. + + It might also not be necessary to follow this detail of the + ABI. */ + if (!flag_weak || ! targetm.cxx.library_rtti_comdat ()) { gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo)); DECL_INTERFACE_KNOWN (tinfo) = 1; @@ -1478,12 +1543,12 @@ emit_tinfo_decl (tree decl) if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl)) { tree init; - + DECL_EXTERNAL (decl) = 0; init = get_pseudo_ti_init (type, get_pseudo_ti_index (type)); DECL_INITIAL (decl) = init; mark_used (decl); - cp_finish_decl (decl, init, NULL_TREE, 0); + cp_finish_decl (decl, init, false, NULL_TREE, 0); return true; } else