diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 147 |
1 files changed, 73 insertions, 74 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index da5fcd3b3ab..e24d6a230b9 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -96,7 +96,6 @@ static tree get_derived_offset PROTO((tree, tree)); static tree get_basefndecls PROTO((tree, tree)); static void set_rtti_entry PROTO((tree, tree, tree)); static tree build_vtable PROTO((tree, tree)); -static tree build_type_pathname PROTO((char *, tree, tree)); static void prepare_fresh_vtable PROTO((tree, tree)); static void fixup_vtable_deltas1 PROTO((tree, tree)); static void fixup_vtable_deltas PROTO((tree, int, tree)); @@ -588,8 +587,8 @@ get_vtable_name (type) tree type; { tree type_id = build_typename_overload (type); - char *buf = (char *)alloca (strlen (VTABLE_NAME_FORMAT) - + IDENTIFIER_LENGTH (type_id) + 2); + char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + + IDENTIFIER_LENGTH (type_id) + 2); char *ptr = IDENTIFIER_POINTER (type_id); int i; for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ; @@ -737,69 +736,6 @@ build_vtable (binfo, type) return decl; } -/* Given a base type PARENT, and a derived type TYPE, build - a name which distinguishes exactly the PARENT member of TYPE's type. - - FORMAT is a string which controls how sprintf formats the name - we have generated. - - For example, given - - class A; class B; class C : A, B; - - it is possible to distinguish "A" from "C's A". And given - - class L; - class A : L; class B : L; class C : A, B; - - it is possible to distinguish "L" from "A's L", and also from - "C's L from A". - - Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the - type, as template have DECL_NAMEs like: X<int>, whereas the - DECL_ASSEMBLER_NAME is set to be something the assembler can handle. */ - -static tree -build_type_pathname (format, parent, type) - char *format; - tree parent, type; -{ - extern struct obstack temporary_obstack; - char *first, *base, *name; - int i; - tree id; - - parent = TYPE_MAIN_VARIANT (parent); - - /* Remember where to cut the obstack to. */ - first = obstack_base (&temporary_obstack); - - /* Put on TYPE+PARENT. */ - obstack_grow (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (type), - TYPE_ASSEMBLER_NAME_LENGTH (type)); -#ifdef JOINER - obstack_1grow (&temporary_obstack, JOINER); -#else - obstack_1grow (&temporary_obstack, '_'); -#endif - obstack_grow0 (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (parent), - TYPE_ASSEMBLER_NAME_LENGTH (parent)); - i = obstack_object_size (&temporary_obstack); - base = obstack_base (&temporary_obstack); - obstack_finish (&temporary_obstack); - - /* Put on FORMAT+TYPE+PARENT. */ - obstack_blank (&temporary_obstack, strlen (format) + i + 1); - name = obstack_base (&temporary_obstack); - sprintf (name, format, base); - id = get_identifier (name); - obstack_free (&temporary_obstack, first); - - return id; -} - extern tree signed_size_zero_node; /* Give TYPE a new virtual function table which is initialized @@ -810,20 +746,83 @@ extern tree signed_size_zero_node; FOR_TYPE is the derived type which caused this table to be needed. - BINFO is the type association which provided TYPE for FOR_TYPE. */ + BINFO is the type association which provided TYPE for FOR_TYPE. + + The order in which vtables are built (by calling this function) for + an object must remain the same, otherwise a binary incompatibility + can result. */ static void prepare_fresh_vtable (binfo, for_type) tree binfo, for_type; { - tree basetype = BINFO_TYPE (binfo); + tree basetype; tree orig_decl = BINFO_VTABLE (binfo); - /* This name is too simplistic. We can have multiple basetypes for - for_type, and we really want different names. (mrs) */ - tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type); - tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); + tree name; + tree new_decl; tree offset; + tree path = binfo; + char *buf, *buf2; + char joiner = '_'; + int i; + +#ifdef JOINER + joiner = JOINER; +#endif + + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo)); + + buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype); + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1; + + /* We know that the vtable that we are going to create doesn't exist + yet in the global namespace, and when we finish, it will be + pushed into the global namespace. In complex MI hierarchies, we + have to loop while the name we are thinking of adding is globally + defined, adding more name components to the vtable name as we + loop, until the name is unique. This is because in complex MI + cases, we might have the same base more than once. This means + that the order in which this function is called for vtables must + remain the same, otherwise binary compatibility can be + compromised. */ + + while (1) + { + char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type) + 1 + i); + char *new_buf2; + + sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner, + buf2); + buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1); + sprintf (buf, VTABLE_NAME_FORMAT, buf1); + name = get_identifier (buf); + + /* If this name doesn't clash, then we can use it, otherwise + we add more to the name until it is unique. */ + + if (! IDENTIFIER_GLOBAL_VALUE (name)) + break; + + /* Set values for next loop through, if the name isn't unique. */ + + path = BINFO_INHERITANCE_CHAIN (path); + + /* We better not run out of stuff to make it unique. */ + my_friendly_assert (path != NULL_TREE, 368); + + basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path)); + + /* We better not run out of stuff to make it unique. */ + my_friendly_assert (for_type != basetype, 369); + + i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i; + new_buf2 = (char *) alloca (i); + sprintf (new_buf2, "%s%c%s", + TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2); + buf2 = new_buf2; + } + new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); /* Remember which class this vtable is really for. */ DECL_CONTEXT (new_decl) = for_type; @@ -5407,8 +5406,8 @@ get_vfield_name (type) binfo = BINFO_BASETYPE (binfo, 0); type = BINFO_TYPE (binfo); - buf = (char *)alloca (sizeof (VFIELD_NAME_FORMAT) - + TYPE_NAME_LENGTH (type) + 2); + buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) + + TYPE_NAME_LENGTH (type) + 2); sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type)); return get_identifier (buf); } |