Bring in a trimmed down gcc-3.4-20040618.
[dragonfly.git] / contrib / gcc-3.4 / 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 "objc-act.h"
54 #include "input.h"
55 #include "except.h"
56 #include "function.h"
57 #include "output.h"
58 #include "toplev.h"
59 #include "ggc.h"
60 #include "varray.h"
61 #include "debug.h"
62 #include "target.h"
63 #include "diagnostic.h"
64 #include "cgraph.h"
65
66 #define OBJC_VOID_AT_END        build_tree_list (NULL_TREE, void_type_node)
67
68 /* This is the default way of generating a method name.  */
69 /* I am not sure it is really correct.
70    Perhaps there's a danger that it will make name conflicts
71    if method names contain underscores. -- rms.  */
72 #ifndef OBJC_GEN_METHOD_LABEL
73 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
74   do {                                      \
75     char *temp;                             \
76     sprintf ((BUF), "_%s_%s_%s_%s",         \
77              ((IS_INST) ? "i" : "c"),       \
78              (CLASS_NAME),                  \
79              ((CAT_NAME)? (CAT_NAME) : ""), \
80              (SEL_NAME));                   \
81     for (temp = (BUF); *temp; temp++)       \
82       if (*temp == ':') *temp = '_';        \
83   } while (0)
84 #endif
85
86 /* These need specifying.  */
87 #ifndef OBJC_FORWARDING_STACK_OFFSET
88 #define OBJC_FORWARDING_STACK_OFFSET 0
89 #endif
90
91 #ifndef OBJC_FORWARDING_MIN_OFFSET
92 #define OBJC_FORWARDING_MIN_OFFSET 0
93 #endif
94 \f
95 /* Set up for use of obstacks.  */
96
97 #include "obstack.h"
98
99 /* This obstack is used to accumulate the encoding of a data type.  */
100 static struct obstack util_obstack;
101
102 /* This points to the beginning of obstack contents, so we can free
103    the whole contents.  */
104 char *util_firstobj;
105
106 /* The version identifies which language generation and runtime
107    the module (file) was compiled for, and is recorded in the
108    module descriptor.  */
109
110 #define OBJC_VERSION    (flag_next_runtime ? 5 : 8)
111 #define PROTOCOL_VERSION 2
112
113 /* (Decide if these can ever be validly changed.) */
114 #define OBJC_ENCODE_INLINE_DEFS         0
115 #define OBJC_ENCODE_DONT_INLINE_DEFS    1
116
117 /*** Private Interface (procedures) ***/
118
119 /* Used by compile_file.  */
120
121 static void init_objc (void);
122 static void finish_objc (void);
123
124 /* Code generation.  */
125
126 static void synth_module_prologue (void);
127 static tree objc_build_constructor (tree, tree);
128 static rtx build_module_descriptor (void);
129 static tree init_module_descriptor (tree);
130 static tree build_objc_method_call (int, tree, tree, tree, tree);
131 static void generate_strings (void);
132 static tree get_proto_encoding (tree);
133 static void build_selector_translation_table (void);
134
135 static tree objc_add_static_instance (tree, tree);
136
137 static void build_objc_exception_stuff (void);
138 static tree objc_declare_variable (enum rid, tree, tree, tree);
139 static tree objc_enter_block (void);
140 static tree objc_exit_block (void);
141 static void objc_build_try_enter_fragment (void);
142 static void objc_build_try_exit_fragment (void);
143 static void objc_build_extract_fragment (void);
144 static tree objc_build_extract_expr (void);
145
146 static tree build_ivar_template (void);
147 static tree build_method_template (void);
148 static tree build_private_template (tree);
149 static void build_class_template (void);
150 static void build_selector_template (void);
151 static void build_category_template (void);
152 static tree lookup_method_in_hash_lists (tree, int);
153 static void build_super_template (void);
154 static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
155 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
156 static void synth_forward_declarations (void);
157 static int ivar_list_length (tree);
158 static tree get_class_ivars (tree, int);
159 static void generate_ivar_lists (void);
160 static void generate_dispatch_tables (void);
161 static void generate_shared_structures (void);
162 static tree generate_protocol_list (tree);
163 static void generate_forward_declaration_to_string_table (void);
164 static void build_protocol_reference (tree);
165
166 static tree build_keyword_selector (tree);
167 static tree synth_id_with_class_suffix (const char *, tree);
168
169 static void generate_static_references (void);
170 static int check_methods_accessible (tree, tree, int);
171 static void encode_aggregate_within (tree, int, int, int, int);
172 static const char *objc_demangle (const char *);
173 static void objc_expand_function_end (void);
174
175 /* Hash tables to manage the global pool of method prototypes.  */
176
177 hash *nst_method_hash_list = 0;
178 hash *cls_method_hash_list = 0;
179
180 static size_t hash_func (tree);
181 static void hash_init (void);
182 static void hash_enter (hash *, tree);
183 static hash hash_lookup (hash *, tree);
184 static void hash_add_attr (hash, tree);
185 static tree lookup_method (tree, tree);
186 static tree lookup_method_static (tree, tree, int);
187 static void add_method_to_hash_list (hash *, tree);
188 static tree add_class (tree);
189 static void add_category (tree, tree);
190 static inline tree lookup_category (tree, tree);
191
192 enum string_section
193 {
194   class_names,          /* class, category, protocol, module names */
195   meth_var_names,       /* method and variable names */
196   meth_var_types        /* method and variable type descriptors */
197 };
198
199 static tree add_objc_string (tree, enum string_section);
200 static tree get_objc_string_decl (tree, enum string_section);
201 static tree build_objc_string_decl (enum string_section);
202 static tree build_selector_reference_decl (void);
203
204 /* Protocol additions.  */
205
206 static tree add_protocol (tree);
207 static tree lookup_protocol (tree);
208 static void check_protocol_recursively (tree, tree);
209 static tree lookup_and_install_protocols (tree);
210
211 /* Type encoding.  */
212
213 static void encode_type_qualifiers (tree);
214 static void encode_pointer (tree, int, int);
215 static void encode_array (tree, int, int);
216 static void encode_aggregate (tree, int, int);
217 static void encode_next_bitfield (int);
218 static void encode_gnu_bitfield (int, tree, int);
219 static void encode_type (tree, int, int);
220 static void encode_field_decl (tree, int, int);
221
222 static void really_start_method (tree, tree);
223 static int comp_method_with_proto (tree, tree);
224 static int objc_types_are_equivalent (tree, tree);
225 static int comp_proto_with_proto (tree, tree);
226 static tree get_arg_type_list (tree, int, int);
227 static tree objc_expr_last (tree);
228 static void synth_self_and_ucmd_args (void);
229
230 /* Utilities for debugging and error diagnostics.  */
231
232 static void warn_with_method (const char *, int, tree);
233 static void error_with_ivar (const char *, tree, tree);
234 static char *gen_method_decl (tree, char *);
235 static char *gen_declaration (tree, char *);
236 static void gen_declaration_1 (tree, char *);
237 static char *gen_declarator (tree, char *, const char *);
238 static int is_complex_decl (tree);
239 static void adorn_decl (tree, char *);
240 static void dump_interface (FILE *, tree);
241
242 /* Everything else.  */
243
244 static tree define_decl (tree, tree);
245 static tree lookup_method_in_protocol_list (tree, tree, int);
246 static tree lookup_protocol_in_reflist (tree, tree);
247 static tree create_builtin_decl (enum tree_code, tree, const char *);
248 static void setup_string_decl (void);
249 static int check_string_class_template (void);
250 static tree my_build_string (int, const char *);
251 static void build_objc_symtab_template (void);
252 static tree init_def_list (tree);
253 static tree init_objc_symtab (tree);
254 static tree build_metadata_decl (const char *, tree);
255 static void forward_declare_categories (void);
256 static void generate_objc_symtab_decl (void);
257 static tree build_selector (tree);
258 static tree build_typed_selector_reference (tree, tree);
259 static tree build_selector_reference (tree);
260 static tree build_class_reference_decl (void);
261 static void add_class_reference (tree);
262 static tree build_protocol_template (void);
263 static tree build_descriptor_table_initializer (tree, tree);
264 static tree build_method_prototype_list_template (tree, int);
265 static tree build_method_prototype_template (void);
266 static tree objc_method_parm_type (tree);
267 static int objc_encoded_type_size (tree);
268 static tree encode_method_prototype (tree);
269 static tree generate_descriptor_table (tree, const char *, int, tree, tree);
270 static void generate_method_descriptors (tree);
271 static void generate_protocol_references (tree);
272 static void generate_protocols (void);
273 static void check_ivars (tree, tree);
274 static tree build_ivar_list_template (tree, int);
275 static tree build_method_list_template (tree, int);
276 static tree build_ivar_list_initializer (tree, tree);
277 static tree generate_ivars_list (tree, const char *, int, tree);
278 static tree build_dispatch_table_initializer (tree, tree);
279 static tree generate_dispatch_table (tree, const char *, int, tree);
280 static tree build_shared_structure_initializer (tree, tree, tree, tree,
281                                                 tree, int, tree, tree, tree);
282 static void generate_category (tree);
283 static int is_objc_type_qualifier (tree);
284 static tree adjust_type_for_id_default (tree);
285 static tree check_duplicates (hash, int, int);
286 static tree receiver_is_class_object (tree, int, int);
287 static int check_methods (tree, tree, int);
288 static int conforms_to_protocol (tree, tree);
289 static void check_protocol (tree, const char *, const char *);
290 static void check_protocols (tree, const char *, const char *);
291 static void gen_declspecs (tree, char *, int);
292 static void generate_classref_translation_entry (tree);
293 static void handle_class_ref (tree);
294 static void generate_struct_by_value_array (void)
295      ATTRIBUTE_NORETURN;
296 static void mark_referenced_methods (void);
297 static void generate_objc_image_info (void);
298
299 /*** Private Interface (data) ***/
300
301 /* Reserved tag definitions.  */
302
303 #define TYPE_ID                 "id"
304 #define TAG_OBJECT              "objc_object"
305 #define TAG_CLASS               "objc_class"
306 #define TAG_SUPER               "objc_super"
307 #define TAG_SELECTOR            "objc_selector"
308
309 #define UTAG_CLASS              "_objc_class"
310 #define UTAG_IVAR               "_objc_ivar"
311 #define UTAG_IVAR_LIST          "_objc_ivar_list"
312 #define UTAG_METHOD             "_objc_method"
313 #define UTAG_METHOD_LIST        "_objc_method_list"
314 #define UTAG_CATEGORY           "_objc_category"
315 #define UTAG_MODULE             "_objc_module"
316 #define UTAG_SYMTAB             "_objc_symtab"
317 #define UTAG_SUPER              "_objc_super"
318 #define UTAG_SELECTOR           "_objc_selector"
319
320 #define UTAG_PROTOCOL           "_objc_protocol"
321 #define UTAG_METHOD_PROTOTYPE   "_objc_method_prototype"
322 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
323
324 /* Note that the string object global name is only needed for the
325    NeXT runtime.  */
326 #define STRING_OBJECT_GLOBAL_FORMAT "_%sClassReference"
327
328 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
329
330 static const char *TAG_GETCLASS;
331 static const char *TAG_GETMETACLASS;
332 static const char *TAG_MSGSEND;
333 static const char *TAG_MSGSENDSUPER;
334 /* The NeXT Objective-C messenger may have two extra entry points, for use
335    when returning a structure. */
336 static const char *TAG_MSGSEND_STRET;
337 static const char *TAG_MSGSENDSUPER_STRET;
338 static const char *TAG_EXECCLASS;
339 static const char *default_constant_string_class_name;
340
341 /* Runtime metadata flags.  */
342 #define CLS_FACTORY                     0x0001L
343 #define CLS_META                        0x0002L
344
345 #define OBJC_MODIFIER_STATIC            0x00000001
346 #define OBJC_MODIFIER_FINAL             0x00000002
347 #define OBJC_MODIFIER_PUBLIC            0x00000004
348 #define OBJC_MODIFIER_PRIVATE           0x00000008
349 #define OBJC_MODIFIER_PROTECTED         0x00000010
350 #define OBJC_MODIFIER_NATIVE            0x00000020
351 #define OBJC_MODIFIER_SYNCHRONIZED      0x00000040
352 #define OBJC_MODIFIER_ABSTRACT          0x00000080
353 #define OBJC_MODIFIER_VOLATILE          0x00000100
354 #define OBJC_MODIFIER_TRANSIENT         0x00000200
355 #define OBJC_MODIFIER_NONE_SPECIFIED    0x80000000
356
357 #define TAG_MSGSEND_NONNIL              "objc_msgSendNonNil"
358 #define TAG_MSGSEND_NONNIL_STRET        "objc_msgSendNonNil_stret"
359 #define TAG_EXCEPTIONEXTRACT            "objc_exception_extract"
360 #define TAG_EXCEPTIONTRYENTER           "objc_exception_try_enter"
361 #define TAG_EXCEPTIONTRYEXIT            "objc_exception_try_exit"
362 #define TAG_EXCEPTIONMATCH              "objc_exception_match"
363 #define TAG_EXCEPTIONTHROW              "objc_exception_throw"
364 #define TAG_SYNCENTER                   "objc_sync_enter"
365 #define TAG_SYNCEXIT                    "objc_sync_exit"
366 #define TAG_SETJMP                      "_setjmp"
367 #define TAG_RETURN_STRUCT               "objc_return_struct"
368
369 #define UTAG_EXCDATA                    "_objc_exception_data"
370 #define UTAG_EXCDATA_VAR                "_stackExceptionData"
371 #define UTAG_CAUGHTEXC_VAR              "_caughtException"
372 #define UTAG_RETHROWEXC_VAR             "_rethrowException"
373 #define UTAG_EVALONCE_VAR               "_eval_once"
374
375 struct val_stack {
376   long val;
377   struct val_stack *next;
378 };
379 static struct val_stack *catch_count_stack, *exc_binding_stack;
380
381 /* useful for debugging */
382 static int if_nesting_count;
383 static int blk_nesting_count;
384
385 static void val_stack_push (struct val_stack **, long);
386 static void val_stack_pop (struct val_stack **);
387
388 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
389 tree objc_global_trees[OCTI_MAX];
390
391 static void handle_impent (struct imp_entry *);
392
393 struct imp_entry *imp_list = 0;
394 int imp_count = 0;      /* `@implementation' */
395 int cat_count = 0;      /* `@category' */
396
397 /* Use to generate method labels.  */
398 static int method_slot = 0;
399
400 #define BUFSIZE         1024
401
402 static char *errbuf;    /* Buffer for error diagnostics */
403
404 /* Data imported from tree.c.  */
405
406 extern enum debug_info_type write_symbols;
407
408 /* Data imported from toplev.c.  */
409
410 extern const char *dump_base_name;
411 \f
412 static int flag_typed_selectors;
413
414 FILE *gen_declaration_file;
415
416 /* Tells "encode_pointer/encode_aggregate" whether we are generating
417    type descriptors for instance variables (as opposed to methods).
418    Type descriptors for instance variables contain more information
419    than methods (for static typing and embedded structures).  */
420
421 static int generating_instance_variables = 0;
422
423 /* Some platforms pass small structures through registers versus
424    through an invisible pointer.  Determine at what size structure is
425    the transition point between the two possibilities.  */
426
427 static void
428 generate_struct_by_value_array (void)
429 {
430   tree type;
431   tree field_decl, field_decl_chain;
432   int i, j;
433   int aggregate_in_mem[32];
434   int found = 0;
435
436   /* Presumably no platform passes 32 byte structures in a register.  */
437   for (i = 1; i < 32; i++)
438     {
439       char buffer[5];
440
441       /* Create an unnamed struct that has `i' character components */
442       type = start_struct (RECORD_TYPE, NULL_TREE);
443
444       strcpy (buffer, "c1");
445       field_decl = create_builtin_decl (FIELD_DECL,
446                                         char_type_node,
447                                         buffer);
448       field_decl_chain = field_decl;
449
450       for (j = 1; j < i; j++)
451         {
452           sprintf (buffer, "c%d", j + 1);
453           field_decl = create_builtin_decl (FIELD_DECL,
454                                             char_type_node,
455                                             buffer);
456           chainon (field_decl_chain, field_decl);
457         }
458       finish_struct (type, field_decl_chain, NULL_TREE);
459
460       aggregate_in_mem[i] = aggregate_value_p (type, 0);
461       if (!aggregate_in_mem[i])
462         found = 1;
463     }
464
465   /* We found some structures that are returned in registers instead of memory
466      so output the necessary data.  */
467   if (found)
468     {
469       for (i = 31; i >= 0;  i--)
470         if (!aggregate_in_mem[i])
471           break;
472       printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
473
474       /* The first member of the structure is always 0 because we don't handle
475          structures with 0 members */
476       printf ("static int struct_forward_array[] = {\n  0");
477
478       for (j = 1; j <= i; j++)
479         printf (", %d", aggregate_in_mem[j]);
480       printf ("\n};\n");
481     }
482
483   exit (0);
484 }
485
486 bool
487 objc_init (void)
488 {
489   if (c_objc_common_init () == false)
490     return false;
491
492   /* Force the line number back to 0; check_newline will have
493      raised it to 1, which will make the builtin functions appear
494      not to be built in.  */
495   input_line = 0;
496
497   /* If gen_declaration desired, open the output file.  */
498   if (flag_gen_declaration)
499     {
500       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
501       gen_declaration_file = fopen (dumpname, "w");
502       if (gen_declaration_file == 0)
503         fatal_error ("can't open %s: %m", dumpname);
504       free (dumpname);
505     }
506
507   if (flag_next_runtime)
508     {
509       TAG_GETCLASS = "objc_getClass";
510       TAG_GETMETACLASS = "objc_getMetaClass";
511       TAG_MSGSEND = "objc_msgSend";
512       TAG_MSGSENDSUPER = "objc_msgSendSuper";
513       TAG_MSGSEND_STRET = "objc_msgSend_stret";
514       TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
515       TAG_EXECCLASS = "__objc_execClass";
516       default_constant_string_class_name = "NSConstantString";
517     }
518   else
519     {
520       TAG_GETCLASS = "objc_get_class";
521       TAG_GETMETACLASS = "objc_get_meta_class";
522       TAG_MSGSEND = "objc_msg_lookup";
523       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
524       /* GNU runtime does not provide special functions to support
525          structure-returning methods.  */
526       TAG_EXECCLASS = "__objc_exec_class";
527       default_constant_string_class_name = "NXConstantString";
528       flag_typed_selectors = 1;
529     }
530
531   objc_ellipsis_node = make_node (ERROR_MARK);
532
533   init_objc ();
534
535   if (print_struct_values)
536     generate_struct_by_value_array ();
537
538   return true;
539 }
540
541 void
542 finish_file (void)
543 {
544   mark_referenced_methods ();
545   c_objc_common_finish_file ();
546
547   /* Finalize Objective-C runtime data.  No need to generate tables
548      and code if only checking syntax.  */
549   if (!flag_syntax_only)
550     finish_objc ();
551
552   if (gen_declaration_file)
553     fclose (gen_declaration_file);
554 }
555 \f
556 static tree
557 define_decl (tree declarator, tree declspecs)
558 {
559   tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
560   finish_decl (decl, NULL_TREE, NULL_TREE);
561   return decl;
562 }
563
564 static tree
565 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
566                                 int class_meth)
567 {
568    tree rproto, p;
569    tree fnd = 0;
570
571    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
572      {
573         p = TREE_VALUE (rproto);
574
575         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
576           {
577             if ((fnd = lookup_method (class_meth
578                                       ? PROTOCOL_CLS_METHODS (p)
579                                       : PROTOCOL_NST_METHODS (p), sel_name)))
580               ;
581             else if (PROTOCOL_LIST (p))
582               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
583                                                     sel_name, class_meth);
584           }
585         else
586           {
587             ; /* An identifier...if we could not find a protocol.  */
588           }
589
590         if (fnd)
591           return fnd;
592      }
593
594    return 0;
595 }
596
597 static tree
598 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
599 {
600   tree rproto, p;
601
602   /* Make sure the protocol is supported by the object on the rhs.  */
603   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
604     {
605       tree fnd = 0;
606       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
607         {
608           p = TREE_VALUE (rproto);
609
610           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
611             {
612               if (lproto == p)
613                 fnd = lproto;
614
615               else if (PROTOCOL_LIST (p))
616                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
617             }
618
619           if (fnd)
620             return fnd;
621         }
622     }
623   else
624     {
625       ; /* An identifier...if we could not find a protocol.  */
626     }
627
628   return 0;
629 }
630
631 /* Return 1 if LHS and RHS are compatible types for assignment or
632    various other operations.  Return 0 if they are incompatible, and
633    return -1 if we choose to not decide (because the types are really
634    just C types, not ObjC specific ones).  When the operation is
635    REFLEXIVE (typically comparisons), check for compatibility in
636    either direction; when it's not (typically assignments), don't.
637
638    This function is called in two cases: when both lhs and rhs are
639    pointers to records (in which case we check protocols too), and
640    when both lhs and rhs are records (in which case we check class
641    inheritance only).
642
643    Warnings about classes/protocols not implementing a protocol are
644    emitted here (multiple of those warnings might be emitted for a
645    single line!); generic warnings about incompatible assignments and
646    lacks of casts in comparisons are/must be emitted by the caller if
647    we return 0.
648 */
649
650 int
651 objc_comptypes (tree lhs, tree rhs, int reflexive)
652 {
653   /* New clause for protocols.  */
654
655   /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE.  We only
656      manage the ObjC ones, and leave the rest to the C code.  */
657   if (TREE_CODE (lhs) == POINTER_TYPE
658       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
659       && TREE_CODE (rhs) == POINTER_TYPE
660       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
661     {
662       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
663       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
664
665       if (lhs_is_proto)
666         {
667           tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
668           tree rproto, rproto_list;
669           tree p;
670
671           /* <Protocol> = <Protocol>  */
672           if (rhs_is_proto)
673             {
674               rproto_list = TYPE_PROTOCOL_LIST (rhs);
675
676               if (!reflexive)
677                 {
678                   /* An assignment between objects of type 'id
679                      <Protocol>'; make sure the protocol on the lhs is
680                      supported by the object on the rhs.  */
681                   for (lproto = lproto_list; lproto;
682                        lproto = TREE_CHAIN (lproto))
683                     {
684                       p = TREE_VALUE (lproto);
685                       rproto = lookup_protocol_in_reflist (rproto_list, p);
686
687                       if (!rproto)
688                         warning
689                           ("object does not conform to the `%s' protocol",
690                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
691                     }
692                   return 1;
693                 }
694               else
695                 {
696                   /* Obscure case - a comparison between two objects
697                      of type 'id <Protocol>'.  Check that either the
698                      protocol on the lhs is supported by the object on
699                      the rhs, or viceversa.  */
700
701                   /* Check if the protocol on the lhs is supported by the
702                      object on the rhs.  */
703                   for (lproto = lproto_list; lproto;
704                        lproto = TREE_CHAIN (lproto))
705                     {
706                       p = TREE_VALUE (lproto);
707                       rproto = lookup_protocol_in_reflist (rproto_list, p);
708
709                       if (!rproto)
710                         {
711                           /* Check failed - check if the protocol on the rhs
712                              is supported by the object on the lhs.  */
713                           for (rproto = rproto_list; rproto;
714                                rproto = TREE_CHAIN (rproto))
715                             {
716                               p = TREE_VALUE (rproto);
717                               lproto = lookup_protocol_in_reflist (lproto_list,
718                                                                    p);
719
720                               if (!lproto)
721                                 {
722                                   /* This check failed too: incompatible  */
723                                   return 0;
724                                 }
725                             }
726                           return 1;
727                         }
728                     }
729                   return 1;
730                 }
731             }
732           /* <Protocol> = <class> *  */
733           else if (TYPED_OBJECT (TREE_TYPE (rhs)))
734             {
735               tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
736               tree rinter;
737
738               /* Make sure the protocol is supported by the object on
739                  the rhs.  */
740               for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
741                 {
742                   p = TREE_VALUE (lproto);
743                   rproto = 0;
744                   rinter = lookup_interface (rname);
745
746                   while (rinter && !rproto)
747                     {
748                       tree cat;
749
750                       rproto_list = CLASS_PROTOCOL_LIST (rinter);
751                       rproto = lookup_protocol_in_reflist (rproto_list, p);
752                       /* If the underlying ObjC class does not have
753                          the protocol we're looking for, check for "one-off"
754                          protocols (e.g., `NSObject<MyProt> *foo;') attached
755                          to the rhs.  */
756                       if (!rproto)
757                         {
758                           rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
759                           rproto = lookup_protocol_in_reflist (rproto_list, p);
760                         }
761
762                       /* Check for protocols adopted by categories.  */
763                       cat = CLASS_CATEGORY_LIST (rinter);
764                       while (cat && !rproto)
765                         {
766                           rproto_list = CLASS_PROTOCOL_LIST (cat);
767                           rproto = lookup_protocol_in_reflist (rproto_list, p);
768                           cat = CLASS_CATEGORY_LIST (cat);
769                         }
770
771                       rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
772                     }
773
774                   if (!rproto)
775                     warning ("class `%s' does not implement the `%s' protocol",
776                              IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
777                              IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
778                 }
779               return 1;
780             }
781           /* <Protocol> = id */
782           else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
783             {
784               return 1;
785             }
786           /* <Protocol> = Class */
787           else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
788             {
789               return 0;
790             }
791           /* <Protocol> = ?? : let comptypes decide.  */
792           return -1;
793         }
794       else if (rhs_is_proto)
795         {
796           /* <class> * = <Protocol> */
797           if (TYPED_OBJECT (TREE_TYPE (lhs)))
798             {
799               if (reflexive)
800                 {
801                   tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
802                   tree rinter;
803                   tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
804
805                   /* Make sure the protocol is supported by the object on
806                      the lhs.  */
807                   for (rproto = rproto_list; rproto;
808                        rproto = TREE_CHAIN (rproto))
809                     {
810                       tree p = TREE_VALUE (rproto);
811                       tree lproto = 0;
812                       rinter = lookup_interface (rname);
813
814                       while (rinter && !lproto)
815                         {
816                           tree cat;
817
818                           tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
819                           lproto = lookup_protocol_in_reflist (lproto_list, p);
820                           /* If the underlying ObjC class does not
821                              have the protocol we're looking for,
822                              check for "one-off" protocols (e.g.,
823                              `NSObject<MyProt> *foo;') attached to the
824                              lhs.  */
825                           if (!lproto)
826                             {
827                               lproto_list = TYPE_PROTOCOL_LIST
828                                 (TREE_TYPE (lhs));
829                               lproto = lookup_protocol_in_reflist
830                                 (lproto_list, p);
831                             }
832
833                           /* Check for protocols adopted by categories.  */
834                           cat = CLASS_CATEGORY_LIST (rinter);
835                           while (cat && !lproto)
836                             {
837                               lproto_list = CLASS_PROTOCOL_LIST (cat);
838                               lproto = lookup_protocol_in_reflist (lproto_list,
839                                                                    p);
840                               cat = CLASS_CATEGORY_LIST (cat);
841                             }
842                         
843                           rinter = lookup_interface (CLASS_SUPER_NAME
844                                                      (rinter));
845                         }
846                 
847                       if (!lproto)
848                         warning ("class `%s' does not implement the `%s' protocol",
849                                  IDENTIFIER_POINTER (OBJC_TYPE_NAME
850                                                      (TREE_TYPE (lhs))),
851                                  IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
852                     }
853                   return 1;
854                 }
855               else
856                 return 0;
857             }
858           /* id = <Protocol> */
859           else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
860             {
861               return 1;
862             }
863           /* Class = <Protocol> */
864           else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
865             {
866               return 0;
867             }
868           /* ??? = <Protocol> : let comptypes decide */
869           else
870             {
871               return -1;
872             }
873         }
874       else
875         {
876           /* Attention: we shouldn't defer to comptypes here.  One bad
877              side effect would be that we might loose the REFLEXIVE
878              information.
879           */
880           lhs = TREE_TYPE (lhs);
881           rhs = TREE_TYPE (rhs);
882         }
883     }
884
885   if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
886     {
887       /* Nothing to do with ObjC - let immediately comptypes take
888          responsibility for checking.  */
889       return -1;
890     }
891
892   /* `id' = `<class> *' `<class> *' = `id': always allow it.
893      Please note that
894      'Object *o = [[Object alloc] init]; falls
895      in the case <class> * = `id'.
896   */
897   if ((OBJC_TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
898       || (OBJC_TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
899     return 1;
900
901   /* `id' = `Class', `Class' = `id' */
902
903   else if ((OBJC_TYPE_NAME (lhs) == objc_object_id
904             && OBJC_TYPE_NAME (rhs) == objc_class_id)
905            || (OBJC_TYPE_NAME (lhs) == objc_class_id
906                && OBJC_TYPE_NAME (rhs) == objc_object_id))
907     return 1;
908
909   /* `<class> *' = `<class> *' */
910
911   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
912     {
913       tree lname = OBJC_TYPE_NAME (lhs);
914       tree rname = OBJC_TYPE_NAME (rhs);
915       tree inter;
916
917       if (lname == rname)
918         return 1;
919
920       /* If the left hand side is a super class of the right hand side,
921          allow it.  */
922       for (inter = lookup_interface (rname); inter;
923            inter = lookup_interface (CLASS_SUPER_NAME (inter)))
924         if (lname == CLASS_SUPER_NAME (inter))
925           return 1;
926
927       /* Allow the reverse when reflexive.  */
928       if (reflexive)
929         for (inter = lookup_interface (lname); inter;
930              inter = lookup_interface (CLASS_SUPER_NAME (inter)))
931           if (rname == CLASS_SUPER_NAME (inter))
932             return 1;
933
934       return 0;
935     }
936   else
937     /* Not an ObjC type - let comptypes do the check.  */
938     return -1;
939 }
940
941 /* Called from finish_decl.  */
942
943 void
944 objc_check_decl (tree decl)
945 {
946   tree type = TREE_TYPE (decl);
947
948   if (TREE_CODE (type) != RECORD_TYPE)
949     return;
950   if (TYPE_NAME (type) && (type = is_class_name (TYPE_NAME (type))))
951     error ("statically allocated instance of Objective-C class `%s'",
952            IDENTIFIER_POINTER (type));
953 }
954
955 /* Implement static typing.  At this point, we know we have an interface.  */
956
957 tree
958 get_static_reference (tree interface, tree protocols)
959 {
960   tree type = xref_tag (RECORD_TYPE, interface);
961
962   if (protocols)
963     {
964       tree t, m = TYPE_MAIN_VARIANT (type);
965
966       t = copy_node (type);
967
968       /* Add this type to the chain of variants of TYPE.  */
969       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
970       TYPE_NEXT_VARIANT (m) = t;
971
972       /* Look up protocols and install in lang specific list.  Note
973          that the protocol list can have a different lifetime than T!  */
974       SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
975
976       /* This forces a new pointer type to be created later
977          (in build_pointer_type)...so that the new template
978          we just created will actually be used...what a hack!  */
979       if (TYPE_POINTER_TO (t))
980         TYPE_POINTER_TO (t) = NULL_TREE;
981
982       type = t;
983     }
984
985   return type;
986 }
987
988 tree
989 get_object_reference (tree protocols)
990 {
991   tree type_decl = lookup_name (objc_id_id);
992   tree type;
993
994   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
995     {
996       type = TREE_TYPE (type_decl);
997       if (TYPE_MAIN_VARIANT (type) != id_type)
998         warning ("unexpected type for `id' (%s)",
999                  gen_declaration (type, errbuf));
1000     }
1001   else
1002     {
1003       error ("undefined type `id', please import <objc/objc.h>");
1004       return error_mark_node;
1005     }
1006
1007   /* This clause creates a new pointer type that is qualified with
1008      the protocol specification...this info is used later to do more
1009      elaborate type checking.  */
1010
1011   if (protocols)
1012     {
1013       tree t, m = TYPE_MAIN_VARIANT (type);
1014
1015       t = copy_node (type);
1016
1017       /* Add this type to the chain of variants of TYPE.  */
1018       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1019       TYPE_NEXT_VARIANT (m) = t;
1020
1021       /* Look up protocols...and install in lang specific list */
1022       SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
1023
1024       /* This forces a new pointer type to be created later
1025          (in build_pointer_type)...so that the new template
1026          we just created will actually be used...what a hack!  */
1027       if (TYPE_POINTER_TO (t))
1028         TYPE_POINTER_TO (t) = NULL_TREE;
1029
1030       type = t;
1031     }
1032   return type;
1033 }
1034
1035 /* Check for circular dependencies in protocols.  The arguments are
1036    PROTO, the protocol to check, and LIST, a list of protocol it
1037    conforms to.  */
1038
1039 static void
1040 check_protocol_recursively (tree proto, tree list)
1041 {
1042   tree p;
1043
1044   for (p = list; p; p = TREE_CHAIN (p))
1045     {
1046       tree pp = TREE_VALUE (p);
1047
1048       if (TREE_CODE (pp) == IDENTIFIER_NODE)
1049         pp = lookup_protocol (pp);
1050
1051       if (pp == proto)
1052         fatal_error ("protocol `%s' has circular dependency",
1053                      IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1054       if (pp)
1055         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1056     }
1057 }
1058
1059 /* Look up PROTOCOLS, and return a list of those that are found.
1060    If none are found, return NULL.  */
1061
1062 static tree
1063 lookup_and_install_protocols (tree protocols)
1064 {
1065   tree proto;
1066   tree return_value = NULL_TREE;
1067
1068   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1069     {
1070       tree ident = TREE_VALUE (proto);
1071       tree p = lookup_protocol (ident);
1072
1073       if (!p)
1074         error ("cannot find protocol declaration for `%s'",
1075                IDENTIFIER_POINTER (ident));
1076       else
1077         return_value = chainon (return_value,
1078                                 build_tree_list (NULL_TREE, p));
1079     }
1080
1081   return return_value;
1082 }
1083
1084 /* Create and push a decl for a built-in external variable or field NAME.
1085    CODE says which.
1086    TYPE is its data type.  */
1087
1088 static tree
1089 create_builtin_decl (enum tree_code code, tree type, const char *name)
1090 {
1091   tree decl = build_decl (code, get_identifier (name), type);
1092
1093   if (code == VAR_DECL)
1094     {
1095       TREE_STATIC (decl) = 1;
1096       make_decl_rtl (decl, 0);
1097       pushdecl (decl);
1098       DECL_ARTIFICIAL (decl) = 1;
1099     }
1100
1101   return decl;
1102 }
1103
1104 /* Find the decl for the constant string class.  */
1105
1106 static void
1107 setup_string_decl (void)
1108 {
1109   if (!string_class_decl)
1110     {
1111       if (!constant_string_global_id)
1112         {
1113           char *name;
1114           size_t length;
1115           /* %s in format will provide room for terminating null */
1116           length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1117                    + strlen (constant_string_class_name);
1118           name = xmalloc (length);
1119           sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1120                    constant_string_class_name);
1121           constant_string_global_id = get_identifier (name);
1122         }
1123       string_class_decl = lookup_name (constant_string_global_id);
1124     }
1125 }
1126
1127 /* Purpose: "play" parser, creating/installing representations
1128    of the declarations that are required by Objective-C.
1129
1130    Model:
1131
1132         type_spec--------->sc_spec
1133         (tree_list)        (tree_list)
1134             |                  |
1135             |                  |
1136         identifier_node    identifier_node  */
1137
1138 static void
1139 synth_module_prologue (void)
1140 {
1141   tree temp_type;
1142
1143   /* Defined in `objc.h' */
1144   objc_object_id = get_identifier (TAG_OBJECT);
1145
1146   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1147
1148   id_type = build_pointer_type (objc_object_reference);
1149
1150   objc_id_id = get_identifier (TYPE_ID);
1151   objc_class_id = get_identifier (TAG_CLASS);
1152
1153   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1154   temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1155   objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
1156   protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1157                                 temp_type));
1158
1159   /* Declare type of selector-objects that represent an operation name.  */
1160
1161   /* `struct objc_selector *' */
1162   selector_type
1163     = build_pointer_type (xref_tag (RECORD_TYPE,
1164                                     get_identifier (TAG_SELECTOR)));
1165
1166   /* Forward declare type, or else the prototype for msgSendSuper will
1167      complain.  */
1168
1169   /* `struct objc_super *' */
1170   super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1171                                           get_identifier (TAG_SUPER)));
1172
1173
1174   /* id objc_msgSend (id, SEL, ...); */
1175
1176   temp_type
1177     = build_function_type (id_type,
1178                            tree_cons (NULL_TREE, id_type,
1179                                       tree_cons (NULL_TREE, selector_type,
1180                                                  NULL_TREE)));
1181
1182   if (! flag_next_runtime)
1183     {
1184       umsg_decl = build_decl (FUNCTION_DECL,
1185                               get_identifier (TAG_MSGSEND), temp_type);
1186       DECL_EXTERNAL (umsg_decl) = 1;
1187       TREE_PUBLIC (umsg_decl) = 1;
1188       DECL_INLINE (umsg_decl) = 1;
1189       DECL_ARTIFICIAL (umsg_decl) = 1;
1190
1191       make_decl_rtl (umsg_decl, NULL);
1192       pushdecl (umsg_decl);
1193     }
1194   else
1195     {
1196       umsg_decl = builtin_function (TAG_MSGSEND,
1197                                     temp_type, 0, NOT_BUILT_IN,
1198                                     NULL, NULL_TREE);
1199       /* id objc_msgSendNonNil (id, SEL, ...); */
1200       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1201                                            temp_type, 0, NOT_BUILT_IN,
1202                                            NULL, NULL_TREE);
1203     }
1204
1205   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1206
1207   temp_type
1208     = build_function_type (id_type,
1209                            tree_cons (NULL_TREE, super_type,
1210                                       tree_cons (NULL_TREE, selector_type,
1211                                                  NULL_TREE)));
1212
1213   umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1214                                       temp_type, 0, NOT_BUILT_IN,
1215                                       NULL, NULL_TREE);
1216
1217   /* The NeXT runtime defines the following additional entry points,
1218      used for dispatching calls to methods returning structs:
1219
1220      #if defined(__cplusplus)
1221        id objc_msgSend_stret(id self, SEL op, ...);
1222        id objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...);
1223      #else
1224        void objc_msgSend_stret(void * stretAddr, id self, SEL op, ...);
1225        void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
1226                                     SEL op, ...);
1227      #endif
1228
1229      struct objc_return_struct objc_msgSendNonNil_stret(id self, SEL op, ...);
1230
1231      These prototypes appear in <objc/objc-runtime.h>; however, they
1232      CANNOT BE USED DIRECTLY.  In order to call one of the ..._stret
1233      functions, the function must first be cast to a signature that
1234      corresponds to the actual ObjC method being invoked.  This is
1235      what is done by the build_objc_method_call() routine below.  */
1236
1237   if (flag_next_runtime)
1238     {
1239       tree objc_return_struct_type
1240         = xref_tag (RECORD_TYPE,
1241                     get_identifier (TAG_RETURN_STRUCT));
1242
1243       tree stret_temp_type
1244         = build_function_type (id_type,
1245                                tree_cons (NULL_TREE, id_type,
1246                                           tree_cons (NULL_TREE, selector_type,
1247                                                      NULL_TREE)));
1248
1249       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1250                                           stret_temp_type, 0, NOT_BUILT_IN,
1251                                           NULL, NULL_TREE);
1252       stret_temp_type
1253         = build_function_type (objc_return_struct_type,
1254                                tree_cons (NULL_TREE, id_type,
1255                                           tree_cons (NULL_TREE, selector_type,
1256                                                      NULL_TREE)));
1257
1258       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1259                                                  stret_temp_type, 0, NOT_BUILT_IN,
1260                                                  NULL, NULL_TREE);
1261
1262       stret_temp_type
1263         = build_function_type (id_type,
1264                                tree_cons (NULL_TREE, super_type,
1265                                           tree_cons (NULL_TREE, selector_type,
1266                                                      NULL_TREE)));
1267
1268       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1269                                                 stret_temp_type, 0, NOT_BUILT_IN, 0,
1270                                                 NULL_TREE);
1271     }
1272
1273   /* id objc_getClass (const char *); */
1274
1275   temp_type = build_function_type (id_type,
1276                                    tree_cons (NULL_TREE,
1277                                               const_string_type_node,
1278                                               OBJC_VOID_AT_END));
1279
1280   objc_get_class_decl
1281     = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
1282                         NULL, NULL_TREE);
1283
1284   /* id objc_getMetaClass (const char *); */
1285
1286   objc_get_meta_class_decl
1287     = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1288
1289   build_super_template ();
1290   if (flag_next_runtime)
1291     build_objc_exception_stuff ();
1292
1293   /* static SEL _OBJC_SELECTOR_TABLE[]; */
1294
1295   if (! flag_next_runtime)
1296     {
1297       if (flag_typed_selectors)
1298         {
1299           /* Suppress outputting debug symbols, because
1300              dbxout_init hasn'r been called yet.  */
1301           enum debug_info_type save_write_symbols = write_symbols;
1302           const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1303           write_symbols = NO_DEBUG;
1304           debug_hooks = &do_nothing_debug_hooks;
1305
1306           build_selector_template ();
1307           temp_type = build_array_type (objc_selector_template, NULL_TREE);
1308
1309           write_symbols = save_write_symbols;
1310           debug_hooks = save_hooks;
1311         }
1312       else
1313         temp_type = build_array_type (selector_type, NULL_TREE);
1314
1315       layout_type (temp_type);
1316       UOBJC_SELECTOR_TABLE_decl
1317         = create_builtin_decl (VAR_DECL, temp_type,
1318                                "_OBJC_SELECTOR_TABLE");
1319
1320       /* Avoid warning when not sending messages.  */
1321       TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1322     }
1323
1324   generate_forward_declaration_to_string_table ();
1325
1326   /* Forward declare constant_string_id and constant_string_type.  */
1327   if (!constant_string_class_name)
1328     constant_string_class_name = default_constant_string_class_name;
1329
1330   constant_string_id = get_identifier (constant_string_class_name);
1331   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1332
1333   /* Pre-build the following entities - for speed/convenience.  */
1334   self_id = get_identifier ("self");
1335   ucmd_id = get_identifier ("_cmd");
1336 #ifndef OBJCPLUS
1337   /* The C++ front-end does not appear to grok __attribute__((__unused__)).  */
1338   unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1339 #endif  
1340 }
1341
1342 /* Ensure that the ivar list for NSConstantString/NXConstantString
1343    (or whatever was specified via `-fconstant-string-class')
1344    contains fields at least as large as the following three, so that
1345    the runtime can stomp on them with confidence:
1346
1347    struct STRING_OBJECT_CLASS_NAME
1348    {
1349      Object isa;
1350      char *cString;
1351      unsigned int length;
1352    }; */
1353
1354 static int
1355 check_string_class_template (void)
1356 {
1357   tree field_decl = TYPE_FIELDS (constant_string_type);
1358
1359 #define AT_LEAST_AS_LARGE_AS(F, T) \
1360   (F && TREE_CODE (F) == FIELD_DECL \
1361      && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1362          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1363
1364   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1365     return 0;
1366
1367   field_decl = TREE_CHAIN (field_decl);
1368   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1369     return 0;
1370
1371   field_decl = TREE_CHAIN (field_decl);
1372   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1373
1374 #undef AT_LEAST_AS_LARGE_AS
1375 }
1376
1377 /* Avoid calling `check_string_class_template ()' more than once.  */
1378 static GTY(()) int string_layout_checked;
1379
1380 /* Custom build_string which sets TREE_TYPE!  */
1381
1382 static tree
1383 my_build_string (int len, const char *str)
1384 {
1385   return fix_string_type (build_string (len, str));
1386 }
1387
1388 /* Given a chain of STRING_CST's, build a static instance of
1389    NXConstantString which points at the concatenation of those
1390    strings.  We place the string object in the __string_objects
1391    section of the __OBJC segment.  The Objective-C runtime will
1392    initialize the isa pointers of the string objects to point at the
1393    NXConstantString class object.  */
1394
1395 tree
1396 build_objc_string_object (tree string)
1397 {
1398   tree initlist, constructor, constant_string_class;
1399   int length;
1400
1401   string = fix_string_type (string);
1402
1403   constant_string_class = lookup_interface (constant_string_id);
1404   if (!constant_string_class
1405       || !(constant_string_type
1406              = CLASS_STATIC_TEMPLATE (constant_string_class)))
1407     {
1408       error ("cannot find interface declaration for `%s'",
1409              IDENTIFIER_POINTER (constant_string_id));
1410       return error_mark_node;
1411     }
1412
1413   /* Call to 'combine_strings' has been moved above.  */
1414   TREE_SET_CODE (string, STRING_CST);
1415   length = TREE_STRING_LENGTH (string) - 1;
1416
1417   if (!string_layout_checked)
1418     {
1419       /* The NSConstantString/NXConstantString ivar layout is now
1420          known.  */
1421       if (!check_string_class_template ())
1422         {
1423           error ("interface `%s' does not have valid constant string layout",
1424                  IDENTIFIER_POINTER (constant_string_id));
1425           return error_mark_node;
1426         }
1427       add_class_reference (constant_string_id);
1428     }
1429
1430   /* & ((NXConstantString) { NULL, string, length })  */
1431
1432   if (flag_next_runtime)
1433     {
1434       /* For the NeXT runtime, we can generate a literal reference
1435          to the string class, don't need to run a constructor.  */
1436       setup_string_decl ();
1437       if (string_class_decl == NULL_TREE)
1438         {
1439           error ("cannot find reference tag for class `%s'",
1440                  IDENTIFIER_POINTER (constant_string_id));
1441           return error_mark_node;
1442         }
1443       initlist = build_tree_list
1444         (NULL_TREE,
1445          copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
1446     }
1447   else
1448     {
1449       initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1450     }
1451
1452   initlist
1453     = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1454                  initlist);
1455   initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1456   constructor = objc_build_constructor (constant_string_type,
1457                                         nreverse (initlist));
1458
1459   if (!flag_next_runtime)
1460     {
1461       constructor
1462         = objc_add_static_instance (constructor, constant_string_type);
1463     }
1464
1465   return (build_unary_op (ADDR_EXPR, constructor, 1));
1466 }
1467
1468 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1469
1470 static GTY(()) int num_static_inst;
1471
1472 static tree
1473 objc_add_static_instance (tree constructor, tree class_decl)
1474 {
1475   tree *chain, decl;
1476   char buf[256];
1477
1478   /* Find the list of static instances for the CLASS_DECL.  Create one if
1479      not found.  */
1480   for (chain = &objc_static_instances;
1481        *chain && TREE_VALUE (*chain) != class_decl;
1482        chain = &TREE_CHAIN (*chain));
1483   if (!*chain)
1484     {
1485       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1486       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1487     }
1488
1489   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1490   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1491   DECL_COMMON (decl) = 1;
1492   TREE_STATIC (decl) = 1;
1493   DECL_ARTIFICIAL (decl) = 1;
1494   DECL_INITIAL (decl) = constructor;
1495
1496   /* We may be writing something else just now.
1497      Postpone till end of input.  */
1498   DECL_DEFER_OUTPUT (decl) = 1;
1499   pushdecl_top_level (decl);
1500   rest_of_decl_compilation (decl, 0, 1, 0);
1501
1502   /* Add the DECL to the head of this CLASS' list.  */
1503   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1504
1505   return decl;
1506 }
1507
1508 /* Build a static constant CONSTRUCTOR
1509    with type TYPE and elements ELTS.  */
1510
1511 static tree
1512 objc_build_constructor (tree type, tree elts)
1513 {
1514   tree constructor, f, e;
1515
1516   /* ??? Most of the places that we build constructors, we don't fill in
1517      the type of integers properly.  Convert them all en masse.  */
1518   if (TREE_CODE (type) == ARRAY_TYPE)
1519     {
1520       f = TREE_TYPE (type);
1521       if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
1522         for (e = elts; e ; e = TREE_CHAIN (e))
1523           TREE_VALUE (e) = convert (f, TREE_VALUE (e));
1524     }
1525   else
1526     {
1527       f = TYPE_FIELDS (type);
1528       for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
1529         if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
1530             || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
1531           TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
1532     }
1533
1534   constructor = build_constructor (type, elts);
1535   TREE_CONSTANT (constructor) = 1;
1536   TREE_STATIC (constructor) = 1;
1537   TREE_READONLY (constructor) = 1;
1538
1539 #ifdef OBJCPLUS
1540   /* zlaski 2001-Apr-02: mark this as a call to a constructor, as required by
1541      build_unary_op (wasn't true in 2.7.2.1 days) */
1542   TREE_HAS_CONSTRUCTOR (constructor) = 1;
1543 #endif
1544   return constructor;
1545 }
1546 \f
1547 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1548
1549 /* Predefine the following data type:
1550
1551    struct _objc_symtab
1552    {
1553      long sel_ref_cnt;
1554      SEL *refs;
1555      short cls_def_cnt;
1556      short cat_def_cnt;
1557      void *defs[cls_def_cnt + cat_def_cnt];
1558    }; */
1559
1560 static void
1561 build_objc_symtab_template (void)
1562 {
1563   tree field_decl, field_decl_chain;
1564
1565   objc_symtab_template
1566     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1567
1568   /* long sel_ref_cnt; */
1569
1570   field_decl = create_builtin_decl (FIELD_DECL,
1571                                     long_integer_type_node,
1572                                     "sel_ref_cnt");
1573   field_decl_chain = field_decl;
1574
1575   /* SEL *refs; */
1576
1577   field_decl = create_builtin_decl (FIELD_DECL,
1578                                     build_pointer_type (selector_type),
1579                                     "refs");
1580   chainon (field_decl_chain, field_decl);
1581
1582   /* short cls_def_cnt; */
1583
1584   field_decl = create_builtin_decl (FIELD_DECL,
1585                                     short_integer_type_node,
1586                                     "cls_def_cnt");
1587   chainon (field_decl_chain, field_decl);
1588
1589   /* short cat_def_cnt; */
1590
1591   field_decl = create_builtin_decl (FIELD_DECL,
1592                                     short_integer_type_node,
1593                                     "cat_def_cnt");
1594   chainon (field_decl_chain, field_decl);
1595
1596   if (imp_count || cat_count || !flag_next_runtime)
1597     {
1598       /* void *defs[imp_count + cat_count (+ 1)]; */
1599       /* NB: The index is one less than the size of the array.  */
1600       int index = imp_count + cat_count
1601                 + (flag_next_runtime? -1: 0);
1602       field_decl = create_builtin_decl
1603                    (FIELD_DECL,
1604                     build_array_type
1605                     (ptr_type_node,
1606                      build_index_type (build_int_2 (index, 0))),
1607                     "defs");
1608       chainon (field_decl_chain, field_decl);
1609     }
1610
1611   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1612 }
1613
1614 /* Create the initial value for the `defs' field of _objc_symtab.
1615    This is a CONSTRUCTOR.  */
1616
1617 static tree
1618 init_def_list (tree type)
1619 {
1620   tree expr, initlist = NULL_TREE;
1621   struct imp_entry *impent;
1622
1623   if (imp_count)
1624     for (impent = imp_list; impent; impent = impent->next)
1625       {
1626         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1627           {
1628             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1629             initlist = tree_cons (NULL_TREE, expr, initlist);
1630           }
1631       }
1632
1633   if (cat_count)
1634     for (impent = imp_list; impent; impent = impent->next)
1635       {
1636         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1637           {
1638             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1639             initlist = tree_cons (NULL_TREE, expr, initlist);
1640           }
1641       }
1642
1643   if (!flag_next_runtime)
1644     {
1645       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1646       tree expr;
1647
1648       if (static_instances_decl)
1649         expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1650       else
1651         expr = build_int_2 (0, 0);
1652
1653       initlist = tree_cons (NULL_TREE, expr, initlist);
1654     }
1655
1656   return objc_build_constructor (type, nreverse (initlist));
1657 }
1658
1659 /* Construct the initial value for all of _objc_symtab.  */
1660
1661 static tree
1662 init_objc_symtab (tree type)
1663 {
1664   tree initlist;
1665
1666   /* sel_ref_cnt = { ..., 5, ... } */
1667
1668   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1669
1670   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1671
1672   if (flag_next_runtime || ! sel_ref_chain)
1673     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1674   else
1675     initlist = tree_cons (NULL_TREE,
1676                           build_unary_op (ADDR_EXPR,
1677                                           UOBJC_SELECTOR_TABLE_decl, 1),
1678                           initlist);
1679
1680   /* cls_def_cnt = { ..., 5, ... } */
1681
1682   initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1683
1684   /* cat_def_cnt = { ..., 5, ... } */
1685
1686   initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1687
1688   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1689
1690   if (imp_count || cat_count || !flag_next_runtime)
1691     {
1692
1693       tree field = TYPE_FIELDS (type);
1694       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1695
1696       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1697                             initlist);
1698     }
1699
1700   return objc_build_constructor (type, nreverse (initlist));
1701 }
1702
1703 /* Generate forward declarations for metadata such as
1704   'OBJC_CLASS_...'.  */
1705
1706 static tree
1707 build_metadata_decl (const char *name, tree type)
1708 {
1709   tree decl, decl_specs;
1710   /* extern struct TYPE NAME_<name>; */
1711   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
1712   decl_specs = tree_cons (NULL_TREE, type, decl_specs);
1713   decl = define_decl (synth_id_with_class_suffix
1714                       (name,
1715                        objc_implementation_context),
1716                       decl_specs);
1717   TREE_USED (decl) = 1;
1718   DECL_ARTIFICIAL (decl) = 1;
1719   TREE_PUBLIC (decl) = 0;
1720   return decl;
1721 }
1722
1723 /* Push forward-declarations of all the categories so that
1724    init_def_list can use them in a CONSTRUCTOR.  */
1725
1726 static void
1727 forward_declare_categories (void)
1728 {
1729   struct imp_entry *impent;
1730   tree sav = objc_implementation_context;
1731
1732   for (impent = imp_list; impent; impent = impent->next)
1733     {
1734       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1735         {
1736           /* Set an invisible arg to synth_id_with_class_suffix.  */
1737           objc_implementation_context = impent->imp_context;
1738           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1739           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1740                                                     objc_category_template);                    
1741         }
1742     }
1743   objc_implementation_context = sav;
1744 }
1745
1746 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1747    and initialized appropriately.  */
1748
1749 static void
1750 generate_objc_symtab_decl (void)
1751 {
1752   tree sc_spec;
1753
1754   if (!objc_category_template)
1755     build_category_template ();
1756
1757   /* forward declare categories */
1758   if (cat_count)
1759     forward_declare_categories ();
1760
1761   if (!objc_symtab_template)
1762     build_objc_symtab_template ();
1763
1764   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1765
1766   UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1767                                    tree_cons (NULL_TREE,
1768                                               objc_symtab_template, sc_spec),
1769                                    1,
1770                                    NULL_TREE);
1771
1772   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1773   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1774   DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1775   finish_decl (UOBJC_SYMBOLS_decl,
1776                init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1777                NULL_TREE);
1778 }
1779 \f
1780 static tree
1781 init_module_descriptor (tree type)
1782 {
1783   tree initlist, expr;
1784
1785   /* version = { 1, ... } */
1786
1787   expr = build_int_2 (OBJC_VERSION, 0);
1788   initlist = build_tree_list (NULL_TREE, expr);
1789
1790   /* size = { ..., sizeof (struct objc_module), ... } */
1791
1792   expr = size_in_bytes (objc_module_template);
1793   initlist = tree_cons (NULL_TREE, expr, initlist);
1794
1795   /* name = { ..., "foo.m", ... } */
1796
1797   expr = add_objc_string (get_identifier (input_filename), class_names);
1798   initlist = tree_cons (NULL_TREE, expr, initlist);
1799
1800   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1801
1802   if (UOBJC_SYMBOLS_decl)
1803     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1804   else
1805     expr = build_int_2 (0, 0);
1806   initlist = tree_cons (NULL_TREE, expr, initlist);
1807
1808   return objc_build_constructor (type, nreverse (initlist));
1809 }
1810
1811 /* Write out the data structures to describe Objective C classes defined.
1812    If appropriate, compile and output a setup function to initialize them.
1813    Return a symbol_ref to the function to call to initialize the Objective C
1814    data structures for this file (and perhaps for other files also).
1815
1816    struct objc_module { ... } _OBJC_MODULE = { ... };   */
1817
1818 static rtx
1819 build_module_descriptor (void)
1820 {
1821   tree decl_specs, field_decl, field_decl_chain;
1822
1823   objc_module_template
1824     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1825
1826   /* Long version; */
1827
1828   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1829   field_decl = get_identifier ("version");
1830   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1831   field_decl_chain = field_decl;
1832
1833   /* long  size; */
1834
1835   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1836   field_decl = get_identifier ("size");
1837   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1838   chainon (field_decl_chain, field_decl);
1839
1840   /* char  *name; */
1841
1842   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1843   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1844   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1845   chainon (field_decl_chain, field_decl);
1846
1847   /* struct objc_symtab *symtab; */
1848
1849   decl_specs = get_identifier (UTAG_SYMTAB);
1850   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1851   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1852   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1853   chainon (field_decl_chain, field_decl);
1854
1855   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1856
1857   /* Create an instance of "objc_module".  */
1858
1859   decl_specs = tree_cons (NULL_TREE, objc_module_template,
1860                           build_tree_list (NULL_TREE,
1861                                            ridpointers[(int) RID_STATIC]));
1862
1863   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1864                                    decl_specs, 1, NULL_TREE);
1865
1866   DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1867   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1868   DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
1869
1870   finish_decl (UOBJC_MODULES_decl,
1871                init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1872                NULL_TREE);
1873
1874   /* Mark the decl to avoid "defined but not used" warning.  */
1875   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1876
1877   /* Generate a constructor call for the module descriptor.
1878      This code was generated by reading the grammar rules
1879      of c-parse.in;  Therefore, it may not be the most efficient
1880      way of generating the requisite code.  */
1881
1882   if (flag_next_runtime)
1883     return NULL_RTX;
1884
1885   {
1886     tree parms, execclass_decl, decelerator, void_list_node_1;
1887     tree init_function_name, init_function_decl;
1888
1889     /* Declare void __objc_execClass (void *); */
1890
1891     void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1892     execclass_decl = build_decl (FUNCTION_DECL,
1893                                  get_identifier (TAG_EXECCLASS),
1894                                  build_function_type (void_type_node,
1895                                         tree_cons (NULL_TREE, ptr_type_node,
1896                                                    OBJC_VOID_AT_END)));
1897                                                 
1898     DECL_EXTERNAL (execclass_decl) = 1;
1899     DECL_ARTIFICIAL (execclass_decl) = 1;
1900     TREE_PUBLIC (execclass_decl) = 1;
1901     pushdecl (execclass_decl);
1902     rest_of_decl_compilation (execclass_decl, 0, 0, 0);
1903     assemble_external (execclass_decl);
1904
1905     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
1906
1907     init_function_name = get_file_function_name ('I');
1908     start_function (void_list_node_1,
1909                     build_nt (CALL_EXPR, init_function_name,
1910                               tree_cons (NULL_TREE, NULL_TREE,
1911                                          OBJC_VOID_AT_END),
1912                               NULL_TREE),
1913                     NULL_TREE);
1914     store_parm_decls ();
1915
1916     init_function_decl = current_function_decl;
1917     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
1918     TREE_USED (init_function_decl) = 1;
1919     /* Don't let this one be deferred.  */
1920     DECL_INLINE (init_function_decl) = 0;
1921     DECL_UNINLINABLE (init_function_decl) = 1;
1922     current_function_cannot_inline
1923       = "static constructors and destructors cannot be inlined";
1924
1925     parms
1926       = build_tree_list (NULL_TREE,
1927                          build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1928     decelerator = build_function_call (execclass_decl, parms);
1929
1930     c_expand_expr_stmt (decelerator);
1931
1932     finish_function ();
1933
1934     return XEXP (DECL_RTL (init_function_decl), 0);
1935   }
1936 }
1937
1938 /* extern const char _OBJC_STRINGS[]; */
1939
1940 static void
1941 generate_forward_declaration_to_string_table (void)
1942 {
1943   tree sc_spec, decl_specs, expr_decl;
1944
1945   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1946   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1947
1948   expr_decl
1949     = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1950
1951   UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1952 }
1953
1954 /* Return the DECL of the string IDENT in the SECTION.  */
1955
1956 static tree
1957 get_objc_string_decl (tree ident, enum string_section section)
1958 {
1959   tree chain;
1960
1961   if (section == class_names)
1962     chain = class_names_chain;
1963   else if (section == meth_var_names)
1964     chain = meth_var_names_chain;
1965   else if (section == meth_var_types)
1966     chain = meth_var_types_chain;
1967   else
1968     abort ();
1969
1970   for (; chain != 0; chain = TREE_CHAIN (chain))
1971     if (TREE_VALUE (chain) == ident)
1972       return (TREE_PURPOSE (chain));
1973
1974   abort ();
1975   return NULL_TREE;
1976 }
1977
1978 /* Output references to all statically allocated objects.  Return the DECL
1979    for the array built.  */
1980
1981 static void
1982 generate_static_references (void)
1983 {
1984   tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1985   tree class_name, class, decl, initlist;
1986   tree cl_chain, in_chain, type;
1987   int num_inst, num_class;
1988   char buf[256];
1989
1990   if (flag_next_runtime)
1991     abort ();
1992
1993   for (cl_chain = objc_static_instances, num_class = 0;
1994        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1995     {
1996       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1997            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1998
1999       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
2000       ident = get_identifier (buf);
2001
2002       expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
2003       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
2004                              build_tree_list (NULL_TREE,
2005                                               ridpointers[(int) RID_STATIC]));
2006       decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
2007       DECL_CONTEXT (decl) = 0;
2008       DECL_ARTIFICIAL (decl) = 1;
2009
2010       /* Output {class_name, ...}.  */
2011       class = TREE_VALUE (cl_chain);
2012       class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
2013       initlist = build_tree_list (NULL_TREE,
2014                                   build_unary_op (ADDR_EXPR, class_name, 1));
2015
2016       /* Output {..., instance, ...}.  */
2017       for (in_chain = TREE_PURPOSE (cl_chain);
2018            in_chain; in_chain = TREE_CHAIN (in_chain))
2019         {
2020           expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2021           initlist = tree_cons (NULL_TREE, expr, initlist);
2022         }
2023
2024       /* Output {..., NULL}.  */
2025       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2026
2027       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2028       finish_decl (decl, expr, NULL_TREE);
2029       TREE_USED (decl) = 1;
2030
2031       type = build_array_type (build_pointer_type (void_type_node), 0);
2032       decl = build_decl (VAR_DECL, ident, type);
2033       TREE_USED (decl) = 1;
2034       TREE_STATIC (decl) = 1;
2035       decls
2036         = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2037     }
2038
2039   decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
2040   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
2041   expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
2042   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
2043                          build_tree_list (NULL_TREE,
2044                                           ridpointers[(int) RID_STATIC]));
2045   static_instances_decl
2046     = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
2047   TREE_USED (static_instances_decl) = 1;
2048   DECL_CONTEXT (static_instances_decl) = 0;
2049   DECL_ARTIFICIAL (static_instances_decl) = 1;
2050   expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
2051                             nreverse (decls));
2052   finish_decl (static_instances_decl, expr, NULL_TREE);
2053 }
2054
2055 /* Output all strings.  */
2056
2057 static void
2058 generate_strings (void)
2059 {
2060   tree sc_spec, decl_specs, expr_decl;
2061   tree chain, string_expr;
2062   tree string, decl;
2063
2064   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2065     {
2066       string = TREE_VALUE (chain);
2067       decl = TREE_PURPOSE (chain);
2068       sc_spec
2069         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2070       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2071       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2072       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2073       DECL_CONTEXT (decl) = NULL_TREE;
2074       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2075                                      IDENTIFIER_POINTER (string));
2076       finish_decl (decl, string_expr, NULL_TREE);
2077     }
2078
2079   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2080     {
2081       string = TREE_VALUE (chain);
2082       decl = TREE_PURPOSE (chain);
2083       sc_spec
2084         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2085       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2086       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2087       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2088       DECL_CONTEXT (decl) = NULL_TREE;
2089       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2090                                      IDENTIFIER_POINTER (string));
2091       finish_decl (decl, string_expr, NULL_TREE);
2092     }
2093
2094   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2095     {
2096       string = TREE_VALUE (chain);
2097       decl = TREE_PURPOSE (chain);
2098       sc_spec
2099         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2100       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2101       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2102       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2103       DECL_CONTEXT (decl) = NULL_TREE;
2104       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2105                                 IDENTIFIER_POINTER (string));
2106       finish_decl (decl, string_expr, NULL_TREE);
2107     }
2108 }
2109
2110 static GTY(()) int selector_reference_idx;
2111
2112 static tree
2113 build_selector_reference_decl (void)
2114 {
2115   tree decl, ident;
2116   char buf[256];
2117
2118   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2119
2120   ident = get_identifier (buf);
2121
2122   decl = build_decl (VAR_DECL, ident, selector_type);
2123   DECL_EXTERNAL (decl) = 1;
2124   TREE_PUBLIC (decl) = 0;
2125   TREE_USED (decl) = 1;
2126   DECL_ARTIFICIAL (decl) = 1;
2127   DECL_CONTEXT (decl) = 0;
2128
2129   make_decl_rtl (decl, 0);
2130   pushdecl_top_level (decl);
2131
2132   return decl;
2133 }
2134
2135 /* Just a handy wrapper for add_objc_string.  */
2136
2137 static tree
2138 build_selector (tree ident)
2139 {
2140   tree expr = add_objc_string (ident, meth_var_names);
2141   if (flag_typed_selectors)
2142     return expr;
2143   else
2144     return build_c_cast (selector_type, expr); /* cast! */
2145 }
2146
2147 static void
2148 build_selector_translation_table (void)
2149 {
2150   tree sc_spec, decl_specs;
2151   tree chain, initlist = NULL_TREE;
2152   int offset = 0;
2153   tree decl = NULL_TREE, var_decl, name;
2154
2155   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2156     {
2157       tree expr;
2158
2159       if (warn_selector && objc_implementation_context)
2160       {
2161         tree method_chain;
2162         bool found = false;
2163         for (method_chain = meth_var_names_chain;
2164              method_chain;
2165              method_chain = TREE_CHAIN (method_chain))
2166           {
2167             if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2168               {
2169                 found = true;
2170                 break;
2171               }
2172           }
2173         if (!found)
2174           {
2175             /* Adjust line number for warning message.  */
2176             int save_lineno = input_line;
2177             if (flag_next_runtime && TREE_PURPOSE (chain))
2178               input_line = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
2179             warning ("creating selector for non existant method %s",
2180                      IDENTIFIER_POINTER (TREE_VALUE (chain)));
2181             input_line = save_lineno;
2182           }
2183       }
2184
2185       expr = build_selector (TREE_VALUE (chain));
2186
2187       if (flag_next_runtime)
2188         {
2189           name = DECL_NAME (TREE_PURPOSE (chain));
2190
2191           sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2192
2193           /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2194           decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2195
2196           var_decl = name;
2197
2198           /* The `decl' that is returned from start_decl is the one that we
2199              forward declared in `build_selector_reference'  */
2200           decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
2201         }
2202
2203       /* add one for the '\0' character */
2204       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2205
2206       if (flag_next_runtime)
2207         finish_decl (decl, expr, NULL_TREE);
2208       else
2209         {
2210           if (flag_typed_selectors)
2211             {
2212               tree eltlist = NULL_TREE;
2213               tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2214               eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2215               eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2216               expr = objc_build_constructor (objc_selector_template,
2217                                              nreverse (eltlist));
2218             }
2219           initlist = tree_cons (NULL_TREE, expr, initlist);
2220
2221         }
2222     }
2223
2224   if (! flag_next_runtime)
2225     {
2226       /* Cause the variable and its initial value to be actually output.  */
2227       DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2228       TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2229       /* NULL terminate the list and fix the decl for output.  */
2230       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2231       DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
2232       initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2233                                          nreverse (initlist));
2234       finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2235       current_function_decl = NULL_TREE;
2236     }
2237 }
2238
2239 static tree
2240 get_proto_encoding (tree proto)
2241 {
2242   tree encoding;
2243   if (proto)
2244     {
2245       if (! METHOD_ENCODING (proto))
2246         {
2247           encoding = encode_method_prototype (proto);
2248           METHOD_ENCODING (proto) = encoding;
2249         }
2250       else
2251         encoding = METHOD_ENCODING (proto);
2252
2253       return add_objc_string (encoding, meth_var_types);
2254     }
2255   else
2256     return build_int_2 (0, 0);
2257 }
2258
2259 /* sel_ref_chain is a list whose "value" fields will be instances of
2260    identifier_node that represent the selector.  */
2261
2262 static tree
2263 build_typed_selector_reference (tree ident, tree prototype)
2264 {
2265   tree *chain = &sel_ref_chain;
2266   tree expr;
2267   int index = 0;
2268
2269   while (*chain)
2270     {
2271       if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2272         goto return_at_index;
2273
2274       index++;
2275       chain = &TREE_CHAIN (*chain);
2276     }
2277
2278   *chain = tree_cons (prototype, ident, NULL_TREE);
2279
2280  return_at_index:
2281   expr = build_unary_op (ADDR_EXPR,
2282                          build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2283                                           build_int_2 (index, 0)),
2284                          1);
2285   return build_c_cast (selector_type, expr);
2286 }
2287
2288 static tree
2289 build_selector_reference (tree ident)
2290 {
2291   tree *chain = &sel_ref_chain;
2292   tree expr;
2293   int index = 0;
2294
2295   while (*chain)
2296     {
2297       if (TREE_VALUE (*chain) == ident)
2298         return (flag_next_runtime
2299                 ? TREE_PURPOSE (*chain)
2300                 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2301                                    build_int_2 (index, 0)));
2302
2303       index++;
2304       chain = &TREE_CHAIN (*chain);
2305     }
2306
2307   expr = build_selector_reference_decl ();
2308
2309   *chain = tree_cons (expr, ident, NULL_TREE);
2310
2311   return (flag_next_runtime
2312           ? expr
2313           : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2314                              build_int_2 (index, 0)));
2315 }
2316
2317 static GTY(()) int class_reference_idx;
2318
2319 static tree
2320 build_class_reference_decl (void)
2321 {
2322   tree decl, ident;
2323   char buf[256];
2324
2325   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2326
2327   ident = get_identifier (buf);
2328
2329   decl = build_decl (VAR_DECL, ident, objc_class_type);
2330   DECL_EXTERNAL (decl) = 1;
2331   TREE_PUBLIC (decl) = 0;
2332   TREE_USED (decl) = 1;
2333   DECL_CONTEXT (decl) = 0;
2334   DECL_ARTIFICIAL (decl) = 1;
2335
2336   make_decl_rtl (decl, 0);
2337   pushdecl_top_level (decl);
2338
2339   return decl;
2340 }
2341
2342 /* Create a class reference, but don't create a variable to reference
2343    it.  */
2344
2345 static void
2346 add_class_reference (tree ident)
2347 {
2348   tree chain;
2349
2350   if ((chain = cls_ref_chain))
2351     {
2352       tree tail;
2353       do
2354         {
2355           if (ident == TREE_VALUE (chain))
2356             return;
2357
2358           tail = chain;
2359           chain = TREE_CHAIN (chain);
2360         }
2361       while (chain);
2362
2363       /* Append to the end of the list */
2364       TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2365     }
2366   else
2367     cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2368 }
2369
2370 /* Get a class reference, creating it if necessary.  Also create the
2371    reference variable.  */
2372
2373 tree
2374 get_class_reference (tree ident)
2375 {
2376   tree orig_ident;
2377
2378 #ifdef OBJCPLUS
2379   if (processing_template_decl)
2380     /* Must wait until template instantiation time.  */
2381     return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2382   if (TREE_CODE (ident) == TYPE_DECL)
2383     ident = DECL_NAME (ident);
2384 #endif
2385   orig_ident = ident;
2386
2387   if (!(ident = is_class_name (ident)))
2388     {
2389       error ("`%s' is not an Objective-C class name or alias",
2390              IDENTIFIER_POINTER (orig_ident));
2391       return error_mark_node;
2392     }
2393
2394   if (flag_next_runtime && !flag_zero_link)
2395     {
2396       tree *chain;
2397       tree decl;
2398
2399       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2400         if (TREE_VALUE (*chain) == ident)
2401           {
2402             if (! TREE_PURPOSE (*chain))
2403               TREE_PURPOSE (*chain) = build_class_reference_decl ();
2404
2405             return TREE_PURPOSE (*chain);
2406           }
2407
2408       decl = build_class_reference_decl ();
2409       *chain = tree_cons (decl, ident, NULL_TREE);
2410       return decl;
2411     }
2412   else
2413     {
2414       tree params;
2415
2416       add_class_reference (ident);
2417
2418       params = build_tree_list (NULL_TREE,
2419                                 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2420                                                  IDENTIFIER_POINTER (ident)));
2421
2422       assemble_external (objc_get_class_decl);
2423       return build_function_call (objc_get_class_decl, params);
2424     }
2425 }
2426
2427 /* For each string section we have a chain which maps identifier nodes
2428    to decls for the strings.  */
2429
2430 static tree
2431 add_objc_string (tree ident, enum string_section section)
2432 {
2433   tree *chain, decl;
2434
2435   if (section == class_names)
2436     chain = &class_names_chain;
2437   else if (section == meth_var_names)
2438     chain = &meth_var_names_chain;
2439   else if (section == meth_var_types)
2440     chain = &meth_var_types_chain;
2441   else
2442     abort ();
2443
2444   while (*chain)
2445     {
2446       if (TREE_VALUE (*chain) == ident)
2447         return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2448
2449       chain = &TREE_CHAIN (*chain);
2450     }
2451
2452   decl = build_objc_string_decl (section);
2453
2454   *chain = tree_cons (decl, ident, NULL_TREE);
2455
2456   return build_unary_op (ADDR_EXPR, decl, 1);
2457 }
2458
2459 static GTY(()) int class_names_idx;
2460 static GTY(()) int meth_var_names_idx;
2461 static GTY(()) int meth_var_types_idx;
2462
2463 static tree
2464 build_objc_string_decl (enum string_section section)
2465 {
2466   tree decl, ident;
2467   char buf[256];
2468
2469   if (section == class_names)
2470     sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2471   else if (section == meth_var_names)
2472     sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2473   else if (section == meth_var_types)
2474     sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2475
2476   ident = get_identifier (buf);
2477
2478   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2479   DECL_EXTERNAL (decl) = 1;
2480   TREE_PUBLIC (decl) = 0;
2481   TREE_USED (decl) = 1;
2482   TREE_CONSTANT (decl) = 1;
2483   DECL_CONTEXT (decl) = 0;
2484   DECL_ARTIFICIAL (decl) = 1;
2485
2486   make_decl_rtl (decl, 0);
2487   pushdecl_top_level (decl);
2488
2489   return decl;
2490 }
2491
2492
2493 void
2494 objc_declare_alias (tree alias_ident, tree class_ident)
2495 {
2496   tree underlying_class;
2497
2498 #ifdef OBJCPLUS
2499   if (current_namespace != global_namespace) {
2500     error ("Objective-C declarations may only appear in global scope");
2501   }
2502 #endif /* OBJCPLUS */
2503
2504   if (!(underlying_class = is_class_name (class_ident)))
2505     warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2506   else if (is_class_name (alias_ident))
2507     warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2508   else
2509     alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2510 }
2511
2512 void
2513 objc_declare_class (tree ident_list)
2514 {
2515   tree list;
2516 #ifdef OBJCPLUS
2517   if (current_namespace != global_namespace) {
2518     error ("Objective-C declarations may only appear in global scope");
2519   }
2520 #endif /* OBJCPLUS */
2521
2522   for (list = ident_list; list; list = TREE_CHAIN (list))
2523     {
2524       tree ident = TREE_VALUE (list);
2525
2526       if (! is_class_name (ident))
2527         {
2528           tree record = lookup_name (ident);
2529         
2530           if (record && ! TREE_STATIC_TEMPLATE (record))
2531             {
2532               error ("`%s' redeclared as different kind of symbol",
2533                      IDENTIFIER_POINTER (ident));
2534               error ("%Jprevious declaration of '%D'",
2535                      record, record);
2536             }
2537
2538           record = xref_tag (RECORD_TYPE, ident);
2539           TREE_STATIC_TEMPLATE (record) = 1;
2540           class_chain = tree_cons (NULL_TREE, ident, class_chain);
2541         }
2542     }
2543 }
2544
2545 tree
2546 is_class_name (tree ident)
2547 {
2548   tree chain;
2549
2550   if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2551       && identifier_global_value (ident))
2552     ident = identifier_global_value (ident);
2553   while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2554     ident = TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2555
2556 #ifdef OBJCPLUS
2557   if (ident && TREE_CODE (ident) == RECORD_TYPE)
2558     ident = TYPE_NAME (ident);
2559   if (ident && TREE_CODE (ident) == TYPE_DECL)
2560     ident = DECL_NAME (ident);
2561 #endif
2562   if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2563     return NULL_TREE;
2564
2565   if (lookup_interface (ident))
2566     return ident;
2567
2568   for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2569     {
2570       if (ident == TREE_VALUE (chain))
2571         return ident;
2572     }
2573
2574   for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2575     {
2576       if (ident == TREE_VALUE (chain))
2577         return TREE_PURPOSE (chain);
2578     }
2579
2580   return 0;
2581 }
2582
2583 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
2584    class instance.  This is needed by other parts of the compiler to
2585    handle ObjC types gracefully.  */
2586
2587 tree
2588 objc_is_object_ptr (tree type)
2589 {
2590   type = TYPE_MAIN_VARIANT (type);
2591   if (!type || TREE_CODE (type) != POINTER_TYPE)
2592     return 0;
2593   /* NB: This function may be called before the ObjC front-end has
2594      been initialized, in which case ID_TYPE will be NULL.  */
2595   if (id_type && type && TYPE_P (type)
2596       && (IS_ID (type)
2597           || TREE_TYPE (type) == TREE_TYPE (objc_class_type)))
2598     return type;
2599   return is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
2600 }
2601
2602 tree
2603 lookup_interface (tree ident)
2604 {
2605   tree chain;
2606
2607 #ifdef OBJCPLUS
2608   if (ident && TREE_CODE (ident) == TYPE_DECL)
2609     ident = DECL_NAME (ident);
2610 #endif
2611   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2612     {
2613       if (ident == CLASS_NAME (chain))
2614       return chain;
2615     }
2616   return NULL_TREE;
2617 }
2618
2619 /* Implement @defs (<classname>) within struct bodies.  */
2620
2621 tree
2622 get_class_ivars_from_name (tree class_name)
2623 {
2624   tree interface = lookup_interface (class_name);
2625   tree field, fields = NULL_TREE;
2626
2627   if (interface)
2628     {
2629       tree raw_ivar = get_class_ivars (interface, 1);
2630
2631       /* Regenerate the FIELD_DECLs for the enclosing struct.  */
2632       for (; raw_ivar; raw_ivar = TREE_CHAIN (raw_ivar))
2633         {
2634           field = grokfield (TREE_PURPOSE (TREE_VALUE (raw_ivar)),
2635                              TREE_PURPOSE (raw_ivar),
2636                              TREE_VALUE (TREE_VALUE (raw_ivar)));
2637 #ifdef OBJCPLUS
2638           finish_member_declaration (field);
2639 #else
2640           fields = chainon (fields, field);
2641 #endif
2642         }
2643     }
2644   else
2645     error ("cannot find interface declaration for `%s'",
2646            IDENTIFIER_POINTER (class_name));
2647
2648   return fields;
2649 }
2650
2651 /* Used by: build_private_template, continue_class,
2652    and for @defs constructs.  */
2653
2654 static tree
2655 get_class_ivars (tree interface, int raw)
2656 {
2657   tree my_name, super_name, ivar_chain;
2658
2659   my_name = CLASS_NAME (interface);
2660   super_name = CLASS_SUPER_NAME (interface);
2661   if (raw)
2662     ivar_chain = CLASS_RAW_IVARS (interface);
2663   else
2664     {
2665       ivar_chain = CLASS_IVARS (interface);
2666       /* Save off a pristine copy of the leaf ivars (i.e, those not
2667          inherited from a super class).  */
2668       if (!CLASS_OWN_IVARS (interface))
2669         CLASS_OWN_IVARS (interface) = copy_list (ivar_chain);
2670     }
2671
2672   while (super_name)
2673     {
2674       tree op1;
2675       tree super_interface = lookup_interface (super_name);
2676
2677       if (!super_interface)
2678         {
2679           /* fatal did not work with 2 args...should fix */
2680           error ("cannot find interface declaration for `%s', superclass of `%s'",
2681                  IDENTIFIER_POINTER (super_name),
2682                  IDENTIFIER_POINTER (my_name));
2683           exit (FATAL_EXIT_CODE);
2684         }
2685
2686       if (super_interface == interface)
2687         fatal_error ("circular inheritance in interface declaration for `%s'",
2688                      IDENTIFIER_POINTER (super_name));
2689
2690       interface = super_interface;
2691       my_name = CLASS_NAME (interface);
2692       super_name = CLASS_SUPER_NAME (interface);
2693
2694       op1 = (raw ? CLASS_RAW_IVARS (interface) : CLASS_OWN_IVARS (interface));
2695       if (op1)
2696         {
2697           tree head = copy_list (op1);
2698
2699           /* Prepend super class ivars...make a copy of the list, we
2700              do not want to alter the original.  */
2701           chainon (head, ivar_chain);
2702           ivar_chain = head;
2703         }
2704     }
2705
2706   return ivar_chain;
2707 }
2708
2709 static tree
2710 objc_enter_block (void)
2711 {
2712   tree block;
2713
2714 #ifdef OBJCPLUS
2715   block = begin_compound_stmt (0);
2716 #else
2717   block = c_begin_compound_stmt ();
2718   pushlevel (0);
2719   clear_last_expr ();
2720   add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
2721 #endif
2722
2723   objc_exception_block_stack = tree_cons (NULL_TREE, block,
2724                                           objc_exception_block_stack);
2725
2726   blk_nesting_count++;
2727   return block;
2728 }
2729
2730 static tree
2731 objc_exit_block (void)
2732 {
2733   tree block = TREE_VALUE (objc_exception_block_stack);
2734 #ifndef OBJCPLUS
2735   tree scope_stmt, inner;
2736 #endif
2737
2738   objc_clear_super_receiver ();
2739 #ifdef OBJCPLUS
2740   finish_compound_stmt (0, block);
2741 #else
2742   scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
2743   inner = poplevel (KEEP_MAYBE, 1, 0);
2744
2745   SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
2746         = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
2747         = inner;
2748   RECHAIN_STMTS (block, COMPOUND_BODY (block));
2749 #endif
2750   last_expr_type = NULL_TREE;
2751   objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack); 
2752
2753   blk_nesting_count--;
2754   return block;
2755 }
2756
2757 static tree
2758 objc_declare_variable (enum rid scspec, tree name, tree type, tree init)
2759 {
2760   tree decl;
2761
2762   type = tree_cons (NULL_TREE, type,
2763                     tree_cons (NULL_TREE, ridpointers[(int) scspec],
2764                                NULL_TREE));
2765   TREE_STATIC (type) = 1;
2766   decl = start_decl (name, type, (init != NULL_TREE), NULL_TREE);
2767   finish_decl (decl, init, NULL_TREE);
2768   /* This prevents `unused variable' warnings when compiling with -Wall.  */
2769   TREE_USED (decl) = 1;
2770   DECL_ARTIFICIAL (decl) = 1;
2771   return decl;
2772 }
2773
2774 tree
2775 objc_build_throw_stmt (tree throw_expr)
2776 {
2777   tree func_params;
2778
2779   if (!flag_objc_exceptions)
2780     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
2781
2782   if (!throw_expr && objc_caught_exception)
2783     throw_expr = TREE_VALUE (objc_caught_exception);
2784
2785   if (!throw_expr)
2786     {
2787       error ("`@throw;' (rethrow) used outside of a `@catch' block");
2788       return error_mark_node;
2789     }
2790
2791   func_params = tree_cons (NULL_TREE, throw_expr, NULL_TREE);
2792
2793   assemble_external (objc_exception_throw_decl);
2794   return c_expand_expr_stmt (build_function_call (objc_exception_throw_decl,
2795                                                   func_params));
2796 }
2797
2798 static void
2799 val_stack_push (struct val_stack **nc, long val)
2800 {
2801   struct val_stack *new_elem = xmalloc (sizeof (struct val_stack));
2802   new_elem->val = val;
2803   new_elem->next = *nc;
2804   *nc = new_elem;
2805 }
2806
2807 static void
2808 val_stack_pop (struct val_stack **nc)
2809 {
2810   struct val_stack *old_elem = *nc;
2811   *nc = old_elem->next;
2812   free (old_elem);
2813 }
2814
2815 static void
2816 objc_build_try_enter_fragment (void)
2817 {
2818   /* objc_exception_try_enter(&_stackExceptionData);
2819      if (!_setjmp(&_stackExceptionData.buf)) {  */
2820
2821   tree func_params, if_stmt, cond;
2822
2823   func_params
2824     = tree_cons (NULL_TREE,
2825                  build_unary_op (ADDR_EXPR,
2826                                  TREE_VALUE (objc_stack_exception_data),
2827                                  0),
2828                  NULL_TREE);
2829
2830   assemble_external (objc_exception_try_enter_decl);
2831   c_expand_expr_stmt (build_function_call
2832                       (objc_exception_try_enter_decl, func_params));
2833
2834   if_stmt = c_begin_if_stmt ();
2835   if_nesting_count++;
2836   /* If <setjmp.h> has been included, the _setjmp prototype has
2837      acquired a real, breathing type for its parameter.  Cast our
2838      argument to that type.  */
2839   func_params
2840     = tree_cons (NULL_TREE,
2841                  build_c_cast (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))
2842                                ? TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
2843                                : ptr_type_node,
2844                                build_unary_op
2845                                (ADDR_EXPR,
2846                                 build_component_ref (TREE_VALUE (objc_stack_exception_data),
2847                                                      get_identifier ("buf")), 0)),
2848                  NULL_TREE);
2849   assemble_external (objc_setjmp_decl);
2850   cond = build_unary_op (TRUTH_NOT_EXPR,
2851                          build_function_call (objc_setjmp_decl, func_params),
2852                          0);
2853   c_expand_start_cond (c_common_truthvalue_conversion (cond),
2854                        0, if_stmt);
2855   objc_enter_block ();
2856 }
2857
2858 static tree
2859 objc_build_extract_expr (void)
2860 {
2861   /*    ... = objc_exception_extract(&_stackExceptionData);  */
2862
2863   tree func_params
2864     = tree_cons (NULL_TREE,
2865                  build_unary_op (ADDR_EXPR,
2866                                  TREE_VALUE (objc_stack_exception_data), 0),
2867                  NULL_TREE);
2868
2869   assemble_external (objc_exception_extract_decl);
2870   return build_function_call (objc_exception_extract_decl, func_params);
2871 }
2872
2873 static void
2874 objc_build_try_exit_fragment (void)
2875 {
2876   /* objc_exception_try_exit(&_stackExceptionData); */
2877
2878   tree func_params
2879     = tree_cons (NULL_TREE,
2880                  build_unary_op (ADDR_EXPR,
2881                                  TREE_VALUE (objc_stack_exception_data), 0),
2882                  NULL_TREE);
2883
2884     assemble_external (objc_exception_try_exit_decl);
2885     c_expand_expr_stmt (build_function_call (objc_exception_try_exit_decl,
2886                                              func_params));
2887 }
2888
2889 static void
2890 objc_build_extract_fragment (void)
2891 {
2892   /* } else {
2893       _rethrowException = objc_exception_extract(&_stackExceptionData);
2894      }  */
2895
2896   objc_exit_block ();
2897   c_finish_then ();
2898
2899   c_expand_start_else ();
2900   objc_enter_block ();
2901   c_expand_expr_stmt (build_modify_expr
2902                       (TREE_VALUE (objc_rethrow_exception),
2903                        NOP_EXPR,
2904                        objc_build_extract_expr ()));
2905   objc_exit_block ();
2906   c_finish_else ();
2907   c_expand_end_cond ();
2908   if_nesting_count--;
2909 }
2910
2911 tree
2912 objc_build_try_prologue (void)
2913 {
2914   /* { // new scope
2915        struct _objc_exception_data _stackExceptionData;
2916        volatile id _rethrowException = nil;
2917        { // begin TRY-CATCH scope
2918          objc_exception_try_enter(&_stackExceptionData);
2919          if (!_setjmp(&_stackExceptionData.buf)) {  */
2920
2921   tree try_catch_block;
2922
2923   if (!flag_objc_exceptions)
2924     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
2925
2926   objc_mark_locals_volatile ((void *)(exc_binding_stack
2927                                       ? exc_binding_stack->val
2928                                       : 0));
2929   objc_enter_block ();
2930   objc_stack_exception_data
2931     = tree_cons (NULL_TREE,
2932                  objc_declare_variable (RID_AUTO,
2933                                         get_identifier (UTAG_EXCDATA_VAR),
2934                                         xref_tag (RECORD_TYPE,
2935                                                   get_identifier (UTAG_EXCDATA)),
2936                                         NULL_TREE),
2937                  objc_stack_exception_data);
2938   objc_rethrow_exception = tree_cons (NULL_TREE,
2939                                       objc_declare_variable (RID_VOLATILE,
2940                                                              get_identifier (UTAG_RETHROWEXC_VAR),
2941                                                              id_type,
2942                                                              build_int_2 (0, 0)),
2943                                       objc_rethrow_exception);
2944
2945   try_catch_block = objc_enter_block ();
2946   val_stack_push (&exc_binding_stack, (long) get_current_scope ());
2947   objc_build_try_enter_fragment ();
2948
2949   return try_catch_block;
2950 }
2951
2952 void
2953 objc_build_try_epilogue (int also_catch_prologue)
2954 {
2955   if (also_catch_prologue)
2956     {
2957       /* } else {
2958            register id _caughtException = objc_exception_extract( &_stackExceptionData);
2959            objc_exception_try_enter(&_stackExceptionData);
2960            if(!_setjmp(&_stackExceptionData.buf)) {
2961              if (0) {  */
2962
2963       tree if_stmt;
2964
2965       objc_exit_block ();
2966       c_finish_then ();
2967                 
2968       c_expand_start_else ();
2969       objc_enter_block ();
2970       objc_caught_exception
2971         = tree_cons (NULL_TREE,
2972                      objc_declare_variable (RID_REGISTER,
2973                                             get_identifier (UTAG_CAUGHTEXC_VAR),
2974                                             id_type,
2975                                             objc_build_extract_expr ()),
2976                      objc_caught_exception);
2977       objc_build_try_enter_fragment ();
2978       val_stack_push (&catch_count_stack, 1);
2979       if_stmt = c_begin_if_stmt ();
2980       if_nesting_count++;
2981       c_expand_start_cond (c_common_truthvalue_conversion (boolean_false_node),
2982                            0, if_stmt);
2983       objc_enter_block ();
2984
2985       /* Start a new chain of @catch statements for this @try.  */
2986       objc_catch_type = tree_cons (objc_catch_type, NULL_TREE, NULL_TREE);
2987     }
2988   else
2989     {  /* !also_catch_prologue */
2990
2991       /* } else {
2992            _rethrowException = objc_exception_extract( &_stackExceptionData);
2993          }
2994        }  */
2995       objc_build_extract_fragment ();
2996       objc_exit_block ();
2997     }
2998 }
2999
3000 void
3001 objc_build_catch_stmt (tree catch_expr)
3002 {
3003   /* } else if (objc_exception_match(objc_get_class("SomeClass"), _caughtException)) {
3004        register SomeClass *e = _caughtException;  */
3005
3006   tree if_stmt, cond, func_params, prev_catch, var_name, var_type;
3007   int catch_id;
3008
3009 #ifndef OBJCPLUS
3010   /* Yet another C/C++ impedance mismatch.  */
3011   catch_expr = TREE_PURPOSE (catch_expr);
3012 #endif
3013
3014   var_name = TREE_VALUE (catch_expr);
3015   var_type = TREE_VALUE (TREE_PURPOSE (catch_expr));
3016   if (TREE_CODE (var_name) == INDIRECT_REF)
3017     var_name = TREE_OPERAND (var_name, 0);
3018   if (TREE_CODE (var_type) == TYPE_DECL
3019       || TREE_CODE (var_type) == POINTER_TYPE)
3020     var_type = TREE_TYPE (var_type);
3021   catch_id = (var_type == TREE_TYPE (id_type));
3022
3023   if (!flag_objc_exceptions)
3024     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3025
3026   if (!(catch_id || TYPED_OBJECT (var_type)))
3027     fatal_error ("`@catch' parameter is not a known Objective-C class type");
3028
3029   /* Examine previous @catch clauses for the current @try block for
3030      superclasses of the 'var_type' class.  */
3031   for (prev_catch = objc_catch_type; TREE_VALUE (prev_catch);
3032        prev_catch = TREE_CHAIN (prev_catch))
3033     {
3034       if (TREE_VALUE (prev_catch) == TREE_TYPE (id_type))
3035         {
3036           warning ("Exception already handled by preceding `@catch(id)'");
3037           break;
3038         }
3039       else if (!catch_id
3040                && objc_comptypes (TREE_VALUE (prev_catch), var_type, 0) == 1)
3041         warning ("Exception of type `%s *' already handled by `@catch (%s *)'",
3042                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (var_type)),
3043                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_VALUE (prev_catch))));
3044     }
3045
3046   objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
3047
3048   objc_exit_block ();
3049   c_finish_then ();
3050
3051   c_expand_start_else ();
3052   catch_count_stack->val++;
3053   if_stmt = c_begin_if_stmt ();
3054   if_nesting_count++;
3055
3056   if (catch_id)
3057     cond = integer_one_node;
3058   else
3059     {
3060       cond = get_class_reference (OBJC_TYPE_NAME (var_type));
3061         
3062       func_params
3063         = tree_cons (NULL_TREE, cond,
3064                      tree_cons (NULL_TREE,
3065                                 TREE_VALUE (objc_caught_exception),
3066                                 NULL_TREE));
3067       assemble_external (objc_exception_match_decl);
3068       cond = build_function_call (objc_exception_match_decl, func_params);
3069     }
3070
3071   c_expand_start_cond (c_common_truthvalue_conversion (cond),
3072                        0, if_stmt);
3073   objc_enter_block ();
3074   objc_declare_variable (RID_REGISTER, var_name,
3075                          build_pointer_type (var_type),
3076                          TREE_VALUE (objc_caught_exception));
3077 }
3078
3079 void
3080 objc_build_catch_epilogue (void)
3081 {
3082   /*     } else {
3083            _rethrowException = _caughtException;
3084            objc_exception_try_exit(&_stackExceptionData);
3085          }
3086        } else {
3087          _rethrowException = objc_exception_extract(&_stackExceptionData);
3088        }
3089      }
3090    } // end TRY-CATCH scope
3091   */
3092
3093   objc_exit_block ();
3094   c_finish_then ();
3095
3096   c_expand_start_else ();
3097   objc_enter_block ();
3098   c_expand_expr_stmt
3099     (build_modify_expr
3100      (TREE_VALUE (objc_rethrow_exception),
3101       NOP_EXPR,
3102       TREE_VALUE (objc_caught_exception)));
3103   objc_build_try_exit_fragment ();      
3104   objc_exit_block ();
3105   while (catch_count_stack->val--)
3106     {
3107       c_finish_else ();         /* close off all the nested ifs ! */
3108       c_expand_end_cond ();
3109       if_nesting_count--;
3110     }
3111   val_stack_pop (&catch_count_stack);
3112   objc_caught_exception = TREE_CHAIN (objc_caught_exception);
3113
3114   objc_build_extract_fragment ();
3115
3116   objc_exit_block ();
3117   c_finish_else ();
3118   c_expand_end_cond ();
3119   if_nesting_count--;
3120   objc_exit_block ();
3121
3122   /* Return to enclosing chain of @catch statements (if any).  */
3123   while (TREE_VALUE (objc_catch_type))
3124     objc_catch_type = TREE_CHAIN (objc_catch_type);
3125   objc_catch_type = TREE_PURPOSE (objc_catch_type);
3126 }
3127
3128 tree
3129 objc_build_finally_prologue (void)
3130 {
3131   /* { // begin FINALLY scope
3132        if (!_rethrowException) {
3133          objc_exception_try_exit(&_stackExceptionData);
3134        }  */
3135
3136   tree blk = objc_enter_block ();
3137
3138   tree if_stmt = c_begin_if_stmt ();
3139   if_nesting_count++;
3140
3141   c_expand_start_cond (c_common_truthvalue_conversion
3142                        (build_unary_op
3143                         (TRUTH_NOT_EXPR,
3144                          TREE_VALUE (objc_rethrow_exception), 0)),
3145                        0, if_stmt);
3146   objc_enter_block ();
3147   objc_build_try_exit_fragment ();
3148   objc_exit_block ();
3149   c_finish_then ();
3150   c_expand_end_cond ();
3151   if_nesting_count--;
3152
3153   return blk;
3154 }
3155
3156 tree
3157 objc_build_finally_epilogue (void)
3158 {
3159   /*    if (_rethrowException) {
3160           objc_exception_throw(_rethrowException);
3161         }
3162       } // end FINALLY scope
3163     } */
3164
3165   tree if_stmt = c_begin_if_stmt ();
3166   if_nesting_count++;
3167
3168   c_expand_start_cond
3169     (c_common_truthvalue_conversion (TREE_VALUE (objc_rethrow_exception)),
3170      0, if_stmt);
3171   objc_enter_block ();
3172   objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
3173   objc_exit_block ();
3174   c_finish_then ();
3175   c_expand_end_cond ();
3176   if_nesting_count--;
3177
3178   objc_exit_block ();
3179   objc_rethrow_exception = TREE_CHAIN (objc_rethrow_exception);
3180   objc_stack_exception_data = TREE_CHAIN (objc_stack_exception_data);
3181
3182   val_stack_pop (&exc_binding_stack);
3183   return objc_exit_block ();
3184 }
3185
3186 tree
3187 objc_build_try_catch_finally_stmt (int has_catch, int has_finally)
3188 {
3189   /* NB: The operative assumption here is that TRY_FINALLY_EXPR will
3190      deal with all exits from 'try_catch_blk' and route them through
3191      'finally_blk'.  */
3192   tree outer_blk = objc_build_finally_epilogue ();
3193   tree prec_stmt = TREE_CHAIN (TREE_CHAIN (COMPOUND_BODY (outer_blk)));
3194   tree try_catch_blk = TREE_CHAIN (prec_stmt), try_catch_expr;
3195   tree finally_blk = TREE_CHAIN (try_catch_blk), finally_expr;
3196   tree succ_stmt = TREE_CHAIN (finally_blk);
3197   tree try_finally_stmt, try_finally_expr;
3198
3199   if (!flag_objc_exceptions)
3200     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3201
3202   /* It is an error to have a @try block without a @catch and/or @finally
3203      (even though sensible code can be generated nonetheless).  */
3204
3205   if (!has_catch && !has_finally)
3206     error ("`@try' without `@catch' or `@finally'");
3207
3208   /* We shall now do something truly disgusting.  We shall remove the
3209      'try_catch_blk' and 'finally_blk' from the 'outer_blk' statement
3210      chain, and replace them with a TRY_FINALLY_EXPR statement!  If
3211      this doesn't work, we will have to learn (from Per/gcj) how to
3212      construct the 'outer_blk' lazily.  */
3213
3214   TREE_CHAIN (try_catch_blk) = TREE_CHAIN (finally_blk) = NULL_TREE;
3215   try_catch_expr = build1 (STMT_EXPR, void_type_node, try_catch_blk);
3216   TREE_SIDE_EFFECTS (try_catch_expr) = 1;
3217   finally_expr = build1 (STMT_EXPR, void_type_node, finally_blk);
3218   TREE_SIDE_EFFECTS (finally_expr) = 1;
3219   try_finally_expr = build (TRY_FINALLY_EXPR, void_type_node, try_catch_expr,
3220                             finally_expr);
3221   TREE_SIDE_EFFECTS (try_finally_expr) = 1;
3222   try_finally_stmt = build_stmt (EXPR_STMT, try_finally_expr);
3223   TREE_CHAIN (prec_stmt) = try_finally_stmt;
3224   TREE_CHAIN (try_finally_stmt) = succ_stmt;
3225         
3226   return outer_blk;  /* the whole enchilada */
3227 }
3228
3229 void
3230 objc_build_synchronized_prologue (tree sync_expr)
3231 {
3232   /* {
3233        id _eval_once = <sync_expr>;
3234        @try {
3235               objc_sync_enter( _eval_once );  */
3236
3237   tree func_params;
3238
3239   if (!flag_objc_exceptions)
3240     fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3241
3242   objc_enter_block ();
3243   objc_eval_once
3244     = tree_cons (NULL_TREE,
3245                  objc_declare_variable (RID_AUTO,
3246                                         get_identifier (UTAG_EVALONCE_VAR),
3247                                         id_type,
3248                                         sync_expr),
3249                  objc_eval_once);
3250   objc_build_try_prologue ();
3251   objc_enter_block ();  
3252   func_params = tree_cons (NULL_TREE,
3253                            TREE_VALUE (objc_eval_once),
3254                            NULL_TREE);
3255
3256   assemble_external (objc_sync_enter_decl);
3257   c_expand_expr_stmt (build_function_call
3258                       (objc_sync_enter_decl, func_params));
3259 }
3260
3261 tree
3262 objc_build_synchronized_epilogue (void)
3263 {
3264   /* }
3265        @finally {
3266          objc_sync_exit( _eval_once );
3267        }
3268      }  */
3269
3270   tree func_params;
3271
3272   objc_exit_block ();   
3273   objc_build_try_epilogue (0);
3274   objc_build_finally_prologue ();
3275   func_params = tree_cons (NULL_TREE, TREE_VALUE (objc_eval_once),
3276                            NULL_TREE);
3277
3278   assemble_external (objc_sync_exit_decl);
3279   c_expand_expr_stmt (build_function_call (objc_sync_exit_decl,
3280                                            func_params));
3281   objc_build_try_catch_finally_stmt (0, 1);
3282
3283   return objc_exit_block ();
3284 }
3285
3286 /* Predefine the following data type:
3287
3288    struct _objc_exception_data
3289    {
3290      int buf[_JBLEN];
3291      void *pointers[4];
3292    }; */
3293
3294 /* The following yuckiness should prevent users from having to #include
3295    <setjmp.h> in their code... */
3296
3297 #ifdef TARGET_POWERPC
3298 /* snarfed from /usr/include/ppc/setjmp.h */
3299 #define _JBLEN (26 + 36 + 129 + 1)
3300 #else
3301 /* snarfed from /usr/include/i386/{setjmp,signal}.h */
3302 #define _JBLEN 18
3303 #endif
3304
3305 static void
3306 build_objc_exception_stuff (void)
3307 {
3308   tree field_decl, field_decl_chain, index, temp_type;
3309
3310   /* Suppress outputting debug symbols, because
3311      dbxout_init hasn't been called yet.  */
3312   enum debug_info_type save_write_symbols = write_symbols;
3313   const struct gcc_debug_hooks *save_hooks = debug_hooks;
3314
3315   write_symbols = NO_DEBUG;
3316   debug_hooks = &do_nothing_debug_hooks;
3317   objc_exception_data_template
3318     = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3319
3320   /* int buf[_JBLEN]; */
3321
3322   index = build_index_type (build_int_2 (_JBLEN - 1, 0));
3323   field_decl = create_builtin_decl (FIELD_DECL,
3324                                     build_array_type (integer_type_node, index),
3325                                     "buf");
3326   field_decl_chain = field_decl;
3327
3328   /* void *pointers[4]; */
3329
3330   index = build_index_type (build_int_2 (4 - 1, 0));
3331   field_decl = create_builtin_decl (FIELD_DECL,
3332                                     build_array_type (ptr_type_node, index),
3333                                     "pointers");
3334   chainon (field_decl_chain, field_decl);
3335
3336   finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3337
3338   /* int _setjmp(...); */
3339   /* If the user includes <setjmp.h>, this shall be superceded by
3340      'int _setjmp(jmp_buf);' */
3341   temp_type = build_function_type (integer_type_node, NULL_TREE);
3342   objc_setjmp_decl
3343     = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3344
3345   /* id objc_exception_extract(struct _objc_exception_data *); */
3346   temp_type
3347     = build_function_type (id_type,
3348                            tree_cons (NULL_TREE,
3349                                       build_pointer_type (objc_exception_data_template),
3350                                       OBJC_VOID_AT_END));
3351   objc_exception_extract_decl
3352     = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3353   /* void objc_exception_try_enter(struct _objc_exception_data *); */
3354   /* void objc_exception_try_exit(struct _objc_exception_data *); */
3355   temp_type
3356     = build_function_type (void_type_node,
3357                            tree_cons (NULL_TREE,
3358                                       build_pointer_type (objc_exception_data_template),
3359                                       OBJC_VOID_AT_END));
3360   objc_exception_try_enter_decl
3361     = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3362   objc_exception_try_exit_decl
3363     = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3364   /* void objc_exception_throw(id) __attribute__((noreturn)); */
3365   /* void objc_sync_enter(id); */
3366   /* void objc_sync_exit(id); */
3367   temp_type = build_function_type (void_type_node,
3368                                    tree_cons (NULL_TREE, id_type,
3369                                               OBJC_VOID_AT_END));
3370   objc_exception_throw_decl
3371     = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3372   DECL_ATTRIBUTES (objc_exception_throw_decl)
3373     = tree_cons (get_identifier ("noreturn"), NULL_TREE, NULL_TREE);
3374   objc_sync_enter_decl
3375     = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3376   objc_sync_exit_decl
3377     = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3378   /* int objc_exception_match(id, id); */
3379   temp_type = build_function_type (integer_type_node,
3380                                    tree_cons (NULL_TREE, id_type,
3381                                               tree_cons (NULL_TREE, id_type,
3382                                                          OBJC_VOID_AT_END)));
3383   objc_exception_match_decl
3384     = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3385         
3386   write_symbols = save_write_symbols;
3387   debug_hooks = save_hooks;
3388 }
3389
3390 /* struct <classname> {
3391      struct objc_class *isa;
3392      ...
3393    };  */
3394
3395 static tree
3396 build_private_template (tree class)
3397 {
3398   tree ivar_context;
3399
3400   if (CLASS_STATIC_TEMPLATE (class))
3401     {
3402       uprivate_record = CLASS_STATIC_TEMPLATE (class);
3403       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3404     }
3405   else
3406     {
3407       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3408       ivar_context = get_class_ivars (class, 0);
3409
3410       finish_struct (uprivate_record, ivar_context, NULL_TREE);
3411
3412       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3413
3414       /* mark this record as class template - for class type checking */
3415       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3416     }
3417
3418   instance_type
3419     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3420                                                       uprivate_record),
3421                                      build1 (INDIRECT_REF, NULL_TREE,
3422                                              NULL_TREE)));
3423
3424   return ivar_context;
3425 }
3426 \f
3427 /* Begin code generation for protocols...  */
3428
3429 /* struct objc_protocol {
3430      char *protocol_name;
3431      struct objc_protocol **protocol_list;
3432      struct objc_method_desc *instance_methods;
3433      struct objc_method_desc *class_methods;
3434    };  */
3435
3436 static tree
3437 build_protocol_template (void)
3438 {
3439   tree decl_specs, field_decl, field_decl_chain;
3440   tree template;
3441
3442   template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
3443
3444   /* struct objc_class *isa; */
3445
3446   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3447                                         get_identifier (UTAG_CLASS)));
3448   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3449   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3450   field_decl_chain = field_decl;
3451
3452   /* char *protocol_name; */
3453
3454   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3455   field_decl
3456     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
3457   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3458   chainon (field_decl_chain, field_decl);
3459
3460   /* struct objc_protocol **protocol_list; */
3461
3462   decl_specs = build_tree_list (NULL_TREE, template);
3463   field_decl
3464     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3465   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3466   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3467   chainon (field_decl_chain, field_decl);
3468
3469   /* struct objc_method_list *instance_methods; */
3470
3471   decl_specs
3472     = build_tree_list (NULL_TREE,
3473                        xref_tag (RECORD_TYPE,
3474                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3475   field_decl
3476     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3477   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3478   chainon (field_decl_chain, field_decl);
3479
3480   /* struct objc_method_list *class_methods; */
3481
3482   decl_specs
3483     = build_tree_list (NULL_TREE,
3484                        xref_tag (RECORD_TYPE,
3485                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3486   field_decl
3487     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3488   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3489   chainon (field_decl_chain, field_decl);
3490
3491   return finish_struct (template, field_decl_chain, NULL_TREE);
3492 }
3493
3494 static tree
3495 build_descriptor_table_initializer (tree type, tree entries)
3496 {
3497   tree initlist = NULL_TREE;
3498
3499   do
3500     {
3501       tree eltlist = NULL_TREE;
3502
3503       eltlist
3504         = tree_cons (NULL_TREE,
3505                      build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3506       eltlist
3507         = tree_cons (NULL_TREE,
3508                      add_objc_string (METHOD_ENCODING (entries),
3509                                       meth_var_types),
3510                      eltlist);
3511
3512       initlist
3513         = tree_cons (NULL_TREE,
3514                      objc_build_constructor (type, nreverse (eltlist)),
3515                      initlist);
3516
3517       entries = TREE_CHAIN (entries);
3518     }
3519   while (entries);
3520
3521   return objc_build_constructor (build_array_type (type, 0),
3522                                  nreverse (initlist));
3523 }
3524
3525 /* struct objc_method_prototype_list {
3526      int count;
3527      struct objc_method_prototype {
3528         SEL name;
3529         char *types;
3530      } list[1];
3531    };  */
3532
3533 static tree
3534 build_method_prototype_list_template (tree list_type, int size)
3535 {
3536   tree objc_ivar_list_record;
3537   tree decl_specs, field_decl, field_decl_chain;
3538
3539   /* Generate an unnamed struct definition.  */
3540
3541   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3542
3543   /* int method_count; */
3544
3545   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3546   field_decl = get_identifier ("method_count");
3547   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3548   field_decl_chain = field_decl;
3549
3550   /* struct objc_method method_list[]; */
3551
3552   decl_specs = build_tree_list (NULL_TREE, list_type);
3553   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3554                          build_int_2 (size, 0));
3555   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3556   chainon (field_decl_chain, field_decl);
3557
3558   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3559
3560   return objc_ivar_list_record;
3561 }
3562
3563 static tree
3564 build_method_prototype_template (void)
3565 {
3566   tree proto_record;
3567   tree decl_specs, field_decl, field_decl_chain;
3568
3569   proto_record
3570     = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
3571
3572   /* struct objc_selector *_cmd; */
3573   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
3574                           get_identifier (TAG_SELECTOR)), NULL_TREE);
3575   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3576   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3577   field_decl_chain = field_decl;
3578
3579   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3580   field_decl
3581     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
3582   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3583   chainon (field_decl_chain, field_decl);
3584
3585   finish_struct (proto_record, field_decl_chain, NULL_TREE);
3586
3587   return proto_record;
3588 }
3589
3590 static tree
3591 objc_method_parm_type (tree type)
3592 {
3593   type = groktypename (TREE_TYPE (type));
3594   if (TREE_CODE (type) == TYPE_DECL)
3595     type = TREE_TYPE (type);
3596   return TYPE_MAIN_VARIANT (type);
3597 }
3598
3599 static int
3600 objc_encoded_type_size (tree type)
3601 {
3602   int sz = int_size_in_bytes (type);
3603
3604   /* Make all integer and enum types at least as large
3605      as an int.  */
3606   if (sz > 0 && (TREE_CODE (type) == INTEGER_TYPE
3607                  || TREE_CODE (type) == BOOLEAN_TYPE
3608                  || TREE_CODE (type) == ENUMERAL_TYPE))
3609     sz = MAX (sz, int_size_in_bytes (integer_type_node));
3610   /* Treat arrays as pointers, since that's how they're
3611      passed in.  */
3612   else if (TREE_CODE (type) == ARRAY_TYPE)
3613     sz = int_size_in_bytes (ptr_type_node);
3614   return sz;
3615 }
3616
3617 static tree
3618 encode_method_prototype (tree method_decl)
3619 {
3620   tree parms;
3621   int parm_offset, i;
3622   char buf[40];
3623   tree result;
3624
3625   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
3626   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
3627
3628   /* Encode return type.  */
3629   encode_type (objc_method_parm_type (method_decl),
3630                obstack_object_size (&util_obstack),
3631                OBJC_ENCODE_INLINE_DEFS);
3632
3633   /* Stack size.  */
3634   /* The first two arguments (self and _cmd) are pointers; account for
3635      their size.  */
3636   i = int_size_in_bytes (ptr_type_node);
3637   parm_offset = 2 * i;
3638   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3639        parms = TREE_CHAIN (parms))
3640     {
3641       tree type = objc_method_parm_type (parms);
3642       int sz = objc_encoded_type_size (type);
3643
3644       /* If a type size is not known, bail out.  */
3645       if (sz < 0)
3646         {
3647           error ("%Jtype '%D' does not have a known size",
3648                  type, type);
3649           /* Pretend that the encoding succeeded; the compilation will
3650              fail nevertheless.  */
3651           goto finish_encoding;
3652         }
3653       parm_offset += sz;
3654     }
3655
3656   sprintf (buf, "%d@0:%d", parm_offset, i);
3657   obstack_grow (&util_obstack, buf, strlen (buf));
3658
3659   /* Argument types.  */
3660   parm_offset = 2 * i;
3661   for (parms = METHOD_SEL_ARGS (method_decl); parms;
3662        parms = TREE_CHAIN (parms))
3663     {
3664       tree type = objc_method_parm_type (parms);
3665
3666       /* Process argument qualifiers for user supplied arguments.  */
3667       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
3668
3669       /* Type.  */
3670       encode_type (type, obstack_object_size (&util_obstack),
3671                    OBJC_ENCODE_INLINE_DEFS);
3672
3673       /* Compute offset.  */
3674       sprintf (buf, "%d", parm_offset);
3675       parm_offset += objc_encoded_type_size (type);
3676
3677       obstack_grow (&util_obstack, buf, strlen (buf));
3678     }
3679
3680   finish_encoding:
3681   obstack_1grow (&util_obstack, '\0');
3682   result = get_identifier (obstack_finish (&util_obstack));
3683   obstack_free (&util_obstack, util_firstobj);
3684   return result;
3685 }
3686
3687 static tree
3688 generate_descriptor_table (tree type, const char *name, int size, tree list,
3689                            tree proto)
3690 {
3691   tree sc_spec, decl_specs, decl, initlist;
3692
3693   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3694   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3695
3696   decl = start_decl (synth_id_with_class_suffix (name, proto),
3697                      decl_specs, 1, NULL_TREE);
3698   DECL_CONTEXT (decl) = NULL_TREE;
3699
3700   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3701   initlist = tree_cons (NULL_TREE, list, initlist);
3702
3703   finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
3704                NULL_TREE);
3705
3706   return decl;
3707 }
3708
3709 static void
3710 generate_method_descriptors (tree protocol)
3711 {
3712   tree initlist, chain, method_list_template;
3713   tree cast, variable_length_type;
3714   int size;
3715
3716   if (!objc_method_prototype_template)
3717     objc_method_prototype_template = build_method_prototype_template ();
3718
3719   cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3720                                 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
3721                           NULL_TREE);
3722   variable_length_type = groktypename (cast);
3723
3724   chain = PROTOCOL_CLS_METHODS (protocol);
3725   if (chain)
3726     {
3727       size = list_length (chain);
3728
3729       method_list_template
3730         = build_method_prototype_list_template (objc_method_prototype_template,
3731                                                 size);
3732
3733       initlist
3734         = build_descriptor_table_initializer (objc_method_prototype_template,
3735                                               chain);
3736
3737       UOBJC_CLASS_METHODS_decl
3738         = generate_descriptor_table (method_list_template,
3739                                      "_OBJC_PROTOCOL_CLASS_METHODS",
3740                                      size, initlist, protocol);
3741       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3742     }
3743   else
3744     UOBJC_CLASS_METHODS_decl = 0;
3745
3746   chain = PROTOCOL_NST_METHODS (protocol);
3747   if (chain)
3748     {
3749       size = list_length (chain);
3750
3751       method_list_template
3752         = build_method_prototype_list_template (objc_method_prototype_template,
3753                                                 size);
3754       initlist
3755         = build_descriptor_table_initializer (objc_method_prototype_template,
3756                                               chain);
3757
3758       UOBJC_INSTANCE_METHODS_decl
3759         = generate_descriptor_table (method_list_template,
3760                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
3761                                      size, initlist, protocol);
3762       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3763     }
3764   else
3765     UOBJC_INSTANCE_METHODS_decl = 0;
3766 }
3767
3768 static void
3769 generate_protocol_references (tree plist)
3770 {
3771   tree lproto;
3772
3773   /* Forward declare protocols referenced.  */
3774   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3775     {
3776       tree proto = TREE_VALUE (lproto);
3777
3778       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3779           && PROTOCOL_NAME (proto))
3780         {
3781           if (! PROTOCOL_FORWARD_DECL (proto))
3782             build_protocol_reference (proto);
3783
3784           if (PROTOCOL_LIST (proto))
3785             generate_protocol_references (PROTOCOL_LIST (proto));
3786         }
3787     }
3788 }
3789
3790 /* For each protocol which was referenced either from a @protocol()
3791    expression, or because a class/category implements it (then a
3792    pointer to the protocol is stored in the struct describing the
3793    class/category), we create a statically allocated instance of the
3794    Protocol class.  The code is written in such a way as to generate
3795    as few Protocol objects as possible; we generate a unique Protocol
3796    instance for each protocol, and we don't generate a Protocol
3797    instance if the protocol is never referenced (either from a
3798    @protocol() or from a class/category implementation).  These
3799    statically allocated objects can be referred to via the static
3800    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3801
3802    The statically allocated Protocol objects that we generate here
3803    need to be fixed up at runtime in order to be used: the 'isa'
3804    pointer of the objects need to be set up to point to the 'Protocol'
3805    class, as known at runtime.
3806
3807    The NeXT runtime fixes up all protocols at program startup time,
3808    before main() is entered.  It uses a low-level trick to look up all
3809    those symbols, then loops on them and fixes them up.
3810
3811    The GNU runtime as well fixes up all protocols before user code
3812    from the module is executed; it requires pointers to those symbols
3813    to be put in the objc_symtab (which is then passed as argument to
3814    the function __objc_exec_class() which the compiler sets up to be
3815    executed automatically when the module is loaded); setup of those
3816    Protocol objects happen in two ways in the GNU runtime: all
3817    Protocol objects referred to by a class or category implementation
3818    are fixed up when the class/category is loaded; all Protocol
3819    objects referred to by a @protocol() expression are added by the
3820    compiler to the list of statically allocated instances to fixup
3821    (the same list holding the statically allocated constant string
3822    objects).  Because, as explained above, the compiler generates as
3823    few Protocol objects as possible, some Protocol object might end up
3824    being referenced multiple times when compiled with the GNU runtime,
3825    and end up being fixed up multiple times at runtime inizialization.
3826    But that doesn't hurt, it's just a little inefficient.  */
3827
3828 static void
3829 generate_protocols (void)
3830 {
3831   tree p, encoding;
3832   tree sc_spec, decl_specs, decl;
3833   tree initlist, protocol_name_expr, refs_decl, refs_expr;
3834   tree cast_type2;
3835
3836   if (! objc_protocol_template)
3837     objc_protocol_template = build_protocol_template ();
3838
3839   /* If a protocol was directly referenced, pull in indirect references.  */
3840   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3841     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3842       generate_protocol_references (PROTOCOL_LIST (p));
3843
3844   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3845     {
3846       tree nst_methods = PROTOCOL_NST_METHODS (p);
3847       tree cls_methods = PROTOCOL_CLS_METHODS (p);
3848
3849       /* If protocol wasn't referenced, don't generate any code.  */
3850       if (! PROTOCOL_FORWARD_DECL (p))
3851         continue;
3852
3853       /* Make sure we link in the Protocol class.  */
3854       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3855
3856       while (nst_methods)
3857         {
3858           if (! METHOD_ENCODING (nst_methods))
3859             {
3860               encoding = encode_method_prototype (nst_methods);
3861               METHOD_ENCODING (nst_methods) = encoding;
3862             }
3863           nst_methods = TREE_CHAIN (nst_methods);
3864         }
3865
3866       while (cls_methods)
3867         {
3868           if (! METHOD_ENCODING (cls_methods))
3869             {
3870               encoding = encode_method_prototype (cls_methods);
3871               METHOD_ENCODING (cls_methods) = encoding;
3872             }
3873
3874           cls_methods = TREE_CHAIN (cls_methods);
3875         }
3876       generate_method_descriptors (p);
3877
3878       if (PROTOCOL_LIST (p))
3879         refs_decl = generate_protocol_list (p);
3880       else
3881         refs_decl = 0;
3882
3883       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3884
3885       sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3886                            NULL_TREE);
3887       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3888
3889       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3890                          decl_specs, 1, NULL_TREE);
3891
3892       DECL_CONTEXT (decl) = NULL_TREE;
3893
3894       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3895
3896       if (refs_decl)
3897         {
3898           cast_type2
3899             = groktypename
3900                 (build_tree_list (build_tree_list (NULL_TREE,
3901                                                    objc_protocol_template),
3902                                   build1 (INDIRECT_REF, NULL_TREE,
3903                                           build1 (INDIRECT_REF, NULL_TREE,
3904                                                   NULL_TREE))));
3905
3906           refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3907           TREE_TYPE (refs_expr) = cast_type2;
3908         }
3909       else
3910         refs_expr = build_int_2 (0, 0);
3911
3912       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3913          by generate_method_descriptors, which is called above.  */
3914       initlist = build_protocol_initializer (TREE_TYPE (decl),
3915                                              protocol_name_expr, refs_expr,
3916                                              UOBJC_INSTANCE_METHODS_decl,
3917                                              UOBJC_CLASS_METHODS_decl);
3918       finish_decl (decl, initlist, NULL_TREE);
3919
3920       /* Mark the decl as used to avoid "defined but not used" warning.  */
3921       TREE_USED (decl) = 1;
3922     }
3923 }
3924
3925 static tree
3926 build_protocol_initializer (tree type, tree protocol_name,
3927                             tree protocol_list, tree instance_methods,
3928                             tree class_methods)
3929 {
3930   tree initlist = NULL_TREE, expr;
3931   tree cast_type;
3932
3933   cast_type = groktypename
3934     (build_tree_list
3935      (build_tree_list (NULL_TREE,
3936                        xref_tag (RECORD_TYPE,
3937                                  get_identifier (UTAG_CLASS))),
3938       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3939
3940   /* Filling the "isa" in with one allows the runtime system to
3941      detect that the version change...should remove before final release.  */
3942
3943   expr = build_int_2 (PROTOCOL_VERSION, 0);
3944   TREE_TYPE (expr) = cast_type;
3945   initlist = tree_cons (NULL_TREE, expr, initlist);
3946   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3947   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3948
3949   if (!instance_methods)
3950     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3951   else
3952     {
3953       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3954       initlist = tree_cons (NULL_TREE, expr, initlist);
3955     }
3956
3957   if (!class_methods)
3958     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3959   else
3960     {
3961       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3962       initlist = tree_cons (NULL_TREE, expr, initlist);
3963     }
3964
3965   return objc_build_constructor (type, nreverse (initlist));
3966 }
3967 \f
3968 /* struct objc_category {
3969      char *category_name;
3970      char *class_name;
3971      struct objc_method_list *instance_methods;
3972      struct objc_method_list *class_methods;
3973      struct objc_protocol_list *protocols;
3974    };   */
3975
3976 static void
3977 build_category_template (void)
3978 {
3979   tree decl_specs, field_decl, field_decl_chain;
3980
3981   objc_category_template = start_struct (RECORD_TYPE,
3982                                          get_identifier (UTAG_CATEGORY));
3983   /* char *category_name; */
3984
3985   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3986   field_decl
3987     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3988   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3989   field_decl_chain = field_decl;
3990
3991   /* char *class_name; */
3992
3993   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3994   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3995   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3996   chainon (field_decl_chain, field_decl);
3997
3998   /* struct objc_method_list *instance_methods; */
3999
4000   decl_specs = build_tree_list (NULL_TREE,
4001                                 xref_tag (RECORD_TYPE,
4002                                           get_identifier (UTAG_METHOD_LIST)));
4003   field_decl
4004     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
4005   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4006   chainon (field_decl_chain, field_decl);
4007
4008   /* struct objc_method_list *class_methods; */
4009
4010   decl_specs = build_tree_list (NULL_TREE,
4011                                 xref_tag (RECORD_TYPE,
4012                                           get_identifier (UTAG_METHOD_LIST)));
4013   field_decl
4014     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
4015   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4016   chainon (field_decl_chain, field_decl);
4017
4018   /* struct objc_protocol **protocol_list; */
4019
4020   decl_specs = build_tree_list (NULL_TREE,
4021                                 xref_tag (RECORD_TYPE,
4022                                           get_identifier (UTAG_PROTOCOL)));
4023   field_decl
4024     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4025   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4026   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4027   chainon (field_decl_chain, field_decl);
4028
4029   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4030 }
4031
4032 /* struct objc_selector {
4033      void *sel_id;
4034      char *sel_type;
4035    }; */
4036
4037 static void
4038 build_selector_template (void)
4039 {
4040
4041   tree decl_specs, field_decl, field_decl_chain;
4042
4043   objc_selector_template
4044     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4045
4046   /* void *sel_id; */
4047
4048   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4049   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4050   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4051   field_decl_chain = field_decl;
4052
4053   /* char *sel_type; */
4054
4055   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4056   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
4057   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4058   chainon (field_decl_chain, field_decl);
4059
4060   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4061 }
4062
4063 /* struct objc_class {
4064      struct objc_class *isa;
4065      struct objc_class *super_class;
4066      char *name;
4067      long version;
4068      long info;
4069      long instance_size;
4070      struct objc_ivar_list *ivars;
4071      struct objc_method_list *methods;
4072      if (flag_next_runtime)
4073        struct objc_cache *cache;
4074      else {
4075        struct sarray *dtable;
4076        struct objc_class *subclass_list;
4077        struct objc_class *sibling_class;
4078      }
4079      struct objc_protocol_list *protocols;
4080      if (flag_next_runtime)
4081        void *sel_id;
4082      void *gc_object_type;
4083    };  */
4084
4085 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4086    the NeXT/Apple runtime; still, the compiler must generate them to
4087    maintain backward binary compatibility (and to allow for future
4088    expansion).  */
4089
4090 static void
4091 build_class_template (void)
4092 {
4093   tree decl_specs, field_decl, field_decl_chain;
4094
4095   objc_class_template
4096     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4097
4098   /* struct objc_class *isa; */
4099
4100   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4101   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
4102   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4103   field_decl_chain = field_decl;
4104
4105   /* struct objc_class *super_class; */
4106
4107   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4108   field_decl
4109     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4110   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4111   chainon (field_decl_chain, field_decl);
4112
4113   /* char *name; */
4114
4115   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4116   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
4117   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4118   chainon (field_decl_chain, field_decl);
4119
4120   /* long version; */
4121
4122   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4123   field_decl = get_identifier ("version");
4124   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4125   chainon (field_decl_chain, field_decl);
4126
4127   /* long info; */
4128
4129   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4130   field_decl = get_identifier ("info");
4131   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4132   chainon (field_decl_chain, field_decl);
4133
4134   /* long instance_size; */
4135
4136   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4137   field_decl = get_identifier ("instance_size");
4138   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4139   chainon (field_decl_chain, field_decl);
4140
4141   /* struct objc_ivar_list *ivars; */
4142
4143   decl_specs = build_tree_list (NULL_TREE,
4144                                 xref_tag (RECORD_TYPE,
4145                                           get_identifier (UTAG_IVAR_LIST)));
4146   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
4147   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4148   chainon (field_decl_chain, field_decl);
4149
4150   /* struct objc_method_list *methods; */
4151
4152   decl_specs = build_tree_list (NULL_TREE,
4153                                 xref_tag (RECORD_TYPE,
4154                                           get_identifier (UTAG_METHOD_LIST)));
4155   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
4156   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4157   chainon (field_decl_chain, field_decl);
4158
4159   if (flag_next_runtime)
4160     {
4161       /* struct objc_cache *cache; */
4162
4163       decl_specs = build_tree_list (NULL_TREE,
4164                                     xref_tag (RECORD_TYPE,
4165                                               get_identifier ("objc_cache")));
4166       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
4167       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4168       chainon (field_decl_chain, field_decl);
4169     }
4170   else
4171     {
4172       /* struct sarray *dtable; */
4173
4174       decl_specs = build_tree_list (NULL_TREE,
4175                                     xref_tag (RECORD_TYPE,
4176                                               get_identifier ("sarray")));
4177       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
4178       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4179       chainon (field_decl_chain, field_decl);
4180
4181       /* struct objc_class *subclass_list; */
4182
4183       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4184       field_decl
4185         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
4186       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4187       chainon (field_decl_chain, field_decl);
4188
4189       /* struct objc_class *sibling_class; */
4190
4191       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4192       field_decl
4193         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
4194       field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4195       chainon (field_decl_chain, field_decl);
4196     }
4197
4198   /* struct objc_protocol **protocol_list; */
4199
4200   decl_specs = build_tree_list (NULL_TREE,
4201                                 xref_tag (RECORD_TYPE,
4202                                           get_identifier (UTAG_PROTOCOL)));
4203   field_decl
4204     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4205   field_decl
4206     = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4207   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4208   chainon (field_decl_chain, field_decl);
4209
4210   if (flag_next_runtime)
4211     {
4212       /* void *sel_id; */
4213
4214       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4215       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4216       field_decl
4217         = grokfield (field_decl, decl_specs, NULL_TREE);
4218       chainon (field_decl_chain, field_decl);
4219     }
4220
4221   /* void *gc_object_type; */
4222
4223   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4224   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
4225   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4226   chainon (field_decl_chain, field_decl);
4227
4228   finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
4229 }
4230
4231 /* Generate appropriate forward declarations for an implementation.  */
4232
4233 static void
4234 synth_forward_declarations (void)
4235 {
4236   tree an_id;
4237
4238   /* static struct objc_class _OBJC_CLASS_<my_name>; */
4239   UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
4240                                                   objc_class_template);
4241
4242   /* static struct objc_class _OBJC_METACLASS_<my_name>; */
4243   UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
4244                                                   objc_class_template);
4245
4246   /* Pre-build the following entities - for speed/convenience.  */
4247
4248   an_id = get_identifier ("super_class");
4249   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
4250   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
4251 }
4252
4253 static void
4254 error_with_ivar (const char *message, tree decl, tree rawdecl)
4255 {
4256   error ("%J%s `%s'", decl,
4257          message, gen_declaration (rawdecl, errbuf));
4258
4259 }
4260
4261 static void
4262 check_ivars (tree inter, tree imp)
4263 {
4264   tree intdecls = CLASS_IVARS (inter);
4265   tree impdecls = CLASS_IVARS (imp);
4266   tree rawintdecls = CLASS_RAW_IVARS (inter);
4267   tree rawimpdecls = CLASS_RAW_IVARS (imp);
4268
4269   while (1)
4270     {
4271       tree t1, t2;
4272
4273 #ifdef OBJCPLUS
4274       if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4275         intdecls = TREE_CHAIN (intdecls);
4276 #endif
4277       if (intdecls == 0 && impdecls == 0)
4278         break;
4279       if (intdecls == 0 || impdecls == 0)
4280         {
4281           error ("inconsistent instance variable specification");
4282           break;
4283         }
4284
4285       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4286
4287       if (!comptypes (t1, t2, false)
4288           || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
4289                                   TREE_VALUE (TREE_VALUE (rawimpdecls))))
4290         {
4291           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4292             {
4293               error_with_ivar ("conflicting instance variable type",
4294                                impdecls, rawimpdecls);
4295               error_with_ivar ("previous declaration of",
4296                                intdecls, rawintdecls);
4297             }
4298           else                  /* both the type and the name don't match */
4299             {
4300               error ("inconsistent instance variable specification");
4301               break;
4302             }
4303         }
4304
4305       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4306         {
4307           error_with_ivar ("conflicting instance variable name",
4308                            impdecls, rawimpdecls);
4309           error_with_ivar ("previous declaration of",
4310                            intdecls, rawintdecls);
4311         }
4312
4313       intdecls = TREE_CHAIN (intdecls);
4314       impdecls = TREE_CHAIN (impdecls);
4315       rawintdecls = TREE_CHAIN (rawintdecls);
4316       rawimpdecls = TREE_CHAIN (rawimpdecls);
4317     }
4318 }
4319
4320 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
4321    This needs to be done just once per compilation.  */
4322
4323 static void
4324 build_super_template (void)
4325 {
4326   tree decl_specs, field_decl, field_decl_chain;
4327
4328   /* Suppress outputting debug symbols, because
4329      dbxout_init hasn't been called yet.  */
4330   enum debug_info_type save_write_symbols = write_symbols;
4331   const struct gcc_debug_hooks *save_hooks = debug_hooks;
4332
4333   write_symbols = NO_DEBUG;
4334   debug_hooks = &do_nothing_debug_hooks;
4335
4336   objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
4337
4338   /* struct objc_object *self; */
4339
4340   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
4341   field_decl = get_identifier ("self");
4342   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4343   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4344   field_decl_chain = field_decl;
4345
4346   /* struct objc_class *class; */
4347
4348   decl_specs = get_identifier (UTAG_CLASS);
4349   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
4350   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
4351
4352   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4353   chainon (field_decl_chain, field_decl);
4354
4355   finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
4356
4357   write_symbols = save_write_symbols;
4358   debug_hooks = save_hooks;
4359 }
4360
4361 /* struct objc_ivar {
4362      char *ivar_name;
4363      char *ivar_type;
4364      int ivar_offset;
4365    };  */
4366
4367 static tree
4368 build_ivar_template (void)
4369 {
4370   tree objc_ivar_id, objc_ivar_record;
4371   tree decl_specs, field_decl, field_decl_chain;
4372
4373   objc_ivar_id = get_identifier (UTAG_IVAR);
4374   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
4375
4376   /* char *ivar_name; */
4377
4378   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4379   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
4380
4381   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4382   field_decl_chain = field_decl;
4383
4384   /* char *ivar_type; */
4385
4386   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4387   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
4388
4389   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4390   chainon (field_decl_chain, field_decl);
4391
4392   /* int ivar_offset; */
4393
4394   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4395   field_decl = get_identifier ("ivar_offset");
4396
4397   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4398   chainon (field_decl_chain, field_decl);
4399
4400   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
4401
4402   return objc_ivar_record;
4403 }
4404
4405 /* struct {
4406      int ivar_count;
4407      struct objc_ivar ivar_list[ivar_count];
4408    };  */
4409
4410 static tree
4411 build_ivar_list_template (tree list_type, int size)
4412 {
4413   tree objc_ivar_list_record;
4414   tree decl_specs, field_decl, field_decl_chain;
4415
4416   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4417
4418   /* int ivar_count; */
4419
4420   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4421   field_decl = get_identifier ("ivar_count");
4422
4423   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4424   field_decl_chain = field_decl;
4425
4426   /* struct objc_ivar ivar_list[]; */
4427
4428   decl_specs = build_tree_list (NULL_TREE, list_type);
4429   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
4430                          build_int_2 (size, 0));
4431
4432   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4433   chainon (field_decl_chain, field_decl);
4434
4435   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4436
4437   return objc_ivar_list_record;
4438 }
4439
4440 /* struct {
4441      int method_next;
4442      int method_count;
4443      struct objc_method method_list[method_count];
4444    };  */
4445
4446 static tree
4447 build_method_list_template (tree list_type, int size)
4448 {
4449   tree objc_ivar_list_record;
4450   tree decl_specs, field_decl, field_decl_chain;
4451
4452   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4453
4454   /* int method_next; */
4455
4456   decl_specs
4457     = build_tree_list
4458       (NULL_TREE,
4459        xref_tag (RECORD_TYPE,
4460                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
4461   field_decl
4462     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
4463   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4464   field_decl_chain = field_decl;
4465
4466   /* int method_count; */
4467
4468   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4469   field_decl = get_identifier ("method_count");
4470
4471   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4472   chainon (field_decl_chain, field_decl);
4473
4474   /* struct objc_method method_list[]; */
4475
4476   decl_specs = build_tree_list (NULL_TREE, list_type);
4477   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
4478                          build_int_2 (size, 0));
4479
4480   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4481   chainon (field_decl_chain, field_decl);
4482
4483   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4484
4485   return objc_ivar_list_record;
4486 }
4487
4488 static tree
4489 build_ivar_list_initializer (tree type, tree field_decl)
4490 {
4491   tree initlist = NULL_TREE;
4492
4493   do
4494     {
4495       tree ivar = NULL_TREE;
4496
4497       /* Set name.  */
4498       if (DECL_NAME (field_decl))
4499         ivar = tree_cons (NULL_TREE,
4500                           add_objc_string (DECL_NAME (field_decl),
4501                                            meth_var_names),
4502                           ivar);
4503       else
4504         /* Unnamed bit-field ivar (yuck).  */
4505         ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
4506
4507       /* Set type.  */
4508       encode_field_decl (field_decl,
4509                          obstack_object_size (&util_obstack),
4510                          OBJC_ENCODE_DONT_INLINE_DEFS);
4511
4512       /* Null terminate string.  */
4513       obstack_1grow (&util_obstack, 0);
4514       ivar
4515         = tree_cons
4516           (NULL_TREE,
4517            add_objc_string (get_identifier (obstack_finish (&util_obstack)),
4518                             meth_var_types),
4519            ivar);
4520       obstack_free (&util_obstack, util_firstobj);
4521
4522       /* Set offset.  */
4523       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
4524       initlist = tree_cons (NULL_TREE,
4525                             objc_build_constructor (type, nreverse (ivar)),
4526                             initlist);
4527       do
4528         field_decl = TREE_CHAIN (field_decl);
4529       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
4530     }
4531   while (field_decl);
4532
4533   return objc_build_constructor (build_array_type (type, 0),
4534                                  nreverse (initlist));
4535 }
4536
4537 static tree
4538 generate_ivars_list (tree type, const char *name, int size, tree list)
4539 {
4540   tree sc_spec, decl_specs, decl, initlist;
4541
4542   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4543   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4544
4545   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4546                      decl_specs, 1, NULL_TREE);
4547
4548   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
4549   initlist = tree_cons (NULL_TREE, list, initlist);
4550
4551   finish_decl (decl,
4552                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4553                NULL_TREE);
4554
4555   return decl;
4556 }
4557
4558 /* Count only the fields occurring in T.  */
4559 static int
4560 ivar_list_length (tree t)
4561 {
4562   int count = 0;
4563
4564   for (; t; t = TREE_CHAIN (t))
4565     if (TREE_CODE (t) == FIELD_DECL)
4566       ++count;
4567
4568   return count;
4569 }
4570
4571 static void
4572 generate_ivar_lists (void)
4573 {
4574   tree initlist, ivar_list_template, chain;
4575   tree cast, variable_length_type;
4576   int size;
4577
4578   generating_instance_variables = 1;
4579
4580   if (!objc_ivar_template)
4581     objc_ivar_template = build_ivar_template ();
4582
4583   cast
4584     = build_tree_list
4585       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
4586                                          get_identifier (UTAG_IVAR_LIST))),
4587        NULL_TREE);
4588   variable_length_type = groktypename (cast);
4589
4590   /* Only generate class variables for the root of the inheritance
4591      hierarchy since these will be the same for every class.  */
4592
4593   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
4594       && (chain = TYPE_FIELDS (objc_class_template)))
4595     {
4596       size = ivar_list_length (chain);
4597
4598       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4599       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4600
4601       UOBJC_CLASS_VARIABLES_decl
4602         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
4603                                size, initlist);
4604       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
4605     }
4606   else
4607     UOBJC_CLASS_VARIABLES_decl = 0;
4608
4609   chain = CLASS_IVARS (implementation_template);
4610   if (chain)
4611     {
4612       size = ivar_list_length (chain);
4613       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4614       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4615
4616       UOBJC_INSTANCE_VARIABLES_decl
4617         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
4618                                size, initlist);
4619       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
4620     }
4621   else
4622     UOBJC_INSTANCE_VARIABLES_decl = 0;
4623
4624   generating_instance_variables = 0;
4625 }
4626
4627 static tree
4628 build_dispatch_table_initializer (tree type, tree entries)
4629 {
4630   tree initlist = NULL_TREE;
4631
4632   do
4633     {
4634       tree elemlist = NULL_TREE;
4635
4636       elemlist = tree_cons (NULL_TREE,
4637                             build_selector (METHOD_SEL_NAME (entries)),
4638                             NULL_TREE);
4639
4640       /* Generate the method encoding if we don't have one already.  */
4641       if (! METHOD_ENCODING (entries))
4642         METHOD_ENCODING (entries) =
4643           encode_method_prototype (entries);
4644
4645       elemlist = tree_cons (NULL_TREE,
4646                             add_objc_string (METHOD_ENCODING (entries),
4647                                              meth_var_types),
4648                             elemlist);
4649
4650       elemlist = tree_cons (NULL_TREE,
4651                             build_unary_op (ADDR_EXPR,
4652                                             METHOD_DEFINITION (entries), 1),
4653                             elemlist);
4654
4655       initlist = tree_cons (NULL_TREE,
4656                             objc_build_constructor (type, nreverse (elemlist)),
4657                             initlist);
4658
4659       entries = TREE_CHAIN (entries);
4660     }
4661   while (entries);
4662
4663   return objc_build_constructor (build_array_type (type, 0),
4664                                  nreverse (initlist));
4665 }
4666
4667 /* To accomplish method prototyping without generating all kinds of
4668    inane warnings, the definition of the dispatch table entries were
4669    changed from:
4670
4671         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4672    to:
4673         struct objc_method { SEL _cmd; ...; void *_imp; };  */
4674
4675 static tree
4676 build_method_template (void)
4677 {
4678   tree _SLT_record;
4679   tree decl_specs, field_decl, field_decl_chain;
4680
4681   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4682
4683   /* struct objc_selector *_cmd; */
4684   decl_specs = tree_cons (NULL_TREE,
4685                           xref_tag (RECORD_TYPE,
4686                                     get_identifier (TAG_SELECTOR)),
4687                           NULL_TREE);
4688   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4689
4690   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4691   field_decl_chain = field_decl;
4692
4693   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4694   field_decl = build1 (INDIRECT_REF, NULL_TREE,
4695                        get_identifier ("method_types"));
4696   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4697   chainon (field_decl_chain, field_decl);
4698
4699   /* void *_imp; */
4700
4701   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4702   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4703   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4704   chainon (field_decl_chain, field_decl);
4705
4706   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4707
4708   return _SLT_record;
4709 }
4710
4711
4712 static tree
4713 generate_dispatch_table (tree type, const char *name, int size, tree list)
4714 {
4715   tree sc_spec, decl_specs, decl, initlist;
4716
4717   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4718   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4719
4720   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4721                      decl_specs, 1, NULL_TREE);
4722
4723   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4724   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4725   initlist = tree_cons (NULL_TREE, list, initlist);
4726
4727   finish_decl (decl,
4728                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4729                NULL_TREE);
4730
4731   return decl;
4732 }
4733
4734 static void
4735 mark_referenced_methods (void)
4736 {
4737   struct imp_entry *impent;
4738   tree chain;
4739
4740   for (impent = imp_list; impent; impent = impent->next)
4741     {
4742       chain = CLASS_CLS_METHODS (impent->imp_context);
4743       while (chain)
4744         {
4745           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4746           chain = TREE_CHAIN (chain);
4747         }
4748
4749       chain = CLASS_NST_METHODS (impent->imp_context);
4750       while (chain)
4751         {
4752           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4753           chain = TREE_CHAIN (chain);
4754         }
4755     }
4756 }
4757
4758 static void
4759 generate_dispatch_tables (void)
4760 {
4761   tree initlist, chain, method_list_template;
4762   tree cast, variable_length_type;
4763   int size;
4764
4765   if (!objc_method_template)
4766     objc_method_template = build_method_template ();
4767
4768   cast
4769     = build_tree_list
4770       (build_tree_list (NULL_TREE,
4771                         xref_tag (RECORD_TYPE,
4772                                   get_identifier (UTAG_METHOD_LIST))),
4773        NULL_TREE);
4774
4775   variable_length_type = groktypename (cast);
4776
4777   chain = CLASS_CLS_METHODS (objc_implementation_context);
4778   if (chain)
4779     {
4780       size = list_length (chain);
4781
4782       method_list_template
4783         = build_method_list_template (objc_method_template, size);
4784       initlist
4785         = build_dispatch_table_initializer (objc_method_template, chain);
4786
4787       UOBJC_CLASS_METHODS_decl
4788         = generate_dispatch_table (method_list_template,
4789                                    ((TREE_CODE (objc_implementation_context)
4790                                      == CLASS_IMPLEMENTATION_TYPE)
4791                                     ? "_OBJC_CLASS_METHODS"
4792                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
4793                                    size, initlist);
4794       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4795     }
4796   else
4797     UOBJC_CLASS_METHODS_decl = 0;
4798
4799   chain = CLASS_NST_METHODS (objc_implementation_context);
4800   if (chain)
4801     {
4802       size = list_length (chain);
4803
4804       method_list_template
4805         = build_method_list_template (objc_method_template, size);
4806       initlist
4807         = build_dispatch_table_initializer (objc_method_template, chain);
4808
4809       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4810         UOBJC_INSTANCE_METHODS_decl
4811           = generate_dispatch_table (method_list_template,
4812                                      "_OBJC_INSTANCE_METHODS",
4813                                      size, initlist);
4814       else
4815         /* We have a category.  */
4816         UOBJC_INSTANCE_METHODS_decl
4817           = generate_dispatch_table (method_list_template,
4818                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
4819                                      size, initlist);
4820       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4821     }
4822   else
4823     UOBJC_INSTANCE_METHODS_decl = 0;
4824 }
4825
4826 static tree
4827 generate_protocol_list (tree i_or_p)
4828 {
4829   tree initlist, decl_specs, sc_spec;
4830   tree refs_decl, expr_decl, lproto, e, plist;
4831   tree cast_type;
4832   int size = 0;
4833
4834   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4835       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4836     plist = CLASS_PROTOCOL_LIST (i_or_p);
4837   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4838     plist = PROTOCOL_LIST (i_or_p);
4839   else
4840     abort ();
4841
4842   cast_type = groktypename
4843     (build_tree_list
4844      (build_tree_list (NULL_TREE,
4845                        xref_tag (RECORD_TYPE,
4846                                  get_identifier (UTAG_PROTOCOL))),
4847       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4848
4849   /* Compute size.  */
4850   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4851     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4852         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4853       size++;
4854
4855   /* Build initializer.  */
4856   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4857
4858   e = build_int_2 (size, 0);
4859   TREE_TYPE (e) = cast_type;
4860   initlist = tree_cons (NULL_TREE, e, initlist);
4861
4862   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4863     {
4864       tree pval = TREE_VALUE (lproto);
4865
4866       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4867           && PROTOCOL_FORWARD_DECL (pval))
4868         {
4869           e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4870           initlist = tree_cons (NULL_TREE, e, initlist);
4871         }
4872     }
4873
4874   /* static struct objc_protocol *refs[n]; */
4875
4876   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4877   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4878                                            get_identifier (UTAG_PROTOCOL)),
4879                           sc_spec);
4880
4881   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4882     expr_decl = build_nt (ARRAY_REF,
4883                           synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4884                                                       i_or_p),
4885                           build_int_2 (size + 2, 0));
4886   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4887     expr_decl = build_nt (ARRAY_REF,
4888                           synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4889                                                       i_or_p),
4890                           build_int_2 (size + 2, 0));
4891   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4892     expr_decl
4893       = build_nt (ARRAY_REF,
4894                   synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4895                                               i_or_p),
4896                   build_int_2 (size + 2, 0));
4897   else
4898     abort ();
4899
4900   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4901
4902   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4903   DECL_CONTEXT (refs_decl) = NULL_TREE;
4904
4905   finish_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4906                                                   nreverse (initlist)),
4907                NULL_TREE);
4908
4909   return refs_decl;
4910 }
4911
4912 static tree
4913 build_category_initializer (tree type, tree cat_name, tree class_name,
4914                             tree instance_methods, tree class_methods,
4915                             tree protocol_list)
4916 {
4917   tree initlist = NULL_TREE, expr;
4918
4919   initlist = tree_cons (NULL_TREE, cat_name, initlist);
4920   initlist = tree_cons (NULL_TREE, class_name, initlist);
4921
4922   if (!instance_methods)
4923     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4924   else
4925     {
4926       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4927       initlist = tree_cons (NULL_TREE, expr, initlist);
4928     }
4929   if (!class_methods)
4930     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4931   else
4932     {
4933       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4934       initlist = tree_cons (NULL_TREE, expr, initlist);
4935     }
4936
4937   /* protocol_list = */
4938   if (!protocol_list)
4939      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4940   else
4941      {
4942        tree cast_type2 = groktypename
4943          (build_tree_list
4944           (build_tree_list (NULL_TREE,
4945                             xref_tag (RECORD_TYPE,
4946                                       get_identifier (UTAG_PROTOCOL))),
4947            build1 (INDIRECT_REF, NULL_TREE,
4948                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4949
4950         expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4951         TREE_TYPE (expr) = cast_type2;
4952         initlist = tree_cons (NULL_TREE, expr, initlist);
4953      }
4954
4955   return objc_build_constructor (type, nreverse (initlist));
4956 }
4957
4958 /* struct objc_class {
4959      struct objc_class *isa;
4960      struct objc_class *super_class;
4961      char *name;
4962      long version;
4963      long info;
4964      long instance_size;
4965      struct objc_ivar_list *ivars;
4966      struct objc_method_list *methods;
4967      if (flag_next_runtime)
4968        struct objc_cache *cache;
4969      else {
4970        struct sarray *dtable;
4971        struct objc_class *subclass_list;
4972        struct objc_class *sibling_class;
4973      }
4974      struct objc_protocol_list *protocols;
4975      if (flag_next_runtime)
4976        void *sel_id;
4977      void *gc_object_type;
4978    };  */
4979
4980 static tree
4981 build_shared_structure_initializer (tree type, tree isa, tree super,
4982                                     tree name, tree size, int status,
4983                                     tree dispatch_table, tree ivar_list,
4984                                     tree protocol_list)
4985 {
4986   tree initlist = NULL_TREE, expr;
4987
4988   /* isa = */
4989   initlist = tree_cons (NULL_TREE, isa, initlist);
4990
4991   /* super_class = */
4992   initlist = tree_cons (NULL_TREE, super, initlist);
4993
4994   /* name = */
4995   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4996
4997   /* version = */
4998   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4999
5000   /* info = */
5001   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
5002
5003   /* instance_size = */
5004   initlist = tree_cons (NULL_TREE, size, initlist);
5005
5006   /* objc_ivar_list = */
5007   if (!ivar_list)
5008     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5009   else
5010     {
5011       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
5012       initlist = tree_cons (NULL_TREE, expr, initlist);
5013     }
5014
5015   /* objc_method_list = */
5016   if (!dispatch_table)
5017     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5018   else
5019     {
5020       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
5021       initlist = tree_cons (NULL_TREE, expr, initlist);
5022     }
5023
5024   if (flag_next_runtime)
5025     /* method_cache = */
5026     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5027   else
5028     {
5029       /* dtable = */
5030       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5031
5032       /* subclass_list = */
5033       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5034
5035       /* sibling_class = */
5036       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5037     }
5038
5039   /* protocol_list = */
5040   if (! protocol_list)
5041     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5042   else
5043      {
5044        tree cast_type2
5045          = groktypename
5046          (build_tree_list
5047           (build_tree_list (NULL_TREE,
5048                             xref_tag (RECORD_TYPE,
5049                                       get_identifier (UTAG_PROTOCOL))),
5050            build1 (INDIRECT_REF, NULL_TREE,
5051                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
5052
5053      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
5054      TREE_TYPE (expr) = cast_type2;
5055      initlist = tree_cons (NULL_TREE, expr, initlist);
5056      }
5057
5058   if (flag_next_runtime)
5059     /* sel_id = NULL */
5060     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5061
5062   /* gc_object_type = NULL */
5063   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5064
5065   return objc_build_constructor (type, nreverse (initlist));
5066 }
5067
5068 /* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
5069
5070 static inline tree
5071 lookup_category (tree class, tree cat_name)
5072 {
5073   tree category = CLASS_CATEGORY_LIST (class);
5074
5075   while (category && CLASS_SUPER_NAME (category) != cat_name)
5076     category = CLASS_CATEGORY_LIST (category);
5077   return category;
5078 }
5079
5080 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
5081
5082 static void
5083 generate_category (tree cat)
5084 {
5085   tree sc_spec, decl_specs, decl;
5086   tree initlist, cat_name_expr, class_name_expr;
5087   tree protocol_decl, category;
5088
5089   add_class_reference (CLASS_NAME (cat));
5090   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5091
5092   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5093
5094   category = lookup_category (implementation_template,
5095                                 CLASS_SUPER_NAME (cat));
5096
5097   if (category && CLASS_PROTOCOL_LIST (category))
5098     {
5099       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5100       protocol_decl = generate_protocol_list (category);
5101     }
5102   else
5103     protocol_decl = 0;
5104
5105   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
5106   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
5107
5108   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
5109                                                  objc_implementation_context),
5110                      decl_specs, 1, NULL_TREE);
5111
5112   initlist = build_category_initializer (TREE_TYPE (decl),
5113                                          cat_name_expr, class_name_expr,
5114                                          UOBJC_INSTANCE_METHODS_decl,
5115                                          UOBJC_CLASS_METHODS_decl,
5116                                          protocol_decl);
5117
5118   finish_decl (decl, initlist, NULL_TREE);
5119 }
5120
5121 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5122    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
5123
5124 static void
5125 generate_shared_structures (void)
5126 {
5127   tree sc_spec, decl_specs, decl;
5128   tree name_expr, super_expr, root_expr;
5129   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5130   tree cast_type, initlist, protocol_decl;
5131
5132   my_super_id = CLASS_SUPER_NAME (implementation_template);
5133   if (my_super_id)
5134     {
5135       add_class_reference (my_super_id);
5136
5137       /* Compute "my_root_id" - this is required for code generation.
5138          the "isa" for all meta class structures points to the root of
5139          the inheritance hierarchy (e.g. "__Object")...  */
5140       my_root_id = my_super_id;
5141       do
5142         {
5143           tree my_root_int = lookup_interface (my_root_id);
5144
5145           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5146             my_root_id = CLASS_SUPER_NAME (my_root_int);
5147           else
5148             break;
5149         }
5150       while (1);
5151     }
5152   else
5153     /* No super class.  */
5154     my_root_id = CLASS_NAME (implementation_template);
5155
5156   cast_type
5157     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5158                                                       objc_class_template),
5159                                      build1 (INDIRECT_REF,
5160                                              NULL_TREE, NULL_TREE)));
5161
5162   name_expr = add_objc_string (CLASS_NAME (implementation_template),
5163                                class_names);
5164
5165   /* Install class `isa' and `super' pointers at runtime.  */
5166   if (my_super_id)
5167     {
5168       super_expr = add_objc_string (my_super_id, class_names);
5169       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5170     }
5171   else
5172     super_expr = build_int_2 (0, 0);
5173
5174   root_expr = add_objc_string (my_root_id, class_names);
5175   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5176
5177   if (CLASS_PROTOCOL_LIST (implementation_template))
5178     {
5179       generate_protocol_references
5180         (CLASS_PROTOCOL_LIST (implementation_template));
5181       protocol_decl = generate_protocol_list (implementation_template);
5182     }
5183   else
5184     protocol_decl = 0;
5185
5186   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5187
5188   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5189   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5190
5191   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
5192                      NULL_TREE);
5193
5194   initlist
5195     = build_shared_structure_initializer
5196       (TREE_TYPE (decl),
5197        root_expr, super_expr, name_expr,
5198        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5199        2 /*CLS_META*/,
5200        UOBJC_CLASS_METHODS_decl,
5201        UOBJC_CLASS_VARIABLES_decl,
5202        protocol_decl);
5203
5204   finish_decl (decl, initlist, NULL_TREE);
5205
5206   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5207
5208   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
5209                      NULL_TREE);
5210
5211   initlist
5212     = build_shared_structure_initializer
5213       (TREE_TYPE (decl),
5214        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5215        super_expr, name_expr,
5216        convert (integer_type_node,
5217                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5218                                 (implementation_template))),
5219        1 /*CLS_FACTORY*/,
5220        UOBJC_INSTANCE_METHODS_decl,
5221        UOBJC_INSTANCE_VARIABLES_decl,
5222        protocol_decl);
5223
5224   finish_decl (decl, initlist, NULL_TREE);
5225 }
5226
5227 static tree
5228 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5229 {
5230   char *string;
5231   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5232       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5233     {
5234       const char *const class_name
5235         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5236       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
5237       sprintf (string, "%s_%s", preamble,
5238                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5239     }
5240   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5241            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5242     {
5243       /* We have a category.  */
5244       const char *const class_name
5245         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5246       const char *const class_super_name
5247         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5248       string = (char *) alloca (strlen (preamble)
5249                                 + strlen (class_name)
5250                                 + strlen (class_super_name)
5251                                 + 3);
5252       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5253     }
5254   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5255     {
5256       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5257       string
5258         = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
5259       sprintf (string, "%s_%s", preamble, protocol_name);
5260     }
5261   else
5262     abort ();
5263
5264   return get_identifier (string);
5265 }
5266
5267 static int
5268 is_objc_type_qualifier (tree node)
5269 {
5270   return (TREE_CODE (node) == IDENTIFIER_NODE
5271           && (node == ridpointers [(int) RID_CONST]
5272               || node == ridpointers [(int) RID_VOLATILE]
5273               || node == ridpointers [(int) RID_IN]
5274               || node == ridpointers [(int) RID_OUT]
5275               || node == ridpointers [(int) RID_INOUT]
5276               || node == ridpointers [(int) RID_BYCOPY]
5277               || node == ridpointers [(int) RID_BYREF]
5278               || node == ridpointers [(int) RID_ONEWAY]));
5279 }
5280
5281 /* If type is empty or only type qualifiers are present, add default
5282    type of id (otherwise grokdeclarator will default to int).  */
5283
5284 static tree
5285 adjust_type_for_id_default (tree type)
5286 {
5287   tree declspecs, chain;
5288
5289   if (!type)
5290     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
5291                             build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5292
5293   declspecs = TREE_PURPOSE (type);
5294
5295   /* Determine if a typespec is present.  */
5296   for (chain = declspecs;
5297        chain;
5298        chain = TREE_CHAIN (chain))
5299     {
5300       if (TYPED_OBJECT (TREE_VALUE (chain))
5301           && !(TREE_VALUE (type)
5302                && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
5303         error ("can not use an object as parameter to a method\n");
5304       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
5305         return type;
5306     }
5307
5308   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
5309                                      declspecs),
5310                           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5311 }
5312
5313 /*   Usage:
5314                 keyworddecl:
5315                         selector ':' '(' typename ')' identifier
5316
5317      Purpose:
5318                 Transform an Objective-C keyword argument into
5319                 the C equivalent parameter declarator.
5320
5321      In:        key_name, an "identifier_node" (optional).
5322                 arg_type, a  "tree_list" (optional).
5323                 arg_name, an "identifier_node".
5324
5325      Note:      It would be really nice to strongly type the preceding
5326                 arguments in the function prototype; however, then I
5327                 could not use the "accessor" macros defined in "tree.h".
5328
5329      Out:       an instance of "keyword_decl".  */
5330
5331 tree
5332 build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5333 {
5334   tree keyword_decl;
5335
5336   /* If no type is specified, default to "id".  */
5337   arg_type = adjust_type_for_id_default (arg_type);
5338
5339   keyword_decl = make_node (KEYWORD_DECL);
5340
5341   TREE_TYPE (keyword_decl) = arg_type;
5342   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5343   KEYWORD_KEY_NAME (keyword_decl) = key_name;
5344
5345   return keyword_decl;
5346 }
5347
5348 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
5349
5350 static tree
5351 build_keyword_selector (tree selector)
5352 {
5353   int len = 0;
5354   tree key_chain, key_name;
5355   char *buf;
5356
5357   /* Scan the selector to see how much space we'll need.  */
5358   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5359     {
5360       if (TREE_CODE (selector) == KEYWORD_DECL)
5361         key_name = KEYWORD_KEY_NAME (key_chain);
5362       else if (TREE_CODE (selector) == TREE_LIST)
5363         key_name = TREE_PURPOSE (key_chain);
5364       else
5365         abort ();
5366
5367       if (key_name)
5368         len += IDENTIFIER_LENGTH (key_name) + 1;
5369       else
5370         /* Just a ':' arg.  */
5371         len++;
5372     }
5373
5374   buf = (char *) alloca (len + 1);
5375   /* Start the buffer out as an empty string.  */
5376   buf[0] = '\0';
5377
5378   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5379     {
5380       if (TREE_CODE (selector) == KEYWORD_DECL)
5381         key_name = KEYWORD_KEY_NAME (key_chain);
5382       else if (TREE_CODE (selector) == TREE_LIST)
5383         {
5384           key_name = TREE_PURPOSE (key_chain);
5385           /* The keyword decl chain will later be used as a function argument
5386              chain.  Unhook the selector itself so as to not confuse other
5387              parts of the compiler.  */
5388           TREE_PURPOSE (key_chain) = NULL_TREE;
5389         }
5390       else
5391         abort ();
5392
5393       if (key_name)
5394         strcat (buf, IDENTIFIER_POINTER (key_name));
5395       strcat (buf, ":");
5396     }
5397
5398   return get_identifier (buf);
5399 }
5400
5401 /* Used for declarations and definitions.  */
5402
5403 tree
5404 build_method_decl (enum tree_code code, tree ret_type, tree selector,
5405                    tree add_args)
5406 {
5407   tree method_decl;
5408
5409   /* If no type is specified, default to "id".  */
5410   ret_type = adjust_type_for_id_default (ret_type);
5411
5412   method_decl = make_node (code);
5413   TREE_TYPE (method_decl) = ret_type;
5414
5415   /* If we have a keyword selector, create an identifier_node that
5416      represents the full selector name (`:' included)...  */
5417   if (TREE_CODE (selector) == KEYWORD_DECL)
5418     {
5419       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5420       METHOD_SEL_ARGS (method_decl) = selector;
5421       METHOD_ADD_ARGS (method_decl) = add_args;
5422     }
5423   else
5424     {
5425       METHOD_SEL_NAME (method_decl) = selector;
5426       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5427       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5428     }
5429
5430   return method_decl;
5431 }
5432
5433 #define METHOD_DEF 0
5434 #define METHOD_REF 1
5435
5436 /* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
5437    an argument list for method METH.  CONTEXT is either METHOD_DEF or
5438    METHOD_REF, saying whether we are trying to define a method or call
5439    one.  SUPERFLAG says this is for a send to super; this makes a
5440    difference for the NeXT calling sequence in which the lookup and
5441    the method call are done together.  If METH is null, user-defined
5442    arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
5443
5444 static tree
5445 get_arg_type_list (tree meth, int context, int superflag)
5446 {
5447   tree arglist, akey;
5448
5449   /* Receiver type.  */
5450   if (flag_next_runtime && superflag)
5451     arglist = build_tree_list (NULL_TREE, super_type);
5452   else if (context == METHOD_DEF)
5453     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
5454   else
5455     arglist = build_tree_list (NULL_TREE, id_type);
5456
5457   /* Selector type - will eventually change to `int'.  */
5458   chainon (arglist, build_tree_list (NULL_TREE, selector_type));
5459
5460   /* No actual method prototype given -- assume that remaining arguments
5461      are `...'.  */
5462   if (!meth)
5463     return arglist;
5464
5465   /* Build a list of argument types.  */
5466   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
5467     {
5468       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
5469       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
5470     }
5471
5472   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
5473     /* We have a `, ...' immediately following the selector,
5474        finalize the arglist...simulate get_parm_info (0).  */
5475     ;
5476   else if (METHOD_ADD_ARGS (meth))
5477     {
5478       /* we have a variable length selector */
5479       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
5480       chainon (arglist, add_arg_list);
5481     }
5482   else
5483     /* finalize the arglist...simulate get_parm_info (1) */
5484     chainon (arglist, OBJC_VOID_AT_END);
5485
5486   return arglist;
5487 }
5488
5489 static tree
5490 check_duplicates (hash hsh, int methods, int is_class)
5491 {
5492   tree meth = NULL_TREE;
5493
5494   if (hsh)
5495     {
5496       meth = hsh->key;
5497
5498       if (hsh->list)
5499         {
5500           /* We have two or more methods with the same name but
5501              different types.  */
5502           attr loop;
5503
5504           warning ("multiple %s named `%c%s' found",
5505                    methods ? "methods" : "selectors",
5506                    (is_class ? '+' : '-'),
5507                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5508
5509           warn_with_method (methods ? "using" : "found",
5510                             ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5511                              ? '-'
5512                              : '+'), 
5513                             meth);
5514           for (loop = hsh->list; loop; loop = loop->next)
5515             warn_with_method ("also found",
5516                               ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
5517                                ? '-' 
5518                                : '+'),
5519                               loop->value);
5520         }
5521     }
5522   return meth;
5523 }
5524
5525 /* If RECEIVER is a class reference, return the identifier node for
5526    the referenced class.  RECEIVER is created by get_class_reference,
5527    so we check the exact form created depending on which runtimes are
5528    used.  */
5529
5530 static tree
5531 receiver_is_class_object (tree receiver, int self, int super)
5532 {
5533   tree chain, exp, arg;
5534
5535   /* The receiver is 'self' or 'super' in the context of a class method.  */
5536   if (objc_method_context
5537       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
5538       && (self || super))
5539     return (super
5540             ? CLASS_SUPER_NAME (implementation_template)
5541             : CLASS_NAME (implementation_template));
5542
5543   if (flag_next_runtime)
5544     {
5545       /* The receiver is a variable created by
5546          build_class_reference_decl.  */
5547       if (TREE_CODE (receiver) == VAR_DECL
5548           && TREE_TYPE (TREE_TYPE (receiver)) == TREE_TYPE (objc_class_type))
5549         /* Look up the identifier.  */
5550         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5551           if (TREE_PURPOSE (chain) == receiver)
5552             return TREE_VALUE (chain);
5553     }
5554
5555   /* The receiver is a function call that returns an id.  Check if
5556      it is a call to objc_getClass, if so, pick up the class name.  */
5557   if (TREE_CODE (receiver) == CALL_EXPR
5558       && (exp = TREE_OPERAND (receiver, 0))
5559       && TREE_CODE (exp) == ADDR_EXPR
5560       && (exp = TREE_OPERAND (exp, 0))
5561       && TREE_CODE (exp) == FUNCTION_DECL
5562       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
5563          prototypes for objc_get_class().  Thankfuly, they seem to share the
5564          same function type.  */
5565       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
5566       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
5567       /* We have a call to objc_get_class/objc_getClass!  */
5568       && (arg = TREE_OPERAND (receiver, 1))
5569       && TREE_CODE (arg) == TREE_LIST
5570       && (arg = TREE_VALUE (arg)))
5571     {
5572       STRIP_NOPS (arg);
5573       if (TREE_CODE (arg) == ADDR_EXPR
5574           && (arg = TREE_OPERAND (arg, 0))
5575           && TREE_CODE (arg) == STRING_CST)
5576         /* Finally, we have the class name.  */
5577         return get_identifier (TREE_STRING_POINTER (arg));
5578     }
5579   return 0;
5580 }
5581 \f
5582 /* If we are currently building a message expr, this holds
5583    the identifier of the selector of the message.  This is
5584    used when printing warnings about argument mismatches.  */
5585
5586 static tree current_objc_message_selector = 0;
5587
5588 tree
5589 objc_message_selector (void)
5590 {
5591   return current_objc_message_selector;
5592 }
5593
5594 /* Construct an expression for sending a message.
5595    MESS has the object to send to in TREE_PURPOSE
5596    and the argument list (including selector) in TREE_VALUE.
5597
5598    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
5599    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
5600
5601 tree
5602 build_message_expr (tree mess)
5603 {
5604   tree receiver = TREE_PURPOSE (mess);
5605   tree sel_name;
5606   tree args = TREE_VALUE (mess);
5607   tree method_params = NULL_TREE;
5608
5609   if (TREE_CODE (receiver) == ERROR_MARK)
5610     return error_mark_node;
5611
5612   /* Obtain the full selector name.  */
5613   if (TREE_CODE (args) == IDENTIFIER_NODE)
5614     /* A unary selector.  */
5615     sel_name = args;
5616   else if (TREE_CODE (args) == TREE_LIST)
5617     sel_name = build_keyword_selector (args);
5618   else
5619     abort ();
5620
5621   /* Build the parameter list to give to the method.  */
5622   if (TREE_CODE (args) == TREE_LIST)
5623     {
5624       tree chain = args, prev = NULL_TREE;
5625
5626       /* We have a keyword selector--check for comma expressions.  */
5627       while (chain)
5628         {
5629           tree element = TREE_VALUE (chain);
5630
5631           /* We have a comma expression, must collapse...  */
5632           if (TREE_CODE (element) == TREE_LIST)
5633             {
5634               if (prev)
5635                 TREE_CHAIN (prev) = element;
5636               else
5637                 args = element;
5638             }
5639           prev = chain;
5640           chain = TREE_CHAIN (chain);
5641         }
5642       method_params = args;
5643     }
5644
5645 #ifdef OBJCPLUS
5646   if (processing_template_decl)
5647     /* Must wait until template instantiation time.  */
5648     return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
5649                          method_params);
5650 #endif
5651
5652   return finish_message_expr (receiver, sel_name, method_params);
5653 }
5654
5655 /* Look up method SEL_NAME that would be suitable for receiver
5656    of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
5657    nonzero), and report on any duplicates.  */
5658
5659 static tree
5660 lookup_method_in_hash_lists (tree sel_name, int is_class)
5661 {
5662   hash method_prototype = NULL;
5663
5664   if (!is_class)
5665     method_prototype = hash_lookup (nst_method_hash_list,
5666                                     sel_name);
5667                                         
5668   if (!method_prototype)
5669     {
5670       method_prototype = hash_lookup (cls_method_hash_list,
5671                                       sel_name);
5672       is_class = 1;
5673     }
5674
5675   return check_duplicates (method_prototype, 1, is_class);
5676 }
5677
5678 /* The 'finish_message_expr' routine is called from within
5679    'build_message_expr' for non-template functions.  In the case of
5680    C++ template functions, it is called from 'build_expr_from_tree'
5681    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
5682
5683 tree
5684 finish_message_expr (tree receiver, tree sel_name, tree method_params)
5685 {
5686   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
5687   tree selector, retval, is_class;
5688   int self, super, have_cast;
5689
5690   /* Extract the receiver of the message, as well as its type
5691      (where the latter may take the form of a cast or be inferred
5692      from the implementation context).  */
5693   rtype = receiver;
5694   while (TREE_CODE (rtype) == COMPOUND_EXPR
5695               || TREE_CODE (rtype) == MODIFY_EXPR
5696               || TREE_CODE (rtype) == NOP_EXPR
5697               || TREE_CODE (rtype) == COMPONENT_REF)
5698     rtype = TREE_OPERAND (rtype, 0);
5699   self = (rtype == self_decl);
5700   super = (rtype == UOBJC_SUPER_decl);
5701   rtype = TREE_TYPE (receiver);
5702   have_cast = (TREE_CODE (receiver) == NOP_EXPR
5703                || (TREE_CODE (receiver) == COMPOUND_EXPR
5704                    && !IS_SUPER (rtype)));
5705
5706   /* If the receiver is a class object, retrieve the corresponding
5707      @interface, if one exists. */
5708   is_class = receiver_is_class_object (receiver, self, super);
5709
5710   /* Now determine the receiver type (if an explicit cast has not been
5711      provided).  */
5712   if (!have_cast)
5713     {
5714       if (is_class)
5715         rtype = lookup_interface (is_class);
5716       /* Handle `self' and `super'.  */
5717       else if (super)
5718         {
5719           if (!CLASS_SUPER_NAME (implementation_template))
5720             {
5721               error ("no super class declared in @interface for `%s'",
5722                      IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5723               return error_mark_node;
5724             }
5725           rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5726         }
5727       else if (self)
5728         rtype = lookup_interface (CLASS_NAME (implementation_template));
5729     }
5730
5731   /* If receiver is of type `id' or `Class' (or if the @interface for a
5732      class is not visible), we shall be satisfied with the existence of
5733      any instance or class method. */
5734   if (!rtype || IS_ID (rtype)
5735         || TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
5736     {
5737       if (!rtype)
5738         rtype = xref_tag (RECORD_TYPE, is_class);
5739       else if (IS_ID (rtype))
5740         {
5741           rprotos = TYPE_PROTOCOL_LIST (rtype);
5742           rtype = NULL_TREE;
5743         }
5744       else
5745         is_class = TYPE_NAME (rtype) = get_identifier ("Class");
5746
5747       if (rprotos)
5748         method_prototype
5749           = lookup_method_in_protocol_list (rprotos, sel_name,
5750                                             is_class != NULL_TREE);
5751       if (!method_prototype && !rprotos)
5752         method_prototype
5753           = lookup_method_in_hash_lists (sel_name,
5754                                          is_class != NULL_TREE);
5755     }
5756   else
5757     {
5758       tree orig_rtype = rtype, saved_rtype;
5759
5760       if (TREE_CODE (rtype) == POINTER_TYPE)
5761         rtype = TREE_TYPE (rtype);
5762       /* Traverse typedef aliases */
5763       while (TREE_CODE (rtype) == RECORD_TYPE && TYPE_NAME (rtype)
5764              && TREE_CODE (TYPE_NAME (rtype)) == TYPE_DECL
5765              && DECL_ORIGINAL_TYPE (TYPE_NAME (rtype)))
5766         rtype = DECL_ORIGINAL_TYPE (TYPE_NAME (rtype));
5767       saved_rtype = rtype;
5768       if (TYPED_OBJECT (rtype))
5769         {
5770           rprotos = TYPE_PROTOCOL_LIST (rtype);
5771           rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
5772         }
5773       /* If we could not find an @interface declaration, we must have
5774          only seen a @class declaration; so, we cannot say anything
5775          more intelligent about which methods the receiver will
5776          understand. */
5777       if (!rtype)
5778         rtype = saved_rtype;
5779       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
5780           || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
5781         {
5782           /* We have a valid ObjC class name.  Look up the method name
5783              in the published @interface for the class (and its
5784              superclasses). */
5785           method_prototype
5786             = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
5787
5788           /* If the method was not found in the @interface, it may still
5789              exist locally as part of the @implementation.  */
5790           if (!method_prototype && objc_implementation_context
5791              && CLASS_NAME (objc_implementation_context)
5792                 == OBJC_TYPE_NAME (rtype))                      
5793             method_prototype
5794               = lookup_method
5795                 ((is_class
5796                   ? CLASS_CLS_METHODS (objc_implementation_context)
5797                   : CLASS_NST_METHODS (objc_implementation_context)),
5798                   sel_name);
5799
5800           /* If we haven't found a candidate method by now, try looking for
5801              it in the protocol list.  */
5802           if (!method_prototype && rprotos)
5803             method_prototype
5804               = lookup_method_in_protocol_list (rprotos, sel_name,
5805                                                 is_class != NULL_TREE);
5806         }
5807       else
5808         {
5809           warning ("invalid receiver type `%s'",
5810                    gen_declaration (orig_rtype, errbuf));
5811           rtype = rprotos = NULL_TREE;
5812         }
5813     }   
5814
5815   if (!method_prototype)
5816     {
5817       static bool warn_missing_methods = false;
5818
5819       if (rtype)
5820         warning ("`%s' may not respond to `%c%s'",
5821                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
5822                  (is_class ? '+' : '-'),
5823                  IDENTIFIER_POINTER (sel_name));
5824       if (rprotos)
5825         warning ("`%c%s' not implemented by protocol(s)",
5826                  (is_class ? '+' : '-'),
5827                  IDENTIFIER_POINTER (sel_name));
5828       if (!warn_missing_methods)
5829         {
5830           warning ("(Messages without a matching method signature");
5831           warning ("will be assumed to return `id' and accept");
5832           warning ("`...' as arguments.)");
5833           warn_missing_methods = true;
5834         }
5835     }
5836
5837   /* Save the selector name for printing error messages.  */
5838   current_objc_message_selector = sel_name;
5839
5840   /* Build the parameters list for looking up the method.
5841      These are the object itself and the selector.  */
5842
5843   if (flag_typed_selectors)
5844     selector = build_typed_selector_reference (sel_name, method_prototype);
5845   else
5846     selector = build_selector_reference (sel_name);
5847
5848   retval = build_objc_method_call (super, method_prototype,
5849                                    receiver,
5850                                    selector, method_params);
5851
5852   current_objc_message_selector = 0;
5853
5854   return retval;
5855 }
5856 \f
5857 /* Build a tree expression to send OBJECT the operation SELECTOR,
5858    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5859    assuming the method has prototype METHOD_PROTOTYPE.
5860    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5861    Use METHOD_PARAMS as list of args to pass to the method.
5862    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
5863
5864 static tree
5865 build_objc_method_call (int super_flag, tree method_prototype,
5866                         tree lookup_object, tree selector,
5867                         tree method_params)
5868 {
5869   tree sender = (super_flag ? umsg_super_decl :
5870                  (!flag_next_runtime || flag_nil_receivers
5871                   ? umsg_decl
5872                   : umsg_nonnil_decl));
5873   tree rcv_p = (super_flag ? super_type : id_type);
5874
5875   /* If a prototype for the method to be called exists, then cast
5876      the sender's return type and arguments to match that of the method.
5877      Otherwise, leave sender as is.  */
5878   tree ret_type
5879     = (method_prototype
5880        ? groktypename (TREE_TYPE (method_prototype))
5881        : id_type);
5882   tree sender_cast
5883     = build_pointer_type
5884       (build_function_type
5885        (ret_type,
5886         get_arg_type_list
5887         (method_prototype, METHOD_REF, super_flag)));
5888
5889   lookup_object = build_c_cast (rcv_p, lookup_object);
5890
5891   if (flag_next_runtime)
5892     {
5893       /* If we are returning a struct in memory, and the address
5894          of that memory location is passed as a hidden first
5895          argument, then change which messenger entry point this
5896          expr will call.  NB: Note that sender_cast remains
5897          unchanged (it already has a struct return type).  */
5898       if (!targetm.calls.struct_value_rtx (0, 0)
5899           && (TREE_CODE (ret_type) == RECORD_TYPE
5900               || TREE_CODE (ret_type) == UNION_TYPE)
5901           && targetm.calls.return_in_memory (ret_type, 0))
5902         sender = (super_flag ? umsg_super_stret_decl :
5903                 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
5904
5905       method_params = tree_cons (NULL_TREE, lookup_object,
5906                                  tree_cons (NULL_TREE, selector,
5907                                             method_params));
5908       TREE_USED (sender) = 1;
5909       assemble_external (sender);
5910       /* We want to cast the sender, not convert it.  */
5911       return build_function_call (build_c_cast (sender_cast, sender),
5912                                   method_params);
5913     }
5914   else
5915     {
5916       /* This is the portable (GNU) way.  */
5917       tree method, object;
5918
5919       /* First, call the lookup function to get a pointer to the method,
5920          then cast the pointer, then call it with the method arguments.
5921          Use SAVE_EXPR to avoid evaluating the receiver twice.  */
5922       lookup_object = save_expr (lookup_object);
5923       object = (super_flag ? self_decl : lookup_object);
5924       TREE_USED (sender) = 1;
5925       assemble_external (sender);
5926       method
5927         = build_function_call (sender,
5928                                tree_cons (NULL_TREE, lookup_object,
5929                                           tree_cons (NULL_TREE, selector,
5930                                                      NULL_TREE)));
5931
5932       /* Pass the object to the method.  */
5933       TREE_USED (method) = 1;
5934       assemble_external (method);
5935       return build_function_call
5936              (build_c_cast (sender_cast, method),
5937               tree_cons (NULL_TREE, object,
5938                          tree_cons (NULL_TREE, selector, method_params)));
5939     }
5940 }
5941 \f
5942 static void
5943 build_protocol_reference (tree p)
5944 {
5945   tree decl, ident, ptype;
5946
5947   /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5948
5949   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5950   ptype
5951     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5952                                                       objc_protocol_template),
5953                                      NULL_TREE));
5954
5955   if (identifier_global_value (ident))
5956     decl = identifier_global_value (ident); /* Set by pushdecl.  */
5957   else
5958     {
5959       decl = build_decl (VAR_DECL, ident, ptype);
5960       DECL_EXTERNAL (decl) = 1;
5961       TREE_PUBLIC (decl) = 0;
5962       TREE_USED (decl) = 1;
5963       DECL_ARTIFICIAL (decl) = 1;
5964
5965       make_decl_rtl (decl, 0);
5966       pushdecl_top_level (decl);
5967    }
5968
5969   PROTOCOL_FORWARD_DECL (p) = decl;
5970 }
5971
5972 /* This function is called by the parser when (and only when) a
5973    @protocol() expression is found, in order to compile it.  */
5974 tree
5975 build_protocol_expr (tree protoname)
5976 {
5977   tree expr;
5978   tree p = lookup_protocol (protoname);
5979
5980   if (!p)
5981     {
5982       error ("cannot find protocol declaration for `%s'",
5983              IDENTIFIER_POINTER (protoname));
5984       return error_mark_node;
5985     }
5986
5987   if (!PROTOCOL_FORWARD_DECL (p))
5988     build_protocol_reference (p);
5989
5990   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5991
5992   TREE_TYPE (expr) = protocol_type;
5993
5994   /* The @protocol() expression is being compiled into a pointer to a
5995      statically allocated instance of the Protocol class.  To become
5996      usable at runtime, the 'isa' pointer of the instance need to be
5997      fixed up at runtime by the runtime library, to point to the
5998      actual 'Protocol' class.  */
5999
6000   /* For the GNU runtime, put the static Protocol instance in the list
6001      of statically allocated instances, so that we make sure that its
6002      'isa' pointer is fixed up at runtime by the GNU runtime library
6003      to point to the Protocol class (at runtime, when loading the
6004      module, the GNU runtime library loops on the statically allocated
6005      instances (as found in the defs field in objc_symtab) and fixups
6006      all the 'isa' pointers of those objects).  */
6007   if (! flag_next_runtime)
6008     {
6009       /* This type is a struct containing the fields of a Protocol
6010         object.  (Cfr. protocol_type instead is the type of a pointer
6011         to such a struct).  */
6012       tree protocol_struct_type = xref_tag
6013        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
6014       tree *chain;
6015
6016       /* Look for the list of Protocol statically allocated instances
6017         to fixup at runtime.  Create a new list to hold Protocol
6018         statically allocated instances, if the list is not found.  At
6019         present there is only another list, holding NSConstantString
6020         static instances to be fixed up at runtime.  */
6021       for (chain = &objc_static_instances;
6022            *chain && TREE_VALUE (*chain) != protocol_struct_type;
6023            chain = &TREE_CHAIN (*chain));
6024       if (!*chain)
6025         {
6026          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6027          add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6028                           class_names);
6029        }
6030
6031       /* Add this statically allocated instance to the Protocol list.  */
6032       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6033                                          PROTOCOL_FORWARD_DECL (p),
6034                                          TREE_PURPOSE (*chain));
6035     }
6036
6037
6038   return expr;
6039 }
6040
6041 /* This function is called by the parser when a @selector() expression
6042    is found, in order to compile it.  It is only called by the parser
6043    and only to compile a @selector().  */
6044 tree
6045 build_selector_expr (tree selnamelist)
6046 {
6047   tree selname;
6048
6049   /* Obtain the full selector name.  */
6050   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6051     /* A unary selector.  */
6052     selname = selnamelist;
6053   else if (TREE_CODE (selnamelist) == TREE_LIST)
6054     selname = build_keyword_selector (selnamelist);
6055   else
6056     abort ();
6057
6058   /* If we are required to check @selector() expressions as they
6059      are found, check that the selector has been declared.  */
6060   if (warn_undeclared_selector)
6061     {
6062       /* Look the selector up in the list of all known class and
6063          instance methods (up to this line) to check that the selector
6064          exists.  */
6065       hash hsh;
6066
6067       /* First try with instance methods.  */
6068       hsh = hash_lookup (nst_method_hash_list, selname);
6069
6070       /* If not found, try with class methods.  */
6071       if (!hsh)
6072         {
6073           hsh = hash_lookup (cls_method_hash_list, selname);
6074         }
6075
6076       /* If still not found, print out a warning.  */
6077       if (!hsh)
6078         {
6079           warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
6080         }
6081     }
6082
6083
6084   if (flag_typed_selectors)
6085     return build_typed_selector_reference (selname, 0);
6086   else
6087     return build_selector_reference (selname);
6088 }
6089
6090 tree
6091 build_encode_expr (tree type)
6092 {
6093   tree result;
6094   const char *string;
6095
6096   encode_type (type, obstack_object_size (&util_obstack),
6097                OBJC_ENCODE_INLINE_DEFS);
6098   obstack_1grow (&util_obstack, 0);    /* null terminate string */
6099   string = obstack_finish (&util_obstack);
6100
6101   /* Synthesize a string that represents the encoded struct/union.  */
6102   result = my_build_string (strlen (string) + 1, string);
6103   obstack_free (&util_obstack, util_firstobj);
6104   return result;
6105 }
6106
6107 tree
6108 build_ivar_reference (tree id)
6109 {
6110   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6111     {
6112       /* Historically, a class method that produced objects (factory
6113          method) would assign `self' to the instance that it
6114          allocated.  This would effectively turn the class method into
6115          an instance method.  Following this assignment, the instance
6116          variables could be accessed.  That practice, while safe,
6117          violates the simple rule that a class method should not refer
6118          to an instance variable.  It's better to catch the cases
6119          where this is done unknowingly than to support the above
6120          paradigm.  */
6121       warning ("instance variable `%s' accessed in class method",
6122                IDENTIFIER_POINTER (id));
6123       TREE_TYPE (self_decl) = instance_type; /* cast */
6124     }
6125
6126   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
6127 }
6128 \f
6129 /* Compute a hash value for a given method SEL_NAME.  */
6130
6131 static size_t
6132 hash_func (tree sel_name)
6133 {
6134   const unsigned char *s
6135     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6136   size_t h = 0;
6137
6138   while (*s)
6139     h = h * 67 + *s++ - 113;
6140   return h;
6141 }
6142
6143 static void
6144 hash_init (void)
6145 {
6146   nst_method_hash_list
6147     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6148   cls_method_hash_list
6149     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6150 }
6151
6152 /* WARNING!!!!  hash_enter is called with a method, and will peek
6153    inside to find its selector!  But hash_lookup is given a selector
6154    directly, and looks for the selector that's inside the found
6155    entry's key (method) for comparison.  */
6156
6157 static void
6158 hash_enter (hash *hashlist, tree method)
6159 {
6160   hash obj;
6161   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6162
6163   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6164   obj->list = 0;
6165   obj->next = hashlist[slot];
6166   obj->key = method;
6167
6168   hashlist[slot] = obj;         /* append to front */
6169 }
6170
6171 static hash
6172 hash_lookup (hash *hashlist, tree sel_name)
6173 {
6174   hash target;
6175
6176   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6177
6178   while (target)
6179     {
6180       if (sel_name == METHOD_SEL_NAME (target->key))
6181         return target;
6182
6183       target = target->next;
6184     }
6185   return 0;
6186 }
6187
6188 static void
6189 hash_add_attr (hash entry, tree value)
6190 {
6191   attr obj;
6192
6193   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6194   obj->next = entry->list;
6195   obj->value = value;
6196
6197   entry->list = obj;            /* append to front */
6198 }
6199 \f
6200 static tree
6201 lookup_method (tree mchain, tree method)
6202 {
6203   tree key;
6204
6205   if (TREE_CODE (method) == IDENTIFIER_NODE)
6206     key = method;
6207   else
6208     key = METHOD_SEL_NAME (method);
6209
6210   while (mchain)
6211     {
6212       if (METHOD_SEL_NAME (mchain) == key)
6213         return mchain;
6214
6215       mchain = TREE_CHAIN (mchain);
6216     }
6217   return NULL_TREE;
6218 }
6219
6220 static tree
6221 lookup_method_static (tree interface, tree ident, int is_class)
6222 {
6223   tree meth = NULL_TREE, root_inter = NULL_TREE;
6224   tree inter = interface;
6225
6226   while (inter)
6227     {
6228       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6229       tree category = inter;
6230
6231       /* First, look up the method in the class itself.  */
6232       if ((meth = lookup_method (chain, ident)))
6233         return meth;
6234
6235       /* Failing that, look for the method in each category of the class.  */
6236       while ((category = CLASS_CATEGORY_LIST (category)))
6237         {
6238           chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6239
6240           /* Check directly in each category.  */
6241           if ((meth = lookup_method (chain, ident)))
6242             return meth;
6243
6244           /* Failing that, check in each category's protocols.  */
6245           if (CLASS_PROTOCOL_LIST (category))
6246             {
6247               if ((meth = (lookup_method_in_protocol_list
6248                            (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6249                 return meth;
6250             }
6251         }
6252
6253       /* If not found in categories, check in protocols of the main class.  */
6254       if (CLASS_PROTOCOL_LIST (inter))
6255         {
6256           if ((meth = (lookup_method_in_protocol_list
6257                        (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6258             return meth;
6259         }
6260
6261       /* Failing that, climb up the inheritance hierarchy.  */
6262       root_inter = inter;
6263       inter = lookup_interface (CLASS_SUPER_NAME (inter));
6264     }
6265   while (inter);
6266
6267   /* If no class (factory) method was found, check if an _instance_
6268      method of the same name exists in the root class.  This is what
6269      the Objective-C runtime will do.  If an instance method was not
6270      found, return 0.  */
6271   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6272 }
6273
6274 /* Add the method to the hash list if it doesn't contain an identical
6275    method already. */
6276 static void
6277 add_method_to_hash_list (hash *hash_list, tree method)
6278 {
6279   hash hsh;
6280
6281   if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6282     {
6283       /* Install on a global chain.  */
6284       hash_enter (hash_list, method);
6285     }
6286   else
6287     {
6288       /* Check types against those; if different, add to a list.  */
6289       attr loop;
6290       int already_there = comp_proto_with_proto (method, hsh->key);
6291       for (loop = hsh->list; !already_there && loop; loop = loop->next)
6292         already_there |= comp_proto_with_proto (method, loop->value);
6293       if (!already_there)
6294         hash_add_attr (hsh, method);
6295     }
6296 }
6297
6298 tree
6299 objc_add_method (tree class, tree method, int is_class)
6300 {
6301   tree mth;
6302
6303   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
6304     {
6305       /* put method on list in reverse order */
6306       if (is_class)
6307         {
6308           TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6309           CLASS_CLS_METHODS (class) = method;
6310         }
6311       else
6312         {
6313           TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6314           CLASS_NST_METHODS (class) = method;
6315         }
6316     }
6317   else
6318     {
6319       /* When processing an @interface for a class or category, give hard
6320          errors on methods with identical selectors but differing argument
6321          and/or return types. We do not do this for @implementations, because
6322          C/C++ will do it for us (i.e., there will be duplicate function
6323          definition errors).  */
6324       if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6325            || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6326           && !comp_proto_with_proto (method, mth))
6327         error ("duplicate declaration of method `%c%s'",
6328                 is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6329     }
6330
6331   if (is_class)
6332     add_method_to_hash_list (cls_method_hash_list, method);
6333   else
6334     {
6335       add_method_to_hash_list (nst_method_hash_list, method);
6336
6337       /* Instance methods in root classes (and categories thereof)
6338          may acts as class methods as a last resort. */
6339       if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6340           || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6341         class = lookup_interface (CLASS_NAME (class));
6342
6343       if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
6344           && !CLASS_SUPER_NAME (class))
6345         add_method_to_hash_list (cls_method_hash_list, method);
6346     }
6347
6348   return method;
6349 }
6350
6351 static tree
6352 add_class (tree class)
6353 {
6354   /* Put interfaces on list in reverse order.  */
6355   TREE_CHAIN (class) = interface_chain;
6356   interface_chain = class;
6357   return interface_chain;
6358 }
6359
6360 static void
6361 add_category (tree class, tree category)
6362 {
6363   /* Put categories on list in reverse order.  */
6364   tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
6365
6366   if (cat)
6367     {
6368       warning ("duplicate interface declaration for category `%s(%s)'",
6369                IDENTIFIER_POINTER (CLASS_NAME (class)),
6370                IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
6371     }
6372   else
6373     {
6374       CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
6375       CLASS_CATEGORY_LIST (class) = category;
6376     }
6377 }
6378
6379 /* Called after parsing each instance variable declaration. Necessary to
6380    preserve typedefs and implement public/private...
6381
6382    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
6383
6384 tree
6385 add_instance_variable (tree class, int public, tree declarator,
6386                        tree declspecs, tree width)
6387 {
6388   tree field_decl = grokfield (declarator, declspecs, width);
6389   tree field_type = TREE_TYPE (field_decl);
6390   const char *ivar_name = DECL_NAME (field_decl)
6391                           ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
6392                           : "<unnamed>";
6393   tree raw_decl;
6394
6395 #ifdef OBJCPLUS
6396   if (TREE_CODE (field_type) == REFERENCE_TYPE)
6397     {
6398       error ("illegal reference type specified for instance variable `%s'",
6399              ivar_name);
6400       /* Return class as is without adding this ivar.  */
6401       return class;
6402     }
6403 #endif
6404
6405   if (field_type == error_mark_node || !TYPE_SIZE (field_type)
6406       || TYPE_SIZE (field_type) == error_mark_node
6407       /* 'type[0]' is allowed, but 'type[]' is not! */
6408 #ifdef OBJCPLUS
6409       || (TYPE_SIZE (field_type) == bitsize_zero_node
6410           && !TREE_OPERAND (declarator, 1))
6411 #endif
6412       )
6413     {
6414       error ("instance variable `%s' has unknown size", ivar_name);
6415       /* Return class as is without adding this ivar.  */
6416       return class;
6417     }
6418
6419 #ifdef OBJCPLUS
6420   /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
6421      cannot be ivars; ditto for classes with vtables. */
6422   if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
6423       || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
6424     {
6425       const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
6426       if(TYPE_POLYMORPHIC_P (field_type)) {
6427         /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
6428         error ("type `%s' has virtual member functions", type_name);
6429         error ("illegal aggregate type `%s' specified for instance variable `%s'",
6430                type_name, ivar_name);
6431         /* Return class as is without adding this ivar.  */
6432         return class;
6433       }
6434       /* user-defined constructors and destructors are not known to Obj-C and
6435          hence will not be called.  This may or may not be a problem. */
6436       if (TYPE_NEEDS_CONSTRUCTING (field_type))
6437         warning ("type `%s' has a user-defined constructor", type_name);
6438       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
6439         warning ("type `%s' has a user-defined destructor", type_name);
6440       warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
6441     }
6442 #endif
6443
6444   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
6445   switch (public)
6446     {
6447     case 0:
6448       TREE_PUBLIC (field_decl) = 0;
6449       TREE_PRIVATE (field_decl) = 0;
6450       TREE_PROTECTED (field_decl) = 1;
6451       break;
6452
6453     case 1:
6454       TREE_PUBLIC (field_decl) = 1;
6455       TREE_PRIVATE (field_decl) = 0;
6456       TREE_PROTECTED (field_decl) = 0;
6457       break;
6458
6459     case 2:
6460       TREE_PUBLIC (field_decl) = 0;
6461       TREE_PRIVATE (field_decl) = 1;
6462       TREE_PROTECTED (field_decl) = 0;
6463       break;
6464
6465     }
6466
6467   raw_decl = build_tree_list (declspecs, build_tree_list (declarator, width));
6468   CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), raw_decl);
6469   CLASS_IVARS (class) = chainon (CLASS_IVARS (class), field_decl);
6470   return class;
6471 }
6472 \f
6473 tree
6474 is_ivar (tree decl_chain, tree ident)
6475 {
6476   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
6477     if (DECL_NAME (decl_chain) == ident)
6478       return decl_chain;
6479   return NULL_TREE;
6480 }
6481
6482 /* True if the ivar is private and we are not in its implementation.  */
6483
6484 int
6485 is_private (tree decl)
6486 {
6487   return (TREE_PRIVATE (decl)
6488           && ! is_ivar (CLASS_IVARS (implementation_template),
6489                         DECL_NAME (decl)));
6490 }
6491
6492 /* We have an instance variable reference;, check to see if it is public.  */
6493
6494 int
6495 is_public (tree expr, tree identifier)
6496 {
6497   tree basetype = TREE_TYPE (expr);
6498   enum tree_code code = TREE_CODE (basetype);
6499   tree decl;
6500
6501   if (code == RECORD_TYPE)
6502     {
6503       if (TREE_STATIC_TEMPLATE (basetype))
6504         {
6505           if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6506             {
6507               error ("cannot find interface declaration for `%s'",
6508                      IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6509               return 0;
6510             }
6511
6512           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6513             {
6514               if (TREE_PUBLIC (decl))
6515                 return 1;
6516
6517               /* Important difference between the Stepstone translator:
6518                  all instance variables should be public within the context
6519                  of the implementation.  */
6520               if (objc_implementation_context
6521                   && (((TREE_CODE (objc_implementation_context)
6522                         == CLASS_IMPLEMENTATION_TYPE)
6523                        || (TREE_CODE (objc_implementation_context)
6524                            == CATEGORY_IMPLEMENTATION_TYPE))
6525                       && (CLASS_NAME (objc_implementation_context)
6526                           == OBJC_TYPE_NAME (basetype))))
6527                 {
6528                   int private = is_private (decl);
6529
6530                   if (private)
6531                     error ("instance variable `%s' is declared private",
6532                            IDENTIFIER_POINTER (DECL_NAME (decl)));
6533                   return !private;
6534                 }
6535
6536               /* The 2.95.2 compiler sometimes allowed C functions to access
6537                  non-@public ivars.  We will let this slide for now...  */
6538               if (!objc_method_context)
6539               {
6540                 warning ("instance variable `%s' is %s; "
6541                          "this will be a hard error in the future",
6542                          IDENTIFIER_POINTER (identifier),
6543                          TREE_PRIVATE (decl) ? "@private" : "@protected");
6544                 return 1;
6545               }
6546                 
6547               error ("instance variable `%s' is declared %s",
6548                      IDENTIFIER_POINTER (identifier),
6549                      TREE_PRIVATE (decl) ? "private" : "protected");
6550               return 0;
6551             }
6552         }
6553
6554       else if (objc_implementation_context && (basetype == objc_object_reference))
6555         {
6556           TREE_TYPE (expr) = uprivate_record;
6557           warning ("static access to object of type `id'");
6558         }
6559     }
6560
6561   return 1;
6562 }
6563 \f
6564 /* Make sure all entries in CHAIN are also in LIST.  */
6565
6566 static int
6567 check_methods (tree chain, tree list, int mtype)
6568 {
6569   int first = 1;
6570
6571   while (chain)
6572     {
6573       if (!lookup_method (list, chain))
6574         {
6575           if (first)
6576             {
6577               if (TREE_CODE (objc_implementation_context)
6578                   == CLASS_IMPLEMENTATION_TYPE)
6579                 warning ("incomplete implementation of class `%s'",
6580                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6581               else if (TREE_CODE (objc_implementation_context)
6582                        == CATEGORY_IMPLEMENTATION_TYPE)
6583                 warning ("incomplete implementation of category `%s'",
6584                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6585               first = 0;
6586             }
6587
6588           warning ("method definition for `%c%s' not found",
6589                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6590         }
6591
6592       chain = TREE_CHAIN (chain);
6593     }
6594
6595     return first;
6596 }
6597
6598 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
6599
6600 static int
6601 conforms_to_protocol (tree class, tree protocol)
6602 {
6603    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6604      {
6605        tree p = CLASS_PROTOCOL_LIST (class);
6606        while (p && TREE_VALUE (p) != protocol)
6607          p = TREE_CHAIN (p);
6608
6609        if (!p)
6610          {
6611            tree super = (CLASS_SUPER_NAME (class)
6612                          ? lookup_interface (CLASS_SUPER_NAME (class))
6613                          : NULL_TREE);
6614            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6615            if (!tmp)
6616              return 0;
6617          }
6618      }
6619
6620    return 1;
6621 }
6622
6623 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6624    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
6625
6626 static int
6627 check_methods_accessible (tree chain, tree context, int mtype)
6628 {
6629   int first = 1;
6630   tree list;
6631   tree base_context = context;
6632
6633   while (chain)
6634     {
6635       context = base_context;
6636       while (context)
6637         {
6638           if (mtype == '+')
6639             list = CLASS_CLS_METHODS (context);
6640           else
6641             list = CLASS_NST_METHODS (context);
6642
6643           if (lookup_method (list, chain))
6644               break;
6645
6646           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6647                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6648             context = (CLASS_SUPER_NAME (context)
6649                        ? lookup_interface (CLASS_SUPER_NAME (context))
6650                        : NULL_TREE);
6651
6652           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6653                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6654             context = (CLASS_NAME (context)
6655                        ? lookup_interface (CLASS_NAME (context))
6656                        : NULL_TREE);
6657           else
6658             abort ();
6659         }
6660
6661       if (context == NULL_TREE)
6662         {
6663           if (first)
6664             {
6665               if (TREE_CODE (objc_implementation_context)
6666                   == CLASS_IMPLEMENTATION_TYPE)
6667                 warning ("incomplete implementation of class `%s'",
6668                          IDENTIFIER_POINTER
6669                            (CLASS_NAME (objc_implementation_context)));
6670               else if (TREE_CODE (objc_implementation_context)
6671                        == CATEGORY_IMPLEMENTATION_TYPE)
6672                 warning ("incomplete implementation of category `%s'",
6673                          IDENTIFIER_POINTER
6674                            (CLASS_SUPER_NAME (objc_implementation_context)));
6675               first = 0;
6676             }
6677           warning ("method definition for `%c%s' not found",
6678                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6679         }
6680
6681       chain = TREE_CHAIN (chain); /* next method...  */
6682     }
6683   return first;
6684 }
6685
6686 /* Check whether the current interface (accessible via
6687    'objc_implementation_context') actually implements protocol P, along
6688    with any protocols that P inherits.  */
6689
6690 static void
6691 check_protocol (tree p, const char *type, const char *name)
6692 {
6693   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6694     {
6695       int f1, f2;
6696
6697       /* Ensure that all protocols have bodies!  */
6698       if (warn_protocol)
6699         {
6700           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6701                               CLASS_CLS_METHODS (objc_implementation_context),
6702                               '+');
6703           f2 = check_methods (PROTOCOL_NST_METHODS (p),
6704                               CLASS_NST_METHODS (objc_implementation_context),
6705                               '-');
6706         }
6707       else
6708         {
6709           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6710                                          objc_implementation_context,
6711                                          '+');
6712           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6713                                          objc_implementation_context,
6714                                          '-');
6715         }
6716
6717       if (!f1 || !f2)
6718         warning ("%s `%s' does not fully implement the `%s' protocol",
6719                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6720     }
6721
6722   /* Check protocols recursively.  */
6723   if (PROTOCOL_LIST (p))
6724     {
6725       tree subs = PROTOCOL_LIST (p);
6726       tree super_class =
6727         lookup_interface (CLASS_SUPER_NAME (implementation_template));
6728
6729       while (subs)
6730         {
6731           tree sub = TREE_VALUE (subs);
6732
6733           /* If the superclass does not conform to the protocols
6734              inherited by P, then we must!  */
6735           if (!super_class || !conforms_to_protocol (super_class, sub))
6736             check_protocol (sub, type, name);
6737           subs = TREE_CHAIN (subs);
6738         }
6739     }
6740 }
6741
6742 /* Check whether the current interface (accessible via
6743    'objc_implementation_context') actually implements the protocols listed
6744    in PROTO_LIST.  */
6745
6746 static void
6747 check_protocols (tree proto_list, const char *type, const char *name)
6748 {
6749   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6750     {
6751       tree p = TREE_VALUE (proto_list);
6752
6753       check_protocol (p, type, name);
6754     }
6755 }
6756 \f
6757 /* Make sure that the class CLASS_NAME is defined
6758    CODE says which kind of thing CLASS_NAME ought to be.
6759    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6760    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
6761
6762 tree
6763 start_class (enum tree_code code, tree class_name, tree super_name,
6764              tree protocol_list)
6765 {
6766   tree class, decl;
6767
6768 #ifdef OBJCPLUS
6769   if (current_namespace != global_namespace) {
6770     error ("Objective-C declarations may only appear in global scope");
6771   }
6772 #endif /* OBJCPLUS */
6773
6774   if (objc_implementation_context)
6775     {
6776       warning ("`@end' missing in implementation context");
6777       finish_class (objc_implementation_context);
6778       objc_ivar_chain = NULL_TREE;
6779       objc_implementation_context = NULL_TREE;
6780     }
6781
6782   class = make_node (code);
6783   TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
6784
6785   CLASS_NAME (class) = class_name;
6786   CLASS_SUPER_NAME (class) = super_name;
6787   CLASS_CLS_METHODS (class) = NULL_TREE;
6788
6789   if (! is_class_name (class_name)
6790       && (decl = lookup_name (class_name)))
6791     {
6792       error ("`%s' redeclared as different kind of symbol",
6793              IDENTIFIER_POINTER (class_name));
6794       error ("%Jprevious declaration of '%D'",
6795              decl, decl);
6796     }
6797
6798   if (code == CLASS_IMPLEMENTATION_TYPE)
6799     {
6800       {
6801         tree chain;
6802
6803         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6804            if (TREE_VALUE (chain) == class_name)
6805              {
6806                error ("reimplementation of class `%s'",
6807                       IDENTIFIER_POINTER (class_name));
6808                return error_mark_node;
6809              }
6810         implemented_classes = tree_cons (NULL_TREE, class_name,
6811                                          implemented_classes);
6812       }
6813
6814       /* Reset for multiple classes per file.  */
6815       method_slot = 0;
6816
6817       objc_implementation_context = class;
6818
6819       /* Lookup the interface for this implementation.  */
6820
6821       if (!(implementation_template = lookup_interface (class_name)))
6822         {
6823           warning ("cannot find interface declaration for `%s'",
6824                    IDENTIFIER_POINTER (class_name));
6825           add_class (implementation_template = objc_implementation_context);
6826         }
6827
6828       /* If a super class has been specified in the implementation,
6829          insure it conforms to the one specified in the interface.  */
6830
6831       if (super_name
6832           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6833         {
6834           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6835           const char *const name =
6836             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6837           error ("conflicting super class name `%s'",
6838                  IDENTIFIER_POINTER (super_name));
6839           error ("previous declaration of `%s'", name);
6840         }
6841
6842       else if (! super_name)
6843         {
6844           CLASS_SUPER_NAME (objc_implementation_context)
6845             = CLASS_SUPER_NAME (implementation_template);
6846         }
6847     }
6848
6849   else if (code == CLASS_INTERFACE_TYPE)
6850     {
6851       if (lookup_interface (class_name))
6852 #ifdef OBJCPLUS
6853         error ("duplicate interface declaration for class `%s'",
6854 #else
6855         warning ("duplicate interface declaration for class `%s'",
6856 #endif  
6857         IDENTIFIER_POINTER (class_name));
6858       else
6859         add_class (class);
6860
6861       if (protocol_list)
6862         CLASS_PROTOCOL_LIST (class)
6863           = lookup_and_install_protocols (protocol_list);
6864     }
6865
6866   else if (code == CATEGORY_INTERFACE_TYPE)
6867     {
6868       tree class_category_is_assoc_with;
6869
6870       /* For a category, class_name is really the name of the class that
6871          the following set of methods will be associated with. We must
6872          find the interface so that can derive the objects template.  */
6873
6874       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6875         {
6876           error ("cannot find interface declaration for `%s'",
6877                  IDENTIFIER_POINTER (class_name));
6878           exit (FATAL_EXIT_CODE);
6879         }
6880       else
6881         add_category (class_category_is_assoc_with, class);
6882
6883       if (protocol_list)
6884         CLASS_PROTOCOL_LIST (class)
6885           = lookup_and_install_protocols (protocol_list);
6886     }
6887
6888   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6889     {
6890       /* Reset for multiple classes per file.  */
6891       method_slot = 0;
6892
6893       objc_implementation_context = class;
6894
6895       /* For a category, class_name is really the name of the class that
6896          the following set of methods will be associated with.  We must
6897          find the interface so that can derive the objects template.  */
6898
6899       if (!(implementation_template = lookup_interface (class_name)))
6900         {
6901           error ("cannot find interface declaration for `%s'",
6902                  IDENTIFIER_POINTER (class_name));
6903           exit (FATAL_EXIT_CODE);
6904         }
6905     }
6906   return class;
6907 }
6908
6909 tree
6910 continue_class (tree class)
6911 {
6912   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6913       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6914     {
6915       struct imp_entry *imp_entry;
6916       tree ivar_context;
6917
6918       /* Check consistency of the instance variables.  */
6919
6920       if (CLASS_IVARS (class))
6921         check_ivars (implementation_template, class);
6922
6923       /* code generation */
6924
6925       ivar_context = build_private_template (implementation_template);
6926
6927       if (!objc_class_template)
6928         build_class_template ();
6929
6930       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6931
6932       imp_entry->next = imp_list;
6933       imp_entry->imp_context = class;
6934       imp_entry->imp_template = implementation_template;
6935
6936       synth_forward_declarations ();
6937       imp_entry->class_decl = UOBJC_CLASS_decl;
6938       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6939
6940       /* Append to front and increment count.  */
6941       imp_list = imp_entry;
6942       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6943         imp_count++;
6944       else
6945         cat_count++;
6946
6947       return ivar_context;
6948     }
6949
6950   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6951     {
6952       if (!CLASS_STATIC_TEMPLATE (class))
6953         {
6954           tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6955           finish_struct (record, get_class_ivars (class, 0), NULL_TREE);
6956           CLASS_STATIC_TEMPLATE (class) = record;
6957
6958           /* Mark this record as a class template for static typing.  */
6959           TREE_STATIC_TEMPLATE (record) = 1;
6960         }
6961
6962       return NULL_TREE;
6963     }
6964
6965   else
6966     return error_mark_node;
6967 }
6968
6969 /* This is called once we see the "@end" in an interface/implementation.  */
6970
6971 void
6972 finish_class (tree class)
6973 {
6974   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6975     {
6976       /* All code generation is done in finish_objc.  */
6977
6978       if (implementation_template != objc_implementation_context)
6979         {
6980           /* Ensure that all method listed in the interface contain bodies.  */
6981           check_methods (CLASS_CLS_METHODS (implementation_template),
6982                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6983           check_methods (CLASS_NST_METHODS (implementation_template),
6984                          CLASS_NST_METHODS (objc_implementation_context), '-');
6985
6986           if (CLASS_PROTOCOL_LIST (implementation_template))
6987             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6988                              "class",
6989                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6990         }
6991     }
6992
6993   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6994     {
6995       tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6996
6997       if (category)
6998         {
6999           /* Ensure all method listed in the interface contain bodies.  */
7000           check_methods (CLASS_CLS_METHODS (category),
7001                          CLASS_CLS_METHODS (objc_implementation_context), '+');
7002           check_methods (CLASS_NST_METHODS (category),
7003                          CLASS_NST_METHODS (objc_implementation_context), '-');
7004
7005           if (CLASS_PROTOCOL_LIST (category))
7006             check_protocols (CLASS_PROTOCOL_LIST (category),
7007                              "category",
7008                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7009         }
7010     }
7011
7012   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
7013     {
7014       tree decl_specs;
7015       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
7016       char *string = (char *) alloca (strlen (class_name) + 3);
7017
7018       /* extern struct objc_object *_<my_name>; */
7019
7020       sprintf (string, "_%s", class_name);
7021
7022       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
7023       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
7024       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
7025                    decl_specs);
7026     }
7027 }
7028
7029 static tree
7030 add_protocol (tree protocol)
7031 {
7032   /* Put protocol on list in reverse order.  */
7033   TREE_CHAIN (protocol) = protocol_chain;
7034   protocol_chain = protocol;
7035   return protocol_chain;
7036 }
7037
7038 static tree
7039 lookup_protocol (tree ident)
7040 {
7041   tree chain;
7042
7043   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7044     if (ident == PROTOCOL_NAME (chain))
7045       return chain;
7046
7047   return NULL_TREE;
7048 }
7049
7050 /* This function forward declares the protocols named by NAMES.  If
7051    they are already declared or defined, the function has no effect.  */
7052
7053 void
7054 objc_declare_protocols (tree names)
7055 {
7056   tree list;
7057
7058 #ifdef OBJCPLUS
7059   if (current_namespace != global_namespace) {
7060     error ("Objective-C declarations may only appear in global scope");
7061   }
7062 #endif /* OBJCPLUS */
7063
7064   for (list = names; list; list = TREE_CHAIN (list))
7065     {
7066       tree name = TREE_VALUE (list);
7067
7068       if (lookup_protocol (name) == NULL_TREE)
7069         {
7070           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7071
7072           TYPE_BINFO (protocol) = make_tree_vec (2);
7073           PROTOCOL_NAME (protocol) = name;
7074           PROTOCOL_LIST (protocol) = NULL_TREE;
7075           add_protocol (protocol);
7076           PROTOCOL_DEFINED (protocol) = 0;
7077           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7078         }
7079     }
7080 }
7081
7082 tree
7083 start_protocol (enum tree_code code, tree name, tree list)
7084 {
7085   tree protocol;
7086
7087 #ifdef OBJCPLUS
7088   if (current_namespace != global_namespace) {
7089     error ("Objective-C declarations may only appear in global scope");
7090   }
7091 #endif /* OBJCPLUS */
7092
7093   /* This is as good a place as any.  Need to invoke
7094      push_tag_toplevel.  */
7095   if (!objc_protocol_template)
7096     objc_protocol_template = build_protocol_template ();
7097
7098   protocol = lookup_protocol (name);
7099
7100   if (!protocol)
7101     {
7102       protocol = make_node (code);
7103       TYPE_BINFO (protocol) = make_tree_vec (2);
7104
7105       PROTOCOL_NAME (protocol) = name;
7106       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7107       add_protocol (protocol);
7108       PROTOCOL_DEFINED (protocol) = 1;
7109       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7110
7111       check_protocol_recursively (protocol, list);
7112     }
7113   else if (! PROTOCOL_DEFINED (protocol))
7114     {
7115       PROTOCOL_DEFINED (protocol) = 1;
7116       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7117
7118       check_protocol_recursively (protocol, list);
7119     }
7120   else
7121     {
7122       warning ("duplicate declaration for protocol `%s'",
7123                IDENTIFIER_POINTER (name));
7124     }
7125   return protocol;
7126 }
7127
7128 void
7129 finish_protocol (tree protocol ATTRIBUTE_UNUSED)
7130 {
7131 }
7132
7133 \f
7134 /* "Encode" a data type into a string, which grows in util_obstack.
7135    ??? What is the FORMAT?  Someone please document this!  */
7136
7137 static void
7138 encode_type_qualifiers (tree declspecs)
7139 {
7140   tree spec;
7141
7142   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7143     {
7144       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
7145         obstack_1grow (&util_obstack, 'r');
7146       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7147         obstack_1grow (&util_obstack, 'n');
7148       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7149         obstack_1grow (&util_obstack, 'N');
7150       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7151         obstack_1grow (&util_obstack, 'o');
7152       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7153         obstack_1grow (&util_obstack, 'O');
7154       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7155         obstack_1grow (&util_obstack, 'R');
7156       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7157         obstack_1grow (&util_obstack, 'V');
7158     }
7159 }
7160
7161 /* Encode a pointer type.  */
7162
7163 static void
7164 encode_pointer (tree type, int curtype, int format)
7165 {
7166   tree pointer_to = TREE_TYPE (type);
7167
7168   if (TREE_CODE (pointer_to) == RECORD_TYPE)
7169     {
7170       if (OBJC_TYPE_NAME (pointer_to)
7171           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7172         {
7173           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7174
7175           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7176             {
7177               obstack_1grow (&util_obstack, '@');
7178               return;
7179             }
7180           else if (TREE_STATIC_TEMPLATE (pointer_to))
7181             {
7182               if (generating_instance_variables)
7183                 {
7184                   obstack_1grow (&util_obstack, '@');
7185                   obstack_1grow (&util_obstack, '"');
7186                   obstack_grow (&util_obstack, name, strlen (name));
7187                   obstack_1grow (&util_obstack, '"');
7188                   return;
7189                 }
7190               else
7191                 {
7192                   obstack_1grow (&util_obstack, '@');
7193                   return;
7194                 }
7195             }
7196           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7197             {
7198               obstack_1grow (&util_obstack, '#');
7199               return;
7200             }
7201           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7202             {
7203               obstack_1grow (&util_obstack, ':');
7204               return;
7205             }
7206         }
7207     }
7208   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7209            && TYPE_MODE (pointer_to) == QImode)
7210     {
7211       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7212                   ? OBJC_TYPE_NAME (pointer_to)
7213                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7214
7215       if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7216         {
7217           obstack_1grow (&util_obstack, '*');
7218           return;
7219         }
7220     }
7221
7222   /* We have a type that does not get special treatment.  */
7223
7224   /* NeXT extension */
7225   obstack_1grow (&util_obstack, '^');
7226   encode_type (pointer_to, curtype, format);
7227 }
7228
7229 static void
7230 encode_array (tree type, int curtype, int format)
7231 {
7232   tree an_int_cst = TYPE_SIZE (type);
7233   tree array_of = TREE_TYPE (type);
7234   char buffer[40];
7235
7236   /* An incomplete array is treated like a pointer.  */
7237   if (an_int_cst == NULL)
7238     {
7239       encode_pointer (type, curtype, format);
7240       return;
7241     }
7242
7243   sprintf (buffer, "[%ld",
7244            (long) (TREE_INT_CST_LOW (an_int_cst)
7245                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7246
7247   obstack_grow (&util_obstack, buffer, strlen (buffer));
7248   encode_type (array_of, curtype, format);
7249   obstack_1grow (&util_obstack, ']');
7250   return;
7251 }
7252 \f
7253 static void
7254 encode_aggregate_within (tree type, int curtype, int format, int left,
7255                          int right)
7256 {
7257   tree name;
7258   /* NB: aggregates that are pointed to have slightly different encoding
7259      rules in that you never encode the names of instance variables.  */
7260   int pointed_to
7261    = (obstack_object_size (&util_obstack) > 0
7262       && *(obstack_next_free (&util_obstack) - 1) == '^');
7263   int inline_contents
7264    = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7265       && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7266
7267   /* Traverse struct aliases; it is important to get the
7268      original struct and its tag name (if any).  */
7269   type = TYPE_MAIN_VARIANT (type);
7270   name = OBJC_TYPE_NAME (type);
7271   /* Open parenth/bracket.  */                          
7272   obstack_1grow (&util_obstack, left);
7273
7274   /* Encode the struct/union tag name, or '?' if a tag was
7275      not provided.  Typedef aliases do not qualify.  */
7276   if (name && TREE_CODE (name) == IDENTIFIER_NODE
7277 #ifdef OBJCPLUS
7278       /* Did this struct have a tag?  */
7279       && !TYPE_WAS_ANONYMOUS (type)
7280 #endif
7281       )
7282     obstack_grow (&util_obstack,
7283                   IDENTIFIER_POINTER (name),
7284                   strlen (IDENTIFIER_POINTER (name)));
7285   else
7286     obstack_1grow (&util_obstack, '?');
7287
7288   /* Encode the types (and possibly names) of the inner fields,
7289      if required.  */
7290   if (inline_contents)
7291     {
7292       tree fields = TYPE_FIELDS (type);
7293
7294       obstack_1grow (&util_obstack, '=');
7295       for (; fields; fields = TREE_CHAIN (fields))
7296         {
7297 #ifdef OBJCPLUS
7298           /* C++ static members, and things that are not fields at all,
7299              should not appear in the encoding.  */
7300           if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7301             continue;
7302 #endif
7303           if (generating_instance_variables && !pointed_to)
7304             {
7305               tree fname = DECL_NAME (fields);
7306
7307               obstack_1grow (&util_obstack, '"');
7308               if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7309                 obstack_grow (&util_obstack,
7310                               IDENTIFIER_POINTER (fname),
7311                               strlen (IDENTIFIER_POINTER (fname)));
7312               obstack_1grow (&util_obstack, '"');
7313             }
7314           encode_field_decl (fields, curtype, format);
7315         }
7316     }
7317   /* Close parenth/bracket.  */                         
7318   obstack_1grow (&util_obstack, right);
7319 }
7320
7321 static void
7322 encode_aggregate (tree type, int curtype, int format)
7323 {
7324   enum tree_code code = TREE_CODE (type);
7325
7326   switch (code)
7327     {
7328     case RECORD_TYPE:
7329       {
7330         encode_aggregate_within (type, curtype, format, '{', '}');
7331         break;
7332       }
7333     case UNION_TYPE:
7334       {
7335         encode_aggregate_within (type, curtype, format, '(', ')');
7336         break;
7337       }
7338
7339     case ENUMERAL_TYPE:
7340       obstack_1grow (&util_obstack, 'i');
7341       break;
7342
7343     default:
7344       break;
7345     }
7346 }
7347
7348 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7349    field type.  */
7350
7351 static void
7352 encode_next_bitfield (int width)
7353 {
7354   char buffer[40];
7355   sprintf (buffer, "b%d", width);
7356   obstack_grow (&util_obstack, buffer, strlen (buffer));
7357 }
7358 \f
7359 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
7360 static void
7361 encode_type (tree type, int curtype, int format)
7362 {
7363   enum tree_code code = TREE_CODE (type);
7364   char c;
7365
7366   if (code == INTEGER_TYPE)
7367     {
7368       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7369         {
7370         case 8:  c = TREE_UNSIGNED (type) ? 'C' : 'c'; break;
7371         case 16: c = TREE_UNSIGNED (type) ? 'S' : 's'; break;
7372         case 32: 
7373           if (type == long_unsigned_type_node
7374               || type == long_integer_type_node)
7375                  c = TREE_UNSIGNED (type) ? 'L' : 'l';
7376           else
7377                  c = TREE_UNSIGNED (type) ? 'I' : 'i';
7378           break;
7379         case 64: c = TREE_UNSIGNED (type) ? 'Q' : 'q'; break;
7380         default: abort ();
7381         }
7382       obstack_1grow (&util_obstack, c);
7383     }
7384
7385   else if (code == REAL_TYPE)
7386     {
7387       /* Floating point types.  */
7388       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7389         {
7390         case 32:  c = 'f'; break;
7391         case 64:
7392         case 128: c = 'd'; break;
7393         default: abort ();
7394         }
7395       obstack_1grow (&util_obstack, c);
7396     }
7397
7398   else if (code == VOID_TYPE)
7399     obstack_1grow (&util_obstack, 'v');
7400
7401   else if (code == BOOLEAN_TYPE)
7402     obstack_1grow (&util_obstack, 'B');
7403
7404   else if (code == ARRAY_TYPE)
7405     encode_array (type, curtype, format);
7406
7407   else if (code == POINTER_TYPE)
7408     encode_pointer (type, curtype, format);
7409
7410   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7411     encode_aggregate (type, curtype, format);
7412
7413   else if (code == FUNCTION_TYPE) /* '?' */
7414     obstack_1grow (&util_obstack, '?');
7415 }
7416
7417 static void
7418 encode_gnu_bitfield (int position, tree type, int size)
7419 {
7420   enum tree_code code = TREE_CODE (type);
7421   char buffer[40];
7422   char charType = '?';
7423
7424   if (code == INTEGER_TYPE)
7425     {
7426       if (integer_zerop (TYPE_MIN_VALUE (type)))
7427         {
7428           /* Unsigned integer types.  */
7429
7430           if (TYPE_MODE (type) == QImode)
7431             charType = 'C';
7432           else if (TYPE_MODE (type) == HImode)
7433             charType = 'S';
7434           else if (TYPE_MODE (type) == SImode)
7435             {
7436               if (type == long_unsigned_type_node)
7437                 charType = 'L';
7438               else
7439                 charType = 'I';
7440             }
7441           else if (TYPE_MODE (type) == DImode)
7442             charType = 'Q';
7443         }
7444
7445       else
7446         /* Signed integer types.  */
7447         {
7448           if (TYPE_MODE (type) == QImode)
7449             charType = 'c';
7450           else if (TYPE_MODE (type) == HImode)
7451             charType = 's';
7452           else if (TYPE_MODE (type) == SImode)
7453             {
7454               if (type == long_integer_type_node)
7455                 charType = 'l';
7456               else
7457                 charType = 'i';
7458             }
7459
7460           else if (TYPE_MODE (type) == DImode)
7461             charType = 'q';
7462         }
7463     }
7464   else if (code == ENUMERAL_TYPE)
7465     charType = 'i';
7466   else
7467     abort ();
7468
7469   sprintf (buffer, "b%d%c%d", position, charType, size);
7470   obstack_grow (&util_obstack, buffer, strlen (buffer));
7471 }
7472
7473 static void
7474 encode_field_decl (tree field_decl, int curtype, int format)
7475 {
7476   tree type;
7477
7478 #ifdef OBJCPLUS
7479   /* C++ static members, and things that are not fields at all,
7480      should not appear in the encoding.  */
7481   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7482     return;
7483 #endif
7484
7485   type = TREE_TYPE (field_decl);
7486
7487   /* Generate the bitfield typing information, if needed.  Note the difference
7488      between GNU and NeXT runtimes.  */
7489   if (DECL_BIT_FIELD_TYPE (field_decl))
7490     {
7491       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7492
7493       if (flag_next_runtime)
7494         encode_next_bitfield (size);
7495       else
7496         encode_gnu_bitfield (int_bit_position (field_decl),
7497                                   DECL_BIT_FIELD_TYPE (field_decl), size);
7498     }
7499   else
7500     encode_type (TREE_TYPE (field_decl), curtype, format);
7501 }
7502
7503 static tree
7504 objc_expr_last (tree complex_expr)
7505 {
7506   tree next;
7507
7508   if (complex_expr)
7509     while ((next = TREE_OPERAND (complex_expr, 0)))
7510       complex_expr = next;
7511
7512   return complex_expr;
7513 }
7514
7515 static void
7516 synth_self_and_ucmd_args (void)
7517 {
7518   tree decl_specs;
7519
7520   if (objc_method_context
7521       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7522     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7523   else
7524     /* Really a `struct objc_class *'. However, we allow people to
7525        assign to self, which changes its type midstream.  */
7526     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7527
7528   push_parm_decl (build_tree_list
7529                   (build_tree_list (decl_specs,
7530                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
7531                    unused_list));
7532
7533   decl_specs = build_tree_list (NULL_TREE,
7534                                 xref_tag (RECORD_TYPE,
7535                                           get_identifier (TAG_SELECTOR)));
7536   push_parm_decl (build_tree_list
7537                   (build_tree_list (decl_specs,
7538                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7539                    unused_list));
7540 }
7541
7542 /* Transform a method definition into a function definition as follows:
7543    - synthesize the first two arguments, "self" and "_cmd".  */
7544
7545 void
7546 start_method_def (tree method)
7547 {
7548   /* Required to implement _msgSuper.  */
7549   objc_method_context = method;
7550   UOBJC_SUPER_decl = NULL_TREE;
7551
7552   /* Must be called BEFORE start_function.  */
7553   pushlevel (0);
7554
7555   /* Generate prototype declarations for arguments..."new-style".  */
7556   synth_self_and_ucmd_args ();
7557
7558   /* Generate argument declarations if a keyword_decl.  */
7559   if (METHOD_SEL_ARGS (method))
7560     {
7561       tree arglist = METHOD_SEL_ARGS (method);
7562       do
7563         {
7564           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7565           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7566
7567           if (arg_decl)
7568             {
7569               tree last_expr = objc_expr_last (arg_decl);
7570
7571               /* Unite the abstract decl with its name.  */
7572               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7573               push_parm_decl (build_tree_list
7574                               (build_tree_list (arg_spec, arg_decl),
7575                                NULL_TREE));
7576
7577 #ifndef OBJCPLUS        
7578               /* Unhook: restore the abstract declarator.  */
7579               TREE_OPERAND (last_expr, 0) = NULL_TREE;
7580 #endif  
7581             }
7582
7583           else
7584             push_parm_decl (build_tree_list
7585                             (build_tree_list (arg_spec,
7586                                               KEYWORD_ARG_NAME (arglist)),
7587                              NULL_TREE));
7588
7589           arglist = TREE_CHAIN (arglist);
7590         }
7591       while (arglist);
7592     }
7593
7594   if (METHOD_ADD_ARGS (method) != NULL_TREE
7595       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7596     {
7597       /* We have a variable length selector - in "prototype" format.  */
7598       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7599       while (akey)
7600         {
7601           /* This must be done prior to calling pushdecl.  pushdecl is
7602              going to change our chain on us.  */
7603           tree nextkey = TREE_CHAIN (akey);
7604           pushdecl (akey);
7605           akey = nextkey;
7606         }
7607     }
7608 }
7609
7610 static void
7611 warn_with_method (const char *message, int mtype, tree method)
7612 {
7613   /* Add a readable method name to the warning.  */
7614   warning ("%J%s `%c%s'", method,
7615            message, mtype, gen_method_decl (method, errbuf));
7616 }
7617
7618 /* Return 1 if METHOD is consistent with PROTO.  */
7619
7620 static int
7621 comp_method_with_proto (tree method, tree proto)
7622 {
7623   /* Create a function template node at most once.  */
7624   if (!function1_template)
7625     function1_template = make_node (FUNCTION_TYPE);
7626
7627   /* Install argument types - normally set by build_function_type.  */
7628   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7629
7630   /* install return type */
7631   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7632
7633   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
7634                     false);
7635 }
7636
7637 /* Return 1 if TYPE1 is equivalent to TYPE2.  */
7638
7639 static int
7640 objc_types_are_equivalent (tree type1, tree type2)
7641 {
7642   if (type1 == type2)
7643     return 1;
7644   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7645     return 0;
7646   type1 = TYPE_PROTOCOL_LIST (type1);
7647   type2 = TYPE_PROTOCOL_LIST (type2);
7648   if (list_length (type1) == list_length (type2))
7649     {
7650       for (; type2; type2 = TREE_CHAIN (type2))
7651         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7652           return 0;
7653       return 1;
7654     }
7655   return 0;
7656 }
7657
7658 /* Return 1 if PROTO1 is equivalent to PROTO2.  */
7659
7660 static int
7661 comp_proto_with_proto (tree proto1, tree proto2)
7662 {
7663   tree type1, type2;
7664
7665   /* The following test is needed in case there are hashing
7666      collisions.  */
7667   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7668     return 0;
7669
7670   /* Compare return types.  */
7671   type1 = groktypename (TREE_TYPE (proto1));
7672   type2 = groktypename (TREE_TYPE (proto2));
7673
7674   if (!objc_types_are_equivalent (type1, type2))
7675     return 0;
7676
7677   /* Compare argument types.  */
7678   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7679        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7680        type1 && type2;
7681        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7682     {
7683       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7684         return 0;
7685     }
7686
7687   return (!type1 && !type2);
7688 }
7689
7690 /* - Generate an identifier for the function. the format is "_n_cls",
7691      where 1 <= n <= nMethods, and cls is the name the implementation we
7692      are processing.
7693    - Install the return type from the method declaration.
7694    - If we have a prototype, check for type consistency.  */
7695
7696 static void
7697 really_start_method (tree method, tree parmlist)
7698 {
7699   tree sc_spec, ret_spec, ret_decl, decl_specs;
7700   tree method_decl, method_id;
7701   const char *sel_name, *class_name, *cat_name;
7702   char *buf;
7703
7704   /* Synth the storage class & assemble the return type.  */
7705   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7706   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7707   decl_specs = chainon (sc_spec, ret_spec);
7708
7709   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7710   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7711   cat_name = ((TREE_CODE (objc_implementation_context)
7712                == CLASS_IMPLEMENTATION_TYPE)
7713               ? NULL
7714               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7715   method_slot++;
7716
7717   /* Make sure this is big enough for any plausible method label.  */
7718   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7719                          + (cat_name ? strlen (cat_name) : 0));
7720
7721   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7722                          class_name, cat_name, sel_name, method_slot);
7723
7724   method_id = get_identifier (buf);
7725
7726 #ifdef OBJCPLUS
7727   /* Objective-C methods cannot be overloaded, so we don't need
7728      the type encoding appended.  It looks bad anyway... */
7729   push_lang_context (lang_name_c);
7730 #endif
7731
7732   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7733
7734   /* Check the declarator portion of the return type for the method.  */
7735   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7736     {
7737       /* Unite the complex decl (specified in the abstract decl) with the
7738          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7739       tree save_expr = objc_expr_last (ret_decl);
7740
7741       TREE_OPERAND (save_expr, 0) = method_decl;
7742       method_decl = ret_decl;
7743
7744       /* Fool the parser into thinking it is starting a function.  */
7745       start_function (decl_specs, method_decl, NULL_TREE);
7746
7747       /* Unhook: this has the effect of restoring the abstract declarator.  */
7748       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7749     }
7750
7751   else
7752     {
7753       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7754
7755       /* Fool the parser into thinking it is starting a function.  */
7756       start_function (decl_specs, method_decl, NULL_TREE);
7757
7758       /* Unhook: this has the effect of restoring the abstract declarator.  */
7759       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7760     }
7761
7762 #ifdef OBJCPLUS
7763   /* set self_decl from the first argument...this global is used by
7764    * build_ivar_reference().build_indirect_ref().
7765    */
7766   self_decl = DECL_ARGUMENTS (current_function_decl);
7767
7768   /* snaroff (3/28/96): when compiling with -Wall, this suppresses
7769    * the following: warning:unused parameter `struct objc_selector * _cmd'
7770    */
7771   TREE_USED (self_decl) = 1;
7772   TREE_USED (TREE_CHAIN (self_decl)) = 1;
7773   /* Ditto for the underlying (static) C function.  */
7774   TREE_USED (current_function_decl) = 1;
7775   pop_lang_context ();
7776 #endif
7777
7778   METHOD_DEFINITION (method) = current_function_decl;
7779
7780   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7781
7782   if (implementation_template != objc_implementation_context)
7783     {
7784       tree proto
7785         = lookup_method_static (implementation_template,
7786                                 METHOD_SEL_NAME (method),
7787                                 TREE_CODE (method) == CLASS_METHOD_DECL);
7788
7789       if (proto)
7790         {
7791           if (!comp_method_with_proto (method, proto))
7792             {
7793               char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7794
7795               warn_with_method ("conflicting types for", type, method);
7796               warn_with_method ("previous declaration of", type, proto);
7797             }
7798         }
7799       else
7800         {
7801           /* We have a method @implementation even though we did not
7802              see a corresponding @interface declaration (which is allowed
7803              by Objective-C rules).  Go ahead and place the method in
7804              the @interface anyway, so that message dispatch lookups
7805              will see it.  */
7806           tree interface = implementation_template;
7807
7808           if (TREE_CODE (objc_implementation_context)
7809               == CATEGORY_IMPLEMENTATION_TYPE)
7810             interface = lookup_category
7811                         (interface,
7812                          CLASS_SUPER_NAME (objc_implementation_context));
7813
7814           if (interface)
7815             objc_add_method (interface, copy_node (method),
7816                              TREE_CODE (method) == CLASS_METHOD_DECL);
7817         }
7818     }
7819 }
7820
7821 /* The following routine is always called...this "architecture" is to
7822    accommodate "old-style" variable length selectors.
7823
7824    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7825
7826 void
7827 continue_method_def (void)
7828 {
7829   tree parmlist;
7830
7831   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7832     /* We have a `, ...' immediately following the selector.  */
7833     parmlist = get_parm_info (0);
7834   else
7835     parmlist = get_parm_info (1); /* place a `void_at_end' */
7836
7837 #ifndef OBJCPLUS
7838   /* Set self_decl from the first argument...this global is used by
7839      build_ivar_reference calling build_indirect_ref.  */
7840   self_decl = TREE_PURPOSE (parmlist);
7841 #endif /* !OBJCPLUS */
7842
7843   poplevel (0, 0, 0);
7844   really_start_method (objc_method_context, parmlist);
7845   store_parm_decls ();
7846 }
7847
7848 static void *UOBJC_SUPER_scope = 0;
7849
7850 /* _n_Method (id self, SEL sel, ...)
7851      {
7852        struct objc_super _S;
7853        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7854      }  */
7855
7856 tree
7857 get_super_receiver (void)
7858 {
7859   if (objc_method_context)
7860     {
7861       tree super_expr, super_expr_list;
7862
7863       if (!UOBJC_SUPER_decl)
7864       {
7865         UOBJC_SUPER_decl = start_decl (get_identifier (TAG_SUPER),
7866                                        build_tree_list (NULL_TREE,
7867                                        objc_super_template),
7868                                        0, NULL_TREE);
7869         
7870         finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7871
7872         /* This prevents `unused variable' warnings when compiling with -Wall.  */
7873         TREE_USED (UOBJC_SUPER_decl) = 1;
7874         DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7875
7876         UOBJC_SUPER_scope = get_current_scope ();
7877       }
7878
7879       /* Set receiver to self.  */
7880       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7881       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7882       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7883
7884       /* Set class to begin searching.  */
7885       super_expr = build_component_ref (UOBJC_SUPER_decl,
7886                                         get_identifier ("class"));
7887
7888       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7889         {
7890           /* [_cls, __cls]Super are "pre-built" in
7891              synth_forward_declarations.  */
7892
7893           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7894                                           ((TREE_CODE (objc_method_context)
7895                                             == INSTANCE_METHOD_DECL)
7896                                            ? ucls_super_ref
7897                                            : uucls_super_ref));
7898         }
7899
7900       else
7901         /* We have a category.  */
7902         {
7903           tree super_name = CLASS_SUPER_NAME (implementation_template);
7904           tree super_class;
7905
7906           /* Barf if super used in a category of Object.  */
7907           if (!super_name)
7908             {
7909               error ("no super class declared in interface for `%s'",
7910                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7911               return error_mark_node;
7912             }
7913
7914           if (flag_next_runtime && !flag_zero_link)
7915             {
7916               super_class = get_class_reference (super_name);
7917               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7918                 /* If we are in a class method, we must retrieve the
7919                    _metaclass_ for the current class, pointed at by
7920                    the class's "isa" pointer.  The following assumes that
7921                    "isa" is the first ivar in a class (which it must be).  */
7922                 super_class
7923                   = build_indirect_ref
7924                     (build_c_cast (build_pointer_type (objc_class_type),
7925                                    super_class), "unary *");
7926             }
7927           else
7928             {
7929               add_class_reference (super_name);
7930               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7931                              ? objc_get_class_decl : objc_get_meta_class_decl);
7932               assemble_external (super_class);
7933               super_class
7934                 = build_function_call
7935                   (super_class,
7936                    build_tree_list
7937                    (NULL_TREE,
7938                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7939                                      IDENTIFIER_POINTER (super_name))));
7940             }
7941
7942           super_expr
7943             = build_modify_expr (super_expr, NOP_EXPR,
7944                                  build_c_cast (TREE_TYPE (super_expr),
7945                                                super_class));
7946         }
7947
7948       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7949
7950       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7951       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7952
7953       return build_compound_expr (super_expr_list);
7954     }
7955   else
7956     {
7957       error ("[super ...] must appear in a method context");
7958       return error_mark_node;
7959     }
7960 }
7961
7962 /* When exiting a scope, sever links to a 'super' declaration (if any)
7963    therein contained.  */
7964
7965 void
7966 objc_clear_super_receiver (void)
7967 {
7968   if (objc_method_context
7969       && UOBJC_SUPER_scope == get_current_scope ()) {
7970     UOBJC_SUPER_decl = 0;
7971     UOBJC_SUPER_scope = 0;
7972   }
7973 }
7974
7975 static void
7976 objc_expand_function_end (void)
7977 {
7978   /* This routine may also get called for C functions, including those
7979      nested within ObjC methods.  In such cases, method encoding is
7980      meaningless.  */
7981   if (objc_method_context == NULL_TREE
7982       || DECL_INITIAL (objc_method_context) != current_function_decl)
7983     return;
7984
7985   METHOD_ENCODING (objc_method_context)
7986     = encode_method_prototype (objc_method_context);
7987 }
7988
7989 void
7990 finish_method_def (void)
7991 {
7992   lang_expand_function_end = objc_expand_function_end;
7993   /* We cannot validly inline ObjC methods, at least not without a language
7994      extension to declare that a method need not be dynamically
7995      dispatched, so suppress all thoughts of doing so.  */
7996   DECL_INLINE (current_function_decl) = 0;
7997   DECL_UNINLINABLE (current_function_decl) = 1;
7998   current_function_cannot_inline = "methods cannot be inlined";
7999
8000   finish_function ();
8001   lang_expand_function_end = NULL;
8002
8003   /* Required to implement _msgSuper. This must be done AFTER finish_function,
8004      since the optimizer may find "may be used before set" errors.  */
8005   objc_method_context = NULL_TREE;
8006 }
8007
8008 #if 0
8009 int
8010 lang_report_error_function (tree decl)
8011 {
8012   if (objc_method_context)
8013     {
8014       fprintf (stderr, "In method `%s'\n",
8015                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8016       return 1;
8017     }
8018
8019   else
8020     return 0;
8021 }
8022 #endif
8023
8024 static int
8025 is_complex_decl (tree type)
8026 {
8027   return (TREE_CODE (type) == ARRAY_TYPE
8028           || TREE_CODE (type) == FUNCTION_TYPE
8029           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
8030 }
8031
8032 \f
8033 /* Code to convert a decl node into text for a declaration in C.  */
8034
8035 static char tmpbuf[256];
8036
8037 static void
8038 adorn_decl (tree decl, char *str)
8039 {
8040   enum tree_code code = TREE_CODE (decl);
8041
8042   if (code == ARRAY_REF)
8043     {
8044       tree an_int_cst = TREE_OPERAND (decl, 1);
8045
8046       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
8047         sprintf (str + strlen (str), "[%ld]",
8048                  (long) TREE_INT_CST_LOW (an_int_cst));
8049       else
8050         strcat (str, "[]");
8051     }
8052
8053   else if (code == ARRAY_TYPE)
8054     {
8055       tree an_int_cst = TYPE_SIZE (decl);
8056       tree array_of = TREE_TYPE (decl);
8057
8058       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
8059         sprintf (str + strlen (str), "[%ld]",
8060                  (long) (TREE_INT_CST_LOW (an_int_cst)
8061                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
8062       else
8063         strcat (str, "[]");
8064     }
8065
8066   else if (code == CALL_EXPR)
8067     {
8068       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
8069
8070       strcat (str, "(");
8071       while (chain)
8072         {
8073           gen_declaration_1 (chain, str);
8074           chain = TREE_CHAIN (chain);
8075           if (chain)
8076             strcat (str, ", ");
8077         }
8078       strcat (str, ")");
8079     }
8080
8081   else if (code == FUNCTION_TYPE)
8082     {
8083       tree chain  = TYPE_ARG_TYPES (decl);
8084
8085       strcat (str, "(");
8086       while (chain && TREE_VALUE (chain) != void_type_node)
8087         {
8088           gen_declaration_1 (TREE_VALUE (chain), str);
8089           chain = TREE_CHAIN (chain);
8090           if (chain && TREE_VALUE (chain) != void_type_node)
8091             strcat (str, ", ");
8092         }
8093       strcat (str, ")");
8094     }
8095
8096   else if (code == INDIRECT_REF)
8097     {
8098       strcpy (tmpbuf, "*");
8099       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
8100         {
8101           tree chain;
8102
8103           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
8104                chain;
8105                chain = TREE_CHAIN (chain))
8106             {
8107               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
8108                 {
8109                   strcat (tmpbuf, " ");
8110                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
8111                 }
8112             }
8113           if (str[0])
8114             strcat (tmpbuf, " ");
8115         }
8116       strcat (tmpbuf, str);
8117       strcpy (str, tmpbuf);
8118     }
8119
8120   else if (code == POINTER_TYPE)
8121     {
8122       strcpy (tmpbuf, "*");
8123       if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
8124         {
8125           if (TREE_READONLY (decl))
8126             strcat (tmpbuf, " const");
8127           if (TYPE_VOLATILE (decl))
8128             strcat (tmpbuf, " volatile");
8129           if (str[0])
8130             strcat (tmpbuf, " ");
8131         }
8132       strcat (tmpbuf, str);
8133       strcpy (str, tmpbuf);
8134     }
8135 }
8136
8137 static char *
8138 gen_declarator (tree decl, char *buf, const char *name)
8139 {
8140   if (decl)
8141     {
8142       enum tree_code code = TREE_CODE (decl);
8143       char *str;
8144       tree op;
8145       int wrap = 0;
8146
8147       switch (code)
8148         {
8149         case ARRAY_REF:
8150         case INDIRECT_REF:
8151         case CALL_EXPR:
8152           op = TREE_OPERAND (decl, 0);
8153
8154           /* We have a pointer to a function or array...(*)(), (*)[] */
8155           if ((code == ARRAY_REF || code == CALL_EXPR)
8156               && op && TREE_CODE (op) == INDIRECT_REF)
8157             wrap = 1;
8158
8159           str = gen_declarator (op, buf, name);
8160
8161           if (wrap)
8162             {
8163               strcpy (tmpbuf, "(");
8164               strcat (tmpbuf, str);
8165               strcat (tmpbuf, ")");
8166               strcpy (str, tmpbuf);
8167             }
8168
8169           adorn_decl (decl, str);
8170           break;
8171
8172         case ARRAY_TYPE:
8173         case FUNCTION_TYPE:
8174         case POINTER_TYPE:
8175           strcpy (buf, name);
8176           str = buf;
8177
8178           /* This clause is done iteratively rather than recursively.  */
8179           do
8180             {
8181               op = (is_complex_decl (TREE_TYPE (decl))
8182                     ? TREE_TYPE (decl) : NULL_TREE);
8183
8184               adorn_decl (decl, str);
8185
8186               /* We have a pointer to a function or array...(*)(), (*)[] */
8187               if (code == POINTER_TYPE
8188                   && op && (TREE_CODE (op) == FUNCTION_TYPE
8189                             || TREE_CODE (op) == ARRAY_TYPE))
8190                 {
8191                   strcpy (tmpbuf, "(");
8192                   strcat (tmpbuf, str);
8193                   strcat (tmpbuf, ")");
8194                   strcpy (str, tmpbuf);
8195                 }
8196
8197               decl = (is_complex_decl (TREE_TYPE (decl))
8198                       ? TREE_TYPE (decl) : NULL_TREE);
8199             }
8200
8201           while (decl && (code = TREE_CODE (decl)))
8202             ;
8203
8204           break;
8205
8206         case IDENTIFIER_NODE:
8207           /* Will only happen if we are processing a "raw" expr-decl.  */
8208           strcpy (buf, IDENTIFIER_POINTER (decl));
8209           return buf;
8210
8211         default:
8212           abort ();
8213         }
8214
8215       return str;
8216     }
8217
8218   else
8219     /* We have an abstract declarator or a _DECL node.  */
8220     {
8221       strcpy (buf, name);
8222       return buf;
8223     }
8224 }
8225
8226 static void
8227 gen_declspecs (tree declspecs, char *buf, int raw)
8228 {
8229   if (raw)
8230     {
8231       tree chain;
8232
8233       for (chain = nreverse (copy_list (declspecs));
8234            chain; chain = TREE_CHAIN (chain))
8235         {
8236           tree aspec = TREE_VALUE (chain);
8237
8238           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
8239             strcat (buf, IDENTIFIER_POINTER (aspec));
8240           else if (TREE_CODE (aspec) == RECORD_TYPE)
8241             {
8242               if (OBJC_TYPE_NAME (aspec))
8243                 {
8244                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8245
8246                   if (! TREE_STATIC_TEMPLATE (aspec))
8247                     strcat (buf, "struct ");
8248                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8249
8250                   /* NEW!!! */
8251                   if (protocol_list)
8252                     {
8253                       tree chain = protocol_list;
8254
8255                       strcat (buf, " <");
8256                       while (chain)
8257                         {
8258                           strcat (buf,
8259                                   IDENTIFIER_POINTER
8260                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
8261                           chain = TREE_CHAIN (chain);
8262                           if (chain)
8263                             strcat (buf, ", ");
8264                         }
8265                       strcat (buf, ">");
8266                     }
8267                 }
8268
8269               else
8270                 strcat (buf, "untagged struct");
8271             }
8272
8273           else if (TREE_CODE (aspec) == UNION_TYPE)
8274             {
8275               if (OBJC_TYPE_NAME (aspec))
8276                 {
8277                   if (! TREE_STATIC_TEMPLATE (aspec))
8278                     strcat (buf, "union ");
8279                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8280                 }
8281               else
8282                 strcat (buf, "untagged union");
8283             }
8284
8285           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
8286             {
8287               if (OBJC_TYPE_NAME (aspec))
8288                 {
8289                   if (! TREE_STATIC_TEMPLATE (aspec))
8290                     strcat (buf, "enum ");
8291                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8292                 }
8293               else
8294                 strcat (buf, "untagged enum");
8295             }
8296
8297           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
8298             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
8299
8300           else if (IS_ID (aspec))
8301             {
8302               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8303
8304               strcat (buf, "id");
8305               if (protocol_list)
8306                 {
8307                   tree chain = protocol_list;
8308
8309                   strcat (buf, " <");
8310                   while (chain)
8311                     {
8312                       strcat (buf,
8313                               IDENTIFIER_POINTER
8314                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8315                       chain = TREE_CHAIN (chain);
8316                       if (chain)
8317                         strcat (buf, ", ");
8318                     }
8319                   strcat (buf, ">");
8320                 }
8321             }
8322           if (TREE_CHAIN (chain))
8323             strcat (buf, " ");
8324         }
8325     }
8326   else
8327     {
8328       /* Type qualifiers.  */
8329       if (TREE_READONLY (declspecs))
8330         strcat (buf, "const ");
8331       if (TYPE_VOLATILE (declspecs))
8332         strcat (buf, "volatile ");
8333
8334       switch (TREE_CODE (declspecs))
8335         {
8336           /* Type specifiers.  */
8337
8338         case INTEGER_TYPE:
8339           declspecs = TYPE_MAIN_VARIANT (declspecs);
8340
8341           /* Signed integer types.  */
8342
8343           if (declspecs == short_integer_type_node)
8344             strcat (buf, "short int ");
8345           else if (declspecs == integer_type_node)
8346             strcat (buf, "int ");
8347           else if (declspecs == long_integer_type_node)
8348             strcat (buf, "long int ");
8349           else if (declspecs == long_long_integer_type_node)
8350             strcat (buf, "long long int ");
8351           else if (declspecs == signed_char_type_node
8352                    || declspecs == char_type_node)
8353             strcat (buf, "char ");
8354
8355           /* Unsigned integer types.  */
8356
8357           else if (declspecs == short_unsigned_type_node)
8358             strcat (buf, "unsigned short ");
8359           else if (declspecs == unsigned_type_node)
8360             strcat (buf, "unsigned int ");
8361           else if (declspecs == long_unsigned_type_node)
8362             strcat (buf, "unsigned long ");
8363           else if (declspecs == long_long_unsigned_type_node)
8364             strcat (buf, "unsigned long long ");
8365           else if (declspecs == unsigned_char_type_node)
8366             strcat (buf, "unsigned char ");
8367           break;
8368
8369         case REAL_TYPE:
8370           declspecs = TYPE_MAIN_VARIANT (declspecs);
8371
8372           if (declspecs == float_type_node)
8373             strcat (buf, "float ");
8374           else if (declspecs == double_type_node)
8375             strcat (buf, "double ");
8376           else if (declspecs == long_double_type_node)
8377             strcat (buf, "long double ");
8378           break;
8379
8380         case RECORD_TYPE:
8381           if (OBJC_TYPE_NAME (declspecs)
8382               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8383             {
8384               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8385
8386               if (! TREE_STATIC_TEMPLATE (declspecs))
8387                 strcat (buf, "struct ");
8388               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8389
8390               if (protocol_list)
8391                 {
8392                   tree chain = protocol_list;
8393
8394                   strcat (buf, " <");
8395                   while (chain)
8396                     {
8397                       strcat (buf,
8398                               IDENTIFIER_POINTER
8399                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8400                       chain = TREE_CHAIN (chain);
8401                       if (chain)
8402                         strcat (buf, ", ");
8403                     }
8404                   strcat (buf, ">");
8405                 }
8406             }
8407
8408           else
8409             strcat (buf, "untagged struct");
8410
8411           strcat (buf, " ");
8412           break;
8413
8414         case UNION_TYPE:
8415           if (OBJC_TYPE_NAME (declspecs)
8416               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8417             {
8418               strcat (buf, "union ");
8419               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8420               strcat (buf, " ");
8421             }
8422
8423           else
8424             strcat (buf, "untagged union ");
8425           break;
8426
8427         case ENUMERAL_TYPE:
8428           if (OBJC_TYPE_NAME (declspecs)
8429               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8430             {
8431               strcat (buf, "enum ");
8432               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8433               strcat (buf, " ");
8434             }
8435
8436           else
8437             strcat (buf, "untagged enum ");
8438           break;
8439
8440         case VOID_TYPE:
8441           strcat (buf, "void ");
8442           break;
8443
8444         case POINTER_TYPE:
8445           {
8446             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8447
8448             strcat (buf, "id");
8449             if (protocol_list)
8450               {
8451                 tree chain = protocol_list;
8452
8453                 strcat (buf, " <");
8454                 while (chain)
8455                   {
8456                     strcat (buf,
8457                             IDENTIFIER_POINTER
8458                             (PROTOCOL_NAME (TREE_VALUE (chain))));
8459                     chain = TREE_CHAIN (chain);
8460                     if (chain)
8461                       strcat (buf, ", ");
8462                   }
8463
8464                 strcat (buf, ">");
8465               }
8466           }
8467           break;
8468
8469         default:
8470           break;
8471         }
8472     }
8473 }
8474
8475 /* Given a tree node, produce a printable description of it in the given
8476    buffer, overwriting the buffer.  */
8477
8478 static char *
8479 gen_declaration (tree atype_or_adecl, char *buf)
8480 {
8481   buf[0] = '\0';
8482   gen_declaration_1 (atype_or_adecl, buf);
8483   return buf;
8484 }
8485
8486 /* Given a tree node, append a printable description to the end of the
8487    given buffer.  */
8488
8489 static void
8490 gen_declaration_1 (tree atype_or_adecl, char *buf)
8491 {
8492   char declbuf[256];
8493
8494   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
8495     {
8496       tree declspecs;   /* "identifier_node", "record_type" */
8497       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
8498       tree width = NULL_TREE;   /* for bitfields */
8499
8500       /* We have a "raw", abstract declarator (typename).  */
8501       declarator = TREE_VALUE (atype_or_adecl);
8502       /* In the case of raw ivars, the declarator itself is a list,
8503          and contains bitfield widths.  */
8504       if (declarator && TREE_CODE (declarator) == TREE_LIST)
8505         {
8506           width = TREE_VALUE (declarator);
8507           declarator = TREE_PURPOSE (declarator);
8508         }
8509       declspecs  = TREE_PURPOSE (atype_or_adecl);
8510
8511       gen_declspecs (declspecs, buf, 1);
8512       if (declarator)
8513         {
8514           strcat (buf, " ");
8515           strcat (buf, gen_declarator (declarator, declbuf, ""));
8516         }
8517       if (width)
8518         sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED, 
8519                  TREE_INT_CST_LOW (width));
8520     }
8521
8522   else
8523     {
8524       tree atype;
8525       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
8526       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
8527
8528       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8529           || TREE_CODE (atype_or_adecl) == PARM_DECL
8530           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8531         atype = TREE_TYPE (atype_or_adecl);
8532       else
8533         /* Assume we have a *_type node.  */
8534         atype = atype_or_adecl;
8535
8536       if (is_complex_decl (atype))
8537         {
8538           tree chain;
8539
8540           /* Get the declaration specifier; it is at the end of the list.  */
8541           declarator = chain = atype;
8542           do
8543             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8544           while (is_complex_decl (chain));
8545           declspecs = chain;
8546         }
8547
8548       else
8549         {
8550           declspecs = atype;
8551           declarator = NULL_TREE;
8552         }
8553
8554       gen_declspecs (declspecs, buf, 0);
8555
8556       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8557           || TREE_CODE (atype_or_adecl) == PARM_DECL
8558           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8559         {
8560           const char *const decl_name =
8561             (DECL_NAME (atype_or_adecl)
8562              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8563
8564           if (declarator)
8565             {
8566               strcat (buf, " ");
8567               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8568             }
8569
8570           else if (decl_name[0])
8571             {
8572               strcat (buf, " ");
8573               strcat (buf, decl_name);
8574             }
8575         }
8576       else if (declarator)
8577         {
8578           strcat (buf, " ");
8579           strcat (buf, gen_declarator (declarator, declbuf, ""));
8580         }
8581     }
8582 }
8583
8584 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8585
8586 /* Given a method tree, put a printable description into the given
8587    buffer (overwriting) and return a pointer to the buffer.  */
8588
8589 static char *
8590 gen_method_decl (tree method, char *buf)
8591 {
8592   tree chain;
8593
8594   buf[0] = '\0';
8595   if (RAW_TYPESPEC (method) != objc_object_reference)
8596     {
8597       strcat (buf, "(");
8598       gen_declaration_1 (TREE_TYPE (method), buf);
8599       strcat (buf, ")");
8600     }
8601
8602   chain = METHOD_SEL_ARGS (method);
8603   if (chain)
8604     {
8605       /* We have a chain of keyword_decls.  */
8606       do
8607         {
8608           if (KEYWORD_KEY_NAME (chain))
8609             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8610
8611           strcat (buf, ":");
8612           if (RAW_TYPESPEC (chain) != objc_object_reference)
8613             {
8614               strcat (buf, "(");
8615               gen_declaration_1 (TREE_TYPE (chain), buf);
8616               strcat (buf, ")");
8617             }
8618
8619           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8620           if ((chain = TREE_CHAIN (chain)))
8621             strcat (buf, " ");
8622         }
8623       while (chain);
8624
8625       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8626         strcat (buf, ", ...");
8627       else if (METHOD_ADD_ARGS (method))
8628         {
8629           /* We have a tree list node as generate by get_parm_info.  */
8630           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8631
8632           /* Know we have a chain of parm_decls.  */
8633           while (chain)
8634             {
8635               strcat (buf, ", ");
8636               gen_declaration_1 (chain, buf);
8637               chain = TREE_CHAIN (chain);
8638             }
8639         }
8640     }
8641
8642   else
8643     /* We have a unary selector.  */
8644     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8645
8646   return buf;
8647 }
8648 \f
8649 /* Debug info.  */
8650
8651
8652 /* Dump an @interface declaration of the supplied class CHAIN to the
8653    supplied file FP.  Used to implement the -gen-decls option (which
8654    prints out an @interface declaration of all classes compiled in
8655    this run); potentially useful for debugging the compiler too.  */
8656 static void
8657 dump_interface (FILE *fp, tree chain)
8658 {
8659   /* FIXME: A heap overflow here whenever a method (or ivar)
8660      declaration is so long that it doesn't fit in the buffer.  The
8661      code and all the related functions should be rewritten to avoid
8662      using fixed size buffers.  */
8663   char *buf = (char *) xmalloc (1024 * 10);
8664   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8665   tree ivar_decls = CLASS_RAW_IVARS (chain);
8666   tree nst_methods = CLASS_NST_METHODS (chain);
8667   tree cls_methods = CLASS_CLS_METHODS (chain);
8668
8669   fprintf (fp, "\n@interface %s", my_name);
8670
8671   /* CLASS_SUPER_NAME is used to store the superclass name for
8672      classes, and the category name for categories.  */
8673   if (CLASS_SUPER_NAME (chain))
8674     {
8675       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8676
8677       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8678           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8679         {
8680           fprintf (fp, " (%s)\n", name);
8681         }
8682       else
8683         {
8684           fprintf (fp, " : %s\n", name);
8685         }
8686     }
8687   else
8688     fprintf (fp, "\n");
8689
8690   /* FIXME - the following doesn't seem to work at the moment.  */
8691   if (ivar_decls)
8692     {
8693       fprintf (fp, "{\n");
8694       do
8695         {
8696           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8697           ivar_decls = TREE_CHAIN (ivar_decls);
8698         }
8699       while (ivar_decls);
8700       fprintf (fp, "}\n");
8701     }
8702
8703   while (nst_methods)
8704     {
8705       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8706       nst_methods = TREE_CHAIN (nst_methods);
8707     }
8708
8709   while (cls_methods)
8710     {
8711       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8712       cls_methods = TREE_CHAIN (cls_methods);
8713     }
8714
8715   fprintf (fp, "@end\n");
8716 }
8717
8718 /* Demangle function for Objective-C */
8719 static const char *
8720 objc_demangle (const char *mangled)
8721 {
8722   char *demangled, *cp;
8723
8724   if (mangled[0] == '_' &&
8725       (mangled[1] == 'i' || mangled[1] == 'c') &&
8726       mangled[2] == '_')
8727     {
8728       cp = demangled = xmalloc(strlen(mangled) + 2);
8729       if (mangled[1] == 'i')
8730         *cp++ = '-';            /* for instance method */
8731       else
8732         *cp++ = '+';            /* for class method */
8733       *cp++ = '[';              /* opening left brace */
8734       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8735       while (*cp && *cp == '_')
8736         cp++;                   /* skip any initial underbars in class name */
8737       cp = strchr(cp, '_');     /* find first non-initial underbar */
8738       if (cp == NULL)
8739         {
8740           free(demangled);      /* not mangled name */
8741           return mangled;
8742         }
8743       if (cp[1] == '_')  /* easy case: no category name */
8744         {
8745           *cp++ = ' ';            /* replace two '_' with one ' ' */
8746           strcpy(cp, mangled + (cp - demangled) + 2);
8747         }
8748       else
8749         {
8750           *cp++ = '(';            /* less easy case: category name */
8751           cp = strchr(cp, '_');
8752           if (cp == 0)
8753             {
8754               free(demangled);    /* not mangled name */
8755               return mangled;
8756             }
8757           *cp++ = ')';
8758           *cp++ = ' ';            /* overwriting 1st char of method name... */
8759           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8760         }
8761       while (*cp && *cp == '_')
8762         cp++;                   /* skip any initial underbars in method name */
8763       for (; *cp; cp++)
8764         if (*cp == '_')
8765           *cp = ':';            /* replace remaining '_' with ':' */
8766       *cp++ = ']';              /* closing right brace */
8767       *cp++ = 0;                /* string terminator */
8768       return demangled;
8769     }
8770   else
8771     return mangled;             /* not an objc mangled name */
8772 }
8773
8774 const char *
8775 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8776 {
8777   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8778 }
8779
8780 static void
8781 init_objc (void)
8782 {
8783   gcc_obstack_init (&util_obstack);
8784   util_firstobj = (char *) obstack_finish (&util_obstack);
8785
8786   errbuf = (char *) xmalloc (BUFSIZE);
8787   hash_init ();
8788   synth_module_prologue ();
8789 }
8790 \f
8791 static void
8792 finish_objc (void)
8793 {
8794   struct imp_entry *impent;
8795   tree chain;
8796   /* The internally generated initializers appear to have missing braces.
8797      Don't warn about this.  */
8798   int save_warn_missing_braces = warn_missing_braces;
8799   warn_missing_braces = 0;
8800
8801   /* A missing @end may not be detected by the parser.  */
8802   if (objc_implementation_context)
8803     {
8804       warning ("`@end' missing in implementation context");
8805       finish_class (objc_implementation_context);
8806       objc_ivar_chain = NULL_TREE;
8807       objc_implementation_context = NULL_TREE;
8808     }
8809
8810   generate_forward_declaration_to_string_table ();
8811
8812   /* Process the static instances here because initialization of objc_symtab
8813      depends on them.  */
8814   if (objc_static_instances)
8815     generate_static_references ();
8816
8817   if (imp_list || class_names_chain
8818       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8819     generate_objc_symtab_decl ();
8820
8821   for (impent = imp_list; impent; impent = impent->next)
8822     {
8823       objc_implementation_context = impent->imp_context;
8824       implementation_template = impent->imp_template;
8825
8826       UOBJC_CLASS_decl = impent->class_decl;
8827       UOBJC_METACLASS_decl = impent->meta_decl;
8828
8829       /* Dump the @interface of each class as we compile it, if the
8830          -gen-decls option is in use.  TODO: Dump the classes in the
8831          order they were found, rather than in reverse order as we
8832          are doing now.  */
8833       if (flag_gen_declaration)
8834         {
8835           dump_interface (gen_declaration_file, objc_implementation_context);
8836         }
8837
8838       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8839         {
8840           /* all of the following reference the string pool...  */
8841           generate_ivar_lists ();
8842           generate_dispatch_tables ();
8843           generate_shared_structures ();
8844         }
8845       else
8846         {
8847           generate_dispatch_tables ();
8848           generate_category (objc_implementation_context);
8849         }
8850     }
8851
8852   /* If we are using an array of selectors, we must always
8853      finish up the array decl even if no selectors were used.  */
8854   if (! flag_next_runtime || sel_ref_chain)
8855     build_selector_translation_table ();
8856
8857   if (protocol_chain)
8858     generate_protocols ();
8859
8860   if (flag_replace_objc_classes && imp_list)
8861     generate_objc_image_info ();
8862
8863   if (objc_implementation_context || class_names_chain || objc_static_instances
8864       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8865     {
8866       /* Arrange for ObjC data structures to be initialized at run time.  */
8867       rtx init_sym = build_module_descriptor ();
8868       if (init_sym && targetm.have_ctors_dtors)
8869         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8870     }
8871
8872   /* Dump the class references.  This forces the appropriate classes
8873      to be linked into the executable image, preserving unix archive
8874      semantics.  This can be removed when we move to a more dynamically
8875      linked environment.  */
8876
8877   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8878     {
8879       handle_class_ref (chain);
8880       if (TREE_PURPOSE (chain))
8881         generate_classref_translation_entry (chain);
8882     }
8883
8884   for (impent = imp_list; impent; impent = impent->next)
8885     handle_impent (impent);
8886
8887   /* Dump the string table last.  */
8888
8889   generate_strings ();
8890
8891   if (warn_selector)
8892     {
8893       int slot;
8894       hash hsh;
8895
8896       /* Run through the selector hash tables and print a warning for any
8897          selector which has multiple methods.  */
8898
8899       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8900         {
8901           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8902             check_duplicates (hsh, 0, 1);
8903           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8904             check_duplicates (hsh, 0, 1);
8905         }
8906     }
8907
8908   warn_missing_braces = save_warn_missing_braces;
8909 }
8910 \f
8911 /* Subroutines of finish_objc.  */
8912
8913 static void
8914 generate_classref_translation_entry (tree chain)
8915 {
8916   tree expr, name, decl_specs, decl, sc_spec;
8917   tree type;
8918
8919   type = TREE_TYPE (TREE_PURPOSE (chain));
8920
8921   expr = add_objc_string (TREE_VALUE (chain), class_names);
8922   expr = build_c_cast (type, expr); /* cast! */
8923
8924   name = DECL_NAME (TREE_PURPOSE (chain));
8925
8926   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8927
8928   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8929   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8930
8931   /* The decl that is returned from start_decl is the one that we
8932      forward declared in build_class_reference.  */
8933   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8934   DECL_CONTEXT (decl) = NULL_TREE;
8935   finish_decl (decl, expr, NULL_TREE);
8936   return;
8937 }
8938
8939 static void
8940 handle_class_ref (tree chain)
8941 {
8942   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8943   char *string = (char *) alloca (strlen (name) + 30);
8944   tree decl;
8945   tree exp;
8946
8947   sprintf (string, "%sobjc_class_name_%s",
8948            (flag_next_runtime ? "." : "__"), name);
8949
8950 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8951   if (flag_next_runtime)
8952     {
8953       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8954       return;
8955     }
8956 #endif
8957
8958   /* Make a decl for this name, so we can use its address in a tree.  */
8959   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8960   DECL_EXTERNAL (decl) = 1;
8961   TREE_PUBLIC (decl) = 1;
8962
8963   pushdecl (decl);
8964   rest_of_decl_compilation (decl, 0, 0, 0);
8965
8966   /* Make a decl for the address.  */
8967   sprintf (string, "%sobjc_class_ref_%s",
8968            (flag_next_runtime ? "." : "__"), name);
8969   exp = build1 (ADDR_EXPR, string_type_node, decl);
8970   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8971   DECL_INITIAL (decl) = exp;
8972   TREE_STATIC (decl) = 1;
8973   TREE_USED (decl) = 1;
8974
8975   pushdecl (decl);
8976   rest_of_decl_compilation (decl, 0, 0, 0);
8977 }
8978
8979 static void
8980 handle_impent (struct imp_entry *impent)
8981 {
8982   char *string;
8983
8984   objc_implementation_context = impent->imp_context;
8985   implementation_template = impent->imp_template;
8986
8987   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8988     {
8989       const char *const class_name =
8990         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8991
8992       string = (char *) alloca (strlen (class_name) + 30);
8993
8994       sprintf (string, "%sobjc_class_name_%s",
8995                (flag_next_runtime ? "." : "__"), class_name);
8996     }
8997   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8998     {
8999       const char *const class_name =
9000         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
9001       const char *const class_super_name =
9002         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
9003
9004       string = (char *) alloca (strlen (class_name)
9005                                 + strlen (class_super_name) + 30);
9006
9007       /* Do the same for categories.  Even though no references to
9008          these symbols are generated automatically by the compiler, it
9009          gives you a handle to pull them into an archive by hand.  */
9010       sprintf (string, "*%sobjc_category_name_%s_%s",
9011                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
9012     }
9013   else
9014     return;
9015
9016 #ifdef ASM_DECLARE_CLASS_REFERENCE
9017   if (flag_next_runtime)
9018     {
9019       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9020       return;
9021     }
9022   else
9023 #endif
9024     {
9025       tree decl, init;
9026
9027       init = build_int_2 (0, 0);
9028       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
9029       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9030       TREE_PUBLIC (decl) = 1;
9031       TREE_READONLY (decl) = 1;
9032       TREE_USED (decl) = 1;
9033       TREE_CONSTANT (decl) = 1;
9034       DECL_CONTEXT (decl) = 0;
9035       DECL_ARTIFICIAL (decl) = 1;
9036       DECL_INITIAL (decl) = init;
9037       assemble_variable (decl, 1, 0, 0);
9038     }
9039 }
9040 \f
9041 /* The Fix-and-Countinue functionality available in Mac OS X 10.3 and
9042    later requires that ObjC translation units participating in F&C be
9043    specially marked.  The following routine accomplishes this.  */
9044
9045 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9046
9047 static void
9048 generate_objc_image_info (void)
9049 {
9050   tree sc_spec, decl, initlist;
9051
9052   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
9053   decl
9054    = start_decl (get_identifier ("_OBJC_IMAGE_INFO"),
9055                  tree_cons (NULL_TREE,
9056                             build_array_type
9057                             (integer_type_node,
9058                              build_index_type (build_int_2 (1, 0))),
9059                             sc_spec),
9060                  1,
9061                  NULL_TREE);
9062
9063   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
9064   initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
9065   initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
9066
9067   TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
9068   TREE_CONSTANT (initlist) = TREE_STATIC (initlist) = 1;
9069   finish_decl (decl, initlist, NULL_TREE);
9070 }
9071
9072 /* Look up ID as an instance variable.  */
9073
9074 tree
9075 lookup_objc_ivar (tree id)
9076 {
9077   tree decl;
9078
9079   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
9080     /* We have a message to super.  */
9081     return get_super_receiver ();
9082   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
9083     {
9084       if (is_private (decl))
9085         return 0;
9086       else
9087         return build_ivar_reference (id);
9088     }
9089   else
9090     return 0;
9091 }
9092
9093 #include "gt-objc-objc-act.h"
9094 #include "gtype-objc.h"