OSDN Git Service

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