OSDN Git Service

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