OSDN Git Service

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