mirror of git://gcc.gnu.org/git/gcc.git
In libobjc/: 2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
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. From-SVN: r168122
This commit is contained in:
parent
c8613835dd
commit
c07499dc75
|
@ -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>
|
2010-12-21 Steven Bosscher <steven@gcc.gnu.org>
|
||||||
|
|
||||||
PR middle-end/45310
|
PR middle-end/45310
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
||||||
# GCC Objective-C testsuite that uses the `dg.exp' driver.
|
# 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
|
# 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
|
# 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.
|
# All done.
|
||||||
dg-finish
|
dg-finish
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
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>
|
2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
* objc-private/common.h: When DEBUG is defined, include <stdio.h>.
|
* objc-private/common.h: When DEBUG is defined, include <stdio.h>.
|
||||||
|
|
|
@ -44,8 +44,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
#define OBJC_VERSION 8
|
#define OBJC_VERSION 8
|
||||||
#define PROTOCOL_VERSION 2
|
#define PROTOCOL_VERSION 2
|
||||||
|
|
||||||
/* This list contains all modules currently loaded into the
|
/* This list contains modules currently loaded into the runtime and
|
||||||
runtime. */
|
for which the +load method has not been called yet. */
|
||||||
static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
|
static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* This list contains all proto_list's not yet assigned class
|
/* 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
|
#endif
|
||||||
|
|
||||||
/* Walks on a linked list of methods in the reverse order and executes
|
/* Walks on a linked list of methods in the reverse order and executes
|
||||||
all the methods corresponding to `op' selector. Walking in the
|
all the methods corresponding to the `+load' selector. Walking in
|
||||||
reverse order assures the +load of class is executed first and then
|
the reverse order assures the +load of class is executed first and
|
||||||
+load of categories because of the way in which categories are
|
then +load of categories because of the way in which categories are
|
||||||
added to the class methods. */
|
added to the class methods. This function needs to be called with
|
||||||
|
the objc_runtime_mutex locked. */
|
||||||
static void
|
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;
|
int i;
|
||||||
|
|
||||||
if (! method_list)
|
if (!method_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* First execute the `op' message in the following method lists. */
|
/* This needs no lock protection because we are called with the
|
||||||
__objc_send_message_in_list (method_list->method_next, class, op);
|
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. */
|
/* Search the method list. */
|
||||||
for (i = 0; i < method_list->method_count; i++)
|
for (i = 0; i < method_list->method_count; i++)
|
||||||
{
|
{
|
||||||
struct objc_method *mth = &method_list->method_list[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))
|
&& ! 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,
|
objc_hash_add (&__objc_load_methods,
|
||||||
mth->method_imp,
|
mth->method_imp,
|
||||||
mth->method_imp);
|
mth->method_imp);
|
||||||
|
|
||||||
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
|
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);
|
(*mth->method_imp) ((id)class, mth->method_name);
|
||||||
|
|
||||||
break;
|
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
|
static void
|
||||||
__objc_send_load (objc_class_tree *tree,
|
__objc_send_load (objc_class_tree *tree,
|
||||||
int level __attribute__ ((__unused__)))
|
int level __attribute__ ((__unused__)))
|
||||||
{
|
{
|
||||||
static SEL load_sel = 0;
|
|
||||||
Class class = tree->class;
|
Class class = tree->class;
|
||||||
struct objc_method_list *method_list = class->class_pointer->methods;
|
struct objc_method_list *method_list = class->class_pointer->methods;
|
||||||
|
|
||||||
if (! load_sel)
|
__objc_send_load_using_method_list (method_list, class);
|
||||||
load_sel = sel_registerName ("load");
|
|
||||||
|
|
||||||
__objc_send_message_in_list (method_list, class, load_sel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -580,8 +590,8 @@ __objc_exec_class (struct objc_module *module)
|
||||||
previous_constructors = 1;
|
previous_constructors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the module pointer for later processing. (not currently
|
/* Save the module pointer so that later we remember to call +load
|
||||||
used). */
|
on all classes and categories on it. */
|
||||||
objc_mutex_lock (__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_module_list = list_cons (module, __objc_module_list);
|
__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);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function needs to be called with the objc_runtime_mutex
|
||||||
|
locked. */
|
||||||
static void
|
static void
|
||||||
objc_send_load (void)
|
objc_send_load (void)
|
||||||
{
|
{
|
||||||
if (! __objc_module_list)
|
if (!__objc_module_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Try to find out if all the classes loaded so far also have their
|
/* 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
|
that are allocated in the +load method are in general of a class
|
||||||
declared in the same module. */
|
declared in the same module. */
|
||||||
if (unresolved_classes)
|
if (unresolved_classes)
|
||||||
|
@ -742,7 +754,7 @@ objc_send_load (void)
|
||||||
|
|
||||||
/* If we still have classes for whom we don't have yet their
|
/* 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
|
super classes known to the runtime we don't send the +load
|
||||||
messages. */
|
messages yet. */
|
||||||
if (unresolved_classes)
|
if (unresolved_classes)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -791,6 +803,25 @@ __objc_create_classes_tree (struct objc_module *module)
|
||||||
|
|
||||||
objc_tree_insert_class (class);
|
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
|
static void
|
||||||
|
|
Loading…
Reference in New Issue