Fixed getting the superclass when building class tree used for +load, would

cause extremely rare crashes

Co-Authored-By: Nicola Pero <n.pero@mi.flashnet.it>

From-SVN: r66822
This commit is contained in:
Richard Frith-Macdonald 2003-05-15 09:34:32 +00:00 committed by Nicola Pero
parent 2b972239e8
commit e083f3f926
2 changed files with 56 additions and 10 deletions

View File

@ -1,3 +1,12 @@
Tue May 13 14:56:03 2003 Richard Frith-Macdonald <rfm@gnu.org>
Nicola Pero <n.pero@mi.flashnet.it>
libobjc/10742
* init.c (class_superclass_of_class): New function.
(create_tree_of_subclasses_inherited_from): Use it.
(__objc_tree_insert_class): Likewise.
(class_is_subclass_of_class): Likewise.
2003-04-11 David Chad <davidc@freebsd.org>
Loren J. Rittle <ljrittle@acm.org>

View File

@ -99,6 +99,50 @@ static struct objc_list *__objc_class_tree_list = NULL;
should not be destroyed during the execution of the program. */
static cache_ptr __objc_load_methods = NULL;
/* This function is used when building the class tree used to send
ordinately the +load message to all classes needing it. The tree
is really needed so that superclasses will get the message before
subclasses.
This tree will contain classes which are being loaded (or have just
being loaded), and whose super_class pointers have not yet been
resolved. This implies that their super_class pointers point to a
string with the name of the superclass; when the first message is
sent to the class (/an object of that class) the class links will
be resolved, which will replace the super_class pointers with
pointers to the actual superclasses.
Unfortunately, the tree might also contain classes which had been
loaded previously, and whose class links have already been
resolved.
This function returns the superclass of a class in both cases, and
can be used to build the determine the class relationships while
building the tree.
*/
static Class class_superclass_of_class (Class class)
{
char *super_class_name;
/* If the class links have been resolved, use the resolved
* links. */
if (CLS_ISRESOLV (class))
return class->super_class;
/* Else, 'class' has not yet been resolved. This means that its
* super_class pointer is really the name of the super class (rather
* than a pointer to the actual superclass). */
super_class_name = (char *)class->super_class;
/* Return Nil for a root class. */
if (super_class_name == NULL)
return Nil;
/* Lookup the superclass of non-root classes. */
return objc_lookup_class (super_class_name);
}
/* Creates a tree of classes whose topmost class is directly inherited
from `upper' and the bottom class in this tree is
`bottom_class'. The classes in this tree are super classes of
@ -127,9 +171,7 @@ create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
tree = objc_calloc (1, sizeof (objc_class_tree));
tree->class = superclass;
tree->subclasses = list_cons (prev, tree->subclasses);
superclass = (superclass->super_class ?
objc_lookup_class ((char *) superclass->super_class)
: Nil);
superclass = class_superclass_of_class (superclass);
prev = tree;
}
@ -157,10 +199,7 @@ __objc_tree_insert_class (objc_class_tree *tree, Class class)
DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
return tree;
}
else if ((class->super_class ?
objc_lookup_class ((char *) class->super_class)
: Nil)
== tree->class)
else if (class_superclass_of_class (class) == tree->class)
{
/* If class is a direct subclass of tree->class then add class to the
list of subclasses. First check to see if it wasn't already
@ -370,9 +409,7 @@ class_is_subclass_of_class (Class class, Class superclass)
{
if (class == superclass)
return YES;
class = (class->super_class ?
objc_lookup_class ((char *) class->super_class)
: Nil);
class = class_superclass_of_class (class);
}
return NO;