OSDN Git Service

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