mirror of git://gcc.gnu.org/git/gcc.git
Make rtti lazier
Make rtti lazier * rtti.c (enum tinfo_kind): Add TK_DERIVED_TYPES, TK_VMI_CLASS_TYPES, TK_MAX. Delete TK_FIXED. (tinfo_names): New. (typeid_ok_p): Add quotes to error messages. Use get_tinfo_desc. (get_tinfo_decl): Use get_tinfo_desc. (get_pseudo_ti_init): Likewise. Adjust VMI construction. (create_pseudo_type_info): Delete. (get_pseudo_ti_index): Just determine the index. (get_tinfo_desc): New. Create all types lazily. (create_tinfo_types): Just allocate the descriptor array. (emit_support_tinfos): Use non-inserting type lookup. Set builtin location. From-SVN: r249258
This commit is contained in:
parent
bfe8a528aa
commit
ac9a1c7ec5
|
|
@ -1,3 +1,19 @@
|
||||||
|
2017-06-16 Nathan Sidwell <nathan@acm.org>
|
||||||
|
|
||||||
|
Make rtti lazier
|
||||||
|
* rtti.c (enum tinfo_kind): Add TK_DERIVED_TYPES,
|
||||||
|
TK_VMI_CLASS_TYPES, TK_MAX. Delete TK_FIXED.
|
||||||
|
(tinfo_names): New.
|
||||||
|
(typeid_ok_p): Add quotes to error messages. Use get_tinfo_desc.
|
||||||
|
(get_tinfo_decl): Use get_tinfo_desc.
|
||||||
|
(get_pseudo_ti_init): Likewise. Adjust VMI construction.
|
||||||
|
(create_pseudo_type_info): Delete.
|
||||||
|
(get_pseudo_ti_index): Just determine the index.
|
||||||
|
(get_tinfo_desc): New. Create all types lazily.
|
||||||
|
(create_tinfo_types): Just allocate the descriptor array.
|
||||||
|
(emit_support_tinfos): Use non-inserting type lookup. Set builtin
|
||||||
|
location.
|
||||||
|
|
||||||
2017-06-15 Martin Sebor <msebor@redhat.com>
|
2017-06-15 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
PR c++/80560
|
PR c++/80560
|
||||||
|
|
|
||||||
479
gcc/cp/rtti.c
479
gcc/cp/rtti.c
|
|
@ -75,7 +75,8 @@ enum tinfo_kind
|
||||||
{
|
{
|
||||||
TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */
|
TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */
|
||||||
TK_BASE_TYPE, /* abi::__base_class_type_info */
|
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_ARRAY_TYPE, /* abi::__array_type_info */
|
||||||
TK_FUNCTION_TYPE, /* abi::__function_type_info */
|
TK_FUNCTION_TYPE, /* abi::__function_type_info */
|
||||||
TK_ENUMERAL_TYPE, /* abi::__enum_type_info */
|
TK_ENUMERAL_TYPE, /* abi::__enum_type_info */
|
||||||
|
|
@ -83,8 +84,26 @@ enum tinfo_kind
|
||||||
TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */
|
TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */
|
||||||
TK_CLASS_TYPE, /* abi::__class_type_info */
|
TK_CLASS_TYPE, /* abi::__class_type_info */
|
||||||
TK_SI_CLASS_TYPE, /* abi::__si_class_type_info */
|
TK_SI_CLASS_TYPE, /* abi::__si_class_type_info */
|
||||||
TK_FIXED /* end of fixed descriptors. */
|
TK_VMI_CLASS_TYPES, /* abi::__vmi_class_type_info<int> */
|
||||||
/* ... abi::__vmi_type_info<I> */
|
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.
|
/* Helper macro to get maximum scalar-width of pointer or of the 'long'-type.
|
||||||
|
|
@ -115,9 +134,9 @@ static tree generic_initializer (tinfo_s *, tree);
|
||||||
static tree ptr_initializer (tinfo_s *, tree);
|
static tree ptr_initializer (tinfo_s *, tree);
|
||||||
static tree ptm_initializer (tinfo_s *, tree);
|
static tree ptm_initializer (tinfo_s *, tree);
|
||||||
static tree class_initializer (tinfo_s *, tree, unsigned, ...);
|
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 tree get_pseudo_ti_init (tree, unsigned);
|
||||||
static unsigned get_pseudo_ti_index (tree);
|
static unsigned get_pseudo_ti_index (tree);
|
||||||
|
static tinfo_s *get_tinfo_desc (unsigned);
|
||||||
static void create_tinfo_types (void);
|
static void create_tinfo_types (void);
|
||||||
static bool typeinfo_in_lib_p (tree);
|
static bool typeinfo_in_lib_p (tree);
|
||||||
|
|
||||||
|
|
@ -289,30 +308,27 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain)
|
||||||
static bool
|
static bool
|
||||||
typeid_ok_p (void)
|
typeid_ok_p (void)
|
||||||
{
|
{
|
||||||
tree pseudo_type_info, type_info_type;
|
|
||||||
|
|
||||||
if (! flag_rtti)
|
if (! flag_rtti)
|
||||||
{
|
{
|
||||||
error ("cannot use typeid with -fno-rtti");
|
error ("cannot use %<typeid%> with -fno-rtti");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!COMPLETE_TYPE_P (const_type_info_type_node))
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pseudo_type_info = (*tinfo_descs)[TK_TYPE_INFO_TYPE].type;
|
tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
|
||||||
type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
|
tree real = TYPE_MAIN_VARIANT (const_type_info_type_node);
|
||||||
|
|
||||||
/* Make sure abi::__type_info_pseudo has the same alias set
|
/* Make sure abi::__type_info_pseudo has the same alias set
|
||||||
as std::type_info. */
|
as std::type_info. */
|
||||||
if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
|
if (! TYPE_ALIAS_SET_KNOWN_P (pseudo))
|
||||||
TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
|
TYPE_ALIAS_SET (pseudo) = get_alias_set (real);
|
||||||
else
|
else
|
||||||
gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
|
gcc_assert (TYPE_ALIAS_SET (pseudo) == get_alias_set (real));
|
||||||
== get_alias_set (type_info_type));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -428,7 +444,7 @@ get_tinfo_decl (tree type)
|
||||||
if (!d)
|
if (!d)
|
||||||
{
|
{
|
||||||
int ix = get_pseudo_ti_index (type);
|
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);
|
d = build_lang_decl (VAR_DECL, name, ti->type);
|
||||||
SET_DECL_ASSEMBLER_NAME (d, name);
|
SET_DECL_ASSEMBLER_NAME (d, name);
|
||||||
|
|
@ -1105,7 +1121,7 @@ typeinfo_in_lib_p (tree type)
|
||||||
static tree
|
static tree
|
||||||
get_pseudo_ti_init (tree type, unsigned tk_index)
|
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);
|
gcc_assert (at_eof);
|
||||||
switch (tk_index)
|
switch (tk_index)
|
||||||
|
|
@ -1140,22 +1156,18 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
|
||||||
int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0)
|
int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0)
|
||||||
| (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1));
|
| (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1));
|
||||||
tree binfo = TYPE_BINFO (type);
|
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);
|
vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo);
|
||||||
tree offset_type = LONGPTR_T;
|
tree offset_type = LONGPTR_T;
|
||||||
tree base_inits = NULL_TREE;
|
|
||||||
int ix;
|
|
||||||
vec<constructor_elt, va_gc> *init_vec = NULL;
|
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);
|
vec_safe_grow (init_vec, nbases);
|
||||||
/* Generate the base information initializer. */
|
/* Generate the base information initializer. */
|
||||||
for (ix = nbases; ix--;)
|
for (unsigned ix = nbases; ix--;)
|
||||||
{
|
{
|
||||||
tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
|
tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
|
||||||
tree base_init;
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
tree tinfo;
|
tree tinfo;
|
||||||
tree offset;
|
tree offset;
|
||||||
|
|
@ -1185,12 +1197,12 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
|
||||||
vec_alloc (v, 2);
|
vec_alloc (v, 2);
|
||||||
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo);
|
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo);
|
||||||
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset);
|
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset);
|
||||||
base_init = build_constructor (init_list_type_node, v);
|
tree base_init = build_constructor (init_list_type_node, v);
|
||||||
e = &(*init_vec)[ix];
|
constructor_elt *e = &(*init_vec)[ix];
|
||||||
e->index = NULL_TREE;
|
e->index = NULL_TREE;
|
||||||
e->value = base_init;
|
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. */
|
/* get_tinfo_ptr might have reallocated the tinfo_descs vector. */
|
||||||
ti = &(*tinfo_descs)[tk_index];
|
ti = &(*tinfo_descs)[tk_index];
|
||||||
|
|
@ -1202,69 +1214,6 @@ get_pseudo_ti_init (tree type, unsigned 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
|
/* 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
|
TYPE. TYPE must be a complete type (or cv void), except at the end
|
||||||
of the translation unit. */
|
of the translation unit. */
|
||||||
|
|
@ -1299,23 +1248,16 @@ get_pseudo_ti_index (tree type)
|
||||||
case UNION_TYPE:
|
case UNION_TYPE:
|
||||||
case RECORD_TYPE:
|
case RECORD_TYPE:
|
||||||
if (TYPE_PTRMEMFUNC_P (type))
|
if (TYPE_PTRMEMFUNC_P (type))
|
||||||
{
|
|
||||||
ix = TK_POINTER_MEMBER_TYPE;
|
ix = TK_POINTER_MEMBER_TYPE;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!COMPLETE_TYPE_P (type))
|
else if (!COMPLETE_TYPE_P (type))
|
||||||
{
|
{
|
||||||
if (!at_eof)
|
if (!at_eof)
|
||||||
cxx_incomplete_type_error (NULL_TREE, type);
|
cxx_incomplete_type_error (NULL_TREE, type);
|
||||||
ix = TK_CLASS_TYPE;
|
ix = TK_CLASS_TYPE;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (!TYPE_BINFO (type)
|
else if (!TYPE_BINFO (type)
|
||||||
|| !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)))
|
|| !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)))
|
||||||
{
|
|
||||||
ix = TK_CLASS_TYPE;
|
ix = TK_CLASS_TYPE;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tree binfo = TYPE_BINFO (type);
|
tree binfo = TYPE_BINFO (type);
|
||||||
|
|
@ -1327,49 +1269,13 @@ get_pseudo_ti_index (tree type)
|
||||||
&& (*base_accesses)[0] == access_public_node
|
&& (*base_accesses)[0] == access_public_node
|
||||||
&& !BINFO_VIRTUAL_P (base_binfo)
|
&& !BINFO_VIRTUAL_P (base_binfo)
|
||||||
&& integer_zerop (BINFO_OFFSET (base_binfo)))
|
&& integer_zerop (BINFO_OFFSET (base_binfo)))
|
||||||
{
|
|
||||||
/* single non-virtual public. */
|
/* single non-virtual public. */
|
||||||
ix = TK_SI_CLASS_TYPE;
|
ix = TK_SI_CLASS_TYPE;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ix = TK_VMI_CLASS_TYPES + num_bases - 1;
|
||||||
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;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
ix = TK_BUILTIN_TYPE;
|
ix = TK_BUILTIN_TYPE;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1377,107 +1283,202 @@ get_pseudo_ti_index (tree type)
|
||||||
return ix;
|
return ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the required builtin types exist for generating the type_info
|
/* Return pointer to tinfo descriptor. Possibly creating the tinfo
|
||||||
variable definitions. */
|
descriptor in the first place. */
|
||||||
|
|
||||||
|
static tinfo_s *
|
||||||
|
get_tinfo_desc (unsigned ix)
|
||||||
|
{
|
||||||
|
unsigned len = tinfo_descs->length ();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
tinfo_s *res = &(*tinfo_descs)[ix];
|
||||||
|
|
||||||
|
if (res->type)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
|
||||||
|
/* Fields to add, chained in reverse order. */
|
||||||
|
tree fields = NULL_TREE;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
DECL_CHAIN (fld_base) = fields;
|
||||||
|
fields = fld_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TK_BUILTIN_TYPE:
|
||||||
|
/* Fundamental type_info */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_ARRAY_TYPE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_FUNCTION_TYPE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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
|
static void
|
||||||
create_tinfo_types (void)
|
create_tinfo_types (void)
|
||||||
{
|
{
|
||||||
tinfo_s *ti;
|
|
||||||
|
|
||||||
gcc_assert (!tinfo_descs);
|
gcc_assert (!tinfo_descs);
|
||||||
|
|
||||||
vec_safe_grow (tinfo_descs, TK_FIXED);
|
vec_alloc (tinfo_descs, TK_MAX + 20);
|
||||||
|
|
||||||
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 (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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fundamental type_info */
|
|
||||||
create_pseudo_type_info (TK_BUILTIN_TYPE, "__fundamental_type_info", NULL);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Base class internal helper. Pointer to base type, offset to base,
|
|
||||||
flags. */
|
|
||||||
{
|
|
||||||
tree field, fields;
|
|
||||||
|
|
||||||
field = build_decl (BUILTINS_LOCATION,
|
|
||||||
FIELD_DECL, NULL_TREE, type_info_ptr_type);
|
|
||||||
fields = field;
|
|
||||||
|
|
||||||
field = build_decl (BUILTINS_LOCATION,
|
|
||||||
FIELD_DECL, NULL_TREE, LONGPTR_T);
|
|
||||||
DECL_CHAIN (field) = fields;
|
|
||||||
fields = field;
|
|
||||||
|
|
||||||
ti = &(*tinfo_descs)[TK_BASE_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
pop_abi_namespace ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper for emit_support_tinfos. Emits the type_info descriptor of
|
/* Helper for emit_support_tinfos. Emits the type_info descriptor of
|
||||||
|
|
@ -1545,18 +1546,23 @@ emit_support_tinfos (void)
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
int ix;
|
int ix;
|
||||||
tree bltn_type, dtor;
|
|
||||||
|
|
||||||
push_abi_namespace ();
|
/* Look for a defined class. */
|
||||||
bltn_type = xref_tag (class_type,
|
tree bltn_type = lookup_qualified_name
|
||||||
get_identifier ("__fundamental_type_info"),
|
(abi_node, get_identifier ("__fundamental_type_info"), true, false, false);
|
||||||
/*tag_scope=*/ts_current, false);
|
if (TREE_CODE (bltn_type) != TYPE_DECL)
|
||||||
pop_abi_namespace ();
|
return;
|
||||||
|
|
||||||
|
bltn_type = TREE_TYPE (bltn_type);
|
||||||
if (!COMPLETE_TYPE_P (bltn_type))
|
if (!COMPLETE_TYPE_P (bltn_type))
|
||||||
return;
|
return;
|
||||||
dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
|
tree dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
|
||||||
if (!dtor || DECL_EXTERNAL (dtor))
|
if (!dtor || DECL_EXTERNAL (dtor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* All these are really builtins. So set the location. */
|
||||||
|
location_t saved_loc = input_location;
|
||||||
|
input_location = BUILTINS_LOCATION;
|
||||||
doing_runtime = 1;
|
doing_runtime = 1;
|
||||||
for (ix = 0; fundamentals[ix]; ix++)
|
for (ix = 0; fundamentals[ix]; ix++)
|
||||||
emit_support_tinfo_1 (*fundamentals[ix]);
|
emit_support_tinfo_1 (*fundamentals[ix]);
|
||||||
|
|
@ -1568,6 +1574,7 @@ emit_support_tinfos (void)
|
||||||
}
|
}
|
||||||
for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t))
|
for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t))
|
||||||
emit_support_tinfo_1 (TREE_VALUE (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
|
/* Finish a type info decl. DECL_PTR is a pointer to an unemitted
|
||||||
|
|
@ -1606,7 +1613,7 @@ emit_tinfo_decl (tree decl)
|
||||||
TREE_PUBLIC (decl) = 0;
|
TREE_PUBLIC (decl) = 0;
|
||||||
DECL_EXTERNAL (decl) = 0;
|
DECL_EXTERNAL (decl) = 0;
|
||||||
DECL_INTERFACE_KNOWN (decl) = 1;
|
DECL_INTERFACE_KNOWN (decl) = 1;
|
||||||
}
|
}u
|
||||||
|
|
||||||
import_export_decl (decl);
|
import_export_decl (decl);
|
||||||
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
|
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue