OSDN Git Service

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