In libobjc/: 2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com>
In libobjc/: 2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com> * init.c (create_tree_of_subclasses_inherited_from): Use class_superclass_of_class instead of assuming a class is unresolved when it could be resolved. Tidied up code. (__objc_tree_insert_class): Enhanced DEBUG_PRINTF. (objc_tree_insert_class): Tidied up loop; return immediately upon inserting a class. (__objc_exec_class): Do not set __objc_class_tree_list. In gcc/testsuite/: 2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/special/special.exp: Added load-category-2 and load-category-3 tests. * objc.dg/special/load-category-2.h: New. * objc.dg/special/load-category-2.m: New. * objc.dg/special/load-category-2a.m: New. * objc.dg/special/load-category-3.h: New. * objc.dg/special/load-category-3.m: New. * objc.dg/special/load-category-3a.m: New. From-SVN: r168251
This commit is contained in:
parent
f8a64a9ad3
commit
fa539f5189
|
@ -1,3 +1,14 @@
|
||||||
|
2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
|
* objc.dg/special/special.exp: Added load-category-2 and
|
||||||
|
load-category-3 tests.
|
||||||
|
* objc.dg/special/load-category-2.h: New.
|
||||||
|
* objc.dg/special/load-category-2.m: New.
|
||||||
|
* objc.dg/special/load-category-2a.m: New.
|
||||||
|
* objc.dg/special/load-category-3.h: New.
|
||||||
|
* objc.dg/special/load-category-3.m: New.
|
||||||
|
* objc.dg/special/load-category-3a.m: New.
|
||||||
|
|
||||||
2010-12-25 Ira Rosen <irar@il.ibm.com>
|
2010-12-25 Ira Rosen <irar@il.ibm.com>
|
||||||
|
|
||||||
PR testsuite/47057
|
PR testsuite/47057
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
|
||||||
|
/* Test the order of calling +load between classes and categories. */
|
||||||
|
|
||||||
|
void complete_load_step (int load_step);
|
||||||
|
void check_that_load_step_was_completed (int load_step);
|
||||||
|
void check_that_load_step_was_not_completed (int load_step);
|
||||||
|
|
||||||
|
@interface TestClass1
|
||||||
|
{
|
||||||
|
id isa;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface TestClass2 : TestClass1
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface TestClass3 : TestClass2
|
||||||
|
@end
|
|
@ -0,0 +1,106 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
|
||||||
|
#include "load-category-2.h"
|
||||||
|
|
||||||
|
/* This test tests that +load is called in the correct order for
|
||||||
|
classes and categories. +load needs to be called in superclasses
|
||||||
|
before subclasses, and in the main class before categories. */
|
||||||
|
|
||||||
|
/* Compile the classes in random order to prevent the runtime from
|
||||||
|
sending +load in the correct order just because the classes happen
|
||||||
|
to have been compiled in that order. */
|
||||||
|
@implementation TestClass2
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass2 +load]\n");
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_not_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (4);
|
||||||
|
|
||||||
|
complete_load_step (1);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass3
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass3 +load]\n");
|
||||||
|
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (5);
|
||||||
|
|
||||||
|
complete_load_step (2);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass1
|
||||||
|
+ initialize { return self; }
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass1 +load]\n");
|
||||||
|
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_not_completed (0);
|
||||||
|
check_that_load_step_was_not_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (3);
|
||||||
|
|
||||||
|
complete_load_step (0);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL load_step_completed[6] = { NO, NO, NO, NO, NO, NO };
|
||||||
|
|
||||||
|
void complete_load_step (int load_step)
|
||||||
|
{
|
||||||
|
load_step_completed[load_step] = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_that_load_step_was_completed (int load_step)
|
||||||
|
{
|
||||||
|
if (load_step_completed[load_step] == NO)
|
||||||
|
{
|
||||||
|
printf ("Load step %d was not completed but should have been\n", load_step);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_that_load_step_was_not_completed (int load_step)
|
||||||
|
{
|
||||||
|
if (load_step_completed[load_step] == YES)
|
||||||
|
{
|
||||||
|
printf ("Load step %d was completed but shouldn't have been\n", load_step);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
check_that_load_step_was_completed (2);
|
||||||
|
check_that_load_step_was_completed (3);
|
||||||
|
check_that_load_step_was_completed (4);
|
||||||
|
check_that_load_step_was_completed (5);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
|
||||||
|
#include "load-category-2.h"
|
||||||
|
|
||||||
|
/* Compile the categories in random order to prevent the runtime from
|
||||||
|
sending +load in the correct order just because the classes happen
|
||||||
|
to have been compiled in that order. */
|
||||||
|
@implementation TestClass2 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass2(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
|
||||||
|
complete_load_step (4);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass3 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass3(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (2);
|
||||||
|
|
||||||
|
complete_load_step (5);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass1 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass1(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
|
||||||
|
complete_load_step (3);
|
||||||
|
}
|
||||||
|
@end
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
|
||||||
|
void complete_load_step (int load_step);
|
||||||
|
void check_that_load_step_was_completed (int load_step);
|
||||||
|
void check_that_load_step_was_not_completed (int load_step);
|
||||||
|
|
||||||
|
@interface TestClass1
|
||||||
|
{
|
||||||
|
id isa;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface TestClass2 : TestClass1
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface TestClass3 : TestClass2
|
||||||
|
@end
|
|
@ -0,0 +1,88 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||||
|
|
||||||
|
/* This test is identical to load-category-2, but the classes and
|
||||||
|
categories are created in inverted order in the modules, to test
|
||||||
|
that you can load classes first, or categories first, and it all
|
||||||
|
still works in both cases. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
|
||||||
|
#include "load-category-3.h"
|
||||||
|
|
||||||
|
@implementation TestClass2 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass2(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
|
||||||
|
complete_load_step (4);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass3 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass3(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (2);
|
||||||
|
|
||||||
|
complete_load_step (5);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass1 (Category)
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass1(Category) +load]\n");
|
||||||
|
|
||||||
|
/* Check that the corresponding class's +load was done. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
|
||||||
|
complete_load_step (3);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
static BOOL load_step_completed[6] = { NO, NO, NO, NO, NO, NO };
|
||||||
|
|
||||||
|
void complete_load_step (int load_step)
|
||||||
|
{
|
||||||
|
load_step_completed[load_step] = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_that_load_step_was_completed (int load_step)
|
||||||
|
{
|
||||||
|
if (load_step_completed[load_step] == NO)
|
||||||
|
{
|
||||||
|
printf ("Load step %d was not completed but should have been\n", load_step);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_that_load_step_was_not_completed (int load_step)
|
||||||
|
{
|
||||||
|
if (load_step_completed[load_step] == YES)
|
||||||
|
{
|
||||||
|
printf ("Load step %d was completed but shouldn't have been\n", load_step);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
check_that_load_step_was_completed (2);
|
||||||
|
check_that_load_step_was_completed (3);
|
||||||
|
check_that_load_step_was_completed (4);
|
||||||
|
check_that_load_step_was_completed (5);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
|
||||||
|
|
||||||
|
/* This test is identical to load-category-2, but the classes and
|
||||||
|
categories are created in inverted order in the modules, to test
|
||||||
|
that you can load classes first, or categories first, and it all
|
||||||
|
still works. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
|
||||||
|
#include "load-category-3.h"
|
||||||
|
|
||||||
|
@implementation TestClass2
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass2 +load]\n");
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_not_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (4);
|
||||||
|
|
||||||
|
complete_load_step (1);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass3
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass3 +load]\n");
|
||||||
|
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_completed (0);
|
||||||
|
check_that_load_step_was_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (5);
|
||||||
|
|
||||||
|
complete_load_step (2);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TestClass1
|
||||||
|
+ initialize { return self; }
|
||||||
|
+ load
|
||||||
|
{
|
||||||
|
printf ("[TestClass1 +load]\n");
|
||||||
|
|
||||||
|
/* Check superclasses/subclasses +load order. */
|
||||||
|
check_that_load_step_was_not_completed (0);
|
||||||
|
check_that_load_step_was_not_completed (1);
|
||||||
|
check_that_load_step_was_not_completed (2);
|
||||||
|
|
||||||
|
/* Check that the corresponding category's +load was not done. */
|
||||||
|
check_that_load_step_was_not_completed (3);
|
||||||
|
|
||||||
|
complete_load_step (0);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ if ![info exists DEFAULT_CFLAGS] then {
|
||||||
# Initialize `dg'.
|
# Initialize `dg'.
|
||||||
dg-init
|
dg-init
|
||||||
|
|
||||||
|
# TODO: All these testcases compile and link two Objective-C modules.
|
||||||
|
# Remove code duplication and factor the common code out.
|
||||||
|
|
||||||
#
|
#
|
||||||
# unclaimed-category-1 test
|
# unclaimed-category-1 test
|
||||||
#
|
#
|
||||||
|
@ -83,6 +86,60 @@ if ![string match "" $lines] then {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# load-category-2 test
|
||||||
|
#
|
||||||
|
# This test is similar to the one above. We compile load-category-2.m
|
||||||
|
# and load-category-2a.m, link them together, and execute the result.
|
||||||
|
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
|
||||||
|
lappend add_flags "additional_flags=-fgnu-runtime"
|
||||||
|
set lines [objc_target_compile "$srcdir/$subdir/load-category-2a.m" "load-category-2a.o" object $add_flags ]
|
||||||
|
if ![string match "" $lines] then {
|
||||||
|
fail "load-category-2a.o"
|
||||||
|
} else {
|
||||||
|
dg-runtest "$srcdir/$subdir/load-category-2.m" "load-category-2a.o" "-I${srcdir}/../../libobjc -fgnu-runtime"
|
||||||
|
file delete load-category-2a.o
|
||||||
|
}
|
||||||
|
|
||||||
|
if [istarget "*-*-darwin*" ] {
|
||||||
|
set add_flags ""
|
||||||
|
lappend add_flags "additional_flags=-fnext-runtime"
|
||||||
|
set lines [objc_target_compile "$srcdir/$subdir/load-category-2a.m" "load-category-2a.o" object $add_flags ]
|
||||||
|
if ![string match "" $lines] then {
|
||||||
|
fail "load-category-2a.o"
|
||||||
|
} else {
|
||||||
|
dg-runtest "$srcdir/$subdir/load-category-2.m" "load-category-2a.o" "-fnext-runtime"
|
||||||
|
file delete load-category-2a.o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# load-category-3 test
|
||||||
|
#
|
||||||
|
# This test is similar to the one above. We compile load-category-3.m
|
||||||
|
# and load-category-3a.m, link them together, and execute the result.
|
||||||
|
set add_flags "additional_flags=-I${srcdir}/../../libobjc"
|
||||||
|
lappend add_flags "additional_flags=-fgnu-runtime"
|
||||||
|
set lines [objc_target_compile "$srcdir/$subdir/load-category-3a.m" "load-category-3a.o" object $add_flags ]
|
||||||
|
if ![string match "" $lines] then {
|
||||||
|
fail "load-category-3a.o"
|
||||||
|
} else {
|
||||||
|
dg-runtest "$srcdir/$subdir/load-category-3.m" "load-category-3a.o" "-I${srcdir}/../../libobjc -fgnu-runtime"
|
||||||
|
file delete load-category-3a.o
|
||||||
|
}
|
||||||
|
|
||||||
|
if [istarget "*-*-darwin*" ] {
|
||||||
|
set add_flags ""
|
||||||
|
lappend add_flags "additional_flags=-fnext-runtime"
|
||||||
|
set lines [objc_target_compile "$srcdir/$subdir/load-category-3a.m" "load-category-3a.o" object $add_flags ]
|
||||||
|
if ![string match "" $lines] then {
|
||||||
|
fail "load-category-3a.o"
|
||||||
|
} else {
|
||||||
|
dg-runtest "$srcdir/$subdir/load-category-3.m" "load-category-3a.o" "-fnext-runtime"
|
||||||
|
file delete load-category-3a.o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# All done.
|
# All done.
|
||||||
dg-finish
|
dg-finish
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
|
* init.c (create_tree_of_subclasses_inherited_from): Use
|
||||||
|
class_superclass_of_class instead of assuming a class is
|
||||||
|
unresolved when it could be resolved. Tidied up assignment and
|
||||||
|
check.
|
||||||
|
(__objc_tree_insert_class): Enhanced DEBUG_PRINTF.
|
||||||
|
(objc_tree_insert_class): Tidied up loop; return immediately upon
|
||||||
|
inserting a class.
|
||||||
|
(__objc_exec_class): Do not set __objc_class_tree_list.
|
||||||
|
|
||||||
2010-12-24 Nicola Pero <nicola.pero@meta-innovation.com>
|
2010-12-24 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
* selector.c (sel_getTypedSelector): Return NULL if given a NULL
|
* selector.c (sel_getTypedSelector): Return NULL if given a NULL
|
||||||
|
|
|
@ -109,9 +109,9 @@ BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
|
||||||
static void objc_send_load (void);
|
static void objc_send_load (void);
|
||||||
|
|
||||||
/* Inserts all the classes defined in module in a tree of classes that
|
/* Inserts all the classes defined in module in a tree of classes that
|
||||||
resembles the class hierarchy. This tree is traversed in preorder
|
resembles the class hierarchy. This tree is traversed in preorder
|
||||||
and the classes in its nodes receive the +load message if these
|
and the classes in its nodes receive the +load message if these
|
||||||
methods were not executed before. The algorithm ensures that when
|
methods were not executed before. The algorithm ensures that when
|
||||||
the +load method of a class is executed all the superclasses have
|
the +load method of a class is executed all the superclasses have
|
||||||
been already received the +load message. */
|
been already received the +load message. */
|
||||||
static void __objc_create_classes_tree (struct objc_module *module);
|
static void __objc_create_classes_tree (struct objc_module *module);
|
||||||
|
@ -124,15 +124,22 @@ static void __objc_call_load_callback (struct objc_module *module);
|
||||||
installed in the runtime. */
|
installed in the runtime. */
|
||||||
static BOOL class_is_subclass_of_class (Class class, Class superclass);
|
static BOOL class_is_subclass_of_class (Class class, Class superclass);
|
||||||
|
|
||||||
|
/* This is a node in the class tree hierarchy used to send +load
|
||||||
|
messages. */
|
||||||
typedef struct objc_class_tree
|
typedef struct objc_class_tree
|
||||||
{
|
{
|
||||||
|
/* The class corresponding to the node. */
|
||||||
Class class;
|
Class class;
|
||||||
struct objc_list *subclasses; /* `head' is a pointer to an
|
|
||||||
objc_class_tree. */
|
/* This is a linked list of all the direct subclasses of this class.
|
||||||
|
'head' points to a subclass node; 'tail' points to the next
|
||||||
|
objc_list node (whose 'head' points to another subclass node,
|
||||||
|
etc). */
|
||||||
|
struct objc_list *subclasses;
|
||||||
} objc_class_tree;
|
} objc_class_tree;
|
||||||
|
|
||||||
/* This is a linked list of objc_class_tree trees. The head of these
|
/* This is a linked list of objc_class_tree trees. The head of these
|
||||||
trees are root classes (their super class is Nil). These different
|
trees are root classes (their super class is Nil). These different
|
||||||
trees represent different class hierarchies. */
|
trees represent different class hierarchies. */
|
||||||
static struct objc_list *__objc_class_tree_list = NULL;
|
static struct objc_list *__objc_class_tree_list = NULL;
|
||||||
|
|
||||||
|
@ -145,7 +152,7 @@ static cache_ptr __objc_load_methods = NULL;
|
||||||
is really needed so that superclasses will get the message before
|
is really needed so that superclasses will get the message before
|
||||||
subclasses.
|
subclasses.
|
||||||
|
|
||||||
This tree will contain classes which are being loaded (or have just
|
This tree may contain classes which are being loaded (or have just
|
||||||
being loaded), and whose super_class pointers have not yet been
|
being loaded), and whose super_class pointers have not yet been
|
||||||
resolved. This implies that their super_class pointers point to a
|
resolved. This implies that their super_class pointers point to a
|
||||||
string with the name of the superclass; when the first message is
|
string with the name of the superclass; when the first message is
|
||||||
|
@ -184,29 +191,30 @@ static Class class_superclass_of_class (Class class)
|
||||||
|
|
||||||
|
|
||||||
/* Creates a tree of classes whose topmost class is directly inherited
|
/* Creates a tree of classes whose topmost class is directly inherited
|
||||||
from `upper' and the bottom class in this tree is
|
from `upper' and the bottom class in this tree is `bottom_class'.
|
||||||
`bottom_class'. The classes in this tree are super classes of
|
If `upper' is Nil, creates a class hierarchy up to a root class.
|
||||||
`bottom_class'. `subclasses' member of each tree node point to the
|
The classes in this tree are super classes of `bottom_class'. The
|
||||||
next subclass tree node. */
|
`subclasses' member of each tree node point to the list of
|
||||||
|
subclasses for the node. */
|
||||||
static objc_class_tree *
|
static objc_class_tree *
|
||||||
create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||||
{
|
{
|
||||||
Class superclass;
|
Class superclass;
|
||||||
objc_class_tree *tree, *prev;
|
objc_class_tree *tree, *prev;
|
||||||
|
|
||||||
if (bottom_class->super_class)
|
|
||||||
superclass = objc_getClass ((char *) bottom_class->super_class);
|
|
||||||
else
|
|
||||||
superclass = Nil;
|
|
||||||
|
|
||||||
DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
|
DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
|
||||||
DEBUG_PRINTF (" bottom_class = %s, upper = %s\n",
|
DEBUG_PRINTF (" bottom_class = %s, upper = %s\n",
|
||||||
(bottom_class ? bottom_class->name : NULL),
|
(bottom_class ? bottom_class->name : NULL),
|
||||||
(upper ? upper->name : NULL));
|
(upper ? upper->name : NULL));
|
||||||
|
|
||||||
tree = prev = objc_calloc (1, sizeof (objc_class_tree));
|
superclass = class_superclass_of_class (bottom_class);
|
||||||
|
|
||||||
|
prev = objc_calloc (1, sizeof (objc_class_tree));
|
||||||
prev->class = bottom_class;
|
prev->class = bottom_class;
|
||||||
|
|
||||||
|
if (superclass == upper)
|
||||||
|
return prev;
|
||||||
|
|
||||||
while (superclass != upper)
|
while (superclass != upper)
|
||||||
{
|
{
|
||||||
tree = objc_calloc (1, sizeof (objc_class_tree));
|
tree = objc_calloc (1, sizeof (objc_class_tree));
|
||||||
|
@ -220,16 +228,16 @@ create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert the `class' into the proper place in the `tree' class
|
/* Insert the `class' into the proper place in the `tree' class
|
||||||
hierarchy. This function returns a new tree if the class has been
|
hierarchy. This function returns a new tree if the class has been
|
||||||
successfully inserted into the tree or NULL if the class is not
|
successfully inserted into the tree or NULL if the class is not
|
||||||
part of the classes hierarchy described by `tree'. This function is
|
part of the classes hierarchy described by `tree'. This function
|
||||||
private to objc_tree_insert_class (), you should not call it
|
is private to objc_tree_insert_class (), you should not call it
|
||||||
directly. */
|
directly. */
|
||||||
static objc_class_tree *
|
static objc_class_tree *
|
||||||
__objc_tree_insert_class (objc_class_tree *tree, Class class)
|
__objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
{
|
{
|
||||||
DEBUG_PRINTF ("__objc_tree_insert_class: tree = %p, class = %s\n",
|
DEBUG_PRINTF ("__objc_tree_insert_class: tree = %p (root: %s), class = %s\n",
|
||||||
tree, class->name);
|
tree, ((tree && tree->class) ? tree->class->name : "Nil"), class->name);
|
||||||
|
|
||||||
if (tree == NULL)
|
if (tree == NULL)
|
||||||
return create_tree_of_subclasses_inherited_from (class, NULL);
|
return create_tree_of_subclasses_inherited_from (class, NULL);
|
||||||
|
@ -315,27 +323,26 @@ objc_tree_insert_class (Class class)
|
||||||
{
|
{
|
||||||
struct objc_list *list_node;
|
struct objc_list *list_node;
|
||||||
objc_class_tree *tree;
|
objc_class_tree *tree;
|
||||||
|
|
||||||
list_node = __objc_class_tree_list;
|
list_node = __objc_class_tree_list;
|
||||||
while (list_node)
|
while (list_node)
|
||||||
{
|
{
|
||||||
|
/* Try to insert the class in this class hierarchy. */
|
||||||
tree = __objc_tree_insert_class (list_node->head, class);
|
tree = __objc_tree_insert_class (list_node->head, class);
|
||||||
if (tree)
|
if (tree)
|
||||||
{
|
{
|
||||||
list_node->head = tree;
|
list_node->head = tree;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
list_node = list_node->tail;
|
list_node = list_node->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the list was finished but the class hasn't been inserted,
|
/* If the list was finished but the class hasn't been inserted, we
|
||||||
insert it here. */
|
don't have an existing class hierarchy that can accomodate it.
|
||||||
if (! list_node)
|
Create a new one. */
|
||||||
{
|
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
||||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
__objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
|
||||||
__objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Traverse tree in preorder. Used to send +load. */
|
/* Traverse tree in preorder. Used to send +load. */
|
||||||
|
@ -603,7 +610,6 @@ __objc_exec_class (struct objc_module *module)
|
||||||
duplicate_classes = objc_hash_new (8,
|
duplicate_classes = objc_hash_new (8,
|
||||||
(hash_func_type)objc_hash_ptr,
|
(hash_func_type)objc_hash_ptr,
|
||||||
objc_compare_ptrs);
|
objc_compare_ptrs);
|
||||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
|
||||||
__objc_load_methods = objc_hash_new (128,
|
__objc_load_methods = objc_hash_new (128,
|
||||||
(hash_func_type)objc_hash_ptr,
|
(hash_func_type)objc_hash_ptr,
|
||||||
objc_compare_ptrs);
|
objc_compare_ptrs);
|
||||||
|
|
Loading…
Reference in New Issue