{
TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */
TK_BASE_TYPE, /* abi::__base_class_type_info */
- TK_BUILTIN_TYPE, /* abi::__fundamental_type_info */
+ TK_DERIVED_TYPES, /* Start of types derived from abi::__type_info */
+ TK_BUILTIN_TYPE = TK_DERIVED_TYPES, /* abi::__fundamental_type_info */
TK_ARRAY_TYPE, /* abi::__array_type_info */
TK_FUNCTION_TYPE, /* abi::__function_type_info */
TK_ENUMERAL_TYPE, /* abi::__enum_type_info */
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<I> */
+ TK_VMI_CLASS_TYPES, /* abi::__vmi_class_type_info<int> */
+ TK_MAX
+};
+
+/* Names of the tinfo types. Must be same order as TK enumeration
+ above. */
+
+static const char *const tinfo_names[TK_MAX] =
+{
+ "__type_info",
+ "__base_class_type_info",
+ "__fundamental_type_info",
+ "__array_type_info",
+ "__function_type_info",
+ "__enum_type_info",
+ "__pointer_type_info",
+ "__pointer_to_member_type_info",
+ "__class_type_info",
+ "__si_class_type_info",
+ "__vmi_class_type_info"
};
/* Helper macro to get maximum scalar-width of pointer or of the 'long'-type.
static tree ptr_initializer (tinfo_s *, tree);
static tree ptm_initializer (tinfo_s *, tree);
static tree class_initializer (tinfo_s *, tree, unsigned, ...);
-static void create_pseudo_type_info (int, const char *, ...);
static tree get_pseudo_ti_init (tree, unsigned);
static unsigned get_pseudo_ti_index (tree);
+static tinfo_s *get_tinfo_desc (unsigned);
static void create_tinfo_types (void);
static bool typeinfo_in_lib_p (tree);
static bool
typeid_ok_p (void)
{
- tree pseudo_type_info, type_info_type;
-
if (! flag_rtti)
{
- error ("cannot use typeid with -fno-rtti");
+ error ("cannot use %<typeid%> with -fno-rtti");
return false;
}
if (!COMPLETE_TYPE_P (const_type_info_type_node))
{
- error ("must #include <typeinfo> before using typeid");
+ error ("must %<#include <typeinfo>%> before using %<typeid%>");
return false;
}
- pseudo_type_info = (*tinfo_descs)[TK_TYPE_INFO_TYPE].type;
- type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
+ tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
+ tree real = 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);
+ if (! TYPE_ALIAS_SET_KNOWN_P (pseudo))
+ TYPE_ALIAS_SET (pseudo) = get_alias_set (real);
else
- gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
- == get_alias_set (type_info_type));
+ gcc_assert (TYPE_ALIAS_SET (pseudo) == get_alias_set (real));
return true;
}
if (!d)
{
int ix = get_pseudo_ti_index (type);
- tinfo_s *ti = &(*tinfo_descs)[ix];
-
+ const tinfo_s *ti = get_tinfo_desc (ix);
+
d = build_lang_decl (VAR_DECL, name, ti->type);
SET_DECL_ASSEMBLER_NAME (d, name);
/* Remember the type it is for. */
static tree
get_pseudo_ti_init (tree type, unsigned tk_index)
{
- tinfo_s *ti = &(*tinfo_descs)[tk_index];
+ tinfo_s *ti = get_tinfo_desc (tk_index);
gcc_assert (at_eof);
switch (tk_index)
int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0)
| (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1));
tree binfo = TYPE_BINFO (type);
- int nbases = BINFO_N_BASE_BINFOS (binfo);
+ unsigned nbases = BINFO_N_BASE_BINFOS (binfo);
vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo);
tree offset_type = LONGPTR_T;
- tree base_inits = NULL_TREE;
- int ix;
vec<constructor_elt, va_gc> *init_vec = NULL;
- constructor_elt *e;
- gcc_assert (tk_index >= TK_FIXED);
+ gcc_assert (tk_index - TK_VMI_CLASS_TYPES + 1 == nbases);
vec_safe_grow (init_vec, nbases);
/* Generate the base information initializer. */
- for (ix = nbases; ix--;)
+ for (unsigned ix = nbases; ix--;)
{
tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
- tree base_init;
int flags = 0;
tree tinfo;
tree offset;
vec_alloc (v, 2);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset);
- base_init = build_constructor (init_list_type_node, v);
- e = &(*init_vec)[ix];
+ tree base_init = build_constructor (init_list_type_node, v);
+ constructor_elt *e = &(*init_vec)[ix];
e->index = NULL_TREE;
e->value = base_init;
}
- base_inits = build_constructor (init_list_type_node, init_vec);
+ tree base_inits = build_constructor (init_list_type_node, init_vec);
/* get_tinfo_ptr might have reallocated the tinfo_descs vector. */
ti = &(*tinfo_descs)[tk_index];
}
}
-/* Generate the RECORD_TYPE containing the data layout of a type_info
- derivative as used by the runtime. This layout must be consistent with
- that defined in the runtime support. Also generate the VAR_DECL for the
- type's vtable. We explicitly manage the vtable member, and name it for
- real type as used in the runtime. The RECORD type has a different name,
- to avoid collisions. Return a TREE_LIST who's TINFO_PSEUDO_TYPE
- is the generated type and TINFO_VTABLE_NAME is the name of the
- vtable. We have to delay generating the VAR_DECL of the vtable
- until the end of the translation, when we'll have seen the library
- definition, if there was one.
-
- REAL_NAME is the runtime's name of the type. Trailing arguments are
- additional FIELD_DECL's for the structure. The final argument must be
- NULL. */
-
-static void
-create_pseudo_type_info (int tk, const char *real_name, ...)
-{
- tinfo_s *ti;
- tree pseudo_type;
- char *pseudo_name;
- tree fields;
- tree field_decl;
- va_list ap;
-
- va_start (ap, real_name);
-
- /* Generate the pseudo type name. */
- pseudo_name = (char *) alloca (strlen (real_name) + 30);
- strcpy (pseudo_name, real_name);
- strcat (pseudo_name, "_pseudo");
- if (tk >= TK_FIXED)
- sprintf (pseudo_name + strlen (pseudo_name), "%d", tk - TK_FIXED);
-
- /* First field is the pseudo type_info base class. */
- fields = build_decl (input_location,
- FIELD_DECL, NULL_TREE,
- (*tinfo_descs)[TK_TYPE_INFO_TYPE].type);
-
- /* Now add the derived fields. */
- while ((field_decl = va_arg (ap, tree)))
- {
- DECL_CHAIN (field_decl) = fields;
- fields = field_decl;
- }
-
- /* Create the pseudo 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;
-
- ti = &(*tinfo_descs)[tk];
- ti->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
- 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);
-}
-
/* Return the index of a pseudo type info type node used to describe
TYPE. TYPE must be a complete type (or cv void), except at the end
of the translation unit. */
case UNION_TYPE:
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
- {
- ix = TK_POINTER_MEMBER_TYPE;
- break;
- }
+ ix = TK_POINTER_MEMBER_TYPE;
else if (!COMPLETE_TYPE_P (type))
{
if (!at_eof)
cxx_incomplete_type_error (NULL_TREE, type);
ix = TK_CLASS_TYPE;
- break;
}
else if (!TYPE_BINFO (type)
|| !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)))
- {
- ix = TK_CLASS_TYPE;
- break;
- }
+ ix = TK_CLASS_TYPE;
else
{
tree binfo = TYPE_BINFO (type);
&& (*base_accesses)[0] == access_public_node
&& !BINFO_VIRTUAL_P (base_binfo)
&& integer_zerop (BINFO_OFFSET (base_binfo)))
- {
- /* single non-virtual public. */
- ix = TK_SI_CLASS_TYPE;
- break;
- }
+ /* single non-virtual public. */
+ ix = TK_SI_CLASS_TYPE;
else
- {
- tinfo_s *ti;
- tree array_domain, base_array;
-
- ix = TK_FIXED + num_bases;
- if (vec_safe_length (tinfo_descs) <= ix)
- {
- /* too short, extend. */
- unsigned len = vec_safe_length (tinfo_descs);
-
- vec_safe_grow (tinfo_descs, ix + 1);
- while (tinfo_descs->iterate (len++, &ti))
- ti->type = ti->vtable = ti->name = NULL_TREE;
- }
- else if ((*tinfo_descs)[ix].type)
- /* already created. */
- break;
-
- /* Create the array of __base_class_type_info entries. */
- array_domain = build_index_type (size_int (num_bases - 1));
- base_array = build_array_type ((*tinfo_descs)[TK_BASE_TYPE].type,
- array_domain);
-
- push_abi_namespace ();
- create_pseudo_type_info
- (ix, "__vmi_class_type_info",
- 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_abi_namespace ();
- break;
- }
+ ix = TK_VMI_CLASS_TYPES + num_bases - 1;
}
+ break;
+
default:
ix = TK_BUILTIN_TYPE;
break;
return ix;
}
-/* Make sure the required builtin types exist for generating the type_info
- variable definitions. */
+/* Return pointer to tinfo descriptor. Possibly creating the tinfo
+ descriptor in the first place. */
-static void
-create_tinfo_types (void)
+static tinfo_s *
+get_tinfo_desc (unsigned ix)
{
- tinfo_s *ti;
+ unsigned len = tinfo_descs->length ();
- gcc_assert (!tinfo_descs);
+ if (len <= ix)
+ {
+ /* too short, extend. */
+ len = ix + 1 - len;
+ vec_safe_reserve (tinfo_descs, len);
+ tinfo_s elt;
+ elt.type = elt.vtable = elt.name = NULL_TREE;
+ while (len--)
+ tinfo_descs->quick_push (elt);
+ }
- vec_safe_grow (tinfo_descs, TK_FIXED);
+ tinfo_s *res = &(*tinfo_descs)[ix];
- push_abi_namespace ();
+ if (res->type)
+ return res;
- /* Create the internal type_info structure. This is used as a base for
- the other structures. */
- {
- tree field, fields;
-
- field = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, NULL_TREE, const_ptr_type_node);
- fields = field;
-
- field = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, NULL_TREE, const_string_type_node);
- DECL_CHAIN (field) = fields;
- fields = field;
-
- ti = &(*tinfo_descs)[TK_TYPE_INFO_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);
- }
+ /* Ok, we have to create it. This layout must be consistent with
+ that defined in the runtime support. We explicitly manage the
+ vtable member, and name it for real type as used in the runtime.
+ The RECORD type has a different name, to avoid collisions. We
+ have to delay generating the VAR_DECL of the vtable until the end
+ of the translation, when we'll have seen the library definition,
+ if there was one. */
- /* Fundamental type_info */
- create_pseudo_type_info (TK_BUILTIN_TYPE, "__fundamental_type_info", NULL);
+ /* Fields to add, chained in reverse order. */
+ tree fields = NULL_TREE;
- /* Array, function and enum type_info. No additional fields. */
- 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);
+ if (ix >= TK_DERIVED_TYPES)
+ {
+ /* First field is the pseudo type_info base class. */
+ tree fld_base = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
+ get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
- /* Class type_info. No additional fields. */
- create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL);
+ DECL_CHAIN (fld_base) = fields;
+ fields = fld_base;
+ }
- /* 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 (BUILTINS_LOCATION,
- FIELD_DECL, NULL_TREE, type_info_ptr_type),
- NULL);
+ switch (ix)
+ {
+ case TK_TYPE_INFO_TYPE:
+ {
+ tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, const_ptr_type_node);
+ fields = fld_ptr;
+
+ tree fld_str = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, const_string_type_node);
+ DECL_CHAIN (fld_str) = fields;
+ fields = fld_str;
+ break;
+ }
- /* Base class internal helper. Pointer to base type, offset to base,
- flags. */
- {
- tree field, fields;
+ case TK_BASE_TYPE:
+ {
+ /* Base class internal helper. Pointer to base type, offset to
+ base, flags. */
+ tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, type_info_ptr_type);
+ DECL_CHAIN (fld_ptr) = fields;
+ fields = fld_ptr;
+
+ tree fld_flag = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, LONGPTR_T);
+ DECL_CHAIN (fld_flag) = fields;
+ fields = fld_flag;
+ break;
+ }
- field = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, NULL_TREE, type_info_ptr_type);
- fields = field;
+ case TK_BUILTIN_TYPE:
+ /* Fundamental type_info */
+ break;
- field = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, NULL_TREE, LONGPTR_T);
- DECL_CHAIN (field) = fields;
- fields = field;
+ case TK_ARRAY_TYPE:
+ break;
- ti = &(*tinfo_descs)[TK_BASE_TYPE];
+ case TK_FUNCTION_TYPE:
+ break;
- 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);
- }
+ case TK_ENUMERAL_TYPE:
+ break;
+
+ case TK_POINTER_TYPE:
+ case TK_POINTER_MEMBER_TYPE:
+ {
+ /* Pointer type_info. Adds two fields, qualification mask and
+ pointer to the pointed to type. This is really a
+ descendant of __pbase_type_info. */
+ tree fld_mask = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, integer_type_node);
+ DECL_CHAIN (fld_mask) = fields;
+ fields = fld_mask;
+
+ tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, type_info_ptr_type);
+ DECL_CHAIN (fld_ptr) = fields;
+ fields = fld_ptr;
+
+ if (ix == TK_POINTER_MEMBER_TYPE)
+ {
+ /* Add a pointer to the class too. */
+ tree fld_cls = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, type_info_ptr_type);
+ DECL_CHAIN (fld_cls) = fields;
+ fields = fld_cls;
+ }
+ break;
+ }
+
+ case TK_CLASS_TYPE:
+ /* Class type_info. No additional fields. */
+ break;
+
+ case TK_SI_CLASS_TYPE:
+ {
+ /* Single public non-virtual base class. Add pointer to base
+ class. This is really a descendant of
+ __class_type_info. */
+ tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, type_info_ptr_type);
+ DECL_CHAIN (fld_ptr) = fields;
+ fields = fld_ptr;
+ break;
+ }
+
+ default: /* Multiple inheritance. */
+ {
+ unsigned num_bases = ix - TK_VMI_CLASS_TYPES + 1;
+
+ tree fld_flg = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, integer_type_node);
+ DECL_CHAIN (fld_flg) = fields;
+ fields = fld_flg;
+
+ tree fld_cnt = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, integer_type_node);
+ DECL_CHAIN (fld_cnt) = fields;
+ fields = fld_cnt;
+
+ /* Create the array of __base_class_type_info entries. */
+ tree domain = build_index_type (size_int (num_bases - 1));
+ tree array = build_array_type (get_tinfo_desc (TK_BASE_TYPE)->type,
+ domain);
+ tree fld_ary = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, array);
+ DECL_CHAIN (fld_ary) = fields;
+ fields = fld_ary;
+ break;
+ }
+ }
+
+ push_abi_namespace ();
+
+ /* Generate the pseudo type name. */
+ const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES
+ ? ix : unsigned (TK_VMI_CLASS_TYPES)];
+ size_t name_len = strlen (real_name);
+ char *pseudo_name = (char *) alloca (name_len + 30);
+ memcpy (pseudo_name, real_name, name_len);
+ /* Those >= TK_VMI_CLASS_TYPES need a discriminator, may as well
+ apply it to all. See get_peudo_tinfo_index where we make use of
+ this. */
+ sprintf (pseudo_name + name_len, "_pseudo_%d", ix);
- /* 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 (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,
- pointer to the member's type info and pointer to the class.
- This is really a descendant of __pbase_type_info. */
- create_pseudo_type_info (TK_POINTER_MEMBER_TYPE,
- "__pointer_to_member_type_info",
- 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);
+ /* Create the pseudo type. */
+ tree pseudo_type = make_class_type (RECORD_TYPE);
+ /* Pass the fields chained in reverse. */
+ finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
+ CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
+
+ res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
+ res->name = get_identifier (real_name);
+
+ /* Pretend this is public so determine_visibility doesn't give vtables
+ internal linkage. */
+ TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1;
pop_abi_namespace ();
+ return res;
+}
+
+/* We lazily create the type info types. */
+
+static void
+create_tinfo_types (void)
+{
+ gcc_assert (!tinfo_descs);
+
+ vec_alloc (tinfo_descs, TK_MAX + 20);
}
/* Helper for emit_support_tinfos. Emits the type_info descriptor of
0
};
int ix;
- tree bltn_type, dtor;
- push_abi_namespace ();
- bltn_type = xref_tag (class_type,
- get_identifier ("__fundamental_type_info"),
- /*tag_scope=*/ts_current, false);
- pop_abi_namespace ();
+ /* Look for a defined class. */
+ tree bltn_type = lookup_qualified_name
+ (abi_node, get_identifier ("__fundamental_type_info"), true, false, false);
+ if (TREE_CODE (bltn_type) != TYPE_DECL)
+ return;
+
+ bltn_type = TREE_TYPE (bltn_type);
if (!COMPLETE_TYPE_P (bltn_type))
return;
- dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
+ tree dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
if (!dtor || DECL_EXTERNAL (dtor))
return;
+
+ /* All these are really builtins. So set the location. */
+ location_t saved_loc = input_location;
+ input_location = BUILTINS_LOCATION;
doing_runtime = 1;
for (ix = 0; fundamentals[ix]; ix++)
emit_support_tinfo_1 (*fundamentals[ix]);
}
for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t))
emit_support_tinfo_1 (TREE_VALUE (t));
+ input_location = saved_loc;
}
/* Finish a type info decl. DECL_PTR is a pointer to an unemitted
TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
- }
+ }u
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))