OSDN Git Service

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