OSDN Git Service

* c-parse.in (OFFSETOF, offsetof_member_designator): New.
[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   return (TREE_PRIVATE (decl)
6471           && ! is_ivar (CLASS_IVARS (implementation_template),
6472                         DECL_NAME (decl)));
6473 }
6474
6475 /* We have an instance variable reference;, check to see if it is public.  */
6476
6477 int
6478 objc_is_public (tree expr, tree identifier)
6479 {
6480   tree basetype = TREE_TYPE (expr);
6481   enum tree_code code = TREE_CODE (basetype);
6482   tree decl;
6483
6484   if (code == RECORD_TYPE)
6485     {
6486       if (TREE_STATIC_TEMPLATE (basetype))
6487         {
6488           if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6489             {
6490               error ("cannot find interface declaration for `%s'",
6491                      IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6492               return 0;
6493             }
6494
6495           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6496             {
6497               if (TREE_PUBLIC (decl))
6498                 return 1;
6499
6500               /* Important difference between the Stepstone translator:
6501                  all instance variables should be public within the context
6502                  of the implementation.  */
6503               if (objc_implementation_context
6504                   && (((TREE_CODE (objc_implementation_context)
6505                         == CLASS_IMPLEMENTATION_TYPE)
6506                        || (TREE_CODE (objc_implementation_context)
6507                            == CATEGORY_IMPLEMENTATION_TYPE))
6508                       && (CLASS_NAME (objc_implementation_context)
6509                           == OBJC_TYPE_NAME (basetype))))
6510                 {
6511                   int private = is_private (decl);
6512
6513                   if (private)
6514                     error ("instance variable `%s' is declared private",
6515                            IDENTIFIER_POINTER (DECL_NAME (decl)));
6516                   return !private;
6517                 }
6518
6519               /* The 2.95.2 compiler sometimes allowed C functions to access
6520                  non-@public ivars.  We will let this slide for now...  */
6521               if (!objc_method_context)
6522               {
6523                 warning ("instance variable `%s' is %s; "
6524                          "this will be a hard error in the future",
6525                          IDENTIFIER_POINTER (identifier),
6526                          TREE_PRIVATE (decl) ? "@private" : "@protected");
6527                 return 1;
6528               }
6529                 
6530               error ("instance variable `%s' is declared %s",
6531                      IDENTIFIER_POINTER (identifier),
6532                      TREE_PRIVATE (decl) ? "private" : "protected");
6533               return 0;
6534             }
6535         }
6536
6537       else if (objc_implementation_context && (basetype == objc_object_reference))
6538         {
6539           TREE_TYPE (expr) = uprivate_record;
6540           warning ("static access to object of type `id'");
6541         }
6542     }
6543
6544   return 1;
6545 }
6546 \f
6547 /* Make sure all entries in CHAIN are also in LIST.  */
6548
6549 static int
6550 check_methods (tree chain, tree list, int mtype)
6551 {
6552   int first = 1;
6553
6554   while (chain)
6555     {
6556       if (!lookup_method (list, chain))
6557         {
6558           if (first)
6559             {
6560               if (TREE_CODE (objc_implementation_context)
6561                   == CLASS_IMPLEMENTATION_TYPE)
6562                 warning ("incomplete implementation of class `%s'",
6563                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6564               else if (TREE_CODE (objc_implementation_context)
6565                        == CATEGORY_IMPLEMENTATION_TYPE)
6566                 warning ("incomplete implementation of category `%s'",
6567                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6568               first = 0;
6569             }
6570
6571           warning ("method definition for `%c%s' not found",
6572                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6573         }
6574
6575       chain = TREE_CHAIN (chain);
6576     }
6577
6578     return first;
6579 }
6580
6581 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
6582
6583 static int
6584 conforms_to_protocol (tree class, tree protocol)
6585 {
6586    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6587      {
6588        tree p = CLASS_PROTOCOL_LIST (class);
6589        while (p && TREE_VALUE (p) != protocol)
6590          p = TREE_CHAIN (p);
6591
6592        if (!p)
6593          {
6594            tree super = (CLASS_SUPER_NAME (class)
6595                          ? lookup_interface (CLASS_SUPER_NAME (class))
6596                          : NULL_TREE);
6597            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6598            if (!tmp)
6599              return 0;
6600          }
6601      }
6602
6603    return 1;
6604 }
6605
6606 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6607    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
6608
6609 static int
6610 check_methods_accessible (tree chain, tree context, int mtype)
6611 {
6612   int first = 1;
6613   tree list;
6614   tree base_context = context;
6615
6616   while (chain)
6617     {
6618       context = base_context;
6619       while (context)
6620         {
6621           if (mtype == '+')
6622             list = CLASS_CLS_METHODS (context);
6623           else
6624             list = CLASS_NST_METHODS (context);
6625
6626           if (lookup_method (list, chain))
6627               break;
6628
6629           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6630                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6631             context = (CLASS_SUPER_NAME (context)
6632                        ? lookup_interface (CLASS_SUPER_NAME (context))
6633                        : NULL_TREE);
6634
6635           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6636                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6637             context = (CLASS_NAME (context)
6638                        ? lookup_interface (CLASS_NAME (context))
6639                        : NULL_TREE);
6640           else
6641             abort ();
6642         }
6643
6644       if (context == NULL_TREE)
6645         {
6646           if (first)
6647             {
6648               if (TREE_CODE (objc_implementation_context)
6649                   == CLASS_IMPLEMENTATION_TYPE)
6650                 warning ("incomplete implementation of class `%s'",
6651                          IDENTIFIER_POINTER
6652                            (CLASS_NAME (objc_implementation_context)));
6653               else if (TREE_CODE (objc_implementation_context)
6654                        == CATEGORY_IMPLEMENTATION_TYPE)
6655                 warning ("incomplete implementation of category `%s'",
6656                          IDENTIFIER_POINTER
6657                            (CLASS_SUPER_NAME (objc_implementation_context)));
6658               first = 0;
6659             }
6660           warning ("method definition for `%c%s' not found",
6661                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6662         }
6663
6664       chain = TREE_CHAIN (chain); /* next method...  */
6665     }
6666   return first;
6667 }
6668
6669 /* Check whether the current interface (accessible via
6670    'objc_implementation_context') actually implements protocol P, along
6671    with any protocols that P inherits.  */
6672
6673 static void
6674 check_protocol (tree p, const char *type, const char *name)
6675 {
6676   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6677     {
6678       int f1, f2;
6679
6680       /* Ensure that all protocols have bodies!  */
6681       if (warn_protocol)
6682         {
6683           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6684                               CLASS_CLS_METHODS (objc_implementation_context),
6685                               '+');
6686           f2 = check_methods (PROTOCOL_NST_METHODS (p),
6687                               CLASS_NST_METHODS (objc_implementation_context),
6688                               '-');
6689         }
6690       else
6691         {
6692           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6693                                          objc_implementation_context,
6694                                          '+');
6695           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6696                                          objc_implementation_context,
6697                                          '-');
6698         }
6699
6700       if (!f1 || !f2)
6701         warning ("%s `%s' does not fully implement the `%s' protocol",
6702                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6703     }
6704
6705   /* Check protocols recursively.  */
6706   if (PROTOCOL_LIST (p))
6707     {
6708       tree subs = PROTOCOL_LIST (p);
6709       tree super_class =
6710         lookup_interface (CLASS_SUPER_NAME (implementation_template));
6711
6712       while (subs)
6713         {
6714           tree sub = TREE_VALUE (subs);
6715
6716           /* If the superclass does not conform to the protocols
6717              inherited by P, then we must!  */
6718           if (!super_class || !conforms_to_protocol (super_class, sub))
6719             check_protocol (sub, type, name);
6720           subs = TREE_CHAIN (subs);
6721         }
6722     }
6723 }
6724
6725 /* Check whether the current interface (accessible via
6726    'objc_implementation_context') actually implements the protocols listed
6727    in PROTO_LIST.  */
6728
6729 static void
6730 check_protocols (tree proto_list, const char *type, const char *name)
6731 {
6732   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6733     {
6734       tree p = TREE_VALUE (proto_list);
6735
6736       check_protocol (p, type, name);
6737     }
6738 }
6739 \f
6740 /* Make sure that the class CLASS_NAME is defined
6741    CODE says which kind of thing CLASS_NAME ought to be.
6742    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6743    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
6744
6745 tree
6746 start_class (enum tree_code code, tree class_name, tree super_name,
6747              tree protocol_list)
6748 {
6749   tree class, decl;
6750
6751 #ifdef OBJCPLUS
6752   if (current_namespace != global_namespace) {
6753     error ("Objective-C declarations may only appear in global scope");
6754   }
6755 #endif /* OBJCPLUS */
6756
6757   if (objc_implementation_context)
6758     {
6759       warning ("`@end' missing in implementation context");
6760       finish_class (objc_implementation_context);
6761       objc_ivar_chain = NULL_TREE;
6762       objc_implementation_context = NULL_TREE;
6763     }
6764
6765   class = make_node (code);
6766   TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
6767
6768   CLASS_NAME (class) = class_name;
6769   CLASS_SUPER_NAME (class) = super_name;
6770   CLASS_CLS_METHODS (class) = NULL_TREE;
6771
6772   if (! is_class_name (class_name)
6773       && (decl = lookup_name (class_name)))
6774     {
6775       error ("`%s' redeclared as different kind of symbol",
6776              IDENTIFIER_POINTER (class_name));
6777       error ("%Jprevious declaration of '%D'",
6778              decl, decl);
6779     }
6780
6781   if (code == CLASS_IMPLEMENTATION_TYPE)
6782     {
6783       {
6784         tree chain;
6785
6786         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6787            if (TREE_VALUE (chain) == class_name)
6788              {
6789                error ("reimplementation of class `%s'",
6790                       IDENTIFIER_POINTER (class_name));
6791                return error_mark_node;
6792              }
6793         implemented_classes = tree_cons (NULL_TREE, class_name,
6794                                          implemented_classes);
6795       }
6796
6797       /* Reset for multiple classes per file.  */
6798       method_slot = 0;
6799
6800       objc_implementation_context = class;
6801
6802       /* Lookup the interface for this implementation.  */
6803
6804       if (!(implementation_template = lookup_interface (class_name)))
6805         {
6806           warning ("cannot find interface declaration for `%s'",
6807                    IDENTIFIER_POINTER (class_name));
6808           add_class (implementation_template = objc_implementation_context);
6809         }
6810
6811       /* If a super class has been specified in the implementation,
6812          insure it conforms to the one specified in the interface.  */
6813
6814       if (super_name
6815           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6816         {
6817           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6818           const char *const name =
6819             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6820           error ("conflicting super class name `%s'",
6821                  IDENTIFIER_POINTER (super_name));
6822           error ("previous declaration of `%s'", name);
6823         }
6824
6825       else if (! super_name)
6826         {
6827           CLASS_SUPER_NAME (objc_implementation_context)
6828             = CLASS_SUPER_NAME (implementation_template);
6829         }
6830     }
6831
6832   else if (code == CLASS_INTERFACE_TYPE)
6833     {
6834       if (lookup_interface (class_name))
6835 #ifdef OBJCPLUS
6836         error ("duplicate interface declaration for class `%s'",
6837 #else
6838         warning ("duplicate interface declaration for class `%s'",
6839 #endif  
6840         IDENTIFIER_POINTER (class_name));
6841       else
6842         add_class (class);
6843
6844       if (protocol_list)
6845         CLASS_PROTOCOL_LIST (class)
6846           = lookup_and_install_protocols (protocol_list);
6847     }
6848
6849   else if (code == CATEGORY_INTERFACE_TYPE)
6850     {
6851       tree class_category_is_assoc_with;
6852
6853       /* For a category, class_name is really the name of the class that
6854          the following set of methods will be associated with. We must
6855          find the interface so that can derive the objects template.  */
6856
6857       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6858         {
6859           error ("cannot find interface declaration for `%s'",
6860                  IDENTIFIER_POINTER (class_name));
6861           exit (FATAL_EXIT_CODE);
6862         }
6863       else
6864         add_category (class_category_is_assoc_with, class);
6865
6866       if (protocol_list)
6867         CLASS_PROTOCOL_LIST (class)
6868           = lookup_and_install_protocols (protocol_list);
6869     }
6870
6871   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6872     {
6873       /* Reset for multiple classes per file.  */
6874       method_slot = 0;
6875
6876       objc_implementation_context = class;
6877
6878       /* For a category, class_name is really the name of the class that
6879          the following set of methods will be associated with.  We must
6880          find the interface so that can derive the objects template.  */
6881
6882       if (!(implementation_template = lookup_interface (class_name)))
6883         {
6884           error ("cannot find interface declaration for `%s'",
6885                  IDENTIFIER_POINTER (class_name));
6886           exit (FATAL_EXIT_CODE);
6887         }
6888     }
6889   return class;
6890 }
6891
6892 tree
6893 continue_class (tree class)
6894 {
6895   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6896       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6897     {
6898       struct imp_entry *imp_entry;
6899       tree ivar_context;
6900
6901       /* Check consistency of the instance variables.  */
6902
6903       if (CLASS_IVARS (class))
6904         check_ivars (implementation_template, class);
6905
6906       /* code generation */
6907
6908       ivar_context = build_private_template (implementation_template);
6909
6910       if (!objc_class_template)
6911         build_class_template ();
6912
6913       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6914
6915       imp_entry->next = imp_list;
6916       imp_entry->imp_context = class;
6917       imp_entry->imp_template = implementation_template;
6918
6919       synth_forward_declarations ();
6920       imp_entry->class_decl = UOBJC_CLASS_decl;
6921       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6922
6923       /* Append to front and increment count.  */
6924       imp_list = imp_entry;
6925       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6926         imp_count++;
6927       else
6928         cat_count++;
6929
6930       return ivar_context;
6931     }
6932
6933   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6934     {
6935       if (!CLASS_STATIC_TEMPLATE (class))
6936         {
6937           tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6938           finish_struct (record, get_class_ivars (class, 0), NULL_TREE);
6939           CLASS_STATIC_TEMPLATE (class) = record;
6940
6941           /* Mark this record as a class template for static typing.  */
6942           TREE_STATIC_TEMPLATE (record) = 1;
6943         }
6944
6945       return NULL_TREE;
6946     }
6947
6948   else
6949     return error_mark_node;
6950 }
6951
6952 /* This is called once we see the "@end" in an interface/implementation.  */
6953
6954 void
6955 finish_class (tree class)
6956 {
6957   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6958     {
6959       /* All code generation is done in finish_objc.  */
6960
6961       if (implementation_template != objc_implementation_context)
6962         {
6963           /* Ensure that all method listed in the interface contain bodies.  */
6964           check_methods (CLASS_CLS_METHODS (implementation_template),
6965                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6966           check_methods (CLASS_NST_METHODS (implementation_template),
6967                          CLASS_NST_METHODS (objc_implementation_context), '-');
6968
6969           if (CLASS_PROTOCOL_LIST (implementation_template))
6970             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6971                              "class",
6972                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6973         }
6974     }
6975
6976   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6977     {
6978       tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6979
6980       if (category)
6981         {
6982           /* Ensure all method listed in the interface contain bodies.  */
6983           check_methods (CLASS_CLS_METHODS (category),
6984                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6985           check_methods (CLASS_NST_METHODS (category),
6986                          CLASS_NST_METHODS (objc_implementation_context), '-');
6987
6988           if (CLASS_PROTOCOL_LIST (category))
6989             check_protocols (CLASS_PROTOCOL_LIST (category),
6990                              "category",
6991                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6992         }
6993     }
6994
6995   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6996     {
6997       tree decl_specs;
6998       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6999       char *string = (char *) alloca (strlen (class_name) + 3);
7000
7001       /* extern struct objc_object *_<my_name>; */
7002
7003       sprintf (string, "_%s", class_name);
7004
7005       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
7006       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
7007       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
7008                    decl_specs);
7009     }
7010 }
7011
7012 static tree
7013 add_protocol (tree protocol)
7014 {
7015   /* Put protocol on list in reverse order.  */
7016   TREE_CHAIN (protocol) = protocol_chain;
7017   protocol_chain = protocol;
7018   return protocol_chain;
7019 }
7020
7021 static tree
7022 lookup_protocol (tree ident)
7023 {
7024   tree chain;
7025
7026   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7027     if (ident == PROTOCOL_NAME (chain))
7028       return chain;
7029
7030   return NULL_TREE;
7031 }
7032
7033 /* This function forward declares the protocols named by NAMES.  If
7034    they are already declared or defined, the function has no effect.  */
7035
7036 void
7037 objc_declare_protocols (tree names)
7038 {
7039   tree list;
7040
7041 #ifdef OBJCPLUS
7042   if (current_namespace != global_namespace) {
7043     error ("Objective-C declarations may only appear in global scope");
7044   }
7045 #endif /* OBJCPLUS */
7046
7047   for (list = names; list; list = TREE_CHAIN (list))
7048     {
7049       tree name = TREE_VALUE (list);
7050
7051       if (lookup_protocol (name) == NULL_TREE)
7052         {
7053           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7054
7055           TYPE_BINFO (protocol) = make_tree_vec (2);
7056           PROTOCOL_NAME (protocol) = name;
7057           PROTOCOL_LIST (protocol) = NULL_TREE;
7058           add_protocol (protocol);
7059           PROTOCOL_DEFINED (protocol) = 0;
7060           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7061         }
7062     }
7063 }
7064
7065 tree
7066 start_protocol (enum tree_code code, tree name, tree list)
7067 {
7068   tree protocol;
7069
7070 #ifdef OBJCPLUS
7071   if (current_namespace != global_namespace) {
7072     error ("Objective-C declarations may only appear in global scope");
7073   }
7074 #endif /* OBJCPLUS */
7075
7076   /* This is as good a place as any.  Need to invoke
7077      push_tag_toplevel.  */
7078   if (!objc_protocol_template)
7079     objc_protocol_template = build_protocol_template ();
7080
7081   protocol = lookup_protocol (name);
7082
7083   if (!protocol)
7084     {
7085       protocol = make_node (code);
7086       TYPE_BINFO (protocol) = make_tree_vec (2);
7087
7088       PROTOCOL_NAME (protocol) = name;
7089       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7090       add_protocol (protocol);
7091       PROTOCOL_DEFINED (protocol) = 1;
7092       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7093
7094       check_protocol_recursively (protocol, list);
7095     }
7096   else if (! PROTOCOL_DEFINED (protocol))
7097     {
7098       PROTOCOL_DEFINED (protocol) = 1;
7099       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7100
7101       check_protocol_recursively (protocol, list);
7102     }
7103   else
7104     {
7105       warning ("duplicate declaration for protocol `%s'",
7106                IDENTIFIER_POINTER (name));
7107     }
7108   return protocol;
7109 }
7110
7111 void
7112 finish_protocol (tree protocol ATTRIBUTE_UNUSED)
7113 {
7114 }
7115
7116 \f
7117 /* "Encode" a data type into a string, which grows in util_obstack.
7118    ??? What is the FORMAT?  Someone please document this!  */
7119
7120 static void
7121 encode_type_qualifiers (tree declspecs)
7122 {
7123   tree spec;
7124
7125   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7126     {
7127       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
7128         obstack_1grow (&util_obstack, 'r');
7129       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7130         obstack_1grow (&util_obstack, 'n');
7131       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7132         obstack_1grow (&util_obstack, 'N');
7133       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7134         obstack_1grow (&util_obstack, 'o');
7135       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7136         obstack_1grow (&util_obstack, 'O');
7137       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7138         obstack_1grow (&util_obstack, 'R');
7139       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7140         obstack_1grow (&util_obstack, 'V');
7141     }
7142 }
7143
7144 /* Encode a pointer type.  */
7145
7146 static void
7147 encode_pointer (tree type, int curtype, int format)
7148 {
7149   tree pointer_to = TREE_TYPE (type);
7150
7151   if (TREE_CODE (pointer_to) == RECORD_TYPE)
7152     {
7153       if (OBJC_TYPE_NAME (pointer_to)
7154           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7155         {
7156           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7157
7158           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7159             {
7160               obstack_1grow (&util_obstack, '@');
7161               return;
7162             }
7163           else if (TREE_STATIC_TEMPLATE (pointer_to))
7164             {
7165               if (generating_instance_variables)
7166                 {
7167                   obstack_1grow (&util_obstack, '@');
7168                   obstack_1grow (&util_obstack, '"');
7169                   obstack_grow (&util_obstack, name, strlen (name));
7170                   obstack_1grow (&util_obstack, '"');
7171                   return;
7172                 }
7173               else
7174                 {
7175                   obstack_1grow (&util_obstack, '@');
7176                   return;
7177                 }
7178             }
7179           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7180             {
7181               obstack_1grow (&util_obstack, '#');
7182               return;
7183             }
7184           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7185             {
7186               obstack_1grow (&util_obstack, ':');
7187               return;
7188             }
7189         }
7190     }
7191   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7192            && TYPE_MODE (pointer_to) == QImode)
7193     {
7194       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7195                   ? OBJC_TYPE_NAME (pointer_to)
7196                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7197
7198       if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7199         {
7200           obstack_1grow (&util_obstack, '*');
7201           return;
7202         }
7203     }
7204
7205   /* We have a type that does not get special treatment.  */
7206
7207   /* NeXT extension */
7208   obstack_1grow (&util_obstack, '^');
7209   encode_type (pointer_to, curtype, format);
7210 }
7211
7212 static void
7213 encode_array (tree type, int curtype, int format)
7214 {
7215   tree an_int_cst = TYPE_SIZE (type);
7216   tree array_of = TREE_TYPE (type);
7217   char buffer[40];
7218
7219   /* An incomplete array is treated like a pointer.  */
7220   if (an_int_cst == NULL)
7221     {
7222       encode_pointer (type, curtype, format);
7223       return;
7224     }
7225
7226   sprintf (buffer, "[%ld",
7227            (long) (TREE_INT_CST_LOW (an_int_cst)
7228                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7229
7230   obstack_grow (&util_obstack, buffer, strlen (buffer));
7231   encode_type (array_of, curtype, format);
7232   obstack_1grow (&util_obstack, ']');
7233   return;
7234 }
7235 \f
7236 static void
7237 encode_aggregate_within (tree type, int curtype, int format, int left,
7238                          int right)
7239 {
7240   tree name;
7241   /* NB: aggregates that are pointed to have slightly different encoding
7242      rules in that you never encode the names of instance variables.  */
7243   int pointed_to
7244    = (obstack_object_size (&util_obstack) > 0
7245       && *(obstack_next_free (&util_obstack) - 1) == '^');
7246   int inline_contents
7247    = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7248       && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7249
7250   /* Traverse struct aliases; it is important to get the
7251      original struct and its tag name (if any).  */
7252   type = TYPE_MAIN_VARIANT (type);
7253   name = OBJC_TYPE_NAME (type);
7254   /* Open parenth/bracket.  */                          
7255   obstack_1grow (&util_obstack, left);
7256
7257   /* Encode the struct/union tag name, or '?' if a tag was
7258      not provided.  Typedef aliases do not qualify.  */
7259   if (name && TREE_CODE (name) == IDENTIFIER_NODE
7260 #ifdef OBJCPLUS
7261       /* Did this struct have a tag?  */
7262       && !TYPE_WAS_ANONYMOUS (type)
7263 #endif
7264       )
7265     obstack_grow (&util_obstack,
7266                   IDENTIFIER_POINTER (name),
7267                   strlen (IDENTIFIER_POINTER (name)));
7268   else
7269     obstack_1grow (&util_obstack, '?');
7270
7271   /* Encode the types (and possibly names) of the inner fields,
7272      if required.  */
7273   if (inline_contents)
7274     {
7275       tree fields = TYPE_FIELDS (type);
7276
7277       obstack_1grow (&util_obstack, '=');
7278       for (; fields; fields = TREE_CHAIN (fields))
7279         {
7280 #ifdef OBJCPLUS
7281           /* C++ static members, and things that are not fields at all,
7282              should not appear in the encoding.  */
7283           if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7284             continue;
7285 #endif
7286           if (generating_instance_variables && !pointed_to)
7287             {
7288               tree fname = DECL_NAME (fields);
7289
7290               obstack_1grow (&util_obstack, '"');
7291               if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7292                 obstack_grow (&util_obstack,
7293                               IDENTIFIER_POINTER (fname),
7294                               strlen (IDENTIFIER_POINTER (fname)));
7295               obstack_1grow (&util_obstack, '"');
7296             }
7297           encode_field_decl (fields, curtype, format);
7298         }
7299     }
7300   /* Close parenth/bracket.  */                         
7301   obstack_1grow (&util_obstack, right);
7302 }
7303
7304 static void
7305 encode_aggregate (tree type, int curtype, int format)
7306 {
7307   enum tree_code code = TREE_CODE (type);
7308
7309   switch (code)
7310     {
7311     case RECORD_TYPE:
7312       {
7313         encode_aggregate_within (type, curtype, format, '{', '}');
7314         break;
7315       }
7316     case UNION_TYPE:
7317       {
7318         encode_aggregate_within (type, curtype, format, '(', ')');
7319         break;
7320       }
7321
7322     case ENUMERAL_TYPE:
7323       obstack_1grow (&util_obstack, 'i');
7324       break;
7325
7326     default:
7327       break;
7328     }
7329 }
7330
7331 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7332    field type.  */
7333
7334 static void
7335 encode_next_bitfield (int width)
7336 {
7337   char buffer[40];
7338   sprintf (buffer, "b%d", width);
7339   obstack_grow (&util_obstack, buffer, strlen (buffer));
7340 }
7341 \f
7342 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
7343 static void
7344 encode_type (tree type, int curtype, int format)
7345 {
7346   enum tree_code code = TREE_CODE (type);
7347   char c;
7348
7349   if (code == INTEGER_TYPE)
7350     {
7351       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7352         {
7353         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
7354         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
7355         case 32: 
7356           if (type == long_unsigned_type_node
7357               || type == long_integer_type_node)
7358                  c = TYPE_UNSIGNED (type) ? 'L' : 'l';
7359           else
7360                  c = TYPE_UNSIGNED (type) ? 'I' : 'i';
7361           break;
7362         case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
7363         default: abort ();
7364         }
7365       obstack_1grow (&util_obstack, c);
7366     }
7367
7368   else if (code == REAL_TYPE)
7369     {
7370       /* Floating point types.  */
7371       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7372         {
7373         case 32:  c = 'f'; break;
7374         case 64:
7375         case 128: c = 'd'; break;
7376         default: abort ();
7377         }
7378       obstack_1grow (&util_obstack, c);
7379     }
7380
7381   else if (code == VOID_TYPE)
7382     obstack_1grow (&util_obstack, 'v');
7383
7384   else if (code == BOOLEAN_TYPE)
7385     obstack_1grow (&util_obstack, 'B');
7386
7387   else if (code == ARRAY_TYPE)
7388     encode_array (type, curtype, format);
7389
7390   else if (code == POINTER_TYPE)
7391     encode_pointer (type, curtype, format);
7392
7393   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7394     encode_aggregate (type, curtype, format);
7395
7396   else if (code == FUNCTION_TYPE) /* '?' */
7397     obstack_1grow (&util_obstack, '?');
7398 }
7399
7400 static void
7401 encode_gnu_bitfield (int position, tree type, int size)
7402 {
7403   enum tree_code code = TREE_CODE (type);
7404   char buffer[40];
7405   char charType = '?';
7406
7407   if (code == INTEGER_TYPE)
7408     {
7409       if (integer_zerop (TYPE_MIN_VALUE (type)))
7410         {
7411           /* Unsigned integer types.  */
7412
7413           if (TYPE_MODE (type) == QImode)
7414             charType = 'C';
7415           else if (TYPE_MODE (type) == HImode)
7416             charType = 'S';
7417           else if (TYPE_MODE (type) == SImode)
7418             {
7419               if (type == long_unsigned_type_node)
7420                 charType = 'L';
7421               else
7422                 charType = 'I';
7423             }
7424           else if (TYPE_MODE (type) == DImode)
7425             charType = 'Q';
7426         }
7427
7428       else
7429         /* Signed integer types.  */
7430         {
7431           if (TYPE_MODE (type) == QImode)
7432             charType = 'c';
7433           else if (TYPE_MODE (type) == HImode)
7434             charType = 's';
7435           else if (TYPE_MODE (type) == SImode)
7436             {
7437               if (type == long_integer_type_node)
7438                 charType = 'l';
7439               else
7440                 charType = 'i';
7441             }
7442
7443           else if (TYPE_MODE (type) == DImode)
7444             charType = 'q';
7445         }
7446     }
7447   else if (code == ENUMERAL_TYPE)
7448     charType = 'i';
7449   else
7450     abort ();
7451
7452   sprintf (buffer, "b%d%c%d", position, charType, size);
7453   obstack_grow (&util_obstack, buffer, strlen (buffer));
7454 }
7455
7456 static void
7457 encode_field_decl (tree field_decl, int curtype, int format)
7458 {
7459   tree type;
7460
7461 #ifdef OBJCPLUS
7462   /* C++ static members, and things that are not fields at all,
7463      should not appear in the encoding.  */
7464   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7465     return;
7466 #endif
7467
7468   type = TREE_TYPE (field_decl);
7469
7470   /* Generate the bitfield typing information, if needed.  Note the difference
7471      between GNU and NeXT runtimes.  */
7472   if (DECL_BIT_FIELD_TYPE (field_decl))
7473     {
7474       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7475
7476       if (flag_next_runtime)
7477         encode_next_bitfield (size);
7478       else
7479         encode_gnu_bitfield (int_bit_position (field_decl),
7480                                   DECL_BIT_FIELD_TYPE (field_decl), size);
7481     }
7482   else
7483     encode_type (TREE_TYPE (field_decl), curtype, format);
7484 }
7485
7486 static tree
7487 objc_expr_last (tree complex_expr)
7488 {
7489   tree next;
7490
7491   if (complex_expr)
7492     while ((next = TREE_OPERAND (complex_expr, 0)))
7493       complex_expr = next;
7494
7495   return complex_expr;
7496 }
7497
7498 static void
7499 synth_self_and_ucmd_args (void)
7500 {
7501   tree decl_specs;
7502
7503   if (objc_method_context
7504       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7505     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7506   else
7507     /* Really a `struct objc_class *'. However, we allow people to
7508        assign to self, which changes its type midstream.  */
7509     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7510
7511   push_parm_decl (build_tree_list
7512                   (build_tree_list (decl_specs,
7513                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
7514                    unused_list));
7515
7516   decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (selector_type));
7517   push_parm_decl (build_tree_list
7518                   (build_tree_list (decl_specs,
7519                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7520                    unused_list));
7521 }
7522
7523 /* Transform a method definition into a function definition as follows:
7524    - synthesize the first two arguments, "self" and "_cmd".  */
7525
7526 void
7527 start_method_def (tree method)
7528 {
7529   /* Required to implement _msgSuper.  */
7530   objc_method_context = method;
7531   UOBJC_SUPER_decl = NULL_TREE;
7532
7533   /* Must be called BEFORE start_function.  */
7534   push_scope ();
7535   declare_parm_level ();
7536
7537   /* Generate prototype declarations for arguments..."new-style".  */
7538   synth_self_and_ucmd_args ();
7539
7540   /* Generate argument declarations if a keyword_decl.  */
7541   if (METHOD_SEL_ARGS (method))
7542     {
7543       tree arglist = METHOD_SEL_ARGS (method);
7544       do
7545         {
7546           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7547           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7548
7549           if (arg_decl)
7550             {
7551               tree last_expr = objc_expr_last (arg_decl);
7552
7553               /* Unite the abstract decl with its name.  */
7554               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7555               push_parm_decl (build_tree_list
7556                               (build_tree_list (arg_spec, arg_decl),
7557                                NULL_TREE));
7558
7559 #ifndef OBJCPLUS        
7560               /* Unhook: restore the abstract declarator.  */
7561               TREE_OPERAND (last_expr, 0) = NULL_TREE;
7562 #endif  
7563             }
7564
7565           else
7566             push_parm_decl (build_tree_list
7567                             (build_tree_list (arg_spec,
7568                                               KEYWORD_ARG_NAME (arglist)),
7569                              NULL_TREE));
7570
7571           arglist = TREE_CHAIN (arglist);
7572         }
7573       while (arglist);
7574     }
7575
7576   if (METHOD_ADD_ARGS (method) != NULL_TREE
7577       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7578     {
7579       /* We have a variable length selector - in "prototype" format.  */
7580       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7581       while (akey)
7582         {
7583           /* This must be done prior to calling pushdecl.  pushdecl is
7584              going to change our chain on us.  */
7585           tree nextkey = TREE_CHAIN (akey);
7586           pushdecl (akey);
7587           akey = nextkey;
7588         }
7589     }
7590 }
7591
7592 static void
7593 warn_with_method (const char *message, int mtype, tree method)
7594 {
7595   /* Add a readable method name to the warning.  */
7596   warning ("%J%s `%c%s'", method,
7597            message, mtype, gen_method_decl (method, errbuf));
7598 }
7599
7600 /* Return 1 if METHOD is consistent with PROTO.  */
7601
7602 static int
7603 comp_method_with_proto (tree method, tree proto)
7604 {
7605   /* Create a function template node at most once.  */
7606   if (!function1_template)
7607     function1_template = make_node (FUNCTION_TYPE);
7608
7609   /* Install argument types - normally set by build_function_type.  */
7610   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7611
7612   /* install return type */
7613   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7614
7615   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
7616                     false);
7617 }
7618
7619 /* Return 1 if TYPE1 is equivalent to TYPE2.  */
7620
7621 static int
7622 objc_types_are_equivalent (tree type1, tree type2)
7623 {
7624   if (type1 == type2)
7625     return 1;
7626   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7627     return 0;
7628   type1 = TYPE_PROTOCOL_LIST (type1);
7629   type2 = TYPE_PROTOCOL_LIST (type2);
7630   if (list_length (type1) == list_length (type2))
7631     {
7632       for (; type2; type2 = TREE_CHAIN (type2))
7633         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7634           return 0;
7635       return 1;
7636     }
7637   return 0;
7638 }
7639
7640 /* Return 1 if PROTO1 is equivalent to PROTO2.  */
7641
7642 static int
7643 comp_proto_with_proto (tree proto1, tree proto2)
7644 {
7645   tree type1, type2;
7646
7647   /* The following test is needed in case there are hashing
7648      collisions.  */
7649   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7650     return 0;
7651
7652   /* Compare return types.  */
7653   type1 = groktypename (TREE_TYPE (proto1));
7654   type2 = groktypename (TREE_TYPE (proto2));
7655
7656   if (!objc_types_are_equivalent (type1, type2))
7657     return 0;
7658
7659   /* Compare argument types.  */
7660   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7661        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7662        type1 && type2;
7663        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7664     {
7665       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7666         return 0;
7667     }
7668
7669   return (!type1 && !type2);
7670 }
7671
7672 /* - Generate an identifier for the function. the format is "_n_cls",
7673      where 1 <= n <= nMethods, and cls is the name the implementation we
7674      are processing.
7675    - Install the return type from the method declaration.
7676    - If we have a prototype, check for type consistency.  */
7677
7678 static void
7679 really_start_method (tree method, tree parmlist)
7680 {
7681   tree sc_spec, ret_spec, ret_decl, decl_specs;
7682   tree method_decl, method_id;
7683   const char *sel_name, *class_name, *cat_name;
7684   char *buf;
7685
7686   /* Synth the storage class & assemble the return type.  */
7687   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7688   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7689   decl_specs = chainon (sc_spec, ret_spec);
7690
7691   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7692   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7693   cat_name = ((TREE_CODE (objc_implementation_context)
7694                == CLASS_IMPLEMENTATION_TYPE)
7695               ? NULL
7696               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7697   method_slot++;
7698
7699   /* Make sure this is big enough for any plausible method label.  */
7700   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7701                          + (cat_name ? strlen (cat_name) : 0));
7702
7703   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7704                          class_name, cat_name, sel_name, method_slot);
7705
7706   method_id = get_identifier (buf);
7707
7708 #ifdef OBJCPLUS
7709   /* Objective-C methods cannot be overloaded, so we don't need
7710      the type encoding appended.  It looks bad anyway... */
7711   push_lang_context (lang_name_c);
7712 #endif
7713
7714   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7715
7716   /* Check the declarator portion of the return type for the method.  */
7717   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7718     {
7719       /* Unite the complex decl (specified in the abstract decl) with the
7720          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7721       tree save_expr = objc_expr_last (ret_decl);
7722
7723       TREE_OPERAND (save_expr, 0) = method_decl;
7724       method_decl = ret_decl;
7725
7726       /* Fool the parser into thinking it is starting a function.  */
7727       start_function (decl_specs, method_decl, NULL_TREE);
7728
7729       /* Unhook: this has the effect of restoring the abstract declarator.  */
7730       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7731     }
7732
7733   else
7734     {
7735       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7736
7737       /* Fool the parser into thinking it is starting a function.  */
7738       start_function (decl_specs, method_decl, NULL_TREE);
7739
7740       /* Unhook: this has the effect of restoring the abstract declarator.  */
7741       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7742     }
7743
7744 #ifdef OBJCPLUS
7745   /* set self_decl from the first argument...this global is used by
7746    * build_ivar_reference().build_indirect_ref().
7747    */
7748   self_decl = DECL_ARGUMENTS (current_function_decl);
7749
7750   /* snaroff (3/28/96): when compiling with -Wall, this suppresses
7751    * the following: warning:unused parameter `struct objc_selector * _cmd'
7752    */
7753   TREE_USED (self_decl) = 1;
7754   TREE_USED (TREE_CHAIN (self_decl)) = 1;
7755   /* Ditto for the underlying (static) C function.  */
7756   TREE_USED (current_function_decl) = 1;
7757   pop_lang_context ();
7758 #endif
7759
7760   METHOD_DEFINITION (method) = current_function_decl;
7761
7762   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7763
7764   if (implementation_template != objc_implementation_context)
7765     {
7766       tree proto
7767         = lookup_method_static (implementation_template,
7768                                 METHOD_SEL_NAME (method),
7769                                 TREE_CODE (method) == CLASS_METHOD_DECL);
7770
7771       if (proto)
7772         {
7773           if (!comp_method_with_proto (method, proto))
7774             {
7775               char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7776
7777               warn_with_method ("conflicting types for", type, method);
7778               warn_with_method ("previous declaration of", type, proto);
7779             }
7780         }
7781       else
7782         {
7783           /* We have a method @implementation even though we did not
7784              see a corresponding @interface declaration (which is allowed
7785              by Objective-C rules).  Go ahead and place the method in
7786              the @interface anyway, so that message dispatch lookups
7787              will see it.  */
7788           tree interface = implementation_template;
7789
7790           if (TREE_CODE (objc_implementation_context)
7791               == CATEGORY_IMPLEMENTATION_TYPE)
7792             interface = lookup_category
7793                         (interface,
7794                          CLASS_SUPER_NAME (objc_implementation_context));
7795
7796           if (interface)
7797             objc_add_method (interface, copy_node (method),
7798                              TREE_CODE (method) == CLASS_METHOD_DECL);
7799         }
7800     }
7801 }
7802
7803 /* The following routine is always called...this "architecture" is to
7804    accommodate "old-style" variable length selectors.
7805
7806    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7807
7808 void
7809 continue_method_def (void)
7810 {
7811   tree parmlist;
7812
7813   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7814     /* We have a `, ...' immediately following the selector.  */
7815     parmlist = get_parm_info (/*ellipsis=*/true);
7816   else
7817     parmlist = get_parm_info (/*ellipsis=*/false);
7818
7819 #ifndef OBJCPLUS
7820   /* Set self_decl from the first argument...this global is used by
7821      build_ivar_reference calling build_indirect_ref.  */
7822   self_decl = TREE_PURPOSE (parmlist);
7823 #endif /* !OBJCPLUS */
7824
7825   pop_scope ();
7826   really_start_method (objc_method_context, parmlist);
7827   store_parm_decls ();
7828 }
7829
7830 static void *UOBJC_SUPER_scope = 0;
7831
7832 /* _n_Method (id self, SEL sel, ...)
7833      {
7834        struct objc_super _S;
7835        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7836      }  */
7837
7838 tree
7839 get_super_receiver (void)
7840 {
7841   if (objc_method_context)
7842     {
7843       tree super_expr, super_expr_list;
7844
7845       if (!UOBJC_SUPER_decl)
7846       {
7847         UOBJC_SUPER_decl = start_decl (get_identifier (TAG_SUPER),
7848                                        build_tree_list (NULL_TREE,
7849                                        objc_super_template),
7850                                        0, NULL_TREE);
7851         
7852         finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7853
7854         /* This prevents `unused variable' warnings when compiling with -Wall.  */
7855         TREE_USED (UOBJC_SUPER_decl) = 1;
7856         DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7857
7858         UOBJC_SUPER_scope = get_current_scope ();
7859       }
7860
7861       /* Set receiver to self.  */
7862       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7863       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7864       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7865
7866       /* Set class to begin searching.  */
7867 #ifdef OBJCPLUS
7868       super_expr = build_component_ref (UOBJC_SUPER_decl,
7869                                         get_identifier ("super_class"));
7870 #else
7871       super_expr = build_component_ref (UOBJC_SUPER_decl,
7872                                         get_identifier ("class"));
7873 #endif
7874
7875       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7876         {
7877           /* [_cls, __cls]Super are "pre-built" in
7878              synth_forward_declarations.  */
7879
7880           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7881                                           ((TREE_CODE (objc_method_context)
7882                                             == INSTANCE_METHOD_DECL)
7883                                            ? ucls_super_ref
7884                                            : uucls_super_ref));
7885         }
7886
7887       else
7888         /* We have a category.  */
7889         {
7890           tree super_name = CLASS_SUPER_NAME (implementation_template);
7891           tree super_class;
7892
7893           /* Barf if super used in a category of Object.  */
7894           if (!super_name)
7895             {
7896               error ("no super class declared in interface for `%s'",
7897                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7898               return error_mark_node;
7899             }
7900
7901           if (flag_next_runtime && !flag_zero_link)
7902             {
7903               super_class = get_class_reference (super_name);
7904               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7905                 /* If we are in a class method, we must retrieve the
7906                    _metaclass_ for the current class, pointed at by
7907                    the class's "isa" pointer.  The following assumes that
7908                    "isa" is the first ivar in a class (which it must be).  */
7909                 super_class
7910                   = build_indirect_ref
7911                     (build_c_cast (build_pointer_type (objc_class_type),
7912                                    super_class), "unary *");
7913             }
7914           else
7915             {
7916               add_class_reference (super_name);
7917               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7918                              ? objc_get_class_decl : objc_get_meta_class_decl);
7919               assemble_external (super_class);
7920               super_class
7921                 = build_function_call
7922                   (super_class,
7923                    build_tree_list
7924                    (NULL_TREE,
7925                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7926                                      IDENTIFIER_POINTER (super_name))));
7927             }
7928
7929           super_expr
7930             = build_modify_expr (super_expr, NOP_EXPR,
7931                                  build_c_cast (TREE_TYPE (super_expr),
7932                                                super_class));
7933         }
7934
7935       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7936
7937       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7938       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7939
7940       return build_compound_expr (super_expr_list);
7941     }
7942   else
7943     {
7944       error ("[super ...] must appear in a method context");
7945       return error_mark_node;
7946     }
7947 }
7948
7949 /* When exiting a scope, sever links to a 'super' declaration (if any)
7950    therein contained.  */
7951
7952 void
7953 objc_clear_super_receiver (void)
7954 {
7955   if (objc_method_context
7956       && UOBJC_SUPER_scope == get_current_scope ()) {
7957     UOBJC_SUPER_decl = 0;
7958     UOBJC_SUPER_scope = 0;
7959   }
7960 }
7961
7962 static void
7963 objc_expand_function_end (void)
7964 {
7965   /* This routine may also get called for C functions, including those
7966      nested within ObjC methods.  In such cases, method encoding is
7967      meaningless.  */
7968   if (objc_method_context == NULL_TREE
7969       || DECL_INITIAL (objc_method_context) != current_function_decl)
7970     return;
7971
7972   METHOD_ENCODING (objc_method_context)
7973     = encode_method_prototype (objc_method_context);
7974 }
7975
7976 void
7977 finish_method_def (void)
7978 {
7979   lang_expand_function_end = objc_expand_function_end;
7980   /* We cannot validly inline ObjC methods, at least not without a language
7981      extension to declare that a method need not be dynamically
7982      dispatched, so suppress all thoughts of doing so.  */
7983   DECL_INLINE (current_function_decl) = 0;
7984   DECL_UNINLINABLE (current_function_decl) = 1;
7985   current_function_cannot_inline = "methods cannot be inlined";
7986
7987   finish_function ();
7988   lang_expand_function_end = NULL;
7989
7990   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7991      since the optimizer may find "may be used before set" errors.  */
7992   objc_method_context = NULL_TREE;
7993 }
7994
7995 #if 0
7996 int
7997 lang_report_error_function (tree decl)
7998 {
7999   if (objc_method_context)
8000     {
8001       fprintf (stderr, "In method `%s'\n",
8002                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8003       return 1;
8004     }
8005
8006   else
8007     return 0;
8008 }
8009 #endif
8010
8011 static int
8012 is_complex_decl (tree type)
8013 {
8014   return (TREE_CODE (type) == ARRAY_TYPE
8015           || TREE_CODE (type) == FUNCTION_TYPE
8016           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
8017 }
8018
8019 \f
8020 /* Code to convert a decl node into text for a declaration in C.  */
8021
8022 static char tmpbuf[256];
8023
8024 static void
8025 adorn_decl (tree decl, char *str)
8026 {
8027   enum tree_code code = TREE_CODE (decl);
8028
8029   if (code == ARRAY_REF)
8030     {
8031       tree an_int_cst = TREE_OPERAND (decl, 1);
8032
8033       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
8034         sprintf (str + strlen (str), "[%ld]",
8035                  (long) TREE_INT_CST_LOW (an_int_cst));
8036       else
8037         strcat (str, "[]");
8038     }
8039
8040   else if (code == ARRAY_TYPE)
8041     {
8042       tree an_int_cst = TYPE_SIZE (decl);
8043       tree array_of = TREE_TYPE (decl);
8044
8045       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
8046         sprintf (str + strlen (str), "[%ld]",
8047                  (long) (TREE_INT_CST_LOW (an_int_cst)
8048                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
8049       else
8050         strcat (str, "[]");
8051     }
8052
8053   else if (code == CALL_EXPR)
8054     {
8055       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
8056
8057       strcat (str, "(");
8058       while (chain)
8059         {
8060           gen_declaration_1 (chain, str);
8061           chain = TREE_CHAIN (chain);
8062           if (chain)
8063             strcat (str, ", ");
8064         }
8065       strcat (str, ")");
8066     }
8067
8068   else if (code == FUNCTION_TYPE)
8069     {
8070       tree chain  = TYPE_ARG_TYPES (decl);
8071
8072       strcat (str, "(");
8073       while (chain && TREE_VALUE (chain) != void_type_node)
8074         {
8075           gen_declaration_1 (TREE_VALUE (chain), str);
8076           chain = TREE_CHAIN (chain);
8077           if (chain && TREE_VALUE (chain) != void_type_node)
8078             strcat (str, ", ");
8079         }
8080       strcat (str, ")");
8081     }
8082
8083   else if (code == INDIRECT_REF)
8084     {
8085       strcpy (tmpbuf, "*");
8086       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
8087         {
8088           tree chain;
8089
8090           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
8091                chain;
8092                chain = TREE_CHAIN (chain))
8093             {
8094               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
8095                 {
8096                   strcat (tmpbuf, " ");
8097                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
8098                 }
8099             }
8100           if (str[0])
8101             strcat (tmpbuf, " ");
8102         }
8103       strcat (tmpbuf, str);
8104       strcpy (str, tmpbuf);
8105     }
8106
8107   else if (code == POINTER_TYPE)
8108     {
8109       strcpy (tmpbuf, "*");
8110       if (TYPE_READONLY (decl) || TYPE_VOLATILE (decl))
8111         {
8112           if (TYPE_READONLY (decl))
8113             strcat (tmpbuf, " const");
8114           if (TYPE_VOLATILE (decl))
8115             strcat (tmpbuf, " volatile");
8116           if (str[0])
8117             strcat (tmpbuf, " ");
8118         }
8119       strcat (tmpbuf, str);
8120       strcpy (str, tmpbuf);
8121     }
8122 }
8123
8124 static char *
8125 gen_declarator (tree decl, char *buf, const char *name)
8126 {
8127   if (decl)
8128     {
8129       enum tree_code code = TREE_CODE (decl);
8130       char *str;
8131       tree op;
8132       int wrap = 0;
8133
8134       switch (code)
8135         {
8136         case ARRAY_REF:
8137         case INDIRECT_REF:
8138         case CALL_EXPR:
8139           op = TREE_OPERAND (decl, 0);
8140
8141           /* We have a pointer to a function or array...(*)(), (*)[] */
8142           if ((code == ARRAY_REF || code == CALL_EXPR)
8143               && op && TREE_CODE (op) == INDIRECT_REF)
8144             wrap = 1;
8145
8146           str = gen_declarator (op, buf, name);
8147
8148           if (wrap)
8149             {
8150               strcpy (tmpbuf, "(");
8151               strcat (tmpbuf, str);
8152               strcat (tmpbuf, ")");
8153               strcpy (str, tmpbuf);
8154             }
8155
8156           adorn_decl (decl, str);
8157           break;
8158
8159         case ARRAY_TYPE:
8160         case FUNCTION_TYPE:
8161         case POINTER_TYPE:
8162           strcpy (buf, name);
8163           str = buf;
8164
8165           /* This clause is done iteratively rather than recursively.  */
8166           do
8167             {
8168               op = (is_complex_decl (TREE_TYPE (decl))
8169                     ? TREE_TYPE (decl) : NULL_TREE);
8170
8171               adorn_decl (decl, str);
8172
8173               /* We have a pointer to a function or array...(*)(), (*)[] */
8174               if (code == POINTER_TYPE
8175                   && op && (TREE_CODE (op) == FUNCTION_TYPE
8176                             || TREE_CODE (op) == ARRAY_TYPE))
8177                 {
8178                   strcpy (tmpbuf, "(");
8179                   strcat (tmpbuf, str);
8180                   strcat (tmpbuf, ")");
8181                   strcpy (str, tmpbuf);
8182                 }
8183
8184               decl = (is_complex_decl (TREE_TYPE (decl))
8185                       ? TREE_TYPE (decl) : NULL_TREE);
8186             }
8187
8188           while (decl && (code = TREE_CODE (decl)))
8189             ;
8190
8191           break;
8192
8193         case IDENTIFIER_NODE:
8194           /* Will only happen if we are processing a "raw" expr-decl.  */
8195           strcpy (buf, IDENTIFIER_POINTER (decl));
8196           return buf;
8197
8198         default:
8199           abort ();
8200         }
8201
8202       return str;
8203     }
8204
8205   else
8206     /* We have an abstract declarator or a _DECL node.  */
8207     {
8208       strcpy (buf, name);
8209       return buf;
8210     }
8211 }
8212
8213 static void
8214 gen_declspecs (tree declspecs, char *buf, int raw)
8215 {
8216   if (raw)
8217     {
8218       tree chain;
8219
8220       for (chain = nreverse (copy_list (declspecs));
8221            chain; chain = TREE_CHAIN (chain))
8222         {
8223           tree aspec = TREE_VALUE (chain);
8224
8225           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
8226             strcat (buf, IDENTIFIER_POINTER (aspec));
8227           else if (TREE_CODE (aspec) == RECORD_TYPE)
8228             {
8229               if (OBJC_TYPE_NAME (aspec))
8230                 {
8231                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8232
8233                   if (! TREE_STATIC_TEMPLATE (aspec))
8234                     strcat (buf, "struct ");
8235                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8236
8237                   /* NEW!!! */
8238                   if (protocol_list)
8239                     {
8240                       tree chain = protocol_list;
8241
8242                       strcat (buf, " <");
8243                       while (chain)
8244                         {
8245                           strcat (buf,
8246                                   IDENTIFIER_POINTER
8247                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
8248                           chain = TREE_CHAIN (chain);
8249                           if (chain)
8250                             strcat (buf, ", ");
8251                         }
8252                       strcat (buf, ">");
8253                     }
8254                 }
8255
8256               else
8257                 strcat (buf, "untagged struct");
8258             }
8259
8260           else if (TREE_CODE (aspec) == UNION_TYPE)
8261             {
8262               if (OBJC_TYPE_NAME (aspec))
8263                 {
8264                   if (! TREE_STATIC_TEMPLATE (aspec))
8265                     strcat (buf, "union ");
8266                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8267                 }
8268               else
8269                 strcat (buf, "untagged union");
8270             }
8271
8272           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
8273             {
8274               if (OBJC_TYPE_NAME (aspec))
8275                 {
8276                   if (! TREE_STATIC_TEMPLATE (aspec))
8277                     strcat (buf, "enum ");
8278                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8279                 }
8280               else
8281                 strcat (buf, "untagged enum");
8282             }
8283
8284           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
8285             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
8286
8287           else if (IS_ID (aspec))
8288             {
8289               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8290
8291               strcat (buf, "id");
8292               if (protocol_list)
8293                 {
8294                   tree chain = protocol_list;
8295
8296                   strcat (buf, " <");
8297                   while (chain)
8298                     {
8299                       strcat (buf,
8300                               IDENTIFIER_POINTER
8301                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8302                       chain = TREE_CHAIN (chain);
8303                       if (chain)
8304                         strcat (buf, ", ");
8305                     }
8306                   strcat (buf, ">");
8307                 }
8308             }
8309           if (TREE_CHAIN (chain))
8310             strcat (buf, " ");
8311         }
8312     }
8313   else
8314     {
8315       /* Type qualifiers.  */
8316       if (TYPE_READONLY (declspecs))
8317         strcat (buf, "const ");
8318       if (TYPE_VOLATILE (declspecs))
8319         strcat (buf, "volatile ");
8320
8321       switch (TREE_CODE (declspecs))
8322         {
8323           /* Type specifiers.  */
8324
8325         case INTEGER_TYPE:
8326           declspecs = TYPE_MAIN_VARIANT (declspecs);
8327
8328           /* Signed integer types.  */
8329
8330           if (declspecs == short_integer_type_node)
8331             strcat (buf, "short int ");
8332           else if (declspecs == integer_type_node)
8333             strcat (buf, "int ");
8334           else if (declspecs == long_integer_type_node)
8335             strcat (buf, "long int ");
8336           else if (declspecs == long_long_integer_type_node)
8337             strcat (buf, "long long int ");
8338           else if (declspecs == signed_char_type_node
8339                    || declspecs == char_type_node)
8340             strcat (buf, "char ");
8341
8342           /* Unsigned integer types.  */
8343
8344           else if (declspecs == short_unsigned_type_node)
8345             strcat (buf, "unsigned short ");
8346           else if (declspecs == unsigned_type_node)
8347             strcat (buf, "unsigned int ");
8348           else if (declspecs == long_unsigned_type_node)
8349             strcat (buf, "unsigned long ");
8350           else if (declspecs == long_long_unsigned_type_node)
8351             strcat (buf, "unsigned long long ");
8352           else if (declspecs == unsigned_char_type_node)
8353             strcat (buf, "unsigned char ");
8354           break;
8355
8356         case REAL_TYPE:
8357           declspecs = TYPE_MAIN_VARIANT (declspecs);
8358
8359           if (declspecs == float_type_node)
8360             strcat (buf, "float ");
8361           else if (declspecs == double_type_node)
8362             strcat (buf, "double ");
8363           else if (declspecs == long_double_type_node)
8364             strcat (buf, "long double ");
8365           break;
8366
8367         case RECORD_TYPE:
8368           if (OBJC_TYPE_NAME (declspecs)
8369               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8370             {
8371               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8372
8373               if (! TREE_STATIC_TEMPLATE (declspecs))
8374                 strcat (buf, "struct ");
8375               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8376
8377               if (protocol_list)
8378                 {
8379                   tree chain = protocol_list;
8380
8381                   strcat (buf, " <");
8382                   while (chain)
8383                     {
8384                       strcat (buf,
8385                               IDENTIFIER_POINTER
8386                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8387                       chain = TREE_CHAIN (chain);
8388                       if (chain)
8389                         strcat (buf, ", ");
8390                     }
8391                   strcat (buf, ">");
8392                 }
8393             }
8394
8395           else
8396             strcat (buf, "untagged struct");
8397
8398           strcat (buf, " ");
8399           break;
8400
8401         case UNION_TYPE:
8402           if (OBJC_TYPE_NAME (declspecs)
8403               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8404             {
8405               strcat (buf, "union ");
8406               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8407               strcat (buf, " ");
8408             }
8409
8410           else
8411             strcat (buf, "untagged union ");
8412           break;
8413
8414         case ENUMERAL_TYPE:
8415           if (OBJC_TYPE_NAME (declspecs)
8416               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8417             {
8418               strcat (buf, "enum ");
8419               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8420               strcat (buf, " ");
8421             }
8422
8423           else
8424             strcat (buf, "untagged enum ");
8425           break;
8426
8427         case VOID_TYPE:
8428           strcat (buf, "void ");
8429           break;
8430
8431         case POINTER_TYPE:
8432           {
8433             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8434
8435             strcat (buf, "id");
8436             if (protocol_list)
8437               {
8438                 tree chain = protocol_list;
8439
8440                 strcat (buf, " <");
8441                 while (chain)
8442                   {
8443                     strcat (buf,
8444                             IDENTIFIER_POINTER
8445                             (PROTOCOL_NAME (TREE_VALUE (chain))));
8446                     chain = TREE_CHAIN (chain);
8447                     if (chain)
8448                       strcat (buf, ", ");
8449                   }
8450
8451                 strcat (buf, ">");
8452               }
8453           }
8454           break;
8455
8456         default:
8457           break;
8458         }
8459     }
8460 }
8461
8462 /* Given a tree node, produce a printable description of it in the given
8463    buffer, overwriting the buffer.  */
8464
8465 static char *
8466 gen_declaration (tree atype_or_adecl, char *buf)
8467 {
8468   buf[0] = '\0';
8469   gen_declaration_1 (atype_or_adecl, buf);
8470   return buf;
8471 }
8472
8473 /* Given a tree node, append a printable description to the end of the
8474    given buffer.  */
8475
8476 static void
8477 gen_declaration_1 (tree atype_or_adecl, char *buf)
8478 {
8479   char declbuf[256];
8480
8481   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
8482     {
8483       tree declspecs;   /* "identifier_node", "record_type" */
8484       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
8485       tree width = NULL_TREE;   /* for bitfields */
8486
8487       /* We have a "raw", abstract declarator (typename).  */
8488       declarator = TREE_VALUE (atype_or_adecl);
8489       /* In the case of raw ivars, the declarator itself is a list,
8490          and contains bitfield widths.  */
8491       if (declarator && TREE_CODE (declarator) == TREE_LIST)
8492         {
8493           width = TREE_VALUE (declarator);
8494           declarator = TREE_PURPOSE (declarator);
8495         }
8496       declspecs  = TREE_PURPOSE (atype_or_adecl);
8497
8498       gen_declspecs (declspecs, buf, 1);
8499       if (declarator)
8500         {
8501           strcat (buf, " ");
8502           strcat (buf, gen_declarator (declarator, declbuf, ""));
8503         }
8504       if (width)
8505         sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED, 
8506                  TREE_INT_CST_LOW (width));
8507     }
8508
8509   else
8510     {
8511       tree atype;
8512       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
8513       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
8514
8515       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8516           || TREE_CODE (atype_or_adecl) == PARM_DECL
8517           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8518         atype = TREE_TYPE (atype_or_adecl);
8519       else
8520         /* Assume we have a *_type node.  */
8521         atype = atype_or_adecl;
8522
8523       if (is_complex_decl (atype))
8524         {
8525           tree chain;
8526
8527           /* Get the declaration specifier; it is at the end of the list.  */
8528           declarator = chain = atype;
8529           do
8530             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8531           while (is_complex_decl (chain));
8532           declspecs = chain;
8533         }
8534
8535       else
8536         {
8537           declspecs = atype;
8538           declarator = NULL_TREE;
8539         }
8540
8541       gen_declspecs (declspecs, buf, 0);
8542
8543       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8544           || TREE_CODE (atype_or_adecl) == PARM_DECL
8545           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8546         {
8547           const char *const decl_name =
8548             (DECL_NAME (atype_or_adecl)
8549              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8550
8551           if (declarator)
8552             {
8553               strcat (buf, " ");
8554               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8555             }
8556
8557           else if (decl_name[0])
8558             {
8559               strcat (buf, " ");
8560               strcat (buf, decl_name);
8561             }
8562         }
8563       else if (declarator)
8564         {
8565           strcat (buf, " ");
8566           strcat (buf, gen_declarator (declarator, declbuf, ""));
8567         }
8568     }
8569 }
8570
8571 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8572
8573 /* Given a method tree, put a printable description into the given
8574    buffer (overwriting) and return a pointer to the buffer.  */
8575
8576 static char *
8577 gen_method_decl (tree method, char *buf)
8578 {
8579   tree chain;
8580
8581   buf[0] = '\0';
8582   if (RAW_TYPESPEC (method) != objc_object_reference)
8583     {
8584       strcat (buf, "(");
8585       gen_declaration_1 (TREE_TYPE (method), buf);
8586       strcat (buf, ")");
8587     }
8588
8589   chain = METHOD_SEL_ARGS (method);
8590   if (chain)
8591     {
8592       /* We have a chain of keyword_decls.  */
8593       do
8594         {
8595           if (KEYWORD_KEY_NAME (chain))
8596             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8597
8598           strcat (buf, ":");
8599           if (RAW_TYPESPEC (chain) != objc_object_reference)
8600             {
8601               strcat (buf, "(");
8602               gen_declaration_1 (TREE_TYPE (chain), buf);
8603               strcat (buf, ")");
8604             }
8605
8606           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8607           if ((chain = TREE_CHAIN (chain)))
8608             strcat (buf, " ");
8609         }
8610       while (chain);
8611
8612       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8613         strcat (buf, ", ...");
8614       else if (METHOD_ADD_ARGS (method))
8615         {
8616           /* We have a tree list node as generate by get_parm_info.  */
8617           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8618
8619           /* Know we have a chain of parm_decls.  */
8620           while (chain)
8621             {
8622               strcat (buf, ", ");
8623               gen_declaration_1 (chain, buf);
8624               chain = TREE_CHAIN (chain);
8625             }
8626         }
8627     }
8628
8629   else
8630     /* We have a unary selector.  */
8631     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8632
8633   return buf;
8634 }
8635 \f
8636 /* Debug info.  */
8637
8638
8639 /* Dump an @interface declaration of the supplied class CHAIN to the
8640    supplied file FP.  Used to implement the -gen-decls option (which
8641    prints out an @interface declaration of all classes compiled in
8642    this run); potentially useful for debugging the compiler too.  */
8643 static void
8644 dump_interface (FILE *fp, tree chain)
8645 {
8646   /* FIXME: A heap overflow here whenever a method (or ivar)
8647      declaration is so long that it doesn't fit in the buffer.  The
8648      code and all the related functions should be rewritten to avoid
8649      using fixed size buffers.  */
8650   char *buf = (char *) xmalloc (1024 * 10);
8651   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8652   tree ivar_decls = CLASS_RAW_IVARS (chain);
8653   tree nst_methods = CLASS_NST_METHODS (chain);
8654   tree cls_methods = CLASS_CLS_METHODS (chain);
8655
8656   fprintf (fp, "\n@interface %s", my_name);
8657
8658   /* CLASS_SUPER_NAME is used to store the superclass name for
8659      classes, and the category name for categories.  */
8660   if (CLASS_SUPER_NAME (chain))
8661     {
8662       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8663
8664       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8665           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8666         {
8667           fprintf (fp, " (%s)\n", name);
8668         }
8669       else
8670         {
8671           fprintf (fp, " : %s\n", name);
8672         }
8673     }
8674   else
8675     fprintf (fp, "\n");
8676
8677   /* FIXME - the following doesn't seem to work at the moment.  */
8678   if (ivar_decls)
8679     {
8680       fprintf (fp, "{\n");
8681       do
8682         {
8683           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8684           ivar_decls = TREE_CHAIN (ivar_decls);
8685         }
8686       while (ivar_decls);
8687       fprintf (fp, "}\n");
8688     }
8689
8690   while (nst_methods)
8691     {
8692       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8693       nst_methods = TREE_CHAIN (nst_methods);
8694     }
8695
8696   while (cls_methods)
8697     {
8698       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8699       cls_methods = TREE_CHAIN (cls_methods);
8700     }
8701
8702   fprintf (fp, "@end\n");
8703 }
8704
8705 /* Demangle function for Objective-C */
8706 static const char *
8707 objc_demangle (const char *mangled)
8708 {
8709   char *demangled, *cp;
8710
8711   if (mangled[0] == '_' &&
8712       (mangled[1] == 'i' || mangled[1] == 'c') &&
8713       mangled[2] == '_')
8714     {
8715       cp = demangled = xmalloc(strlen(mangled) + 2);
8716       if (mangled[1] == 'i')
8717         *cp++ = '-';            /* for instance method */
8718       else
8719         *cp++ = '+';            /* for class method */
8720       *cp++ = '[';              /* opening left brace */
8721       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8722       while (*cp && *cp == '_')
8723         cp++;                   /* skip any initial underbars in class name */
8724       cp = strchr(cp, '_');     /* find first non-initial underbar */
8725       if (cp == NULL)
8726         {
8727           free(demangled);      /* not mangled name */
8728           return mangled;
8729         }
8730       if (cp[1] == '_')  /* easy case: no category name */
8731         {
8732           *cp++ = ' ';            /* replace two '_' with one ' ' */
8733           strcpy(cp, mangled + (cp - demangled) + 2);
8734         }
8735       else
8736         {
8737           *cp++ = '(';            /* less easy case: category name */
8738           cp = strchr(cp, '_');
8739           if (cp == 0)
8740             {
8741               free(demangled);    /* not mangled name */
8742               return mangled;
8743             }
8744           *cp++ = ')';
8745           *cp++ = ' ';            /* overwriting 1st char of method name... */
8746           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8747         }
8748       while (*cp && *cp == '_')
8749         cp++;                   /* skip any initial underbars in method name */
8750       for (; *cp; cp++)
8751         if (*cp == '_')
8752           *cp = ':';            /* replace remaining '_' with ':' */
8753       *cp++ = ']';              /* closing right brace */
8754       *cp++ = 0;                /* string terminator */
8755       return demangled;
8756     }
8757   else
8758     return mangled;             /* not an objc mangled name */
8759 }
8760
8761 const char *
8762 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8763 {
8764   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8765 }
8766
8767 static void
8768 init_objc (void)
8769 {
8770   gcc_obstack_init (&util_obstack);
8771   util_firstobj = (char *) obstack_finish (&util_obstack);
8772
8773   errbuf = (char *) xmalloc (BUFSIZE);
8774   hash_init ();
8775   synth_module_prologue ();
8776 }
8777 \f
8778 static void
8779 finish_objc (void)
8780 {
8781   struct imp_entry *impent;
8782   tree chain;
8783   /* The internally generated initializers appear to have missing braces.
8784      Don't warn about this.  */
8785   int save_warn_missing_braces = warn_missing_braces;
8786   warn_missing_braces = 0;
8787
8788   /* A missing @end may not be detected by the parser.  */
8789   if (objc_implementation_context)
8790     {
8791       warning ("`@end' missing in implementation context");
8792       finish_class (objc_implementation_context);
8793       objc_ivar_chain = NULL_TREE;
8794       objc_implementation_context = NULL_TREE;
8795     }
8796
8797   /* Process the static instances here because initialization of objc_symtab
8798      depends on them.  */
8799   if (objc_static_instances)
8800     generate_static_references ();
8801
8802   if (imp_list || class_names_chain
8803       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8804     generate_objc_symtab_decl ();
8805
8806   for (impent = imp_list; impent; impent = impent->next)
8807     {
8808       objc_implementation_context = impent->imp_context;
8809       implementation_template = impent->imp_template;
8810
8811       UOBJC_CLASS_decl = impent->class_decl;
8812       UOBJC_METACLASS_decl = impent->meta_decl;
8813
8814       /* Dump the @interface of each class as we compile it, if the
8815          -gen-decls option is in use.  TODO: Dump the classes in the
8816          order they were found, rather than in reverse order as we
8817          are doing now.  */
8818       if (flag_gen_declaration)
8819         {
8820           dump_interface (gen_declaration_file, objc_implementation_context);
8821         }
8822
8823       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8824         {
8825           /* all of the following reference the string pool...  */
8826           generate_ivar_lists ();
8827           generate_dispatch_tables ();
8828           generate_shared_structures ();
8829         }
8830       else
8831         {
8832           generate_dispatch_tables ();
8833           generate_category (objc_implementation_context);
8834         }
8835     }
8836
8837   /* If we are using an array of selectors, we must always
8838      finish up the array decl even if no selectors were used.  */
8839   if (! flag_next_runtime || sel_ref_chain)
8840     build_selector_translation_table ();
8841
8842   if (protocol_chain)
8843     generate_protocols ();
8844
8845   if (flag_replace_objc_classes && imp_list)
8846     generate_objc_image_info ();
8847
8848   if (objc_implementation_context || class_names_chain || objc_static_instances
8849       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8850     {
8851       /* Arrange for ObjC data structures to be initialized at run time.  */
8852       rtx init_sym = build_module_descriptor ();
8853       if (init_sym && targetm.have_ctors_dtors)
8854         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8855     }
8856
8857   /* Dump the class references.  This forces the appropriate classes
8858      to be linked into the executable image, preserving unix archive
8859      semantics.  This can be removed when we move to a more dynamically
8860      linked environment.  */
8861
8862   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8863     {
8864       handle_class_ref (chain);
8865       if (TREE_PURPOSE (chain))
8866         generate_classref_translation_entry (chain);
8867     }
8868
8869   for (impent = imp_list; impent; impent = impent->next)
8870     handle_impent (impent);
8871
8872   /* Dump the string table last.  */
8873
8874   generate_strings ();
8875
8876   if (warn_selector)
8877     {
8878       int slot;
8879       hash hsh;
8880
8881       /* Run through the selector hash tables and print a warning for any
8882          selector which has multiple methods.  */
8883
8884       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8885         {
8886           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8887             check_duplicates (hsh, 0, 1);
8888           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8889             check_duplicates (hsh, 0, 1);
8890         }
8891     }
8892
8893   warn_missing_braces = save_warn_missing_braces;
8894 }
8895 \f
8896 /* Subroutines of finish_objc.  */
8897
8898 static void
8899 generate_classref_translation_entry (tree chain)
8900 {
8901   tree expr, name, decl_specs, decl, sc_spec;
8902   tree type;
8903
8904   type = TREE_TYPE (TREE_PURPOSE (chain));
8905
8906   expr = add_objc_string (TREE_VALUE (chain), class_names);
8907   expr = build_c_cast (type, expr); /* cast! */
8908
8909   name = DECL_NAME (TREE_PURPOSE (chain));
8910
8911   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8912
8913   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8914   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8915
8916   /* The decl that is returned from start_decl is the one that we
8917      forward declared in build_class_reference.  */
8918   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8919   DECL_CONTEXT (decl) = NULL_TREE;
8920   finish_decl (decl, expr, NULL_TREE);
8921   return;
8922 }
8923
8924 static void
8925 handle_class_ref (tree chain)
8926 {
8927   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8928   char *string = (char *) alloca (strlen (name) + 30);
8929   tree decl;
8930   tree exp;
8931
8932   sprintf (string, "%sobjc_class_name_%s",
8933            (flag_next_runtime ? "." : "__"), name);
8934
8935 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8936   if (flag_next_runtime)
8937     {
8938       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8939       return;
8940     }
8941 #endif
8942
8943   /* Make a decl for this name, so we can use its address in a tree.  */
8944   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8945   DECL_EXTERNAL (decl) = 1;
8946   TREE_PUBLIC (decl) = 1;
8947
8948   pushdecl (decl);
8949   rest_of_decl_compilation (decl, 0, 0, 0);
8950
8951   /* Make a decl for the address.  */
8952   sprintf (string, "%sobjc_class_ref_%s",
8953            (flag_next_runtime ? "." : "__"), name);
8954   exp = build1 (ADDR_EXPR, string_type_node, decl);
8955   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8956   DECL_INITIAL (decl) = exp;
8957   TREE_STATIC (decl) = 1;
8958   TREE_USED (decl) = 1;
8959
8960   pushdecl (decl);
8961   rest_of_decl_compilation (decl, 0, 0, 0);
8962 }
8963
8964 static void
8965 handle_impent (struct imp_entry *impent)
8966 {
8967   char *string;
8968
8969   objc_implementation_context = impent->imp_context;
8970   implementation_template = impent->imp_template;
8971
8972   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8973     {
8974       const char *const class_name =
8975         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8976
8977       string = (char *) alloca (strlen (class_name) + 30);
8978
8979       sprintf (string, "%sobjc_class_name_%s",
8980                (flag_next_runtime ? "." : "__"), class_name);
8981     }
8982   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8983     {
8984       const char *const class_name =
8985         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8986       const char *const class_super_name =
8987         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8988
8989       string = (char *) alloca (strlen (class_name)
8990                                 + strlen (class_super_name) + 30);
8991
8992       /* Do the same for categories.  Even though no references to
8993          these symbols are generated automatically by the compiler, it
8994          gives you a handle to pull them into an archive by hand.  */
8995       sprintf (string, "*%sobjc_category_name_%s_%s",
8996                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8997     }
8998   else
8999     return;
9000
9001 #ifdef ASM_DECLARE_CLASS_REFERENCE
9002   if (flag_next_runtime)
9003     {
9004       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9005       return;
9006     }
9007   else
9008 #endif
9009     {
9010       tree decl, init;
9011
9012       init = build_int_2 (0, 0);
9013       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
9014       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9015       TREE_PUBLIC (decl) = 1;
9016       TREE_READONLY (decl) = 1;
9017       TREE_USED (decl) = 1;
9018       TREE_CONSTANT (decl) = 1;
9019       DECL_CONTEXT (decl) = 0;
9020       DECL_ARTIFICIAL (decl) = 1;
9021       DECL_INITIAL (decl) = init;
9022       assemble_variable (decl, 1, 0, 0);
9023     }
9024 }
9025 \f
9026 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
9027    later requires that ObjC translation units participating in F&C be
9028    specially marked.  The following routine accomplishes this.  */
9029
9030 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9031
9032 static void
9033 generate_objc_image_info (void)
9034 {
9035   tree sc_spec, decl, initlist;
9036
9037   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
9038   decl
9039    = start_decl (get_identifier ("_OBJC_IMAGE_INFO"),
9040                  tree_cons (NULL_TREE,
9041                             build_array_type
9042                             (integer_type_node,
9043                              build_index_type (build_int_2 (1, 0))),
9044                             sc_spec),
9045                  1,
9046                  NULL_TREE);
9047
9048   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
9049   initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
9050   initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
9051
9052   TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
9053   TREE_CONSTANT (initlist) = TREE_STATIC (initlist) = 1;
9054   finish_decl (decl, initlist, NULL_TREE);
9055 }
9056
9057 /* Look up ID as an instance variable.  */
9058
9059 tree
9060 lookup_objc_ivar (tree id)
9061 {
9062   tree decl;
9063
9064   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
9065     /* We have a message to super.  */
9066     return get_super_receiver ();
9067   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
9068     {
9069       if (is_private (decl))
9070         return 0;
9071       else
9072         return build_ivar_reference (id);
9073     }
9074   else
9075     return 0;
9076 }
9077
9078 #include "gt-objc-objc-act.h"
9079 #include "gtype-objc.h"