OSDN Git Service

00dd3dfe95d484282c19531b2d8500a26ce5e43f
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3    2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4    Contributed by Steve Naroff.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Purpose: This module implements the Objective-C 4.0 language.
24
25    compatibility issues (with the Stepstone translator):
26
27    - does not recognize the following 3.3 constructs.
28      @requires, @classes, @messages, = (...)
29    - methods with variable arguments must conform to ANSI standard.
30    - tagged structure definitions that appear in BOTH the interface
31      and implementation are not allowed.
32    - public/private: all instance variables are public within the
33      context of the implementation...I consider this to be a bug in
34      the translator.
35    - statically allocated objects are not supported. the user will
36      receive an error if this service is requested.
37
38    code generation `options':
39
40    */
41
42 #include "config.h"
43 #include "system.h"
44 #include "coretypes.h"
45 #include "tm.h"
46 #include "tree.h"
47 #include "rtl.h"
48 #include "tm_p.h"
49 #include "expr.h"
50
51 #ifdef OBJCPLUS
52 #include "cp-tree.h"
53 #else
54 #include "c-tree.h"
55 #endif
56
57 #include "c-common.h"
58 #include "flags.h"
59 #include "langhooks.h"
60 #include "objc-act.h"
61 #include "input.h"
62 #include "except.h"
63 #include "function.h"
64 #include "output.h"
65 #include "toplev.h"
66 #include "ggc.h"
67 #include "varray.h"
68 #include "debug.h"
69 #include "target.h"
70 #include "diagnostic.h"
71 #include "cgraph.h"
72 #include "tree-iterator.h"
73 #include "libfuncs.h"
74 #include "hashtab.h"
75
76 #define OBJC_VOID_AT_END        void_list_node
77
78 /* When building Objective-C++, we are not linking against the C front-end
79    and so need to replicate the C tree-construction functions in some way.  */
80 #ifdef OBJCPLUS
81 #define OBJCP_REMAP_FUNCTIONS
82 #include "objcp-decl.h"
83 #endif  /* OBJCPLUS */
84
85 /* This is the default way of generating a method name.  */
86 /* I am not sure it is really correct.
87    Perhaps there's a danger that it will make name conflicts
88    if method names contain underscores. -- rms.  */
89 #ifndef OBJC_GEN_METHOD_LABEL
90 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
91   do {                                      \
92     char *temp;                             \
93     sprintf ((BUF), "_%s_%s_%s_%s",         \
94              ((IS_INST) ? "i" : "c"),       \
95              (CLASS_NAME),                  \
96              ((CAT_NAME)? (CAT_NAME) : ""), \
97              (SEL_NAME));                   \
98     for (temp = (BUF); *temp; temp++)       \
99       if (*temp == ':') *temp = '_';        \
100   } while (0)
101 #endif
102
103 /* These need specifying.  */
104 #ifndef OBJC_FORWARDING_STACK_OFFSET
105 #define OBJC_FORWARDING_STACK_OFFSET 0
106 #endif
107
108 #ifndef OBJC_FORWARDING_MIN_OFFSET
109 #define OBJC_FORWARDING_MIN_OFFSET 0
110 #endif
111 \f
112 /* Set up for use of obstacks.  */
113
114 #include "obstack.h"
115
116 /* This obstack is used to accumulate the encoding of a data type.  */
117 static struct obstack util_obstack;
118
119 /* This points to the beginning of obstack contents, so we can free
120    the whole contents.  */
121 char *util_firstobj;
122
123 /* The version identifies which language generation and runtime
124    the module (file) was compiled for, and is recorded in the
125    module descriptor.  */
126
127 #define OBJC_VERSION    (flag_next_runtime ? 5 : 8)
128 #define PROTOCOL_VERSION 2
129
130 /* (Decide if these can ever be validly changed.) */
131 #define OBJC_ENCODE_INLINE_DEFS         0
132 #define OBJC_ENCODE_DONT_INLINE_DEFS    1
133
134 /*** Private Interface (procedures) ***/
135
136 /* Used by compile_file.  */
137
138 static void init_objc (void);
139 static void finish_objc (void);
140
141 /* Code generation.  */
142
143 static void synth_module_prologue (void);
144 static tree objc_build_constructor (tree, tree);
145 static void build_module_descriptor (void);
146 static void build_module_initializer_routine (void);
147 static tree init_module_descriptor (tree);
148 static tree build_objc_method_call (int, tree, tree, tree, tree);
149 static void generate_strings (void);
150 static tree get_proto_encoding (tree);
151 static void build_selector_translation_table (void);
152 static tree lookup_interface (tree);
153 static tree objc_add_static_instance (tree, tree);
154
155 static tree start_class (enum tree_code, tree, tree, tree);
156 static tree continue_class (tree);
157 static void finish_class (tree);
158 static void start_method_def (tree);
159 static void objc_start_function (tree, tree, tree, tree);
160 static tree start_protocol (enum tree_code, tree, tree);
161 static tree build_method_decl (enum tree_code, tree, tree, tree);
162 static tree objc_add_method (tree, tree, int);
163 static tree add_instance_variable (tree, int, tree);
164 static tree build_ivar_reference (tree);
165 static tree is_ivar (tree, tree);
166 static int is_private (tree);
167 static tree get_super_receiver (void);
168
169 static void build_objc_exception_stuff (void);
170 static void build_next_objc_exception_stuff (void);
171
172 static tree build_ivar_template (void);
173 static tree build_method_template (void);
174 static tree build_private_template (tree);
175 static void build_class_template (void);
176 static void build_selector_template (void);
177 static void build_category_template (void);
178 static tree lookup_method_in_hash_lists (tree, int);
179 static void build_super_template (void);
180 static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
181 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
182 static void synth_forward_declarations (void);
183 static int ivar_list_length (tree);
184 static tree get_class_ivars (tree);
185 static void generate_ivar_lists (void);
186 static void generate_dispatch_tables (void);
187 static void generate_shared_structures (void);
188 static tree generate_protocol_list (tree);
189 static void build_protocol_reference (tree);
190
191 static tree build_keyword_selector (tree);
192 static const char *synth_id_with_class_suffix (const char *, tree);
193
194 static void generate_static_references (void);
195 static int check_methods_accessible (tree, tree, int);
196 static void encode_aggregate_within (tree, int, int, int, int);
197 static const char *objc_demangle (const char *);
198
199 /* Hash tables to manage the global pool of method prototypes.  */
200
201 hash *nst_method_hash_list = 0;
202 hash *cls_method_hash_list = 0;
203
204 static size_t hash_func (tree);
205 static void hash_init (void);
206 static void hash_enter (hash *, tree);
207 static hash hash_lookup (hash *, tree);
208 static void hash_add_attr (hash, tree);
209 static tree lookup_method (tree, tree);
210 static tree lookup_method_static (tree, tree, int);
211 static void add_method_to_hash_list (hash *, tree);
212 static tree add_class (tree);
213 static void add_category (tree, tree);
214 static inline tree lookup_category (tree, tree);
215
216 enum string_section
217 {
218   class_names,          /* class, category, protocol, module names */
219   meth_var_names,       /* method and variable names */
220   meth_var_types        /* method and variable type descriptors */
221 };
222
223 static tree add_objc_string (tree, enum string_section);
224 static tree get_objc_string_decl (tree, enum string_section);
225 static tree build_objc_string_decl (enum string_section);
226 static tree build_selector_reference_decl (void);
227 static void build_selector_table_decl (void);
228
229 /* Protocol additions.  */
230
231 static tree add_protocol (tree);
232 static tree lookup_protocol (tree);
233 static void check_protocol_recursively (tree, tree);
234 static tree lookup_and_install_protocols (tree);
235
236 /* Type encoding.  */
237
238 static void encode_type_qualifiers (tree);
239 static void encode_pointer (tree, int, int);
240 static void encode_array (tree, int, int);
241 static void encode_aggregate (tree, int, int);
242 static void encode_next_bitfield (int);
243 static void encode_gnu_bitfield (int, tree, int);
244 static void encode_type (tree, int, int);
245 static void encode_field_decl (tree, int, int);
246
247 static void really_start_method (tree, tree);
248 static int objc_types_are_equivalent (tree, tree);
249 static int comp_proto_with_proto (tree, tree);
250 static tree get_arg_type_list (tree, int, int);
251 static void objc_push_parm (tree);
252 static tree objc_get_parm_info (int);
253 static void synth_self_and_ucmd_args (void);
254
255 /* Utilities for debugging and error diagnostics.  */
256
257 static void warn_with_method (const char *, int, tree);
258 static void error_with_ivar (const char *, tree);
259 static char *gen_type_name (tree);
260 static char *gen_type_name_0 (tree);
261 static char *gen_method_decl (tree);
262 static char *gen_declaration (tree);
263 static void dump_interface (FILE *, tree);
264
265 /* Everything else.  */
266
267 static tree lookup_method_in_protocol_list (tree, tree, int);
268 static tree lookup_protocol_in_reflist (tree, tree);
269 static tree start_var_decl (tree, const char *);
270 static void finish_var_decl (tree, tree);
271 static tree create_field_decl (tree, const char *);
272 static tree setup_string_decl (void);
273 static int check_string_class_template (void);
274 static tree my_build_string (int, const char *);
275 static void build_objc_symtab_template (void);
276 static tree init_def_list (tree);
277 static tree init_objc_symtab (tree);
278 static tree build_metadata_decl (const char *, tree);
279 static void forward_declare_categories (void);
280 static void generate_objc_symtab_decl (void);
281 static tree build_selector (tree);
282 static tree build_typed_selector_reference (tree, tree);
283 static tree build_selector_reference (tree);
284 static tree build_class_reference_decl (void);
285 static void add_class_reference (tree);
286 static void build_protocol_template (void);
287 static tree build_descriptor_table_initializer (tree, tree);
288 static tree build_method_prototype_list_template (tree, int);
289 static tree build_method_prototype_template (void);
290 static tree objc_method_parm_type (tree);
291 static int objc_encoded_type_size (tree);
292 static tree encode_method_prototype (tree);
293 static tree generate_descriptor_table (tree, const char *, int, tree, tree);
294 static void generate_method_descriptors (tree);
295 static void generate_protocol_references (tree);
296 static void generate_protocols (void);
297 static void check_ivars (tree, tree);
298 static tree build_ivar_list_template (tree, int);
299 static tree build_method_list_template (tree, int);
300 static tree build_ivar_list_initializer (tree, tree);
301 static tree generate_ivars_list (tree, const char *, int, tree);
302 static tree build_dispatch_table_initializer (tree, tree);
303 static tree generate_dispatch_table (tree, const char *, int, tree);
304 static tree build_shared_structure_initializer (tree, tree, tree, tree,
305                                                 tree, int, tree, tree, tree);
306 static void generate_category (tree);
307 static tree adjust_type_for_id_default (tree);
308 static tree check_duplicates (hash, int, int);
309 static tree receiver_is_class_object (tree, int, int);
310 static int check_methods (tree, tree, int);
311 static int conforms_to_protocol (tree, tree);
312 static void check_protocol (tree, const char *, const char *);
313 static void check_protocols (tree, const char *, const char *);
314 static void generate_classref_translation_entry (tree);
315 static void handle_class_ref (tree);
316 static void generate_struct_by_value_array (void)
317      ATTRIBUTE_NORETURN;
318 static void mark_referenced_methods (void);
319 static void generate_objc_image_info (void);
320
321 /*** Private Interface (data) ***/
322
323 /* Reserved tag definitions.  */
324
325 #define OBJECT_TYPEDEF_NAME             "id"
326 #define CLASS_TYPEDEF_NAME              "Class"
327
328 #define TAG_OBJECT                      "objc_object"
329 #define TAG_CLASS                       "objc_class"
330 #define TAG_SUPER                       "objc_super"
331 #define TAG_SELECTOR                    "objc_selector"
332
333 #define UTAG_CLASS                      "_objc_class"
334 #define UTAG_IVAR                       "_objc_ivar"
335 #define UTAG_IVAR_LIST                  "_objc_ivar_list"
336 #define UTAG_METHOD                     "_objc_method"
337 #define UTAG_METHOD_LIST                "_objc_method_list"
338 #define UTAG_CATEGORY                   "_objc_category"
339 #define UTAG_MODULE                     "_objc_module"
340 #define UTAG_SYMTAB                     "_objc_symtab"
341 #define UTAG_SUPER                      "_objc_super"
342 #define UTAG_SELECTOR                   "_objc_selector"
343
344 #define UTAG_PROTOCOL                   "_objc_protocol"
345 #define UTAG_METHOD_PROTOTYPE           "_objc_method_prototype"
346 #define UTAG_METHOD_PROTOTYPE_LIST      "_objc__method_prototype_list"
347
348 /* Note that the string object global name is only needed for the
349    NeXT runtime.  */
350 #define STRING_OBJECT_GLOBAL_FORMAT     "_%sClassReference"
351
352 #define PROTOCOL_OBJECT_CLASS_NAME      "Protocol"
353
354 static const char *TAG_GETCLASS;
355 static const char *TAG_GETMETACLASS;
356 static const char *TAG_MSGSEND;
357 static const char *TAG_MSGSENDSUPER;
358 /* The NeXT Objective-C messenger may have two extra entry points, for use
359    when returning a structure. */
360 static const char *TAG_MSGSEND_STRET;
361 static const char *TAG_MSGSENDSUPER_STRET;
362 static const char *default_constant_string_class_name;
363
364 /* Runtime metadata flags.  */
365 #define CLS_FACTORY                     0x0001L
366 #define CLS_META                        0x0002L
367
368 #define OBJC_MODIFIER_STATIC            0x00000001
369 #define OBJC_MODIFIER_FINAL             0x00000002
370 #define OBJC_MODIFIER_PUBLIC            0x00000004
371 #define OBJC_MODIFIER_PRIVATE           0x00000008
372 #define OBJC_MODIFIER_PROTECTED         0x00000010
373 #define OBJC_MODIFIER_NATIVE            0x00000020
374 #define OBJC_MODIFIER_SYNCHRONIZED      0x00000040
375 #define OBJC_MODIFIER_ABSTRACT          0x00000080
376 #define OBJC_MODIFIER_VOLATILE          0x00000100
377 #define OBJC_MODIFIER_TRANSIENT         0x00000200
378 #define OBJC_MODIFIER_NONE_SPECIFIED    0x80000000
379
380 /* NeXT-specific tags.  */
381
382 #define TAG_MSGSEND_NONNIL              "objc_msgSendNonNil"
383 #define TAG_MSGSEND_NONNIL_STRET        "objc_msgSendNonNil_stret"
384 #define TAG_EXCEPTIONEXTRACT            "objc_exception_extract"
385 #define TAG_EXCEPTIONTRYENTER           "objc_exception_try_enter"
386 #define TAG_EXCEPTIONTRYEXIT            "objc_exception_try_exit"
387 #define TAG_EXCEPTIONMATCH              "objc_exception_match"
388 #define TAG_EXCEPTIONTHROW              "objc_exception_throw"
389 #define TAG_SYNCENTER                   "objc_sync_enter"
390 #define TAG_SYNCEXIT                    "objc_sync_exit"
391 #define TAG_SETJMP                      "_setjmp"
392 #define UTAG_EXCDATA                    "_objc_exception_data"
393
394 /* GNU-specific tags.  */
395
396 #define TAG_EXECCLASS                   "__objc_exec_class"
397 #define TAG_GNUINIT                     "__objc_gnu_init"
398
399 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
400 tree objc_global_trees[OCTI_MAX];
401
402 static void handle_impent (struct imp_entry *);
403
404 struct imp_entry *imp_list = 0;
405 int imp_count = 0;      /* `@implementation' */
406 int cat_count = 0;      /* `@category' */
407
408 enum tree_code objc_inherit_code;
409 int objc_public_flag;
410
411 /* Use to generate method labels.  */
412 static int method_slot = 0;
413
414 #define BUFSIZE         1024
415
416 static char *errbuf;    /* Buffer for error diagnostics */
417
418 /* Data imported from tree.c.  */
419
420 extern enum debug_info_type write_symbols;
421
422 /* Data imported from toplev.c.  */
423
424 extern const char *dump_base_name;
425 \f
426 static int flag_typed_selectors;
427
428 /* Store all constructed constant strings in a hash table so that
429    they get uniqued properly.  */
430
431 struct string_descriptor GTY(())
432 {
433   /* The literal argument .  */
434   tree literal;
435
436   /* The resulting constant string.  */
437   tree constructor;
438 };
439
440 static GTY((param_is (struct string_descriptor))) htab_t string_htab;
441
442 static hashval_t string_hash (const void *);
443 static int string_eq (const void *, const void *);
444
445 FILE *gen_declaration_file;
446
447 /* Tells "encode_pointer/encode_aggregate" whether we are generating
448    type descriptors for instance variables (as opposed to methods).
449    Type descriptors for instance variables contain more information
450    than methods (for static typing and embedded structures).  */
451
452 static int generating_instance_variables = 0;
453
454 /* Some platforms pass small structures through registers versus
455    through an invisible pointer.  Determine at what size structure is
456    the transition point between the two possibilities.  */
457
458 static void
459 generate_struct_by_value_array (void)
460 {
461   tree type;
462   tree field_decl, field_decl_chain;
463   int i, j;
464   int aggregate_in_mem[32];
465   int found = 0;
466
467   /* Presumably no platform passes 32 byte structures in a register.  */
468   for (i = 1; i < 32; i++)
469     {
470       char buffer[5];
471
472       /* Create an unnamed struct that has `i' character components */
473       type = start_struct (RECORD_TYPE, NULL_TREE);
474
475       strcpy (buffer, "c1");
476       field_decl = create_field_decl (char_type_node,
477                                       buffer);
478       field_decl_chain = field_decl;
479
480       for (j = 1; j < i; j++)
481         {
482           sprintf (buffer, "c%d", j + 1);
483           field_decl = create_field_decl (char_type_node,
484                                           buffer);
485           chainon (field_decl_chain, field_decl);
486         }
487       finish_struct (type, field_decl_chain, NULL_TREE);
488
489       aggregate_in_mem[i] = aggregate_value_p (type, 0);
490       if (!aggregate_in_mem[i])
491         found = 1;
492     }
493
494   /* We found some structures that are returned in registers instead of memory
495      so output the necessary data.  */
496   if (found)
497     {
498       for (i = 31; i >= 0;  i--)
499         if (!aggregate_in_mem[i])
500           break;
501       printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
502
503       /* The first member of the structure is always 0 because we don't handle
504          structures with 0 members */
505       printf ("static int struct_forward_array[] = {\n  0");
506
507       for (j = 1; j <= i; j++)
508         printf (", %d", aggregate_in_mem[j]);
509       printf ("\n};\n");
510     }
511
512   exit (0);
513 }
514
515 bool
516 objc_init (void)
517 {
518 #ifdef OBJCPLUS
519   if (cxx_init () == false)
520 #else
521   if (c_objc_common_init () == false)
522 #endif
523     return false;
524
525   /* Force the line number back to 0; check_newline will have
526      raised it to 1, which will make the builtin functions appear
527      not to be built in.  */
528   input_line = 0;
529
530   /* If gen_declaration desired, open the output file.  */
531   if (flag_gen_declaration)
532     {
533       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
534       gen_declaration_file = fopen (dumpname, "w");
535       if (gen_declaration_file == 0)
536         fatal_error ("can't open %s: %m", dumpname);
537       free (dumpname);
538     }
539
540   if (flag_next_runtime)
541     {
542       TAG_GETCLASS = "objc_getClass";
543       TAG_GETMETACLASS = "objc_getMetaClass";
544       TAG_MSGSEND = "objc_msgSend";
545       TAG_MSGSENDSUPER = "objc_msgSendSuper";
546       TAG_MSGSEND_STRET = "objc_msgSend_stret";
547       TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
548       default_constant_string_class_name = "NSConstantString";
549     }
550   else
551     {
552       TAG_GETCLASS = "objc_get_class";
553       TAG_GETMETACLASS = "objc_get_meta_class";
554       TAG_MSGSEND = "objc_msg_lookup";
555       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
556       /* GNU runtime does not provide special functions to support
557          structure-returning methods.  */
558       default_constant_string_class_name = "NXConstantString";
559       flag_typed_selectors = 1;
560     }
561
562   init_objc ();
563
564   if (print_struct_values)
565     generate_struct_by_value_array ();
566
567   return true;
568 }
569
570 void
571 objc_finish_file (void)
572 {
573   mark_referenced_methods ();
574
575 #ifdef OBJCPLUS
576   /* We need to instantiate templates _before_ we emit ObjC metadata;
577      if we do not, some metadata (such as selectors) may go missing.  */
578   instantiate_pending_templates (0);
579 #endif
580
581   /* Finalize Objective-C runtime data.  No need to generate tables
582      and code if only checking syntax.  */
583   if (!flag_syntax_only)
584     finish_objc ();
585
586   if (gen_declaration_file)
587     fclose (gen_declaration_file);
588
589 #ifdef OBJCPLUS
590   cp_finish_file ();
591 #endif
592 }
593 \f
594 /* Return the first occurrence of a method declaration corresponding
595    to sel_name in rproto_list.  Search rproto_list recursively.
596    If is_class is 0, search for instance methods, otherwise for class
597    methods.  */
598 static tree
599 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
600                                 int is_class)
601 {
602    tree rproto, p;
603    tree fnd = 0;
604
605    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
606      {
607         p = TREE_VALUE (rproto);
608
609         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
610           {
611             if ((fnd = lookup_method (is_class
612                                       ? PROTOCOL_CLS_METHODS (p)
613                                       : PROTOCOL_NST_METHODS (p), sel_name)))
614               ;
615             else if (PROTOCOL_LIST (p))
616               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
617                                                     sel_name, is_class);
618           }
619         else
620           {
621             ; /* An identifier...if we could not find a protocol.  */
622           }
623
624         if (fnd)
625           return fnd;
626      }
627
628    return 0;
629 }
630
631 static tree
632 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
633 {
634   tree rproto, p;
635
636   /* Make sure the protocol is supported by the object on the rhs.  */
637   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
638     {
639       tree fnd = 0;
640       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
641         {
642           p = TREE_VALUE (rproto);
643
644           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
645             {
646               if (lproto == p)
647                 fnd = lproto;
648
649               else if (PROTOCOL_LIST (p))
650                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
651             }
652
653           if (fnd)
654             return fnd;
655         }
656     }
657   else
658     {
659       ; /* An identifier...if we could not find a protocol.  */
660     }
661
662   return 0;
663 }
664
665 void
666 objc_start_class_interface (tree class, tree super_class, tree protos)
667 {
668   objc_interface_context
669     = objc_ivar_context
670     = start_class (CLASS_INTERFACE_TYPE, class, super_class, protos);
671   objc_public_flag = 0;
672 }
673
674 void
675 objc_start_category_interface (tree class, tree categ, tree protos)
676 {
677   objc_interface_context
678     = start_class (CATEGORY_INTERFACE_TYPE, class, categ, protos);
679   objc_ivar_chain
680     = continue_class (objc_interface_context);
681 }
682
683 void
684 objc_start_protocol (tree name, tree protos)
685 {
686   objc_interface_context
687     = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
688 }
689
690 void
691 objc_continue_interface (void)
692 {
693   objc_ivar_chain
694     = continue_class (objc_interface_context);
695 }
696
697 void
698 objc_finish_interface (void)
699 {
700   finish_class (objc_interface_context);
701   objc_interface_context = NULL_TREE;
702 }
703
704 void
705 objc_start_class_implementation (tree class, tree super_class)
706 {
707   objc_implementation_context
708     = objc_ivar_context
709     = start_class (CLASS_IMPLEMENTATION_TYPE, class, super_class, NULL_TREE);
710   objc_public_flag = 0;
711 }
712
713 void
714 objc_start_category_implementation (tree class, tree categ)
715 {
716   objc_implementation_context
717     = start_class (CATEGORY_IMPLEMENTATION_TYPE, class, categ, NULL_TREE);
718   objc_ivar_chain
719     = continue_class (objc_implementation_context);
720 }
721
722 void
723 objc_continue_implementation (void)
724 {
725   objc_ivar_chain
726     = continue_class (objc_implementation_context);
727 }
728
729 void
730 objc_finish_implementation (void)
731 {
732   if (objc_implementation_context)
733     {
734       finish_class (objc_implementation_context);
735       objc_ivar_chain = NULL_TREE;
736       objc_implementation_context = NULL_TREE;
737     }
738   else
739     warning ("`@end' must appear in an @implementation context");
740 }
741
742 void
743 objc_set_visibility (int visibility)
744 {
745   objc_public_flag = visibility;
746 }
747
748 void
749 objc_set_method_type (enum tree_code type)
750 {
751   objc_inherit_code = (type == PLUS_EXPR
752                        ? CLASS_METHOD_DECL
753                        : INSTANCE_METHOD_DECL);
754 }
755
756 tree
757 objc_build_method_signature (tree rettype, tree selector, tree optparms)
758 {
759   return build_method_decl (objc_inherit_code, rettype, selector, optparms);
760 }
761
762 void
763 objc_add_method_declaration (tree decl)
764 {
765   if (!objc_interface_context)
766     fatal_error ("method declaration not in @interface context");
767
768   objc_add_method (objc_interface_context,
769                    decl,
770                    objc_inherit_code == CLASS_METHOD_DECL);
771 }
772
773 void
774 objc_start_method_definition (tree decl)
775 {
776   if (!objc_implementation_context)
777     fatal_error ("method definition not in @implementation context");
778
779   objc_add_method (objc_implementation_context,
780                    decl,
781                    objc_inherit_code == CLASS_METHOD_DECL);
782   start_method_def (decl);
783 }
784
785 void
786 objc_add_instance_variable (tree decl)
787 {
788   (void) add_instance_variable (objc_ivar_context,
789                                 objc_public_flag,
790                                 decl);
791 }
792
793 /* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
794    an '@'.  */
795
796 int
797 objc_is_reserved_word (tree ident)
798 {
799   unsigned char code = C_RID_CODE (ident);
800
801   return (OBJC_IS_AT_KEYWORD (code)
802 #ifdef OBJCPLUS
803           || code == RID_CLASS || code == RID_PUBLIC
804           || code == RID_PROTECTED || code == RID_PRIVATE
805           || code == RID_TRY || code == RID_THROW || code == RID_CATCH
806 #endif
807             );
808 }
809
810 /* Return true if TYPE is 'id'.  */
811
812 static bool
813 objc_is_object_id (tree type)
814 {
815   return OBJC_TYPE_NAME (type) == objc_object_id;
816 }
817
818 static bool
819 objc_is_class_id (tree type)
820 {
821   return OBJC_TYPE_NAME (type) == objc_class_id;
822 }
823
824 /* Return 1 if LHS and RHS are compatible types for assignment or
825    various other operations.  Return 0 if they are incompatible, and
826    return -1 if we choose to not decide (because the types are really
827    just C types, not ObjC specific ones).  When the operation is
828    REFLEXIVE (typically comparisons), check for compatibility in
829    either direction; when it's not (typically assignments), don't.
830
831    This function is called in two cases: when both lhs and rhs are
832    pointers to records (in which case we check protocols too), and
833    when both lhs and rhs are records (in which case we check class
834    inheritance only).
835
836    Warnings about classes/protocols not implementing a protocol are
837    emitted here (multiple of those warnings might be emitted for a
838    single line!); generic warnings about incompatible assignments and
839    lacks of casts in comparisons are/must be emitted by the caller if
840    we return 0.
841 */
842
843 int
844 objc_comptypes (tree lhs, tree rhs, int reflexive)
845 {
846   /* New clause for protocols.  */
847
848   /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE.  We only
849      manage the ObjC ones, and leave the rest to the C code.  */
850   if (TREE_CODE (lhs) == POINTER_TYPE
851       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
852       && TREE_CODE (rhs) == POINTER_TYPE
853       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
854     {
855       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
856       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
857
858       if (lhs_is_proto)
859         {
860           tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
861           tree rproto, rproto_list;
862           tree p;
863
864           /* <Protocol> = <Protocol>  */
865           if (rhs_is_proto)
866             {
867               rproto_list = TYPE_PROTOCOL_LIST (rhs);
868
869               if (!reflexive)
870                 {
871                   /* An assignment between objects of type 'id
872                      <Protocol>'; make sure the protocol on the lhs is
873                      supported by the object on the rhs.  */
874                   for (lproto = lproto_list; lproto;
875                        lproto = TREE_CHAIN (lproto))
876                     {
877                       p = TREE_VALUE (lproto);
878                       rproto = lookup_protocol_in_reflist (rproto_list, p);
879
880                       if (!rproto)
881                         warning
882                           ("object does not conform to the `%s' protocol",
883                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
884                     }
885                   return 1;
886                 }
887               else
888                 {
889                   /* Obscure case - a comparison between two objects
890                      of type 'id <Protocol>'.  Check that either the
891                      protocol on the lhs is supported by the object on
892                      the rhs, or viceversa.  */
893
894                   /* Check if the protocol on the lhs is supported by the
895                      object on the rhs.  */
896                   for (lproto = lproto_list; lproto;
897                        lproto = TREE_CHAIN (lproto))
898                     {
899                       p = TREE_VALUE (lproto);
900                       rproto = lookup_protocol_in_reflist (rproto_list, p);
901
902                       if (!rproto)
903                         {
904                           /* Check failed - check if the protocol on the rhs
905                              is supported by the object on the lhs.  */
906                           for (rproto = rproto_list; rproto;
907                                rproto = TREE_CHAIN (rproto))
908                             {
909                               p = TREE_VALUE (rproto);
910                               lproto = lookup_protocol_in_reflist (lproto_list,
911                                                                    p);
912
913                               if (!lproto)
914                                 {
915                                   /* This check failed too: incompatible  */
916                                   return 0;
917                                 }
918                             }
919                           return 1;
920                         }
921                     }
922                   return 1;
923                 }
924             }
925           /* <Protocol> = <class> *  */
926           else if (TYPED_OBJECT (TREE_TYPE (rhs)))
927             {
928               tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
929               tree rinter;
930
931               /* Make sure the protocol is supported by the object on
932                  the rhs.  */
933               for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
934                 {
935                   p = TREE_VALUE (lproto);
936                   rproto = 0;
937                   rinter = lookup_interface (rname);
938
939                   while (rinter && !rproto)
940                     {
941                       tree cat;
942
943                       rproto_list = CLASS_PROTOCOL_LIST (rinter);
944                       rproto = lookup_protocol_in_reflist (rproto_list, p);
945                       /* If the underlying ObjC class does not have
946                          the protocol we're looking for, check for "one-off"
947                          protocols (e.g., `NSObject<MyProt> *foo;') attached
948                          to the rhs.  */
949                       if (!rproto)
950                         {
951                           rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
952                           rproto = lookup_protocol_in_reflist (rproto_list, p);
953                         }
954
955                       /* Check for protocols adopted by categories.  */
956                       cat = CLASS_CATEGORY_LIST (rinter);
957                       while (cat && !rproto)
958                         {
959                           rproto_list = CLASS_PROTOCOL_LIST (cat);
960                           rproto = lookup_protocol_in_reflist (rproto_list, p);
961                           cat = CLASS_CATEGORY_LIST (cat);
962                         }
963
964                       rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
965                     }
966
967                   if (!rproto)
968                     warning ("class `%s' does not implement the `%s' protocol",
969                              IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
970                              IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
971                 }
972               return 1;
973             }
974           /* <Protocol> = id */
975           else if (objc_is_object_id (TREE_TYPE (rhs)))
976             {
977               return 1;
978             }
979           /* <Protocol> = Class */
980           else if (objc_is_class_id (TREE_TYPE (rhs)))
981             {
982               return 0;
983             }
984           /* <Protocol> = ?? : let comptypes decide.  */
985           return -1;
986         }
987       else if (rhs_is_proto)
988         {
989           /* <class> * = <Protocol> */
990           if (TYPED_OBJECT (TREE_TYPE (lhs)))
991             {
992               if (reflexive)
993                 {
994                   tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
995                   tree rinter;
996                   tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
997
998                   /* Make sure the protocol is supported by the object on
999                      the lhs.  */
1000                   for (rproto = rproto_list; rproto;
1001                        rproto = TREE_CHAIN (rproto))
1002                     {
1003                       tree p = TREE_VALUE (rproto);
1004                       tree lproto = 0;
1005                       rinter = lookup_interface (rname);
1006
1007                       while (rinter && !lproto)
1008                         {
1009                           tree cat;
1010
1011                           tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
1012                           lproto = lookup_protocol_in_reflist (lproto_list, p);
1013                           /* If the underlying ObjC class does not
1014                              have the protocol we're looking for,
1015                              check for "one-off" protocols (e.g.,
1016                              `NSObject<MyProt> *foo;') attached to the
1017                              lhs.  */
1018                           if (!lproto)
1019                             {
1020                               lproto_list = TYPE_PROTOCOL_LIST
1021                                 (TREE_TYPE (lhs));
1022                               lproto = lookup_protocol_in_reflist
1023                                 (lproto_list, p);
1024                             }
1025
1026                           /* Check for protocols adopted by categories.  */
1027                           cat = CLASS_CATEGORY_LIST (rinter);
1028                           while (cat && !lproto)
1029                             {
1030                               lproto_list = CLASS_PROTOCOL_LIST (cat);
1031                               lproto = lookup_protocol_in_reflist (lproto_list,
1032                                                                    p);
1033                               cat = CLASS_CATEGORY_LIST (cat);
1034                             }
1035                         
1036                           rinter = lookup_interface (CLASS_SUPER_NAME
1037                                                      (rinter));
1038                         }
1039                 
1040                       if (!lproto)
1041                         warning ("class `%s' does not implement the `%s' protocol",
1042                                  IDENTIFIER_POINTER (OBJC_TYPE_NAME
1043                                                      (TREE_TYPE (lhs))),
1044                                  IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1045                     }
1046                   return 1;
1047                 }
1048               else
1049                 return 0;
1050             }
1051           /* id = <Protocol> */
1052           else if (objc_is_object_id (TREE_TYPE (lhs)))
1053             {
1054               return 1;
1055             }
1056           /* Class = <Protocol> */
1057           else if (objc_is_class_id (TREE_TYPE (lhs)))
1058             {
1059               return 0;
1060             }
1061           /* ??? = <Protocol> : let comptypes decide */
1062           else
1063             {
1064               return -1;
1065             }
1066         }
1067       else
1068         {
1069           /* Attention: we shouldn't defer to comptypes here.  One bad
1070              side effect would be that we might loose the REFLEXIVE
1071              information.
1072           */
1073           lhs = TREE_TYPE (lhs);
1074           rhs = TREE_TYPE (rhs);
1075         }
1076     }
1077
1078   if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
1079     {
1080       /* Nothing to do with ObjC - let immediately comptypes take
1081          responsibility for checking.  */
1082       return -1;
1083     }
1084
1085   /* `id' = `<class> *' `<class> *' = `id': always allow it.
1086      Please note that
1087      'Object *o = [[Object alloc] init]; falls
1088      in the case <class> * = `id'.
1089   */
1090   if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
1091       || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
1092     return 1;
1093
1094   /* `id' = `Class', `Class' = `id' */
1095
1096   else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
1097            || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
1098     return 1;
1099
1100   /* `Class' != `<class> *' && `<class> *' != `Class'!  */
1101   else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
1102            || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
1103     return 0;
1104
1105   /* `<class> *' = `<class> *' */
1106
1107   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
1108     {
1109       tree lname = OBJC_TYPE_NAME (lhs);
1110       tree rname = OBJC_TYPE_NAME (rhs);
1111       tree inter;
1112
1113       if (lname == rname)
1114         return 1;
1115
1116       /* If the left hand side is a super class of the right hand side,
1117          allow it.  */
1118       for (inter = lookup_interface (rname); inter;
1119            inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1120         if (lname == CLASS_SUPER_NAME (inter))
1121           return 1;
1122
1123       /* Allow the reverse when reflexive.  */
1124       if (reflexive)
1125         for (inter = lookup_interface (lname); inter;
1126              inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1127           if (rname == CLASS_SUPER_NAME (inter))
1128             return 1;
1129
1130       return 0;
1131     }
1132   else
1133     /* Not an ObjC type - let comptypes do the check.  */
1134     return -1;
1135 }
1136
1137 /* Called from finish_decl.  */
1138
1139 void
1140 objc_check_decl (tree decl)
1141 {
1142   tree type = TREE_TYPE (decl);
1143
1144   if (TREE_CODE (type) != RECORD_TYPE)
1145     return;
1146   if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
1147     error ("statically allocated instance of Objective-C class `%s'",
1148            IDENTIFIER_POINTER (type));
1149 }
1150
1151 /* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
1152    either name an Objective-C class, or refer to the special 'id' or 'Class'
1153    types.  If INTERFACE is not a valid ObjC type, just return it unchanged.  */
1154
1155 tree
1156 objc_get_protocol_qualified_type (tree interface, tree protocols)
1157 {
1158   tree type;
1159
1160   if (!interface)
1161     type = objc_object_type;
1162   else if (!(type = objc_is_id (interface)))
1163     {
1164       type = objc_is_class_name (interface);
1165
1166       if (type)
1167         type = xref_tag (RECORD_TYPE, type);
1168       else
1169         return interface;
1170     }
1171
1172   if (protocols)
1173     {
1174       type = build_variant_type_copy (type);
1175       /* Look up protocols and install in lang specific list.  Note
1176          that the protocol list can have a different lifetime than T!  */
1177       SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
1178
1179       /* Establish the ObjC-ness of this record.  */
1180       if (TREE_CODE (type) == RECORD_TYPE)
1181         TREE_STATIC_TEMPLATE (type) = 1;
1182     }
1183
1184   return type;
1185 }
1186
1187 /* Check for circular dependencies in protocols.  The arguments are
1188    PROTO, the protocol to check, and LIST, a list of protocol it
1189    conforms to.  */
1190
1191 static void
1192 check_protocol_recursively (tree proto, tree list)
1193 {
1194   tree p;
1195
1196   for (p = list; p; p = TREE_CHAIN (p))
1197     {
1198       tree pp = TREE_VALUE (p);
1199
1200       if (TREE_CODE (pp) == IDENTIFIER_NODE)
1201         pp = lookup_protocol (pp);
1202
1203       if (pp == proto)
1204         fatal_error ("protocol `%s' has circular dependency",
1205                      IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1206       if (pp)
1207         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1208     }
1209 }
1210
1211 /* Look up PROTOCOLS, and return a list of those that are found.
1212    If none are found, return NULL.  */
1213
1214 static tree
1215 lookup_and_install_protocols (tree protocols)
1216 {
1217   tree proto;
1218   tree return_value = NULL_TREE;
1219
1220   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1221     {
1222       tree ident = TREE_VALUE (proto);
1223       tree p = lookup_protocol (ident);
1224
1225       if (!p)
1226         error ("cannot find protocol declaration for `%s'",
1227                IDENTIFIER_POINTER (ident));
1228       else
1229         return_value = chainon (return_value,
1230                                 build_tree_list (NULL_TREE, p));
1231     }
1232
1233   return return_value;
1234 }
1235
1236 /* Create a declaration for field NAME of a given TYPE.  */
1237
1238 static tree
1239 create_field_decl (tree type, const char *name)
1240 {
1241   return build_decl (FIELD_DECL, get_identifier (name), type);
1242 }
1243
1244 /* Create a global, static declaration for variable NAME of a given TYPE.  The
1245    finish_var_decl() routine will need to be called on it afterwards.  */
1246
1247 static tree
1248 start_var_decl (tree type, const char *name)
1249 {
1250   tree var = build_decl (VAR_DECL, get_identifier (name), type);
1251
1252   TREE_STATIC (var) = 1;
1253   DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
1254   DECL_IGNORED_P (var) = 1;
1255   DECL_ARTIFICIAL (var) = 1;
1256   DECL_CONTEXT (var) = NULL_TREE;
1257 #ifdef OBJCPLUS
1258   DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
1259 #endif
1260
1261   return var;
1262 }
1263
1264 /* Finish off the variable declaration created by start_var_decl().  */
1265
1266 static void
1267 finish_var_decl (tree var, tree initializer)
1268 {
1269   finish_decl (var, initializer, NULL_TREE);
1270   /* Ensure that the variable actually gets output.  */
1271   mark_decl_referenced (var);
1272   /* Mark the decl to avoid "defined but not used" warning.  */
1273   TREE_USED (var) = 1;
1274 }
1275
1276 /* Find the decl for the constant string class refernce.  This is only
1277    used for the NeXT runtime.  */
1278
1279 static tree
1280 setup_string_decl (void)
1281 {
1282   char *name;
1283   size_t length;
1284
1285   /* %s in format will provide room for terminating null */
1286   length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1287            + strlen (constant_string_class_name);
1288   name = xmalloc (length);
1289   sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1290            constant_string_class_name);
1291   constant_string_global_id = get_identifier (name);
1292   string_class_decl = lookup_name (constant_string_global_id);
1293
1294   return string_class_decl;
1295 }
1296
1297 /* Purpose: "play" parser, creating/installing representations
1298    of the declarations that are required by Objective-C.
1299
1300    Model:
1301
1302         type_spec--------->sc_spec
1303         (tree_list)        (tree_list)
1304             |                  |
1305             |                  |
1306         identifier_node    identifier_node  */
1307
1308 static void
1309 synth_module_prologue (void)
1310 {
1311   tree type;
1312   enum debug_info_type save_write_symbols = write_symbols;
1313   const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1314
1315   /* Suppress outputting debug symbols, because
1316      dbxout_init hasn'r been called yet.  */
1317   write_symbols = NO_DEBUG;
1318   debug_hooks = &do_nothing_debug_hooks;
1319
1320 #ifdef OBJCPLUS
1321   push_lang_context (lang_name_c); /* extern "C" */
1322 #endif
1323
1324   /* The following are also defined in <objc/objc.h> and friends.  */
1325
1326   objc_object_id = get_identifier (TAG_OBJECT);
1327   objc_class_id = get_identifier (TAG_CLASS);
1328
1329   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1330   objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
1331   
1332   objc_object_type = build_pointer_type (objc_object_reference);
1333   objc_class_type = build_pointer_type (objc_class_reference);
1334
1335   objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
1336   objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
1337
1338   /* Declare the 'id' and 'Class' typedefs.  */
1339
1340   type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1341                                                 objc_object_name,
1342                                                 objc_object_type));
1343   DECL_IN_SYSTEM_HEADER (type) = 1;
1344   type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1345                                                 objc_class_name,
1346                                                 objc_class_type));
1347   DECL_IN_SYSTEM_HEADER (type) = 1;
1348
1349   /* Forward-declare '@interface Protocol'.  */
1350
1351   type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1352   objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
1353   objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1354                                 type));
1355
1356   /* Declare type of selector-objects that represent an operation name.  */
1357
1358   if (flag_next_runtime)
1359     /* `struct objc_selector *' */
1360     objc_selector_type
1361       = build_pointer_type (xref_tag (RECORD_TYPE,
1362                                       get_identifier (TAG_SELECTOR)));
1363   else
1364     /* `const struct objc_selector *' */
1365     objc_selector_type
1366       = build_pointer_type
1367         (build_qualified_type (xref_tag (RECORD_TYPE,
1368                                          get_identifier (TAG_SELECTOR)),
1369                                TYPE_QUAL_CONST));
1370
1371   /* Declare receiver type used for dispatching messages to 'super'.  */
1372
1373   /* `struct objc_super *' */
1374   objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1375                                                   get_identifier (TAG_SUPER)));
1376
1377   if (flag_next_runtime)
1378     {
1379       /* NB: In order to call one of the ..._stret (struct-returning)
1380       functions, the function *MUST* first be cast to a signature that
1381       corresponds to the actual ObjC method being invoked.  This is
1382       what is done by the build_objc_method_call() routine below.  */
1383
1384       /* id objc_msgSend (id, SEL, ...); */
1385       /* id objc_msgSendNonNil (id, SEL, ...); */
1386       /* id objc_msgSend_stret (id, SEL, ...); */
1387       /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1388       type
1389         = build_function_type (objc_object_type,
1390                                tree_cons (NULL_TREE, objc_object_type,
1391                                           tree_cons (NULL_TREE, objc_selector_type,
1392                                                      NULL_TREE)));
1393       umsg_decl = builtin_function (TAG_MSGSEND,
1394                                     type, 0, NOT_BUILT_IN,
1395                                     NULL, NULL_TREE);
1396       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1397                                            type, 0, NOT_BUILT_IN,
1398                                            NULL, NULL_TREE);
1399       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1400                                           type, 0, NOT_BUILT_IN,
1401                                           NULL, NULL_TREE);
1402       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1403                                                  type, 0, NOT_BUILT_IN,
1404                                                  NULL, NULL_TREE);
1405
1406       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1407       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1408       type
1409         = build_function_type (objc_object_type,
1410                                tree_cons (NULL_TREE, objc_super_type,
1411                                           tree_cons (NULL_TREE, objc_selector_type,
1412                                                      NULL_TREE)));
1413       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1414                                           type, 0, NOT_BUILT_IN,
1415                                           NULL, NULL_TREE);
1416       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1417                                                 type, 0, NOT_BUILT_IN, 0,
1418                                                 NULL_TREE);
1419     }
1420   else
1421     {
1422       /* GNU runtime messenger entry points.  */
1423
1424       /* typedef id (*IMP)(id, SEL, ...); */
1425       tree IMP_type
1426         = build_pointer_type
1427           (build_function_type (objc_object_type,      
1428                                 tree_cons (NULL_TREE, objc_object_type,      
1429                                            tree_cons (NULL_TREE, objc_selector_type,      
1430                                                       NULL_TREE))));      
1431
1432       /* IMP objc_msg_lookup (id, SEL); */
1433       type
1434         = build_function_type (IMP_type,
1435                                tree_cons (NULL_TREE, objc_object_type,
1436                                           tree_cons (NULL_TREE, objc_selector_type,
1437                                                      OBJC_VOID_AT_END)));
1438       umsg_decl = builtin_function (TAG_MSGSEND,
1439                                     type, 0, NOT_BUILT_IN,
1440                                     NULL, NULL_TREE);
1441
1442       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1443       type
1444         = build_function_type (IMP_type,
1445                                tree_cons (NULL_TREE, objc_super_type,
1446                                           tree_cons (NULL_TREE, objc_selector_type,
1447                                                      OBJC_VOID_AT_END)));
1448       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1449                                           type, 0, NOT_BUILT_IN,
1450                                           NULL, NULL_TREE);
1451
1452       /* The following GNU runtime entry point is called to initialize
1453          each module:
1454
1455          __objc_exec_class (void *); */
1456       type
1457         = build_function_type (void_type_node,
1458                                tree_cons (NULL_TREE, ptr_type_node,
1459                                           OBJC_VOID_AT_END));
1460       execclass_decl = builtin_function (TAG_EXECCLASS,
1461                                          type, 0, NOT_BUILT_IN,
1462                                          NULL, NULL_TREE);
1463     }
1464
1465   /* id objc_getClass (const char *); */
1466
1467   type = build_function_type (objc_object_type,
1468                                    tree_cons (NULL_TREE,
1469                                               const_string_type_node,
1470                                               OBJC_VOID_AT_END));
1471
1472   objc_get_class_decl
1473     = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
1474                         NULL, NULL_TREE);
1475
1476   /* id objc_getMetaClass (const char *); */
1477
1478   objc_get_meta_class_decl
1479     = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1480
1481   build_class_template ();
1482   build_super_template ();
1483   build_protocol_template ();
1484   build_category_template ();
1485   build_objc_exception_stuff ();
1486
1487   if (flag_next_runtime)
1488     build_next_objc_exception_stuff ();
1489
1490   /* static SEL _OBJC_SELECTOR_TABLE[]; */
1491
1492   if (! flag_next_runtime)
1493     build_selector_table_decl ();
1494
1495   /* Forward declare constant_string_id and constant_string_type.  */
1496   if (!constant_string_class_name)
1497     constant_string_class_name = default_constant_string_class_name;
1498
1499   constant_string_id = get_identifier (constant_string_class_name);
1500   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1501
1502   /* Pre-build the following entities - for speed/convenience.  */
1503   self_id = get_identifier ("self");
1504   ucmd_id = get_identifier ("_cmd");
1505 #ifndef OBJCPLUS
1506   /* The C++ front-end does not appear to grok __attribute__((__unused__)).  */
1507   unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1508 #endif    
1509
1510 #ifdef OBJCPLUS
1511   pop_lang_context ();
1512 #endif
1513
1514   write_symbols = save_write_symbols;
1515   debug_hooks = save_hooks;
1516 }
1517
1518 /* Ensure that the ivar list for NSConstantString/NXConstantString
1519    (or whatever was specified via `-fconstant-string-class')
1520    contains fields at least as large as the following three, so that
1521    the runtime can stomp on them with confidence:
1522
1523    struct STRING_OBJECT_CLASS_NAME
1524    {
1525      Object isa;
1526      char *cString;
1527      unsigned int length;
1528    }; */
1529
1530 static int
1531 check_string_class_template (void)
1532 {
1533   tree field_decl = TYPE_FIELDS (constant_string_type);
1534
1535 #define AT_LEAST_AS_LARGE_AS(F, T) \
1536   (F && TREE_CODE (F) == FIELD_DECL \
1537      && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1538          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1539
1540   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1541     return 0;
1542
1543   field_decl = TREE_CHAIN (field_decl);
1544   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1545     return 0;
1546
1547   field_decl = TREE_CHAIN (field_decl);
1548   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1549
1550 #undef AT_LEAST_AS_LARGE_AS
1551 }
1552
1553 /* Avoid calling `check_string_class_template ()' more than once.  */
1554 static GTY(()) int string_layout_checked;
1555
1556 /* Custom build_string which sets TREE_TYPE!  */
1557
1558 static tree
1559 my_build_string (int len, const char *str)
1560 {
1561   return fix_string_type (build_string (len, str));
1562 }
1563
1564
1565 static hashval_t
1566 string_hash (const void *ptr)
1567 {
1568   tree str = ((struct string_descriptor *)ptr)->literal;
1569   const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
1570   int i, len = TREE_STRING_LENGTH (str);
1571   hashval_t h = len;
1572
1573   for (i = 0; i < len; i++)
1574     h = ((h * 613) + p[i]);
1575
1576   return h;
1577 }
1578
1579 static int
1580 string_eq (const void *ptr1, const void *ptr2)
1581 {
1582   tree str1 = ((struct string_descriptor *)ptr1)->literal;
1583   tree str2 = ((struct string_descriptor *)ptr2)->literal;
1584   int len1 = TREE_STRING_LENGTH (str1);
1585
1586   return (len1 == TREE_STRING_LENGTH (str2)
1587           && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
1588                       len1));
1589 }
1590
1591 /* Given a chain of STRING_CST's, build a static instance of
1592    NXConstantString which points at the concatenation of those
1593    strings.  We place the string object in the __string_objects
1594    section of the __OBJC segment.  The Objective-C runtime will
1595    initialize the isa pointers of the string objects to point at the
1596    NXConstantString class object.  */
1597
1598 tree
1599 objc_build_string_object (tree string)
1600 {
1601   tree initlist, constructor, constant_string_class;
1602   int length;
1603   tree fields, addr;
1604   struct string_descriptor *desc, key;
1605   void **loc;
1606
1607   /* Prep the string argument.  */
1608   string = fix_string_type (string);
1609   TREE_SET_CODE (string, STRING_CST);
1610   length = TREE_STRING_LENGTH (string) - 1;
1611
1612   /* Check whether the string class being used actually exists and has the
1613      correct ivar layout.  */
1614   if (!string_layout_checked)
1615     {
1616       string_layout_checked = -1;
1617       constant_string_class = lookup_interface (constant_string_id);
1618
1619       if (!constant_string_class
1620           || !(constant_string_type
1621                = CLASS_STATIC_TEMPLATE (constant_string_class)))
1622         error ("cannot find interface declaration for `%s'",
1623                IDENTIFIER_POINTER (constant_string_id));
1624       /* The NSConstantString/NXConstantString ivar layout is now known.  */
1625       else if (!check_string_class_template ())
1626         error ("interface `%s' does not have valid constant string layout",
1627                IDENTIFIER_POINTER (constant_string_id));
1628       /* For the NeXT runtime, we can generate a literal reference
1629          to the string class, don't need to run a constructor.  */
1630       else if (flag_next_runtime && !setup_string_decl ())
1631         error ("cannot find reference tag for class `%s'",
1632                IDENTIFIER_POINTER (constant_string_id));
1633       else
1634         {
1635           string_layout_checked = 1;  /* Success!  */
1636           add_class_reference (constant_string_id);
1637         }
1638     }
1639
1640   if (string_layout_checked == -1)
1641     return error_mark_node;
1642
1643   /* Perhaps we already constructed a constant string just like this one? */
1644   key.literal = string;
1645   loc = htab_find_slot (string_htab, &key, INSERT);
1646   desc = *loc;
1647
1648   if (!desc)
1649     {
1650       *loc = desc = ggc_alloc (sizeof (*desc));
1651       desc->literal = string;
1652
1653       /* GNU:    & ((NXConstantString) { NULL, string, length })  */
1654       /* NeXT:   & ((NSConstantString) { isa, string, length })   */
1655       fields = TYPE_FIELDS (constant_string_type);
1656       initlist
1657         = build_tree_list (fields,
1658                            flag_next_runtime
1659                            ? build_unary_op (ADDR_EXPR, string_class_decl, 0)
1660                            : build_int_cst (NULL_TREE, 0));
1661       fields = TREE_CHAIN (fields);
1662       initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1),
1663                             initlist);
1664       fields = TREE_CHAIN (fields);
1665       initlist = tree_cons (fields, build_int_cst (NULL_TREE, length),
1666                             initlist);
1667       constructor = objc_build_constructor (constant_string_type,
1668                                             nreverse (initlist));
1669       TREE_INVARIANT (constructor) = true;
1670
1671       if (!flag_next_runtime)
1672         constructor
1673           = objc_add_static_instance (constructor, constant_string_type);
1674
1675       desc->constructor = constructor;
1676     }
1677
1678   addr = build_unary_op (ADDR_EXPR, desc->constructor, 1);
1679   TREE_CONSTANT (addr) = true;
1680   TREE_INVARIANT (addr) = true;
1681   TREE_STATIC (addr) = true;
1682
1683   return addr;
1684 }
1685
1686 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1687
1688 static GTY(()) int num_static_inst;
1689
1690 static tree
1691 objc_add_static_instance (tree constructor, tree class_decl)
1692 {
1693   tree *chain, decl;
1694   char buf[256];
1695
1696   /* Find the list of static instances for the CLASS_DECL.  Create one if
1697      not found.  */
1698   for (chain = &objc_static_instances;
1699        *chain && TREE_VALUE (*chain) != class_decl;
1700        chain = &TREE_CHAIN (*chain));
1701   if (!*chain)
1702     {
1703       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1704       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1705     }
1706
1707   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1708   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1709   DECL_COMMON (decl) = 1;
1710   TREE_STATIC (decl) = 1;
1711   DECL_ARTIFICIAL (decl) = 1;
1712   DECL_INITIAL (decl) = constructor;
1713
1714   /* We may be writing something else just now.
1715      Postpone till end of input.  */
1716   DECL_DEFER_OUTPUT (decl) = 1;
1717   pushdecl_top_level (decl);
1718   rest_of_decl_compilation (decl, 1, 0);
1719
1720   /* Add the DECL to the head of this CLASS' list.  */
1721   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1722
1723   return decl;
1724 }
1725
1726 /* Build a static constant CONSTRUCTOR
1727    with type TYPE and elements ELTS.  */
1728
1729 static tree
1730 objc_build_constructor (tree type, tree elts)
1731 {
1732   tree constructor = build_constructor (type, elts);
1733
1734   TREE_CONSTANT (constructor) = 1;
1735   TREE_STATIC (constructor) = 1;
1736   TREE_READONLY (constructor) = 1;
1737
1738 #ifdef OBJCPLUS
1739   /* Adjust for impedance mismatch.  We should figure out how to build
1740      CONSTRUCTORs that consistently please both the C and C++ gods.  */
1741   if (!TREE_PURPOSE (elts))
1742     TREE_TYPE (constructor) = NULL_TREE;
1743   TREE_HAS_CONSTRUCTOR (constructor) = 1;
1744 #endif
1745
1746   return constructor;
1747 }
1748 \f
1749 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1750
1751 /* Predefine the following data type:
1752
1753    struct _objc_symtab
1754    {
1755      long sel_ref_cnt;
1756      SEL *refs;
1757      short cls_def_cnt;
1758      short cat_def_cnt;
1759      void *defs[cls_def_cnt + cat_def_cnt];
1760    }; */
1761
1762 static void
1763 build_objc_symtab_template (void)
1764 {
1765   tree field_decl, field_decl_chain;
1766
1767   objc_symtab_template
1768     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1769
1770   /* long sel_ref_cnt; */
1771   field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt");
1772   field_decl_chain = field_decl;
1773
1774   /* SEL *refs; */
1775   field_decl = create_field_decl (build_pointer_type (objc_selector_type),
1776                                   "refs");
1777   chainon (field_decl_chain, field_decl);
1778
1779   /* short cls_def_cnt; */
1780   field_decl = create_field_decl (short_integer_type_node, "cls_def_cnt");
1781   chainon (field_decl_chain, field_decl);
1782
1783   /* short cat_def_cnt; */
1784   field_decl = create_field_decl (short_integer_type_node,
1785                                   "cat_def_cnt");
1786   chainon (field_decl_chain, field_decl);
1787
1788   if (imp_count || cat_count || !flag_next_runtime)
1789     {
1790       /* void *defs[imp_count + cat_count (+ 1)]; */
1791       /* NB: The index is one less than the size of the array.  */
1792       int index = imp_count + cat_count
1793                 + (flag_next_runtime? -1: 0);
1794       field_decl = create_field_decl
1795                    (build_array_type
1796                     (ptr_type_node,
1797                      build_index_type (build_int_cst (NULL_TREE, index))),
1798                     "defs");
1799       chainon (field_decl_chain, field_decl);
1800     }
1801
1802   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1803 }
1804
1805 /* Create the initial value for the `defs' field of _objc_symtab.
1806    This is a CONSTRUCTOR.  */
1807
1808 static tree
1809 init_def_list (tree type)
1810 {
1811   tree expr, initlist = NULL_TREE;
1812   struct imp_entry *impent;
1813
1814   if (imp_count)
1815     for (impent = imp_list; impent; impent = impent->next)
1816       {
1817         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1818           {
1819             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1820             initlist = tree_cons (NULL_TREE, expr, initlist);
1821           }
1822       }
1823
1824   if (cat_count)
1825     for (impent = imp_list; impent; impent = impent->next)
1826       {
1827         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1828           {
1829             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1830             initlist = tree_cons (NULL_TREE, expr, initlist);
1831           }
1832       }
1833
1834   if (!flag_next_runtime)
1835     {
1836       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1837       tree expr;
1838
1839       if (static_instances_decl)
1840         expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1841       else
1842         expr = build_int_cst (NULL_TREE, 0);
1843
1844       initlist = tree_cons (NULL_TREE, expr, initlist);
1845     }
1846
1847   return objc_build_constructor (type, nreverse (initlist));
1848 }
1849
1850 /* Construct the initial value for all of _objc_symtab.  */
1851
1852 static tree
1853 init_objc_symtab (tree type)
1854 {
1855   tree initlist;
1856
1857   /* sel_ref_cnt = { ..., 5, ... } */
1858
1859   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
1860
1861   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1862
1863   if (flag_next_runtime || ! sel_ref_chain)
1864     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
1865   else
1866     initlist
1867       = tree_cons (NULL_TREE,
1868                    convert (build_pointer_type (objc_selector_type),
1869                             build_unary_op (ADDR_EXPR,
1870                                             UOBJC_SELECTOR_TABLE_decl, 1)),
1871                    initlist);
1872
1873   /* cls_def_cnt = { ..., 5, ... } */
1874
1875   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
1876
1877   /* cat_def_cnt = { ..., 5, ... } */
1878
1879   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
1880
1881   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1882
1883   if (imp_count || cat_count || !flag_next_runtime)
1884     {
1885
1886       tree field = TYPE_FIELDS (type);
1887       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1888
1889       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1890                             initlist);
1891     }
1892
1893   return objc_build_constructor (type, nreverse (initlist));
1894 }
1895
1896 /* Generate forward declarations for metadata such as
1897   'OBJC_CLASS_...'.  */
1898
1899 static tree
1900 build_metadata_decl (const char *name, tree type)
1901 {
1902   tree decl;
1903
1904   /* struct TYPE NAME_<name>; */
1905   decl = start_var_decl (type, synth_id_with_class_suffix
1906                                (name,
1907                                 objc_implementation_context));
1908
1909   return decl;
1910 }
1911
1912 /* Push forward-declarations of all the categories so that
1913    init_def_list can use them in a CONSTRUCTOR.  */
1914
1915 static void
1916 forward_declare_categories (void)
1917 {
1918   struct imp_entry *impent;
1919   tree sav = objc_implementation_context;
1920
1921   for (impent = imp_list; impent; impent = impent->next)
1922     {
1923       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1924         {
1925           /* Set an invisible arg to synth_id_with_class_suffix.  */
1926           objc_implementation_context = impent->imp_context;
1927           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1928           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1929                                                     objc_category_template);
1930         }
1931     }
1932   objc_implementation_context = sav;
1933 }
1934
1935 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1936    and initialized appropriately.  */
1937
1938 static void
1939 generate_objc_symtab_decl (void)
1940 {
1941   /* forward declare categories */
1942   if (cat_count)
1943     forward_declare_categories ();
1944
1945   build_objc_symtab_template ();
1946   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
1947   finish_var_decl (UOBJC_SYMBOLS_decl,
1948                    init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
1949 }
1950 \f
1951 static tree
1952 init_module_descriptor (tree type)
1953 {
1954   tree initlist, expr;
1955
1956   /* version = { 1, ... } */
1957
1958   expr = build_int_cst (NULL_TREE, OBJC_VERSION);
1959   initlist = build_tree_list (NULL_TREE, expr);
1960
1961   /* size = { ..., sizeof (struct _objc_module), ... } */
1962
1963   expr = size_in_bytes (objc_module_template);
1964   initlist = tree_cons (NULL_TREE, expr, initlist);
1965
1966   /* name = { ..., "foo.m", ... } */
1967
1968   expr = add_objc_string (get_identifier (input_filename), class_names);
1969   initlist = tree_cons (NULL_TREE, expr, initlist);
1970
1971   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1972
1973   if (UOBJC_SYMBOLS_decl)
1974     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1975   else
1976     expr = build_int_cst (NULL_TREE, 0);
1977   initlist = tree_cons (NULL_TREE, expr, initlist);
1978
1979   return objc_build_constructor (type, nreverse (initlist));
1980 }
1981
1982 /* Write out the data structures to describe Objective C classes defined.
1983
1984    struct _objc_module { ... } _OBJC_MODULE = { ... };   */
1985
1986 static void
1987 build_module_descriptor (void)
1988 {
1989   tree field_decl, field_decl_chain;
1990
1991 #ifdef OBJCPLUS
1992   push_lang_context (lang_name_c); /* extern "C" */
1993 #endif
1994
1995   objc_module_template
1996     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1997
1998   /* long version; */
1999   field_decl = create_field_decl (long_integer_type_node, "version");
2000   field_decl_chain = field_decl;
2001
2002   /* long size; */
2003   field_decl = create_field_decl (long_integer_type_node, "size");
2004   chainon (field_decl_chain, field_decl);
2005
2006   /* char *name; */
2007   field_decl = create_field_decl (string_type_node, "name");
2008   chainon (field_decl_chain, field_decl);
2009
2010   /* struct _objc_symtab *symtab; */
2011   field_decl
2012     = create_field_decl (build_pointer_type
2013                          (xref_tag (RECORD_TYPE,
2014                                     get_identifier (UTAG_SYMTAB))),
2015                          "symtab");
2016   chainon (field_decl_chain, field_decl);
2017
2018   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
2019
2020   /* Create an instance of "_objc_module".  */
2021   UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
2022   finish_var_decl (UOBJC_MODULES_decl,
2023                    init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
2024
2025 #ifdef OBJCPLUS
2026   pop_lang_context ();
2027 #endif
2028 }
2029
2030 /* The GNU runtime requires us to provide a static initializer function
2031    for each module:
2032
2033    static void __objc_gnu_init (void) {
2034      __objc_exec_class (&L_OBJC_MODULES);
2035    }  */ 
2036
2037 static void
2038 build_module_initializer_routine (void)
2039 {
2040   tree body;
2041
2042 #ifdef OBJCPLUS
2043   push_lang_context (lang_name_c); /* extern "C" */
2044 #endif                                     
2045
2046   objc_push_parm (build_decl (PARM_DECL, NULL_TREE, void_type_node));
2047   objc_start_function (get_identifier (TAG_GNUINIT),
2048                        build_function_type (void_type_node,
2049                                             OBJC_VOID_AT_END),
2050                        NULL_TREE, objc_get_parm_info (0));
2051
2052   body = c_begin_compound_stmt (true);
2053   add_stmt (build_function_call
2054             (execclass_decl,
2055              build_tree_list
2056              (NULL_TREE,
2057               build_unary_op (ADDR_EXPR,
2058                               UOBJC_MODULES_decl, 0))));
2059   add_stmt (c_end_compound_stmt (body, true));
2060
2061   TREE_PUBLIC (current_function_decl) = 0;
2062
2063 #ifndef OBJCPLUS
2064   /* For Objective-C++, we will need to call __objc_gnu_init
2065      from objc_generate_static_init_call() below.  */
2066   DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
2067 #endif
2068
2069   GNU_INIT_decl = current_function_decl;
2070   finish_function ();
2071
2072 #ifdef OBJCPLUS
2073     pop_lang_context ();
2074 #endif
2075 }
2076
2077 #ifdef OBJCPLUS
2078 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
2079    to be called by the module initializer routine.  */
2080
2081 int
2082 objc_static_init_needed_p (void)
2083 {
2084   return (GNU_INIT_decl != NULL_TREE);
2085 }
2086
2087 /* Generate a call to the __objc_gnu_init initializer function.  */
2088
2089 tree
2090 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
2091 {
2092   add_stmt (build_stmt (EXPR_STMT,
2093                         build_function_call (GNU_INIT_decl, NULL_TREE)));
2094
2095   return ctors;
2096 }
2097 #endif /* OBJCPLUS */
2098
2099 /* Return the DECL of the string IDENT in the SECTION.  */
2100
2101 static tree
2102 get_objc_string_decl (tree ident, enum string_section section)
2103 {
2104   tree chain;
2105
2106   if (section == class_names)
2107     chain = class_names_chain;
2108   else if (section == meth_var_names)
2109     chain = meth_var_names_chain;
2110   else if (section == meth_var_types)
2111     chain = meth_var_types_chain;
2112   else
2113     abort ();
2114
2115   for (; chain != 0; chain = TREE_CHAIN (chain))
2116     if (TREE_VALUE (chain) == ident)
2117       return (TREE_PURPOSE (chain));
2118
2119   abort ();
2120   return NULL_TREE;
2121 }
2122
2123 /* Output references to all statically allocated objects.  Return the DECL
2124    for the array built.  */
2125
2126 static void
2127 generate_static_references (void)
2128 {
2129   tree decls = NULL_TREE, expr = NULL_TREE;
2130   tree class_name, class, decl, initlist;
2131   tree cl_chain, in_chain, type
2132     = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
2133   int num_inst, num_class;
2134   char buf[256];
2135
2136   if (flag_next_runtime)
2137     abort ();
2138
2139   for (cl_chain = objc_static_instances, num_class = 0;
2140        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
2141     {
2142       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
2143            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
2144
2145       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
2146       decl = start_var_decl (type, buf);
2147
2148       /* Output {class_name, ...}.  */
2149       class = TREE_VALUE (cl_chain);
2150       class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
2151       initlist = build_tree_list (NULL_TREE,
2152                                   build_unary_op (ADDR_EXPR, class_name, 1));
2153
2154       /* Output {..., instance, ...}.  */
2155       for (in_chain = TREE_PURPOSE (cl_chain);
2156            in_chain; in_chain = TREE_CHAIN (in_chain))
2157         {
2158           expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2159           initlist = tree_cons (NULL_TREE, expr, initlist);
2160         }
2161
2162       /* Output {..., NULL}.  */
2163       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2164
2165       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2166       finish_var_decl (decl, expr);
2167       decls
2168         = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2169     }
2170
2171   decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
2172   expr = objc_build_constructor (type, nreverse (decls));
2173   static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
2174   finish_var_decl (static_instances_decl, expr);
2175 }
2176
2177 /* Output all strings.  */
2178
2179 static void
2180 generate_strings (void)
2181 {
2182   tree chain, string_expr;
2183   tree string, decl, type;
2184
2185   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2186     {
2187       string = TREE_VALUE (chain);
2188       decl = TREE_PURPOSE (chain);
2189       type = build_array_type
2190              (char_type_node,
2191               build_index_type
2192               (build_int_cst (NULL_TREE, 
2193                               IDENTIFIER_LENGTH (string))));
2194       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2195       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2196                                      IDENTIFIER_POINTER (string));
2197       finish_var_decl (decl, string_expr);
2198     }
2199
2200   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2201     {
2202       string = TREE_VALUE (chain);
2203       decl = TREE_PURPOSE (chain);
2204       type = build_array_type
2205              (char_type_node,
2206               build_index_type
2207               (build_int_cst (NULL_TREE,
2208                               IDENTIFIER_LENGTH (string))));
2209       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2210       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2211                                      IDENTIFIER_POINTER (string));
2212       finish_var_decl (decl, string_expr);
2213     }
2214
2215   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2216     {
2217       string = TREE_VALUE (chain);
2218       decl = TREE_PURPOSE (chain);
2219       type = build_array_type
2220              (char_type_node,
2221               build_index_type
2222               (build_int_cst (NULL_TREE,
2223                               IDENTIFIER_LENGTH (string))));
2224       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2225       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2226                                      IDENTIFIER_POINTER (string));
2227       finish_var_decl (decl, string_expr);
2228     }
2229 }
2230
2231 static GTY(()) int selector_reference_idx;
2232
2233 static tree
2234 build_selector_reference_decl (void)
2235 {
2236   tree decl;
2237   char buf[256];
2238
2239   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2240   decl = start_var_decl (objc_selector_type, buf);
2241
2242   return decl;
2243 }
2244
2245 static void
2246 build_selector_table_decl (void)
2247 {
2248   tree temp;
2249
2250   if (flag_typed_selectors)
2251     {
2252       build_selector_template ();
2253       temp = build_array_type (objc_selector_template, NULL_TREE);
2254     }
2255   else
2256     temp = build_array_type (objc_selector_type, NULL_TREE);
2257
2258   UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
2259 }
2260
2261 /* Just a handy wrapper for add_objc_string.  */
2262
2263 static tree
2264 build_selector (tree ident)
2265 {
2266   return convert (objc_selector_type,
2267                   add_objc_string (ident, meth_var_names));
2268 }
2269
2270 static void
2271 build_selector_translation_table (void)
2272 {
2273   tree chain, initlist = NULL_TREE;
2274   int offset = 0;
2275   tree decl = NULL_TREE;
2276
2277   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2278     {
2279       tree expr;
2280
2281       if (warn_selector && objc_implementation_context)
2282       {
2283         tree method_chain;
2284         bool found = false;
2285         for (method_chain = meth_var_names_chain;
2286              method_chain;
2287              method_chain = TREE_CHAIN (method_chain))
2288           {
2289             if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2290               {
2291                 found = true;
2292                 break;
2293               }
2294           }
2295         if (!found)
2296           {
2297             /* Adjust line number for warning message.  */
2298             int save_lineno = input_line;
2299             if (flag_next_runtime && TREE_PURPOSE (chain))
2300               input_line = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
2301             warning ("creating selector for non existant method %s",
2302                      IDENTIFIER_POINTER (TREE_VALUE (chain)));
2303             input_line = save_lineno;
2304           }
2305       }
2306
2307       expr = build_selector (TREE_VALUE (chain));
2308       /* add one for the '\0' character */
2309       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2310
2311       if (flag_next_runtime)
2312         {
2313           decl = TREE_PURPOSE (chain);
2314           finish_var_decl (decl, expr);
2315         }
2316       else
2317         {
2318           if (flag_typed_selectors)
2319             {
2320               tree eltlist = NULL_TREE;
2321               tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2322               eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2323               eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2324               expr = objc_build_constructor (objc_selector_template,
2325                                              nreverse (eltlist));
2326             }
2327
2328           initlist = tree_cons (NULL_TREE, expr, initlist);
2329         }
2330     }
2331
2332   if (! flag_next_runtime)
2333     {
2334       /* Cause the selector table (previously forward-declared)
2335          to be actually output.  */
2336       initlist = tree_cons (NULL_TREE,
2337                             flag_typed_selectors
2338                             ? objc_build_constructor
2339                               (objc_selector_template,
2340                                tree_cons (NULL_TREE,
2341                                           build_int_cst (NULL_TREE, 0),
2342                                           tree_cons (NULL_TREE,
2343                                                      build_int_cst (NULL_TREE, 0), 
2344                                                      NULL_TREE)))
2345                             : build_int_cst (NULL_TREE, 0), initlist);
2346       initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2347                                          nreverse (initlist));
2348       finish_var_decl (UOBJC_SELECTOR_TABLE_decl, initlist);
2349     }
2350 }
2351
2352 static tree
2353 get_proto_encoding (tree proto)
2354 {
2355   tree encoding;
2356   if (proto)
2357     {
2358       if (! METHOD_ENCODING (proto))
2359         {
2360           encoding = encode_method_prototype (proto);
2361           METHOD_ENCODING (proto) = encoding;
2362         }
2363       else
2364         encoding = METHOD_ENCODING (proto);
2365
2366       return add_objc_string (encoding, meth_var_types);
2367     }
2368   else
2369     return build_int_cst (NULL_TREE, 0);
2370 }
2371
2372 /* sel_ref_chain is a list whose "value" fields will be instances of
2373    identifier_node that represent the selector.  */
2374
2375 static tree
2376 build_typed_selector_reference (tree ident, tree prototype)
2377 {
2378   tree *chain = &sel_ref_chain;
2379   tree expr;
2380   int index = 0;
2381
2382   while (*chain)
2383     {
2384       if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2385         goto return_at_index;
2386
2387       index++;
2388       chain = &TREE_CHAIN (*chain);
2389     }
2390
2391   *chain = tree_cons (prototype, ident, NULL_TREE);
2392
2393  return_at_index:
2394   expr = build_unary_op (ADDR_EXPR,
2395                          build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2396                                           build_int_cst (NULL_TREE, index)),
2397                          1);
2398   return convert (objc_selector_type, expr);
2399 }
2400
2401 static tree
2402 build_selector_reference (tree ident)
2403 {
2404   tree *chain = &sel_ref_chain;
2405   tree expr;
2406   int index = 0;
2407
2408   while (*chain)
2409     {
2410       if (TREE_VALUE (*chain) == ident)
2411         return (flag_next_runtime
2412                 ? TREE_PURPOSE (*chain)
2413                 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2414                                    build_int_cst (NULL_TREE, index)));
2415
2416       index++;
2417       chain = &TREE_CHAIN (*chain);
2418     }
2419
2420   expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
2421
2422   *chain = tree_cons (expr, ident, NULL_TREE);
2423
2424   return (flag_next_runtime
2425           ? expr
2426           : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2427                              build_int_cst (NULL_TREE, index)));
2428 }
2429
2430 static GTY(()) int class_reference_idx;
2431
2432 static tree
2433 build_class_reference_decl (void)
2434 {
2435   tree decl;
2436   char buf[256];
2437
2438   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2439   decl = start_var_decl (objc_class_type, buf);
2440
2441   return decl;
2442 }
2443
2444 /* Create a class reference, but don't create a variable to reference
2445    it.  */
2446
2447 static void
2448 add_class_reference (tree ident)
2449 {
2450   tree chain;
2451
2452   if ((chain = cls_ref_chain))
2453     {
2454       tree tail;
2455       do
2456         {
2457           if (ident == TREE_VALUE (chain))
2458             return;
2459
2460           tail = chain;
2461           chain = TREE_CHAIN (chain);
2462         }
2463       while (chain);
2464
2465       /* Append to the end of the list */
2466       TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2467     }
2468   else
2469     cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2470 }
2471
2472 /* Get a class reference, creating it if necessary.  Also create the
2473    reference variable.  */
2474
2475 tree
2476 objc_get_class_reference (tree ident)
2477 {
2478   tree orig_ident;
2479
2480 #ifdef OBJCPLUS
2481   if (processing_template_decl)
2482     /* Must wait until template instantiation time.  */
2483     return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2484   if (TREE_CODE (ident) == TYPE_DECL)
2485     ident = DECL_NAME (ident);
2486 #endif
2487   orig_ident = ident;
2488
2489   if (!(ident = objc_is_class_name (ident)))
2490     {
2491       error ("`%s' is not an Objective-C class name or alias",
2492              IDENTIFIER_POINTER (orig_ident));
2493       return error_mark_node;
2494     }
2495
2496   if (flag_next_runtime && !flag_zero_link)
2497     {
2498       tree *chain;
2499       tree decl;
2500
2501       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2502         if (TREE_VALUE (*chain) == ident)
2503           {
2504             if (! TREE_PURPOSE (*chain))
2505               TREE_PURPOSE (*chain) = build_class_reference_decl ();
2506
2507             return TREE_PURPOSE (*chain);
2508           }
2509
2510       decl = build_class_reference_decl ();
2511       *chain = tree_cons (decl, ident, NULL_TREE);
2512       return decl;
2513     }
2514   else
2515     {
2516       tree params;
2517
2518       add_class_reference (ident);
2519
2520       params = build_tree_list (NULL_TREE,
2521                                 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2522                                                  IDENTIFIER_POINTER (ident)));
2523
2524       assemble_external (objc_get_class_decl);
2525       return build_function_call (objc_get_class_decl, params);
2526     }
2527 }
2528
2529 /* For each string section we have a chain which maps identifier nodes
2530    to decls for the strings.  */
2531
2532 static tree
2533 add_objc_string (tree ident, enum string_section section)
2534 {
2535   tree *chain, decl;
2536
2537   if (section == class_names)
2538     chain = &class_names_chain;
2539   else if (section == meth_var_names)
2540     chain = &meth_var_names_chain;
2541   else if (section == meth_var_types)
2542     chain = &meth_var_types_chain;
2543   else
2544     abort ();
2545
2546   while (*chain)
2547     {
2548       if (TREE_VALUE (*chain) == ident)
2549         return convert (string_type_node,
2550                         build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1));
2551
2552       chain = &TREE_CHAIN (*chain);
2553     }
2554
2555   decl = build_objc_string_decl (section);
2556
2557   *chain = tree_cons (decl, ident, NULL_TREE);
2558
2559   return convert (string_type_node, build_unary_op (ADDR_EXPR, decl, 1));
2560 }
2561
2562 static GTY(()) int class_names_idx;
2563 static GTY(()) int meth_var_names_idx;
2564 static GTY(()) int meth_var_types_idx;
2565
2566 static tree
2567 build_objc_string_decl (enum string_section section)
2568 {
2569   tree decl, ident;
2570   char buf[256];
2571
2572   if (section == class_names)
2573     sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2574   else if (section == meth_var_names)
2575     sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2576   else if (section == meth_var_types)
2577     sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2578
2579   ident = get_identifier (buf);
2580
2581   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2582   DECL_EXTERNAL (decl) = 1;
2583   TREE_PUBLIC (decl) = 0;
2584   TREE_USED (decl) = 1;
2585   TREE_CONSTANT (decl) = 1;
2586   DECL_CONTEXT (decl) = 0;
2587   DECL_ARTIFICIAL (decl) = 1;
2588 #ifdef OBJCPLUS
2589   DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */
2590 #endif  
2591
2592   make_decl_rtl (decl);
2593   pushdecl_top_level (decl);
2594
2595   return decl;
2596 }
2597
2598
2599 void
2600 objc_declare_alias (tree alias_ident, tree class_ident)
2601 {
2602   tree underlying_class;
2603
2604 #ifdef OBJCPLUS
2605   if (current_namespace != global_namespace) {
2606     error ("Objective-C declarations may only appear in global scope");
2607   }
2608 #endif /* OBJCPLUS */
2609
2610   if (!(underlying_class = objc_is_class_name (class_ident)))
2611     warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2612   else if (objc_is_class_name (alias_ident))
2613     warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2614   else
2615     alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2616 }
2617
2618 void
2619 objc_declare_class (tree ident_list)
2620 {
2621   tree list;
2622 #ifdef OBJCPLUS
2623   if (current_namespace != global_namespace) {
2624     error ("Objective-C declarations may only appear in global scope");
2625   }
2626 #endif /* OBJCPLUS */
2627
2628   for (list = ident_list; list; list = TREE_CHAIN (list))
2629     {
2630       tree ident = TREE_VALUE (list);
2631
2632       if (! objc_is_class_name (ident))
2633         {
2634           tree record = lookup_name (ident);
2635         
2636           if (record && ! TREE_STATIC_TEMPLATE (record))
2637             {
2638               error ("`%s' redeclared as different kind of symbol",
2639                      IDENTIFIER_POINTER (ident));
2640               error ("%Jprevious declaration of '%D'",
2641                      record, record);
2642             }
2643
2644           record = xref_tag (RECORD_TYPE, ident);
2645           TREE_STATIC_TEMPLATE (record) = 1;
2646           class_chain = tree_cons (NULL_TREE, ident, class_chain);
2647         }
2648     }
2649 }
2650
2651 tree
2652 objc_is_class_name (tree ident)
2653 {
2654   tree chain;
2655
2656   if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2657       && identifier_global_value (ident))
2658     ident = identifier_global_value (ident);
2659   while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2660     ident = OBJC_TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2661
2662   if (ident && TREE_CODE (ident) == RECORD_TYPE)
2663     ident = OBJC_TYPE_NAME (ident);
2664 #ifdef OBJCPLUS
2665   if (ident && TREE_CODE (ident) == TYPE_DECL)
2666     ident = DECL_NAME (ident);
2667 #endif
2668   if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2669     return NULL_TREE;
2670
2671   if (lookup_interface (ident))
2672     return ident;
2673
2674   for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2675     {
2676       if (ident == TREE_VALUE (chain))
2677         return ident;
2678     }
2679
2680   for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2681     {
2682       if (ident == TREE_VALUE (chain))
2683         return TREE_PURPOSE (chain);
2684     }
2685
2686   return 0;
2687 }
2688
2689 /* Check whether TYPE is either 'id' or 'Class'.  */
2690
2691 tree
2692 objc_is_id (tree type)
2693 {
2694   if (type && TREE_CODE (type) == IDENTIFIER_NODE
2695       && identifier_global_value (type))
2696     type = identifier_global_value (type);
2697
2698   if (type && TREE_CODE (type) == TYPE_DECL)
2699     type = TREE_TYPE (type);
2700
2701   /* NB: This function may be called before the ObjC front-end has
2702      been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL.  */
2703   return (objc_object_type && type && (IS_ID (type) || IS_CLASS (type))
2704           ? type
2705           : NULL_TREE); 
2706 }
2707
2708 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
2709    class instance.  This is needed by other parts of the compiler to
2710    handle ObjC types gracefully.  */
2711
2712 tree
2713 objc_is_object_ptr (tree type)
2714 {
2715   tree ret;
2716
2717   type = TYPE_MAIN_VARIANT (type);
2718   if (!POINTER_TYPE_P (type))
2719     return 0;
2720
2721   ret = objc_is_id (type);
2722   if (!ret)
2723     ret = objc_is_class_name (TREE_TYPE (type));
2724
2725   return ret;
2726 }
2727
2728 static tree
2729 lookup_interface (tree ident)
2730 {
2731   tree chain;
2732
2733 #ifdef OBJCPLUS
2734   if (ident && TREE_CODE (ident) == TYPE_DECL)
2735     ident = DECL_NAME (ident);
2736 #endif
2737   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2738     {
2739       if (ident == CLASS_NAME (chain))
2740       return chain;
2741     }
2742   return NULL_TREE;
2743 }
2744
2745 /* Implement @defs (<classname>) within struct bodies.  */
2746
2747 tree
2748 objc_get_class_ivars (tree class_name)
2749 {
2750   tree interface = lookup_interface (class_name);
2751
2752   if (interface)
2753     return get_class_ivars (interface);
2754
2755   error ("cannot find interface declaration for `%s'",
2756          IDENTIFIER_POINTER (class_name));
2757
2758   return error_mark_node;
2759 }
2760
2761 /* Used by: build_private_template, continue_class,
2762    and for @defs constructs.  */
2763
2764 static tree
2765 get_class_ivars (tree interface)
2766 {
2767   tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
2768
2769   /* Both CLASS_RAW_IVARS and CLASS_IVARS contain a list of ivars declared
2770      by the current class (i.e., they do not include super-class ivars).
2771      However, the CLASS_IVARS list will be side-effected by a call to
2772      finish_struct(), which will fill in field offsets.  */
2773   if (!CLASS_IVARS (interface))
2774     CLASS_IVARS (interface) = ivar_chain;
2775
2776   while (CLASS_SUPER_NAME (interface))
2777     {
2778       /* Prepend super-class ivars.  */
2779       interface = lookup_interface (CLASS_SUPER_NAME (interface));
2780       ivar_chain = chainon (copy_list (CLASS_RAW_IVARS (interface)),
2781                             ivar_chain);
2782     }
2783
2784   return ivar_chain;
2785 }
2786
2787 static tree
2788 objc_create_temporary_var (tree type)
2789 {
2790   tree decl;
2791  
2792   decl = build_decl (VAR_DECL, NULL_TREE, type);
2793   TREE_USED (decl) = 1;
2794   DECL_ARTIFICIAL (decl) = 1;
2795   DECL_IGNORED_P (decl) = 1;
2796   DECL_CONTEXT (decl) = current_function_decl;
2797
2798   return decl;
2799 }
2800 \f
2801 /* Exception handling constructs.  We begin by having the parser do most
2802    of the work and passing us blocks.  What we do next depends on whether
2803    we're doing "native" exception handling or legacy Darwin setjmp exceptions.
2804    We abstract all of this in a handful of appropriately named routines.  */
2805
2806 /* Stack of open try blocks.  */
2807
2808 struct objc_try_context
2809 {
2810   struct objc_try_context *outer;
2811
2812   /* Statements (or statement lists) as processed by the parser.  */
2813   tree try_body;
2814   tree finally_body;
2815
2816   /* Some file position locations.  */
2817   location_t try_locus;
2818   location_t end_try_locus;
2819   location_t end_catch_locus;
2820   location_t finally_locus;
2821   location_t end_finally_locus;
2822
2823   /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
2824      of a TRY_CATCH_EXPR.  Even when doing Darwin setjmp.  */
2825   tree catch_list;
2826
2827   /* The CATCH_EXPR of an open @catch clause.  */
2828   tree current_catch;
2829
2830   /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR.  */
2831   tree caught_decl;
2832   tree stack_decl;
2833   tree rethrow_decl;
2834 };
2835
2836 static struct objc_try_context *cur_try_context;
2837
2838 /* This hook, called via lang_eh_runtime_type, generates a runtime object
2839    that represents TYPE.  For Objective-C, this is just the class name.  */
2840 /* ??? Isn't there a class object or some such?  Is it easy to get?  */
2841
2842 #ifndef OBJCPLUS
2843 static tree
2844 objc_eh_runtime_type (tree type)
2845 {
2846   return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
2847 }
2848 #endif
2849
2850 /* Initialize exception handling.  */
2851
2852 static void
2853 objc_init_exceptions (void)
2854 {
2855   static bool done = false;
2856   if (done)
2857     return;
2858   done = true;
2859
2860   if (flag_objc_sjlj_exceptions)
2861     {
2862       /* On Darwin, ObjC exceptions require a sufficiently recent
2863          version of the runtime, so the user must ask for them explicitly.  */
2864       if (!flag_objc_exceptions)
2865         warning ("use %<-fobjc-exceptions%> to enable Objective-C "
2866                  "exception syntax");
2867     }
2868 #ifndef OBJCPLUS
2869   else
2870     {
2871       c_eh_initialized_p = true;
2872       eh_personality_libfunc
2873         = init_one_libfunc (USING_SJLJ_EXCEPTIONS
2874                             ? "__gnu_objc_personality_sj0"
2875                             : "__gnu_objc_personality_v0");
2876       using_eh_for_cleanups ();
2877       lang_eh_runtime_type = objc_eh_runtime_type;
2878     }
2879 #endif
2880 }
2881
2882 /* Build an EXC_PTR_EXPR, or the moral equivalent.  In the case of Darwin,
2883    we'll arrange for it to be initialized (and associated with a binding)
2884    later.  */
2885
2886 static tree
2887 objc_build_exc_ptr (void)
2888 {
2889   if (flag_objc_sjlj_exceptions)
2890     {
2891       tree var = cur_try_context->caught_decl;
2892       if (!var)
2893         {
2894           var = objc_create_temporary_var (objc_object_type);
2895           cur_try_context->caught_decl = var;
2896         }
2897       return var;
2898     }
2899   else
2900     return build (EXC_PTR_EXPR, objc_object_type);
2901 }
2902
2903 /* Build "objc_exception_try_exit(&_stack)".  */
2904
2905 static tree
2906 next_sjlj_build_try_exit (void)
2907 {
2908   tree t;
2909   t = build_fold_addr_expr (cur_try_context->stack_decl);
2910   t = tree_cons (NULL, t, NULL);
2911   t = build_function_call (objc_exception_try_exit_decl, t);
2912   return t;
2913 }
2914
2915 /* Build
2916         objc_exception_try_enter (&_stack);
2917         if (_setjmp(&_stack.buf))
2918           ;
2919         else
2920           ;
2921    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
2922    empty, ready for the caller to fill them in.  */
2923
2924 static tree
2925 next_sjlj_build_enter_and_setjmp (void)
2926 {
2927   tree t, enter, sj, cond;
2928
2929   t = build_fold_addr_expr (cur_try_context->stack_decl);
2930   t = tree_cons (NULL, t, NULL);
2931   enter = build_function_call (objc_exception_try_enter_decl, t);
2932
2933   t = build_component_ref (cur_try_context->stack_decl,
2934                            get_identifier ("buf"));
2935   t = build_fold_addr_expr (t);
2936   t = convert (ptr_type_node, t);
2937   t = tree_cons (NULL, t, NULL);
2938   sj = build_function_call (objc_setjmp_decl, t);
2939
2940   cond = build (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2941   cond = lang_hooks.truthvalue_conversion (cond);
2942
2943   return build (COND_EXPR, void_type_node, cond, NULL, NULL);
2944 }
2945
2946 /* Build
2947         DECL = objc_exception_extract(&_stack);
2948 */
2949    
2950 static tree
2951 next_sjlj_build_exc_extract (tree decl)
2952 {
2953   tree t;
2954
2955   t = build_fold_addr_expr (cur_try_context->stack_decl);
2956   t = tree_cons (NULL, t, NULL);
2957   t = build_function_call (objc_exception_extract_decl, t);
2958   t = convert (TREE_TYPE (decl), t);
2959   t = build (MODIFY_EXPR, void_type_node, decl, t);
2960
2961   return t;
2962 }
2963
2964 /* Build
2965         if (objc_exception_match(obj_get_class(TYPE), _caught)
2966           BODY
2967         else if (...)
2968           ...
2969         else
2970           {
2971             _rethrow = _caught;
2972             objc_exception_try_exit(&_stack);
2973           }
2974    from the sequence of CATCH_EXPRs in the current try context.  */
2975
2976 static tree
2977 next_sjlj_build_catch_list (void)
2978 {
2979   tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
2980   tree catch_seq, t;
2981   tree *last = &catch_seq;
2982   bool saw_id = false;
2983
2984   for (; !tsi_end_p (i); tsi_next (&i))
2985     {
2986       tree stmt = tsi_stmt (i);
2987       tree type = CATCH_TYPES (stmt);
2988       tree body = CATCH_BODY (stmt);
2989
2990       if (type == NULL)
2991         {
2992           *last = body;
2993           saw_id = true;
2994           break;
2995         }
2996       else
2997         {
2998           tree args, cond;
2999
3000           if (type == error_mark_node)
3001             cond = error_mark_node;
3002           else
3003             {
3004               args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
3005               t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
3006               args = tree_cons (NULL, t, args);
3007               t = build_function_call (objc_exception_match_decl, args);
3008               cond = lang_hooks.truthvalue_conversion (t);
3009             }
3010           t = build (COND_EXPR, void_type_node, cond, body, NULL);
3011           SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
3012
3013           *last = t;
3014           last = &COND_EXPR_ELSE (t);
3015         }
3016     }
3017
3018   if (!saw_id)
3019     {
3020       t = build (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
3021                  cur_try_context->caught_decl);
3022       annotate_with_locus (t, cur_try_context->end_catch_locus);
3023       append_to_statement_list (t, last);
3024
3025       t = next_sjlj_build_try_exit ();
3026       annotate_with_locus (t, cur_try_context->end_catch_locus);
3027       append_to_statement_list (t, last);
3028     }
3029
3030   return catch_seq;
3031 }
3032
3033 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
3034    exception handling.  We aim to build:
3035
3036         {
3037           struct _objc_exception_data _stack;
3038           id volatile _rethrow = 0;
3039           try
3040             {
3041               objc_exception_try_enter (&_stack);
3042               if (_setjmp(&_stack.buf))
3043                 {
3044                   id _caught = objc_exception_extract(&_stack);
3045                   objc_exception_try_enter (&_stack);
3046                   if (_setjmp(&_stack.buf))
3047                     _rethrow = objc_exception_extract(&_stack);
3048                   else
3049                     CATCH-LIST
3050                 }
3051               else
3052                 TRY-BLOCK
3053             }
3054           finally
3055             {
3056               if (!_rethrow)
3057                 objc_exception_try_exit(&_stack);
3058               FINALLY-BLOCK
3059               if (_rethrow)
3060                 objc_exception_throw(_rethrow);
3061             }
3062         }
3063
3064    If CATCH-LIST is empty, we can omit all of the block containing
3065    "_caught" except for the setting of _rethrow.  Note the use of
3066    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
3067    but handles goto and other exits from the block.  */
3068
3069 static tree
3070 next_sjlj_build_try_catch_finally (void)
3071 {
3072   tree rethrow_decl, stack_decl, t;
3073   tree catch_seq, try_fin, bind;
3074
3075   /* Create the declarations involved.  */
3076   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3077   stack_decl = objc_create_temporary_var (t);
3078   cur_try_context->stack_decl = stack_decl;
3079
3080   rethrow_decl = objc_create_temporary_var (objc_object_type);
3081   cur_try_context->rethrow_decl = rethrow_decl;
3082   TREE_THIS_VOLATILE (rethrow_decl) = 1;
3083   TREE_CHAIN (rethrow_decl) = stack_decl;
3084
3085   /* Build the outermost varible binding level.  */
3086   bind = build (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
3087   annotate_with_locus (bind, cur_try_context->try_locus);
3088   TREE_SIDE_EFFECTS (bind) = 1;
3089
3090   /* Initialize rethrow_decl.  */
3091   t = build (MODIFY_EXPR, void_type_node, rethrow_decl,
3092              convert (objc_object_type, null_pointer_node));
3093   annotate_with_locus (t, cur_try_context->try_locus);
3094   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3095
3096   /* Build the outermost TRY_FINALLY_EXPR.  */
3097   try_fin = build (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
3098   annotate_with_locus (try_fin, cur_try_context->try_locus);
3099   TREE_SIDE_EFFECTS (try_fin) = 1;
3100   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
3101
3102   /* Create the complete catch sequence.  */
3103   if (cur_try_context->catch_list)
3104     {
3105       tree caught_decl = objc_build_exc_ptr ();
3106       catch_seq = build_stmt (BIND_EXPR, caught_decl, NULL, NULL);
3107
3108       t = next_sjlj_build_exc_extract (caught_decl);
3109       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3110
3111       t = next_sjlj_build_enter_and_setjmp ();
3112       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
3113       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
3114       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3115     }
3116   else
3117     catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
3118   annotate_with_locus (catch_seq, cur_try_context->end_try_locus);
3119
3120   /* Build the main register-and-try if statement.  */
3121   t = next_sjlj_build_enter_and_setjmp ();
3122   annotate_with_locus (t, cur_try_context->try_locus);
3123   COND_EXPR_THEN (t) = catch_seq;
3124   COND_EXPR_ELSE (t) = cur_try_context->try_body;
3125   TREE_OPERAND (try_fin, 0) = t;
3126
3127   /* Build the complete FINALLY statement list.  */
3128   t = next_sjlj_build_try_exit ();
3129   t = build_stmt (COND_EXPR,
3130                   lang_hooks.truthvalue_conversion (rethrow_decl),
3131                   NULL, t);
3132   annotate_with_locus (t, cur_try_context->finally_locus);
3133   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3134
3135   append_to_statement_list (cur_try_context->finally_body,
3136                             &TREE_OPERAND (try_fin, 1));
3137
3138   t = tree_cons (NULL, rethrow_decl, NULL);
3139   t = build_function_call (objc_exception_throw_decl, t);
3140   t = build_stmt (COND_EXPR,
3141                   lang_hooks.truthvalue_conversion (rethrow_decl),
3142                   t, NULL);
3143   annotate_with_locus (t, cur_try_context->end_finally_locus);
3144   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3145
3146   return bind;
3147 }
3148
3149 /* Called just after parsing the @try and its associated BODY.  We now
3150    must prepare for the tricky bits -- handling the catches and finally.  */
3151
3152 void
3153 objc_begin_try_stmt (location_t try_locus, tree body)
3154 {
3155   struct objc_try_context *c = xcalloc (1, sizeof (*c));
3156   c->outer = cur_try_context;
3157   c->try_body = body;
3158   c->try_locus = try_locus;
3159   c->end_try_locus = input_location;
3160   cur_try_context = c;
3161
3162   objc_init_exceptions ();
3163 }
3164
3165 /* Called just after parsing "@catch (parm)".  Open a binding level, 
3166    enter DECL into the binding level, and initialize it.  Leave the
3167    binding level open while the body of the compound statement is parsed.  */
3168    
3169 void
3170 objc_begin_catch_clause (tree decl)
3171 {
3172   tree compound, type, t;
3173
3174   /* Begin a new scope that the entire catch clause will live in.  */
3175   compound = c_begin_compound_stmt (true);
3176
3177   /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL.  */
3178   decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
3179   lang_hooks.decls.pushdecl (decl);
3180
3181   /* Since a decl is required here by syntax, don't warn if its unused.  */
3182   /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
3183      be what the previous objc implementation did.  */
3184   TREE_USED (decl) = 1;
3185
3186   /* Verify that the type of the catch is valid.  It must be a pointer
3187      to an Objective-C class, or "id" (which is catch-all).  */
3188   type = TREE_TYPE (decl);
3189
3190   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3191     type = NULL;
3192   else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3193     {
3194       error ("@catch parameter is not a known Objective-C class type");
3195       type = error_mark_node;
3196     }
3197   else if (cur_try_context->catch_list)
3198     {
3199       /* Examine previous @catch clauses and see if we've already
3200          caught the type in question.  */
3201       tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3202       for (; !tsi_end_p (i); tsi_next (&i))
3203         {
3204           tree stmt = tsi_stmt (i);
3205           t = CATCH_TYPES (stmt);
3206           if (t == error_mark_node)
3207             continue;
3208           if (!t || objc_comptypes (TREE_TYPE (t), TREE_TYPE (type), 0) == 1)
3209             {
3210               warning ("exception of type %<%T%> will be caught",
3211                        TREE_TYPE (type));
3212               warning ("%H   by earlier handler for %<%T%>",
3213                        EXPR_LOCUS (stmt), TREE_TYPE (t ? t : objc_object_type));
3214               break;
3215             }
3216         }
3217     }
3218
3219   /* Record the data for the catch in the try context so that we can
3220      finalize it later.  */
3221   t = build_stmt (CATCH_EXPR, type, compound);
3222   cur_try_context->current_catch = t;
3223
3224   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3225   t = objc_build_exc_ptr ();
3226   t = convert (TREE_TYPE (decl), t);
3227   t = build (MODIFY_EXPR, void_type_node, decl, t);
3228   add_stmt (t);
3229 }
3230
3231 /* Called just after parsing the closing brace of a @catch clause.  Close
3232    the open binding level, and record a CATCH_EXPR for it.  */
3233
3234 void
3235 objc_finish_catch_clause (void)
3236 {
3237   tree c = cur_try_context->current_catch;
3238   cur_try_context->current_catch = NULL;
3239   cur_try_context->end_catch_locus = input_location;
3240
3241   CATCH_BODY (c) = c_end_compound_stmt (CATCH_BODY (c), 1);
3242   append_to_statement_list (c, &cur_try_context->catch_list);
3243 }
3244
3245 /* Called after parsing a @finally clause and its associated BODY.
3246    Record the body for later placement.  */
3247
3248 void
3249 objc_build_finally_clause (location_t finally_locus, tree body)
3250 {
3251   cur_try_context->finally_body = body;
3252   cur_try_context->finally_locus = finally_locus;
3253   cur_try_context->end_finally_locus = input_location;
3254 }
3255
3256 /* Called to finalize a @try construct.  */
3257
3258 void
3259 objc_finish_try_stmt (void)
3260 {
3261   struct objc_try_context *c = cur_try_context;
3262   tree stmt;
3263
3264   if (c->catch_list == NULL && c->finally_body == NULL)
3265     error ("`@try' without `@catch' or `@finally'");
3266
3267   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
3268   if (flag_objc_sjlj_exceptions)
3269     {
3270       if (!cur_try_context->finally_body)
3271         {
3272           cur_try_context->finally_locus = input_location;
3273           cur_try_context->end_finally_locus = input_location;
3274         }
3275       stmt = next_sjlj_build_try_catch_finally ();
3276     }
3277   else
3278     {
3279       /* Otherwise, nest the CATCH inside a FINALLY.  */
3280       stmt = c->try_body;
3281       if (c->catch_list)
3282         {
3283           stmt = build_stmt (TRY_CATCH_EXPR, stmt, c->catch_list);
3284           annotate_with_locus (stmt, cur_try_context->try_locus);
3285         }
3286       if (c->finally_body)
3287         {
3288           stmt = build_stmt (TRY_FINALLY_EXPR, stmt, c->finally_body);
3289           annotate_with_locus (stmt, cur_try_context->try_locus);
3290         }
3291     }
3292   add_stmt (stmt);
3293
3294   cur_try_context = c->outer;
3295   free (c);
3296 }
3297
3298 tree
3299 objc_build_throw_stmt (tree throw_expr)
3300 {
3301   tree args;
3302
3303   objc_init_exceptions ();
3304
3305   if (throw_expr == NULL)
3306     {
3307       /* If we're not inside a @catch block, there is no "current
3308          exception" to be rethrown.  */
3309       if (cur_try_context == NULL
3310           || cur_try_context->current_catch == NULL)
3311         {
3312           error ("%<@throw%> (rethrow) used outside of a @catch block");
3313           return NULL_TREE;
3314         }
3315
3316       /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3317          value that we get from the runtime.  */
3318       throw_expr = objc_build_exc_ptr ();
3319     }
3320
3321   /* A throw is just a call to the runtime throw function with the
3322      object as a parameter.  */
3323   args = tree_cons (NULL, throw_expr, NULL);
3324   return add_stmt (build_function_call (objc_exception_throw_decl, args));
3325 }
3326
3327 void
3328 objc_build_synchronized (location_t start_locus, tree mutex, tree body)
3329 {
3330   tree args, call;
3331
3332   /* First lock the mutex.  */
3333   mutex = save_expr (mutex);
3334   args = tree_cons (NULL, mutex, NULL);
3335   call = build_function_call (objc_sync_enter_decl, args);
3336   annotate_with_locus (call, start_locus);
3337   add_stmt (call);
3338
3339   /* Build the mutex unlock.  */
3340   args = tree_cons (NULL, mutex, NULL);
3341   call = build_function_call (objc_sync_exit_decl, args);
3342   annotate_with_locus (call, input_location);
3343
3344   /* Put the that and the body in a TRY_FINALLY.  */
3345   objc_begin_try_stmt (start_locus, body);
3346   objc_build_finally_clause (input_location, call);
3347   objc_finish_try_stmt ();
3348 }
3349
3350 \f
3351 /* Predefine the following data type:
3352
3353    struct _objc_exception_data
3354    {
3355      int buf[_JBLEN];
3356      void *pointers[4];
3357    }; */
3358
3359 /* The following yuckiness should prevent users from having to #include
3360    <setjmp.h> in their code... */
3361
3362 #ifdef TARGET_POWERPC
3363 /* snarfed from /usr/include/ppc/setjmp.h */
3364 #define _JBLEN (26 + 36 + 129 + 1)
3365 #else
3366 /* snarfed from /usr/include/i386/{setjmp,signal}.h */
3367 #define _JBLEN 18
3368 #endif
3369
3370 static void
3371 build_next_objc_exception_stuff (void)
3372 {
3373   tree field_decl, field_decl_chain, index, temp_type;
3374
3375   objc_exception_data_template
3376     = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3377
3378   /* int buf[_JBLEN]; */
3379
3380   index = build_index_type (build_int_cst (NULL_TREE, _JBLEN - 1));
3381   field_decl = create_field_decl (build_array_type (integer_type_node, index),
3382                                   "buf");
3383   field_decl_chain = field_decl;
3384
3385   /* void *pointers[4]; */
3386
3387   index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
3388   field_decl = create_field_decl (build_array_type (ptr_type_node, index),
3389                                   "pointers");
3390   chainon (field_decl_chain, field_decl);
3391
3392   finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3393
3394   /* int _setjmp(...); */
3395   /* If the user includes <setjmp.h>, this shall be superseded by
3396      'int _setjmp(jmp_buf);' */
3397   temp_type = build_function_type (integer_type_node, NULL_TREE);
3398   objc_setjmp_decl
3399     = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3400
3401   /* id objc_exception_extract(struct _objc_exception_data *); */
3402   temp_type
3403     = build_function_type (objc_object_type,
3404                            tree_cons (NULL_TREE,
3405                                       build_pointer_type (objc_exception_data_template),
3406                                       OBJC_VOID_AT_END));
3407   objc_exception_extract_decl
3408     = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3409   /* void objc_exception_try_enter(struct _objc_exception_data *); */
3410   /* void objc_exception_try_exit(struct _objc_exception_data *); */
3411   temp_type
3412     = build_function_type (void_type_node,
3413                            tree_cons (NULL_TREE,
3414                                       build_pointer_type (objc_exception_data_template),
3415                                       OBJC_VOID_AT_END));
3416   objc_exception_try_enter_decl
3417     = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3418   objc_exception_try_exit_decl
3419     = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3420
3421   /* int objc_exception_match(id, id); */
3422   temp_type 
3423     = build_function_type (integer_type_node,
3424                            tree_cons (NULL_TREE, objc_object_type,
3425                                       tree_cons (NULL_TREE, objc_object_type,
3426                                                  OBJC_VOID_AT_END)));
3427   objc_exception_match_decl
3428     = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3429 }
3430
3431 static void
3432 build_objc_exception_stuff (void)
3433 {
3434   tree noreturn_list, nothrow_list, temp_type;
3435
3436   noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
3437   nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
3438
3439   /* void objc_exception_throw(id) __attribute__((noreturn)); */
3440   /* void objc_sync_enter(id); */
3441   /* void objc_sync_exit(id); */
3442   temp_type = build_function_type (void_type_node,
3443                                    tree_cons (NULL_TREE, objc_object_type,
3444                                               OBJC_VOID_AT_END));
3445   objc_exception_throw_decl
3446     = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
3447                         noreturn_list);
3448   objc_sync_enter_decl
3449     = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
3450                         NULL, nothrow_list);
3451   objc_sync_exit_decl
3452     = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
3453                         NULL, nothrow_list);
3454 }
3455
3456
3457 /* struct <classname> {
3458      struct _objc_class *isa;
3459      ...
3460    };  */
3461
3462 static tree
3463 build_private_template (tree class)
3464 {
3465   tree ivar_context;
3466
3467   if (CLASS_STATIC_TEMPLATE (class))
3468     {
3469       uprivate_record = CLASS_STATIC_TEMPLATE (class);
3470       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3471     }
3472   else
3473     {
3474       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3475       ivar_context = get_class_ivars (class);
3476
3477       finish_struct (uprivate_record, ivar_context, NULL_TREE);
3478
3479       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3480
3481       /* mark this record as class template - for class type checking */
3482       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3483     }
3484
3485   objc_instance_type = build_pointer_type (uprivate_record);
3486
3487   return ivar_context;
3488 }
3489 \f
3490 /* Begin code generation for protocols...  */
3491
3492 /* struct _objc_protocol {
3493      struct _objc_class *isa;
3494      char *protocol_name;
3495      struct _objc_protocol **protocol_list;
3496      struct _objc__method_prototype_list *instance_methods;
3497      struct _objc__method_prototype_list *class_methods;
3498    };  */
3499
3500 static void
3501 build_protocol_template (void)
3502 {
3503   tree field_decl, field_decl_chain;
3504
3505   objc_protocol_template = start_struct (RECORD_TYPE,
3506                                          get_identifier (UTAG_PROTOCOL));
3507
3508   /* struct _objc_class *isa; */
3509   field_decl = create_field_decl (build_pointer_type
3510                                   (xref_tag (RECORD_TYPE,
3511                                              get_identifier (UTAG_CLASS))),
3512                                   "isa");
3513   field_decl_chain = field_decl;
3514
3515   /* char *protocol_name; */
3516   field_decl = create_field_decl (string_type_node, "protocol_name");
3517   chainon (field_decl_chain, field_decl);
3518
3519   /* struct _objc_protocol **protocol_list; */
3520   field_decl = create_field_decl (build_pointer_type
3521                                   (build_pointer_type
3522                                    (objc_protocol_template)),
3523                                   "protocol_list");
3524   chainon (field_decl_chain, field_decl);
3525
3526   /* struct objc_method_list *instance_methods; */
3527   field_decl = create_field_decl (build_pointer_type
3528                                   (xref_tag (RECORD_TYPE,
3529                                              get_identifier
3530                                              (UTAG_METHOD_PROTOTYPE_LIST))),
3531                                   "instance_methods");
3532   chainon (field_decl_chain, field_decl);
3533
3534   /* struct objc_method_list *class_methods; */
3535   field_decl = create_field_decl (build_pointer_type
3536                                   (xref_tag (RECORD_TYPE,
3537                                              get_identifier
3538                                              (UTAG_METHOD_PROTOTYPE_LIST))),
3539                                   "class_methods");
3540   chainon (field_decl_chain, field_decl);
3541
3542   finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
3543 }
3544
3545 static tree
3546 build_descriptor_table_initializer (tree type, tree entries)
3547 {
3548   tree initlist = NULL_TREE;
3549
3550   do
3551     {
3552       tree eltlist = NULL_TREE;
3553
3554       eltlist
3555         = tree_cons (NULL_TREE,
3556                      build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3557       eltlist
3558         = tree_cons (NULL_TREE,
3559                      add_objc_string (METHOD_ENCODING (entries),
3560                                       meth_var_types),
3561                      eltlist);
3562
3563       initlist
3564         = tree_cons (NULL_TREE,
3565                      objc_build_constructor (type, nreverse (eltlist)),
3566                      initlist);
3567
3568       entries = TREE_CHAIN (entries);
3569     }
3570   while (entries);
3571
3572   return objc_build_constructor (build_array_type (type, 0),
3573                                  nreverse (initlist));
3574 }
3575
3576 /* struct objc_method_prototype_list {
3577      int count;
3578      struct objc_method_prototype {
3579         SEL name;
3580         char *types;
3581      } list[1];
3582    };  */
3583
3584 static tree
3585 build_method_prototype_list_template (tree list_type, int size)
3586 {
3587   tree objc_ivar_list_record;
3588   tree field_decl, field_decl_chain;
3589
3590   /* Generate an unnamed struct definition.  */
3591
3592   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3593
3594   /* int method_count; */
3595   field_decl = create_field_decl (integer_type_node, "method_count");
3596   field_decl_chain = field_decl;
3597
3598   /* struct objc_method method_list[]; */
3599   field_decl = create_field_decl (build_array_type
3600                                   (list_type,
3601                                    build_index_type
3602                                    (build_int_cst (NULL_TREE, size - 1))),
3603                                   "method_list");
3604   chainon (field_decl_chain, field_decl);
3605
3606   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3607
3608   return objc_ivar_list_record;
3609 }
3610
3611 static tree
3612 build_method_prototype_template (void)
3613 {
3614   tree proto_record;
3615   tree field_decl, field_decl_chain;
3616
3617   proto_record
3618     = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
3619
3620   /* SEL _cmd; */
3621   field_decl = create_field_decl (objc_selector_type, "_cmd");
3622   field_decl_chain = field_decl;
3623
3624   /* char *method_types; */
3625   field_decl = create_field_decl (string_type_node, "method_types");
3626   chainon (field_decl_chain, field_decl);
3627
3628   finish_struct (proto_record, field_decl_chain, NULL_TREE);
3629
3630   return proto_record;
3631 }
3632
3633 static tree
3634 objc_method_parm_type (tree type)
3635 {
3636   type = TREE_VALUE (TREE_TYPE (type));
3637   if (TREE_CODE (type) == TYPE_DECL)
3638     type = TREE_TYPE (type);
3639   return TYPE_MAIN_VARIANT (type);
3640 }
3641
3642 static int
3643 objc_encoded_type_size (tree type)
3644 {
3645   int sz = int_size_in_bytes (type);
3646
3647   /* Make all integer and enum types at least as large
3648      as an int.  */
3649   if (sz > 0 && INTEGRAL_TYPE_P (type))
3650     sz = MAX (sz, int_size_in_bytes (integer_type_node));
3651   /* Treat arrays as pointers, since that's how they're
3652      passed in.  */
3653   else if (TREE_CODE (type) == ARRAY_TYPE)
3654     sz = int_size_in_bytes (ptr_type_node);
3655   return sz;
3656 }
3657
3658 static tree
3659 encode_method_prototype (tree method_decl)
3660 {
3661   tree parms;
3662   int parm_offset, i;
3663   char buf[40];
3664   tree result;
3665
3666   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
3667   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
3668
3669   /* Encode return type.  */
3670   encode_type (objc_method_parm_type (method_decl),
3671                obstack_object_size (&util_obstack),
3672                OBJC_ENCODE_INLINE_DEFS);
3673
3674   /* Stack size.  */
3675   /* The first two arguments (self and _cmd) are pointers; account for
3676      their size.  */
3677   i = int_size_in_bytes (ptr_type_node);
3678   parm_offset = 2 * i;
3679   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3680        parms = TREE_CHAIN (parms))
3681     {
3682       tree type = objc_method_parm_type (parms);
3683       int sz = objc_encoded_type_size (type);
3684
3685       /* If a type size is not known, bail out.  */
3686       if (sz < 0)
3687         {
3688           error ("%Jtype '%D' does not have a known size",
3689                  type, type);
3690           /* Pretend that the encoding succeeded; the compilation will
3691              fail nevertheless.  */
3692           goto finish_encoding;
3693         }
3694       parm_offset += sz;
3695     }
3696
3697   sprintf (buf, "%d@0:%d", parm_offset, i);
3698   obstack_grow (&util_obstack, buf, strlen (buf));
3699
3700   /* Argument types.  */
3701   parm_offset = 2 * i;
3702   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3703        parms = TREE_CHAIN (parms))
3704     {
3705       tree type = objc_method_parm_type (parms);
3706
3707       /* Process argument qualifiers for user supplied arguments.  */
3708       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
3709
3710       /* Type.  */
3711       encode_type (type, obstack_object_size (&util_obstack),
3712                    OBJC_ENCODE_INLINE_DEFS);
3713
3714       /* Compute offset.  */
3715       sprintf (buf, "%d", parm_offset);
3716       parm_offset += objc_encoded_type_size (type);
3717
3718       obstack_grow (&util_obstack, buf, strlen (buf));
3719     }
3720
3721   finish_encoding:
3722   obstack_1grow (&util_obstack, '\0');
3723   result = get_identifier (obstack_finish (&util_obstack));
3724   obstack_free (&util_obstack, util_firstobj);
3725   return result;
3726 }
3727
3728 static tree
3729 generate_descriptor_table (tree type, const char *name, int size, tree list,
3730                            tree proto)
3731 {
3732   tree decl, initlist;
3733
3734   decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
3735
3736   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
3737   initlist = tree_cons (NULL_TREE, list, initlist);
3738
3739   finish_var_decl (decl, objc_build_constructor (type, nreverse (initlist)));
3740
3741   return decl;
3742 }
3743
3744 static void
3745 generate_method_descriptors (tree protocol)
3746 {
3747   tree initlist, chain, method_list_template;
3748   tree variable_length_type
3749     = xref_tag (RECORD_TYPE,
3750                 get_identifier (UTAG_METHOD_PROTOTYPE_LIST));
3751   int size;
3752
3753   if (!objc_method_prototype_template)
3754     objc_method_prototype_template = build_method_prototype_template ();
3755
3756   chain = PROTOCOL_CLS_METHODS (protocol);
3757   if (chain)
3758     {
3759       size = list_length (chain);
3760
3761       method_list_template
3762         = build_method_prototype_list_template (objc_method_prototype_template,
3763                                                 size);
3764
3765       initlist
3766         = build_descriptor_table_initializer (objc_method_prototype_template,
3767                                               chain);
3768
3769       UOBJC_CLASS_METHODS_decl
3770         = generate_descriptor_table (method_list_template,
3771                                      "_OBJC_PROTOCOL_CLASS_METHODS",
3772                                      size, initlist, protocol);
3773       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3774     }
3775   else
3776     UOBJC_CLASS_METHODS_decl = 0;
3777
3778   chain = PROTOCOL_NST_METHODS (protocol);
3779   if (chain)
3780     {
3781       size = list_length (chain);
3782
3783       method_list_template
3784         = build_method_prototype_list_template (objc_method_prototype_template,
3785                                                 size);
3786       initlist
3787         = build_descriptor_table_initializer (objc_method_prototype_template,
3788                                               chain);
3789
3790       UOBJC_INSTANCE_METHODS_decl
3791         = generate_descriptor_table (method_list_template,
3792                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
3793                                      size, initlist, protocol);
3794       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3795     }
3796   else
3797     UOBJC_INSTANCE_METHODS_decl = 0;
3798 }
3799
3800 static void
3801 generate_protocol_references (tree plist)
3802 {
3803   tree lproto;
3804
3805   /* Forward declare protocols referenced.  */
3806   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3807     {
3808       tree proto = TREE_VALUE (lproto);
3809
3810       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3811           && PROTOCOL_NAME (proto))
3812         {
3813           if (! PROTOCOL_FORWARD_DECL (proto))
3814             build_protocol_reference (proto);
3815
3816           if (PROTOCOL_LIST (proto))
3817             generate_protocol_references (PROTOCOL_LIST (proto));
3818         }
3819     }
3820 }
3821
3822 /* For each protocol which was referenced either from a @protocol()
3823    expression, or because a class/category implements it (then a
3824    pointer to the protocol is stored in the struct describing the
3825    class/category), we create a statically allocated instance of the
3826    Protocol class.  The code is written in such a way as to generate
3827    as few Protocol objects as possible; we generate a unique Protocol
3828    instance for each protocol, and we don't generate a Protocol
3829    instance if the protocol is never referenced (either from a
3830    @protocol() or from a class/category implementation).  These
3831    statically allocated objects can be referred to via the static
3832    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3833
3834    The statically allocated Protocol objects that we generate here
3835    need to be fixed up at runtime in order to be used: the 'isa'
3836    pointer of the objects need to be set up to point to the 'Protocol'
3837    class, as known at runtime.
3838
3839    The NeXT runtime fixes up all protocols at program startup time,
3840    before main() is entered.  It uses a low-level trick to look up all
3841    those symbols, then loops on them and fixes them up.
3842
3843    The GNU runtime as well fixes up all protocols before user code
3844    from the module is executed; it requires pointers to those symbols
3845    to be put in the objc_symtab (which is then passed as argument to
3846    the function __objc_exec_class() which the compiler sets up to be
3847    executed automatically when the module is loaded); setup of those
3848    Protocol objects happen in two ways in the GNU runtime: all
3849    Protocol objects referred to by a class or category implementation
3850    are fixed up when the class/category is loaded; all Protocol
3851    objects referred to by a @protocol() expression are added by the
3852    compiler to the list of statically allocated instances to fixup
3853    (the same list holding the statically allocated constant string
3854    objects).  Because, as explained above, the compiler generates as
3855    few Protocol objects as possible, some Protocol object might end up
3856    being referenced multiple times when compiled with the GNU runtime,
3857    and end up being fixed up multiple times at runtime inizialization.
3858    But that doesn't hurt, it's just a little inefficient.  */
3859
3860 static void
3861 generate_protocols (void)
3862 {
3863   tree p, encoding;
3864   tree decl;
3865   tree initlist, protocol_name_expr, refs_decl, refs_expr;
3866
3867   /* If a protocol was directly referenced, pull in indirect references.  */
3868   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3869     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3870       generate_protocol_references (PROTOCOL_LIST (p));
3871
3872   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3873     {
3874       tree nst_methods = PROTOCOL_NST_METHODS (p);
3875       tree cls_methods = PROTOCOL_CLS_METHODS (p);
3876
3877       /* If protocol wasn't referenced, don't generate any code.  */
3878       decl = PROTOCOL_FORWARD_DECL (p);
3879
3880       if (!decl)
3881         continue;
3882
3883       /* Make sure we link in the Protocol class.  */
3884       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3885
3886       while (nst_methods)
3887         {
3888           if (! METHOD_ENCODING (nst_methods))
3889             {
3890               encoding = encode_method_prototype (nst_methods);
3891               METHOD_ENCODING (nst_methods) = encoding;
3892             }
3893           nst_methods = TREE_CHAIN (nst_methods);
3894         }
3895
3896       while (cls_methods)
3897         {
3898           if (! METHOD_ENCODING (cls_methods))
3899             {
3900               encoding = encode_method_prototype (cls_methods);
3901               METHOD_ENCODING (cls_methods) = encoding;
3902             }
3903
3904           cls_methods = TREE_CHAIN (cls_methods);
3905         }
3906       generate_method_descriptors (p);
3907
3908       if (PROTOCOL_LIST (p))
3909         refs_decl = generate_protocol_list (p);
3910       else
3911         refs_decl = 0;
3912
3913       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3914       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3915
3916       if (refs_decl)
3917         refs_expr = convert (build_pointer_type (build_pointer_type
3918                                                  (objc_protocol_template)),
3919                              build_unary_op (ADDR_EXPR, refs_decl, 0));
3920       else
3921         refs_expr = build_int_cst (NULL_TREE, 0);
3922
3923       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3924          by generate_method_descriptors, which is called above.  */
3925       initlist = build_protocol_initializer (TREE_TYPE (decl),
3926                                              protocol_name_expr, refs_expr,
3927                                              UOBJC_INSTANCE_METHODS_decl,
3928                                              UOBJC_CLASS_METHODS_decl);
3929       finish_var_decl (decl, initlist);
3930     }
3931 }
3932
3933 static tree
3934 build_protocol_initializer (tree type, tree protocol_name,
3935                             tree protocol_list, tree instance_methods,
3936                             tree class_methods)
3937 {
3938   tree initlist = NULL_TREE, expr;
3939   tree cast_type = build_pointer_type
3940                    (xref_tag (RECORD_TYPE,
3941                               get_identifier (UTAG_CLASS)));
3942
3943   /* Filling the "isa" in with one allows the runtime system to
3944      detect that the version change...should remove before final release.  */
3945
3946   expr = build_int_cst (cast_type, PROTOCOL_VERSION);
3947   initlist = tree_cons (NULL_TREE, expr, initlist);
3948   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3949   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3950
3951   if (!instance_methods)
3952     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
3953   else
3954     {
3955       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3956       initlist = tree_cons (NULL_TREE, expr, initlist);
3957     }
3958
3959   if (!class_methods)
3960     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
3961   else
3962     {
3963       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3964       initlist = tree_cons (NULL_TREE, expr, initlist);
3965     }
3966
3967   return objc_build_constructor (type, nreverse (initlist));
3968 }
3969 \f
3970 /* struct _objc_category {
3971      char *category_name;
3972      char *class_name;
3973      struct _objc_method_list *instance_methods;
3974      struct _objc_method_list *class_methods;
3975      struct _objc_protocol_list *protocols;
3976    };   */
3977
3978 static void
3979 build_category_template (void)
3980 {
3981   tree field_decl, field_decl_chain;
3982
3983   objc_category_template = start_struct (RECORD_TYPE,
3984                                          get_identifier (UTAG_CATEGORY));
3985
3986   /* char *category_name; */
3987   field_decl = create_field_decl (string_type_node, "category_name");
3988   field_decl_chain = field_decl;
3989
3990   /* char *class_name; */
3991   field_decl = create_field_decl (string_type_node, "class_name");
3992   chainon (field_decl_chain, field_decl);
3993
3994   /* struct _objc_method_list *instance_methods; */
3995   field_decl = create_field_decl (build_pointer_type
3996                                   (xref_tag (RECORD_TYPE,
3997                                              get_identifier
3998                                              (UTAG_METHOD_LIST))),
3999                                   "instance_methods");
4000   chainon (field_decl_chain, field_decl);
4001
4002   /* struct _objc_method_list *class_methods; */
4003   field_decl = create_field_decl (build_pointer_type
4004                                   (xref_tag (RECORD_TYPE,
4005                                              get_identifier
4006                                              (UTAG_METHOD_LIST))),
4007                                   "class_methods");
4008   chainon (field_decl_chain, field_decl);
4009
4010   /* struct _objc_protocol **protocol_list; */
4011   field_decl = create_field_decl (build_pointer_type
4012                                   (build_pointer_type
4013                                    (objc_protocol_template)),
4014                                   "protocol_list");
4015   chainon (field_decl_chain, field_decl);
4016
4017   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4018 }
4019
4020 /* struct _objc_selector {
4021      SEL sel_id;
4022      char *sel_type;
4023    }; */
4024
4025 static void
4026 build_selector_template (void)
4027 {
4028
4029   tree field_decl, field_decl_chain;
4030
4031   objc_selector_template
4032     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4033
4034   /* SEL sel_id; */
4035   field_decl = create_field_decl (objc_selector_type, "sel_id");
4036   field_decl_chain = field_decl;
4037
4038   /* char *sel_type; */
4039   field_decl = create_field_decl (string_type_node, "sel_type");
4040   chainon (field_decl_chain, field_decl);
4041
4042   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4043 }
4044
4045 /* struct _objc_class {
4046      struct _objc_class *isa;
4047      struct _objc_class *super_class;
4048      char *name;
4049      long version;
4050      long info;
4051      long instance_size;
4052      struct _objc_ivar_list *ivars;
4053      struct _objc_method_list *methods;
4054      #ifdef __NEXT_RUNTIME__
4055        struct objc_cache *cache;
4056      #else
4057        struct sarray *dtable;
4058        struct _objc_class *subclass_list;
4059        struct _objc_class *sibling_class;
4060      #endif
4061      struct _objc_protocol_list *protocols;
4062      #ifdef __NEXT_RUNTIME__
4063        void *sel_id;
4064      #endif
4065      void *gc_object_type;
4066    };  */
4067
4068 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4069    the NeXT/Apple runtime; still, the compiler must generate them to
4070    maintain backward binary compatibility (and to allow for future
4071    expansion).  */
4072
4073 static void
4074 build_class_template (void)
4075 {
4076   tree field_decl, field_decl_chain;
4077
4078   objc_class_template
4079     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4080
4081   /* struct _objc_class *isa; */
4082   field_decl = create_field_decl (build_pointer_type (objc_class_template),
4083                                   "isa");
4084   field_decl_chain = field_decl;
4085
4086   /* struct _objc_class *super_class; */
4087   field_decl = create_field_decl (build_pointer_type (objc_class_template),
4088                                   "super_class");
4089   chainon (field_decl_chain, field_decl);
4090
4091   /* char *name; */
4092   field_decl = create_field_decl (string_type_node, "name");
4093   chainon (field_decl_chain, field_decl);
4094
4095   /* long version; */
4096   field_decl = create_field_decl (long_integer_type_node, "version");
4097   chainon (field_decl_chain, field_decl);
4098
4099   /* long info; */
4100   field_decl = create_field_decl (long_integer_type_node, "info");
4101   chainon (field_decl_chain, field_decl);
4102
4103   /* long instance_size; */
4104   field_decl = create_field_decl (long_integer_type_node, "instance_size");
4105   chainon (field_decl_chain, field_decl);
4106
4107   /* struct _objc_ivar_list *ivars; */
4108   field_decl = create_field_decl (build_pointer_type
4109                                   (xref_tag (RECORD_TYPE,
4110                                              get_identifier
4111                                              (UTAG_IVAR_LIST))),
4112                                   "ivars");
4113   chainon (field_decl_chain, field_decl);
4114
4115   /* struct _objc_method_list *methods; */
4116   field_decl = create_field_decl (build_pointer_type
4117                                   (xref_tag (RECORD_TYPE,
4118                                              get_identifier
4119                                              (UTAG_METHOD_LIST))),
4120                                   "methods");
4121   chainon (field_decl_chain, field_decl);
4122
4123   if (flag_next_runtime)
4124     {
4125       /* struct objc_cache *cache; */
4126       field_decl = create_field_decl (build_pointer_type
4127                                       (xref_tag (RECORD_TYPE,
4128                                                  get_identifier
4129                                                  ("objc_cache"))),
4130                                       "cache");
4131       chainon (field_decl_chain, field_decl);
4132     }
4133   else
4134     {
4135       /* struct sarray *dtable; */
4136       field_decl = create_field_decl (build_pointer_type
4137                                       (xref_tag (RECORD_TYPE,
4138                                                  get_identifier
4139                                                  ("sarray"))),
4140                                       "dtable");
4141       chainon (field_decl_chain, field_decl);
4142
4143       /* struct objc_class *subclass_list; */
4144       field_decl = create_field_decl (build_pointer_type
4145                                       (objc_class_template),
4146                                       "subclass_list");
4147       chainon (field_decl_chain, field_decl);
4148
4149       /* struct objc_class *sibling_class; */
4150       field_decl = create_field_decl (build_pointer_type
4151                                       (objc_class_template),
4152<