patch for complex MI vtable names
Mike Stump
mrs@wrs.com
Mon Oct 6 18:54:00 GMT 1997
Here is one I'v been meaning to do for years, but never got around to
it, well, I finally got around to it! :-)
I solved this in such a way as to be perfectly backwards compatible
with prior releases, and yet beefy enough to never fail (even in
complex cases).
Could you put this one in? Thanks.
1997-10-06 Mike Stump <mrs@wrs.com>
* class.c (build_type_pathname): Remove.
(prepare_fresh_vtable): Fix problem with complex MI vtable names.
Doing diffs in testsuite/g++.old-deja/g++.mike/virt6.C.~1~:
*** testsuite/g++.old-deja/g++.mike/virt6.C.~1~ Mon Oct 6 17:59:31 1997
--- testsuite/g++.old-deja/g++.mike/virt6.C Mon Oct 6 17:57:26 1997
***************
*** 0 ****
--- 1,39 ----
+ // This testcase ensures that we can build vtable names for complex MI
+ // classes.
+
+ class C_A {
+ public:
+ virtual int foo(void *) { }
+ } a;
+
+ class C_B : public C_A {
+ } b;
+
+ class C_C : public C_A {
+ } c;
+
+ class C_D : public C_A {
+ } d;
+
+ class C_E : public C_C, public C_B {
+ public:
+ virtual int foo(void *) { }
+ } e;
+
+ class C_F : public C_D, public C_B {
+ public:
+ virtual int foo(void *) { }
+ } f;
+
+ class C_G : public C_A {
+ public:
+ virtual int foo(void *) { }
+ } g;
+
+ class C_H : public C_G, public C_E, public C_F {
+ public:
+ virtual int foo(void *) { }
+ } h;
+
+ int main() {
+ }
--------------
Doing diffs in cp/class.c.~1~:
*** cp/class.c.~1~ Thu Oct 2 15:15:47 1997
--- cp/class.c Mon Oct 6 17:34:00 1997
*************** static tree get_derived_offset PROTO((tr
*** 96,102 ****
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));
--- 96,101 ----
*************** get_vtable_name (type)
*** 586,593 ****
tree type;
{
tree type_id = build_typename_overload (type);
! 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++) ;
--- 585,592 ----
tree type;
{
tree type_id = build_typename_overload (type);
! 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++) ;
*************** build_vtable (binfo, type)
*** 735,803 ****
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
--- 734,739 ----
*************** extern tree signed_size_zero_node;
*** 808,827 ****
FOR_TYPE is the derived type which caused this table to
be needed.
! BINFO is the type association which provided TYPE for FOR_TYPE. */
static void
prepare_fresh_vtable (binfo, for_type)
tree binfo, for_type;
{
! tree basetype = BINFO_TYPE (binfo);
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 offset;
/* Remember which class this vtable is really for. */
DECL_CONTEXT (new_decl) = for_type;
--- 744,826 ----
FOR_TYPE is the derived type which caused this table to
be needed.
! 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;
tree orig_decl = BINFO_VTABLE (binfo);
! 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;
*************** get_vfield_name (type)
*** 5405,5412 ****
binfo = BINFO_BASETYPE (binfo, 0);
type = BINFO_TYPE (binfo);
! 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);
}
--- 5404,5411 ----
binfo = BINFO_BASETYPE (binfo, 0);
type = BINFO_TYPE (binfo);
! 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);
}
--------------
Doing diffs in cp/typeck2.c.~1~:
*** cp/typeck2.c.~1~ Mon Aug 25 08:33:32 1997
--- cp/typeck2.c Mon Oct 6 17:34:00 1997
*************** ack (s, v, v2)
*** 301,307 ****
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
! /* First used: 0 (reserved), Last used: 367. Free: */
static int abortcount = 0;
--- 301,307 ----
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
! /* First used: 0 (reserved), Last used: 369. Free: */
static int abortcount = 0;
--------------
More information about the Gcc-bugs
mailing list