OSDN Git Service

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