Add bugs corresponding to PRs 16243 and 16245
[official-gcc.git] / gcc / objc / class.c
blob23bea1549103c81f9777895b3dd1ec56c34ebc2b
1 /* GNU Objective C Runtime class related functions
2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup and Dennis Glatting.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2, or (at your option) any later version.
11 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 details.
16 You should have received a copy of the GNU General Public License along with
17 GNU CC; see the file COPYING. If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 /* As a special exception, if you link this library with files compiled with
21 GCC to produce an executable, this does not cause the resulting executable
22 to be covered by the GNU General Public License. This exception does not
23 however invalidate any other reasons why the executable file might be
24 covered by the GNU General Public License. */
26 #include "runtime.h" /* the kitchen sink */
27 #include "sarray.h"
29 /* The table of classname->class. Used for objc_lookup_class and friends */
30 static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */
32 /* This is a hook which is called by objc_get_class and
33 objc_lookup_class if the runtime is not able to find the class.
34 This may e.g. try to load in the class using dynamic loading */
35 Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
38 /* True when class links has been resolved */
39 BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
42 /* Initial number of buckets size of class hash table. */
43 #define CLASS_HASH_SIZE 32
45 void __objc_init_class_tables()
47 /* Allocate the class hash table */
49 if(__objc_class_hash)
50 return;
52 objc_mutex_lock(__objc_runtime_mutex);
54 __objc_class_hash
55 = hash_new (CLASS_HASH_SIZE,
56 (hash_func_type) hash_string,
57 (compare_func_type) compare_strings);
59 objc_mutex_unlock(__objc_runtime_mutex);
62 /* This function adds a class to the class hash table, and assigns the
63 class a number, unless it's already known */
64 void
65 __objc_add_class_to_hash(Class class)
67 Class h_class;
69 objc_mutex_lock(__objc_runtime_mutex);
71 /* make sure the table is there */
72 assert(__objc_class_hash);
74 /* make sure it's not a meta class */
75 assert(CLS_ISCLASS(class));
77 /* Check to see if the class is already in the hash table. */
78 h_class = hash_value_for_key (__objc_class_hash, class->name);
79 if (!h_class)
81 /* The class isn't in the hash table. Add the class and assign a class
82 number. */
83 static unsigned int class_number = 1;
85 CLS_SETNUMBER(class, class_number);
86 CLS_SETNUMBER(class->class_pointer, class_number);
88 ++class_number;
89 hash_add (&__objc_class_hash, class->name, class);
92 objc_mutex_unlock(__objc_runtime_mutex);
95 /* Get the class object for the class named NAME. If NAME does not
96 identify a known class, the hook _objc_lookup_class is called. If
97 this fails, nil is returned */
98 Class objc_lookup_class (const char* name)
100 Class class;
102 objc_mutex_lock(__objc_runtime_mutex);
104 /* Make sure the class hash table exists. */
105 assert (__objc_class_hash);
107 class = hash_value_for_key (__objc_class_hash, name);
109 objc_mutex_unlock(__objc_runtime_mutex);
111 if (class)
112 return class;
114 if (_objc_lookup_class)
115 return (*_objc_lookup_class)(name);
116 else
117 return 0;
120 /* Get the class object for the class named NAME. If NAME does not
121 identify a known class, the hook _objc_lookup_class is called. If
122 this fails, an error message is issued and the system aborts */
123 Class
124 objc_get_class (const char *name)
126 Class class;
128 objc_mutex_lock(__objc_runtime_mutex);
130 /* Make sure the class hash table exists. */
131 assert (__objc_class_hash);
133 class = hash_value_for_key (__objc_class_hash, name);
135 objc_mutex_unlock(__objc_runtime_mutex);
137 if (class)
138 return class;
140 if (_objc_lookup_class)
141 class = (*_objc_lookup_class)(name);
143 if(class)
144 return class;
146 objc_error(nil, OBJC_ERR_BAD_CLASS,
147 "objc runtime: cannot find class %s\n", name);
150 MetaClass
151 objc_get_meta_class(const char *name)
153 return objc_get_class(name)->class_pointer;
156 /* This function provides a way to enumerate all the classes in the
157 executable. Pass *ENUM_STATE == NULL to start the enumeration. The
158 function will return 0 when there are no more classes.
159 For example:
160 id class;
161 void *es = NULL;
162 while ((class = objc_next_class(&es)))
163 ... do something with class;
165 Class
166 objc_next_class(void **enum_state)
168 objc_mutex_lock(__objc_runtime_mutex);
170 /* make sure the table is there */
171 assert(__objc_class_hash);
173 *(node_ptr*)enum_state =
174 hash_next(__objc_class_hash, *(node_ptr*)enum_state);
176 objc_mutex_unlock(__objc_runtime_mutex);
178 if (*(node_ptr*)enum_state)
179 return (*(node_ptr*)enum_state)->value;
180 return (Class)0;
183 /* Resolve super/subclass links for all classes. The only thing we
184 can be sure of is that the class_pointer for class objects point
185 to the right meta class objects */
186 void __objc_resolve_class_links()
188 node_ptr node;
189 Class object_class = objc_get_class ("Object");
191 assert(object_class);
193 objc_mutex_lock(__objc_runtime_mutex);
195 /* Assign subclass links */
196 for (node = hash_next (__objc_class_hash, NULL); node;
197 node = hash_next (__objc_class_hash, node))
199 Class class1 = node->value;
201 /* Make sure we have what we think we have. */
202 assert (CLS_ISCLASS(class1));
203 assert (CLS_ISMETA(class1->class_pointer));
205 /* The class_pointer of all meta classes point to Object's meta class. */
206 class1->class_pointer->class_pointer = object_class->class_pointer;
208 if (!(CLS_ISRESOLV(class1)))
210 CLS_SETRESOLV(class1);
211 CLS_SETRESOLV(class1->class_pointer);
213 if(class1->super_class)
215 Class a_super_class
216 = objc_get_class ((char *) class1->super_class);
218 assert (a_super_class);
220 DEBUG_PRINTF ("making class connections for: %s\n",
221 class1->name);
223 /* assign subclass links for superclass */
224 class1->sibling_class = a_super_class->subclass_list;
225 a_super_class->subclass_list = class1;
227 /* Assign subclass links for meta class of superclass */
228 if (a_super_class->class_pointer)
230 class1->class_pointer->sibling_class
231 = a_super_class->class_pointer->subclass_list;
232 a_super_class->class_pointer->subclass_list
233 = class1->class_pointer;
236 else /* a root class, make its meta object */
237 /* be a subclass of Object */
239 class1->class_pointer->sibling_class
240 = object_class->subclass_list;
241 object_class->subclass_list = class1->class_pointer;
246 /* Assign superclass links */
247 for (node = hash_next (__objc_class_hash, NULL); node;
248 node = hash_next (__objc_class_hash, node))
250 Class class1 = node->value;
251 Class sub_class;
252 for (sub_class = class1->subclass_list; sub_class;
253 sub_class = sub_class->sibling_class)
255 sub_class->super_class = class1;
256 if(CLS_ISCLASS(sub_class))
257 sub_class->class_pointer->super_class = class1->class_pointer;
261 objc_mutex_unlock(__objc_runtime_mutex);
266 #define CLASSOF(c) ((c)->class_pointer)
268 Class
269 class_pose_as (Class impostor, Class super_class)
271 node_ptr node;
272 Class class1;
274 if (!CLS_ISRESOLV (impostor))
275 __objc_resolve_class_links ();
277 /* preconditions */
278 assert (impostor);
279 assert (super_class);
280 assert (impostor->super_class == super_class);
281 assert (CLS_ISCLASS (impostor));
282 assert (CLS_ISCLASS (super_class));
283 assert (impostor->instance_size == super_class->instance_size);
286 Class *subclass = &(super_class->subclass_list);
288 /* move subclasses of super_class to impostor */
289 while (*subclass)
291 Class nextSub = (*subclass)->sibling_class;
293 if (*subclass != impostor)
295 Class sub = *subclass;
297 /* classes */
298 sub->sibling_class = impostor->subclass_list;
299 sub->super_class = impostor;
300 impostor->subclass_list = sub;
302 /* It will happen that SUB is not a class object if it is
303 the top of the meta class hierarchy chain. (root
304 meta-class objects inherit their class object) If that is
305 the case... don't mess with the meta-meta class. */
306 if (CLS_ISCLASS (sub))
308 /* meta classes */
309 CLASSOF (sub)->sibling_class =
310 CLASSOF (impostor)->subclass_list;
311 CLASSOF (sub)->super_class = CLASSOF (impostor);
312 CLASSOF (impostor)->subclass_list = CLASSOF (sub);
316 *subclass = nextSub;
319 /* set subclasses of superclass to be impostor only */
320 super_class->subclass_list = impostor;
321 CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
323 /* set impostor to have no sibling classes */
324 impostor->sibling_class = 0;
325 CLASSOF (impostor)->sibling_class = 0;
328 /* check relationship of impostor and super_class is kept. */
329 assert (impostor->super_class == super_class);
330 assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
332 /* This is how to update the lookup table. Regardless of
333 what the keys of the hashtable is, change all values that are
334 superclass into impostor. */
336 objc_mutex_lock(__objc_runtime_mutex);
338 for (node = hash_next (__objc_class_hash, NULL); node;
339 node = hash_next (__objc_class_hash, node))
341 class1 = (Class)node->value;
342 if (class1 == super_class)
344 node->value = impostor; /* change hash table value */
348 objc_mutex_unlock(__objc_runtime_mutex);
350 /* next, we update the dispatch tables... */
351 __objc_update_dispatch_table_for_class (CLASSOF (impostor));
352 __objc_update_dispatch_table_for_class (impostor);
354 return impostor;