OSDN Git Service

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