OSDN Git Service

* gfortran.texi: Use @table @emph instead of @itemize @emph.
[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),
2829                        0, if_stmt);
2830   objc_enter_block ();
2831 }
2832
2833 static tree
2834 objc_build_extract_expr (void)
2835 {
2836   /*    ... = objc_exception_extract(&_stackExceptionData);  */
2837
2838   tree func_params
2839     = tree_cons (NULL_TREE,
2840                  build_unary_op (ADDR_EXPR,
2841                                  TREE_VALUE (objc_stack_exception_data), 0),
2842                  NULL_TREE);
2843
2844   assemble_external (objc_exception_extract_decl);
2845   return build_function_call (objc_exception_extract_decl, func_params);
2846 }
2847
2848 static void
2849 objc_build_try_exit_fragment (void)
2850 {
2851   /* objc_exception_try_exit(&_stackExceptionData); */
2852
2853   tree func_params
2854     = tree_cons (NULL_TREE,
2855                  build_unary_op (ADDR_EXPR,
2856                                  TREE_VALUE (objc_stack_exception_data), 0),
2857                  NULL_TREE);
2858
2859     assemble_external (objc_exception_try_exit_decl);
2860     c_expand_expr_stmt (build_function_call (objc_exception_try_exit_decl,
2861                                              func_params));
2862 }
2863
2864 static void
2865 objc_build_extract_fragment (void)
2866 {
2867   /* } else {
2868       _rethrowException = objc_exception_extract(&_stackExceptionData);
2869      }  */
2870
2871   objc_exit_block ();
2872   c_finish_then ();
2873
2874   c_expand_start_else ();
2875   objc_enter_block ();
2876   c_expand_expr_stmt (build_modify_expr
2877                       (TREE_VALUE (objc_rethrow_exception),
2878                        NOP_EXPR,
2879                        objc_build_extract_expr ()));
2880   objc_exit_block ();
2881   c_finish_else ();
2882   c_expand_end_cond ();
2883   if_nesting_count--;
2884 }
2885
2886 tree
2887 objc_build_try_prologue (void)
2888 {
2889   /* { // new scope
2890        struct _objc_exception_data _stackExceptionData;
2891        volatile id _rethrowException = nil;
2892        { // begin TRY-CATCH scope
2893          objc_exception_try_enter(&_stackExceptionData);
2894          if (!_setjmp(&_stackExceptionData.buf)) {  */
2895
2896   tree try_catch_block;
2897
2898   if (!flag_objc_exceptions)
2899     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
2900
2901   objc_mark_locals_volatile ((void *)(exc_binding_stack
2902                                       ? exc_binding_stack->val
2903                                       : 0));
2904   objc_enter_block ();
2905   objc_stack_exception_data
2906     = tree_cons (NULL_TREE,
2907                  objc_declare_variable (RID_AUTO,
2908                                         get_identifier (UTAG_EXCDATA_VAR),
2909                                         xref_tag (RECORD_TYPE,
2910                                                   get_identifier (UTAG_EXCDATA)),
2911                                         NULL_TREE),
2912                  objc_stack_exception_data);
2913   objc_rethrow_exception = tree_cons (NULL_TREE,
2914                                       objc_declare_variable (RID_VOLATILE,
2915                                                              get_identifier (UTAG_RETHROWEXC_VAR),
2916                                                              id_type,
2917                                                              build_int_2 (0, 0)),
2918                                       objc_rethrow_exception);
2919
2920   try_catch_block = objc_enter_block ();
2921   val_stack_push (&exc_binding_stack, (long) get_current_scope ());
2922   objc_build_try_enter_fragment ();
2923
2924   return try_catch_block;
2925 }
2926
2927 void
2928 objc_build_try_epilogue (int also_catch_prologue)
2929 {
2930   if (also_catch_prologue)
2931     {
2932       /* } else {
2933            register id _caughtException = objc_exception_extract( &_stackExceptionData);
2934            objc_exception_try_enter(&_stackExceptionData);
2935            if(!_setjmp(&_stackExceptionData.buf)) {
2936              if (0) {  */
2937
2938       tree if_stmt;
2939
2940       objc_exit_block ();
2941       c_finish_then ();
2942                 
2943       c_expand_start_else ();
2944       objc_enter_block ();
2945       objc_caught_exception
2946         = tree_cons (NULL_TREE,
2947                      objc_declare_variable (RID_REGISTER,
2948                                             get_identifier (UTAG_CAUGHTEXC_VAR),
2949                                             id_type,
2950                                             objc_build_extract_expr ()),
2951                      objc_caught_exception);
2952       objc_build_try_enter_fragment ();
2953       val_stack_push (&catch_count_stack, 1);
2954       if_stmt = c_begin_if_stmt ();
2955       if_nesting_count++;
2956       c_expand_start_cond ((*lang_hooks.truthvalue_conversion) (boolean_false_node),
2957                            0, if_stmt);
2958       objc_enter_block ();
2959
2960       /* Start a new chain of @catch statements for this @try.  */
2961       objc_catch_type = tree_cons (objc_catch_type, NULL_TREE, NULL_TREE);
2962     }
2963   else
2964     {  /* !also_catch_prologue */
2965
2966       /* } else {
2967            _rethrowException = objc_exception_extract( &_stackExceptionData);
2968          }
2969        }  */
2970       objc_build_extract_fragment ();
2971       objc_exit_block ();
2972     }
2973 }
2974
2975 void
2976 objc_build_catch_stmt (tree catch_expr)
2977 {
2978   /* } else if (objc_exception_match(objc_get_class("SomeClass"), _caughtException)) {
2979        register SomeClass *e = _caughtException;  */
2980
2981   tree if_stmt, cond, func_params, prev_catch, var_name, var_type;
2982   int catch_id;
2983
2984 #ifndef OBJCPLUS
2985   /* Yet another C/C++ impedance mismatch.  */
2986   catch_expr = TREE_PURPOSE (catch_expr);
2987 #endif
2988
2989   var_name = TREE_VALUE (catch_expr);
2990   var_type = TREE_VALUE (TREE_PURPOSE (catch_expr));
2991   if (TREE_CODE (var_name) == INDIRECT_REF)
2992     var_name = TREE_OPERAND (var_name, 0);
2993   if (TREE_CODE (var_type) == TYPE_DECL
2994       || TREE_CODE (var_type) == POINTER_TYPE)
2995     var_type = TREE_TYPE (var_type);
2996   catch_id = (var_type == TREE_TYPE (id_type));
2997
2998   if (!flag_objc_exceptions)
2999     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3000
3001   if (!(catch_id || TYPED_OBJECT (var_type)))
3002     fatal_error ("`@catch' parameter is not a known Objective-C class type");
3003
3004   /* Examine previous @catch clauses for the current @try block for
3005      superclasses of the 'var_type' class.  */
3006   for (prev_catch = objc_catch_type; TREE_VALUE (prev_catch);
3007        prev_catch = TREE_CHAIN (prev_catch))
3008     {
3009       if (TREE_VALUE (prev_catch) == TREE_TYPE (id_type))
3010         {
3011           warning ("Exception already handled by preceding `@catch(id)'");
3012           break;
3013         }
3014       else if (!catch_id
3015                && objc_comptypes (TREE_VALUE (prev_catch), var_type, 0) == 1)
3016         warning ("Exception of type `%s *' already handled by `@catch (%s *)'",
3017                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (var_type)),
3018                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_VALUE (prev_catch))));
3019     }
3020
3021   objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
3022
3023   objc_exit_block ();
3024   c_finish_then ();
3025
3026   c_expand_start_else ();
3027   catch_count_stack->val++;
3028   if_stmt = c_begin_if_stmt ();
3029   if_nesting_count++;
3030
3031   if (catch_id)
3032     cond = integer_one_node;
3033   else
3034     {
3035       cond = get_class_reference (OBJC_TYPE_NAME (var_type));
3036         
3037       func_params
3038         = tree_cons (NULL_TREE, cond,
3039                      tree_cons (NULL_TREE,
3040                                 TREE_VALUE (objc_caught_exception),
3041                                 NULL_TREE));
3042       assemble_external (objc_exception_match_decl);
3043       cond = build_function_call (objc_exception_match_decl, func_params);
3044     }
3045
3046   c_expand_start_cond ((*lang_hooks.truthvalue_conversion) (cond),
3047                        0, if_stmt);
3048   objc_enter_block ();
3049   objc_declare_variable (RID_REGISTER, var_name,
3050                          build_pointer_type (var_type),
3051                          TREE_VALUE (objc_caught_exception));
3052 }
3053
3054 void
3055 objc_build_catch_epilogue (void)
3056 {
3057   /*     } else {
3058            _rethrowException = _caughtException;
3059            objc_exception_try_exit(&_stackExceptionData);
3060          }
3061        } else {
3062          _rethrowException = objc_exception_extract(&_stackExceptionData);
3063        }
3064      }
3065    } // end TRY-CATCH scope
3066   */
3067
3068   objc_exit_block ();
3069   c_finish_then ();
3070
3071   c_expand_start_else ();
3072   objc_enter_block ();
3073   c_expand_expr_stmt
3074     (build_modify_expr
3075      (TREE_VALUE (objc_rethrow_exception),
3076       NOP_EXPR,
3077       TREE_VALUE (objc_caught_exception)));
3078   objc_build_try_exit_fragment ();      
3079   objc_exit_block ();
3080   while (catch_count_stack->val--)
3081     {
3082       c_finish_else ();         /* close off all the nested ifs ! */
3083       c_expand_end_cond ();
3084       if_nesting_count--;
3085     }
3086   val_stack_pop (&catch_count_stack);
3087   objc_caught_exception = TREE_CHAIN (objc_caught_exception);
3088
3089   objc_build_extract_fragment ();
3090
3091   objc_exit_block ();
3092   c_finish_else ();
3093   c_expand_end_cond ();
3094   if_nesting_count--;
3095   objc_exit_block ();
3096
3097   /* Return to enclosing chain of @catch statements (if any).  */
3098   while (TREE_VALUE (objc_catch_type))
3099     objc_catch_type = TREE_CHAIN (objc_catch_type);
3100   objc_catch_type = TREE_PURPOSE (objc_catch_type);
3101 }
3102
3103 tree
3104 objc_build_finally_prologue (void)
3105 {
3106   /* { // begin FINALLY scope
3107        if (!_rethrowException) {
3108          objc_exception_try_exit(&_stackExceptionData);
3109        }  */
3110
3111   tree blk = objc_enter_block ();
3112
3113   tree if_stmt = c_begin_if_stmt ();
3114   if_nesting_count++;
3115
3116   c_expand_start_cond ((*lang_hooks.truthvalue_conversion)
3117                        (build_unary_op
3118                         (TRUTH_NOT_EXPR,
3119                          TREE_VALUE (objc_rethrow_exception), 0)),
3120                        0, if_stmt);
3121   objc_enter_block ();
3122   objc_build_try_exit_fragment ();
3123   objc_exit_block ();
3124   c_finish_then ();
3125   c_expand_end_cond ();
3126   if_nesting_count--;
3127
3128   return blk;
3129 }
3130
3131 tree
3132 objc_build_finally_epilogue (void)
3133 {
3134   /*    if (_rethrowException) {
3135           objc_exception_throw(_rethrowException);
3136         }
3137       } // end FINALLY scope
3138     } */
3139
3140   tree if_stmt = c_begin_if_stmt ();
3141   if_nesting_count++;
3142
3143   c_expand_start_cond
3144     ((*lang_hooks.truthvalue_conversion) (TREE_VALUE (objc_rethrow_exception)),
3145      0, if_stmt);
3146   objc_enter_block ();
3147   objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
3148   objc_exit_block ();
3149   c_finish_then ();
3150   c_expand_end_cond ();
3151   if_nesting_count--;
3152
3153   objc_exit_block ();
3154   objc_rethrow_exception = TREE_CHAIN (objc_rethrow_exception);
3155   objc_stack_exception_data = TREE_CHAIN (objc_stack_exception_data);
3156
3157   val_stack_pop (&exc_binding_stack);
3158   return objc_exit_block ();
3159 }
3160
3161 tree
3162 objc_build_try_catch_finally_stmt (int has_catch, int has_finally)
3163 {
3164   /* NB: The operative assumption here is that TRY_FINALLY_EXPR will
3165      deal with all exits from 'try_catch_blk' and route them through
3166      'finally_blk'.  */
3167   tree outer_blk = objc_build_finally_epilogue ();
3168   tree prec_stmt = TREE_CHAIN (TREE_CHAIN (COMPOUND_BODY (outer_blk)));
3169   tree try_catch_blk = TREE_CHAIN (prec_stmt), try_catch_expr;
3170   tree finally_blk = TREE_CHAIN (try_catch_blk), finally_expr;
3171   tree succ_stmt = TREE_CHAIN (finally_blk);
3172   tree try_finally_stmt, try_finally_expr;
3173
3174   if (!flag_objc_exceptions)
3175     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3176
3177   /* It is an error to have a @try block without a @catch and/or @finally
3178      (even though sensible code can be generated nonetheless).  */
3179
3180   if (!has_catch && !has_finally)
3181     error ("`@try' without `@catch' or `@finally'");
3182
3183   /* We shall now do something truly disgusting.  We shall remove the
3184      'try_catch_blk' and 'finally_blk' from the 'outer_blk' statement
3185      chain, and replace them with a TRY_FINALLY_EXPR statement!  If
3186      this doesn't work, we will have to learn (from Per/gcj) how to
3187      construct the 'outer_blk' lazily.  */
3188
3189   TREE_CHAIN (try_catch_blk) = TREE_CHAIN (finally_blk) = NULL_TREE;
3190   try_catch_expr = build1 (STMT_EXPR, void_type_node, try_catch_blk);
3191   TREE_SIDE_EFFECTS (try_catch_expr) = 1;
3192   finally_expr = build1 (STMT_EXPR, void_type_node, finally_blk);
3193   TREE_SIDE_EFFECTS (finally_expr) = 1;
3194   try_finally_expr = build (TRY_FINALLY_EXPR, void_type_node, try_catch_expr,
3195                             finally_expr);
3196   TREE_SIDE_EFFECTS (try_finally_expr) = 1;
3197   try_finally_stmt = build_stmt (EXPR_STMT, try_finally_expr);
3198   TREE_CHAIN (prec_stmt) = try_finally_stmt;
3199   TREE_CHAIN (try_finally_stmt) = succ_stmt;
3200         
3201   return outer_blk;  /* the whole enchilada */
3202 }
3203
3204 void
3205 objc_build_synchronized_prologue (tree sync_expr)
3206 {
3207   /* {
3208        id _eval_once = <sync_expr>;
3209        @try {
3210               objc_sync_enter( _eval_once );  */
3211
3212   tree func_params;
3213
3214   if (!flag_objc_exceptions)
3215     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3216
3217   objc_enter_block ();
3218   objc_eval_once
3219     = tree_cons (NULL_TREE,
3220                  objc_declare_variable (RID_AUTO,
3221                                         get_identifier (UTAG_EVALONCE_VAR),
3222                                         id_type,
3223                                         sync_expr),
3224                  objc_eval_once);
3225   objc_build_try_prologue ();
3226   objc_enter_block ();  
3227   func_params = tree_cons (NULL_TREE,
3228                            TREE_VALUE (objc_eval_once),
3229                            NULL_TREE);
3230
3231   assemble_external (objc_sync_enter_decl);
3232   c_expand_expr_stmt (build_function_call
3233                       (objc_sync_enter_decl, func_params));
3234 }
3235
3236 tree
3237 objc_build_synchronized_epilogue (void)
3238 {
3239   /* }
3240        @finally {
3241          objc_sync_exit( _eval_once );
3242        }
3243      }  */
3244
3245   tree func_params;
3246
3247   objc_exit_block ();   
3248   objc_build_try_epilogue (0);
3249   objc_build_finally_prologue ();
3250   func_params = tree_cons (NULL_TREE, TREE_VALUE (objc_eval_once),
3251                            NULL_TREE);
3252
3253   assemble_external (objc_sync_exit_decl);
3254   c_expand_expr_stmt (build_function_call (objc_sync_exit_decl,
3255                                            func_params));
3256   objc_build_try_catch_finally_stmt (0, 1);
3257
3258   return objc_exit_block ();
3259 }
3260
3261 /* Predefine the following data type:
3262
3263    struct _objc_exception_data
3264    {
3265      int buf[_JBLEN];
3266      void *pointers[4];
3267    }; */
3268
3269 /* The following yuckiness should prevent users from having to #include
3270    <setjmp.h> in their code... */
3271
3272 #ifdef TARGET_POWERPC
3273 /* snarfed from /usr/include/ppc/setjmp.h */
3274 #define _JBLEN (26 + 36 + 129 + 1)
3275 #else
3276 /* snarfed from /usr/include/i386/{setjmp,signal}.h */
3277 #define _JBLEN 18
3278 #endif
3279
3280 static void
3281 build_objc_exception_stuff (void)
3282 {
3283   tree field_decl, field_decl_chain, index, temp_type;
3284
3285   /* Suppress outputting debug symbols, because
3286      dbxout_init hasn't been called yet.  */
3287   enum debug_info_type save_write_symbols = write_symbols;
3288   const struct gcc_debug_hooks *save_hooks = debug_hooks;
3289
3290   write_symbols = NO_DEBUG;
3291   debug_hooks = &do_nothing_debug_hooks;
3292   objc_exception_data_template
3293     = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3294
3295   /* int buf[_JBLEN]; */
3296
3297   index = build_index_type (build_int_2 (_JBLEN - 1, 0));
3298   field_decl = create_builtin_decl (FIELD_DECL,
3299                                     build_array_type (integer_type_node, index),
3300                                     "buf");
3301   field_decl_chain = field_decl;
3302
3303   /* void *pointers[4]; */
3304
3305   index = build_index_type (build_int_2 (4 - 1, 0));
3306   field_decl = create_builtin_decl (FIELD_DECL,
3307                                     build_array_type (ptr_type_node, index),
3308                                     "pointers");
3309   chainon (field_decl_chain, field_decl);
3310
3311   finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3312
3313   /* int _setjmp(...); */
3314   /* If the user includes <setjmp.h>, this shall be superseded by
3315      'int _setjmp(jmp_buf);' */
3316   temp_type = build_function_type (integer_type_node, NULL_TREE);
3317   objc_setjmp_decl
3318     = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3319
3320   /* id objc_exception_extract(struct _objc_exception_data *); */
3321   temp_type
3322     = build_function_type (id_type,
3323                            tree_cons (NULL_TREE,
3324                                       build_pointer_type (objc_exception_data_template),
3325                                       void_list_node));
3326   objc_exception_extract_decl
3327     = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3328   /* void objc_exception_try_enter(struct _objc_exception_data *); */
3329   /* void objc_exception_try_exit(struct _objc_exception_data *); */
3330   temp_type
3331     = build_function_type (void_type_node,
3332                            tree_cons (NULL_TREE,
3333                                       build_pointer_type (objc_exception_data_template),
3334                                       void_list_node));
3335   objc_exception_try_enter_decl
3336     = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3337   objc_exception_try_exit_decl
3338     = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3339   /* void objc_exception_throw(id) __attribute__((noreturn)); */
3340   /* void objc_sync_enter(id); */
3341   /* void objc_sync_exit(id); */
3342   temp_type = build_function_type (void_type_node,
3343                                    tree_cons (NULL_TREE, id_type,
3344                                               void_list_node));
3345   objc_exception_throw_decl
3346     = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3347   DECL_ATTRIBUTES (objc_exception_throw_decl)
3348     = tree_cons (get_identifier ("noreturn"), NULL_TREE, NULL_TREE);
3349   objc_sync_enter_decl
3350     = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3351   objc_sync_exit_decl
3352     = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3353   /* int objc_exception_match(id, id); */
3354   temp_type = build_function_type (integer_type_node,
3355                                    tree_cons (NULL_TREE, id_type,
3356                                               tree_cons (NULL_TREE, id_type,
3357                                                          void_list_node)));
3358   objc_exception_match_decl
3359     = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3360         
3361   write_symbols = save_write_symbols;
3362   debug_hooks = save_hooks;
3363 }
3364
3365 /* struct <classname> {
3366      struct objc_class *isa;
3367      ...
3368    };  */
3369
3370 static tree
3371 build_private_template (tree class)
3372 {
3373   tree ivar_context;
3374
3375   if (CLASS_STATIC_TEMPLATE (class))
3376     {
3377       uprivate_record = CLASS_STATIC_TEMPLATE (class);
3378       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3379     }
3380   else
3381     {
3382       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3383       ivar_context = get_class_ivars (class, 0);
3384
3385       finish_struct (uprivate_record, ivar_context, NULL_TREE);
3386
3387       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3388
3389       /* mark this record as class template - for class type checking */
3390       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3391     }
3392
3393   instance_type
3394     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3395                                                       uprivate_record),
3396                                      build1 (INDIRECT_REF, NULL_TREE,
3397                                              NULL_TREE)));
3398
3399   return ivar_context;
3400 }
3401 \f
3402 /* Begin code generation for protocols...  */
3403
3404 /* struct objc_protocol {
3405      char *protocol_name;
3406      struct objc_protocol **protocol_list;
3407      struct objc_method_desc *instance_methods;
3408      struct objc_method_desc *class_methods;
3409    };  */
3410
3411 static tree
3412 build_protocol_template (void)
3413 {
3414   tree decl_specs, field_decl, field_decl_chain;
3415   tree template;
3416
3417   template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
3418
3419   /* struct objc_class *isa; */
3420
3421   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3422                                         get_identifier (UTAG_CLASS)));
3423   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3424   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3425   field_decl_chain = field_decl;
3426
3427   /* char *protocol_name; */
3428
3429   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3430   field_decl
3431     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
3432   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3433   chainon (field_decl_chain, field_decl);
3434
3435   /* struct objc_protocol **protocol_list; */
3436
3437   decl_specs = build_tree_list (NULL_TREE, template);
3438   field_decl
3439     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3440   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3441   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3442   chainon (field_decl_chain, field_decl);
3443
3444   /* struct objc_method_list *instance_methods; */
3445
3446   decl_specs
3447     = build_tree_list (NULL_TREE,
3448                        xref_tag (RECORD_TYPE,
3449                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3450   field_decl
3451     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3452   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3453   chainon (field_decl_chain, field_decl);
3454
3455   /* struct objc_method_list *class_methods; */
3456
3457   decl_specs
3458     = build_tree_list (NULL_TREE,
3459                        xref_tag (RECORD_TYPE,
3460                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3461   field_decl
3462     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3463   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3464   chainon (field_decl_chain, field_decl);
3465
3466   return finish_struct (template, field_decl_chain, NULL_TREE);
3467 }
3468
3469 static tree
3470 build_descriptor_table_initializer (tree type, tree entries)
3471 {
3472   tree initlist = NULL_TREE;
3473
3474   do
3475     {
3476       tree eltlist = NULL_TREE;
3477
3478       eltlist
3479         = tree_cons (NULL_TREE,
3480                      build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3481       eltlist
3482         = tree_cons (NULL_TREE,
3483                      add_objc_string (METHOD_ENCODING (entries),
3484                                       meth_var_types),
3485                      eltlist);
3486
3487       initlist
3488         = tree_cons (NULL_TREE,
3489                      objc_build_constructor (type, nreverse (eltlist)),
3490                      initlist);
3491
3492       entries = TREE_CHAIN (entries);
3493     }
3494   while (entries);
3495
3496   return objc_build_constructor (build_array_type (type, 0),
3497                                  nreverse (initlist));
3498 }
3499
3500 /* struct objc_method_prototype_list {
3501      int count;
3502      struct objc_method_prototype {
3503         SEL name;
3504         char *types;
3505      } list[1];
3506    };  */
3507
3508 static tree
3509 build_method_prototype_list_template (tree list_type, int size)
3510 {
3511   tree objc_ivar_list_record;
3512   tree decl_specs, field_decl, field_decl_chain;
3513
3514   /* Generate an unnamed struct definition.  */
3515
3516   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3517
3518   /* int method_count; */
3519
3520   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3521   field_decl = get_identifier ("method_count");
3522   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3523   field_decl_chain = field_decl;
3524
3525   /* struct objc_method method_list[]; */
3526
3527   decl_specs = build_tree_list (NULL_TREE, list_type);
3528   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3529                          build_int_2 (size, 0));
3530   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3531   chainon (field_decl_chain, field_decl);
3532
3533   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3534
3535   return objc_ivar_list_record;
3536 }
3537
3538 static tree
3539 build_method_prototype_template (void)
3540 {
3541   tree proto_record;
3542   tree decl_specs, field_decl, field_decl_chain;
3543
3544   proto_record
3545     = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
3546
3547   /* struct objc_selector *_cmd; */
3548   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
3549                           get_identifier (TAG_SELECTOR)), NULL_TREE);
3550   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3551   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3552   field_decl_chain = field_decl;
3553
3554   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3555   field_decl
3556     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
3557   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3558   chainon (field_decl_chain, field_decl);
3559
3560   finish_struct (proto_record, field_decl_chain, NULL_TREE);
3561
3562   return proto_record;
3563 }
3564
3565 static tree
3566 objc_method_parm_type (tree type)
3567 {
3568   type = groktypename (TREE_TYPE (type));
3569   if (TREE_CODE (type) == TYPE_DECL)
3570     type = TREE_TYPE (type);
3571   return TYPE_MAIN_VARIANT (type);
3572 }
3573
3574 static int
3575 objc_encoded_type_size (tree type)
3576 {
3577   int sz = int_size_in_bytes (type);
3578
3579   /* Make all integer and enum types at least as large
3580      as an int.  */
3581   if (sz > 0 && (TREE_CODE (type) == INTEGER_TYPE
3582                  || TREE_CODE (type) == BOOLEAN_TYPE
3583                  || TREE_CODE (type) == ENUMERAL_TYPE))
3584     sz = MAX (sz, int_size_in_bytes (integer_type_node));
3585   /* Treat arrays as pointers, since that's how they're
3586      passed in.  */
3587   else if (TREE_CODE (type) == ARRAY_TYPE)
3588     sz = int_size_in_bytes (ptr_type_node);
3589   return sz;
3590 }
3591
3592 static tree
3593 encode_method_prototype (tree method_decl)
3594 {
3595   tree parms;
3596   int parm_offset, i;
3597   char buf[40];
3598   tree result;
3599
3600   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
3601   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
3602
3603   /* Encode return type.  */
3604   encode_type (objc_method_parm_type (method_decl),
3605                obstack_object_size (&util_obstack),
3606                OBJC_ENCODE_INLINE_DEFS);
3607
3608   /* Stack size.  */
3609   /* The first two arguments (self and _cmd) are pointers; account for
3610      their size.  */
3611   i = int_size_in_bytes (ptr_type_node);
3612   parm_offset = 2 * i;
3613   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3614        parms = TREE_CHAIN (parms))
3615     {
3616       tree type = objc_method_parm_type (parms);
3617       int sz = objc_encoded_type_size (type);
3618
3619       /* If a type size is not known, bail out.  */
3620       if (sz < 0)
3621         {
3622           error ("%Jtype '%D' does not have a known size",
3623                  type, type);
3624           /* Pretend that the encoding succeeded; the compilation will
3625              fail nevertheless.  */
3626           goto finish_encoding;
3627         }
3628       parm_offset += sz;
3629     }
3630
3631   sprintf (buf, "%d@0:%d", parm_offset, i);
3632   obstack_grow (&util_obstack, buf, strlen (buf));
3633
3634   /* Argument types.  */
3635   parm_offset = 2 * i;
3636   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3637        parms = TREE_CHAIN (parms))
3638     {
3639       tree type = objc_method_parm_type (parms);
3640
3641       /* Process argument qualifiers for user supplied arguments.  */
3642       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
3643
3644       /* Type.  */
3645       encode_type (type, obstack_object_size (&util_obstack),
3646                    OBJC_ENCODE_INLINE_DEFS);
3647
3648       /* Compute offset.  */
3649       sprintf (buf, "%d", parm_offset);
3650       parm_offset += objc_encoded_type_size (type);
3651
3652       obstack_grow (&util_obstack, buf, strlen (buf));
3653     }
3654
3655   finish_encoding:
3656   obstack_1grow (&util_obstack, '\0');
3657   result = get_identifier (obstack_finish (&util_obstack));
3658   obstack_free (&util_obstack, util_firstobj);
3659   return result;
3660 }
3661
3662 static tree
3663 generate_descriptor_table (tree type, const char *name, int size, tree list,
3664                            tree proto)
3665 {
3666   tree sc_spec, decl_specs, decl, initlist;
3667
3668   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3669   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3670
3671   decl = start_decl (synth_id_with_class_suffix (name, proto),
3672                      decl_specs, 1, NULL_TREE);
3673   DECL_CONTEXT (decl) = NULL_TREE;
3674
3675   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3676   initlist = tree_cons (NULL_TREE, list, initlist);
3677
3678   finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
3679                NULL_TREE);
3680
3681   return decl;
3682 }
3683
3684 static void
3685 generate_method_descriptors (tree protocol)
3686 {
3687   tree initlist, chain, method_list_template;
3688   tree cast, variable_length_type;
3689   int size;
3690
3691   if (!objc_method_prototype_template)
3692     objc_method_prototype_template = build_method_prototype_template ();
3693
3694   cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3695                                 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
3696                           NULL_TREE);
3697   variable_length_type = groktypename (cast);
3698
3699   chain = PROTOCOL_CLS_METHODS (protocol);
3700   if (chain)
3701     {
3702       size = list_length (chain);
3703
3704       method_list_template
3705         = build_method_prototype_list_template (objc_method_prototype_template,
3706                                                 size);
3707
3708       initlist
3709         = build_descriptor_table_initializer (objc_method_prototype_template,
3710                                               chain);
3711
3712       UOBJC_CLASS_METHODS_decl
3713         = generate_descriptor_table (method_list_template,
3714                                      "_OBJC_PROTOCOL_CLASS_METHODS",
3715                                      size, initlist, protocol);
3716       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3717     }
3718   else
3719     UOBJC_CLASS_METHODS_decl = 0;
3720
3721   chain = PROTOCOL_NST_METHODS (protocol);
3722   if (chain)
3723     {
3724       size = list_length (chain);
3725
3726       method_list_template
3727         = build_method_prototype_list_template (objc_method_prototype_template,
3728                                                 size);
3729       initlist
3730         = build_descriptor_table_initializer (objc_method_prototype_template,
3731                                               chain);
3732
3733       UOBJC_INSTANCE_METHODS_decl
3734         = generate_descriptor_table (method_list_template,
3735                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
3736                                      size, initlist, protocol);
3737       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3738     }
3739   else
3740     UOBJC_INSTANCE_METHODS_decl = 0;
3741 }
3742
3743 static void
3744 generate_protocol_references (tree plist)
3745 {
3746   tree lproto;
3747
3748   /* Forward declare protocols referenced.  */
3749   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3750     {
3751       tree proto = TREE_VALUE (lproto);
3752
3753       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3754           && PROTOCOL_NAME (proto))
3755         {
3756           if (! PROTOCOL_FORWARD_DECL (proto))
3757             build_protocol_reference (proto);
3758
3759           if (PROTOCOL_LIST (proto))
3760             generate_protocol_references (PROTOCOL_LIST (proto));
3761         }
3762     }
3763 }
3764
3765 /* For each protocol which was referenced either from a @protocol()
3766    expression, or because a class/category implements it (then a
3767    pointer to the protocol is stored in the struct describing the
3768    class/category), we create a statically allocated instance of the
3769    Protocol class.  The code is written in such a way as to generate
3770    as few Protocol objects as possible; we generate a unique Protocol
3771    instance for each protocol, and we don't generate a Protocol
3772    instance if the protocol is never referenced (either from a
3773    @protocol() or from a class/category implementation).  These
3774    statically allocated objects can be referred to via the static
3775    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3776
3777    The statically allocated Protocol objects that we generate here
3778    need to be fixed up at runtime in order to be used: the 'isa'
3779    pointer of the objects need to be set up to point to the 'Protocol'
3780    class, as known at runtime.
3781
3782    The NeXT runtime fixes up all protocols at program startup time,
3783    before main() is entered.  It uses a low-level trick to look up all
3784    those symbols, then loops on them and fixes them up.
3785
3786    The GNU runtime as well fixes up all protocols before user code
3787    from the module is executed; it requires pointers to those symbols
3788    to be put in the objc_symtab (which is then passed as argument to
3789    the function __objc_exec_class() which the compiler sets up to be
3790    executed automatically when the module is loaded); setup of those
3791    Protocol objects happen in two ways in the GNU runtime: all
3792    Protocol objects referred to by a class or category implementation
3793    are fixed up when the class/category is loaded; all Protocol
3794    objects referred to by a @protocol() expression are added by the
3795    compiler to the list of statically allocated instances to fixup
3796    (the same list holding the statically allocated constant string
3797    objects).  Because, as explained above, the compiler generates as
3798    few Protocol objects as possible, some Protocol object might end up
3799    being referenced multiple times when compiled with the GNU runtime,
3800    and end up being fixed up multiple times at runtime inizialization.
3801    But that doesn't hurt, it's just a little inefficient.  */
3802
3803 static void
3804 generate_protocols (void)
3805 {
3806   tree p, encoding;
3807   tree sc_spec, decl_specs, decl;
3808   tree initlist, protocol_name_expr, refs_decl, refs_expr;
3809   tree cast_type2;
3810
3811   if (! objc_protocol_template)
3812     objc_protocol_template = build_protocol_template ();
3813
3814   /* If a protocol was directly referenced, pull in indirect references.  */
3815   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3816     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3817       generate_protocol_references (PROTOCOL_LIST (p));
3818
3819   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3820     {
3821       tree nst_methods = PROTOCOL_NST_METHODS (p);
3822       tree cls_methods = PROTOCOL_CLS_METHODS (p);
3823
3824       /* If protocol wasn't referenced, don't generate any code.  */
3825       if (! PROTOCOL_FORWARD_DECL (p))
3826         continue;
3827
3828       /* Make sure we link in the Protocol class.  */
3829       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3830
3831       while (nst_methods)
3832         {
3833           if (! METHOD_ENCODING (nst_methods))
3834             {
3835               encoding = encode_method_prototype (nst_methods);
3836               METHOD_ENCODING (nst_methods) = encoding;
3837             }
3838           nst_methods = TREE_CHAIN (nst_methods);
3839         }
3840
3841       while (cls_methods)
3842         {
3843           if (! METHOD_ENCODING (cls_methods))
3844             {
3845               encoding = encode_method_prototype (cls_methods);
3846               METHOD_ENCODING (cls_methods) = encoding;
3847             }
3848
3849           cls_methods = TREE_CHAIN (cls_methods);
3850         }
3851       generate_method_descriptors (p);
3852
3853       if (PROTOCOL_LIST (p))
3854         refs_decl = generate_protocol_list (p);
3855       else
3856         refs_decl = 0;
3857
3858       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3859
3860       sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3861                            NULL_TREE);
3862       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3863
3864       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3865                          decl_specs, 1, NULL_TREE);
3866
3867       DECL_CONTEXT (decl) = NULL_TREE;
3868
3869       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3870
3871       if (refs_decl)
3872         {
3873           cast_type2
3874             = groktypename
3875                 (build_tree_list (build_tree_list (NULL_TREE,
3876                                                    objc_protocol_template),
3877                                   build1 (INDIRECT_REF, NULL_TREE,
3878                                           build1 (INDIRECT_REF, NULL_TREE,
3879                                                   NULL_TREE))));
3880
3881           refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3882           TREE_TYPE (refs_expr) = cast_type2;
3883         }
3884       else
3885         refs_expr = build_int_2 (0, 0);
3886
3887       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3888          by generate_method_descriptors, which is called above.  */
3889       initlist = build_protocol_initializer (TREE_TYPE (decl),
3890                                              protocol_name_expr, refs_expr,
3891                                              UOBJC_INSTANCE_METHODS_decl,
3892                                              UOBJC_CLASS_METHODS_decl);
3893       finish_decl (decl, initlist, NULL_TREE);
3894
3895       /* Mark the decl as used to avoid "defined but not used" warning.  */
3896       TREE_USED (decl) = 1;
3897     }
3898 }
3899
3900 static tree
3901 build_protocol_initializer (tree type, tree protocol_name,
3902                             tree protocol_list, tree instance_methods,
3903                             tree class_methods)
3904 {
3905   tree initlist = NULL_TREE, expr;
3906   tree cast_type;
3907
3908   cast_type = groktypename
3909     (build_tree_list
3910      (build_tree_list (NULL_TREE,
3911                        xref_tag (RECORD_TYPE,
3912                                  get_identifier (UTAG_CLASS))),
3913       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3914
3915   /* Filling the "isa" in with one allows the runtime system to
3916      detect that the version change...should remove before final release.  */
3917
3918   expr = build_int_2 (PROTOCOL_VERSION, 0);
3919   TREE_TYPE (expr) = cast_type;
3920   initlist = tree_cons (NULL_TREE, expr, initlist);
3921   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3922   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3923
3924   if (!instance_methods)
3925     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3926   else
3927     {
3928       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3929       initlist = tree_cons (NULL_TREE, expr, initlist);
3930     }
3931
3932   if (!class_methods)
3933     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3934   else
3935     {
3936       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3937       initlist = tree_cons (NULL_TREE, expr, initlist);
3938     }
3939
3940   return objc_build_constructor (type, nreverse (initlist));
3941 }
3942 \f
3943 /* struct objc_category {
3944      char *category_name;
3945      char *class_name;
3946      struct objc_method_list *instance_methods;
3947      struct objc_method_list *class_methods;
3948      struct objc_protocol_list *protocols;
3949    };   */
3950
3951 static void
3952 build_category_template (void)
3953 {
3954   tree decl_specs, field_decl, field_decl_chain;
3955
3956   objc_category_template = start_struct (RECORD_TYPE,
3957                                          get_identifier (UTAG_CATEGORY));
3958   /* char *category_name; */
3959
3960   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3961   field_decl
3962     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3963   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3964   field_decl_chain = field_decl;
3965
3966   /* char *class_name; */
3967
3968   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3969   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3970   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3971   chainon (field_decl_chain, field_decl);
3972
3973   /* struct objc_method_list *instance_methods; */
3974
3975   decl_specs = build_tree_list (NULL_TREE,
3976                                 xref_tag (RECORD_TYPE,
3977                                           get_identifier (UTAG_METHOD_LIST)));
3978   field_decl
3979     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3980   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3981   chainon (field_decl_chain, field_decl);
3982
3983   /* struct objc_method_list *class_methods; */
3984
3985   decl_specs = build_tree_list (NULL_TREE,
3986                                 xref_tag (RECORD_TYPE,
3987                                           get_identifier (UTAG_METHOD_LIST)));
3988   field_decl
3989     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3990   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3991   chainon (field_decl_chain, field_decl);
3992
3993   /* struct objc_protocol **protocol_list; */
3994
3995   decl_specs = build_tree_list (NULL_TREE,
3996                                 xref_tag (RECORD_TYPE,
3997                                           get_identifier (UTAG_PROTOCOL)));
3998   field_decl
3999     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4000   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4001   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4002   chainon (field_decl_chain, field_decl);
4003
4004   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4005 }
4006
4007 /* struct objc_selector {
4008      void *sel_id;
4009      char *sel_type;
4010    }; */
4011
4012 static void
4013 build_selector_template (void)
4014 {
4015
4016   tree decl_specs, field_decl, field_decl_chain;
4017
4018   objc_selector_template
4019     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4020
4021   /* void *sel_id; */
4022
4023   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4024   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4025   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4026   field_decl_chain = field_decl;
4027
4028   /* char *sel_type; */
4029
4030   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4031   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
4032   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4033   chainon (field_decl_chain, field_decl);
4034
4035   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4036 }
4037
4038 /* struct objc_class {
4039      struct objc_class *isa;
4040      struct objc_class *super_class;
4041      char *name;
4042      long version;
4043      long info;
4044      long instance_size;
4045      struct objc_ivar_list *ivars;
4046      struct objc_method_list *methods;
4047      if (flag_next_runtime)
4048        struct objc_cache *cache;
4049      else {
4050        struct sarray *dtable;
4051        struct objc_class *subclass_list;
4052        struct objc_class *sibling_class;
4053      }
4054      struct objc_protocol_list *protocols;
4055      if (flag_next_runtime)
4056        void *sel_id;
4057      void *gc_object_type;
4058    };  */
4059
4060 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4061    the NeXT/Apple runtime; still, the compiler must generate them to
4062    maintain backward binary compatibility (and to allow for future
4063    expansion).  */
4064
4065 static void
4066 build_class_template (void)
4067 {
4068   tree decl_specs, field_decl, field_decl_chain;
4069
4070   objc_class_template
4071     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4072
4073   /* struct objc_class *isa; */
4074
4075   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4076   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
4077   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4078   field_decl_chain = field_decl;
4079
4080   /* struct objc_class *super_class; */
4081
4082   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4083   field_decl
4084     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4085   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4086   chainon (field_decl_chain, field_decl);
4087
4088   /* char *name; */
4089
4090   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4091   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
4092   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4093   chainon (field_decl_chain, field_decl);
4094
4095   /* long version; */
4096
4097   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4098   field_decl = get_identifier ("version");
4099   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4100   chainon (field_decl_chain, field_decl);
4101
4102   /* long info; */
4103
4104   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4105   field_decl = get_identifier ("info");
4106   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4107   chainon (field_decl_chain, field_decl);
4108
4109   /* long instance_size; */
4110
4111   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4112   field_decl = get_identifier ("instance_size");
4113   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4114   chainon (field_decl_chain, field_decl);
4115
4116   /* struct objc_ivar_list *ivars; */
4117
4118   decl_specs = build_tree_list (NULL_TREE,
4119                                 xref_tag (RECORD_TYPE,
4120                                           get_identifier (UTAG_IVAR_LIST)));
4121   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
4122   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4123   chainon (field_decl_chain, field_decl);
4124
4125   /* struct objc_method_list *methods; */
4126
4127   decl_specs = build_tree_list (NULL_TREE,
4128                                 xref_tag (RECORD_TYPE,
4129                                           get_identifier (UTAG_METHOD_LIST)));
4130   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
4131   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4132   chainon (field_decl_chain, field_decl);
4133
4134   if (flag_next_runtime)
4135     {
4136       /* struct objc_cache *cache; */
4137
4138       decl_specs = build_tree_list (NULL_TREE,
4139                                     xref_tag (RECORD_TYPE,
4140                                               get_identifier ("objc_cache")));
4141       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
4142       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4143       chainon (field_decl_chain, field_decl);
4144     }
4145   else
4146     {
4147       /* struct sarray *dtable; */
4148
4149       decl_specs = build_tree_list (NULL_TREE,
4150                                     xref_tag (RECORD_TYPE,
4151                                               get_identifier ("sarray")));
4152       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
4153       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4154       chainon (field_decl_chain, field_decl);
4155
4156       /* struct objc_class *subclass_list; */
4157
4158       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4159       field_decl
4160         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
4161       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4162       chainon (field_decl_chain, field_decl);
4163
4164       /* struct objc_class *sibling_class; */
4165
4166       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4167       field_decl
4168         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
4169       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4170       chainon (field_decl_chain, field_decl);
4171     }
4172
4173   /* struct objc_protocol **protocol_list; */
4174
4175   decl_specs = build_tree_list (NULL_TREE,
4176                                 xref_tag (RECORD_TYPE,
4177                                           get_identifier (UTAG_PROTOCOL)));
4178   field_decl
4179     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4180   field_decl
4181     = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4182   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4183   chainon (field_decl_chain, field_decl);
4184
4185   if (flag_next_runtime)
4186     {
4187       /* void *sel_id; */
4188
4189       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4190       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4191       field_decl
4192         = grokfield (field_decl, decl_specs, NULL_TREE);
4193       chainon (field_decl_chain, field_decl);
4194     }
4195
4196   /* void *gc_object_type; */
4197
4198   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4199   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
4200   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4201   chainon (field_decl_chain, field_decl);
4202
4203   finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
4204 }
4205
4206 /* Generate appropriate forward declarations for an implementation.  */
4207
4208 static void
4209 synth_forward_declarations (void)
4210 {
4211   tree an_id;
4212
4213   /* static struct objc_class _OBJC_CLASS_<my_name>; */
4214   UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
4215                                                   objc_class_template);
4216
4217   /* static struct objc_class _OBJC_METACLASS_<my_name>; */
4218   UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
4219                                                   objc_class_template);
4220
4221   /* Pre-build the following entities - for speed/convenience.  */
4222
4223   an_id = get_identifier ("super_class");
4224   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
4225   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
4226 }
4227
4228 static void
4229 error_with_ivar (const char *message, tree decl, tree rawdecl)
4230 {
4231   error ("%J%s `%s'", decl,
4232          message, gen_declaration (rawdecl, errbuf));
4233
4234 }
4235
4236 static void
4237 check_ivars (tree inter, tree imp)
4238 {
4239   tree intdecls = CLASS_IVARS (inter);
4240   tree impdecls = CLASS_IVARS (imp);
4241   tree rawintdecls = CLASS_RAW_IVARS (inter);
4242   tree rawimpdecls = CLASS_RAW_IVARS (imp);
4243
4244   while (1)
4245     {
4246       tree t1, t2;
4247
4248 #ifdef OBJCPLUS
4249       if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4250         intdecls = TREE_CHAIN (intdecls);
4251 #endif
4252       if (intdecls == 0 && impdecls == 0)
4253         break;
4254       if (intdecls == 0 || impdecls == 0)
4255         {
4256           error ("inconsistent instance variable specification");
4257           break;
4258         }
4259
4260       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4261
4262       if (!comptypes (t1, t2, false)
4263           || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
4264                                   TREE_VALUE (TREE_VALUE (rawimpdecls))))
4265         {
4266           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4267             {
4268               error_with_ivar ("conflicting instance variable type",
4269                                impdecls, rawimpdecls);
4270               error_with_ivar ("previous declaration of",
4271                                intdecls, rawintdecls);
4272             }
4273           else                  /* both the type and the name don't match */
4274             {
4275               error ("inconsistent instance variable specification");
4276               break;
4277             }
4278         }
4279
4280       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4281         {
4282           error_with_ivar ("conflicting instance variable name",
4283                            impdecls, rawimpdecls);
4284           error_with_ivar ("previous declaration of",
4285                            intdecls, rawintdecls);
4286         }
4287
4288       intdecls = TREE_CHAIN (intdecls);
4289       impdecls = TREE_CHAIN (impdecls);
4290       rawintdecls = TREE_CHAIN (rawintdecls);
4291       rawimpdecls = TREE_CHAIN (rawimpdecls);
4292     }
4293 }
4294
4295 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
4296    This needs to be done just once per compilation.  */
4297
4298 static void
4299 build_super_template (void)
4300 {
4301   tree decl_specs, field_decl, field_decl_chain;
4302
4303   /* Suppress outputting debug symbols, because
4304      dbxout_init hasn't been called yet.  */
4305   enum debug_info_type save_write_symbols = write_symbols;
4306   const struct gcc_debug_hooks *save_hooks = debug_hooks;
4307
4308   write_symbols = NO_DEBUG;
4309   debug_hooks = &do_nothing_debug_hooks;
4310
4311   objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
4312
4313   /* struct objc_object *self; */
4314
4315   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
4316   field_decl = get_identifier ("self");
4317   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4318   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4319   field_decl_chain = field_decl;
4320
4321 #ifdef OBJCPLUS
4322   /* struct objc_class *super_class; */
4323 #else
4324   /* struct objc_class *class; */
4325 #endif
4326
4327   decl_specs = get_identifier (UTAG_CLASS);
4328   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
4329 #ifdef OBJCPLUS
4330   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4331 #else
4332   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
4333 #endif
4334
4335   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4336   chainon (field_decl_chain, field_decl);
4337
4338   finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
4339
4340   write_symbols = save_write_symbols;
4341   debug_hooks = save_hooks;
4342 }
4343
4344 /* struct objc_ivar {
4345      char *ivar_name;
4346      char *ivar_type;
4347      int ivar_offset;
4348    };  */
4349
4350 static tree
4351 build_ivar_template (void)
4352 {
4353   tree objc_ivar_id, objc_ivar_record;
4354   tree decl_specs, field_decl, field_decl_chain;
4355
4356   objc_ivar_id = get_identifier (UTAG_IVAR);
4357   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
4358
4359   /* char *ivar_name; */
4360
4361   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4362   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
4363
4364   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4365   field_decl_chain = field_decl;
4366
4367   /* char *ivar_type; */
4368
4369   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4370   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
4371
4372   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4373   chainon (field_decl_chain, field_decl);
4374
4375   /* int ivar_offset; */
4376
4377   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4378   field_decl = get_identifier ("ivar_offset");
4379
4380   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4381   chainon (field_decl_chain, field_decl);
4382
4383   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
4384
4385   return objc_ivar_record;
4386 }
4387
4388 /* struct {
4389      int ivar_count;
4390      struct objc_ivar ivar_list[ivar_count];
4391    };  */
4392
4393 static tree
4394 build_ivar_list_template (tree list_type, int size)
4395 {
4396   tree objc_ivar_list_record;
4397   tree decl_specs, field_decl, field_decl_chain;
4398
4399   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4400
4401   /* int ivar_count; */
4402
4403   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4404   field_decl = get_identifier ("ivar_count");
4405
4406   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4407   field_decl_chain = field_decl;
4408
4409   /* struct objc_ivar ivar_list[]; */
4410
4411   decl_specs = build_tree_list (NULL_TREE, list_type);
4412   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
4413                          build_int_2 (size, 0));
4414
4415   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4416   chainon (field_decl_chain, field_decl);
4417
4418   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4419
4420   return objc_ivar_list_record;
4421 }
4422
4423 /* struct {
4424      int method_next;
4425      int method_count;
4426      struct objc_method method_list[method_count];
4427    };  */
4428
4429 static tree
4430 build_method_list_template (tree list_type, int size)
4431 {
4432   tree objc_ivar_list_record;
4433   tree decl_specs, field_decl, field_decl_chain;
4434
4435   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4436
4437   /* int method_next; */
4438
4439   decl_specs
4440     = build_tree_list
4441       (NULL_TREE,
4442        xref_tag (RECORD_TYPE,
4443                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
4444   field_decl
4445     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
4446   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4447   field_decl_chain = field_decl;
4448
4449   /* int method_count; */
4450
4451   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4452   field_decl = get_identifier ("method_count");
4453
4454   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4455   chainon (field_decl_chain, field_decl);
4456
4457   /* struct objc_method method_list[]; */
4458
4459   decl_specs = build_tree_list (NULL_TREE, list_type);
4460   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
4461                          build_int_2 (size, 0));
4462
4463   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4464   chainon (field_decl_chain, field_decl);
4465
4466   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4467
4468   return objc_ivar_list_record;
4469 }
4470
4471 static tree
4472 build_ivar_list_initializer (tree type, tree field_decl)
4473 {
4474   tree initlist = NULL_TREE;
4475
4476   do
4477     {
4478       tree ivar = NULL_TREE;
4479
4480       /* Set name.  */
4481       if (DECL_NAME (field_decl))
4482         ivar = tree_cons (NULL_TREE,
4483                           add_objc_string (DECL_NAME (field_decl),
4484                                            meth_var_names),
4485                           ivar);
4486       else
4487         /* Unnamed bit-field ivar (yuck).  */
4488         ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
4489
4490       /* Set type.  */
4491       encode_field_decl (field_decl,
4492                          obstack_object_size (&util_obstack),
4493                          OBJC_ENCODE_DONT_INLINE_DEFS);
4494
4495       /* Null terminate string.  */
4496       obstack_1grow (&util_obstack, 0);
4497       ivar
4498         = tree_cons
4499           (NULL_TREE,
4500            add_objc_string (get_identifier (obstack_finish (&util_obstack)),
4501                             meth_var_types),
4502            ivar);
4503       obstack_free (&util_obstack, util_firstobj);
4504
4505       /* Set offset.  */
4506       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
4507       initlist = tree_cons (NULL_TREE,
4508                             objc_build_constructor (type, nreverse (ivar)),
4509                             initlist);
4510       do
4511         field_decl = TREE_CHAIN (field_decl);
4512       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
4513     }
4514   while (field_decl);
4515
4516   return objc_build_constructor (build_array_type (type, 0),
4517                                  nreverse (initlist));
4518 }
4519
4520 static tree
4521 generate_ivars_list (tree type, const char *name, int size, tree list)
4522 {
4523   tree sc_spec, decl_specs, decl, initlist;
4524
4525   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4526   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4527
4528   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4529                      decl_specs, 1, NULL_TREE);
4530
4531   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
4532   initlist = tree_cons (NULL_TREE, list, initlist);
4533
4534   finish_decl (decl,
4535                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4536                NULL_TREE);
4537
4538   return decl;
4539 }
4540
4541 /* Count only the fields occurring in T.  */
4542 static int
4543 ivar_list_length (tree t)
4544 {
4545   int count = 0;
4546
4547   for (; t; t = TREE_CHAIN (t))
4548     if (TREE_CODE (t) == FIELD_DECL)
4549       ++count;
4550
4551   return count;
4552 }
4553
4554 static void
4555 generate_ivar_lists (void)
4556 {
4557   tree initlist, ivar_list_template, chain;
4558   tree cast, variable_length_type;
4559   int size;
4560
4561   generating_instance_variables = 1;
4562
4563   if (!objc_ivar_template)
4564     objc_ivar_template = build_ivar_template ();
4565
4566   cast
4567     = build_tree_list
4568       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
4569                                          get_identifier (UTAG_IVAR_LIST))),
4570        NULL_TREE);
4571   variable_length_type = groktypename (cast);
4572
4573   /* Only generate class variables for the root of the inheritance
4574      hierarchy since these will be the same for every class.  */
4575
4576   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
4577       && (chain = TYPE_FIELDS (objc_class_template)))
4578     {
4579       size = ivar_list_length (chain);
4580
4581       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4582       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4583
4584       UOBJC_CLASS_VARIABLES_decl
4585         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
4586                                size, initlist);
4587       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
4588     }
4589   else
4590     UOBJC_CLASS_VARIABLES_decl = 0;
4591
4592   chain = CLASS_IVARS (implementation_template);
4593   if (chain)
4594     {
4595       size = ivar_list_length (chain);
4596       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4597       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4598
4599       UOBJC_INSTANCE_VARIABLES_decl
4600         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
4601                                size, initlist);
4602       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
4603     }
4604   else
4605     UOBJC_INSTANCE_VARIABLES_decl = 0;
4606
4607   generating_instance_variables = 0;
4608 }
4609
4610 static tree
4611 build_dispatch_table_initializer (tree type, tree entries)
4612 {
4613   tree initlist = NULL_TREE;
4614
4615   do
4616     {
4617       tree elemlist = NULL_TREE;
4618
4619       elemlist = tree_cons (NULL_TREE,
4620                             build_selector (METHOD_SEL_NAME (entries)),
4621                             NULL_TREE);
4622
4623       /* Generate the method encoding if we don't have one already.  */
4624       if (! METHOD_ENCODING (entries))
4625         METHOD_ENCODING (entries) =
4626           encode_method_prototype (entries);
4627
4628       elemlist = tree_cons (NULL_TREE,
4629                             add_objc_string (METHOD_ENCODING (entries),
4630                                              meth_var_types),
4631                             elemlist);
4632
4633       elemlist = tree_cons (NULL_TREE,
4634                             build_unary_op (ADDR_EXPR,
4635                                             METHOD_DEFINITION (entries), 1),
4636                             elemlist);
4637
4638       initlist = tree_cons (NULL_TREE,
4639                             objc_build_constructor (type, nreverse (elemlist)),
4640                             initlist);
4641
4642       entries = TREE_CHAIN (entries);
4643     }
4644   while (entries);
4645
4646   return objc_build_constructor (build_array_type (type, 0),
4647                                  nreverse (initlist));
4648 }
4649
4650 /* To accomplish method prototyping without generating all kinds of
4651    inane warnings, the definition of the dispatch table entries were
4652    changed from:
4653
4654         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4655    to:
4656         struct objc_method { SEL _cmd; ...; void *_imp; };  */
4657
4658 static tree
4659 build_method_template (void)
4660 {
4661   tree _SLT_record;
4662   tree decl_specs, field_decl, field_decl_chain;
4663
4664   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4665
4666   /* struct objc_selector *_cmd; */
4667   decl_specs = tree_cons (NULL_TREE,
4668                           xref_tag (RECORD_TYPE,
4669                                     get_identifier (TAG_SELECTOR)),
4670                           NULL_TREE);
4671   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4672
4673   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4674   field_decl_chain = field_decl;
4675
4676   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4677   field_decl = build1 (INDIRECT_REF, NULL_TREE,
4678                        get_identifier ("method_types"));
4679   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4680   chainon (field_decl_chain, field_decl);
4681
4682   /* void *_imp; */
4683
4684   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4685   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4686   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4687   chainon (field_decl_chain, field_decl);
4688
4689   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4690
4691   return _SLT_record;
4692 }
4693
4694
4695 static tree
4696 generate_dispatch_table (tree type, const char *name, int size, tree list)
4697 {
4698   tree sc_spec, decl_specs, decl, initlist;
4699
4700   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4701   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4702
4703   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4704                      decl_specs, 1, NULL_TREE);
4705
4706   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4707   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4708   initlist = tree_cons (NULL_TREE, list, initlist);
4709
4710   finish_decl (decl,
4711                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4712                NULL_TREE);
4713
4714   return decl;
4715 }
4716
4717 static void
4718 mark_referenced_methods (void)
4719 {
4720   struct imp_entry *impent;
4721   tree chain;
4722
4723   for (impent = imp_list; impent; impent = impent->next)
4724     {
4725       chain = CLASS_CLS_METHODS (impent->imp_context);
4726       while (chain)
4727         {
4728           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4729           chain = TREE_CHAIN (chain);
4730         }
4731
4732       chain = CLASS_NST_METHODS (impent->imp_context);
4733       while (chain)
4734         {
4735           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4736           chain = TREE_CHAIN (chain);
4737         }
4738     }
4739 }
4740
4741 static void
4742 generate_dispatch_tables (void)
4743 {
4744   tree initlist, chain, method_list_template;
4745   tree cast, variable_length_type;
4746   int size;
4747
4748   if (!objc_method_template)
4749     objc_method_template = build_method_template ();
4750
4751   cast
4752     = build_tree_list
4753       (build_tree_list (NULL_TREE,
4754                         xref_tag (RECORD_TYPE,
4755                                   get_identifier (UTAG_METHOD_LIST))),
4756        NULL_TREE);
4757
4758   variable_length_type = groktypename (cast);
4759
4760   chain = CLASS_CLS_METHODS (objc_implementation_context);
4761   if (chain)
4762     {
4763       size = list_length (chain);
4764
4765       method_list_template
4766         = build_method_list_template (objc_method_template, size);
4767       initlist
4768         = build_dispatch_table_initializer (objc_method_template, chain);
4769
4770       UOBJC_CLASS_METHODS_decl
4771         = generate_dispatch_table (method_list_template,
4772                                    ((TREE_CODE (objc_implementation_context)
4773                                      == CLASS_IMPLEMENTATION_TYPE)
4774                                     ? "_OBJC_CLASS_METHODS"
4775                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
4776                                    size, initlist);
4777       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4778     }
4779   else
4780     UOBJC_CLASS_METHODS_decl = 0;
4781
4782   chain = CLASS_NST_METHODS (objc_implementation_context);
4783   if (chain)
4784     {
4785       size = list_length (chain);
4786
4787       method_list_template
4788         = build_method_list_template (objc_method_template, size);
4789       initlist
4790         = build_dispatch_table_initializer (objc_method_template, chain);
4791
4792       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4793         UOBJC_INSTANCE_METHODS_decl
4794           = generate_dispatch_table (method_list_template,
4795                                      "_OBJC_INSTANCE_METHODS",
4796                                      size, initlist);
4797       else
4798         /* We have a category.  */
4799         UOBJC_INSTANCE_METHODS_decl
4800           = generate_dispatch_table (method_list_template,
4801                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
4802                                      size, initlist);
4803       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4804     }
4805   else
4806     UOBJC_INSTANCE_METHODS_decl = 0;
4807 }
4808
4809 static tree
4810 generate_protocol_list (tree i_or_p)
4811 {
4812   tree initlist, decl_specs, sc_spec;
4813   tree refs_decl, expr_decl, lproto, e, plist;
4814   tree cast_type;
4815   int size = 0;
4816
4817   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4818       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4819     plist = CLASS_PROTOCOL_LIST (i_or_p);
4820   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4821     plist = PROTOCOL_LIST (i_or_p);
4822   else
4823     abort ();
4824
4825   cast_type = groktypename
4826     (build_tree_list
4827      (build_tree_list (NULL_TREE,
4828                        xref_tag (RECORD_TYPE,
4829                                  get_identifier (UTAG_PROTOCOL))),
4830       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4831
4832   /* Compute size.  */
4833   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4834     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4835         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4836       size++;
4837
4838   /* Build initializer.  */
4839   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4840
4841   e = build_int_2 (size, 0);
4842   TREE_TYPE (e) = cast_type;
4843   initlist = tree_cons (NULL_TREE, e, initlist);
4844
4845   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4846     {
4847       tree pval = TREE_VALUE (lproto);
4848
4849       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4850           && PROTOCOL_FORWARD_DECL (pval))
4851         {
4852           e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4853           initlist = tree_cons (NULL_TREE, e, initlist);
4854         }
4855     }
4856
4857   /* static struct objc_protocol *refs[n]; */
4858
4859   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4860   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4861                                            get_identifier (UTAG_PROTOCOL)),
4862                           sc_spec);
4863
4864   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4865     expr_decl = build_nt (ARRAY_REF,
4866                           synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4867                                                       i_or_p),
4868                           build_int_2 (size + 2, 0));
4869   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4870     expr_decl = build_nt (ARRAY_REF,
4871                           synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4872                                                       i_or_p),
4873                           build_int_2 (size + 2, 0));
4874   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4875     expr_decl
4876       = build_nt (ARRAY_REF,
4877                   synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4878                                               i_or_p),
4879                   build_int_2 (size + 2, 0));
4880   else
4881     abort ();
4882
4883   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4884
4885   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4886   DECL_CONTEXT (refs_decl) = NULL_TREE;
4887
4888   finish_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4889                                                   nreverse (initlist)),
4890                NULL_TREE);
4891
4892   return refs_decl;
4893 }
4894
4895 static tree
4896 build_category_initializer (tree type, tree cat_name, tree class_name,
4897                             tree instance_methods, tree class_methods,
4898                             tree protocol_list)
4899 {
4900   tree initlist = NULL_TREE, expr;
4901
4902   initlist = tree_cons (NULL_TREE, cat_name, initlist);
4903   initlist = tree_cons (NULL_TREE, class_name, initlist);
4904
4905   if (!instance_methods)
4906     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4907   else
4908     {
4909       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4910       initlist = tree_cons (NULL_TREE, expr, initlist);
4911     }
4912   if (!class_methods)
4913     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4914   else
4915     {
4916       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4917       initlist = tree_cons (NULL_TREE, expr, initlist);
4918     }
4919
4920   /* protocol_list = */
4921   if (!protocol_list)
4922      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4923   else
4924      {
4925        tree cast_type2 = groktypename
4926          (build_tree_list
4927           (build_tree_list (NULL_TREE,
4928                             xref_tag (RECORD_TYPE,
4929                                       get_identifier (UTAG_PROTOCOL))),
4930            build1 (INDIRECT_REF, NULL_TREE,
4931                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4932
4933         expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4934         TREE_TYPE (expr) = cast_type2;
4935         initlist = tree_cons (NULL_TREE, expr, initlist);
4936      }
4937
4938   return objc_build_constructor (type, nreverse (initlist));
4939 }
4940
4941 /* struct objc_class {
4942      struct objc_class *isa;
4943      struct objc_class *super_class;
4944      char *name;
4945      long version;
4946      long info;
4947      long instance_size;
4948      struct objc_ivar_list *ivars;
4949      struct objc_method_list *methods;
4950      if (flag_next_runtime)
4951        struct objc_cache *cache;
4952      else {
4953        struct sarray *dtable;
4954        struct objc_class *subclass_list;
4955        struct objc_class *sibling_class;
4956      }
4957      struct objc_protocol_list *protocols;
4958      if (flag_next_runtime)
4959        void *sel_id;
4960      void *gc_object_type;
4961    };  */
4962
4963 static tree
4964 build_shared_structure_initializer (tree type, tree isa, tree super,
4965                                     tree name, tree size, int status,
4966                                     tree dispatch_table, tree ivar_list,
4967                                     tree protocol_list)
4968 {
4969   tree initlist = NULL_TREE, expr;
4970
4971   /* isa = */
4972   initlist = tree_cons (NULL_TREE, isa, initlist);
4973
4974   /* super_class = */
4975   initlist = tree_cons (NULL_TREE, super, initlist);
4976
4977   /* name = */
4978   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4979
4980   /* version = */
4981   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4982
4983   /* info = */
4984   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4985
4986   /* instance_size = */
4987   initlist = tree_cons (NULL_TREE, size, initlist);
4988
4989   /* objc_ivar_list = */
4990   if (!ivar_list)
4991     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4992   else
4993     {
4994       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4995       initlist = tree_cons (NULL_TREE, expr, initlist);
4996     }
4997
4998   /* objc_method_list = */
4999   if (!dispatch_table)
5000     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5001   else
5002     {
5003       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
5004       initlist = tree_cons (NULL_TREE, expr, initlist);
5005     }
5006
5007   if (flag_next_runtime)
5008     /* method_cache = */
5009     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5010   else
5011     {
5012       /* dtable = */
5013       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5014
5015       /* subclass_list = */
5016       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5017
5018       /* sibling_class = */
5019       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5020     }
5021
5022   /* protocol_list = */
5023   if (! protocol_list)
5024     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5025   else
5026      {
5027        tree cast_type2
5028          = groktypename
5029          (build_tree_list
5030           (build_tree_list (NULL_TREE,
5031                             xref_tag (RECORD_TYPE,
5032                                       get_identifier (UTAG_PROTOCOL))),
5033            build1 (INDIRECT_REF, NULL_TREE,
5034                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
5035
5036      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
5037      TREE_TYPE (expr) = cast_type2;
5038      initlist = tree_cons (NULL_TREE, expr, initlist);
5039      }
5040
5041   if (flag_next_runtime)
5042     /* sel_id = NULL */
5043     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5044
5045   /* gc_object_type = NULL */
5046   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5047
5048   return objc_build_constructor (type, nreverse (initlist));
5049 }
5050
5051 /* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
5052
5053 static inline tree
5054 lookup_category (tree class, tree cat_name)
5055 {
5056   tree category = CLASS_CATEGORY_LIST (class);
5057
5058   while (category && CLASS_SUPER_NAME (category) != cat_name)
5059     category = CLASS_CATEGORY_LIST (category);
5060   return category;
5061 }
5062
5063 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
5064
5065 static void
5066 generate_category (tree cat)
5067 {
5068   tree sc_spec, decl_specs, decl;
5069   tree initlist, cat_name_expr, class_name_expr;
5070   tree protocol_decl, category;
5071
5072   add_class_reference (CLASS_NAME (cat));
5073   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5074
5075   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5076
5077   category = lookup_category (implementation_template,
5078                                 CLASS_SUPER_NAME (cat));
5079
5080   if (category && CLASS_PROTOCOL_LIST (category))
5081     {
5082       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5083       protocol_decl = generate_protocol_list (category);
5084     }
5085   else
5086     protocol_decl = 0;
5087
5088   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
5089   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
5090
5091   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
5092                                                  objc_implementation_context),
5093                      decl_specs, 1, NULL_TREE);
5094
5095   initlist = build_category_initializer (TREE_TYPE (decl),
5096                                          cat_name_expr, class_name_expr,
5097                                          UOBJC_INSTANCE_METHODS_decl,
5098                                          UOBJC_CLASS_METHODS_decl,
5099                                          protocol_decl);
5100
5101   finish_decl (decl, initlist, NULL_TREE);
5102 }
5103
5104 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5105    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
5106
5107 static void
5108 generate_shared_structures (void)
5109 {
5110   tree sc_spec, decl_specs, decl;
5111   tree name_expr, super_expr, root_expr;
5112   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5113   tree cast_type, initlist, protocol_decl;
5114
5115   my_super_id = CLASS_SUPER_NAME (implementation_template);
5116   if (my_super_id)
5117     {
5118       add_class_reference (my_super_id);
5119
5120       /* Compute "my_root_id" - this is required for code generation.
5121          the "isa" for all meta class structures points to the root of
5122          the inheritance hierarchy (e.g. "__Object")...  */
5123       my_root_id = my_super_id;
5124       do
5125         {
5126           tree my_root_int = lookup_interface (my_root_id);
5127
5128           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5129             my_root_id = CLASS_SUPER_NAME (my_root_int);
5130           else
5131             break;
5132         }
5133       while (1);
5134     }
5135   else
5136     /* No super class.  */
5137     my_root_id = CLASS_NAME (implementation_template);
5138
5139   cast_type
5140     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5141                                                       objc_class_template),
5142                                      build1 (INDIRECT_REF,
5143                                              NULL_TREE, NULL_TREE)));
5144
5145   name_expr = add_objc_string (CLASS_NAME (implementation_template),
5146                                class_names);
5147
5148   /* Install class `isa' and `super' pointers at runtime.  */
5149   if (my_super_id)
5150     {
5151       super_expr = add_objc_string (my_super_id, class_names);
5152       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5153     }
5154   else
5155     super_expr = build_int_2 (0, 0);
5156
5157   root_expr = add_objc_string (my_root_id, class_names);
5158   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5159
5160   if (CLASS_PROTOCOL_LIST (implementation_template))
5161     {
5162       generate_protocol_references
5163         (CLASS_PROTOCOL_LIST (implementation_template));
5164       protocol_decl = generate_protocol_list (implementation_template);
5165     }
5166   else
5167     protocol_decl = 0;
5168
5169   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5170
5171   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5172   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5173
5174   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
5175                      NULL_TREE);
5176
5177   initlist
5178     = build_shared_structure_initializer
5179       (TREE_TYPE (decl),
5180        root_expr, super_expr, name_expr,
5181        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5182        2 /*CLS_META*/,
5183        UOBJC_CLASS_METHODS_decl,
5184        UOBJC_CLASS_VARIABLES_decl,
5185        protocol_decl);
5186
5187   finish_decl (decl, initlist, NULL_TREE);
5188
5189   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5190
5191   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
5192                      NULL_TREE);
5193
5194   initlist
5195     = build_shared_structure_initializer
5196       (TREE_TYPE (decl),
5197        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5198        super_expr, name_expr,
5199        convert (integer_type_node,
5200                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5201                                 (implementation_template))),
5202        1 /*CLS_FACTORY*/,
5203        UOBJC_INSTANCE_METHODS_decl,
5204        UOBJC_INSTANCE_VARIABLES_decl,
5205        protocol_decl);
5206
5207   finish_decl (decl, initlist, NULL_TREE);
5208 }
5209
5210 static tree
5211 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5212 {
5213   char *string;
5214   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5215       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5216     {
5217       const char *const class_name
5218         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5219       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
5220       sprintf (string, "%s_%s", preamble,
5221                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5222     }
5223   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5224            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5225     {
5226       /* We have a category.  */
5227       const char *const class_name
5228         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5229       const char *const class_super_name
5230         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5231       string = (char *) alloca (strlen (preamble)
5232                                 + strlen (class_name)
5233                                 + strlen (class_super_name)
5234                                 + 3);
5235       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5236     }
5237   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5238     {
5239       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5240       string
5241         = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
5242       sprintf (string, "%s_%s", preamble, protocol_name);
5243     }
5244   else
5245     abort ();
5246
5247   return get_identifier (string);
5248 }
5249
5250 static int
5251 is_objc_type_qualifier (tree node)
5252 {
5253   return (TREE_CODE (node) == IDENTIFIER_NODE
5254           && (node == ridpointers [(int) RID_CONST]
5255               || node == ridpointers [(int) RID_VOLATILE]
5256               || node == ridpointers [(int) RID_IN]
5257               || node == ridpointers [(int) RID_OUT]
5258               || node == ridpointers [(int) RID_INOUT]
5259               || node == ridpointers [(int) RID_BYCOPY]
5260               || node == ridpointers [(int) RID_BYREF]
5261               || node == ridpointers [(int) RID_ONEWAY]));
5262 }
5263
5264 /* If type is empty or only type qualifiers are present, add default
5265    type of id (otherwise grokdeclarator will default to int).  */
5266
5267 static tree
5268 adjust_type_for_id_default (tree type)
5269 {
5270   tree declspecs, chain;
5271
5272   if (!type)
5273     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
5274                             build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5275
5276   declspecs = TREE_PURPOSE (type);
5277
5278   /* Determine if a typespec is present.  */
5279   for (chain = declspecs;
5280        chain;
5281        chain = TREE_CHAIN (chain))
5282     {
5283       if (TYPED_OBJECT (TREE_VALUE (chain))
5284           && !(TREE_VALUE (type)
5285                && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
5286         error ("can not use an object as parameter to a method\n");
5287       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
5288         return type;
5289     }
5290
5291   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
5292                                      declspecs),
5293                           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5294 }
5295
5296 /*   Usage:
5297                 keyworddecl:
5298                         selector ':' '(' typename ')' identifier
5299
5300      Purpose:
5301                 Transform an Objective-C keyword argument into
5302                 the C equivalent parameter declarator.
5303
5304      In:        key_name, an "identifier_node" (optional).
5305                 arg_type, a  "tree_list" (optional).
5306                 arg_name, an "identifier_node".
5307
5308      Note:      It would be really nice to strongly type the preceding
5309                 arguments in the function prototype; however, then I
5310                 could not use the "accessor" macros defined in "tree.h".
5311
5312      Out:       an instance of "keyword_decl".  */
5313
5314 tree
5315 build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5316 {
5317   tree keyword_decl;
5318
5319   /* If no type is specified, default to "id".  */
5320   arg_type = adjust_type_for_id_default (arg_type);
5321
5322   keyword_decl = make_node (KEYWORD_DECL);
5323
5324   TREE_TYPE (keyword_decl) = arg_type;
5325   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5326   KEYWORD_KEY_NAME (keyword_decl) = key_name;
5327
5328   return keyword_decl;
5329 }
5330
5331 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
5332
5333 static tree
5334 build_keyword_selector (tree selector)
5335 {
5336   int len = 0;
5337   tree key_chain, key_name;
5338   char *buf;
5339
5340   /* Scan the selector to see how much space we'll need.  */
5341   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5342     {
5343       if (TREE_CODE (selector) == KEYWORD_DECL)
5344         key_name = KEYWORD_KEY_NAME (key_chain);
5345       else if (TREE_CODE (selector) == TREE_LIST)
5346         key_name = TREE_PURPOSE (key_chain);
5347       else
5348         abort ();
5349
5350       if (key_name)
5351         len += IDENTIFIER_LENGTH (key_name) + 1;
5352       else
5353         /* Just a ':' arg.  */
5354         len++;
5355     }
5356
5357   buf = (char *) alloca (len + 1);
5358   /* Start the buffer out as an empty string.  */
5359   buf[0] = '\0';
5360
5361   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5362     {
5363       if (TREE_CODE (selector) == KEYWORD_DECL)
5364         key_name = KEYWORD_KEY_NAME (key_chain);
5365       else if (TREE_CODE (selector) == TREE_LIST)
5366         {
5367           key_name = TREE_PURPOSE (key_chain);
5368           /* The keyword decl chain will later be used as a function argument
5369              chain.  Unhook the selector itself so as to not confuse other
5370              parts of the compiler.  */
5371           TREE_PURPOSE (key_chain) = NULL_TREE;
5372         }
5373       else
5374         abort ();
5375
5376       if (key_name)
5377         strcat (buf, IDENTIFIER_POINTER (key_name));
5378       strcat (buf, ":");
5379     }
5380
5381   return get_identifier (buf);
5382 }
5383
5384 /* Used for declarations and definitions.  */
5385
5386 tree
5387 build_method_decl (enum tree_code code, tree ret_type, tree selector,
5388                    tree add_args)
5389 {
5390   tree method_decl;
5391
5392   /* If no type is specified, default to "id".  */
5393   ret_type = adjust_type_for_id_default (ret_type);
5394
5395   method_decl = make_node (code);
5396   TREE_TYPE (method_decl) = ret_type;
5397
5398   /* If we have a keyword selector, create an identifier_node that
5399      represents the full selector name (`:' included)...  */
5400   if (TREE_CODE (selector) == KEYWORD_DECL)
5401     {
5402       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5403       METHOD_SEL_ARGS (method_decl) = selector;
5404       METHOD_ADD_ARGS (method_decl) = add_args;
5405     }
5406   else
5407     {
5408       METHOD_SEL_NAME (method_decl) = selector;
5409       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5410       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5411     }
5412
5413   return method_decl;
5414 }
5415
5416 #define METHOD_DEF 0
5417 #define METHOD_REF 1
5418
5419 /* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
5420    an argument list for method METH.  CONTEXT is either METHOD_DEF or
5421    METHOD_REF, saying whether we are trying to define a method or call
5422    one.  SUPERFLAG says this is for a send to super; this makes a
5423    difference for the NeXT calling sequence in which the lookup and
5424    the method call are done together.  If METH is null, user-defined
5425    arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
5426
5427 static tree
5428 get_arg_type_list (tree meth, int context, int superflag)
5429 {
5430   tree arglist, akey;
5431
5432   /* Receiver type.  */
5433   if (flag_next_runtime && superflag)
5434     arglist = build_tree_list (NULL_TREE, super_type);
5435   else if (context == METHOD_DEF)
5436     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
5437   else
5438     arglist = build_tree_list (NULL_TREE, id_type);
5439
5440   /* Selector type - will eventually change to `int'.  */
5441   chainon (arglist, build_tree_list (NULL_TREE, selector_type));
5442
5443   /* No actual method prototype given -- assume that remaining arguments
5444      are `...'.  */
5445   if (!meth)
5446     return arglist;
5447
5448   /* Build a list of argument types.  */
5449   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
5450     {
5451       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
5452       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
5453     }
5454
5455   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
5456     /* We have a `, ...' immediately following the selector,
5457        finalize the arglist...simulate get_parm_info (true).  */
5458     ;
5459   else if (METHOD_ADD_ARGS (meth))
5460     {
5461       /* we have a variable length selector */
5462       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
5463       chainon (arglist, add_arg_list);
5464     }
5465   else
5466     /* finalize the arglist...simulate get_parm_info (false) */
5467     chainon (arglist, void_list_node);
5468
5469   return arglist;
5470 }
5471
5472 static tree
5473 check_duplicates (hash hsh, int methods, int is_class)
5474 {
5475   tree meth = NULL_TREE;
5476
5477   if (hsh)
5478     {
5479       meth = hsh->key;
5480
5481       if (hsh->list)
5482         {
5483           /* We have two or more methods with the same name but
5484              different types.  */
5485           attr loop;
5486
5487           warning ("multiple %s named `%c%s' found",
5488                    methods ? "methods" : "selectors",
5489                    (is_class ? '+' : '-'),
5490                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5491
5492           warn_with_method (methods ? "using" : "found",
5493                             ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5494                              ? '-'
5495                              : '+'), 
5496                             meth);
5497           for (loop = hsh->list; loop; loop = loop->next)
5498             warn_with_method ("also found",
5499                               ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
5500                                ? '-' 
5501                                : '+'),
5502                               loop->value);
5503         }
5504     }
5505   return meth;
5506 }
5507
5508 /* If RECEIVER is a class reference, return the identifier node for
5509    the referenced class.  RECEIVER is created by get_class_reference,
5510    so we check the exact form created depending on which runtimes are
5511    used.  */
5512
5513 static tree
5514 receiver_is_class_object (tree receiver, int self, int super)
5515 {
5516   tree chain, exp, arg;
5517
5518   /* The receiver is 'self' or 'super' in the context of a class method.  */
5519   if (objc_method_context
5520       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
5521       && (self || super))
5522     return (super
5523             ? CLASS_SUPER_NAME (implementation_template)
5524             : CLASS_NAME (implementation_template));
5525
5526   if (flag_next_runtime)
5527     {
5528       /* The receiver is a variable created by
5529          build_class_reference_decl.  */
5530       if (TREE_CODE (receiver) == VAR_DECL
5531           && TREE_TYPE (TREE_TYPE (receiver)) == TREE_TYPE (objc_class_type))
5532         /* Look up the identifier.  */
5533         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5534           if (TREE_PURPOSE (chain) == receiver)
5535             return TREE_VALUE (chain);
5536     }
5537
5538   /* The receiver is a function call that returns an id.  Check if
5539      it is a call to objc_getClass, if so, pick up the class name.  */
5540   if (TREE_CODE (receiver) == CALL_EXPR
5541       && (exp = TREE_OPERAND (receiver, 0))
5542       && TREE_CODE (exp) == ADDR_EXPR
5543       && (exp = TREE_OPERAND (exp, 0))
5544       && TREE_CODE (exp) == FUNCTION_DECL
5545       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
5546          prototypes for objc_get_class().  Thankfully, they seem to share the
5547          same function type.  */
5548       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
5549       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
5550       /* We have a call to objc_get_class/objc_getClass!  */
5551       && (arg = TREE_OPERAND (receiver, 1))
5552       && TREE_CODE (arg) == TREE_LIST
5553       && (arg = TREE_VALUE (arg)))
5554     {
5555       STRIP_NOPS (arg);
5556       if (TREE_CODE (arg) == ADDR_EXPR
5557           && (arg = TREE_OPERAND (arg, 0))
5558           && TREE_CODE (arg) == STRING_CST)
5559         /* Finally, we have the class name.  */
5560         return get_identifier (TREE_STRING_POINTER (arg));
5561     }
5562   return 0;
5563 }
5564 \f
5565 /* If we are currently building a message expr, this holds
5566    the identifier of the selector of the message.  This is
5567    used when printing warnings about argument mismatches.  */
5568
5569 static tree current_objc_message_selector = 0;
5570
5571 tree
5572 objc_message_selector (void)
5573 {
5574   return current_objc_message_selector;
5575 }
5576
5577 /* Construct an expression for sending a message.
5578    MESS has the object to send to in TREE_PURPOSE
5579    and the argument list (including selector) in TREE_VALUE.
5580
5581    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
5582    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
5583
5584 tree
5585 build_message_expr (tree mess)
5586 {
5587   tree receiver = TREE_PURPOSE (mess);
5588   tree sel_name;
5589   tree args = TREE_VALUE (mess);
5590   tree method_params = NULL_TREE;
5591
5592   if (TREE_CODE (receiver) == ERROR_MARK)
5593     return error_mark_node;
5594
5595   /* Obtain the full selector name.  */
5596   if (TREE_CODE (args) == IDENTIFIER_NODE)
5597     /* A unary selector.  */
5598     sel_name = args;
5599   else if (TREE_CODE (args) == TREE_LIST)
5600     sel_name = build_keyword_selector (args);
5601   else
5602     abort ();
5603
5604   /* Build the parameter list to give to the method.  */
5605   if (TREE_CODE (args) == TREE_LIST)
5606     {
5607       tree chain = args, prev = NULL_TREE;
5608
5609       /* We have a keyword selector--check for comma expressions.  */
5610       while (chain)
5611         {
5612           tree element = TREE_VALUE (chain);
5613
5614           /* We have a comma expression, must collapse...  */
5615           if (TREE_CODE (element) == TREE_LIST)
5616             {
5617               if (prev)
5618                 TREE_CHAIN (prev) = element;
5619               else
5620                 args = element;
5621             }
5622           prev = chain;
5623           chain = TREE_CHAIN (chain);
5624         }
5625       method_params = args;
5626     }
5627
5628 #ifdef OBJCPLUS
5629   if (processing_template_decl)
5630     /* Must wait until template instantiation time.  */
5631     return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
5632                          method_params);
5633 #endif
5634
5635   return finish_message_expr (receiver, sel_name, method_params);
5636 }
5637
5638 /* Look up method SEL_NAME that would be suitable for receiver
5639    of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
5640    nonzero), and report on any duplicates.  */
5641
5642 static tree
5643 lookup_method_in_hash_lists (tree sel_name, int is_class)
5644 {
5645   hash method_prototype = NULL;
5646
5647   if (!is_class)
5648     method_prototype = hash_lookup (nst_method_hash_list,
5649                                     sel_name);
5650                                         
5651   if (!method_prototype)
5652     {
5653       method_prototype = hash_lookup (cls_method_hash_list,
5654                                       sel_name);
5655       is_class = 1;
5656     }
5657
5658   return check_duplicates (method_prototype, 1, is_class);
5659 }
5660
5661 /* The 'finish_message_expr' routine is called from within
5662    'build_message_expr' for non-template functions.  In the case of
5663    C++ template functions, it is called from 'build_expr_from_tree'
5664    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
5665
5666 tree
5667 finish_message_expr (tree receiver, tree sel_name, tree method_params)
5668 {
5669   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
5670   tree selector, retval, is_class;
5671   int self, super, have_cast;
5672
5673   /* Extract the receiver of the message, as well as its type
5674      (where the latter may take the form of a cast or be inferred
5675      from the implementation context).  */
5676   rtype = receiver;
5677   while (TREE_CODE (rtype) == COMPOUND_EXPR
5678               || TREE_CODE (rtype) == MODIFY_EXPR
5679               || TREE_CODE (rtype) == NOP_EXPR
5680               || TREE_CODE (rtype) == COMPONENT_REF)
5681     rtype = TREE_OPERAND (rtype, 0);
5682   self = (rtype == self_decl);
5683   super = (rtype == UOBJC_SUPER_decl);
5684   rtype = TREE_TYPE (receiver);
5685   have_cast = (TREE_CODE (receiver) == NOP_EXPR
5686                || (TREE_CODE (receiver) == COMPOUND_EXPR
5687                    && !IS_SUPER (rtype)));
5688
5689   /* If the receiver is a class object, retrieve the corresponding
5690      @interface, if one exists. */
5691   is_class = receiver_is_class_object (receiver, self, super);
5692
5693   /* Now determine the receiver type (if an explicit cast has not been
5694      provided).  */
5695   if (!have_cast)
5696     {
5697       if (is_class)
5698         rtype = lookup_interface (is_class);
5699       /* Handle `self' and `super'.  */
5700       else if (super)
5701         {
5702           if (!CLASS_SUPER_NAME (implementation_template))
5703             {
5704               error ("no super class declared in @interface for `%s'",
5705                      IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5706               return error_mark_node;
5707             }
5708           rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5709         }
5710       else if (self)
5711         rtype = lookup_interface (CLASS_NAME (implementation_template));
5712     }
5713
5714   /* If receiver is of type `id' or `Class' (or if the @interface for a
5715      class is not visible), we shall be satisfied with the existence of
5716      any instance or class method. */
5717   if (!rtype || IS_ID (rtype)
5718         || TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
5719     {
5720       if (!rtype)
5721         rtype = xref_tag (RECORD_TYPE, is_class);
5722       else if (IS_ID (rtype))
5723         {
5724           rprotos = TYPE_PROTOCOL_LIST (rtype);
5725           rtype = NULL_TREE;
5726         }
5727       else
5728         is_class = TYPE_NAME (rtype) = get_identifier ("Class");
5729
5730       if (rprotos)
5731         method_prototype
5732           = lookup_method_in_protocol_list (rprotos, sel_name,
5733                                             is_class != NULL_TREE);
5734       if (!method_prototype && !rprotos)
5735         method_prototype
5736           = lookup_method_in_hash_lists (sel_name,
5737                                          is_class != NULL_TREE);
5738     }
5739   else
5740     {
5741       tree orig_rtype = rtype, saved_rtype;
5742
5743       if (TREE_CODE (rtype) == POINTER_TYPE)
5744         rtype = TREE_TYPE (rtype);
5745       /* Traverse typedef aliases */
5746       while (TREE_CODE (rtype) == RECORD_TYPE && TYPE_NAME (rtype)
5747              && TREE_CODE (TYPE_NAME (rtype)) == TYPE_DECL
5748              && DECL_ORIGINAL_TYPE (TYPE_NAME (rtype)))
5749         rtype = DECL_ORIGINAL_TYPE (TYPE_NAME (rtype));
5750       saved_rtype = rtype;
5751       if (TYPED_OBJECT (rtype))
5752         {
5753           rprotos = TYPE_PROTOCOL_LIST (rtype);
5754           rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
5755         }
5756       /* If we could not find an @interface declaration, we must have
5757          only seen a @class declaration; so, we cannot say anything
5758          more intelligent about which methods the receiver will
5759          understand. */
5760       if (!rtype)
5761         rtype = saved_rtype;
5762       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
5763           || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
5764         {
5765           /* We have a valid ObjC class name.  Look up the method name
5766              in the published @interface for the class (and its
5767              superclasses). */
5768           method_prototype
5769             = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
5770
5771           /* If the method was not found in the @interface, it may still
5772              exist locally as part of the @implementation.  */
5773           if (!method_prototype && objc_implementation_context
5774              && CLASS_NAME (objc_implementation_context)
5775                 == OBJC_TYPE_NAME (rtype))                      
5776             method_prototype
5777               = lookup_method
5778                 ((is_class
5779                   ? CLASS_CLS_METHODS (objc_implementation_context)
5780                   : CLASS_NST_METHODS (objc_implementation_context)),
5781                   sel_name);
5782
5783           /* If we haven't found a candidate method by now, try looking for
5784              it in the protocol list.  */
5785           if (!method_prototype && rprotos)
5786             method_prototype
5787               = lookup_method_in_protocol_list (rprotos, sel_name,
5788                                                 is_class != NULL_TREE);
5789         }
5790       else
5791         {
5792           warning ("invalid receiver type `%s'",
5793                    gen_declaration (orig_rtype, errbuf));
5794           rtype = rprotos = NULL_TREE;
5795         }
5796     }   
5797
5798   if (!method_prototype)
5799     {
5800       static bool warn_missing_methods = false;
5801
5802       if (rtype)
5803         warning ("`%s' may not respond to `%c%s'",
5804                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
5805                  (is_class ? '+' : '-'),
5806                  IDENTIFIER_POINTER (sel_name));
5807       if (rprotos)
5808         warning ("`%c%s' not implemented by protocol(s)",
5809                  (is_class ? '+' : '-'),
5810                  IDENTIFIER_POINTER (sel_name));
5811       if (!warn_missing_methods)
5812         {
5813           warning ("(Messages without a matching method signature");
5814           warning ("will be assumed to return `id' and accept");
5815           warning ("`...' as arguments.)");
5816           warn_missing_methods = true;
5817         }
5818     }
5819
5820   /* Save the selector name for printing error messages.  */
5821   current_objc_message_selector = sel_name;
5822
5823   /* Build the parameters list for looking up the method.
5824      These are the object itself and the selector.  */
5825
5826   if (flag_typed_selectors)
5827     selector = build_typed_selector_reference (sel_name, method_prototype);
5828   else
5829     selector = build_selector_reference (sel_name);
5830
5831   retval = build_objc_method_call (super, method_prototype,
5832                                    receiver,
5833                                    selector, method_params);
5834
5835   current_objc_message_selector = 0;
5836
5837   return retval;
5838 }
5839 \f
5840 /* Build a tree expression to send OBJECT the operation SELECTOR,
5841    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5842    assuming the method has prototype METHOD_PROTOTYPE.
5843    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5844    Use METHOD_PARAMS as list of args to pass to the method.
5845    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
5846
5847 static tree
5848 build_objc_method_call (int super_flag, tree method_prototype,
5849                         tree lookup_object, tree selector,
5850                         tree method_params)
5851 {
5852   tree sender = (super_flag ? umsg_super_decl :
5853                  (!flag_next_runtime || flag_nil_receivers
5854                   ? umsg_decl
5855                   : umsg_nonnil_decl));
5856   tree rcv_p = (super_flag ? super_type : id_type);
5857
5858   /* If a prototype for the method to be called exists, then cast
5859      the sender's return type and arguments to match that of the method.
5860      Otherwise, leave sender as is.  */
5861   tree ret_type
5862     = (method_prototype
5863        ? groktypename (TREE_TYPE (method_prototype))
5864        : id_type);
5865   tree sender_cast
5866     = build_pointer_type
5867       (build_function_type
5868        (ret_type,
5869         get_arg_type_list
5870         (method_prototype, METHOD_REF, super_flag)));
5871
5872   lookup_object = build_c_cast (rcv_p, lookup_object);
5873
5874   if (flag_next_runtime)
5875     {
5876       /* If we are returning a struct in memory, and the address
5877          of that memory location is passed as a hidden first
5878          argument, then change which messenger entry point this
5879          expr will call.  NB: Note that sender_cast remains
5880          unchanged (it already has a struct return type).  */
5881       if (!targetm.calls.struct_value_rtx (0, 0)
5882           && (TREE_CODE (ret_type) == RECORD_TYPE
5883               || TREE_CODE (ret_type) == UNION_TYPE)
5884           && targetm.calls.return_in_memory (ret_type, 0))
5885         sender = (super_flag ? umsg_super_stret_decl :
5886                 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
5887
5888       method_params = tree_cons (NULL_TREE, lookup_object,
5889                                  tree_cons (NULL_TREE, selector,
5890                                             method_params));
5891       TREE_USED (sender) = 1;
5892       assemble_external (sender);
5893       /* We want to cast the sender, not convert it.  */
5894       return build_function_call (build_c_cast (sender_cast, sender),
5895                                   method_params);
5896     }
5897   else
5898     {
5899       /* This is the portable (GNU) way.  */
5900       tree method, object;
5901
5902       /* First, call the lookup function to get a pointer to the method,
5903          then cast the pointer, then call it with the method arguments.
5904          Use SAVE_EXPR to avoid evaluating the receiver twice.  */
5905       lookup_object = save_expr (lookup_object);
5906       object = (super_flag ? self_decl : lookup_object);
5907       TREE_USED (sender) = 1;
5908       assemble_external (sender);
5909       method
5910         = build_function_call (sender,
5911                                tree_cons (NULL_TREE, lookup_object,
5912                                           tree_cons (NULL_TREE, selector,
5913                                                      NULL_TREE)));
5914
5915       /* Pass the object to the method.  */
5916       TREE_USED (method) = 1;
5917       assemble_external (method);
5918       return build_function_call
5919              (build_c_cast (sender_cast, method),
5920               tree_cons (NULL_TREE, object,
5921                          tree_cons (NULL_TREE, selector, method_params)));
5922     }
5923 }
5924 \f
5925 static void
5926 build_protocol_reference (tree p)
5927 {
5928   tree decl, ident, ptype;
5929
5930   /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5931
5932   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5933   ptype
5934     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5935                                                       objc_protocol_template),
5936                                      NULL_TREE));
5937
5938   if (identifier_global_value (ident))
5939     decl = identifier_global_value (ident); /* Set by pushdecl.  */
5940   else
5941     {
5942       decl = build_decl (VAR_DECL, ident, ptype);
5943       DECL_EXTERNAL (decl) = 1;
5944       TREE_PUBLIC (decl) = 0;
5945       TREE_USED (decl) = 1;
5946       DECL_ARTIFICIAL (decl) = 1;
5947
5948       make_decl_rtl (decl, 0);
5949       pushdecl_top_level (decl);
5950    }
5951
5952   PROTOCOL_FORWARD_DECL (p) = decl;
5953 }
5954
5955 /* This function is called by the parser when (and only when) a
5956    @protocol() expression is found, in order to compile it.  */
5957 tree
5958 build_protocol_expr (tree protoname)
5959 {
5960   tree expr;
5961   tree p = lookup_protocol (protoname);
5962
5963   if (!p)
5964     {
5965       error ("cannot find protocol declaration for `%s'",
5966              IDENTIFIER_POINTER (protoname));
5967       return error_mark_node;
5968     }
5969
5970   if (!PROTOCOL_FORWARD_DECL (p))
5971     build_protocol_reference (p);
5972
5973   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5974
5975   /* ??? Ideally we'd build the reference with protocol_type directly,
5976      if we have it, rather than converting it here.  */
5977   expr = convert (protocol_type, expr);
5978
5979   /* The @protocol() expression is being compiled into a pointer to a
5980      statically allocated instance of the Protocol class.  To become
5981      usable at runtime, the 'isa' pointer of the instance need to be
5982      fixed up at runtime by the runtime library, to point to the
5983      actual 'Protocol' class.  */
5984
5985   /* For the GNU runtime, put the static Protocol instance in the list
5986      of statically allocated instances, so that we make sure that its
5987      'isa' pointer is fixed up at runtime by the GNU runtime library
5988      to point to the Protocol class (at runtime, when loading the
5989      module, the GNU runtime library loops on the statically allocated
5990      instances (as found in the defs field in objc_symtab) and fixups
5991      all the 'isa' pointers of those objects).  */
5992   if (! flag_next_runtime)
5993     {
5994       /* This type is a struct containing the fields of a Protocol
5995         object.  (Cfr. protocol_type instead is the type of a pointer
5996         to such a struct).  */
5997       tree protocol_struct_type = xref_tag
5998        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
5999       tree *chain;
6000
6001       /* Look for the list of Protocol statically allocated instances
6002         to fixup at runtime.  Create a new list to hold Protocol
6003         statically allocated instances, if the list is not found.  At
6004         present there is only another list, holding NSConstantString
6005         static instances to be fixed up at runtime.  */
6006       for (chain = &objc_static_instances;
6007            *chain && TREE_VALUE (*chain) != protocol_struct_type;
6008            chain = &TREE_CHAIN (*chain));
6009       if (!*chain)
6010         {
6011          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6012          add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6013                           class_names);
6014        }
6015
6016       /* Add this statically allocated instance to the Protocol list.  */
6017       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6018                                          PROTOCOL_FORWARD_DECL (p),
6019                                          TREE_PURPOSE (*chain));
6020     }
6021
6022
6023   return expr;
6024 }
6025
6026 /* This function is called by the parser when a @selector() expression
6027    is found, in order to compile it.  It is only called by the parser
6028    and only to compile a @selector().  */
6029 tree
6030 build_selector_expr (tree selnamelist)
6031 {
6032   tree selname;
6033
6034   /* Obtain the full selector name.  */
6035   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6036     /* A unary selector.  */
6037     selname = selnamelist;
6038   else if (TREE_CODE (selnamelist) == TREE_LIST)
6039     selname = build_keyword_selector (selnamelist);
6040   else
6041     abort ();
6042
6043   /* If we are required to check @selector() expressions as they
6044      are found, check that the selector has been declared.  */
6045   if (warn_undeclared_selector)
6046     {
6047       /* Look the selector up in the list of all known class and
6048          instance methods (up to this line) to check that the selector
6049          exists.  */
6050       hash hsh;
6051
6052       /* First try with instance methods.  */
6053       hsh = hash_lookup (nst_method_hash_list, selname);
6054
6055       /* If not found, try with class methods.  */
6056       if (!hsh)
6057         {
6058           hsh = hash_lookup (cls_method_hash_list, selname);
6059         }
6060
6061       /* If still not found, print out a warning.  */
6062       if (!hsh)
6063         {
6064           warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
6065         }
6066     }
6067
6068
6069   if (flag_typed_selectors)
6070     return build_typed_selector_reference (selname, 0);
6071   else
6072     return build_selector_reference (selname);
6073 }
6074
6075 tree
6076 build_encode_expr (tree type)
6077 {
6078   tree result;
6079   const char *string;
6080
6081   encode_type (type, obstack_object_size (&util_obstack),
6082                OBJC_ENCODE_INLINE_DEFS);
6083   obstack_1grow (&util_obstack, 0);    /* null terminate string */
6084   string = obstack_finish (&util_obstack);
6085
6086   /* Synthesize a string that represents the encoded struct/union.  */
6087   result = my_build_string (strlen (string) + 1, string);
6088   obstack_free (&util_obstack, util_firstobj);
6089   return result;
6090 }
6091
6092 tree
6093 build_ivar_reference (tree id)
6094 {
6095   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6096     {
6097       /* Historically, a class method that produced objects (factory
6098          method) would assign `self' to the instance that it
6099          allocated.  This would effectively turn the class method into
6100          an instance method.  Following this assignment, the instance
6101          variables could be accessed.  That practice, while safe,
6102          violates the simple rule that a class method should not refer
6103          to an instance variable.  It's better to catch the cases
6104          where this is done unknowingly than to support the above
6105          paradigm.  */
6106       warning ("instance variable `%s' accessed in class method",
6107                IDENTIFIER_POINTER (id));
6108       TREE_TYPE (self_decl) = instance_type; /* cast */
6109     }
6110
6111   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
6112 }
6113 \f
6114 /* Compute a hash value for a given method SEL_NAME.  */
6115
6116 static size_t
6117 hash_func (tree sel_name)
6118 {
6119   const unsigned char *s
6120     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6121   size_t h = 0;
6122
6123   while (*s)
6124     h = h * 67 + *s++ - 113;
6125   return h;
6126 }
6127
6128 static void
6129 hash_init (void)
6130 {
6131   nst_method_hash_list
6132     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6133   cls_method_hash_list
6134     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6135 }
6136
6137 /* WARNING!!!!  hash_enter is called with a method, and will peek
6138    inside to find its selector!  But hash_lookup is given a selector
6139    directly, and looks for the selector that's inside the found
6140    entry's key (method) for comparison.  */
6141
6142 static void
6143 hash_enter (hash *hashlist, tree method)
6144 {
6145   hash obj;
6146   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6147
6148   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6149   obj->list = 0;
6150   obj->next = hashlist[slot];
6151   obj->key = method;
6152
6153   hashlist[slot] = obj;         /* append to front */
6154 }
6155
6156 static hash
6157 hash_lookup (hash *hashlist, tree sel_name)
6158 {
6159   hash target;
6160
6161   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6162
6163   while (target)
6164     {
6165       if (sel_name == METHOD_SEL_NAME (target->key))
6166         return target;
6167
6168       target = target->next;
6169     }
6170   return 0;
6171 }
6172
6173 static void
6174 hash_add_attr (hash entry, tree value)
6175 {
6176   attr obj;
6177
6178   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6179   obj->next = entry->list;
6180   obj->value = value;
6181
6182   entry->list = obj;            /* append to front */
6183 }
6184 \f
6185 static tree
6186 lookup_method (tree mchain, tree method)
6187 {
6188   tree key;
6189
6190   if (TREE_CODE (method) == IDENTIFIER_NODE)
6191     key = method;
6192   else
6193     key = METHOD_SEL_NAME (method);
6194
6195   while (mchain)
6196     {
6197       if (METHOD_SEL_NAME (mchain) == key)
6198         return mchain;
6199
6200       mchain = TREE_CHAIN (mchain);
6201     }
6202   return NULL_TREE;
6203 }
6204
6205 static tree
6206 lookup_method_static (tree interface, tree ident, int is_class)
6207 {
6208   tree meth = NULL_TREE, root_inter = NULL_TREE;
6209   tree inter = interface;
6210
6211   while (inter)
6212     {
6213       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6214       tree category = inter;
6215
6216       /* First, look up the method in the class itself.  */
6217       if ((meth = lookup_method (chain, ident)))
6218         return meth;
6219
6220       /* Failing that, look for the method in each category of the class.  */
6221       while ((category = CLASS_CATEGORY_LIST (category)))
6222         {
6223           chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6224
6225           /* Check directly in each category.  */
6226           if ((meth = lookup_method (chain, ident)))
6227             return meth;
6228
6229           /* Failing that, check in each category's protocols.  */
6230           if (CLASS_PROTOCOL_LIST (category))
6231             {
6232               if ((meth = (lookup_method_in_protocol_list
6233                            (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6234                 return meth;
6235             }
6236         }
6237
6238       /* If not found in categories, check in protocols of the main class.  */
6239       if (CLASS_PROTOCOL_LIST (inter))
6240         {
6241           if ((meth = (lookup_method_in_protocol_list
6242                        (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6243             return meth;
6244         }
6245
6246       /* Failing that, climb up the inheritance hierarchy.  */
6247       root_inter = inter;
6248       inter = lookup_interface (CLASS_SUPER_NAME (inter));
6249     }
6250   while (inter);
6251
6252   /* If no class (factory) method was found, check if an _instance_
6253      method of the same name exists in the root class.  This is what
6254      the Objective-C runtime will do.  If an instance method was not
6255      found, return 0.  */
6256   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6257 }
6258
6259 /* Add the method to the hash list if it doesn't contain an identical
6260    method already. */
6261 static void
6262 add_method_to_hash_list (hash *hash_list, tree method)
6263 {
6264   hash hsh;
6265
6266   if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6267     {
6268       /* Install on a global chain.  */
6269       hash_enter (hash_list, method);
6270     }
6271   else
6272     {
6273       /* Check types against those; if different, add to a list.  */
6274       attr loop;
6275       int already_there = comp_proto_with_proto (method, hsh->key);
6276       for (loop = hsh->list; !already_there && loop; loop = loop->next)
6277         already_there |= comp_proto_with_proto (method, loop->value);
6278       if (!already_there)
6279         hash_add_attr (hsh, method);
6280     }
6281 }
6282
6283 tree
6284 objc_add_method (tree class, tree method, int is_class)
6285 {
6286   tree mth;
6287
6288   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
6289     {
6290       /* put method on list in reverse order */
6291       if (is_class)
6292         {
6293           TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6294           CLASS_CLS_METHODS (class) = method;
6295         }
6296       else
6297         {
6298           TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6299           CLASS_NST_METHODS (class) = method;
6300         }
6301     }
6302   else
6303     {
6304       /* When processing an @interface for a class or category, give hard
6305          errors on methods with identical selectors but differing argument
6306          and/or return types. We do not do this for @implementations, because
6307          C/C++ will do it for us (i.e., there will be duplicate function
6308          definition errors).  */
6309       if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6310            || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6311           && !comp_proto_with_proto (method, mth))
6312         error ("duplicate declaration of method `%c%s'",
6313                 is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6314     }
6315
6316   if (is_class)
6317     add_method_to_hash_list (cls_method_hash_list, method);
6318   else
6319     {
6320       add_method_to_hash_list (nst_method_hash_list, method);
6321
6322       /* Instance methods in root classes (and categories thereof)
6323          may acts as class methods as a last resort. */
6324       if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6325           || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6326         class = lookup_interface (CLASS_NAME (class));
6327
6328       if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
6329           && !CLASS_SUPER_NAME (class))
6330         add_method_to_hash_list (cls_method_hash_list, method);
6331     }
6332
6333   return method;
6334 }
6335
6336 static tree
6337 add_class (tree class)
6338 {
6339   /* Put interfaces on list in reverse order.  */
6340   TREE_CHAIN (class) = interface_chain;
6341   interface_chain = class;
6342   return interface_chain;
6343 }
6344
6345 static void
6346 add_category (tree class, tree category)
6347 {
6348   /* Put categories on list in reverse order.  */
6349   tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
6350
6351   if (cat)
6352     {
6353       warning ("duplicate interface declaration for category `%s(%s)'",
6354                IDENTIFIER_POINTER (CLASS_NAME (class)),
6355                IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
6356     }
6357   else
6358     {
6359       CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
6360       CLASS_CATEGORY_LIST (class) = category;
6361     }
6362 }
6363
6364 /* Called after parsing each instance variable declaration. Necessary to
6365    preserve typedefs and implement public/private...
6366
6367    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
6368
6369 tree
6370 add_instance_variable (tree class, int public, tree declarator,
6371                        tree declspecs, tree width)
6372 {
6373   tree field_decl = grokfield (declarator, declspecs, width);
6374   tree field_type = TREE_TYPE (field_decl);
6375   const char *ivar_name = DECL_NAME (field_decl)
6376                           ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
6377                           : "<unnamed>";
6378   tree raw_decl;
6379
6380 #ifdef OBJCPLUS
6381   if (TREE_CODE (field_type) == REFERENCE_TYPE)
6382     {
6383       error ("illegal reference type specified for instance variable `%s'",
6384              ivar_name);
6385       /* Return class as is without adding this ivar.  */
6386       return class;
6387     }
6388 #endif
6389
6390   if (field_type == error_mark_node || !TYPE_SIZE (field_type)
6391       || TYPE_SIZE (field_type) == error_mark_node
6392       /* 'type[0]' is allowed, but 'type[]' is not! */
6393 #ifdef OBJCPLUS
6394       || (TYPE_SIZE (field_type) == bitsize_zero_node
6395           && !TREE_OPERAND (declarator, 1))
6396 #endif
6397       )
6398     {
6399       error ("instance variable `%s' has unknown size", ivar_name);
6400       /* Return class as is without adding this ivar.  */
6401       return class;
6402     }
6403
6404 #ifdef OBJCPLUS
6405   /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
6406      cannot be ivars; ditto for classes with vtables. */
6407   if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
6408       || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
6409     {
6410       const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
6411       if(TYPE_POLYMORPHIC_P (field_type)) {
6412         /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
6413         error ("type `%s' has virtual member functions", type_name);
6414         error ("illegal aggregate type `%s' specified for instance variable `%s'",
6415                type_name, ivar_name);
6416         /* Return class as is without adding this ivar.  */
6417         return class;
6418       }
6419       /* user-defined constructors and destructors are not known to Obj-C and
6420          hence will not be called.  This may or may not be a problem. */
6421       if (TYPE_NEEDS_CONSTRUCTING (field_type))
6422         warning ("type `%s' has a user-defined constructor", type_name);
6423       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
6424         warning ("type `%s' has a user-defined destructor", type_name);
6425       warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
6426     }
6427 #endif
6428
6429   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
6430   switch (public)
6431     {
6432     case 0:
6433       TREE_PUBLIC (field_decl) = 0;
6434       TREE_PRIVATE (field_decl) = 0;
6435       TREE_PROTECTED (field_decl) = 1;
6436       break;
6437
6438     case 1:
6439       TREE_PUBLIC (field_decl) = 1;
6440       TREE_PRIVATE (field_decl) = 0;
6441       TREE_PROTECTED (field_decl) = 0;
6442       break;
6443
6444     case 2:
6445       TREE_PUBLIC (field_decl) = 0;
6446       TREE_PRIVATE (field_decl) = 1;
6447       TREE_PROTECTED (field_decl) = 0;
6448       break;
6449
6450     }
6451
6452   raw_decl = build_tree_list (declspecs, build_tree_list (declarator, width));
6453   CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), raw_decl);
6454   CLASS_IVARS (class) = chainon (CLASS_IVARS (class), field_decl);
6455   return class;
6456 }
6457 \f
6458 tree
6459 is_ivar (tree decl_chain, tree ident)
6460 {
6461   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
6462     if (DECL_NAME (decl_chain) == ident)
6463       return decl_chain;
6464   return NULL_TREE;
6465 }
6466
6467 /* True if the ivar is private and we are not in its implementation.  */
6468
6469 int
6470 is_private (tree decl)
6471 {
6472   if (TREE_PRIVATE (decl)
6473       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
6474     {
6475       error ("instance variable `%s' is declared private",
6476              IDENTIFIER_POINTER (DECL_NAME (decl)));
6477       return 1;
6478     }
6479   else
6480     return 0;
6481 }
6482
6483 /* We have an instance variable reference;, check to see if it is public.  */
6484
6485 int
6486 is_public (tree expr, tree identifier)
6487 {
6488   tree basetype = TREE_TYPE (expr);
6489   enum tree_code code = TREE_CODE (basetype);
6490   tree decl;
6491
6492   if (code == RECORD_TYPE)
6493     {
6494       if (TREE_STATIC_TEMPLATE (basetype))
6495         {
6496           if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6497             {
6498               error ("cannot find interface declaration for `%s'",
6499                      IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6500               return 0;
6501             }
6502
6503           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6504             {
6505               if (TREE_PUBLIC (decl))
6506                 return 1;
6507
6508               /* Important difference between the Stepstone translator:
6509                  all instance variables should be public within the context
6510                  of the implementation.  */
6511               if (objc_implementation_context
6512                   && (((TREE_CODE (objc_implementation_context)
6513                         == CLASS_IMPLEMENTATION_TYPE)
6514                        || (TREE_CODE (objc_implementation_context)
6515                            == CATEGORY_IMPLEMENTATION_TYPE))
6516                       && (CLASS_NAME (objc_implementation_context)
6517                           == OBJC_TYPE_NAME (basetype))))
6518                 return ! is_private (decl);
6519
6520               /* The 2.95.2 compiler sometimes allowed C functions to access
6521                  non-@public ivars.  We will let this slide for now...  */
6522               if (!objc_method_context)
6523               {
6524                 warning ("instance variable `%s' is %s; "
6525                          "this will be a hard error in the future",
6526                          IDENTIFIER_POINTER (identifier),
6527                          TREE_PRIVATE (decl) ? "@private" : "@protected");
6528                 return 1;
6529               }
6530                 
6531               error ("instance variable `%s' is declared %s",
6532                      IDENTIFIER_POINTER (identifier),
6533                      TREE_PRIVATE (decl) ? "private" : "protected");
6534               return 0;
6535             }
6536         }
6537
6538       else if (objc_implementation_context && (basetype == objc_object_reference))
6539         {
6540           TREE_TYPE (expr) = uprivate_record;
6541           warning ("static access to object of type `id'");
6542         }
6543     }
6544
6545   return 1;
6546 }
6547 \f
6548 /* Make sure all entries in CHAIN are also in LIST.  */
6549
6550 static int
6551 check_methods (tree chain, tree list, int mtype)
6552 {
6553   int first = 1;
6554
6555   while (chain)
6556     {
6557       if (!lookup_method (list, chain))
6558         {
6559           if (first)
6560             {
6561               if (TREE_CODE (objc_implementation_context)
6562                   == CLASS_IMPLEMENTATION_TYPE)
6563                 warning ("incomplete implementation of class `%s'",
6564                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6565               else if (TREE_CODE (objc_implementation_context)
6566                        == CATEGORY_IMPLEMENTATION_TYPE)
6567                 warning ("incomplete implementation of category `%s'",
6568                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6569               first = 0;
6570             }
6571
6572           warning ("method definition for `%c%s' not found",
6573                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6574         }
6575
6576       chain = TREE_CHAIN (chain);
6577     }
6578
6579     return first;
6580 }
6581
6582 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
6583
6584 static int
6585 conforms_to_protocol (tree class, tree protocol)
6586 {
6587    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6588      {
6589        tree p = CLASS_PROTOCOL_LIST (class);
6590        while (p && TREE_VALUE (p) != protocol)
6591          p = TREE_CHAIN (p);
6592
6593        if (!p)
6594          {
6595            tree super = (CLASS_SUPER_NAME (class)
6596                          ? lookup_interface (CLASS_SUPER_NAME (class))
6597                          : NULL_TREE);
6598            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6599            if (!tmp)
6600              return 0;
6601          }
6602      }
6603
6604    return 1;
6605 }
6606
6607 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6608    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
6609
6610 static int
6611 check_methods_accessible (tree chain, tree context, int mtype)
6612 {
6613   int first = 1;
6614   tree list;
6615   tree base_context = context;
6616
6617   while (chain)
6618     {
6619       context = base_context;
6620       while (context)
6621         {
6622           if (mtype == '+')
6623             list = CLASS_CLS_METHODS (context);
6624           else
6625             list = CLASS_NST_METHODS (context);
6626
6627           if (lookup_method (list, chain))
6628               break;
6629
6630           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6631                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6632             context = (CLASS_SUPER_NAME (context)
6633                        ? lookup_interface (CLASS_SUPER_NAME (context))
6634                        : NULL_TREE);
6635
6636           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6637                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6638             context = (CLASS_NAME (context)
6639                        ? lookup_interface (CLASS_NAME (context))
6640                        : NULL_TREE);
6641           else
6642             abort ();
6643         }
6644
6645       if (context == NULL_TREE)
6646         {
6647           if (first)
6648             {
6649               if (TREE_CODE (objc_implementation_context)
6650                   == CLASS_IMPLEMENTATION_TYPE)
6651                 warning ("incomplete implementation of class `%s'",
6652                          IDENTIFIER_POINTER
6653                            (CLASS_NAME (objc_implementation_context)));
6654               else if (TREE_CODE (objc_implementation_context)
6655                        == CATEGORY_IMPLEMENTATION_TYPE)
6656                 warning ("incomplete implementation of category `%s'",
6657                          IDENTIFIER_POINTER
6658                            (CLASS_SUPER_NAME (objc_implementation_context)));
6659               first = 0;
6660             }
6661           warning ("method definition for `%c%s' not found",
6662                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6663         }
6664
6665       chain = TREE_CHAIN (chain); /* next method...  */
6666     }
6667   return first;
6668 }
6669
6670 /* Check whether the current interface (accessible via
6671    'objc_implementation_context') actually implements protocol P, along
6672    with any protocols that P inherits.  */
6673
6674 static void
6675 check_protocol (tree p, const char *type, const char *name)
6676 {
6677   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6678     {
6679       int f1, f2;
6680
6681       /* Ensure that all protocols have bodies!  */
6682       if (warn_protocol)
6683         {
6684           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6685                               CLASS_CLS_METHODS (objc_implementation_context),
6686                               '+');
6687           f2 = check_methods (PROTOCOL_NST_METHODS (p),
6688                               CLASS_NST_METHODS (objc_implementation_context),
6689                               '-');
6690         }
6691       else
6692         {
6693           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6694                                          objc_implementation_context,
6695                                          '+');
6696           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6697                                          objc_implementation_context,
6698                                          '-');
6699         }
6700
6701       if (!f1 || !f2)
6702         warning ("%s `%s' does not fully implement the `%s' protocol",
6703                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6704     }
6705
6706   /* Check protocols recursively.  */
6707   if (PROTOCOL_LIST (p))
6708     {
6709       tree subs = PROTOCOL_LIST (p);
6710       tree super_class =
6711         lookup_interface (CLASS_SUPER_NAME (implementation_template));
6712
6713       while (subs)
6714         {
6715           tree sub = TREE_VALUE (subs);
6716
6717           /* If the superclass does not conform to the protocols
6718              inherited by P, then we must!  */
6719           if (!super_class || !conforms_to_protocol (super_class, sub))
6720             check_protocol (sub, type, name);
6721           subs = TREE_CHAIN (subs);
6722         }
6723     }
6724 }
6725
6726 /* Check whether the current interface (accessible via
6727    'objc_implementation_context') actually implements the protocols listed
6728    in PROTO_LIST.  */
6729
6730 static void
6731 check_protocols (tree proto_list, const char *type, const char *name)
6732 {
6733   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6734     {
6735       tree p = TREE_VALUE (proto_list);
6736
6737       check_protocol (p, type, name);
6738     }
6739 }
6740 \f
6741 /* Make sure that the class CLASS_NAME is defined
6742    CODE says which kind of thing CLASS_NAME ought to be.
6743    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6744    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
6745
6746 tree
6747 start_class (enum tree_code code, tree class_name, tree super_name,
6748              tree protocol_list)
6749 {
6750   tree class, decl;
6751
6752 #ifdef OBJCPLUS
6753   if (current_namespace != global_namespace) {
6754     error ("Objective-C declarations may only appear in global scope");
6755   }
6756 #endif /* OBJCPLUS */
6757
6758   if (objc_implementation_context)
6759     {
6760       warning ("`@end' missing in implementation context");
6761       finish_class (objc_implementation_context);
6762       objc_ivar_chain = NULL_TREE;
6763       objc_implementation_context = NULL_TREE;
6764     }
6765
6766   class = make_node (code);
6767   TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
6768
6769   CLASS_NAME (class) = class_name;
6770   CLASS_SUPER_NAME (class) = super_name;
6771   CLASS_CLS_METHODS (class) = NULL_TREE;
6772
6773   if (! is_class_name (class_name)
6774       && (decl = lookup_name (class_name)))
6775     {
6776       error ("`%s' redeclared as different kind of symbol",
6777              IDENTIFIER_POINTER (class_name));
6778       error ("%Jprevious declaration of '%D'",
6779              decl, decl);
6780     }
6781
6782   if (code == CLASS_IMPLEMENTATION_TYPE)
6783     {
6784       {
6785         tree chain;
6786
6787         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6788            if (TREE_VALUE (chain) == class_name)
6789              {
6790                error ("reimplementation of class `%s'",
6791                       IDENTIFIER_POINTER (class_name));
6792                return error_mark_node;
6793              }
6794         implemented_classes = tree_cons (NULL_TREE, class_name,
6795                                          implemented_classes);
6796       }
6797
6798       /* Reset for multiple classes per file.  */
6799       method_slot = 0;
6800
6801       objc_implementation_context = class;
6802
6803       /* Lookup the interface for this implementation.  */
6804
6805       if (!(implementation_template = lookup_interface (class_name)))
6806         {
6807           warning ("cannot find interface declaration for `%s'",
6808                    IDENTIFIER_POINTER (class_name));
6809           add_class (implementation_template = objc_implementation_context);
6810         }
6811
6812       /* If a super class has been specified in the implementation,
6813          insure it conforms to the one specified in the interface.  */
6814
6815       if (super_name
6816           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6817         {
6818           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6819           const char *const name =
6820             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6821           error ("conflicting super class name `%s'",
6822                  IDENTIFIER_POINTER (super_name));
6823           error ("previous declaration of `%s'", name);
6824         }
6825
6826       else if (! super_name)
6827         {
6828           CLASS_SUPER_NAME (objc_implementation_context)
6829             = CLASS_SUPER_NAME (implementation_template);
6830         }
6831     }
6832
6833   else if (code == CLASS_INTERFACE_TYPE)
6834     {
6835       if (lookup_interface (class_name))
6836 #ifdef OBJCPLUS
6837         error ("duplicate interface declaration for class `%s'",
6838 #else
6839         warning ("duplicate interface declaration for class `%s'",
6840 #endif  
6841         IDENTIFIER_POINTER (class_name));
6842       else
6843         add_class (class);
6844
6845       if (protocol_list)
6846         CLASS_PROTOCOL_LIST (class)
6847           = lookup_and_install_protocols (protocol_list);
6848     }
6849
6850   else if (code == CATEGORY_INTERFACE_TYPE)
6851     {
6852       tree class_category_is_assoc_with;
6853
6854       /* For a category, class_name is really the name of the class that
6855          the following set of methods will be associated with. We must
6856          find the interface so that can derive the objects template.  */
6857
6858       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6859         {
6860           error ("cannot find interface declaration for `%s'",
6861                  IDENTIFIER_POINTER (class_name));
6862           exit (FATAL_EXIT_CODE);
6863         }
6864       else
6865         add_category (class_category_is_assoc_with, class);
6866
6867       if (protocol_list)
6868         CLASS_PROTOCOL_LIST (class)
6869           = lookup_and_install_protocols (protocol_list);
6870     }
6871
6872   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6873     {
6874       /* Reset for multiple classes per file.  */
6875       method_slot = 0;
6876
6877       objc_implementation_context = class;
6878
6879       /* For a category, class_name is really the name of the class that
6880          the following set of methods will be associated with.  We must
6881          find the interface so that can derive the objects template.  */
6882
6883       if (!(implementation_template = lookup_interface (class_name)))
6884         {
6885           error ("cannot find interface declaration for `%s'",
6886                  IDENTIFIER_POINTER (class_name));
6887           exit (FATAL_EXIT_CODE);
6888         }
6889     }
6890   return class;
6891 }
6892
6893 tree
6894 continue_class (tree class)
6895 {
6896   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6897       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6898     {
6899       struct imp_entry *imp_entry;
6900       tree ivar_context;
6901
6902       /* Check consistency of the instance variables.  */
6903
6904       if (CLASS_IVARS (class))
6905         check_ivars (implementation_template, class);
6906
6907       /* code generation */
6908
6909       ivar_context = build_private_template (implementation_template);
6910
6911       if (!objc_class_template)
6912         build_class_template ();
6913
6914       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6915
6916       imp_entry->next = imp_list;
6917       imp_entry->imp_context = class;
6918       imp_entry->imp_template = implementation_template;
6919
6920       synth_forward_declarations ();
6921       imp_entry->class_decl = UOBJC_CLASS_decl;
6922       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6923
6924       /* Append to front and increment count.  */
6925       imp_list = imp_entry;
6926       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6927         imp_count++;
6928       else
6929         cat_count++;
6930
6931       return ivar_context;
6932     }
6933
6934   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6935     {
6936       if (!CLASS_STATIC_TEMPLATE (class))
6937         {
6938           tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6939           finish_struct (record, get_class_ivars (class, 0), NULL_TREE);
6940           CLASS_STATIC_TEMPLATE (class) = record;
6941
6942           /* Mark this record as a class template for static typing.  */
6943           TREE_STATIC_TEMPLATE (record) = 1;
6944         }
6945
6946       return NULL_TREE;
6947     }
6948
6949   else
6950     return error_mark_node;
6951 }
6952
6953 /* This is called once we see the "@end" in an interface/implementation.  */
6954
6955 void
6956 finish_class (tree class)
6957 {
6958   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6959     {
6960       /* All code generation is done in finish_objc.  */
6961
6962       if (implementation_template != objc_implementation_context)
6963         {
6964           /* Ensure that all method listed in the interface contain bodies.  */
6965           check_methods (CLASS_CLS_METHODS (implementation_template),
6966                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6967           check_methods (CLASS_NST_METHODS (implementation_template),
6968                          CLASS_NST_METHODS (objc_implementation_context), '-');
6969
6970           if (CLASS_PROTOCOL_LIST (implementation_template))
6971             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6972                              "class",
6973                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6974         }
6975     }
6976
6977   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6978     {
6979       tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6980
6981       if (category)
6982         {
6983           /* Ensure all method listed in the interface contain bodies.  */
6984           check_methods (CLASS_CLS_METHODS (category),
6985                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6986           check_methods (CLASS_NST_METHODS (category),
6987                          CLASS_NST_METHODS (objc_implementation_context), '-');
6988
6989           if (CLASS_PROTOCOL_LIST (category))
6990             check_protocols (CLASS_PROTOCOL_LIST (category),
6991                              "category",
6992                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6993         }
6994     }
6995
6996   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6997     {
6998       tree decl_specs;
6999       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
7000       char *string = (char *) alloca (strlen (class_name) + 3);
7001
7002       /* extern struct objc_object *_<my_name>; */
7003
7004       sprintf (string, "_%s", class_name);
7005
7006       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
7007       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
7008       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
7009                    decl_specs);
7010     }
7011 }
7012
7013 static tree
7014 add_protocol (tree protocol)
7015 {
7016   /* Put protocol on list in reverse order.  */
7017   TREE_CHAIN (protocol) = protocol_chain;
7018   protocol_chain = protocol;
7019   return protocol_chain;
7020 }
7021
7022 static tree
7023 lookup_protocol (tree ident)
7024 {
7025   tree chain;
7026
7027   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7028     if (ident == PROTOCOL_NAME (chain))
7029       return chain;
7030
7031   return NULL_TREE;
7032 }
7033
7034 /* This function forward declares the protocols named by NAMES.  If
7035    they are already declared or defined, the function has no effect.  */
7036
7037 void
7038 objc_declare_protocols (tree names)
7039 {
7040   tree list;
7041
7042 #ifdef OBJCPLUS
7043   if (current_namespace != global_namespace) {
7044     error ("Objective-C declarations may only appear in global scope");
7045   }
7046 #endif /* OBJCPLUS */
7047
7048   for (list = names; list; list = TREE_CHAIN (list))
7049     {
7050       tree name = TREE_VALUE (list);
7051
7052       if (lookup_protocol (name) == NULL_TREE)
7053         {
7054           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7055
7056           TYPE_BINFO (protocol) = make_tree_vec (2);
7057           PROTOCOL_NAME (protocol) = name;
7058           PROTOCOL_LIST (protocol) = NULL_TREE;
7059           add_protocol (protocol);
7060           PROTOCOL_DEFINED (protocol) = 0;
7061           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7062         }
7063     }
7064 }
7065
7066 tree
7067 start_protocol (enum tree_code code, tree name, tree list)
7068 {
7069   tree protocol;
7070
7071 #ifdef OBJCPLUS
7072   if (current_namespace != global_namespace) {
7073     error ("Objective-C declarations may only appear in global scope");
7074   }
7075 #endif /* OBJCPLUS */
7076
7077   /* This is as good a place as any.  Need to invoke
7078      push_tag_toplevel.  */
7079   if (!objc_protocol_template)
7080     objc_protocol_template = build_protocol_template ();
7081
7082   protocol = lookup_protocol (name);
7083
7084   if (!protocol)
7085     {
7086       protocol = make_node (code);
7087       TYPE_BINFO (protocol) = make_tree_vec (2);
7088
7089       PROTOCOL_NAME (protocol) = name;
7090       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7091       add_protocol (protocol);
7092       PROTOCOL_DEFINED (protocol) = 1;
7093       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7094
7095       check_protocol_recursively (protocol, list);
7096     }
7097   else if (! PROTOCOL_DEFINED (protocol))
7098     {
7099       PROTOCOL_DEFINED (protocol) = 1;
7100       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7101
7102       check_protocol_recursively (protocol, list);
7103     }
7104   else
7105     {
7106       warning ("duplicate declaration for protocol `%s'",
7107                IDENTIFIER_POINTER (name));
7108     }
7109   return protocol;
7110 }
7111
7112 void
7113 finish_protocol (tree protocol ATTRIBUTE_UNUSED)
7114 {
7115 }
7116
7117 \f
7118 /* "Encode" a data type into a string, which grows in util_obstack.
7119    ??? What is the FORMAT?  Someone please document this!  */
7120
7121 static void
7122 encode_type_qualifiers (tree declspecs)
7123 {
7124   tree spec;
7125
7126   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7127     {
7128       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
7129         obstack_1grow (&util_obstack, 'r');
7130       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7131         obstack_1grow (&util_obstack, 'n');
7132       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7133         obstack_1grow (&util_obstack, 'N');
7134       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7135         obstack_1grow (&util_obstack, 'o');
7136       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7137         obstack_1grow (&util_obstack, 'O');
7138       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7139         obstack_1grow (&util_obstack, 'R');
7140       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7141         obstack_1grow (&util_obstack, 'V');
7142     }
7143 }
7144
7145 /* Encode a pointer type.  */
7146
7147 static void
7148 encode_pointer (tree type, int curtype, int format)
7149 {
7150   tree pointer_to = TREE_TYPE (type);
7151
7152   if (TREE_CODE (pointer_to) == RECORD_TYPE)
7153     {
7154       if (OBJC_TYPE_NAME (pointer_to)
7155           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7156         {
7157           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7158
7159           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7160             {
7161               obstack_1grow (&util_obstack, '@');
7162               return;
7163             }
7164           else if (TREE_STATIC_TEMPLATE (pointer_to))
7165             {
7166               if (generating_instance_variables)
7167                 {
7168                   obstack_1grow (&util_obstack, '@');
7169                   obstack_1grow (&util_obstack, '"');
7170                   obstack_grow (&util_obstack, name, strlen (name));
7171                   obstack_1grow (&util_obstack, '"');
7172                   return;
7173                 }
7174               else
7175                 {
7176                   obstack_1grow (&util_obstack, '@');
7177                   return;
7178                 }
7179             }
7180           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7181             {
7182               obstack_1grow (&util_obstack, '#');
7183               return;
7184             }
7185           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7186             {
7187               obstack_1grow (&util_obstack, ':');
7188               return;
7189             }
7190         }
7191     }
7192   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7193            && TYPE_MODE (pointer_to) == QImode)
7194     {
7195       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7196                   ? OBJC_TYPE_NAME (pointer_to)
7197                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7198
7199       if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7200         {
7201           obstack_1grow (&util_obstack, '*');
7202           return;
7203         }
7204     }
7205
7206   /* We have a type that does not get special treatment.  */
7207
7208   /* NeXT extension */
7209   obstack_1grow (&util_obstack, '^');
7210   encode_type (pointer_to, curtype, format);
7211 }
7212
7213 static void
7214 encode_array (tree type, int curtype, int format)
7215 {
7216   tree an_int_cst = TYPE_SIZE (type);
7217   tree array_of = TREE_TYPE (type);
7218   char buffer[40];
7219
7220   /* An incomplete array is treated like a pointer.  */
7221   if (an_int_cst == NULL)
7222     {
7223       encode_pointer (type, curtype, format);
7224       return;
7225     }
7226
7227   sprintf (buffer, "[%ld",
7228            (long) (TREE_INT_CST_LOW (an_int_cst)
7229                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7230
7231   obstack_grow (&util_obstack, buffer, strlen (buffer));
7232   encode_type (array_of, curtype, format);
7233   obstack_1grow (&util_obstack, ']');
7234   return;
7235 }
7236 \f
7237 static void
7238 encode_aggregate_within (tree type, int curtype, int format, int left,
7239                          int right)
7240 {
7241   tree name;
7242   /* NB: aggregates that are pointed to have slightly different encoding
7243      rules in that you never encode the names of instance variables.  */
7244   int pointed_to
7245    = (obstack_object_size (&util_obstack) > 0
7246       && *(obstack_next_free (&util_obstack) - 1) == '^');
7247   int inline_contents
7248    = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7249       && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7250
7251   /* Traverse struct aliases; it is important to get the
7252      original struct and its tag name (if any).  */
7253   type = TYPE_MAIN_VARIANT (type);
7254   name = OBJC_TYPE_NAME (type);
7255   /* Open parenth/bracket.  */                          
7256   obstack_1grow (&util_obstack, left);
7257
7258   /* Encode the struct/union tag name, or '?' if a tag was
7259      not provided.  Typedef aliases do not qualify.  */
7260   if (name && TREE_CODE (name) == IDENTIFIER_NODE
7261 #ifdef OBJCPLUS
7262       /* Did this struct have a tag?  */
7263       && !TYPE_WAS_ANONYMOUS (type)
7264 #endif
7265       )
7266     obstack_grow (&util_obstack,
7267                   IDENTIFIER_POINTER (name),
7268                   strlen (IDENTIFIER_POINTER (name)));
7269   else
7270     obstack_1grow (&util_obstack, '?');
7271
7272   /* Encode the types (and possibly names) of the inner fields,
7273      if required.  */
7274   if (inline_contents)
7275     {
7276       tree fields = TYPE_FIELDS (type);
7277
7278       obstack_1grow (&util_obstack, '=');
7279       for (; fields; fields = TREE_CHAIN (fields))
7280         {
7281 #ifdef OBJCPLUS
7282           /* C++ static members, and things that are not fields at all,
7283              should not appear in the encoding.  */
7284           if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7285             continue;
7286 #endif
7287           if (generating_instance_variables && !pointed_to)
7288             {
7289               tree fname = DECL_NAME (fields);
7290
7291               obstack_1grow (&util_obstack, '"');
7292               if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7293                 obstack_grow (&util_obstack,
7294                               IDENTIFIER_POINTER (fname),
7295                               strlen (IDENTIFIER_POINTER (fname)));
7296               obstack_1grow (&util_obstack, '"');
7297             }
7298           encode_field_decl (fields, curtype, format);
7299         }
7300     }
7301   /* Close parenth/bracket.  */                         
7302   obstack_1grow (&util_obstack, right);
7303 }
7304
7305 static void
7306 encode_aggregate (tree type, int curtype, int format)
7307 {
7308   enum tree_code code = TREE_CODE (type);
7309
7310   switch (code)
7311     {
7312     case RECORD_TYPE:
7313       {
7314         encode_aggregate_within (type, curtype, format, '{', '}');
7315         break;
7316       }
7317     case UNION_TYPE:
7318       {
7319         encode_aggregate_within (type, curtype, format, '(', ')');
7320         break;
7321       }
7322
7323     case ENUMERAL_TYPE:
7324       obstack_1grow (&util_obstack, 'i');
7325       break;
7326
7327     default:
7328       break;
7329     }
7330 }
7331
7332 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7333    field type.  */
7334
7335 static void
7336 encode_next_bitfield (int width)
7337 {
7338   char buffer[40];
7339   sprintf (buffer, "b%d", width);
7340   obstack_grow (&util_obstack, buffer, strlen (buffer));
7341 }
7342 \f
7343 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
7344 static void
7345 encode_type (tree type, int curtype, int format)
7346 {
7347   enum tree_code code = TREE_CODE (type);
7348   char c;
7349
7350   if (code == INTEGER_TYPE)
7351     {
7352       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7353         {
7354         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
7355         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
7356         case 32: 
7357           if (type == long_unsigned_type_node
7358               || type == long_integer_type_node)
7359                  c = TYPE_UNSIGNED (type) ? 'L' : 'l';
7360           else
7361                  c = TYPE_UNSIGNED (type) ? 'I' : 'i';
7362           break;
7363         case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
7364         default: abort ();
7365         }
7366       obstack_1grow (&util_obstack, c);
7367     }
7368
7369   else if (code == REAL_TYPE)
7370     {
7371       /* Floating point types.  */
7372       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7373         {
7374         case 32:  c = 'f'; break;
7375         case 64:
7376         case 128: c = 'd'; break;
7377         default: abort ();
7378         }
7379       obstack_1grow (&util_obstack, c);
7380     }
7381
7382   else if (code == VOID_TYPE)
7383     obstack_1grow (&util_obstack, 'v');
7384
7385   else if (code == BOOLEAN_TYPE)
7386     obstack_1grow (&util_obstack, 'B');
7387
7388   else if (code == ARRAY_TYPE)
7389     encode_array (type, curtype, format);
7390
7391   else if (code == POINTER_TYPE)
7392     encode_pointer (type, curtype, format);
7393
7394   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7395     encode_aggregate (type, curtype, format);
7396
7397   else if (code == FUNCTION_TYPE) /* '?' */
7398     obstack_1grow (&util_obstack, '?');
7399 }
7400
7401 static void
7402 encode_gnu_bitfield (int position, tree type, int size)
7403 {
7404   enum tree_code code = TREE_CODE (type);
7405   char buffer[40];
7406   char charType = '?';
7407
7408   if (code == INTEGER_TYPE)
7409     {
7410       if (integer_zerop (TYPE_MIN_VALUE (type)))
7411         {
7412           /* Unsigned integer types.  */
7413
7414           if (TYPE_MODE (type) == QImode)
7415             charType = 'C';
7416           else if (TYPE_MODE (type) == HImode)
7417             charType = 'S';
7418           else if (TYPE_MODE (type) == SImode)
7419             {
7420               if (type == long_unsigned_type_node)
7421                 charType = 'L';
7422               else
7423                 charType = 'I';
7424             }
7425           else if (TYPE_MODE (type) == DImode)
7426             charType = 'Q';
7427         }
7428
7429       else
7430         /* Signed integer types.  */
7431         {
7432           if (TYPE_MODE (type) == QImode)
7433             charType = 'c';
7434           else if (TYPE_MODE (type) == HImode)
7435             charType = 's';
7436           else if (TYPE_MODE (type) == SImode)
7437             {
7438               if (type == long_integer_type_node)
7439                 charType = 'l';
7440               else
7441                 charType = 'i';
7442             }
7443
7444           else if (TYPE_MODE (type) == DImode)
7445             charType = 'q';
7446         }
7447     }
7448   else if (code == ENUMERAL_TYPE)
7449     charType = 'i';
7450   else
7451     abort ();
7452
7453   sprintf (buffer, "b%d%c%d", position, charType, size);
7454   obstack_grow (&util_obstack, buffer, strlen (buffer));
7455 }
7456
7457 static void
7458 encode_field_decl (tree field_decl, int curtype, int format)
7459 {
7460   tree type;
7461
7462 #ifdef OBJCPLUS
7463   /* C++ static members, and things that are not fields at all,
7464      should not appear in the encoding.  */
7465   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7466     return;
7467 #endif
7468
7469   type = TREE_TYPE (field_decl);
7470
7471   /* Generate the bitfield typing information, if needed.  Note the difference
7472      between GNU and NeXT runtimes.  */
7473   if (DECL_BIT_FIELD_TYPE (field_decl))
7474     {
7475       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7476
7477       if (flag_next_runtime)
7478         encode_next_bitfield (size);
7479       else
7480         encode_gnu_bitfield (int_bit_position (field_decl),
7481                                   DECL_BIT_FIELD_TYPE (field_decl), size);
7482     }
7483   else
7484     encode_type (TREE_TYPE (field_decl), curtype, format);
7485 }
7486
7487 static tree
7488 objc_expr_last (tree complex_expr)
7489 {
7490   tree next;
7491
7492   if (complex_expr)
7493     while ((next = TREE_OPERAND (complex_expr, 0)))
7494       complex_expr = next;
7495
7496   return complex_expr;
7497 }
7498
7499 static void
7500 synth_self_and_ucmd_args (void)
7501 {
7502   tree decl_specs;
7503
7504   if (objc_method_context
7505       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7506     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7507   else
7508     /* Really a `struct objc_class *'. However, we allow people to
7509        assign to self, which changes its type midstream.  */
7510     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7511
7512   push_parm_decl (build_tree_list
7513                   (build_tree_list (decl_specs,
7514                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
7515                    unused_list));
7516
7517   decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (selector_type));
7518   push_parm_decl (build_tree_list
7519                   (build_tree_list (decl_specs,
7520                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7521                    unused_list));
7522 }
7523
7524 /* Transform a method definition into a function definition as follows:
7525    - synthesize the first two arguments, "self" and "_cmd".  */
7526
7527 void
7528 start_method_def (tree method)
7529 {
7530   /* Required to implement _msgSuper.  */
7531   objc_method_context = method;
7532   UOBJC_SUPER_decl = NULL_TREE;
7533
7534   /* Must be called BEFORE start_function.  */
7535   push_scope ();
7536   declare_parm_level ();
7537
7538   /* Generate prototype declarations for arguments..."new-style".  */
7539   synth_self_and_ucmd_args ();
7540
7541   /* Generate argument declarations if a keyword_decl.  */
7542   if (METHOD_SEL_ARGS (method))
7543     {
7544       tree arglist = METHOD_SEL_ARGS (method);
7545       do
7546         {
7547           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7548           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7549
7550           if (arg_decl)
7551             {
7552               tree last_expr = objc_expr_last (arg_decl);
7553
7554               /* Unite the abstract decl with its name.  */
7555               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7556               push_parm_decl (build_tree_list
7557                               (build_tree_list (arg_spec, arg_decl),
7558                                NULL_TREE));
7559
7560 #ifndef OBJCPLUS        
7561               /* Unhook: restore the abstract declarator.  */
7562               TREE_OPERAND (last_expr, 0) = NULL_TREE;
7563 #endif  
7564             }
7565
7566           else
7567             push_parm_decl (build_tree_list
7568                             (build_tree_list (arg_spec,
7569                                               KEYWORD_ARG_NAME (arglist)),
7570                              NULL_TREE));
7571
7572           arglist = TREE_CHAIN (arglist);
7573         }
7574       while (arglist);
7575     }
7576
7577   if (METHOD_ADD_ARGS (method) != NULL_TREE
7578       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7579     {
7580       /* We have a variable length selector - in "prototype" format.  */
7581       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7582       while (akey)
7583         {
7584           /* This must be done prior to calling pushdecl.  pushdecl is
7585              going to change our chain on us.  */
7586           tree nextkey = TREE_CHAIN (akey);
7587           pushdecl (akey);
7588           akey = nextkey;
7589         }
7590     }
7591 }
7592
7593 static void
7594 warn_with_method (const char *message, int mtype, tree method)
7595 {
7596   /* Add a readable method name to the warning.  */
7597   warning ("%J%s `%c%s'", method,
7598            message, mtype, gen_method_decl (method, errbuf));
7599 }
7600
7601 /* Return 1 if METHOD is consistent with PROTO.  */
7602
7603 static int
7604 comp_method_with_proto (tree method, tree proto)
7605 {
7606   /* Create a function template node at most once.  */
7607   if (!function1_template)
7608     function1_template = make_node (FUNCTION_TYPE);
7609
7610   /* Install argument types - normally set by build_function_type.  */
7611   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7612
7613   /* install return type */
7614   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7615
7616   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
7617                     false);
7618 }
7619
7620 /* Return 1 if TYPE1 is equivalent to TYPE2.  */
7621
7622 static int
7623 objc_types_are_equivalent (tree type1, tree type2)
7624 {
7625   if (type1 == type2)
7626     return 1;
7627   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7628     return 0;
7629   type1 = TYPE_PROTOCOL_LIST (type1);
7630   type2 = TYPE_PROTOCOL_LIST (type2);
7631   if (list_length (type1) == list_length (type2))
7632     {
7633       for (; type2; type2 = TREE_CHAIN (type2))
7634         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7635           return 0;
7636       return 1;
7637     }
7638   return 0;
7639 }
7640
7641 /* Return 1 if PROTO1 is equivalent to PROTO2.  */
7642
7643 static int
7644 comp_proto_with_proto (tree proto1, tree proto2)
7645 {
7646   tree type1, type2;
7647
7648   /* The following test is needed in case there are hashing
7649      collisions.  */
7650   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7651     return 0;
7652
7653   /* Compare return types.  */
7654   type1 = groktypename (TREE_TYPE (proto1));
7655   type2 = groktypename (TREE_TYPE (proto2));
7656
7657   if (!objc_types_are_equivalent (type1, type2))
7658     return 0;
7659
7660   /* Compare argument types.  */
7661   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7662        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7663        type1 && type2;
7664        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7665     {
7666       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7667         return 0;
7668     }
7669
7670   return (!type1 && !type2);
7671 }
7672
7673 /* - Generate an identifier for the function. the format is "_n_cls",
7674      where 1 <= n <= nMethods, and cls is the name the implementation we
7675      are processing.
7676    - Install the return type from the method declaration.
7677    - If we have a prototype, check for type consistency.  */
7678
7679 static void
7680 really_start_method (tree method, tree parmlist)
7681 {
7682   tree sc_spec, ret_spec, ret_decl, decl_specs;
7683   tree method_decl, method_id;
7684   const char *sel_name, *class_name, *cat_name;
7685   char *buf;
7686
7687   /* Synth the storage class & assemble the return type.  */
7688   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7689   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7690   decl_specs = chainon (sc_spec, ret_spec);
7691
7692   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7693   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7694   cat_name = ((TREE_CODE (objc_implementation_context)
7695                == CLASS_IMPLEMENTATION_TYPE)
7696               ? NULL
7697               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7698   method_slot++;
7699
7700   /* Make sure this is big enough for any plausible method label.  */
7701   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7702                          + (cat_name ? strlen (cat_name) : 0));
7703
7704   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7705                          class_name, cat_name, sel_name, method_slot);
7706
7707   method_id = get_identifier (buf);
7708
7709 #ifdef OBJCPLUS
7710   /* Objective-C methods cannot be overloaded, so we don't need
7711      the type encoding appended.  It looks bad anyway... */
7712   push_lang_context (lang_name_c);
7713 #endif
7714
7715   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7716
7717   /* Check the declarator portion of the return type for the method.  */
7718   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7719     {
7720       /* Unite the complex decl (specified in the abstract decl) with the
7721          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7722       tree save_expr = objc_expr_last (ret_decl);
7723
7724       TREE_OPERAND (save_expr, 0) = method_decl;
7725       method_decl = ret_decl;
7726
7727       /* Fool the parser into thinking it is starting a function.  */
7728       start_function (decl_specs, method_decl, NULL_TREE);
7729
7730       /* Unhook: this has the effect of restoring the abstract declarator.  */
7731       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7732     }
7733
7734   else
7735     {
7736       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7737
7738       /* Fool the parser into thinking it is starting a function.  */
7739       start_function (decl_specs, method_decl, NULL_TREE);
7740
7741       /* Unhook: this has the effect of restoring the abstract declarator.  */
7742       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7743     }
7744
7745 #ifdef OBJCPLUS
7746   /* set self_decl from the first argument...this global is used by
7747    * build_ivar_reference().build_indirect_ref().
7748    */
7749   self_decl = DECL_ARGUMENTS (current_function_decl);
7750
7751   /* snaroff (3/28/96): when compiling with -Wall, this suppresses
7752    * the following: warning:unused parameter `struct objc_selector * _cmd'
7753    */
7754   TREE_USED (self_decl) = 1;
7755   TREE_USED (TREE_CHAIN (self_decl)) = 1;
7756   /* Ditto for the underlying (static) C function.  */
7757   TREE_USED (current_function_decl) = 1;
7758   pop_lang_context ();
7759 #endif
7760
7761   METHOD_DEFINITION (method) = current_function_decl;
7762
7763   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7764
7765   if (implementation_template != objc_implementation_context)
7766     {
7767       tree proto
7768         = lookup_method_static (implementation_template,
7769                                 METHOD_SEL_NAME (method),
7770                                 TREE_CODE (method) == CLASS_METHOD_DECL);
7771
7772       if (proto)
7773         {
7774           if (!comp_method_with_proto (method, proto))
7775             {
7776               char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7777
7778               warn_with_method ("conflicting types for", type, method);
7779               warn_with_method ("previous declaration of", type, proto);
7780             }
7781         }
7782       else
7783         {
7784           /* We have a method @implementation even though we did not
7785              see a corresponding @interface declaration (which is allowed
7786              by Objective-C rules).  Go ahead and place the method in
7787              the @interface anyway, so that message dispatch lookups
7788              will see it.  */
7789           tree interface = implementation_template;
7790
7791           if (TREE_CODE (objc_implementation_context)
7792               == CATEGORY_IMPLEMENTATION_TYPE)
7793             interface = lookup_category
7794                         (interface,
7795                          CLASS_SUPER_NAME (objc_implementation_context));
7796
7797           if (interface)
7798             objc_add_method (interface, copy_node (method),
7799                              TREE_CODE (method) == CLASS_METHOD_DECL);
7800         }
7801     }
7802 }
7803
7804 /* The following routine is always called...this "architecture" is to
7805    accommodate "old-style" variable length selectors.
7806
7807    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7808
7809 void
7810 continue_method_def (void)
7811 {
7812   tree parmlist;
7813
7814   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7815     /* We have a `, ...' immediately following the selector.  */
7816     parmlist = get_parm_info (/*ellipsis=*/true);
7817   else
7818     parmlist = get_parm_info (/*ellipsis=*/false);
7819
7820 #ifndef OBJCPLUS
7821   /* Set self_decl from the first argument...this global is used by
7822      build_ivar_reference calling build_indirect_ref.  */
7823   self_decl = TREE_PURPOSE (parmlist);
7824 #endif /* !OBJCPLUS */
7825
7826   pop_scope ();
7827   really_start_method (objc_method_context, parmlist);
7828   store_parm_decls ();
7829 }
7830
7831 static void *UOBJC_SUPER_scope = 0;
7832
7833 /* _n_Method (id self, SEL sel, ...)
7834      {
7835        struct objc_super _S;
7836        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7837      }  */
7838
7839 tree
7840 get_super_receiver (void)
7841 {
7842   if (objc_method_context)
7843     {
7844       tree super_expr, super_expr_list;
7845
7846       if (!UOBJC_SUPER_decl)
7847       {
7848         UOBJC_SUPER_decl = start_decl (get_identifier (TAG_SUPER),
7849                                        build_tree_list (NULL_TREE,
7850                                        objc_super_template),
7851                                        0, NULL_TREE);
7852         
7853         finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7854
7855         /* This prevents `unused variable' warnings when compiling with -Wall.  */
7856         TREE_USED (UOBJC_SUPER_decl) = 1;
7857         DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7858
7859         UOBJC_SUPER_scope = get_current_scope ();
7860       }
7861
7862       /* Set receiver to self.  */
7863       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7864       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7865       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7866
7867       /* Set class to begin searching.  */
7868 #ifdef OBJCPLUS
7869       super_expr = build_component_ref (UOBJC_SUPER_decl,
7870                                         get_identifier ("super_class"));
7871 #else
7872       super_expr = build_component_ref (UOBJC_SUPER_decl,
7873                                         get_identifier ("class"));
7874 #endif
7875
7876       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7877         {
7878           /* [_cls, __cls]Super are "pre-built" in
7879              synth_forward_declarations.  */
7880
7881           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7882                                           ((TREE_CODE (objc_method_context)
7883                                             == INSTANCE_METHOD_DECL)
7884                                            ? ucls_super_ref
7885                                            : uucls_super_ref));
7886         }
7887
7888       else
7889         /* We have a category.  */
7890         {
7891           tree super_name = CLASS_SUPER_NAME (implementation_template);
7892           tree super_class;
7893
7894           /* Barf if super used in a category of Object.  */
7895           if (!super_name)
7896             {
7897               error ("no super class declared in interface for `%s'",
7898                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7899               return error_mark_node;
7900             }
7901
7902           if (flag_next_runtime && !flag_zero_link)
7903             {
7904               super_class = get_class_reference (super_name);
7905               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7906                 /* If we are in a class method, we must retrieve the
7907                    _metaclass_ for the current class, pointed at by
7908                    the class's "isa" pointer.  The following assumes that
7909                    "isa" is the first ivar in a class (which it must be).  */
7910                 super_class
7911                   = build_indirect_ref
7912                     (build_c_cast (build_pointer_type (objc_class_type),
7913                                    super_class), "unary *");
7914             }
7915           else
7916             {
7917               add_class_reference (super_name);
7918               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7919                              ? objc_get_class_decl : objc_get_meta_class_decl);
7920               assemble_external (super_class);
7921               super_class
7922                 = build_function_call
7923                   (super_class,
7924                    build_tree_list
7925                    (NULL_TREE,
7926                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7927                                      IDENTIFIER_POINTER (super_name))));
7928             }
7929
7930           super_expr
7931             = build_modify_expr (super_expr, NOP_EXPR,
7932                                  build_c_cast (TREE_TYPE (super_expr),
7933                                                super_class));
7934         }
7935
7936       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7937
7938       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7939       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7940
7941       return build_compound_expr (super_expr_list);
7942     }
7943   else
7944     {
7945       error ("[super ...] must appear in a method context");
7946       return error_mark_node;
7947     }
7948 }
7949
7950 /* When exiting a scope, sever links to a 'super' declaration (if any)
7951    therein contained.  */
7952
7953 void
7954 objc_clear_super_receiver (void)
7955 {
7956   if (objc_method_context
7957       && UOBJC_SUPER_scope == get_current_scope ()) {
7958     UOBJC_SUPER_decl = 0;
7959     UOBJC_SUPER_scope = 0;
7960   }
7961 }
7962
7963 static void
7964 objc_expand_function_end (void)
7965 {
7966   /* This routine may also get called for C functions, including those
7967      nested within ObjC methods.  In such cases, method encoding is
7968      meaningless.  */
7969   if (objc_method_context == NULL_TREE
7970       || DECL_INITIAL (objc_method_context) != current_function_decl)
7971     return;
7972
7973   METHOD_ENCODING (objc_method_context)
7974     = encode_method_prototype (objc_method_context);
7975 }
7976
7977 void
7978 finish_method_def (void)
7979 {
7980   lang_expand_function_end = objc_expand_function_end;
7981   /* We cannot validly inline ObjC methods, at least not without a language
7982      extension to declare that a method need not be dynamically
7983      dispatched, so suppress all thoughts of doing so.  */
7984   DECL_INLINE (current_function_decl) = 0;
7985   DECL_UNINLINABLE (current_function_decl) = 1;
7986   current_function_cannot_inline = "methods cannot be inlined";
7987
7988   finish_function ();
7989   lang_expand_function_end = NULL;
7990
7991   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7992      since the optimizer may find "may be used before set" errors.  */
7993   objc_method_context = NULL_TREE;
7994 }
7995
7996 #if 0
7997 int
7998 lang_report_error_function (tree decl)
7999 {
8000   if (objc_method_context)
8001     {
8002       fprintf (stderr, "In method `%s'\n",
8003                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8004       return 1;
8005     }
8006
8007   else
8008     return 0;
8009 }
8010 #endif
8011
8012 static int
8013 is_complex_decl (tree type)
8014 {
8015   return (TREE_CODE (type) == ARRAY_TYPE
8016           || TREE_CODE (type) == FUNCTION_TYPE
8017           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
8018 }
8019
8020 \f
8021 /* Code to convert a decl node into text for a declaration in C.  */
8022
8023 static char tmpbuf[256];
8024
8025 static void
8026 adorn_decl (tree decl, char *str)
8027 {
8028   enum tree_code code = TREE_CODE (decl);
8029
8030   if (code == ARRAY_REF)
8031     {
8032       tree an_int_cst = TREE_OPERAND (decl, 1);
8033
8034       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
8035         sprintf (str + strlen (str), "[%ld]",
8036                  (long) TREE_INT_CST_LOW (an_int_cst));
8037       else
8038         strcat (str, "[]");
8039     }
8040
8041   else if (code == ARRAY_TYPE)
8042     {
8043       tree an_int_cst = TYPE_SIZE (decl);
8044       tree array_of = TREE_TYPE (decl);
8045
8046       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
8047         sprintf (str + strlen (str), "[%ld]",
8048                  (long) (TREE_INT_CST_LOW (an_int_cst)
8049                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
8050       else
8051         strcat (str, "[]");
8052     }
8053
8054   else if (code == CALL_EXPR)
8055     {
8056       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
8057
8058       strcat (str, "(");
8059       while (chain)
8060         {
8061           gen_declaration_1 (chain, str);
8062           chain = TREE_CHAIN (chain);
8063           if (chain)
8064             strcat (str, ", ");
8065         }
8066       strcat (str, ")");
8067     }
8068
8069   else if (code == FUNCTION_TYPE)
8070     {
8071       tree chain  = TYPE_ARG_TYPES (decl);
8072
8073       strcat (str, "(");
8074       while (chain && TREE_VALUE (chain) != void_type_node)
8075         {
8076           gen_declaration_1 (TREE_VALUE (chain), str);
8077           chain = TREE_CHAIN (chain);
8078           if (chain && TREE_VALUE (chain) != void_type_node)
8079             strcat (str, ", ");
8080         }
8081       strcat (str, ")");
8082     }
8083
8084   else if (code == INDIRECT_REF)
8085     {
8086       strcpy (tmpbuf, "*");
8087       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
8088         {
8089           tree chain;
8090
8091           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
8092                chain;
8093                chain = TREE_CHAIN (chain))
8094             {
8095               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
8096                 {
8097                   strcat (tmpbuf, " ");
8098                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
8099                 }
8100             }
8101           if (str[0])
8102             strcat (tmpbuf, " ");
8103         }
8104       strcat (tmpbuf, str);
8105       strcpy (str, tmpbuf);
8106     }
8107
8108   else if (code == POINTER_TYPE)
8109     {
8110       strcpy (tmpbuf, "*");
8111       if (TYPE_READONLY (decl) || TYPE_VOLATILE (decl))
8112         {
8113           if (TYPE_READONLY (decl))
8114             strcat (tmpbuf, " const");
8115           if (TYPE_VOLATILE (decl))
8116             strcat (tmpbuf, " volatile");
8117           if (str[0])
8118             strcat (tmpbuf, " ");
8119         }
8120       strcat (tmpbuf, str);
8121       strcpy (str, tmpbuf);
8122     }
8123 }
8124
8125 static char *
8126 gen_declarator (tree decl, char *buf, const char *name)
8127 {
8128   if (decl)
8129     {
8130       enum tree_code code = TREE_CODE (decl);
8131       char *str;
8132       tree op;
8133       int wrap = 0;
8134
8135       switch (code)
8136         {
8137         case ARRAY_REF:
8138         case INDIRECT_REF:
8139         case CALL_EXPR:
8140           op = TREE_OPERAND (decl, 0);
8141
8142           /* We have a pointer to a function or array...(*)(), (*)[] */
8143           if ((code == ARRAY_REF || code == CALL_EXPR)
8144               && op && TREE_CODE (op) == INDIRECT_REF)
8145             wrap = 1;
8146
8147           str = gen_declarator (op, buf, name);
8148
8149           if (wrap)
8150             {
8151               strcpy (tmpbuf, "(");
8152               strcat (tmpbuf, str);
8153               strcat (tmpbuf, ")");
8154               strcpy (str, tmpbuf);
8155             }
8156
8157           adorn_decl (decl, str);
8158           break;
8159
8160         case ARRAY_TYPE:
8161         case FUNCTION_TYPE:
8162         case POINTER_TYPE:
8163           strcpy (buf, name);
8164           str = buf;
8165
8166           /* This clause is done iteratively rather than recursively.  */
8167           do
8168             {
8169               op = (is_complex_decl (TREE_TYPE (decl))
8170                     ? TREE_TYPE (decl) : NULL_TREE);
8171
8172               adorn_decl (decl, str);
8173
8174               /* We have a pointer to a function or array...(*)(), (*)[] */
8175               if (code == POINTER_TYPE
8176                   && op && (TREE_CODE (op) == FUNCTION_TYPE
8177                             || TREE_CODE (op) == ARRAY_TYPE))
8178                 {
8179                   strcpy (tmpbuf, "(");
8180                   strcat (tmpbuf, str);
8181                   strcat (tmpbuf, ")");
8182                   strcpy (str, tmpbuf);
8183                 }
8184
8185               decl = (is_complex_decl (TREE_TYPE (decl))
8186                       ? TREE_TYPE (decl) : NULL_TREE);
8187             }
8188
8189           while (decl && (code = TREE_CODE (decl)))
8190             ;
8191
8192           break;
8193
8194         case IDENTIFIER_NODE:
8195           /* Will only happen if we are processing a "raw" expr-decl.  */
8196           strcpy (buf, IDENTIFIER_POINTER (decl));
8197           return buf;
8198
8199         default:
8200           abort ();
8201         }
8202
8203       return str;
8204     }
8205
8206   else
8207     /* We have an abstract declarator or a _DECL node.  */
8208     {
8209       strcpy (buf, name);
8210       return buf;
8211     }
8212 }
8213
8214 static void
8215 gen_declspecs (tree declspecs, char *buf, int raw)
8216 {
8217   if (raw)
8218     {
8219       tree chain;
8220
8221       for (chain = nreverse (copy_list (declspecs));
8222            chain; chain = TREE_CHAIN (chain))
8223         {
8224           tree aspec = TREE_VALUE (chain);
8225
8226           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
8227             strcat (buf, IDENTIFIER_POINTER (aspec));
8228           else if (TREE_CODE (aspec) == RECORD_TYPE)
8229             {
8230               if (OBJC_TYPE_NAME (aspec))
8231                 {
8232                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8233
8234                   if (! TREE_STATIC_TEMPLATE (aspec))
8235                     strcat (buf, "struct ");
8236                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8237
8238                   /* NEW!!! */
8239                   if (protocol_list)
8240                     {
8241                       tree chain = protocol_list;
8242
8243                       strcat (buf, " <");
8244                       while (chain)
8245                         {
8246                           strcat (buf,
8247                                   IDENTIFIER_POINTER
8248                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
8249                           chain = TREE_CHAIN (chain);
8250                           if (chain)
8251                             strcat (buf, ", ");
8252                         }
8253                       strcat (buf, ">");
8254                     }
8255                 }
8256
8257               else
8258                 strcat (buf, "untagged struct");
8259             }
8260
8261           else if (TREE_CODE (aspec) == UNION_TYPE)
8262             {
8263               if (OBJC_TYPE_NAME (aspec))
8264                 {
8265                   if (! TREE_STATIC_TEMPLATE (aspec))
8266                     strcat (buf, "union ");
8267                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8268                 }
8269               else
8270                 strcat (buf, "untagged union");
8271             }
8272
8273           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
8274             {
8275               if (OBJC_TYPE_NAME (aspec))
8276                 {
8277                   if (! TREE_STATIC_TEMPLATE (aspec))
8278                     strcat (buf, "enum ");
8279                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8280                 }
8281               else
8282                 strcat (buf, "untagged enum");
8283             }
8284
8285           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
8286             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
8287
8288           else if (IS_ID (aspec))
8289             {
8290               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8291
8292               strcat (buf, "id");
8293               if (protocol_list)
8294                 {
8295                   tree chain = protocol_list;
8296
8297                   strcat (buf, " <");
8298                   while (chain)
8299                     {
8300                       strcat (buf,
8301                               IDENTIFIER_POINTER
8302                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8303                       chain = TREE_CHAIN (chain);
8304                       if (chain)
8305                         strcat (buf, ", ");
8306                     }
8307                   strcat (buf, ">");
8308                 }
8309             }
8310           if (TREE_CHAIN (chain))
8311             strcat (buf, " ");
8312         }
8313     }
8314   else
8315     {
8316       /* Type qualifiers.  */
8317       if (TYPE_READONLY (declspecs))
8318         strcat (buf, "const ");
8319       if (TYPE_VOLATILE (declspecs))
8320         strcat (buf, "volatile ");
8321
8322       switch (TREE_CODE (declspecs))
8323         {
8324           /* Type specifiers.  */
8325
8326         case INTEGER_TYPE:
8327           declspecs = TYPE_MAIN_VARIANT (declspecs);
8328
8329           /* Signed integer types.  */
8330
8331           if (declspecs == short_integer_type_node)
8332             strcat (buf, "short int ");
8333           else if (declspecs == integer_type_node)
8334             strcat (buf, "int ");
8335           else if (declspecs == long_integer_type_node)
8336             strcat (buf, "long int ");
8337           else if (declspecs == long_long_integer_type_node)
8338             strcat (buf, "long long int ");
8339           else if (declspecs == signed_char_type_node
8340                    || declspecs == char_type_node)
8341             strcat (buf, "char ");
8342
8343           /* Unsigned integer types.  */
8344
8345           else if (declspecs == short_unsigned_type_node)
8346             strcat (buf, "unsigned short ");
8347           else if (declspecs == unsigned_type_node)
8348             strcat (buf, "unsigned int ");
8349           else if (declspecs == long_unsigned_type_node)
8350             strcat (buf, "unsigned long ");
8351           else if (declspecs == long_long_unsigned_type_node)
8352             strcat (buf, "unsigned long long ");
8353           else if (declspecs == unsigned_char_type_node)
8354             strcat (buf, "unsigned char ");
8355           break;
8356
8357         case REAL_TYPE:
8358           declspecs = TYPE_MAIN_VARIANT (declspecs);
8359
8360           if (declspecs == float_type_node)
8361             strcat (buf, "float ");
8362           else if (declspecs == double_type_node)
8363             strcat (buf, "double ");
8364           else if (declspecs == long_double_type_node)
8365             strcat (buf, "long double ");
8366           break;
8367
8368         case RECORD_TYPE:
8369           if (OBJC_TYPE_NAME (declspecs)
8370               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8371             {
8372               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8373
8374               if (! TREE_STATIC_TEMPLATE (declspecs))
8375                 strcat (buf, "struct ");
8376               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8377
8378               if (protocol_list)
8379                 {
8380                   tree chain = protocol_list;
8381
8382                   strcat (buf, " <");
8383                   while (chain)
8384                     {
8385                       strcat (buf,
8386                               IDENTIFIER_POINTER
8387                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8388                       chain = TREE_CHAIN (chain);
8389                       if (chain)
8390                         strcat (buf, ", ");
8391                     }
8392                   strcat (buf, ">");
8393                 }
8394             }
8395
8396           else
8397             strcat (buf, "untagged struct");
8398
8399           strcat (buf, " ");
8400           break;
8401
8402         case UNION_TYPE:
8403           if (OBJC_TYPE_NAME (declspecs)
8404               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8405             {
8406               strcat (buf, "union ");
8407               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8408               strcat (buf, " ");
8409             }
8410
8411           else
8412             strcat (buf, "untagged union ");
8413           break;
8414
8415         case ENUMERAL_TYPE:
8416           if (OBJC_TYPE_NAME (declspecs)
8417               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8418             {
8419               strcat (buf, "enum ");
8420               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8421               strcat (buf, " ");
8422             }
8423
8424           else
8425             strcat (buf, "untagged enum ");
8426           break;
8427
8428         case VOID_TYPE:
8429           strcat (buf, "void ");
8430           break;
8431
8432         case POINTER_TYPE:
8433           {
8434             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8435
8436             strcat (buf, "id");
8437             if (protocol_list)
8438               {
8439                 tree chain = protocol_list;
8440
8441                 strcat (buf, " <");
8442                 while (chain)
8443                   {
8444                     strcat (buf,
8445                             IDENTIFIER_POINTER
8446                             (PROTOCOL_NAME (TREE_VALUE (chain))));
8447                     chain = TREE_CHAIN (chain);
8448                     if (chain)
8449                       strcat (buf, ", ");
8450                   }
8451
8452                 strcat (buf, ">");
8453               }
8454           }
8455           break;
8456
8457         default:
8458           break;
8459         }
8460     }
8461 }
8462
8463 /* Given a tree node, produce a printable description of it in the given
8464    buffer, overwriting the buffer.  */
8465
8466 static char *
8467 gen_declaration (tree atype_or_adecl, char *buf)
8468 {
8469   buf[0] = '\0';
8470   gen_declaration_1 (atype_or_adecl, buf);
8471   return buf;
8472 }
8473
8474 /* Given a tree node, append a printable description to the end of the
8475    given buffer.  */
8476
8477 static void
8478 gen_declaration_1 (tree atype_or_adecl, char *buf)
8479 {
8480   char declbuf[256];
8481
8482   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
8483     {
8484       tree declspecs;   /* "identifier_node", "record_type" */
8485       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
8486       tree width = NULL_TREE;   /* for bitfields */
8487
8488       /* We have a "raw", abstract declarator (typename).  */
8489       declarator = TREE_VALUE (atype_or_adecl);
8490       /* In the case of raw ivars, the declarator itself is a list,
8491          and contains bitfield widths.  */
8492       if (declarator && TREE_CODE (declarator) == TREE_LIST)
8493         {
8494           width = TREE_VALUE (declarator);
8495           declarator = TREE_PURPOSE (declarator);
8496         }
8497       declspecs  = TREE_PURPOSE (atype_or_adecl);
8498
8499       gen_declspecs (declspecs, buf, 1);
8500       if (declarator)
8501         {
8502           strcat (buf, " ");
8503           strcat (buf, gen_declarator (declarator, declbuf, ""));
8504         }
8505       if (width)
8506         sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED, 
8507                  TREE_INT_CST_LOW (width));
8508     }
8509
8510   else
8511     {
8512       tree atype;
8513       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
8514       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
8515
8516       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8517           || TREE_CODE (atype_or_adecl) == PARM_DECL
8518           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8519         atype = TREE_TYPE (atype_or_adecl);
8520       else
8521         /* Assume we have a *_type node.  */
8522         atype = atype_or_adecl;
8523
8524       if (is_complex_decl (atype))
8525         {
8526           tree chain;
8527
8528           /* Get the declaration specifier; it is at the end of the list.  */
8529           declarator = chain = atype;
8530           do
8531             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8532           while (is_complex_decl (chain));
8533           declspecs = chain;
8534         }
8535
8536       else
8537         {
8538           declspecs = atype;
8539           declarator = NULL_TREE;
8540         }
8541
8542       gen_declspecs (declspecs, buf, 0);
8543
8544       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8545           || TREE_CODE (atype_or_adecl) == PARM_DECL
8546           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8547         {
8548           const char *const decl_name =
8549             (DECL_NAME (atype_or_adecl)
8550              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8551
8552           if (declarator)
8553             {
8554               strcat (buf, " ");
8555               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8556             }
8557
8558           else if (decl_name[0])
8559             {
8560               strcat (buf, " ");
8561               strcat (buf, decl_name);
8562             }
8563         }
8564       else if (declarator)
8565         {
8566           strcat (buf, " ");
8567           strcat (buf, gen_declarator (declarator, declbuf, ""));
8568         }
8569     }
8570 }
8571
8572 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8573
8574 /* Given a method tree, put a printable description into the given
8575    buffer (overwriting) and return a pointer to the buffer.  */
8576
8577 static char *
8578 gen_method_decl (tree method, char *buf)
8579 {
8580   tree chain;
8581
8582   buf[0] = '\0';
8583   if (RAW_TYPESPEC (method) != objc_object_reference)
8584     {
8585       strcat (buf, "(");
8586       gen_declaration_1 (TREE_TYPE (method), buf);
8587       strcat (buf, ")");
8588     }
8589
8590   chain = METHOD_SEL_ARGS (method);
8591   if (chain)
8592     {
8593       /* We have a chain of keyword_decls.  */
8594       do
8595         {
8596           if (KEYWORD_KEY_NAME (chain))
8597             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8598
8599           strcat (buf, ":");
8600           if (RAW_TYPESPEC (chain) != objc_object_reference)
8601             {
8602               strcat (buf, "(");
8603               gen_declaration_1 (TREE_TYPE (chain), buf);
8604               strcat (buf, ")");
8605             }
8606
8607           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8608           if ((chain = TREE_CHAIN (chain)))
8609             strcat (buf, " ");
8610         }
8611       while (chain);
8612
8613       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8614         strcat (buf, ", ...");
8615       else if (METHOD_ADD_ARGS (method))
8616         {
8617           /* We have a tree list node as generate by get_parm_info.  */
8618           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8619
8620           /* Know we have a chain of parm_decls.  */
8621           while (chain)
8622             {
8623               strcat (buf, ", ");
8624               gen_declaration_1 (chain, buf);
8625               chain = TREE_CHAIN (chain);
8626             }
8627         }
8628     }
8629
8630   else
8631     /* We have a unary selector.  */
8632     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8633
8634   return buf;
8635 }
8636 \f
8637 /* Debug info.  */
8638
8639
8640 /* Dump an @interface declaration of the supplied class CHAIN to the
8641    supplied file FP.  Used to implement the -gen-decls option (which
8642    prints out an @interface declaration of all classes compiled in
8643    this run); potentially useful for debugging the compiler too.  */
8644 static void
8645 dump_interface (FILE *fp, tree chain)
8646 {
8647   /* FIXME: A heap overflow here whenever a method (or ivar)
8648      declaration is so long that it doesn't fit in the buffer.  The
8649      code and all the related functions should be rewritten to avoid
8650      using fixed size buffers.  */
8651   char *buf = (char *) xmalloc (1024 * 10);
8652   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8653   tree ivar_decls = CLASS_RAW_IVARS (chain);
8654   tree nst_methods = CLASS_NST_METHODS (chain);
8655   tree cls_methods = CLASS_CLS_METHODS (chain);
8656
8657   fprintf (fp, "\n@interface %s", my_name);
8658
8659   /* CLASS_SUPER_NAME is used to store the superclass name for
8660      classes, and the category name for categories.  */
8661   if (CLASS_SUPER_NAME (chain))
8662     {
8663       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8664
8665       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8666           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8667         {
8668           fprintf (fp, " (%s)\n", name);
8669         }
8670       else
8671         {
8672           fprintf (fp, " : %s\n", name);
8673         }
8674     }
8675   else
8676     fprintf (fp, "\n");
8677
8678   /* FIXME - the following doesn't seem to work at the moment.  */
8679   if (ivar_decls)
8680     {
8681       fprintf (fp, "{\n");
8682       do
8683         {
8684           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8685           ivar_decls = TREE_CHAIN (ivar_decls);
8686         }
8687       while (ivar_decls);
8688       fprintf (fp, "}\n");
8689     }
8690
8691   while (nst_methods)
8692     {
8693       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8694       nst_methods = TREE_CHAIN (nst_methods);
8695     }
8696
8697   while (cls_methods)
8698     {
8699       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8700       cls_methods = TREE_CHAIN (cls_methods);
8701     }
8702
8703   fprintf (fp, "@end\n");
8704 }
8705
8706 /* Demangle function for Objective-C */
8707 static const char *
8708 objc_demangle (const char *mangled)
8709 {
8710   char *demangled, *cp;
8711
8712   if (mangled[0] == '_' &&
8713       (mangled[1] == 'i' || mangled[1] == 'c') &&
8714       mangled[2] == '_')
8715     {
8716       cp = demangled = xmalloc(strlen(mangled) + 2);
8717       if (mangled[1] == 'i')
8718         *cp++ = '-';            /* for instance method */
8719       else
8720         *cp++ = '+';            /* for class method */
8721       *cp++ = '[';              /* opening left brace */
8722       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8723       while (*cp && *cp == '_')
8724         cp++;                   /* skip any initial underbars in class name */
8725       cp = strchr(cp, '_');     /* find first non-initial underbar */
8726       if (cp == NULL)
8727         {
8728           free(demangled);      /* not mangled name */
8729           return mangled;
8730         }
8731       if (cp[1] == '_')  /* easy case: no category name */
8732         {
8733           *cp++ = ' ';            /* replace two '_' with one ' ' */
8734           strcpy(cp, mangled + (cp - demangled) + 2);
8735         }
8736       else
8737         {
8738           *cp++ = '(';            /* less easy case: category name */
8739           cp = strchr(cp, '_');
8740           if (cp == 0)
8741             {
8742               free(demangled);    /* not mangled name */
8743               return mangled;
8744             }
8745           *cp++ = ')';
8746           *cp++ = ' ';            /* overwriting 1st char of method name... */
8747           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8748         }
8749       while (*cp && *cp == '_')
8750         cp++;                   /* skip any initial underbars in method name */
8751       for (; *cp; cp++)
8752         if (*cp == '_')
8753           *cp = ':';            /* replace remaining '_' with ':' */
8754       *cp++ = ']';              /* closing right brace */
8755       *cp++ = 0;                /* string terminator */
8756       return demangled;
8757     }
8758   else
8759     return mangled;             /* not an objc mangled name */
8760 }
8761
8762 const char *
8763 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8764 {
8765   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8766 }
8767
8768 static void
8769 init_objc (void)
8770 {
8771   gcc_obstack_init (&util_obstack);
8772   util_firstobj = (char *) obstack_finish (&util_obstack);
8773
8774   errbuf = (char *) xmalloc (BUFSIZE);
8775   hash_init ();
8776   synth_module_prologue ();
8777 }
8778 \f
8779 static void
8780 finish_objc (void)
8781 {
8782   struct imp_entry *impent;
8783   tree chain;
8784   /* The internally generated initializers appear to have missing braces.
8785      Don't warn about this.  */
8786   int save_warn_missing_braces = warn_missing_braces;
8787   warn_missing_braces = 0;
8788
8789   /* A missing @end may not be detected by the parser.  */
8790   if (objc_implementation_context)
8791     {
8792       warning ("`@end' missing in implementation context");
8793       finish_class (objc_implementation_context);
8794       objc_ivar_chain = NULL_TREE;
8795       objc_implementation_context = NULL_TREE;
8796     }
8797
8798   /* Process the static instances here because initialization of objc_symtab
8799      depends on them.  */
8800   if (objc_static_instances)
8801     generate_static_references ();
8802
8803   if (imp_list || class_names_chain
8804       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8805     generate_objc_symtab_decl ();
8806
8807   for (impent = imp_list; impent; impent = impent->next)
8808     {
8809       objc_implementation_context = impent->imp_context;
8810       implementation_template = impent->imp_template;
8811
8812       UOBJC_CLASS_decl = impent->class_decl;
8813       UOBJC_METACLASS_decl = impent->meta_decl;
8814
8815       /* Dump the @interface of each class as we compile it, if the
8816          -gen-decls option is in use.  TODO: Dump the classes in the
8817          order they were found, rather than in reverse order as we
8818          are doing now.  */
8819       if (flag_gen_declaration)
8820         {
8821           dump_interface (gen_declaration_file, objc_implementation_context);
8822         }
8823
8824       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8825         {
8826           /* all of the following reference the string pool...  */
8827           generate_ivar_lists ();
8828           generate_dispatch_tables ();
8829           generate_shared_structures ();
8830         }
8831       else
8832         {
8833           generate_dispatch_tables ();
8834           generate_category (objc_implementation_context);
8835         }
8836     }
8837
8838   /* If we are using an array of selectors, we must always
8839      finish up the array decl even if no selectors were used.  */
8840   if (! flag_next_runtime || sel_ref_chain)
8841     build_selector_translation_table ();
8842
8843   if (protocol_chain)
8844     generate_protocols ();
8845
8846   if (flag_replace_objc_classes && imp_list)
8847     generate_objc_image_info ();
8848
8849   if (objc_implementation_context || class_names_chain || objc_static_instances
8850       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8851     {
8852       /* Arrange for ObjC data structures to be initialized at run time.  */
8853       rtx init_sym = build_module_descriptor ();
8854       if (init_sym && targetm.have_ctors_dtors)
8855         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8856     }
8857
8858   /* Dump the class references.  This forces the appropriate classes
8859      to be linked into the executable image, preserving unix archive
8860      semantics.  This can be removed when we move to a more dynamically
8861      linked environment.  */
8862
8863   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8864     {
8865       handle_class_ref (chain);
8866       if (TREE_PURPOSE (chain))
8867         generate_classref_translation_entry (chain);
8868     }
8869
8870   for (impent = imp_list; impent; impent = impent->next)
8871     handle_impent (impent);
8872
8873   /* Dump the string table last.  */
8874
8875   generate_strings ();
8876
8877   if (warn_selector)
8878     {
8879       int slot;
8880       hash hsh;
8881
8882       /* Run through the selector hash tables and print a warning for any
8883          selector which has multiple methods.  */
8884
8885       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8886         {
8887           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8888             check_duplicates (hsh, 0, 1);
8889           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8890             check_duplicates (hsh, 0, 1);
8891         }
8892     }
8893
8894   warn_missing_braces = save_warn_missing_braces;
8895 }
8896 \f
8897 /* Subroutines of finish_objc.  */
8898
8899 static void
8900 generate_classref_translation_entry (tree chain)
8901 {
8902   tree expr, name, decl_specs, decl, sc_spec;
8903   tree type;
8904
8905   type = TREE_TYPE (TREE_PURPOSE (chain));
8906
8907   expr = add_objc_string (TREE_VALUE (chain), class_names);
8908   expr = build_c_cast (type, expr); /* cast! */
8909
8910   name = DECL_NAME (TREE_PURPOSE (chain));
8911
8912   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8913
8914   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8915   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8916
8917   /* The decl that is returned from start_decl is the one that we
8918      forward declared in build_class_reference.  */
8919   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8920   DECL_CONTEXT (decl) = NULL_TREE;
8921   finish_decl (decl, expr, NULL_TREE);
8922   return;
8923 }
8924
8925 static void
8926 handle_class_ref (tree chain)
8927 {
8928   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8929   char *string = (char *) alloca (strlen (name) + 30);
8930   tree decl;
8931   tree exp;
8932
8933   sprintf (string, "%sobjc_class_name_%s",
8934            (flag_next_runtime ? "." : "__"), name);
8935
8936 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8937   if (flag_next_runtime)
8938     {
8939       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8940       return;
8941     }
8942 #endif
8943
8944   /* Make a decl for this name, so we can use its address in a tree.  */
8945   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8946   DECL_EXTERNAL (decl) = 1;
8947   TREE_PUBLIC (decl) = 1;
8948
8949   pushdecl (decl);
8950   rest_of_decl_compilation (decl, 0, 0, 0);
8951
8952   /* Make a decl for the address.  */
8953   sprintf (string, "%sobjc_class_ref_%s",
8954            (flag_next_runtime ? "." : "__"), name);
8955   exp = build1 (ADDR_EXPR, string_type_node, decl);
8956   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8957   DECL_INITIAL (decl) = exp;
8958   TREE_STATIC (decl) = 1;
8959   TREE_USED (decl) = 1;
8960
8961   pushdecl (decl);
8962   rest_of_decl_compilation (decl, 0, 0, 0);
8963 }
8964
8965 static void
8966 handle_impent (struct imp_entry *impent)
8967 {
8968   char *string;
8969
8970   objc_implementation_context = impent->imp_context;
8971   implementation_template = impent->imp_template;
8972
8973   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8974     {
8975       const char *const class_name =
8976         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8977
8978       string = (char *) alloca (strlen (class_name) + 30);
8979
8980       sprintf (string, "%sobjc_class_name_%s",
8981                (flag_next_runtime ? "." : "__"), class_name);
8982     }
8983   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8984     {
8985       const char *const class_name =
8986         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8987       const char *const class_super_name =
8988         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8989
8990       string = (char *) alloca (strlen (class_name)
8991                                 + strlen (class_super_name) + 30);
8992
8993       /* Do the same for categories.  Even though no references to
8994          these symbols are generated automatically by the compiler, it
8995          gives you a handle to pull them into an archive by hand.  */
8996       sprintf (string, "*%sobjc_category_name_%s_%s",
8997                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8998     }
8999   else
9000     return;
9001
9002 #ifdef ASM_DECLARE_CLASS_REFERENCE
9003   if (flag_next_runtime)
9004     {
9005       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9006       return;
9007     }
9008   else
9009 #endif
9010     {
9011       tree decl, init;
9012
9013       init = build_int_2 (0, 0);
9014       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
9015       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9016       TREE_PUBLIC (decl) = 1;
9017       TREE_READONLY (decl) = 1;
9018       TREE_USED (decl) = 1;
9019       TREE_CONSTANT (decl) = 1;
9020       DECL_CONTEXT (decl) = 0;
9021       DECL_ARTIFICIAL (decl) = 1;
9022       DECL_INITIAL (decl) = init;
9023       assemble_variable (decl, 1, 0, 0);
9024     }
9025 }
9026 \f
9027 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
9028    later requires that ObjC translation units participating in F&C be
9029    specially marked.  The following routine accomplishes this.  */
9030
9031 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9032
9033 static void
9034 generate_objc_image_info (void)
9035 {
9036   tree sc_spec, decl, initlist;
9037
9038   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
9039   decl
9040    = start_decl (get_identifier ("_OBJC_IMAGE_INFO"),
9041                  tree_cons (NULL_TREE,
9042                             build_array_type
9043                             (integer_type_node,
9044                              build_index_type (build_int_2 (1, 0))),
9045                             sc_spec),
9046                  1,
9047                  NULL_TREE);
9048
9049   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
9050   initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
9051   initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
9052
9053   TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
9054   TREE_CONSTANT (initlist) = TREE_STATIC (initlist) = 1;
9055   finish_decl (decl, initlist, NULL_TREE);
9056 }
9057
9058 /* Look up ID as an instance variable.  */
9059
9060 tree
9061 lookup_objc_ivar (tree id)
9062 {
9063   tree decl;
9064
9065   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
9066     /* We have a message to super.  */
9067     return get_super_receiver ();
9068   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
9069     {
9070       if (is_private (decl))
9071         return error_mark_node;
9072       else
9073         return build_ivar_reference (id);
9074     }
9075   else
9076     return 0;
9077 }
9078
9079 #include "gt-objc-objc-act.h"
9080 #include "gtype-objc.h"