OSDN Git Service

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