OSDN Git Service

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