* Fwd: [C++ PATCH]: Rework typeinfo objects
@ 2002-07-22 3:26 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2002-07-22 3:26 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
I just went looking for this patch on gcc-patches, and didn't find it;
fortunately I still had it in my mail file.
[-- Attachment #2: Type: message/rfc822, Size: 50483 bytes --]
[-- Attachment #2.1.1: Type: text/plain, Size: 761 bytes --]
Jason,
here's that rtti.c patch which reworks the typeinfo objects. Now
when a typeinfo is required, we generate an extern decl of the
ABI-defined type and reinterpret_cast it to std::type_info. At the
end of translation, we generate the appropriate initializers and emit
them.
I broke import_export_tinfo out of import_export_decl. All the
linkage determination code is now either there or in emit_tinfo_decl.
It might be wise to check this patch is ok on a comdat-difficult
host (HPUX?)
built & tested on i686-pc-linux-gnu, ok?
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
[-- Attachment #2.1.2: rtti-8.patch --]
[-- Type: text/plain, Size: 49212 bytes --]
2002-06-20 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
(CPTI_TYPE_INFO_PTR_TYPE): ... this.
(tinfo_decl_type): Replace with ...
(type_info_ptr_type): ... this.
(import_export_tinfo): Declare.
(tinfo_decl_p): Rename to ...
(unemitted_tinfo_decl_p): ... this.
* decl2.c (import_export_decl): Break out tinfo handling into ...
(import_export_tinfo): ... here. New function.
(finish_file): Adjust.
* rtti.c (TINFO_REAL_NAME): New macro.
(init_rtti_processing): Create the tinfo types.
(get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
(get_tinfo_decl): Adjust.
(get_tinfo_ptr): New function.
(get_type_id): Use it.
(tinfo_base_init): Create vtable decl here, if it doesn't exist.
(ptr_initializer): Use get_tinfo_ptr.
(ptm_initializer): Likewise.
(synthesize_tinfo_var): Break into ...
(get_pseudo_ti_init): ... this. Just create the initializer.
(get_pseudo_ti_desc): .. and this.
(create_real_tinfo_var): Remove.
(create_pseudo_type_info): Don't create the vtable decl here.
(get_vmi_pseudo_type_info): Remove.
(create_tinfo_types): Adjust.
(tinfo_decl_p): Rename to ...
(unemitted_tinfo_decl_p): ... here. Adjust.
(emit_tinfo_decl): Adjust. Create the initializer.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.719
diff -c -3 -p -r1.719 cp-tree.h
*** cp/cp-tree.h 16 Jun 2002 19:09:25 -0000 1.719
--- cp/cp-tree.h 21 Jun 2002 11:16:07 -0000
*************** enum cp_tree_index
*** 563,569 ****
CPTI_STD,
CPTI_ABI,
CPTI_TYPE_INFO_TYPE,
! CPTI_TINFO_DECL_TYPE,
CPTI_ABORT_FNDECL,
CPTI_GLOBAL_DELETE_FNDECL,
CPTI_AGGR_TAG,
--- 563,569 ----
CPTI_STD,
CPTI_ABI,
CPTI_TYPE_INFO_TYPE,
! CPTI_TYPE_INFO_PTR_TYPE,
CPTI_ABORT_FNDECL,
CPTI_GLOBAL_DELETE_FNDECL,
CPTI_AGGR_TAG,
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 650,656 ****
#define std_node cp_global_trees[CPTI_STD]
#define abi_node cp_global_trees[CPTI_ABI]
#define type_info_type_node cp_global_trees[CPTI_TYPE_INFO_TYPE]
! #define tinfo_decl_type cp_global_trees[CPTI_TINFO_DECL_TYPE]
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
--- 650,656 ----
#define std_node cp_global_trees[CPTI_STD]
#define abi_node cp_global_trees[CPTI_ABI]
#define type_info_type_node cp_global_trees[CPTI_TYPE_INFO_TYPE]
! #define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE]
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
*************** extern tree coerce_delete_type PARAMS
*** 3919,3924 ****
--- 3919,3925 ----
extern void comdat_linkage PARAMS ((tree));
extern void import_export_vtable PARAMS ((tree, tree, int));
extern void import_export_decl PARAMS ((tree));
+ extern void import_export_tinfo PARAMS ((tree, tree));
extern tree build_cleanup PARAMS ((tree));
extern void finish_file PARAMS ((void));
extern tree reparse_absdcl_as_expr PARAMS ((tree, tree));
*************** extern tree get_tinfo_decl
*** 4147,4153 ****
extern tree get_typeid PARAMS((tree));
extern tree build_dynamic_cast PARAMS((tree, tree));
extern void emit_support_tinfos PARAMS((void));
! extern int tinfo_decl_p PARAMS((tree, void *));
extern int emit_tinfo_decl PARAMS((tree *, void *));
/* in search.c */
--- 4148,4154 ----
extern tree get_typeid PARAMS((tree));
extern tree build_dynamic_cast PARAMS((tree, tree));
extern void emit_support_tinfos PARAMS((void));
! extern int unemitted_tinfo_decl_p PARAMS((tree, void *));
extern int emit_tinfo_decl PARAMS((tree *, void *));
/* in search.c */
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.540
diff -c -3 -p -r1.540 decl2.c
*** cp/decl2.c 16 Jun 2002 19:09:26 -0000 1.540
--- cp/decl2.c 21 Jun 2002 11:16:08 -0000
*************** import_export_decl (decl)
*** 2509,2555 ****
else
comdat_linkage (decl);
}
- else if (tinfo_decl_p (decl, 0))
- {
- /* Here, we only decide whether or not the tinfo node should be
- emitted with the vtable. The decl we're considering isn't
- actually the one which gets emitted; that one is generated in
- create_real_tinfo_var. */
-
- tree ctype = TREE_TYPE (DECL_NAME (decl));
-
- if (IS_AGGR_TYPE (ctype))
- import_export_class (ctype);
-
- if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype)
- && TYPE_POLYMORPHIC_P (ctype)
- /* If -fno-rtti, we're not necessarily emitting this stuff with
- the class, so go ahead and emit it now. This can happen
- when a class is used in exception handling. */
- && flag_rtti
- /* If the type is a cv-qualified variant of a type, then we
- must emit the tinfo function in this translation unit
- since it will not be emitted when the vtable for the type
- is output (which is when the unqualified version is
- generated). */
- && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
- {
- DECL_NOT_REALLY_EXTERN (decl)
- = ! CLASSTYPE_INTERFACE_ONLY (ctype);
- DECL_COMDAT (decl) = 0;
- }
- else
- {
- DECL_NOT_REALLY_EXTERN (decl) = 1;
- DECL_COMDAT (decl) = 1;
- }
- }
else
comdat_linkage (decl);
DECL_INTERFACE_KNOWN (decl) = 1;
}
tree
build_cleanup (decl)
tree decl;
--- 2509,2552 ----
else
comdat_linkage (decl);
}
else
comdat_linkage (decl);
DECL_INTERFACE_KNOWN (decl) = 1;
}
+ /* Here, we only decide whether or not the tinfo node should be
+ emitted with the vtable. */
+
+ void
+ import_export_tinfo (decl, type)
+ tree decl;
+ tree type;
+ {
+ if (DECL_INTERFACE_KNOWN (decl))
+ return;
+
+ if (IS_AGGR_TYPE (type))
+ import_export_class (type);
+
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_INTERFACE_KNOWN (type)
+ && TYPE_POLYMORPHIC_P (type)
+ /* If -fno-rtti, we're not necessarily emitting this stuff with
+ the class, so go ahead and emit it now. This can happen when
+ a class is used in exception handling. */
+ && flag_rtti)
+ {
+ DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type);
+ DECL_COMDAT (decl) = 0;
+ }
+ else
+ {
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+ DECL_COMDAT (decl) = 1;
+ }
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ }
+
tree
build_cleanup (decl)
tree decl;
*************** finish_file ()
*** 3344,3350 ****
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
! if (walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
reconsider = 1;
/* The list of objects with static storage duration is built up
--- 3341,3347 ----
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
! if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
reconsider = 1;
/* The list of objects with static storage duration is built up
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.135
diff -c -3 -p -r1.135 rtti.c
*** cp/rtti.c 14 Jun 2002 00:50:32 -0000 1.135
--- cp/rtti.c 21 Jun 2002 11:16:09 -0000
***************
*** 1,5 ****
/* RunTime Type Identification
! Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
--- 1,5 ----
/* RunTime Type Identification
! Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
*************** Boston, MA 02111-1307, USA. */
*** 30,45 ****
#include "assert.h"
#include "toplev.h"
/* Accessors for the type_info objects. We need to remember several things
about each of the type_info types. The global tree nodes such as
bltn_desc_type_node are TREE_LISTs, and these macros are used to access
the required information. */
/* The RECORD_TYPE of a type_info derived class. */
#define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
! /* The VAR_DECL of the vtable for the type_info derived class. */
#define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
!
! extern struct obstack permanent_obstack;
static tree build_headof PARAMS((tree));
static tree ifnonnull PARAMS((tree, tree));
--- 30,75 ----
#include "assert.h"
#include "toplev.h"
+ /* C++ returns type information to the user in struct type_info
+ objects. We also use type information to implement dynamic_cast and
+ exception handlers. Type information for a particular type is
+ indicated with an ABI defined structure derived from type_info.
+ This would all be very straight forward, but for the fact that the
+ runtime library provides the definitions of the type_info structure
+ and the ABI defined derived classes. We cannot build declarations
+ of them directly in the compiler, but we need to layout objects of
+ their type. Somewhere we have to lie.
+
+ We define layout compatible POD-structs with compiler-defined names
+ and generate the appropriate initializations for them (complete
+ with explicit mention of their vtable). When we have to provide a
+ type_info to the user we reinterpret_cast the internal compiler
+ type to type_info. A well formed program can only explicitly refer
+ to the type_infos of complete types (& cv void). However, we chain
+ pointer type_infos to the pointed-to-type, and that can be
+ incomplete. We only need the addresses of such incomplete
+ type_info objects for static initialization.
+
+ The type information VAR_DECL of a type is held on the
+ IDENTIFIER_GLOBAL_VALUE of the type's mangled name. That VAR_DECL
+ will be the internal type. It will usually have the correct
+ internal type reflecting the kind of type it represents (pointer,
+ array, function, class, inherited class, etc). When the type it
+ represents is incomplete, it will have the internal type
+ corresponding to type_info. That will only happen at the end of
+ translation, when we are emitting the type info objects. */
+
/* Accessors for the type_info objects. We need to remember several things
about each of the type_info types. The global tree nodes such as
bltn_desc_type_node are TREE_LISTs, and these macros are used to access
the required information. */
/* The RECORD_TYPE of a type_info derived class. */
#define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
! /* The VAR_DECL of the vtable for the type_info derived class.
! This is only filled in at the end of the translation. */
#define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
! /* The IDENTIFIER_NODE naming the real class. */
! #define TINFO_REAL_NAME(NODE) TREE_PURPOSE (NODE)
static tree build_headof PARAMS((tree));
static tree ifnonnull PARAMS((tree, tree));
*************** static tree build_dynamic_cast_1 PARAMS(
*** 48,54 ****
static tree throw_bad_cast PARAMS((void));
static tree throw_bad_typeid PARAMS((void));
static tree get_tinfo_decl_dynamic PARAMS((tree));
! static bool typeid_ok_p PARAMS ((void));
static int qualifier_flags PARAMS((tree));
static int target_incomplete_p PARAMS((tree));
static tree tinfo_base_init PARAMS((tree, tree));
--- 78,85 ----
static tree throw_bad_cast PARAMS((void));
static tree throw_bad_typeid PARAMS((void));
static tree get_tinfo_decl_dynamic PARAMS((tree));
! static tree get_tinfo_ptr PARAMS((tree));
! static bool typeid_ok_p PARAMS((void));
static int qualifier_flags PARAMS((tree));
static int target_incomplete_p PARAMS((tree));
static tree tinfo_base_init PARAMS((tree, tree));
*************** static tree dfs_class_hint_mark PARAMS (
*** 59,73 ****
static tree dfs_class_hint_unmark PARAMS ((tree, void *));
static int class_hint_flags PARAMS((tree));
static tree class_initializer PARAMS((tree, tree, tree));
- static tree synthesize_tinfo_var PARAMS((tree));
- static tree create_real_tinfo_var PARAMS((tree, tree, tree, tree, int));
static tree create_pseudo_type_info PARAMS((const char *, int, ...));
! static tree get_vmi_pseudo_type_info PARAMS((int));
static void create_tinfo_types PARAMS((void));
static int typeinfo_in_lib_p PARAMS((tree));
static int doing_runtime = 0;
\f
void
init_rtti_processing ()
{
--- 90,110 ----
static tree dfs_class_hint_unmark PARAMS ((tree, void *));
static int class_hint_flags PARAMS((tree));
static tree class_initializer PARAMS((tree, tree, tree));
static tree create_pseudo_type_info PARAMS((const char *, int, ...));
! static tree get_pseudo_ti_init PARAMS ((tree, tree, int *));
! static tree get_pseudo_ti_desc PARAMS((tree));
static void create_tinfo_types PARAMS((void));
static int typeinfo_in_lib_p PARAMS((tree));
static int doing_runtime = 0;
\f
+
+ /* Declare language defined type_info type and a pointer to const
+ type_info. This is incomplete here, and will be completed when
+ the user #includes <typeinfo>. There are language defined
+ restrictions on what can be done until that is included. Create
+ the internal versions of the ABI types. */
+
void
init_rtti_processing ()
{
*************** init_rtti_processing ()
*** 75,82 ****
type_info_type_node = xref_tag
(class_type_node, get_identifier ("type_info"), 1);
pop_namespace ();
! tinfo_decl_type =
! build_qualified_type (type_info_type_node, TYPE_QUAL_CONST);
}
/* Given the expression EXP of type `class *', return the head of the
--- 112,122 ----
type_info_type_node = xref_tag
(class_type_node, get_identifier ("type_info"), 1);
pop_namespace ();
! type_info_ptr_type =
! build_pointer_type
! (build_qualified_type (type_info_type_node, TYPE_QUAL_CONST));
!
! create_tinfo_types ();
}
/* Given the expression EXP of type `class *', return the head of the
*************** get_tinfo_decl_dynamic (exp)
*** 183,195 ****
/* The RTTI information is at index -1. */
index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
! TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
return t;
}
! /* otherwise return the type_info for the static type of the expr. */
! exp = get_tinfo_decl (TYPE_MAIN_VARIANT (type));
! return build_unary_op (ADDR_EXPR, exp, 0);
}
static bool
--- 223,234 ----
/* The RTTI information is at index -1. */
index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
! TREE_TYPE (t) = type_info_ptr_type;
return t;
}
! /* Otherwise return the type_info for the static type of the expr. */
! return get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
}
static bool
*************** tinfo_name (type)
*** 263,271 ****
return name_string;
}
! /* Returns a decl for the type_info variable for TYPE. You must
! arrange that the decl is mark_used, if actually use it --- decls in
! vtables are only used if the vtable is output. */
tree
get_tinfo_decl (type)
--- 302,310 ----
return name_string;
}
! /* Return a VAR_DECL for the internal ABI defined type_info object for
! TYPE. You must arrange that the decl is mark_used, if actually use
! it --- decls in vtables are only used if the vtable is output. */
tree
get_tinfo_decl (type)
*************** get_tinfo_decl (type)
*** 278,284 ****
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error ("cannot create type information for type `%T' because its size is variable",
! type);
return error_mark_node;
}
--- 317,323 ----
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error ("cannot create type information for type `%T' because its size is variable",
! type);
return error_mark_node;
}
*************** get_tinfo_decl (type)
*** 291,326 ****
name = mangle_typeinfo_for_type (type);
d = IDENTIFIER_GLOBAL_VALUE (name);
! if (d)
! /* OK */;
! else
{
! /* The tinfo decl is the type_info object itself. We make all
! tinfo objects look as type_info, even though they will end up
! being a subclass of that when emitted. This means that we'll
! erroneously think we know the dynamic type -- be careful in the
! runtime. */
! d = build_lang_decl (VAR_DECL, name, tinfo_decl_type);
DECL_ARTIFICIAL (d) = 1;
- DECL_ALIGN (d) = TYPE_ALIGN (ptr_type_node);
- DECL_USER_ALIGN (d) = 0;
TREE_READONLY (d) = 1;
TREE_STATIC (d) = 1;
DECL_EXTERNAL (d) = 1;
- TREE_PUBLIC (d) = 1;
SET_DECL_ASSEMBLER_NAME (d, name);
- DECL_COMDAT (d) = 1;
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
pushdecl_top_level (d);
/* Remember the type it is for. */
TREE_TYPE (name) = type;
- TREE_USED (name) = 1;
}
return d;
}
/* Return the type_info object for TYPE. */
tree
--- 330,373 ----
name = mangle_typeinfo_for_type (type);
d = IDENTIFIER_GLOBAL_VALUE (name);
! if (!d)
{
! tree var_desc = get_pseudo_ti_desc (type);
!
! d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
DECL_ARTIFICIAL (d) = 1;
TREE_READONLY (d) = 1;
TREE_STATIC (d) = 1;
DECL_EXTERNAL (d) = 1;
SET_DECL_ASSEMBLER_NAME (d, name);
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
pushdecl_top_level (d);
+
/* Remember the type it is for. */
TREE_TYPE (name) = type;
}
+
return d;
}
+ /* Return a pointer to a type_info object describing TYPE, suitably
+ cast to the language defined type. */
+
+ static tree
+ get_tinfo_ptr (type)
+ tree type;
+ {
+ tree exp = get_tinfo_decl (type);
+
+ /* Convert to type_info type. */
+ exp = build_unary_op (ADDR_EXPR, exp, 0);
+ exp = ocp_convert (type_info_ptr_type, exp, CONV_REINTERPRET, 0);
+
+ return exp;
+ }
+
/* Return the type_info object for TYPE. */
tree
*************** get_typeid (type)
*** 349,355 ****
if (!type)
return error_mark_node;
! return get_tinfo_decl (type);
}
/* Check whether TEST is null before returning RESULT. If TEST is used in
--- 396,402 ----
if (!type)
return error_mark_node;
! return build_indirect_ref (get_tinfo_ptr (type), NULL);
}
/* Check whether TEST is null before returning RESULT. If TEST is used in
*************** tinfo_base_init (desc, target)
*** 682,687 ****
--- 729,735 ----
{
tree init = NULL_TREE;
tree name_decl;
+ tree vtable_ptr;
{
tree name_name;
*************** tinfo_base_init (desc, target)
*** 709,720 ****
cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
pushdecl_top_level (name_decl);
}
!
! if (TINFO_VTABLE_DECL (desc))
{
! tree vtbl_ptr = TINFO_VTABLE_DECL (desc);
! init = tree_cons (NULL_TREE, vtbl_ptr, init);
}
init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
--- 757,794 ----
cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
pushdecl_top_level (name_decl);
}
!
! vtable_ptr = TINFO_VTABLE_DECL (desc);
! if (!vtable_ptr)
{
! tree real_type;
!
! push_nested_namespace (abi_node);
! real_type = xref_tag (class_type_node, TINFO_REAL_NAME (desc), 1);
! pop_nested_namespace (abi_node);
!
! if (!COMPLETE_TYPE_P (real_type))
! {
! /* We never saw a definition of this type, so we need to
! tell the compiler that this is an exported class, as
! indeed all of the __*_type_info classes are. */
! SET_CLASSTYPE_INTERFACE_KNOWN (real_type);
! CLASSTYPE_INTERFACE_ONLY (real_type) = 1;
! }
!
! vtable_ptr = get_vtable_decl (real_type, /*complete=*/1);
! vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0);
!
! /* We need to point into the middle of the vtable. */
! vtable_ptr = build (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
! size_binop (MULT_EXPR,
! size_int (2),
! TYPE_SIZE_UNIT (vtable_entry_type)));
! TREE_CONSTANT (vtable_ptr) = 1;
!
! TINFO_VTABLE_DECL (desc) = vtable_ptr;
}
+ init = tree_cons (NULL_TREE, vtable_ptr, init);
init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
*************** ptr_initializer (desc, target, non_publi
*** 763,770 ****
}
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
! build_unary_op (ADDR_EXPR,
! get_tinfo_decl (TYPE_MAIN_VARIANT (to)), 0),
init);
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
--- 837,843 ----
}
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
! get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
init);
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
*************** ptm_initializer (desc, target, non_publi
*** 801,812 ****
}
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
! build_unary_op (ADDR_EXPR,
! get_tinfo_decl (TYPE_MAIN_VARIANT (to)), 0),
init);
init = tree_cons (NULL_TREE,
! build_unary_op (ADDR_EXPR, get_tinfo_decl (klass), 0),
! init);
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
--- 874,884 ----
}
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
! get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
init);
init = tree_cons (NULL_TREE,
! get_tinfo_ptr (klass),
! init);
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
*************** typeinfo_in_lib_p (type)
*** 927,1007 ****
}
}
! /* Generate a pseudo_type_info VAR_DECL suitable for the supplied
! TARGET_TYPE and corresponding to PUBLIC_DECL. This is the structure expected by
! the runtime, and therefore has additional fields. If we need not emit a
! definition (because the runtime must contain it), return NULL_TREE,
! otherwise return the VAR_DECL. */
static tree
! synthesize_tinfo_var (public_decl)
! tree public_decl;
{
! tree var_init = NULL_TREE;
! tree var_type = NULL_TREE;
! int non_public = 0;
! tree target_type = TREE_TYPE (DECL_NAME (public_decl));
! my_friendly_assert (target_type != NULL_TREE, 20000120);
!
! /* Say we've dealt with it. */
! TREE_TYPE (DECL_NAME (public_decl)) = NULL_TREE;
!
! switch (TREE_CODE (target_type))
{
case POINTER_TYPE:
! if (TYPE_PTRMEM_P (target_type))
! {
! var_type = ptm_desc_type_node;
! var_init = ptm_initializer (var_type, target_type, &non_public);
! }
else
! {
! if (typeinfo_in_lib_p (target_type) && !doing_runtime)
! /* These are in the runtime. */
! return NULL_TREE;
! var_type = ptr_desc_type_node;
! var_init = ptr_initializer (var_type, target_type, &non_public);
! }
break;
case ENUMERAL_TYPE:
! var_type = enum_desc_type_node;
! var_init = generic_initializer (var_type, target_type);
break;
case FUNCTION_TYPE:
! var_type = func_desc_type_node;
! var_init = generic_initializer (var_type, target_type);
break;
case ARRAY_TYPE:
! var_type = ary_desc_type_node;
! var_init = generic_initializer (var_type, target_type);
break;
case UNION_TYPE:
case RECORD_TYPE:
! if (TYPE_PTRMEMFUNC_P (target_type))
! {
! var_type = ptm_desc_type_node;
! var_init = ptm_initializer (var_type, target_type, &non_public);
! }
! else if (!COMPLETE_TYPE_P (target_type))
{
! /* Emit a non-public class_type_info. */
! non_public = 1;
! var_type = class_desc_type_node;
! var_init = class_initializer (var_type, target_type, NULL_TREE);
! }
! else if (!CLASSTYPE_N_BASECLASSES (target_type))
! {
! var_type = class_desc_type_node;
! var_init = class_initializer (var_type, target_type, NULL_TREE);
}
else
{
! /* if this has a single public non-virtual base, it's easier */
! tree binfo = TYPE_BINFO (target_type);
int nbases = BINFO_N_BASETYPES (binfo);
tree base_binfos = BINFO_BASETYPES (binfo);
tree base_inits = NULL_TREE;
- int is_simple = nbases == 1;
int ix;
/* Generate the base information initializer. */
--- 999,1061 ----
}
}
! /* Generate the initializer for the type info describing
! TYPE. VAR_DESC is a . NON_PUBLIC_P is set non-zero, if the VAR_DECL
! should not be exported from this object file. This should only be
! called at the end of translation, when we know that no further
! types will be completed. */
static tree
! get_pseudo_ti_init (type, var_desc, non_public_p)
! tree type;
! tree var_desc;
! int *non_public_p;
{
! my_friendly_assert (at_eof, 20021120);
! switch (TREE_CODE (type))
{
case POINTER_TYPE:
! if (TYPE_PTRMEM_P (type))
! return ptm_initializer (var_desc, type, non_public_p);
else
! return ptr_initializer (var_desc, type, non_public_p);
break;
case ENUMERAL_TYPE:
! return generic_initializer (var_desc, type);
break;
case FUNCTION_TYPE:
! return generic_initializer (var_desc, type);
break;
case ARRAY_TYPE:
! return generic_initializer (var_desc, type);
break;
case UNION_TYPE:
case RECORD_TYPE:
! if (TYPE_PTRMEMFUNC_P (type))
! return ptm_initializer (var_desc, type, non_public_p);
! else if (var_desc == class_desc_type_node)
{
! if (!COMPLETE_TYPE_P (type))
! /* Emit a non-public class_type_info. */
! *non_public_p = 1;
! return class_initializer (var_desc, type, NULL_TREE);
}
+ else if (var_desc == si_class_desc_type_node)
+ {
+ tree base_binfos = BINFO_BASETYPES (TYPE_BINFO (type));
+ tree base_binfo = TREE_VEC_ELT (base_binfos, 0);
+ tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
+ tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
+
+ return class_initializer (var_desc, type, base_inits);
+ }
else
{
! int hint = class_hint_flags (type);
! tree binfo = TYPE_BINFO (type);
int nbases = BINFO_N_BASETYPES (binfo);
tree base_binfos = BINFO_BASETYPES (binfo);
tree base_inits = NULL_TREE;
int ix;
/* Generate the base information initializer. */
*************** synthesize_tinfo_var (public_decl)
*** 1015,1042 ****
if (TREE_PUBLIC (base_binfo))
flags |= 2;
! tinfo = get_tinfo_decl (BINFO_TYPE (base_binfo));
! tinfo = build_unary_op (ADDR_EXPR, tinfo, 0);
if (TREE_VIA_VIRTUAL (base_binfo))
{
/* We store the vtable offset at which the virtual
base offset can be found. */
! offset = BINFO_VPTR_FIELD (binfo_for_vbase (BINFO_TYPE (base_binfo),
! target_type));
offset = convert (sizetype, offset);
flags |= 1;
}
else
offset = BINFO_OFFSET (base_binfo);
- /* is it a single public inheritance? */
- if (is_simple && flags == 2 && integer_zerop (offset))
- {
- base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
- break;
- }
- is_simple = 0;
-
/* combine offset and flags into one field */
offset = cp_build_binary_op (LSHIFT_EXPR, offset,
build_int_2 (8, 0));
--- 1069,1087 ----
if (TREE_PUBLIC (base_binfo))
flags |= 2;
! tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
{
/* We store the vtable offset at which the virtual
base offset can be found. */
! offset = BINFO_VPTR_FIELD
! (binfo_for_vbase (BINFO_TYPE (base_binfo), type));
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_2 (8, 0));
*************** synthesize_tinfo_var (public_decl)
*** 1047,1134 ****
base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
base_inits = tree_cons (NULL_TREE, base_init, base_inits);
}
!
! if (is_simple)
! var_type = si_class_desc_type_node;
! else
! {
! int hint = class_hint_flags (target_type);
!
! base_inits = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_inits);
! base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
! /* Prepend the number of bases. */
! base_inits = tree_cons (NULL_TREE,
! build_int_2 (nbases, 0), base_inits);
! /* Prepend the hint flags. */
! base_inits = tree_cons (NULL_TREE,
! build_int_2 (hint, 0), base_inits);
! var_type = get_vmi_pseudo_type_info (nbases);
! }
! var_init = class_initializer (var_type, target_type, base_inits);
}
break;
default:
! if (typeinfo_in_lib_p (target_type))
! {
! if (!doing_runtime)
! /* These are guaranteed to be in the runtime. */
! return NULL_TREE;
! var_type = bltn_desc_type_node;
! var_init = generic_initializer (var_type, target_type);
! break;
! }
! abort ();
}
-
- return create_real_tinfo_var (target_type,
- public_decl, TINFO_PSEUDO_TYPE (var_type),
- var_init, non_public);
- }
-
- /* Create the real typeinfo variable. NON_PUBLIC indicates that we cannot
- make this variable public (comdat). */
-
- static tree
- create_real_tinfo_var (target_type, public_decl, type, init, non_public)
- tree target_type;
- tree public_decl;
- tree type;
- tree init;
- int non_public;
- {
- static int count = 0;
- tree decl;
- tree hidden_name;
- char hidden[30];
- tree name = DECL_ASSEMBLER_NAME (public_decl);
-
- /* We cannot give this the name NAME, as that already is globally
- bound to the tinfo_decl we originally created for this type in
- get_tinfo_decl. */
- sprintf (hidden, "__ti_%d", count++);
- hidden_name = get_identifier (hidden);
-
- decl = build_lang_decl (VAR_DECL, hidden_name,
- build_qualified_type (type, TYPE_QUAL_CONST));
- DECL_ARTIFICIAL (decl) = 1;
- TREE_READONLY (decl) = 1;
- TREE_STATIC (decl) = 1;
- DECL_EXTERNAL (decl) = 0;
-
- if (!non_public)
- {
- TREE_PUBLIC (decl) = 1;
- if (flag_weak
- || (DECL_COMDAT (public_decl) && !typeinfo_in_lib_p (target_type)))
- comdat_linkage (decl);
- }
- SET_DECL_ASSEMBLER_NAME (decl, name);
- DECL_INITIAL (decl) = init;
- cp_finish_decl (decl, init, NULL_TREE, 0);
- pushdecl_top_level (decl);
- TREE_USED (decl) = 1;
- return decl;
}
/* Generate the RECORD_TYPE containing the data layout of a type_info
--- 1092,1114 ----
base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
base_inits = tree_cons (NULL_TREE, base_init, base_inits);
}
! base_inits = build (CONSTRUCTOR,
! NULL_TREE, NULL_TREE, base_inits);
! base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
! /* Prepend the number of bases. */
! base_inits = tree_cons (NULL_TREE,
! build_int_2 (nbases, 0), base_inits);
! /* Prepend the hint flags. */
! base_inits = tree_cons (NULL_TREE,
! build_int_2 (hint, 0), base_inits);
!
! return class_initializer (var_desc, type, base_inits);
}
break;
default:
! return generic_initializer (var_desc, type);
}
}
/* Generate the RECORD_TYPE containing the data layout of a type_info
*************** create_real_tinfo_var (target_type, publ
*** 1137,1143 ****
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_DECL is the vtable decl.
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
--- 1117,1126 ----
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
*************** create_real_tinfo_var (target_type, publ
*** 1146,1154 ****
static tree
create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
{
! tree real_type, pseudo_type;
char *pseudo_name;
- tree vtable_decl;
int ix;
tree fields[10];
tree field_decl;
--- 1129,1136 ----
static tree
create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
{
! tree pseudo_type;
char *pseudo_name;
int ix;
tree fields[10];
tree field_decl;
*************** create_pseudo_type_info VPARAMS((const c
*** 1165,1192 ****
if (ident)
sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);
- /* Get the vtable decl. */
- real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
- if (! TYPE_SIZE (real_type))
- {
- /* We never saw a definition of this type, so we need to tell the
- compiler that this is an exported class, as indeed all of the
- __*_type_info classes are. */
- SET_CLASSTYPE_INTERFACE_KNOWN (real_type);
- CLASSTYPE_INTERFACE_ONLY (real_type) = 1;
- }
-
- vtable_decl = get_vtable_decl (real_type, /*complete=*/1);
- vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0);
-
- /* We need to point into the middle of the vtable. */
- vtable_decl
- = build (PLUS_EXPR, TREE_TYPE (vtable_decl), vtable_decl,
- size_binop (MULT_EXPR,
- size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
- TYPE_SIZE_UNIT (vtable_entry_type)));
- TREE_CONSTANT (vtable_decl) = 1;
-
/* First field is the pseudo type_info base class. */
fields[0] = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
--- 1147,1152 ----
*************** create_pseudo_type_info VPARAMS((const c
*** 1200,1252 ****
TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
! TINFO_VTABLE_DECL (result) = vtable_decl;
! TINFO_PSEUDO_TYPE (result) = pseudo_type;
VA_CLOSE (ap);
return result;
}
! /* Return a descriptor for a vmi type with NUM_BASES bases. */
static tree
! get_vmi_pseudo_type_info (num_bases)
! int num_bases;
{
! tree desc;
! tree array_domain, base_array;
!
! if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)
{
! int ix;
! tree extend = make_tree_vec (num_bases + 5);
!
! for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)
! TREE_VEC_ELT (extend, ix) = TREE_VEC_ELT (vmi_class_desc_type_node, ix);
! vmi_class_desc_type_node = extend;
! }
! desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);
!
! if (desc)
! return desc;
!
! /* Add number of bases and trailing array of base_class_type_info. */
! array_domain = build_index_type (size_int (num_bases));
! base_array = build_array_type (base_desc_type_node, array_domain);
!
! push_nested_namespace (abi_node);
!
! desc = create_pseudo_type_info
! ("__vmi_class_type_info", num_bases,
! 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),
! NULL);
!
! pop_nested_namespace (abi_node);
! TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = desc;
! return desc;
}
/* Make sure the required builtin types exist for generating the type_info
--- 1160,1255 ----
TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
! TINFO_REAL_NAME (result) = get_identifier (real_name);
! TINFO_PSEUDO_TYPE (result) =
! cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
VA_CLOSE (ap);
return result;
}
! /* Return 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. */
static tree
! get_pseudo_ti_desc (type)
! tree type;
{
! switch (TREE_CODE (type))
{
! case POINTER_TYPE:
! return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node;
! case ENUMERAL_TYPE:
! return enum_desc_type_node;
! case FUNCTION_TYPE:
! return func_desc_type_node;
! case ARRAY_TYPE:
! return ary_desc_type_node;
! case UNION_TYPE:
! case RECORD_TYPE:
! if (TYPE_PTRMEMFUNC_P (type))
! return ptm_desc_type_node;
! else if (!COMPLETE_TYPE_P (type))
! {
! my_friendly_assert (at_eof, 20020609);
! return class_desc_type_node;
! }
! else if (!CLASSTYPE_N_BASECLASSES (type))
! return class_desc_type_node;
! else
! {
! tree base_binfo =
! TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), 0);
! int num_bases = BINFO_N_BASETYPES (TYPE_BINFO (type));
!
! if (num_bases == 1
! && TREE_PUBLIC (base_binfo)
! && !TREE_VIA_VIRTUAL (base_binfo)
! && integer_zerop (BINFO_OFFSET (base_binfo)))
! /* single non-virtual public. */
! return si_class_desc_type_node;
! else
! {
! tree var_desc;
! tree array_domain, base_array;
!
! if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)
! {
! int ix;
! tree extend = make_tree_vec (num_bases + 5);
!
! for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)
! TREE_VEC_ELT (extend, ix)
! = TREE_VEC_ELT (vmi_class_desc_type_node, ix);
! vmi_class_desc_type_node = extend;
! }
! var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);
! if (var_desc)
! return var_desc;
!
! /* Add number of bases and trailing array of
! base_class_type_info. */
! array_domain = build_index_type (size_int (num_bases));
! base_array =
! build_array_type (base_desc_type_node, array_domain);
!
! push_nested_namespace (abi_node);
! var_desc = create_pseudo_type_info
! ("__vmi_class_type_info", num_bases,
! 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),
! NULL);
! pop_nested_namespace (abi_node);
! TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc;
! return var_desc;
! }
! }
! default:
! return bltn_desc_type_node;
! }
}
/* Make sure the required builtin types exist for generating the type_info
*************** get_vmi_pseudo_type_info (num_bases)
*** 1255,1269 ****
static void
create_tinfo_types ()
{
! tree ptr_type_info;
!
! if (bltn_desc_type_node)
! return;
! push_nested_namespace (abi_node);
! ptr_type_info = build_pointer_type
! (build_qualified_type
! (type_info_type_node, TYPE_QUAL_CONST));
/* Create the internal type_info structure. This is used as a base for
the other structures. */
--- 1258,1266 ----
static void
create_tinfo_types ()
{
! my_friendly_assert (!ti_desc_type_node, 20020609);
! push_nested_namespace (abi_node);
/* Create the internal type_info structure. This is used as a base for
the other structures. */
*************** create_tinfo_types ()
*** 1303,1309 ****
This is really a descendant of __class_type_info. */
si_class_desc_type_node = create_pseudo_type_info
("__si_class_type_info", 0,
! build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
NULL);
/* Base class internal helper. Pointer to base type, offset to base,
--- 1300,1306 ----
This is really a descendant of __class_type_info. */
si_class_desc_type_node = create_pseudo_type_info
("__si_class_type_info", 0,
! build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
NULL);
/* Base class internal helper. Pointer to base type, offset to base,
*************** create_tinfo_types ()
*** 1311,1317 ****
{
tree fields[2];
! fields[0] = build_decl (FIELD_DECL, NULL_TREE, ptr_type_info);
fields[1] = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
base_desc_type_node = make_aggr_type (RECORD_TYPE);
finish_builtin_type (base_desc_type_node, "__base_class_type_info_pseudo",
--- 1308,1314 ----
{
tree fields[2];
! fields[0] = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);
fields[1] = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
base_desc_type_node = make_aggr_type (RECORD_TYPE);
finish_builtin_type (base_desc_type_node, "__base_class_type_info_pseudo",
*************** create_tinfo_types ()
*** 1328,1334 ****
ptr_desc_type_node = create_pseudo_type_info
("__pointer_type_info", 0,
build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
! build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
NULL);
/* Pointer to member data type_info. Add qualifications flags,
--- 1325,1331 ----
ptr_desc_type_node = create_pseudo_type_info
("__pointer_type_info", 0,
build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
! build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
NULL);
/* Pointer to member data type_info. Add qualifications flags,
*************** create_tinfo_types ()
*** 1337,1344 ****
ptm_desc_type_node = create_pseudo_type_info
("__pointer_to_member_type_info", 0,
build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
! build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
! build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
NULL);
pop_nested_namespace (abi_node);
--- 1334,1341 ----
ptm_desc_type_node = create_pseudo_type_info
("__pointer_to_member_type_info", 0,
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);
*************** emit_support_tinfos ()
*** 1405,1476 ****
definition emitted for it. */
int
! tinfo_decl_p (t, data)
tree t;
void *data ATTRIBUTE_UNUSED;
{
! return TREE_CODE (t) == VAR_DECL
! && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == (t)
! && TREE_TYPE (t) == tinfo_decl_type
! && TREE_TYPE (DECL_NAME (t));
}
! /* Emit a suitable type_info definition for the type_info decl pointed to by
! DECL_PTR. We emit a completely new variable, of the correct type for the
! actual type this is describing. The DECL_ASSEMBLER_NAME of the generated
! definition is set to that of the supplied decl, so that they can be tied
! up. Mark the supplied decl as having been dealt with. Emitting one
! definition might cause other definitions to be required.
!
! We need to do things this way, because we're trying to do something like
!
! struct B : A {
! ...
! };
!
! extern const A tinfo_var;
!
! const B tinfo_var = {...};
!
! which is not permitted. Also, we've not necessarily seen the definition of B.
! So we do something like the following,
!
! extern const A tinfo_var;
!
! struct pseudo_A {
! const void *vtable_ptr;
! const char *name;
! };
! struct pseudo_B {
! pseudo_A base;
! ...
! };
!
! const pseudo_B proxy_tinfo_var attribute((assembler_name="tinfo_var")) =
! {
! {&B::vtable, "..."},
! ...
! };
!
! pseudo_A and pseudo_B must be layout equivalent to the real definitions in
! the runtime. */
int
emit_tinfo_decl (decl_ptr, data)
tree *decl_ptr;
void *data ATTRIBUTE_UNUSED;
{
! tree tinfo_decl = *decl_ptr;
! tree decl;
! my_friendly_assert (TREE_TYPE (tinfo_decl) == tinfo_decl_type, 20000121);
! import_export_decl (tinfo_decl);
! if (DECL_REALLY_EXTERN (tinfo_decl) || !DECL_NEEDED_P (tinfo_decl))
return 0;
! create_tinfo_types ();
! decl = synthesize_tinfo_var (tinfo_decl);
! return decl != 0;
}
--- 1402,1460 ----
definition emitted for it. */
int
! unemitted_tinfo_decl_p (t, data)
tree t;
void *data ATTRIBUTE_UNUSED;
{
! if (/* It's a var decl */
! TREE_CODE (t) == VAR_DECL
! /* whos name points back to itself */
! && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t
! /* whos name's type is non-null */
! && TREE_TYPE (DECL_NAME (t))
! /* and whos type is a struct */
! && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
! /* with a first field of our pseudo type info */
! && TREE_TYPE (TYPE_FIELDS (TREE_TYPE (t))) == ti_desc_type_node)
! return 1;
! return 0;
}
! /* Finish a type info decl. DECL_PTR is a pointer to an unemitted
! tinfo decl. Determine whether it needs emitting, and if so
! generate the initializer. */
int
emit_tinfo_decl (decl_ptr, data)
tree *decl_ptr;
void *data ATTRIBUTE_UNUSED;
{
! tree decl = *decl_ptr;
! tree type = TREE_TYPE (DECL_NAME (decl));
! int non_public;
! tree var_desc, var_init;
! import_export_tinfo (decl, type);
! if (DECL_REALLY_EXTERN (decl) || !DECL_NEEDED_P (decl))
! return 0;
! if (!doing_runtime && typeinfo_in_lib_p (type))
return 0;
! non_public = 0;
! var_desc = get_pseudo_ti_desc (type);
! var_init = get_pseudo_ti_init (type, var_desc, &non_public);
! DECL_EXTERNAL (decl) = 0;
! TREE_PUBLIC (decl) = !non_public;
! if (!non_public
! && (flag_weak || (DECL_COMDAT (decl) && !typeinfo_in_lib_p (type))))
! comdat_linkage (decl);
! DECL_INITIAL (decl) = var_init;
! cp_finish_decl (decl, var_init, NULL_TREE, 0);
!
! /* Say we've dealt with it. */
! TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
!
! return 1;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-07-22 10:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-07-22 3:26 Fwd: [C++ PATCH]: Rework typeinfo objects Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).