OSDN Git Service

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