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>
|
||||
|
||||
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.
|
||||
# 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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
* 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 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)
|
||||
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,6 +727,8 @@ __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)
|
||||
{
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue