aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-21 15:34:19 +0000
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-21 15:34:19 +0000
commitb3e841a5e05be750d56e02ffb8ef7f1f3c26d865 (patch)
tree61fdf00a963f3916ab9cbcba2bb1052b6c017925
parent9f2d83847b13e2585b742b52650c1e54783ce237 (diff)
In libobjc/:
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com> PR libobjc/16110 * init.c (__objc_send_message_in_list): Renamed to __objc_send_load_using_method_list. Do not take an 'op' argument. Register the 'load' selector if needed. (__objc_send_load): Do not register the 'load' selector. Updated call to __objc_send_message_in_list. (__objc_create_classes_tree): Add the class of any claimed category that was loaded in the module to the list of classes for which we try to execute +load. In gcc/testsuite/: 2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com> PR libobjc/16110 * objc.dg/special/special.exp: Added new test. * objc.dg/special/load-category-1.m: New. * objc.dg/special/load-category-1a.m: New. * objc.dg/special/load-category-1.h: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168122 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-1.h20
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-1.m40
-rw-r--r--gcc/testsuite/objc.dg/special/load-category-1a.m22
-rw-r--r--gcc/testsuite/objc.dg/special/special.exp29
-rw-r--r--libobjc/ChangeLog12
-rw-r--r--libobjc/init.c77
7 files changed, 184 insertions, 24 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5f597a97b3f..007baf400b9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR libobjc/16110
+ * objc.dg/special/special.exp: Added new test.
+ * objc.dg/special/load-category-1.m: New.
+ * objc.dg/special/load-category-1a.m: New.
+ * objc.dg/special/load-category-1.h: New.
+
2010-12-21 Steven Bosscher <steven@gcc.gnu.org>
PR middle-end/45310
diff --git a/gcc/testsuite/objc.dg/special/load-category-1.h b/gcc/testsuite/objc.dg/special/load-category-1.h
new file mode 100644
index 00000000000..7810487dfe4
--- /dev/null
+++ b/gcc/testsuite/objc.dg/special/load-category-1.h
@@ -0,0 +1,20 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
+
+/* Test that +load works when a category is defined in a different
+ module than the main class. */
+
+/* This function should be called any time +load is invoked, so we can
+ keep the count. */
+extern int increase_load_count (void);
+
+@interface TestClass1
+{
+ id isa;
+}
+@end
+
+@interface TestClass2
+{
+ id isa;
+}
+@end
diff --git a/gcc/testsuite/objc.dg/special/load-category-1.m b/gcc/testsuite/objc.dg/special/load-category-1.m
new file mode 100644
index 00000000000..bfd6373d2b8
--- /dev/null
+++ b/gcc/testsuite/objc.dg/special/load-category-1.m
@@ -0,0 +1,40 @@
+/* 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 <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+#include "load-category-1.h"
+
+@implementation TestClass1
++ initialize { return self; }
++ load
+{
+ increase_load_count ();
+}
+@end
+
+@implementation TestClass2 (Category)
++ load
+{
+ increase_load_count ();
+}
+@end
+
+
+static int load_count = 0;
+
+int increase_load_count (void)
+{
+ load_count++;
+}
+
+int main (void)
+{
+ if (load_count != 4)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/special/load-category-1a.m b/gcc/testsuite/objc.dg/special/load-category-1a.m
new file mode 100644
index 00000000000..f516e7dfa3d
--- /dev/null
+++ b/gcc/testsuite/objc.dg/special/load-category-1a.m
@@ -0,0 +1,22 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+#include "load-category-1.h"
+
+@implementation TestClass2
++ initialize { return self; }
++ load
+{
+ increase_load_count ();
+}
+@end
+
+@implementation TestClass1 (Category)
++ load
+{
+ increase_load_count ();
+}
+@end
diff --git a/gcc/testsuite/objc.dg/special/special.exp b/gcc/testsuite/objc.dg/special/special.exp
index fdc90ecc6b5..dd443808c05 100644
--- a/gcc/testsuite/objc.dg/special/special.exp
+++ b/gcc/testsuite/objc.dg/special/special.exp
@@ -1,5 +1,5 @@
# GCC Objective-C testsuite that uses the `dg.exp' driver.
-# Copyright (C) 1997, 2001, 2007 Free Software Foundation, Inc.
+# Copyright (C) 1997, 2001, 2007, 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -56,6 +56,33 @@ if ![string match "" $lines] then {
}
}
+#
+# load-category-1 test
+#
+# This test is similar to the one above. We compile load-category-1.m
+# and load-category-1a.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-1a.m" "load-category-1a.o" object $add_flags ]
+if ![string match "" $lines] then {
+ fail "load-category-1a.o"
+} else {
+ dg-runtest "$srcdir/$subdir/load-category-1.m" "load-category-1a.o" "-I${srcdir}/../../libobjc -fgnu-runtime"
+ file delete load-category-1a.o
+}
+
+if [istarget "*-*-darwin*" ] {
+set add_flags ""
+lappend add_flags "additional_flags=-fnext-runtime"
+set lines [objc_target_compile "$srcdir/$subdir/load-category-1a.m" "load-category-1a.o" object $add_flags ]
+if ![string match "" $lines] then {
+ fail "load-category-1a.o"
+} else {
+ dg-runtest "$srcdir/$subdir/load-category-1.m" "load-category-1a.o" "-fnext-runtime"
+ file delete load-category-1a.o
+}
+}
+
# All done.
dg-finish
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index 56bfe2e9afb..3cebc765202 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,5 +1,17 @@
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
+ PR libobjc/16110
+ * init.c (__objc_send_message_in_list): Renamed to
+ __objc_send_load_using_method_list. Do not take an 'op' argument.
+ Register the 'load' selector if needed.
+ (__objc_send_load): Do not register the 'load' selector. Updated
+ call to __objc_send_message_in_list.
+ (__objc_create_classes_tree): Add the class of any claimed
+ category that was loaded in the module to the list of classes for
+ which we try to execute +load.
+
+2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
+
* objc-private/common.h: When DEBUG is defined, include <stdio.h>.
Updated comments.
* init.c (__objc_tree_insert_class): Use %p, not %x, when printing
diff --git a/libobjc/init.c b/libobjc/init.c
index 3c64f5bb7ed..d4d7abb4f46 100644
--- a/libobjc/init.c
+++ b/libobjc/init.c
@@ -44,8 +44,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define OBJC_VERSION 8
#define PROTOCOL_VERSION 2
-/* This list contains all modules currently loaded into the
- runtime. */
+/* This list contains modules currently loaded into the runtime and
+ for which the +load method has not been called yet. */
static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
/* This list contains all proto_list's not yet assigned class
@@ -359,37 +359,49 @@ __objc_tree_print (objc_class_tree *tree, int level)
#endif
/* Walks on a linked list of methods in the reverse order and executes
- all the methods corresponding to `op' selector. Walking in the
- reverse order assures the +load of class is executed first and then
- +load of categories because of the way in which categories are
- added to the class methods. */
+ all the methods corresponding to the `+load' selector. Walking in
+ the reverse order assures the +load of class is executed first and
+ then +load of categories because of the way in which categories are
+ added to the class methods. This function needs to be called with
+ the objc_runtime_mutex locked. */
static void
-__objc_send_message_in_list (struct objc_method_list *method_list, Class class, SEL op)
+__objc_send_load_using_method_list (struct objc_method_list *method_list, Class class)
{
+ static SEL load_selector = 0;
int i;
- if (! method_list)
+ if (!method_list)
return;
- /* First execute the `op' message in the following method lists. */
- __objc_send_message_in_list (method_list->method_next, class, op);
+ /* This needs no lock protection because we are called with the
+ objc_runtime_mutex locked. */
+ if (!load_selector)
+ load_selector = sel_registerName ("load");
+
+ /* method_list is a linked list of method lists; since we're
+ executing in reverse order, we need to do the next list before we
+ do this one. */
+ __objc_send_load_using_method_list (method_list->method_next, class);
/* Search the method list. */
for (i = 0; i < method_list->method_count; i++)
{
struct objc_method *mth = &method_list->method_list[i];
- if (mth->method_name && sel_eq (mth->method_name, op)
+ /* We are searching for +load methods that we haven't executed
+ yet. */
+ if (mth->method_name && sel_eq (mth->method_name, load_selector)
&& ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
{
- /* Add this method into the +load hash table. */
+ /* Add this method into the +load hash table, so we won't
+ execute it again next time. */
objc_hash_add (&__objc_load_methods,
mth->method_imp,
mth->method_imp);
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
- /* The method was found and wasn't previously executed. */
+ /* Call +load. */
(*mth->method_imp) ((id)class, mth->method_name);
break;
@@ -397,18 +409,16 @@ __objc_send_message_in_list (struct objc_method_list *method_list, Class class,
}
}
+/* This function needs to be called with the objc_runtime_mutex
+ locked. */
static void
__objc_send_load (objc_class_tree *tree,
int level __attribute__ ((__unused__)))
{
- static SEL load_sel = 0;
Class class = tree->class;
struct objc_method_list *method_list = class->class_pointer->methods;
- if (! load_sel)
- load_sel = sel_registerName ("load");
-
- __objc_send_message_in_list (method_list, class, load_sel);
+ __objc_send_load_using_method_list (method_list, class);
}
static void
@@ -580,8 +590,8 @@ __objc_exec_class (struct objc_module *module)
previous_constructors = 1;
}
- /* Save the module pointer for later processing. (not currently
- used). */
+ /* Save the module pointer so that later we remember to call +load
+ on all classes and categories on it. */
objc_mutex_lock (__objc_runtime_mutex);
__objc_module_list = list_cons (module, __objc_module_list);
@@ -717,14 +727,16 @@ __objc_exec_class (struct objc_module *module)
objc_mutex_unlock (__objc_runtime_mutex);
}
+/* This function needs to be called with the objc_runtime_mutex
+ locked. */
static void
objc_send_load (void)
{
- if (! __objc_module_list)
+ if (!__objc_module_list)
return;
/* Try to find out if all the classes loaded so far also have their
- superclasses known to the runtime. We suppose that the objects
+ superclasses known to the runtime. We suppose that the objects
that are allocated in the +load method are in general of a class
declared in the same module. */
if (unresolved_classes)
@@ -742,7 +754,7 @@ objc_send_load (void)
/* If we still have classes for whom we don't have yet their
super classes known to the runtime we don't send the +load
- messages. */
+ messages yet. */
if (unresolved_classes)
return;
}
@@ -791,6 +803,25 @@ __objc_create_classes_tree (struct objc_module *module)
objc_tree_insert_class (class);
}
+
+ /* Now iterate over "claimed" categories too (ie, categories that
+ extend a class that has already been loaded by the runtime), and
+ insert them in the classes tree hiearchy too. Otherwise, if you
+ add a category, its +load method would not be called if the class
+ is already loaded in the runtime. It the category is
+ "unclaimed", ie, we haven't loaded the main class yet, postpone
+ sending +load as we want to execute +load from the class before
+ we execute the one from the category. */
+ for (i = 0; i < symtab->cat_def_cnt; ++i)
+ {
+ struct objc_category *category = symtab->defs[i + symtab->cls_def_cnt];
+ Class class = objc_getClass (category->class_name);
+
+ /* If the class for the category exists then append its
+ methods. */
+ if (class)
+ objc_tree_insert_class (class);
+ }
}
static void