OSDN Git Service

2005-07-08 Daniel Berlin <dberlin@dberlin.org>
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3    2001, 2002, 2003, 2004, 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 static tree objc_build_volatilized_type (tree);
189
190 #ifdef OBJCPLUS
191 static void objc_generate_cxx_cdtors (void);
192 #endif
193
194 static const char *synth_id_with_class_suffix (const char *, tree);
195
196 /* Hash tables to manage the global pool of method prototypes.  */
197
198 hash *nst_method_hash_list = 0;
199 hash *cls_method_hash_list = 0;
200
201 static hash hash_lookup (hash *, tree);
202 static tree lookup_method (tree, tree);
203 static tree lookup_method_static (tree, tree, int);
204
205 enum string_section
206 {
207   class_names,          /* class, category, protocol, module names */
208   meth_var_names,       /* method and variable names */
209   meth_var_types        /* method and variable type descriptors */
210 };
211
212 static tree add_objc_string (tree, enum string_section);
213 static tree build_objc_string_decl (enum string_section);
214 static void build_selector_table_decl (void);
215
216 /* Protocol additions.  */
217
218 static tree lookup_protocol (tree);
219 static tree lookup_and_install_protocols (tree);
220
221 /* Type encoding.  */
222
223 static void encode_type_qualifiers (tree);
224 static void encode_type (tree, int, int);
225 static void encode_field_decl (tree, int, int);
226
227 #ifdef OBJCPLUS
228 static void really_start_method (tree, tree);
229 #else
230 static void really_start_method (tree, struct c_arg_info *);
231 #endif
232 static int comp_proto_with_proto (tree, tree, int);
233 static void objc_push_parm (tree);
234 #ifdef OBJCPLUS
235 static tree objc_get_parm_info (int);
236 #else
237 static struct c_arg_info *objc_get_parm_info (int);
238 #endif
239
240 /* Utilities for debugging and error diagnostics.  */
241
242 static void warn_with_method (const char *, int, tree);
243 static char *gen_type_name (tree);
244 static char *gen_type_name_0 (tree);
245 static char *gen_method_decl (tree);
246 static char *gen_declaration (tree);
247
248 /* Everything else.  */
249
250 static tree create_field_decl (tree, const char *);
251 static void add_class_reference (tree);
252 static void build_protocol_template (void);
253 static tree encode_method_prototype (tree);
254 static void generate_classref_translation_entry (tree);
255 static void handle_class_ref (tree);
256 static void generate_struct_by_value_array (void)
257      ATTRIBUTE_NORETURN;
258 static void mark_referenced_methods (void);
259 static void generate_objc_image_info (void);
260
261 /*** Private Interface (data) ***/
262
263 /* Reserved tag definitions.  */
264
265 #define OBJECT_TYPEDEF_NAME             "id"
266 #define CLASS_TYPEDEF_NAME              "Class"
267
268 #define TAG_OBJECT                      "objc_object"
269 #define TAG_CLASS                       "objc_class"
270 #define TAG_SUPER                       "objc_super"
271 #define TAG_SELECTOR                    "objc_selector"
272
273 #define UTAG_CLASS                      "_objc_class"
274 #define UTAG_IVAR                       "_objc_ivar"
275 #define UTAG_IVAR_LIST                  "_objc_ivar_list"
276 #define UTAG_METHOD                     "_objc_method"
277 #define UTAG_METHOD_LIST                "_objc_method_list"
278 #define UTAG_CATEGORY                   "_objc_category"
279 #define UTAG_MODULE                     "_objc_module"
280 #define UTAG_SYMTAB                     "_objc_symtab"
281 #define UTAG_SUPER                      "_objc_super"
282 #define UTAG_SELECTOR                   "_objc_selector"
283
284 #define UTAG_PROTOCOL                   "_objc_protocol"
285 #define UTAG_METHOD_PROTOTYPE           "_objc_method_prototype"
286 #define UTAG_METHOD_PROTOTYPE_LIST      "_objc__method_prototype_list"
287
288 /* Note that the string object global name is only needed for the
289    NeXT runtime.  */
290 #define STRING_OBJECT_GLOBAL_FORMAT     "_%sClassReference"
291
292 #define PROTOCOL_OBJECT_CLASS_NAME      "Protocol"
293
294 static const char *TAG_GETCLASS;
295 static const char *TAG_GETMETACLASS;
296 static const char *TAG_MSGSEND;
297 static const char *TAG_MSGSENDSUPER;
298 /* The NeXT Objective-C messenger may have two extra entry points, for use
299    when returning a structure. */
300 static const char *TAG_MSGSEND_STRET;
301 static const char *TAG_MSGSENDSUPER_STRET;
302 static const char *default_constant_string_class_name;
303
304 /* Runtime metadata flags.  */
305 #define CLS_FACTORY                     0x0001L
306 #define CLS_META                        0x0002L
307 #define CLS_HAS_CXX_STRUCTORS           0x2000L
308
309 #define OBJC_MODIFIER_STATIC            0x00000001
310 #define OBJC_MODIFIER_FINAL             0x00000002
311 #define OBJC_MODIFIER_PUBLIC            0x00000004
312 #define OBJC_MODIFIER_PRIVATE           0x00000008
313 #define OBJC_MODIFIER_PROTECTED         0x00000010
314 #define OBJC_MODIFIER_NATIVE            0x00000020
315 #define OBJC_MODIFIER_SYNCHRONIZED      0x00000040
316 #define OBJC_MODIFIER_ABSTRACT          0x00000080
317 #define OBJC_MODIFIER_VOLATILE          0x00000100
318 #define OBJC_MODIFIER_TRANSIENT         0x00000200
319 #define OBJC_MODIFIER_NONE_SPECIFIED    0x80000000
320
321 /* NeXT-specific tags.  */
322
323 #define TAG_MSGSEND_NONNIL              "objc_msgSendNonNil"
324 #define TAG_MSGSEND_NONNIL_STRET        "objc_msgSendNonNil_stret"
325 #define TAG_EXCEPTIONEXTRACT            "objc_exception_extract"
326 #define TAG_EXCEPTIONTRYENTER           "objc_exception_try_enter"
327 #define TAG_EXCEPTIONTRYEXIT            "objc_exception_try_exit"
328 #define TAG_EXCEPTIONMATCH              "objc_exception_match"
329 #define TAG_EXCEPTIONTHROW              "objc_exception_throw"
330 #define TAG_SYNCENTER                   "objc_sync_enter"
331 #define TAG_SYNCEXIT                    "objc_sync_exit"
332 #define TAG_SETJMP                      "_setjmp"
333 #define UTAG_EXCDATA                    "_objc_exception_data"
334
335 #define TAG_ASSIGNIVAR                  "objc_assign_ivar"
336 #define TAG_ASSIGNGLOBAL                "objc_assign_global"
337 #define TAG_ASSIGNSTRONGCAST            "objc_assign_strongCast"
338
339 /* Branch entry points.  All that matters here are the addresses;
340    functions with these names do not really exist in libobjc.  */
341
342 #define TAG_MSGSEND_FAST                "objc_msgSend_Fast"
343 #define TAG_ASSIGNIVAR_FAST             "objc_assign_ivar_Fast"
344
345 #define TAG_CXX_CONSTRUCT               ".cxx_construct"
346 #define TAG_CXX_DESTRUCT                ".cxx_destruct"
347
348 /* GNU-specific tags.  */
349
350 #define TAG_EXECCLASS                   "__objc_exec_class"
351 #define TAG_GNUINIT                     "__objc_gnu_init"
352
353 /* Flags for lookup_method_static().  */
354 #define OBJC_LOOKUP_CLASS       1       /* Look for class methods.  */
355 #define OBJC_LOOKUP_NO_SUPER    2       /* Do not examine superclasses.  */
356
357 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
358 tree objc_global_trees[OCTI_MAX];
359
360 static void handle_impent (struct imp_entry *);
361
362 struct imp_entry *imp_list = 0;
363 int imp_count = 0;      /* `@implementation' */
364 int cat_count = 0;      /* `@category' */
365
366 enum tree_code objc_inherit_code;
367 int objc_public_flag;
368
369 /* Use to generate method labels.  */
370 static int method_slot = 0;
371
372 #define BUFSIZE         1024
373
374 static char *errbuf;    /* Buffer for error diagnostics */
375
376 /* Data imported from tree.c.  */
377
378 extern enum debug_info_type write_symbols;
379
380 /* Data imported from toplev.c.  */
381
382 extern const char *dump_base_name;
383 \f
384 static int flag_typed_selectors;
385
386 /* Store all constructed constant strings in a hash table so that
387    they get uniqued properly.  */
388
389 struct string_descriptor GTY(())
390 {
391   /* The literal argument .  */
392   tree literal;
393
394   /* The resulting constant string.  */
395   tree constructor;
396 };
397
398 static GTY((param_is (struct string_descriptor))) htab_t string_htab;
399
400 /* Store the EH-volatilized types in a hash table, for easy retrieval.  */
401 struct volatilized_type GTY(())
402 {
403   tree type;
404 };
405
406 static GTY((param_is (struct volatilized_type))) htab_t volatilized_htab;
407
408 FILE *gen_declaration_file;
409
410 /* Tells "encode_pointer/encode_aggregate" whether we are generating
411    type descriptors for instance variables (as opposed to methods).
412    Type descriptors for instance variables contain more information
413    than methods (for static typing and embedded structures).  */
414
415 static int generating_instance_variables = 0;
416
417 /* Some platforms pass small structures through registers versus
418    through an invisible pointer.  Determine at what size structure is
419    the transition point between the two possibilities.  */
420
421 static void
422 generate_struct_by_value_array (void)
423 {
424   tree type;
425   tree field_decl, field_decl_chain;
426   int i, j;
427   int aggregate_in_mem[32];
428   int found = 0;
429
430   /* Presumably no platform passes 32 byte structures in a register.  */
431   for (i = 1; i < 32; i++)
432     {
433       char buffer[5];
434
435       /* Create an unnamed struct that has `i' character components */
436       type = start_struct (RECORD_TYPE, NULL_TREE);
437
438       strcpy (buffer, "c1");
439       field_decl = create_field_decl (char_type_node,
440                                       buffer);
441       field_decl_chain = field_decl;
442
443       for (j = 1; j < i; j++)
444         {
445           sprintf (buffer, "c%d", j + 1);
446           field_decl = create_field_decl (char_type_node,
447                                           buffer);
448           chainon (field_decl_chain, field_decl);
449         }
450       finish_struct (type, field_decl_chain, NULL_TREE);
451
452       aggregate_in_mem[i] = aggregate_value_p (type, 0);
453       if (!aggregate_in_mem[i])
454         found = 1;
455     }
456
457   /* We found some structures that are returned in registers instead of memory
458      so output the necessary data.  */
459   if (found)
460     {
461       for (i = 31; i >= 0;  i--)
462         if (!aggregate_in_mem[i])
463           break;
464       printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
465
466       /* The first member of the structure is always 0 because we don't handle
467          structures with 0 members */
468       printf ("static int struct_forward_array[] = {\n  0");
469
470       for (j = 1; j <= i; j++)
471         printf (", %d", aggregate_in_mem[j]);
472       printf ("\n};\n");
473     }
474
475   exit (0);
476 }
477
478 bool
479 objc_init (void)
480 {
481 #ifdef OBJCPLUS
482   if (cxx_init () == false)
483 #else
484   if (c_objc_common_init () == false)
485 #endif
486     return false;
487
488 #ifndef USE_MAPPED_LOCATION
489   /* Force the line number back to 0; check_newline will have
490      raised it to 1, which will make the builtin functions appear
491      not to be built in.  */
492   input_line = 0;
493 #endif
494
495   /* If gen_declaration desired, open the output file.  */
496   if (flag_gen_declaration)
497     {
498       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
499       gen_declaration_file = fopen (dumpname, "w");
500       if (gen_declaration_file == 0)
501         fatal_error ("can't open %s: %m", dumpname);
502       free (dumpname);
503     }
504
505   if (flag_next_runtime)
506     {
507       TAG_GETCLASS = "objc_getClass";
508       TAG_GETMETACLASS = "objc_getMetaClass";
509       TAG_MSGSEND = "objc_msgSend";
510       TAG_MSGSENDSUPER = "objc_msgSendSuper";
511       TAG_MSGSEND_STRET = "objc_msgSend_stret";
512       TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
513       default_constant_string_class_name = "NSConstantString";
514     }
515   else
516     {
517       TAG_GETCLASS = "objc_get_class";
518       TAG_GETMETACLASS = "objc_get_meta_class";
519       TAG_MSGSEND = "objc_msg_lookup";
520       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
521       /* GNU runtime does not provide special functions to support
522          structure-returning methods.  */
523       default_constant_string_class_name = "NXConstantString";
524       flag_typed_selectors = 1;
525     }
526
527   init_objc ();
528
529   if (print_struct_values)
530     generate_struct_by_value_array ();
531
532   return true;
533 }
534
535 void
536 objc_finish_file (void)
537 {
538   mark_referenced_methods ();
539
540 #ifdef OBJCPLUS
541   /* We need to instantiate templates _before_ we emit ObjC metadata;
542      if we do not, some metadata (such as selectors) may go missing.  */
543   at_eof = 1;
544   instantiate_pending_templates (0);
545 #endif
546
547   /* Finalize Objective-C runtime data.  No need to generate tables
548      and code if only checking syntax, or if generating a PCH file.  */
549   if (!flag_syntax_only && !pch_file)
550     finish_objc ();
551
552   if (gen_declaration_file)
553     fclose (gen_declaration_file);
554
555 #ifdef OBJCPLUS
556   cp_finish_file ();
557 #endif
558 }
559 \f
560 /* Return the first occurrence of a method declaration corresponding
561    to sel_name in rproto_list.  Search rproto_list recursively.
562    If is_class is 0, search for instance methods, otherwise for class
563    methods.  */
564 static tree
565 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
566                                 int is_class)
567 {
568    tree rproto, p;
569    tree fnd = 0;
570
571    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
572      {
573         p = TREE_VALUE (rproto);
574
575         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
576           {
577             if ((fnd = lookup_method (is_class
578                                       ? PROTOCOL_CLS_METHODS (p)
579                                       : PROTOCOL_NST_METHODS (p), sel_name)))
580               ;
581             else if (PROTOCOL_LIST (p))
582               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
583                                                     sel_name, is_class);
584           }
585         else
586           {
587             ; /* An identifier...if we could not find a protocol.  */
588           }
589
590         if (fnd)
591           return fnd;
592      }
593
594    return 0;
595 }
596
597 static tree
598 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
599 {
600   tree rproto, p;
601
602   /* Make sure the protocol is supported by the object on the rhs.  */
603   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
604     {
605       tree fnd = 0;
606       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
607         {
608           p = TREE_VALUE (rproto);
609
610           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
611             {
612               if (lproto == p)
613                 fnd = lproto;
614
615               else if (PROTOCOL_LIST (p))
616                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
617             }
618
619           if (fnd)
620             return fnd;
621         }
622     }
623   else
624     {
625       ; /* An identifier...if we could not find a protocol.  */
626     }
627
628   return 0;
629 }
630
631 void
632 objc_start_class_interface (tree class, tree super_class, tree protos)
633 {
634   objc_interface_context
635     = objc_ivar_context
636     = start_class (CLASS_INTERFACE_TYPE, class, super_class, protos);
637   objc_public_flag = 0;
638 }
639
640 void
641 objc_start_category_interface (tree class, tree categ, tree protos)
642 {
643   objc_interface_context
644     = start_class (CATEGORY_INTERFACE_TYPE, class, categ, protos);
645   objc_ivar_chain
646     = continue_class (objc_interface_context);
647 }
648
649 void
650 objc_start_protocol (tree name, tree protos)
651 {
652   objc_interface_context
653     = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
654 }
655
656 void
657 objc_continue_interface (void)
658 {
659   objc_ivar_chain
660     = continue_class (objc_interface_context);
661 }
662
663 void
664 objc_finish_interface (void)
665 {
666   finish_class (objc_interface_context);
667   objc_interface_context = NULL_TREE;
668 }
669
670 void
671 objc_start_class_implementation (tree class, tree super_class)
672 {
673   objc_implementation_context
674     = objc_ivar_context
675     = start_class (CLASS_IMPLEMENTATION_TYPE, class, super_class, NULL_TREE);
676   objc_public_flag = 0;
677 }
678
679 void
680 objc_start_category_implementation (tree class, tree categ)
681 {
682   objc_implementation_context
683     = start_class (CATEGORY_IMPLEMENTATION_TYPE, class, categ, NULL_TREE);
684   objc_ivar_chain
685     = continue_class (objc_implementation_context);
686 }
687
688 void
689 objc_continue_implementation (void)
690 {
691   objc_ivar_chain
692     = continue_class (objc_implementation_context);
693 }
694
695 void
696 objc_finish_implementation (void)
697 {
698 #ifdef OBJCPLUS
699   if (flag_objc_call_cxx_cdtors)
700     objc_generate_cxx_cdtors ();
701 #endif
702
703   if (objc_implementation_context)
704     {
705       finish_class (objc_implementation_context);
706       objc_ivar_chain = NULL_TREE;
707       objc_implementation_context = NULL_TREE;
708     }
709   else
710     warning (0, "%<@end%> must appear in an @implementation context");
711 }
712
713 void
714 objc_set_visibility (int visibility)
715 {
716   objc_public_flag = visibility;
717 }
718
719 void
720 objc_set_method_type (enum tree_code type)
721 {
722   objc_inherit_code = (type == PLUS_EXPR
723                        ? CLASS_METHOD_DECL
724                        : INSTANCE_METHOD_DECL);
725 }
726
727 tree
728 objc_build_method_signature (tree rettype, tree selector,
729                              tree optparms, bool ellipsis)
730 {
731   return build_method_decl (objc_inherit_code, rettype, selector,
732                             optparms, ellipsis);
733 }
734
735 void
736 objc_add_method_declaration (tree decl)
737 {
738   if (!objc_interface_context)
739     fatal_error ("method declaration not in @interface context");
740
741   objc_add_method (objc_interface_context,
742                    decl,
743                    objc_inherit_code == CLASS_METHOD_DECL);
744 }
745
746 void
747 objc_start_method_definition (tree decl)
748 {
749   if (!objc_implementation_context)
750     fatal_error ("method definition not in @implementation context");
751
752   objc_add_method (objc_implementation_context,
753                    decl,
754                    objc_inherit_code == CLASS_METHOD_DECL);
755   start_method_def (decl);
756 }
757
758 void
759 objc_add_instance_variable (tree decl)
760 {
761   (void) add_instance_variable (objc_ivar_context,
762                                 objc_public_flag,
763                                 decl);
764 }
765
766 /* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
767    an '@'.  */
768
769 int
770 objc_is_reserved_word (tree ident)
771 {
772   unsigned char code = C_RID_CODE (ident);
773
774   return (OBJC_IS_AT_KEYWORD (code)
775 #ifdef OBJCPLUS
776           || code == RID_CLASS || code == RID_PUBLIC
777           || code == RID_PROTECTED || code == RID_PRIVATE
778           || code == RID_TRY || code == RID_THROW || code == RID_CATCH
779 #endif
780             );
781 }
782
783 /* Return true if TYPE is 'id'.  */
784
785 static bool
786 objc_is_object_id (tree type)
787 {
788   return OBJC_TYPE_NAME (type) == objc_object_id;
789 }
790
791 static bool
792 objc_is_class_id (tree type)
793 {
794   return OBJC_TYPE_NAME (type) == objc_class_id;
795 }
796
797 /* Construct a C struct with same name as CLASS, a base struct with tag
798    SUPER_NAME (if any), and FIELDS indicated.  */
799
800 static tree
801 objc_build_struct (tree class, tree fields, tree super_name)
802 {
803   tree name = CLASS_NAME (class);
804   tree s = start_struct (RECORD_TYPE, name);
805   tree super = (super_name ? xref_tag (RECORD_TYPE, super_name) : NULL_TREE);
806   tree t, objc_info = NULL_TREE;
807
808   if (super)
809     {
810       /* Prepend a packed variant of the base class into the layout.  This
811          is necessary to preserve ObjC ABI compatibility.  */
812       tree base = build_decl (FIELD_DECL, NULL_TREE, super);
813       tree field = TYPE_FIELDS (super);
814
815       while (field && TREE_CHAIN (field)
816              && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
817         field = TREE_CHAIN (field);
818
819       /* For ObjC ABI purposes, the "packed" size of a base class is the
820          the sum of the offset and the size (in bits) of the last field
821          in the class.  */
822       DECL_SIZE (base)
823         = (field && TREE_CODE (field) == FIELD_DECL
824            ? size_binop (PLUS_EXPR, 
825                          size_binop (PLUS_EXPR,
826                                      size_binop
827                                      (MULT_EXPR,
828                                       convert (bitsizetype,
829                                                DECL_FIELD_OFFSET (field)),
830                                       bitsize_int (BITS_PER_UNIT)),
831                                      DECL_FIELD_BIT_OFFSET (field)),
832                          DECL_SIZE (field))
833            : bitsize_zero_node);
834       DECL_SIZE_UNIT (base)
835         = size_binop (FLOOR_DIV_EXPR, convert (sizetype, DECL_SIZE (base)),
836                       size_int (BITS_PER_UNIT));
837       DECL_ARTIFICIAL (base) = 1;
838       DECL_ALIGN (base) = 1;
839       DECL_FIELD_CONTEXT (base) = s;
840 #ifdef OBJCPLUS
841       DECL_FIELD_IS_BASE (base) = 1;
842
843       if (fields)
844         TREE_NO_WARNING (fields) = 1;   /* Suppress C++ ABI warnings -- we   */
845 #endif                                  /* are following the ObjC ABI here.  */
846       TREE_CHAIN (base) = fields;
847       fields = base;
848     }
849
850   /* NB: Calling finish_struct() may cause type TYPE_LANG_SPECIFIC fields
851      in all variants of this RECORD_TYPE to be clobbered, but it is therein
852      that we store protocol conformance info (e.g., 'NSObject <MyProtocol>').
853      Hence, we must squirrel away the ObjC-specific information before calling
854      finish_struct(), and then reinstate it afterwards.  */
855
856   for (t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t))
857     objc_info
858       = chainon (objc_info,
859                  build_tree_list (NULL_TREE, TYPE_OBJC_INFO (t)));
860
861   /* Point the struct at its related Objective-C class.  */
862   INIT_TYPE_OBJC_INFO (s);
863   TYPE_OBJC_INTERFACE (s) = class;
864
865   s = finish_struct (s, fields, NULL_TREE);
866
867   for (t = TYPE_NEXT_VARIANT (s); t;
868        t = TYPE_NEXT_VARIANT (t), objc_info = TREE_CHAIN (objc_info))
869     {
870       TYPE_OBJC_INFO (t) = TREE_VALUE (objc_info);
871       /* Replace the IDENTIFIER_NODE with an actual @interface.  */
872       TYPE_OBJC_INTERFACE (t) = class;
873     }
874
875   /* Use TYPE_BINFO structures to point at the super class, if any.  */
876   objc_xref_basetypes (s, super);
877
878   /* Mark this struct as a class template.  */
879   CLASS_STATIC_TEMPLATE (class) = s;
880
881   return s;
882 }
883
884 /* Build a type differing from TYPE only in that TYPE_VOLATILE is set.
885    Unlike tree.c:build_qualified_type(), preserve TYPE_LANG_SPECIFIC in the
886    process.  */
887 static tree
888 objc_build_volatilized_type (tree type)
889 {
890   tree t;
891
892   /* Check if we have not constructed the desired variant already.  */
893   for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
894     {
895       /* The type qualifiers must (obviously) match up.  */
896       if (!TYPE_VOLATILE (t)
897           || (TYPE_READONLY (t) != TYPE_READONLY (type))
898           || (TYPE_RESTRICT (t) != TYPE_RESTRICT (type)))
899         continue;
900
901       /* For pointer types, the pointees (and hence their TYPE_LANG_SPECIFIC
902          info, if any) must match up.  */
903       if (POINTER_TYPE_P (t)
904           && (TREE_TYPE (t) != TREE_TYPE (type)))
905         continue;
906
907       /* Everything matches up!  */
908       return t;
909     }
910
911   /* Ok, we could not re-use any of the pre-existing variants.  Create
912      a new one.  */
913   t = build_variant_type_copy (type);
914   TYPE_VOLATILE (t) = 1;
915   
916   return t;
917 }
918
919 /* Mark DECL as being 'volatile' for purposes of Darwin
920    _setjmp()/_longjmp() exception handling.  Called from
921    objc_mark_locals_volatile().  */
922 void
923 objc_volatilize_decl (tree decl)
924 {
925   /* Do not mess with variables that are 'static' or (already)
926      'volatile'.  */
927   if (!TREE_THIS_VOLATILE (decl) && !TREE_STATIC (decl)
928       && (TREE_CODE (decl) == VAR_DECL
929           || TREE_CODE (decl) == PARM_DECL))
930     {
931       tree t = TREE_TYPE (decl);
932       struct volatilized_type key;
933       void **loc;
934
935       t = objc_build_volatilized_type (t);
936       key.type = t;
937       loc = htab_find_slot (volatilized_htab, &key, INSERT);
938
939       if (!*loc)
940         {
941           *loc = ggc_alloc (sizeof (key));
942           ((struct volatilized_type *) *loc)->type = t;
943         }
944
945       TREE_TYPE (decl) = t;
946       TREE_THIS_VOLATILE (decl) = 1;
947       TREE_SIDE_EFFECTS (decl) = 1;
948       DECL_REGISTER (decl) = 0;
949 #ifndef OBJCPLUS
950       C_DECL_REGISTER (decl) = 0;
951 #endif
952     }
953 }
954
955 /* Check if protocol PROTO is adopted (directly or indirectly) by class CLS
956    (including its categoreis and superclasses) or by object type TYP.
957    Issue a warning if PROTO is not adopted anywhere and WARN is set.  */
958
959 static bool
960 objc_lookup_protocol (tree proto, tree cls, tree typ, bool warn)
961 {
962   bool class_type = (cls != NULL_TREE);
963
964   while (cls)
965     {
966       tree c;
967
968       /* Check protocols adopted by the class and its categories.  */
969       for (c = cls; c; c = CLASS_CATEGORY_LIST (c))
970         {
971           if (lookup_protocol_in_reflist (CLASS_PROTOCOL_LIST (c), proto))
972             return true;
973         }
974
975       /* Repeat for superclasses.  */
976       cls = lookup_interface (CLASS_SUPER_NAME (cls));
977     }
978
979   /* Check for any protocols attached directly to the object type.  */
980   if (TYPE_HAS_OBJC_INFO (typ))
981     {
982       if (lookup_protocol_in_reflist (TYPE_OBJC_PROTOCOL_LIST (typ), proto))
983         return true;
984     }
985
986   if (warn)
987     {
988       strcpy (errbuf, class_type ? "class \'" : "type \'");
989       gen_type_name_0 (class_type ? typ : TYPE_POINTER_TO (typ));
990       strcat (errbuf, "\' does not ");
991       /* NB: Types 'id' and 'Class' cannot reasonably be described as
992          "implementing" a given protocol, since they do not have an
993          implementation.  */
994       strcat (errbuf, class_type ? "implement" : "conform to");
995       strcat (errbuf, " the \'");
996       strcat (errbuf, IDENTIFIER_POINTER (PROTOCOL_NAME (proto)));
997       strcat (errbuf, "\' protocol");
998       warning (0, errbuf);
999     }
1000
1001   return false;
1002 }
1003
1004 /* Check if class RCLS and instance struct type RTYP conform to at least the
1005    same protocols that LCLS and LTYP conform to.  */
1006
1007 static bool
1008 objc_compare_protocols (tree lcls, tree ltyp, tree rcls, tree rtyp, bool warn)
1009 {
1010   tree p;
1011   bool have_lproto = false;
1012
1013   while (lcls)
1014     {
1015       /* NB: We do _not_ look at categories defined for LCLS; these may or
1016          may not get loaded in, and therefore it is unreasonable to require
1017          that RCLS/RTYP must implement any of their protocols.  */
1018       for (p = CLASS_PROTOCOL_LIST (lcls); p; p = TREE_CHAIN (p))
1019         {
1020           have_lproto = true;
1021
1022           if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1023             return warn;
1024         }
1025
1026       /* Repeat for superclasses.  */
1027       lcls = lookup_interface (CLASS_SUPER_NAME (lcls));
1028     }
1029
1030   /* Check for any protocols attached directly to the object type.  */
1031   if (TYPE_HAS_OBJC_INFO (ltyp))
1032     {
1033       for (p = TYPE_OBJC_PROTOCOL_LIST (ltyp); p; p = TREE_CHAIN (p))
1034         {
1035           have_lproto = true;
1036
1037           if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1038             return warn;
1039         }
1040     }
1041
1042   /* NB: If LTYP and LCLS have no protocols to search for, return 'true'
1043      vacuously, _unless_ RTYP is a protocol-qualified 'id'.  We can get
1044      away with simply checking for 'id' or 'Class' (!RCLS), since this
1045      routine will not get called in other cases.  */
1046   return have_lproto || (rcls != NULL_TREE);
1047 }
1048
1049 /* Determine if it is permissible to assign (if ARGNO is greater than -3)
1050    an instance of RTYP to an instance of LTYP or to compare the two
1051    (if ARGNO is equal to -3), per ObjC type system rules.  Before
1052    returning 'true', this routine may issue warnings related to, e.g.,
1053    protocol conformance.  When returning 'false', the routine must
1054    produce absolutely no warnings; the C or C++ front-end will do so
1055    instead, if needed.  If either LTYP or RTYP is not an Objective-C type,
1056    the routine must return 'false'.
1057
1058    The ARGNO parameter is encoded as follows:
1059      >= 1       Parameter number (CALLEE contains function being called);
1060      0          Return value;
1061      -1         Assignment;
1062      -2         Initialization;
1063      -3         Comparison (LTYP and RTYP may match in either direction).  */
1064
1065 bool
1066 objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
1067 {
1068   tree lcls, rcls, lproto, rproto;
1069   bool pointers_compatible;
1070
1071   /* We must be dealing with pointer types */
1072   if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
1073     return false;
1074
1075   do
1076     {
1077       ltyp = TREE_TYPE (ltyp);  /* Remove indirections.  */
1078       rtyp = TREE_TYPE (rtyp);
1079     }
1080   while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
1081
1082   /* Past this point, we are only interested in ObjC class instances,
1083      or 'id' or 'Class'.  */
1084   if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
1085     return false;
1086
1087   if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
1088       && !TYPE_HAS_OBJC_INFO (ltyp))
1089     return false;
1090
1091   if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
1092       && !TYPE_HAS_OBJC_INFO (rtyp))
1093     return false;
1094
1095   /* Past this point, we are committed to returning 'true' to the caller.
1096      However, we can still warn about type and/or protocol mismatches.  */
1097
1098   if (TYPE_HAS_OBJC_INFO (ltyp))
1099     {
1100       lcls = TYPE_OBJC_INTERFACE (ltyp);
1101       lproto = TYPE_OBJC_PROTOCOL_LIST (ltyp);
1102     }
1103   else
1104     lcls = lproto = NULL_TREE;
1105
1106   if (TYPE_HAS_OBJC_INFO (rtyp))
1107     {
1108       rcls = TYPE_OBJC_INTERFACE (rtyp);
1109       rproto = TYPE_OBJC_PROTOCOL_LIST (rtyp);
1110     }
1111   else
1112     rcls = rproto = NULL_TREE;
1113
1114   /* If we could not find an @interface declaration, we must have
1115      only seen a @class declaration; for purposes of type comparison,
1116      treat it as a stand-alone (root) class.  */
1117
1118   if (lcls && TREE_CODE (lcls) == IDENTIFIER_NODE)
1119     lcls = NULL_TREE;
1120
1121   if (rcls && TREE_CODE (rcls) == IDENTIFIER_NODE)
1122     rcls = NULL_TREE;
1123
1124   /* If either type is an unqualified 'id', we're done.  */
1125   if ((!lproto && objc_is_object_id (ltyp))
1126       || (!rproto && objc_is_object_id (rtyp)))
1127     return true;
1128
1129   pointers_compatible = (TYPE_MAIN_VARIANT (ltyp) == TYPE_MAIN_VARIANT (rtyp));
1130
1131   /* If the underlying types are the same, and at most one of them has
1132      a protocol list, we do not need to issue any diagnostics.  */
1133   if (pointers_compatible && (!lproto || !rproto))
1134     return true;
1135
1136   /* If exactly one of the types is 'Class', issue a diagnostic; any
1137      exceptions of this rule have already been handled.  */
1138   if (objc_is_class_id (ltyp) ^ objc_is_class_id (rtyp))
1139     pointers_compatible = false;
1140   /* Otherwise, check for inheritance relations.  */
1141   else
1142     {
1143       if (!pointers_compatible)
1144         pointers_compatible
1145           = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp));
1146
1147       if (!pointers_compatible)
1148         pointers_compatible = DERIVED_FROM_P (ltyp, rtyp);
1149
1150       if (!pointers_compatible && argno == -3)
1151         pointers_compatible = DERIVED_FROM_P (rtyp, ltyp);
1152     }
1153
1154   /* If the pointers match modulo protocols, check for protocol conformance
1155      mismatches.  */
1156   if (pointers_compatible)
1157     {
1158       pointers_compatible = objc_compare_protocols (lcls, ltyp, rcls, rtyp,
1159                                                     argno != -3);
1160
1161       if (!pointers_compatible && argno == -3)
1162         pointers_compatible = objc_compare_protocols (rcls, rtyp, lcls, ltyp,
1163                                                       argno != -3);
1164     }
1165
1166   if (!pointers_compatible)
1167     {
1168       /* NB: For the time being, we shall make our warnings look like their
1169          C counterparts.  In the future, we may wish to make them more
1170          ObjC-specific.  */
1171       switch (argno)
1172         {
1173         case -3:
1174           warning (0, "comparison of distinct Objective-C types lacks a cast");
1175           break;
1176
1177         case -2:
1178           warning (0, "initialization from distinct Objective-C type");
1179           break;
1180
1181         case -1:
1182           warning (0, "assignment from distinct Objective-C type");
1183           break;
1184
1185         case 0:
1186           warning (0, "distinct Objective-C type in return");
1187           break;
1188
1189         default:
1190           warning (0, "passing argument %d of %qE from distinct "
1191                    "Objective-C type", argno, callee);
1192           break;
1193         }
1194     }
1195
1196   return true;
1197 }
1198
1199 /* Check if LTYP and RTYP have the same type qualifiers.  If either type
1200    lives in the volatilized hash table, ignore the 'volatile' bit when
1201    making the comparison.  */
1202
1203 bool
1204 objc_type_quals_match (tree ltyp, tree rtyp)
1205 {
1206   int lquals = TYPE_QUALS (ltyp), rquals = TYPE_QUALS (rtyp);
1207   struct volatilized_type key;
1208
1209   key.type = ltyp;
1210
1211   if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
1212     lquals &= ~TYPE_QUAL_VOLATILE;
1213
1214   key.type = rtyp;
1215
1216   if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
1217     rquals &= ~TYPE_QUAL_VOLATILE;
1218
1219   return (lquals == rquals);
1220 }
1221
1222 #ifndef OBJCPLUS
1223 /* Determine if CHILD is derived from PARENT.  The routine assumes that
1224    both parameters are RECORD_TYPEs, and is non-reflexive.  */
1225
1226 static bool
1227 objc_derived_from_p (tree parent, tree child)
1228 {
1229   parent = TYPE_MAIN_VARIANT (parent);
1230
1231   for (child = TYPE_MAIN_VARIANT (child);
1232        TYPE_BINFO (child) && BINFO_N_BASE_BINFOS (TYPE_BINFO (child));)
1233     {
1234       child = TYPE_MAIN_VARIANT (BINFO_TYPE (BINFO_BASE_BINFO
1235                                              (TYPE_BINFO (child),
1236                                               0)));
1237
1238       if (child == parent)
1239         return true;
1240     }
1241
1242   return false;
1243 }
1244 #endif
1245
1246 static tree
1247 objc_build_component_ref (tree datum, tree component)
1248 {
1249   /* If COMPONENT is NULL, the caller is referring to the anonymous
1250      base class field.  */
1251   if (!component)
1252     {
1253       tree base = TYPE_FIELDS (TREE_TYPE (datum));
1254
1255       return build3 (COMPONENT_REF, TREE_TYPE (base), datum, base, NULL_TREE);
1256     }
1257
1258   /* The 'build_component_ref' routine has been removed from the C++
1259      front-end, but 'finish_class_member_access_expr' seems to be
1260      a worthy substitute.  */
1261 #ifdef OBJCPLUS
1262   return finish_class_member_access_expr (datum, component);
1263 #else
1264   return build_component_ref (datum, component);
1265 #endif
1266 }
1267
1268 /* Recursively copy inheritance information rooted at BINFO.  To do this,
1269    we emulate the song and dance performed by cp/tree.c:copy_binfo().  */
1270
1271 static tree
1272 objc_copy_binfo (tree binfo)
1273 {
1274   tree btype = BINFO_TYPE (binfo);
1275   tree binfo2 = make_tree_binfo (BINFO_N_BASE_BINFOS (binfo));
1276   tree base_binfo;
1277   int ix;
1278
1279   BINFO_TYPE (binfo2) = btype;
1280   BINFO_OFFSET (binfo2) = BINFO_OFFSET (binfo);
1281   BINFO_BASE_ACCESSES (binfo2) = BINFO_BASE_ACCESSES (binfo);
1282
1283   /* Recursively copy base binfos of BINFO.  */
1284   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
1285     {
1286       tree base_binfo2 = objc_copy_binfo (base_binfo);
1287
1288       BINFO_INHERITANCE_CHAIN (base_binfo2) = binfo2;
1289       BINFO_BASE_APPEND (binfo2, base_binfo2);
1290     }
1291
1292   return binfo2;
1293 }
1294
1295 /* Record superclass information provided in BASETYPE for ObjC class REF.
1296    This is loosely based on cp/decl.c:xref_basetypes().  */
1297
1298 static void
1299 objc_xref_basetypes (tree ref, tree basetype)
1300 {
1301   tree binfo = make_tree_binfo (basetype ? 1 : 0);
1302
1303   TYPE_BINFO (ref) = binfo;
1304   BINFO_OFFSET (binfo) = size_zero_node;
1305   BINFO_TYPE (binfo) = ref;
1306
1307   if (basetype)
1308     {
1309       tree base_binfo = objc_copy_binfo (TYPE_BINFO (basetype));
1310
1311       BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
1312       BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, 1);
1313       BINFO_BASE_APPEND (binfo, base_binfo);
1314       BINFO_BASE_ACCESS_APPEND (binfo, access_public_node);
1315     }
1316 }
1317
1318 static hashval_t
1319 volatilized_hash (const void *ptr)
1320 {
1321   tree typ = ((struct volatilized_type *)ptr)->type;
1322
1323   return htab_hash_pointer(typ);
1324 }
1325
1326 static int
1327 volatilized_eq (const void *ptr1, const void *ptr2)
1328 {
1329   tree typ1 = ((struct volatilized_type *)ptr1)->type;
1330   tree typ2 = ((struct volatilized_type *)ptr2)->type;
1331
1332   return typ1 == typ2;
1333 }
1334
1335 /* Called from finish_decl.  */
1336
1337 void
1338 objc_check_decl (tree decl)
1339 {
1340   tree type = TREE_TYPE (decl);
1341
1342   if (TREE_CODE (type) != RECORD_TYPE)
1343     return;
1344   if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
1345     error ("statically allocated instance of Objective-C class %qs",
1346            IDENTIFIER_POINTER (type));
1347 }
1348
1349 /* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
1350    either name an Objective-C class, or refer to the special 'id' or 'Class'
1351    types.  If INTERFACE is not a valid ObjC type, just return it unchanged.  */
1352
1353 tree
1354 objc_get_protocol_qualified_type (tree interface, tree protocols)
1355 {
1356   /* If INTERFACE is not provided, default to 'id'.  */
1357   tree type = (interface ? objc_is_id (interface) : objc_object_type);
1358   bool is_ptr = (type != NULL_TREE);
1359
1360   if (!is_ptr)
1361     {
1362       type = objc_is_class_name (interface);
1363
1364       if (type)
1365         type = xref_tag (RECORD_TYPE, type);
1366       else
1367         return interface;
1368     }
1369
1370   if (protocols)
1371     {
1372       type = build_variant_type_copy (type);
1373
1374       /* For pointers (i.e., 'id' or 'Class'), attach the protocol(s)
1375          to the pointee.  */
1376       if (is_ptr)
1377         {
1378           TREE_TYPE (type) = build_variant_type_copy (TREE_TYPE (type));
1379           TYPE_POINTER_TO (TREE_TYPE (type)) = type;
1380           type = TREE_TYPE (type);
1381         }
1382
1383       /* Look up protocols and install in lang specific list.  */
1384       DUP_TYPE_OBJC_INFO (type, TYPE_MAIN_VARIANT (type));
1385       TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols (protocols);
1386
1387       /* For RECORD_TYPEs, point to the @interface; for 'id' and 'Class',
1388          return the pointer to the new pointee variant.  */
1389       if (is_ptr)
1390         type = TYPE_POINTER_TO (type);
1391       else
1392         TYPE_OBJC_INTERFACE (type)
1393           = TYPE_OBJC_INTERFACE (TYPE_MAIN_VARIANT (type));
1394     }
1395
1396   return type;
1397 }
1398
1399 /* Check for circular dependencies in protocols.  The arguments are
1400    PROTO, the protocol to check, and LIST, a list of protocol it
1401    conforms to.  */
1402
1403 static void
1404 check_protocol_recursively (tree proto, tree list)
1405 {
1406   tree p;
1407
1408   for (p = list; p; p = TREE_CHAIN (p))
1409     {
1410       tree pp = TREE_VALUE (p);
1411
1412       if (TREE_CODE (pp) == IDENTIFIER_NODE)
1413         pp = lookup_protocol (pp);
1414
1415       if (pp == proto)
1416         fatal_error ("protocol %qs has circular dependency",
1417                      IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1418       if (pp)
1419         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1420     }
1421 }
1422
1423 /* Look up PROTOCOLS, and return a list of those that are found.
1424    If none are found, return NULL.  */
1425
1426 static tree
1427 lookup_and_install_protocols (tree protocols)
1428 {
1429   tree proto;
1430   tree return_value = NULL_TREE;
1431
1432   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1433     {
1434       tree ident = TREE_VALUE (proto);
1435       tree p = lookup_protocol (ident);
1436
1437       if (!p)
1438         error ("cannot find protocol declaration for %qs",
1439                IDENTIFIER_POINTER (ident));
1440       else
1441         return_value = chainon (return_value,
1442                                 build_tree_list (NULL_TREE, p));
1443     }
1444
1445   return return_value;
1446 }
1447
1448 /* Create a declaration for field NAME of a given TYPE.  */
1449
1450 static tree
1451 create_field_decl (tree type, const char *name)
1452 {
1453   return build_decl (FIELD_DECL, get_identifier (name), type);
1454 }
1455
1456 /* Create a global, static declaration for variable NAME of a given TYPE.  The
1457    finish_var_decl() routine will need to be called on it afterwards.  */
1458
1459 static tree
1460 start_var_decl (tree type, const char *name)
1461 {
1462   tree var = build_decl (VAR_DECL, get_identifier (name), type);
1463
1464   TREE_STATIC (var) = 1;
1465   DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
1466   DECL_IGNORED_P (var) = 1;
1467   DECL_ARTIFICIAL (var) = 1;
1468   DECL_CONTEXT (var) = NULL_TREE;
1469 #ifdef OBJCPLUS
1470   DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
1471 #endif
1472
1473   return var;
1474 }
1475
1476 /* Finish off the variable declaration created by start_var_decl().  */
1477
1478 static void
1479 finish_var_decl (tree var, tree initializer)
1480 {
1481   finish_decl (var, initializer, NULL_TREE);
1482   /* Ensure that the variable actually gets output.  */
1483   mark_decl_referenced (var);
1484   /* Mark the decl to avoid "defined but not used" warning.  */
1485   TREE_USED (var) = 1;
1486 }
1487
1488 /* Find the decl for the constant string class reference.  This is only
1489    used for the NeXT runtime.  */
1490
1491 static tree
1492 setup_string_decl (void)
1493 {
1494   char *name;
1495   size_t length;
1496
1497   /* %s in format will provide room for terminating null */
1498   length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1499            + strlen (constant_string_class_name);
1500   name = xmalloc (length);
1501   sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1502            constant_string_class_name);
1503   constant_string_global_id = get_identifier (name);
1504   string_class_decl = lookup_name (constant_string_global_id);
1505
1506   return string_class_decl;
1507 }
1508
1509 /* Purpose: "play" parser, creating/installing representations
1510    of the declarations that are required by Objective-C.
1511
1512    Model:
1513
1514         type_spec--------->sc_spec
1515         (tree_list)        (tree_list)
1516             |                  |
1517             |                  |
1518         identifier_node    identifier_node  */
1519
1520 static void
1521 synth_module_prologue (void)
1522 {
1523   tree type;
1524   enum debug_info_type save_write_symbols = write_symbols;
1525   const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1526
1527   /* Suppress outputting debug symbols, because
1528      dbxout_init hasn'r been called yet.  */
1529   write_symbols = NO_DEBUG;
1530   debug_hooks = &do_nothing_debug_hooks;
1531
1532 #ifdef OBJCPLUS
1533   push_lang_context (lang_name_c); /* extern "C" */
1534 #endif
1535
1536   /* The following are also defined in <objc/objc.h> and friends.  */
1537
1538   objc_object_id = get_identifier (TAG_OBJECT);
1539   objc_class_id = get_identifier (TAG_CLASS);
1540
1541   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1542   objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
1543   
1544   objc_object_type = build_pointer_type (objc_object_reference);
1545   objc_class_type = build_pointer_type (objc_class_reference);
1546
1547   objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
1548   objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
1549
1550   /* Declare the 'id' and 'Class' typedefs.  */
1551
1552   type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1553                                                 objc_object_name,
1554                                                 objc_object_type));
1555   DECL_IN_SYSTEM_HEADER (type) = 1;
1556   type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1557                                                 objc_class_name,
1558                                                 objc_class_type));
1559   DECL_IN_SYSTEM_HEADER (type) = 1;
1560
1561   /* Forward-declare '@interface Protocol'.  */
1562
1563   type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1564   objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
1565   objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1566                                 type));
1567
1568   /* Declare type of selector-objects that represent an operation name.  */
1569
1570   if (flag_next_runtime)
1571     /* `struct objc_selector *' */
1572     objc_selector_type
1573       = build_pointer_type (xref_tag (RECORD_TYPE,
1574                                       get_identifier (TAG_SELECTOR)));
1575   else
1576     /* `const struct objc_selector *' */
1577     objc_selector_type
1578       = build_pointer_type
1579         (build_qualified_type (xref_tag (RECORD_TYPE,
1580                                          get_identifier (TAG_SELECTOR)),
1581                                TYPE_QUAL_CONST));
1582
1583   /* Declare receiver type used for dispatching messages to 'super'.  */
1584
1585   /* `struct objc_super *' */
1586   objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1587                                                   get_identifier (TAG_SUPER)));
1588
1589   /* Declare pointers to method and ivar lists.  */
1590   objc_method_list_ptr = build_pointer_type
1591                          (xref_tag (RECORD_TYPE,
1592                                     get_identifier (UTAG_METHOD_LIST)));
1593   objc_method_proto_list_ptr
1594     = build_pointer_type (xref_tag (RECORD_TYPE,
1595                                     get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
1596   objc_ivar_list_ptr = build_pointer_type
1597                        (xref_tag (RECORD_TYPE,
1598                                   get_identifier (UTAG_IVAR_LIST)));
1599
1600   if (flag_next_runtime)
1601     {
1602       /* NB: In order to call one of the ..._stret (struct-returning)
1603       functions, the function *MUST* first be cast to a signature that
1604       corresponds to the actual ObjC method being invoked.  This is
1605       what is done by the build_objc_method_call() routine below.  */
1606
1607       /* id objc_msgSend (id, SEL, ...); */
1608       /* id objc_msgSendNonNil (id, SEL, ...); */
1609       /* id objc_msgSend_stret (id, SEL, ...); */
1610       /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1611       type
1612         = build_function_type (objc_object_type,
1613                                tree_cons (NULL_TREE, objc_object_type,
1614                                           tree_cons (NULL_TREE, objc_selector_type,
1615                                                      NULL_TREE)));
1616       umsg_decl = builtin_function (TAG_MSGSEND,
1617                                     type, 0, NOT_BUILT_IN,
1618                                     NULL, NULL_TREE);
1619       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1620                                            type, 0, NOT_BUILT_IN,
1621                                            NULL, NULL_TREE);
1622       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1623                                           type, 0, NOT_BUILT_IN,
1624                                           NULL, NULL_TREE);
1625       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1626                                                  type, 0, NOT_BUILT_IN,
1627                                                  NULL, NULL_TREE);
1628
1629       /* id objc_msgSend_Fast (id, SEL, ...)
1630            __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
1631 #ifdef OFFS_MSGSEND_FAST
1632       umsg_fast_decl = builtin_function (TAG_MSGSEND_FAST,
1633                                          type, 0, NOT_BUILT_IN,
1634                                          NULL, NULL_TREE);
1635       DECL_ATTRIBUTES (umsg_fast_decl) 
1636         = tree_cons (get_identifier ("hard_coded_address"), 
1637                      build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
1638                      NULL_TREE);
1639 #else
1640       /* No direct dispatch availible.  */
1641       umsg_fast_decl = umsg_decl;
1642 #endif
1643
1644       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1645       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1646       type
1647         = build_function_type (objc_object_type,
1648                                tree_cons (NULL_TREE, objc_super_type,
1649                                           tree_cons (NULL_TREE, objc_selector_type,
1650                                                      NULL_TREE)));
1651       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1652                                           type, 0, NOT_BUILT_IN,
1653                                           NULL, NULL_TREE);
1654       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1655                                                 type, 0, NOT_BUILT_IN, 0,
1656                                                 NULL_TREE);
1657     }
1658   else
1659     {
1660       /* GNU runtime messenger entry points.  */
1661
1662       /* typedef id (*IMP)(id, SEL, ...); */
1663       tree IMP_type
1664         = build_pointer_type
1665           (build_function_type (objc_object_type,      
1666                                 tree_cons (NULL_TREE, objc_object_type,      
1667                                            tree_cons (NULL_TREE, objc_selector_type,      
1668                                                       NULL_TREE))));      
1669
1670       /* IMP objc_msg_lookup (id, SEL); */
1671       type
1672         = build_function_type (IMP_type,
1673                                tree_cons (NULL_TREE, objc_object_type,
1674                                           tree_cons (NULL_TREE, objc_selector_type,
1675                                                      OBJC_VOID_AT_END)));
1676       umsg_decl = builtin_function (TAG_MSGSEND,
1677                                     type, 0, NOT_BUILT_IN,
1678                                     NULL, NULL_TREE);
1679
1680       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1681       type
1682         = build_function_type (IMP_type,
1683                                tree_cons (NULL_TREE, objc_super_type,
1684                                           tree_cons (NULL_TREE, objc_selector_type,
1685                                                      OBJC_VOID_AT_END)));
1686       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1687                                           type, 0, NOT_BUILT_IN,
1688                                           NULL, NULL_TREE);
1689
1690       /* The following GNU runtime entry point is called to initialize
1691          each module:
1692
1693          __objc_exec_class (void *); */
1694       type
1695         = build_function_type (void_type_node,
1696                                tree_cons (NULL_TREE, ptr_type_node,
1697                                           OBJC_VOID_AT_END));
1698       execclass_decl = builtin_function (TAG_EXECCLASS,
1699                                          type, 0, NOT_BUILT_IN,
1700                                          NULL, NULL_TREE);
1701     }
1702
1703   /* id objc_getClass (const char *); */
1704
1705   type = build_function_type (objc_object_type,
1706                                    tree_cons (NULL_TREE,
1707                                               const_string_type_node,
1708                                               OBJC_VOID_AT_END));
1709
1710   objc_get_class_decl
1711     = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
1712                         NULL, NULL_TREE);
1713
1714   /* id objc_getMetaClass (const char *); */
1715
1716   objc_get_meta_class_decl
1717     = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1718
1719   build_class_template ();
1720   build_super_template ();
1721   build_protocol_template ();
1722   build_category_template ();
1723   build_objc_exception_stuff ();
1724
1725   if (flag_next_runtime)
1726     build_next_objc_exception_stuff ();
1727
1728   /* static SEL _OBJC_SELECTOR_TABLE[]; */
1729
1730   if (! flag_next_runtime)
1731     build_selector_table_decl ();
1732
1733   /* Forward declare constant_string_id and constant_string_type.  */
1734   if (!constant_string_class_name)
1735     constant_string_class_name = default_constant_string_class_name;
1736
1737   constant_string_id = get_identifier (constant_string_class_name);
1738   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1739
1740   /* Pre-build the following entities - for speed/convenience.  */
1741   self_id = get_identifier ("self");
1742   ucmd_id = get_identifier ("_cmd");
1743
1744 #ifdef OBJCPLUS
1745   pop_lang_context ();
1746 #endif
1747
1748   write_symbols = save_write_symbols;
1749   debug_hooks = save_hooks;
1750 }
1751
1752 /* Ensure that the ivar list for NSConstantString/NXConstantString
1753    (or whatever was specified via `-fconstant-string-class')
1754    contains fields at least as large as the following three, so that
1755    the runtime can stomp on them with confidence:
1756
1757    struct STRING_OBJECT_CLASS_NAME
1758    {
1759      Object isa;
1760      char *cString;
1761      unsigned int length;
1762    }; */
1763
1764 static int
1765 check_string_class_template (void)
1766 {
1767   tree field_decl = objc_get_class_ivars (constant_string_id);
1768
1769 #define AT_LEAST_AS_LARGE_AS(F, T) \
1770   (F && TREE_CODE (F) == FIELD_DECL \
1771      && (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (F))) \
1772          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1773
1774   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1775     return 0;
1776
1777   field_decl = TREE_CHAIN (field_decl);
1778   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1779     return 0;
1780
1781   field_decl = TREE_CHAIN (field_decl);
1782   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1783
1784 #undef AT_LEAST_AS_LARGE_AS
1785 }
1786
1787 /* Avoid calling `check_string_class_template ()' more than once.  */
1788 static GTY(()) int string_layout_checked;
1789
1790 /* Construct an internal string layout to be used as a template for
1791    creating NSConstantString/NXConstantString instances.  */
1792
1793 static tree
1794 objc_build_internal_const_str_type (void)
1795 {
1796   tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1797   tree fields = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
1798   tree field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
1799
1800   TREE_CHAIN (field) = fields; fields = field;
1801   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1802   TREE_CHAIN (field) = fields; fields = field;
1803   /* NB: The finish_builtin_struct() routine expects FIELD_DECLs in
1804      reverse order!  */
1805   finish_builtin_struct (type, "__builtin_ObjCString",
1806                          fields, NULL_TREE);
1807
1808   return type;
1809 }
1810
1811 /* Custom build_string which sets TREE_TYPE!  */
1812
1813 static tree
1814 my_build_string (int len, const char *str)
1815 {
1816   return fix_string_type (build_string (len, str));
1817 }
1818
1819 /* Build a string with contents STR and length LEN and convert it to a
1820    pointer.  */
1821
1822 static tree
1823 my_build_string_pointer (int len, const char *str)
1824 {
1825   tree string = my_build_string (len, str);
1826   tree ptrtype = build_pointer_type (TREE_TYPE (TREE_TYPE (string)));
1827   return build1 (ADDR_EXPR, ptrtype, string);
1828 }
1829
1830 static hashval_t
1831 string_hash (const void *ptr)
1832 {
1833   tree str = ((struct string_descriptor *)ptr)->literal;
1834   const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
1835   int i, len = TREE_STRING_LENGTH (str);
1836   hashval_t h = len;
1837
1838   for (i = 0; i < len; i++)
1839     h = ((h * 613) + p[i]);
1840
1841   return h;
1842 }
1843
1844 static int
1845 string_eq (const void *ptr1, const void *ptr2)
1846 {
1847   tree str1 = ((struct string_descriptor *)ptr1)->literal;
1848   tree str2 = ((struct string_descriptor *)ptr2)->literal;
1849   int len1 = TREE_STRING_LENGTH (str1);
1850
1851   return (len1 == TREE_STRING_LENGTH (str2)
1852           && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
1853                       len1));
1854 }
1855
1856 /* Given a chain of STRING_CST's, build a static instance of
1857    NXConstantString which points at the concatenation of those
1858    strings.  We place the string object in the __string_objects
1859    section of the __OBJC segment.  The Objective-C runtime will
1860    initialize the isa pointers of the string objects to point at the
1861    NXConstantString class object.  */
1862
1863 tree
1864 objc_build_string_object (tree string)
1865 {
1866   tree initlist, constructor, constant_string_class;
1867   int length;
1868   tree fields, addr;
1869   struct string_descriptor *desc, key;
1870   void **loc;
1871
1872   /* Prep the string argument.  */
1873   string = fix_string_type (string);
1874   TREE_SET_CODE (string, STRING_CST);
1875   length = TREE_STRING_LENGTH (string) - 1;
1876
1877   /* Check whether the string class being used actually exists and has the
1878      correct ivar layout.  */
1879   if (!string_layout_checked)
1880     {
1881       string_layout_checked = -1;
1882       constant_string_class = lookup_interface (constant_string_id);
1883       internal_const_str_type = objc_build_internal_const_str_type ();
1884
1885       if (!constant_string_class
1886           || !(constant_string_type
1887                = CLASS_STATIC_TEMPLATE (constant_string_class)))
1888         error ("cannot find interface declaration for %qs",
1889                IDENTIFIER_POINTER (constant_string_id));
1890       /* The NSConstantString/NXConstantString ivar layout is now known.  */
1891       else if (!check_string_class_template ())
1892         error ("interface %qs does not have valid constant string layout",
1893                IDENTIFIER_POINTER (constant_string_id));
1894       /* For the NeXT runtime, we can generate a literal reference
1895          to the string class, don't need to run a constructor.  */
1896       else if (flag_next_runtime && !setup_string_decl ())
1897         error ("cannot find reference tag for class %qs",
1898                IDENTIFIER_POINTER (constant_string_id));
1899       else
1900         {
1901           string_layout_checked = 1;  /* Success!  */
1902           add_class_reference (constant_string_id);
1903         }
1904     }
1905
1906   if (string_layout_checked == -1)
1907     return error_mark_node;
1908
1909   /* Perhaps we already constructed a constant string just like this one? */
1910   key.literal = string;
1911   loc = htab_find_slot (string_htab, &key, INSERT);
1912   desc = *loc;
1913
1914   if (!desc)
1915     {
1916       tree var;
1917       *loc = desc = ggc_alloc (sizeof (*desc));
1918       desc->literal = string;
1919
1920       /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
1921       /* NeXT:   (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length })   */
1922       fields = TYPE_FIELDS (internal_const_str_type);
1923       initlist
1924         = build_tree_list (fields,
1925                            flag_next_runtime
1926                            ? build_unary_op (ADDR_EXPR, string_class_decl, 0)
1927                            : build_int_cst (NULL_TREE, 0));
1928       fields = TREE_CHAIN (fields);
1929       initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1),
1930                             initlist);
1931       fields = TREE_CHAIN (fields);
1932       initlist = tree_cons (fields, build_int_cst (NULL_TREE, length),
1933                             initlist);
1934       constructor = objc_build_constructor (internal_const_str_type,
1935                                             nreverse (initlist));
1936       TREE_INVARIANT (constructor) = true;
1937
1938       if (!flag_next_runtime)
1939         constructor
1940           = objc_add_static_instance (constructor, constant_string_type);
1941       else
1942         {
1943           var = build_decl (CONST_DECL, NULL, TREE_TYPE (constructor));
1944           DECL_INITIAL (var) = constructor;
1945           TREE_STATIC (var) = 1;
1946           pushdecl_top_level (var);
1947           constructor = var;
1948         }
1949       desc->constructor = constructor;
1950     }
1951
1952   addr = convert (build_pointer_type (constant_string_type),
1953                   build_unary_op (ADDR_EXPR, desc->constructor, 1));
1954
1955   return addr;
1956 }
1957
1958 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1959
1960 static GTY(()) int num_static_inst;
1961
1962 static tree
1963 objc_add_static_instance (tree constructor, tree class_decl)
1964 {
1965   tree *chain, decl;
1966   char buf[256];
1967
1968   /* Find the list of static instances for the CLASS_DECL.  Create one if
1969      not found.  */
1970   for (chain = &objc_static_instances;
1971        *chain && TREE_VALUE (*chain) != class_decl;
1972        chain = &TREE_CHAIN (*chain));
1973   if (!*chain)
1974     {
1975       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1976       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1977     }
1978
1979   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1980   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1981   DECL_COMMON (decl) = 1;
1982   TREE_STATIC (decl) = 1;
1983   DECL_ARTIFICIAL (decl) = 1;
1984   DECL_INITIAL (decl) = constructor;
1985
1986   /* We may be writing something else just now.
1987      Postpone till end of input.  */
1988   DECL_DEFER_OUTPUT (decl) = 1;
1989   pushdecl_top_level (decl);
1990   rest_of_decl_compilation (decl, 1, 0);
1991
1992   /* Add the DECL to the head of this CLASS' list.  */
1993   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1994
1995   return decl;
1996 }
1997
1998 /* Build a static constant CONSTRUCTOR
1999    with type TYPE and elements ELTS.  */
2000
2001 static tree
2002 objc_build_constructor (tree type, tree elts)
2003 {
2004   tree constructor = build_constructor (type, elts);
2005
2006   TREE_CONSTANT (constructor) = 1;
2007   TREE_STATIC (constructor) = 1;
2008   TREE_READONLY (constructor) = 1;
2009
2010 #ifdef OBJCPLUS
2011   /* Adjust for impedance mismatch.  We should figure out how to build
2012      CONSTRUCTORs that consistently please both the C and C++ gods.  */
2013   if (!TREE_PURPOSE (elts))
2014     TREE_TYPE (constructor) = NULL_TREE;
2015   TREE_HAS_CONSTRUCTOR (constructor) = 1;
2016 #endif
2017
2018   return constructor;
2019 }
2020 \f
2021 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
2022
2023 /* Predefine the following data type:
2024
2025    struct _objc_symtab
2026    {
2027      long sel_ref_cnt;
2028      SEL *refs;
2029      short cls_def_cnt;
2030      short cat_def_cnt;
2031      void *defs[cls_def_cnt + cat_def_cnt];
2032    }; */
2033
2034 static void
2035 build_objc_symtab_template (void)
2036 {
2037   tree field_decl, field_decl_chain;
2038
2039   objc_symtab_template
2040     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
2041
2042   /* long sel_ref_cnt; */
2043   field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt");
2044   field_decl_chain = field_decl;
2045
2046   /* SEL *refs; */
2047   field_decl = create_field_decl (build_pointer_type (objc_selector_type),
2048                                   "refs");
2049   chainon (field_decl_chain, field_decl);
2050
2051   /* short cls_def_cnt; */
2052   field_decl = create_field_decl (short_integer_type_node, "cls_def_cnt");
2053   chainon (field_decl_chain, field_decl);
2054
2055   /* short cat_def_cnt; */
2056   field_decl = create_field_decl (short_integer_type_node,
2057                                   "cat_def_cnt");
2058   chainon (field_decl_chain, field_decl);
2059
2060   if (imp_count || cat_count || !flag_next_runtime)
2061     {
2062       /* void *defs[imp_count + cat_count (+ 1)]; */
2063       /* NB: The index is one less than the size of the array.  */
2064       int index = imp_count + cat_count
2065                 + (flag_next_runtime? -1: 0);
2066       field_decl = create_field_decl
2067                    (build_array_type
2068                     (ptr_type_node,
2069                      build_index_type (build_int_cst (NULL_TREE, index))),
2070                     "defs");
2071       chainon (field_decl_chain, field_decl);
2072     }
2073
2074   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
2075 }
2076
2077 /* Create the initial value for the `defs' field of _objc_symtab.
2078    This is a CONSTRUCTOR.  */
2079
2080 static tree
2081 init_def_list (tree type)
2082 {
2083   tree expr, initlist = NULL_TREE;
2084   struct imp_entry *impent;
2085
2086   if (imp_count)
2087     for (impent = imp_list; impent; impent = impent->next)
2088       {
2089         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2090           {
2091             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
2092             initlist = tree_cons (NULL_TREE, expr, initlist);
2093           }
2094       }
2095
2096   if (cat_count)
2097     for (impent = imp_list; impent; impent = impent->next)
2098       {
2099         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2100           {
2101             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
2102             initlist = tree_cons (NULL_TREE, expr, initlist);
2103           }
2104       }
2105
2106   if (!flag_next_runtime)
2107     {
2108       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
2109       tree expr;
2110
2111       if (static_instances_decl)
2112         expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
2113       else
2114         expr = build_int_cst (NULL_TREE, 0);
2115
2116       initlist = tree_cons (NULL_TREE, expr, initlist);
2117     }
2118
2119   return objc_build_constructor (type, nreverse (initlist));
2120 }
2121
2122 /* Construct the initial value for all of _objc_symtab.  */
2123
2124 static tree
2125 init_objc_symtab (tree type)
2126 {
2127   tree initlist;
2128
2129   /* sel_ref_cnt = { ..., 5, ... } */
2130
2131   initlist = build_tree_list (NULL_TREE,
2132                               build_int_cst (long_integer_type_node, 0));
2133
2134   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2135
2136   if (flag_next_runtime || ! sel_ref_chain)
2137     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2138   else
2139     initlist
2140       = tree_cons (NULL_TREE,
2141                    convert (build_pointer_type (objc_selector_type),
2142                             build_unary_op (ADDR_EXPR,
2143                                             UOBJC_SELECTOR_TABLE_decl, 1)),
2144                    initlist);
2145
2146   /* cls_def_cnt = { ..., 5, ... } */
2147
2148   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
2149
2150   /* cat_def_cnt = { ..., 5, ... } */
2151
2152   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
2153
2154   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2155
2156   if (imp_count || cat_count || !flag_next_runtime)
2157     {
2158
2159       tree field = TYPE_FIELDS (type);
2160       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
2161
2162       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
2163                             initlist);
2164     }
2165
2166   return objc_build_constructor (type, nreverse (initlist));
2167 }
2168
2169 /* Generate forward declarations for metadata such as
2170   'OBJC_CLASS_...'.  */
2171
2172 static tree
2173 build_metadata_decl (const char *name, tree type)
2174 {
2175   tree decl;
2176
2177   /* struct TYPE NAME_<name>; */
2178   decl = start_var_decl (type, synth_id_with_class_suffix
2179                                (name,
2180                                 objc_implementation_context));
2181
2182   return decl;
2183 }
2184
2185 /* Push forward-declarations of all the categories so that
2186    init_def_list can use them in a CONSTRUCTOR.  */
2187
2188 static void
2189 forward_declare_categories (void)
2190 {
2191   struct imp_entry *impent;
2192   tree sav = objc_implementation_context;
2193
2194   for (impent = imp_list; impent; impent = impent->next)
2195     {
2196       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2197         {
2198           /* Set an invisible arg to synth_id_with_class_suffix.  */
2199           objc_implementation_context = impent->imp_context;
2200           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
2201           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
2202                                                     objc_category_template);
2203         }
2204     }
2205   objc_implementation_context = sav;
2206 }
2207
2208 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2209    and initialized appropriately.  */
2210
2211 static void
2212 generate_objc_symtab_decl (void)
2213 {
2214   /* forward declare categories */
2215   if (cat_count)
2216     forward_declare_categories ();
2217
2218   build_objc_symtab_template ();
2219   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2220   finish_var_decl (UOBJC_SYMBOLS_decl,
2221                    init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2222 }
2223 \f
2224 static tree
2225 init_module_descriptor (tree type)
2226 {
2227   tree initlist, expr;
2228
2229   /* version = { 1, ... } */
2230
2231   expr = build_int_cst (long_integer_type_node, OBJC_VERSION);
2232   initlist = build_tree_list (NULL_TREE, expr);
2233
2234   /* size = { ..., sizeof (struct _objc_module), ... } */
2235
2236   expr = convert (long_integer_type_node,
2237                   size_in_bytes (objc_module_template));
2238   initlist = tree_cons (NULL_TREE, expr, initlist);
2239
2240   /* name = { ..., "foo.m", ... } */
2241
2242   expr = add_objc_string (get_identifier (input_filename), class_names);
2243   initlist = tree_cons (NULL_TREE, expr, initlist);
2244
2245   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
2246
2247   if (UOBJC_SYMBOLS_decl)
2248     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
2249   else
2250     expr = build_int_cst (NULL_TREE, 0);
2251   initlist = tree_cons (NULL_TREE, expr, initlist);
2252
2253   return objc_build_constructor (type, nreverse (initlist));
2254 }
2255
2256 /* Write out the data structures to describe Objective C classes defined.
2257
2258    struct _objc_module { ... } _OBJC_MODULE = { ... };   */
2259
2260 static void
2261 build_module_descriptor (void)
2262 {
2263   tree field_decl, field_decl_chain;
2264
2265 #ifdef OBJCPLUS
2266   push_lang_context (lang_name_c); /* extern "C" */
2267 #endif
2268
2269   objc_module_template
2270     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
2271
2272   /* long version; */
2273   field_decl = create_field_decl (long_integer_type_node, "version");
2274   field_decl_chain = field_decl;
2275
2276   /* long size; */
2277   field_decl = create_field_decl (long_integer_type_node, "size");
2278   chainon (field_decl_chain, field_decl);
2279
2280   /* char *name; */
2281   field_decl = create_field_decl (string_type_node, "name");
2282   chainon (field_decl_chain, field_decl);
2283
2284   /* struct _objc_symtab *symtab; */
2285   field_decl
2286     = create_field_decl (build_pointer_type
2287                          (xref_tag (RECORD_TYPE,
2288                                     get_identifier (UTAG_SYMTAB))),
2289                          "symtab");
2290   chainon (field_decl_chain, field_decl);
2291
2292   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
2293
2294   /* Create an instance of "_objc_module".  */
2295   UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
2296   finish_var_decl (UOBJC_MODULES_decl,
2297                    init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
2298
2299 #ifdef OBJCPLUS
2300   pop_lang_context ();
2301 #endif
2302 }
2303
2304 /* The GNU runtime requires us to provide a static initializer function
2305    for each module:
2306
2307    static void __objc_gnu_init (void) {
2308      __objc_exec_class (&L_OBJC_MODULES);
2309    }  */ 
2310
2311 static void
2312 build_module_initializer_routine (void)
2313 {
2314   tree body;
2315
2316 #ifdef OBJCPLUS
2317   push_lang_context (lang_name_c); /* extern "C" */
2318 #endif                                     
2319
2320   objc_push_parm (build_decl (PARM_DECL, NULL_TREE, void_type_node));
2321   objc_start_function (get_identifier (TAG_GNUINIT),
2322                        build_function_type (void_type_node,
2323                                             OBJC_VOID_AT_END),
2324                        NULL_TREE, objc_get_parm_info (0));
2325
2326   body = c_begin_compound_stmt (true);
2327   add_stmt (build_function_call
2328             (execclass_decl,
2329              build_tree_list
2330              (NULL_TREE,
2331               build_unary_op (ADDR_EXPR,
2332                               UOBJC_MODULES_decl, 0))));
2333   add_stmt (c_end_compound_stmt (body, true));
2334
2335   TREE_PUBLIC (current_function_decl) = 0;
2336
2337 #ifndef OBJCPLUS
2338   /* For Objective-C++, we will need to call __objc_gnu_init
2339      from objc_generate_static_init_call() below.  */
2340   DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
2341 #endif
2342
2343   GNU_INIT_decl = current_function_decl;
2344   finish_function ();
2345
2346 #ifdef OBJCPLUS
2347     pop_lang_context ();
2348 #endif
2349 }
2350
2351 #ifdef OBJCPLUS
2352 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
2353    to be called by the module initializer routine.  */
2354
2355 int
2356 objc_static_init_needed_p (void)
2357 {
2358   return (GNU_INIT_decl != NULL_TREE);
2359 }
2360
2361 /* Generate a call to the __objc_gnu_init initializer function.  */
2362
2363 tree
2364 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
2365 {
2366   add_stmt (build_stmt (EXPR_STMT,
2367                         build_function_call (GNU_INIT_decl, NULL_TREE)));
2368
2369   return ctors;
2370 }
2371 #endif /* OBJCPLUS */
2372
2373 /* Return the DECL of the string IDENT in the SECTION.  */
2374
2375 static tree
2376 get_objc_string_decl (tree ident, enum string_section section)
2377 {
2378   tree chain;
2379
2380   if (section == class_names)
2381     chain = class_names_chain;
2382   else if (section == meth_var_names)
2383     chain = meth_var_names_chain;
2384   else if (section == meth_var_types)
2385     chain = meth_var_types_chain;
2386   else
2387     abort ();
2388
2389   for (; chain != 0; chain = TREE_CHAIN (chain))
2390     if (TREE_VALUE (chain) == ident)
2391       return (TREE_PURPOSE (chain));
2392
2393   abort ();
2394   return NULL_TREE;
2395 }
2396
2397 /* Output references to all statically allocated objects.  Return the DECL
2398    for the array built.  */
2399
2400 static void
2401 generate_static_references (void)
2402 {
2403   tree decls = NULL_TREE, expr = NULL_TREE;
2404   tree class_name, class, decl, initlist;
2405   tree cl_chain, in_chain, type
2406     = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
2407   int num_inst, num_class;
2408   char buf[256];
2409
2410   if (flag_next_runtime)
2411     abort ();
2412
2413   for (cl_chain = objc_static_instances, num_class = 0;
2414        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
2415     {
2416       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
2417            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
2418
2419       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
2420       decl = start_var_decl (type, buf);
2421
2422       /* Output {class_name, ...}.  */
2423       class = TREE_VALUE (cl_chain);
2424       class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
2425       initlist = build_tree_list (NULL_TREE,
2426                                   build_unary_op (ADDR_EXPR, class_name, 1));
2427
2428       /* Output {..., instance, ...}.  */
2429       for (in_chain = TREE_PURPOSE (cl_chain);
2430            in_chain; in_chain = TREE_CHAIN (in_chain))
2431         {
2432           expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2433           initlist = tree_cons (NULL_TREE, expr, initlist);
2434         }
2435
2436       /* Output {..., NULL}.  */
2437       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2438
2439       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2440       finish_var_decl (decl, expr);
2441       decls
2442         = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2443     }
2444
2445   decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
2446   expr = objc_build_constructor (type, nreverse (decls));
2447   static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
2448   finish_var_decl (static_instances_decl, expr);
2449 }
2450
2451 /* Output all strings.  */
2452
2453 static void
2454 generate_strings (void)
2455 {
2456   tree chain, string_expr;
2457   tree string, decl, type;
2458
2459   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2460     {
2461       string = TREE_VALUE (chain);
2462       decl = TREE_PURPOSE (chain);
2463       type = build_array_type
2464              (char_type_node,
2465               build_index_type
2466               (build_int_cst (NULL_TREE, 
2467                               IDENTIFIER_LENGTH (string))));
2468       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2469       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2470                                      IDENTIFIER_POINTER (string));
2471       finish_var_decl (decl, string_expr);
2472     }
2473
2474   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2475     {
2476       string = TREE_VALUE (chain);
2477       decl = TREE_PURPOSE (chain);
2478       type = build_array_type
2479              (char_type_node,
2480               build_index_type
2481               (build_int_cst (NULL_TREE,
2482                               IDENTIFIER_LENGTH (string))));
2483       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2484       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2485                                      IDENTIFIER_POINTER (string));
2486       finish_var_decl (decl, string_expr);
2487     }
2488
2489   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2490     {
2491       string = TREE_VALUE (chain);
2492       decl = TREE_PURPOSE (chain);
2493       type = build_array_type
2494              (char_type_node,
2495               build_index_type
2496               (build_int_cst (NULL_TREE,
2497                               IDENTIFIER_LENGTH (string))));
2498       decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2499       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2500                                      IDENTIFIER_POINTER (string));
2501       finish_var_decl (decl, string_expr);
2502     }
2503 }
2504
2505 static GTY(()) int selector_reference_idx;
2506
2507 static tree
2508 build_selector_reference_decl (void)
2509 {
2510   tree decl;
2511   char buf[256];
2512
2513   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2514   decl = start_var_decl (objc_selector_type, buf);
2515
2516   return decl;
2517 }
2518
2519 static void
2520 build_selector_table_decl (void)
2521 {
2522   tree temp;
2523
2524   if (flag_typed_selectors)
2525     {
2526       build_selector_template ();
2527       temp = build_array_type (objc_selector_template, NULL_TREE);
2528     }
2529   else
2530     temp = build_array_type (objc_selector_type, NULL_TREE);
2531
2532   UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
2533 }
2534
2535 /* Just a handy wrapper for add_objc_string.  */
2536
2537 static tree
2538 build_selector (tree ident)
2539 {
2540   return convert (objc_selector_type,
2541                   add_objc_string (ident, meth_var_names));
2542 }
2543
2544 static void
2545 build_selector_translation_table (void)
2546 {
2547   tree chain, initlist = NULL_TREE;
2548   int offset = 0;
2549   tree decl = NULL_TREE;
2550
2551   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2552     {
2553       tree expr;
2554
2555       if (warn_selector && objc_implementation_context)
2556       {
2557         tree method_chain;
2558         bool found = false;
2559         for (method_chain = meth_var_names_chain;
2560              method_chain;
2561              method_chain = TREE_CHAIN (method_chain))
2562           {
2563             if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2564               {
2565                 found = true;
2566                 break;
2567               }
2568           }
2569         if (!found)
2570           {
2571             location_t *loc;
2572             if (flag_next_runtime && TREE_PURPOSE (chain))
2573               loc = &DECL_SOURCE_LOCATION (TREE_PURPOSE (chain));
2574             else
2575               loc = &input_location;
2576             warning (0, "%Hcreating selector for nonexistent method %qE",
2577                      loc, TREE_VALUE (chain));
2578           }
2579       }
2580
2581       expr = build_selector (TREE_VALUE (chain));
2582       /* add one for the '\0' character */
2583       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2584
2585       if (flag_next_runtime)
2586         {
2587           decl = TREE_PURPOSE (chain);
2588           finish_var_decl (decl, expr);
2589         }
2590       else
2591         {
2592           if (flag_typed_selectors)
2593             {
2594               tree eltlist = NULL_TREE;
2595               tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2596               eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2597               eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2598               expr = objc_build_constructor (objc_selector_template,
2599                                              nreverse (eltlist));
2600             }
2601
2602           initlist = tree_cons (NULL_TREE, expr, initlist);
2603         }
2604     }
2605
2606   if (! flag_next_runtime)
2607     {
2608       /* Cause the selector table (previously forward-declared)
2609          to be actually output.  */
2610       initlist = tree_cons (NULL_TREE,
2611                             flag_typed_selectors
2612                             ? objc_build_constructor
2613                               (objc_selector_template,
2614                                tree_cons (NULL_TREE,
2615                                           build_int_cst (NULL_TREE, 0),
2616                                           tree_cons (NULL_TREE,
2617                                                      build_int_cst (NULL_TREE, 0), 
2618                                                      NULL_TREE)))
2619                             : build_int_cst (NULL_TREE, 0), initlist);
2620       initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2621                                          nreverse (initlist));
2622       finish_var_decl (UOBJC_SELECTOR_TABLE_decl, initlist);
2623     }
2624 }
2625
2626 static tree
2627 get_proto_encoding (tree proto)
2628 {
2629   tree encoding;
2630   if (proto)
2631     {
2632       if (! METHOD_ENCODING (proto))
2633         {
2634           encoding = encode_method_prototype (proto);
2635           METHOD_ENCODING (proto) = encoding;
2636         }
2637       else
2638         encoding = METHOD_ENCODING (proto);
2639
2640       return add_objc_string (encoding, meth_var_types);
2641     }
2642   else
2643     return build_int_cst (NULL_TREE, 0);
2644 }
2645
2646 /* sel_ref_chain is a list whose "value" fields will be instances of
2647    identifier_node that represent the selector.  */
2648
2649 static tree
2650 build_typed_selector_reference (tree ident, tree prototype)
2651 {
2652   tree *chain = &sel_ref_chain;
2653   tree expr;
2654   int index = 0;
2655
2656   while (*chain)
2657     {
2658       if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2659         goto return_at_index;
2660
2661       index++;
2662       chain = &TREE_CHAIN (*chain);
2663     }
2664
2665   *chain = tree_cons (prototype, ident, NULL_TREE);
2666
2667  return_at_index:
2668   expr = build_unary_op (ADDR_EXPR,
2669                          build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2670                                           build_int_cst (NULL_TREE, index)),
2671                          1);
2672   return convert (objc_selector_type, expr);
2673 }
2674
2675 static tree
2676 build_selector_reference (tree ident)
2677 {
2678   tree *chain = &sel_ref_chain;
2679   tree expr;
2680   int index = 0;
2681
2682   while (*chain)
2683     {
2684       if (TREE_VALUE (*chain) == ident)
2685         return (flag_next_runtime
2686                 ? TREE_PURPOSE (*chain)
2687                 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2688                                    build_int_cst (NULL_TREE, index)));
2689
2690       index++;
2691       chain = &TREE_CHAIN (*chain);
2692     }
2693
2694   expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
2695
2696   *chain = tree_cons (expr, ident, NULL_TREE);
2697
2698   return (flag_next_runtime
2699           ? expr
2700           : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2701                              build_int_cst (NULL_TREE, index)));
2702 }
2703
2704 static GTY(()) int class_reference_idx;
2705
2706 static tree
2707 build_class_reference_decl (void)
2708 {
2709   tree decl;
2710   char buf[256];
2711
2712   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2713   decl = start_var_decl (objc_class_type, buf);
2714
2715   return decl;
2716 }
2717
2718 /* Create a class reference, but don't create a variable to reference
2719    it.  */
2720
2721 static void
2722 add_class_reference (tree ident)
2723 {
2724   tree chain;
2725
2726   if ((chain = cls_ref_chain))
2727     {
2728       tree tail;
2729       do
2730         {
2731           if (ident == TREE_VALUE (chain))
2732             return;
2733
2734           tail = chain;
2735           chain = TREE_CHAIN (chain);
2736         }
2737       while (chain);
2738
2739       /* Append to the end of the list */
2740       TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2741     }
2742   else
2743     cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2744 }
2745
2746 /* Get a class reference, creating it if necessary.  Also create the
2747    reference variable.  */
2748
2749 tree
2750 objc_get_class_reference (tree ident)
2751 {
2752   tree orig_ident = (DECL_P (ident)
2753                      ? DECL_NAME (ident)
2754                      : TYPE_P (ident)
2755                      ? OBJC_TYPE_NAME (ident)
2756                      : ident);
2757   bool local_scope = false;
2758
2759 #ifdef OBJCPLUS
2760   if (processing_template_decl)
2761     /* Must wait until template instantiation time.  */
2762     return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2763 #endif
2764
2765   if (TREE_CODE (ident) == TYPE_DECL)
2766     ident = (DECL_ORIGINAL_TYPE (ident)
2767              ? DECL_ORIGINAL_TYPE (ident)
2768              : TREE_TYPE (ident));
2769
2770 #ifdef OBJCPLUS
2771   if (TYPE_P (ident) && TYPE_CONTEXT (ident)
2772       && TYPE_CONTEXT (ident) != global_namespace)
2773     local_scope = true;
2774 #endif
2775
2776   if (local_scope || !(ident = objc_is_class_name (ident)))
2777     {
2778       error ("%qs is not an Objective-C class name or alias",
2779              IDENTIFIER_POINTER (orig_ident));
2780       return error_mark_node;
2781     }
2782
2783   if (flag_next_runtime && !flag_zero_link)
2784     {
2785       tree *chain;
2786       tree decl;
2787
2788       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2789         if (TREE_VALUE (*chain) == ident)
2790           {
2791             if (! TREE_PURPOSE (*chain))
2792               TREE_PURPOSE (*chain) = build_class_reference_decl ();
2793
2794             return TREE_PURPOSE (*chain);
2795           }
2796
2797       decl = build_class_reference_decl ();
2798       *chain = tree_cons (decl, ident, NULL_TREE);
2799       return decl;
2800     }
2801   else
2802     {
2803       tree params;
2804
2805       add_class_reference (ident);
2806
2807       params = build_tree_list (NULL_TREE,
2808                                 my_build_string_pointer
2809                                 (IDENTIFIER_LENGTH (ident) + 1,
2810                                  IDENTIFIER_POINTER (ident)));
2811
2812       assemble_external (objc_get_class_decl);
2813       return build_function_call (objc_get_class_decl, params);
2814     }
2815 }
2816
2817 /* For each string section we have a chain which maps identifier nodes
2818    to decls for the strings.  */
2819
2820 static tree
2821 add_objc_string (tree ident, enum string_section section)
2822 {
2823   tree *chain, decl;
2824
2825   if (section == class_names)
2826     chain = &class_names_chain;
2827   else if (section == meth_var_names)
2828     chain = &meth_var_names_chain;
2829   else if (section == meth_var_types)
2830     chain = &meth_var_types_chain;
2831   else
2832     abort ();
2833
2834   while (*chain)
2835     {
2836       if (TREE_VALUE (*chain) == ident)
2837         return convert (string_type_node,
2838                         build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1));
2839
2840       chain = &TREE_CHAIN (*chain);
2841     }
2842
2843   decl = build_objc_string_decl (section);
2844
2845   *chain = tree_cons (decl, ident, NULL_TREE);
2846
2847   return convert (string_type_node, build_unary_op (ADDR_EXPR, decl, 1));
2848 }
2849
2850 static GTY(()) int class_names_idx;
2851 static GTY(()) int meth_var_names_idx;
2852 static GTY(()) int meth_var_types_idx;
2853
2854 static tree
2855 build_objc_string_decl (enum string_section section)
2856 {
2857   tree decl, ident;
2858   char buf[256];
2859
2860   if (section == class_names)
2861     sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2862   else if (section == meth_var_names)
2863     sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2864   else if (section == meth_var_types)
2865     sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2866
2867   ident = get_identifier (buf);
2868
2869   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2870   DECL_EXTERNAL (decl) = 1;
2871   TREE_PUBLIC (decl) = 0;
2872   TREE_USED (decl) = 1;
2873   TREE_CONSTANT (decl) = 1;
2874   DECL_CONTEXT (decl) = 0;
2875   DECL_ARTIFICIAL (decl) = 1;
2876 #ifdef OBJCPLUS
2877   DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */
2878 #endif  
2879
2880   make_decl_rtl (decl);
2881   pushdecl_top_level (decl);
2882
2883   return decl;
2884 }
2885
2886
2887 void
2888 objc_declare_alias (tree alias_ident, tree class_ident)
2889 {
2890   tree underlying_class;
2891
2892 #ifdef OBJCPLUS
2893   if (current_namespace != global_namespace) {
2894     error ("Objective-C declarations may only appear in global scope");
2895   }
2896 #endif /* OBJCPLUS */
2897
2898   if (!(underlying_class = objc_is_class_name (class_ident)))
2899     warning (0, "cannot find class %qs", IDENTIFIER_POINTER (class_ident));
2900   else if (objc_is_class_name (alias_ident))
2901     warning (0, "class %qs already exists", IDENTIFIER_POINTER (alias_ident));
2902   else
2903     {
2904       /* Implement @compatibility_alias as a typedef.  */
2905 #ifdef OBJCPLUS
2906       push_lang_context (lang_name_c); /* extern "C" */
2907 #endif
2908       lang_hooks.decls.pushdecl (build_decl
2909                                  (TYPE_DECL,
2910                                   alias_ident,
2911                                   xref_tag (RECORD_TYPE, underlying_class)));
2912 #ifdef OBJCPLUS
2913       pop_lang_context ();
2914 #endif
2915       alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2916     }
2917 }
2918
2919 void
2920 objc_declare_class (tree ident_list)
2921 {
2922   tree list;
2923 #ifdef OBJCPLUS
2924   if (current_namespace != global_namespace) {
2925     error ("Objective-C declarations may only appear in global scope");
2926   }
2927 #endif /* OBJCPLUS */
2928
2929   for (list = ident_list; list; list = TREE_CHAIN (list))
2930     {
2931       tree ident = TREE_VALUE (list);
2932
2933       if (! objc_is_class_name (ident))
2934         {
2935           tree record = lookup_name (ident), type = record;
2936
2937           if (record)
2938             {
2939               if (TREE_CODE (record) == TYPE_DECL)
2940                 type = DECL_ORIGINAL_TYPE (record);
2941
2942               if (!TYPE_HAS_OBJC_INFO (type)
2943                   || !TYPE_OBJC_INTERFACE (type))
2944                 {
2945                   error ("%qs redeclared as different kind of symbol",
2946                          IDENTIFIER_POINTER (ident));
2947                   error ("previous declaration of %q+D",
2948                          record);
2949                 }
2950             }
2951
2952           record = xref_tag (RECORD_TYPE, ident);
2953           INIT_TYPE_OBJC_INFO (record);
2954           TYPE_OBJC_INTERFACE (record) = ident;
2955           class_chain = tree_cons (NULL_TREE, ident, class_chain);
2956         }
2957     }
2958 }
2959
2960 tree
2961 objc_is_class_name (tree ident)
2962 {
2963   tree chain;
2964
2965   if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2966       && identifier_global_value (ident))
2967     ident = identifier_global_value (ident);
2968   while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2969     ident = OBJC_TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2970
2971   if (ident && TREE_CODE (ident) == RECORD_TYPE)
2972     ident = OBJC_TYPE_NAME (ident);
2973 #ifdef OBJCPLUS
2974   if (ident && TREE_CODE (ident) == TYPE_DECL)
2975     ident = DECL_NAME (ident);
2976 #endif
2977   if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2978     return NULL_TREE;
2979
2980   if (lookup_interface (ident))
2981     return ident;
2982
2983   for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2984     {
2985       if (ident == TREE_VALUE (chain))
2986         return ident;
2987     }
2988
2989   for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2990     {
2991       if (ident == TREE_VALUE (chain))
2992         return TREE_PURPOSE (chain);
2993     }
2994
2995   return 0;
2996 }
2997
2998 /* Check whether TYPE is either 'id' or 'Class'.  */
2999
3000 tree
3001 objc_is_id (tree type)
3002 {
3003   if (type && TREE_CODE (type) == IDENTIFIER_NODE
3004       && identifier_global_value (type))
3005     type = identifier_global_value (type);
3006
3007   if (type && TREE_CODE (type) == TYPE_DECL)
3008     type = TREE_TYPE (type);
3009
3010   /* NB: This function may be called before the ObjC front-end has
3011      been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL.  */
3012   return (objc_object_type && type
3013           && (IS_ID (type) || IS_CLASS (type) || IS_SUPER (type))
3014           ? type
3015           : NULL_TREE); 
3016 }
3017
3018 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
3019    class instance.  This is needed by other parts of the compiler to
3020    handle ObjC types gracefully.  */
3021
3022 tree
3023 objc_is_object_ptr (tree type)
3024 {
3025   tree ret;
3026
3027   type = TYPE_MAIN_VARIANT (type);
3028   if (!POINTER_TYPE_P (type))
3029     return 0;
3030
3031   ret = objc_is_id (type);
3032   if (!ret)
3033     ret = objc_is_class_name (TREE_TYPE (type));
3034
3035   return ret;
3036 }
3037
3038 static int
3039 objc_is_gcable_type (tree type, int or_strong_p)
3040 {
3041   tree name; 
3042
3043   if (!TYPE_P (type))
3044     return 0;
3045   if (objc_is_id (TYPE_MAIN_VARIANT (type)))
3046     return 1;
3047   if (or_strong_p && lookup_attribute ("objc_gc", TYPE_ATTRIBUTES (type)))
3048     return 1;
3049   if (TREE_CODE (type) != POINTER_TYPE && TREE_CODE (type) != INDIRECT_REF)
3050     return 0;
3051   type = TREE_TYPE (type);
3052   if (TREE_CODE (type) != RECORD_TYPE)
3053     return 0;
3054   name = TYPE_NAME (type);
3055   return (objc_is_class_name (name) != NULL_TREE);
3056 }
3057
3058 static tree
3059 objc_substitute_decl (tree expr, tree oldexpr, tree newexpr)
3060 {
3061   if (expr == oldexpr)
3062     return newexpr;
3063
3064   switch (TREE_CODE (expr))
3065     {
3066     case COMPONENT_REF:
3067       return objc_build_component_ref
3068              (objc_substitute_decl (TREE_OPERAND (expr, 0),
3069                                     oldexpr,
3070                                     newexpr),
3071               DECL_NAME (TREE_OPERAND (expr, 1)));
3072     case ARRAY_REF:
3073       return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
3074                                                     oldexpr,
3075                                                     newexpr),
3076                               TREE_OPERAND (expr, 1));
3077     case INDIRECT_REF:
3078       return build_indirect_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
3079                                                        oldexpr,
3080                                                        newexpr), "->");
3081     default:
3082       return expr;
3083     }
3084 }
3085
3086 static tree
3087 objc_build_ivar_assignment (tree outervar, tree lhs, tree rhs)
3088 {
3089   tree func_params;
3090   /* The LHS parameter contains the expression 'outervar->memberspec';
3091      we need to transform it into '&((typeof(outervar) *) 0)->memberspec',
3092      where memberspec may be arbitrarily complex (e.g., 'g->f.d[2].g[3]').
3093   */
3094   tree offs
3095     = objc_substitute_decl
3096       (lhs, outervar, convert (TREE_TYPE (outervar), integer_zero_node));
3097   tree func
3098     = (flag_objc_direct_dispatch
3099        ? objc_assign_ivar_fast_decl
3100        : objc_assign_ivar_decl);
3101
3102   offs = convert (integer_type_node, build_unary_op (ADDR_EXPR, offs, 0));
3103   offs = fold (offs);
3104   func_params = tree_cons (NULL_TREE, 
3105         convert (objc_object_type, rhs),
3106             tree_cons (NULL_TREE, convert (objc_object_type, outervar),
3107                 tree_cons (NULL_TREE, offs,
3108                     NULL_TREE)));
3109
3110   assemble_external (func);
3111   return build_function_call (func, func_params);
3112 }
3113
3114 static tree
3115 objc_build_global_assignment (tree lhs, tree rhs)
3116 {
3117   tree func_params = tree_cons (NULL_TREE,
3118         convert (objc_object_type, rhs),
3119             tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3120                       build_unary_op (ADDR_EXPR, lhs, 0)),
3121                     NULL_TREE));
3122
3123   assemble_external (objc_assign_global_decl);
3124   return build_function_call (objc_assign_global_decl, func_params);
3125 }
3126
3127 static tree
3128 objc_build_strong_cast_assignment (tree lhs, tree rhs)
3129 {
3130   tree func_params = tree_cons (NULL_TREE,
3131         convert (objc_object_type, rhs),
3132             tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3133                       build_unary_op (ADDR_EXPR, lhs, 0)), 
3134                     NULL_TREE));
3135
3136   assemble_external (objc_assign_strong_cast_decl);
3137   return build_function_call (objc_assign_strong_cast_decl, func_params);
3138 }
3139
3140 static int
3141 objc_is_gcable_p (tree expr)
3142 {
3143   return (TREE_CODE (expr) == COMPONENT_REF
3144           ? objc_is_gcable_p (TREE_OPERAND (expr, 1))
3145           : TREE_CODE (expr) == ARRAY_REF
3146           ? (objc_is_gcable_p (TREE_TYPE (expr))
3147              || objc_is_gcable_p (TREE_OPERAND (expr, 0)))
3148           : TREE_CODE (expr) == ARRAY_TYPE
3149           ? objc_is_gcable_p (TREE_TYPE (expr))
3150           : TYPE_P (expr)
3151           ? objc_is_gcable_type (expr, 1)
3152           : (objc_is_gcable_p (TREE_TYPE (expr))
3153              || (DECL_P (expr)
3154                  && lookup_attribute ("objc_gc", DECL_ATTRIBUTES (expr)))));
3155 }
3156
3157 static int
3158 objc_is_ivar_reference_p (tree expr)
3159 {
3160   return (TREE_CODE (expr) == ARRAY_REF
3161           ? objc_is_ivar_reference_p (TREE_OPERAND (expr, 0))
3162           : TREE_CODE (expr) == COMPONENT_REF
3163           ? TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL
3164           : 0);
3165 }
3166
3167 static int
3168 objc_is_global_reference_p (tree expr)
3169 {
3170   return (TREE_CODE (expr) == INDIRECT_REF || TREE_CODE (expr) == PLUS_EXPR
3171           ? objc_is_global_reference_p (TREE_OPERAND (expr, 0))
3172           : DECL_P (expr)
3173           ? (!DECL_CONTEXT (expr) || TREE_STATIC (expr))
3174           : 0);
3175 }
3176
3177 tree
3178 objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
3179 {
3180   tree result = NULL_TREE, outer;
3181   int strong_cast_p = 0, outer_gc_p = 0, indirect_p = 0;
3182
3183   /* See if we have any lhs casts, and strip them out.  NB: The lvalue casts
3184      will have been transformed to the form '*(type *)&expr'.  */
3185   if (TREE_CODE (lhs) == INDIRECT_REF)
3186     {
3187       outer = TREE_OPERAND (lhs, 0);
3188
3189       while (!strong_cast_p
3190              && (TREE_CODE (outer) == CONVERT_EXPR
3191                  || TREE_CODE (outer) == NOP_EXPR
3192                  || TREE_CODE (outer) == NON_LVALUE_EXPR))
3193         {
3194           tree lhstype = TREE_TYPE (outer);
3195
3196           /* Descend down the cast chain, and record the first objc_gc
3197              attribute found.  */
3198           if (POINTER_TYPE_P (lhstype))
3199             {
3200               tree attr
3201                 = lookup_attribute ("objc_gc",
3202                                     TYPE_ATTRIBUTES (TREE_TYPE (lhstype)));
3203
3204               if (attr)
3205                 strong_cast_p = 1;
3206             }
3207
3208           outer = TREE_OPERAND (outer, 0);
3209         }
3210     }
3211
3212   /* If we have a __strong cast, it trumps all else.  */
3213   if (strong_cast_p)
3214     {
3215       if (modifycode != NOP_EXPR)
3216         goto invalid_pointer_arithmetic;
3217
3218       if (warn_assign_intercept)
3219         warning (0, "strong-cast assignment has been intercepted");
3220
3221       result = objc_build_strong_cast_assignment (lhs, rhs);
3222
3223       goto exit_point;
3224     }
3225
3226   /* the lhs must be of a suitable type, regardless of its underlying
3227      structure.  */
3228   if (!objc_is_gcable_p (lhs))
3229     goto exit_point;
3230
3231   outer = lhs;
3232
3233   while (outer
3234          && (TREE_CODE (outer) == COMPONENT_REF
3235              || TREE_CODE (outer) == ARRAY_REF))
3236     outer = TREE_OPERAND (outer, 0);
3237
3238   if (TREE_CODE (outer) == INDIRECT_REF)
3239     {
3240       outer = TREE_OPERAND (outer, 0);
3241       indirect_p = 1;
3242     }
3243
3244   outer_gc_p = objc_is_gcable_p (outer);
3245   
3246   /* Handle ivar assignments. */
3247   if (objc_is_ivar_reference_p (lhs))
3248     {
3249       /* if the struct to the left of the ivar is not an Objective-C object (__strong
3250          doesn't cut it here), the best we can do here is suggest a cast.  */
3251       if (!objc_is_gcable_type (TREE_TYPE (outer), 0))
3252         {
3253           /* We may still be able to use the global write barrier... */
3254           if (!indirect_p && objc_is_global_reference_p (outer))
3255             goto global_reference;
3256
3257          suggest_cast:
3258           if (modifycode == NOP_EXPR)
3259             {
3260               if (warn_assign_intercept)
3261                 warning (0, "strong-cast may possibly be needed");
3262             }
3263
3264           goto exit_point;
3265         }
3266
3267       if (modifycode != NOP_EXPR)
3268         goto invalid_pointer_arithmetic;
3269
3270       if (warn_assign_intercept)
3271         warning (0, "instance variable assignment has been intercepted");
3272
3273       result = objc_build_ivar_assignment (outer, lhs, rhs);
3274
3275       goto exit_point;
3276     }
3277
3278   /* Likewise, intercept assignment to global/static variables if their type is
3279      GC-marked.  */    
3280   if (objc_is_global_reference_p (outer))
3281     {
3282       if (indirect_p)
3283         goto suggest_cast;
3284
3285      global_reference:
3286       if (modifycode != NOP_EXPR)
3287         {
3288          invalid_pointer_arithmetic:
3289           if (outer_gc_p)
3290             warning (0, "pointer arithmetic for garbage-collected objects not allowed");
3291
3292           goto exit_point;
3293         }
3294
3295       if (warn_assign_intercept)
3296         warning (0, "global/static variable assignment has been intercepted");
3297
3298       result = objc_build_global_assignment (lhs, rhs);
3299     }
3300
3301   /* In all other cases, fall back to the normal mechanism.  */
3302  exit_point:
3303   return result;
3304 }
3305
3306 struct interface_tuple GTY(())
3307 {
3308   tree id;
3309   tree class_name;
3310 };
3311
3312 static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
3313
3314 static hashval_t
3315 hash_interface (const void *p)
3316 {
3317   const struct interface_tuple *d = p;
3318   return htab_hash_pointer (d->id);
3319 }
3320
3321 static int
3322 eq_interface (const void *p1, const void *p2)
3323 {
3324   const struct interface_tuple *d = p1;
3325   return d->id == p2;
3326 }
3327
3328 static tree
3329 lookup_interface (tree ident)
3330 {
3331 #ifdef OBJCPLUS
3332   if (ident && TREE_CODE (ident) == TYPE_DECL)
3333     ident = DECL_NAME (ident);
3334 #endif
3335
3336   if (ident == NULL_TREE || TREE_CODE (ident) != IDENTIFIER_NODE)
3337     return NULL_TREE;
3338
3339   {
3340     struct interface_tuple **slot;
3341     tree i = NULL_TREE;
3342
3343     if (interface_htab)
3344       {
3345         slot = (struct interface_tuple **)
3346           htab_find_slot_with_hash (interface_htab, ident,
3347                                     htab_hash_pointer (ident),
3348                                     NO_INSERT);
3349         if (slot && *slot)
3350           i = (*slot)->class_name;
3351       }
3352     return i;
3353   }
3354 }
3355
3356 /* Implement @defs (<classname>) within struct bodies.  */
3357
3358 tree
3359 objc_get_class_ivars (tree class_name)
3360 {
3361   tree interface = lookup_interface (class_name);
3362
3363   if (interface)
3364     return get_class_ivars (interface, true);
3365
3366   error ("cannot find interface declaration for %qs",
3367          IDENTIFIER_POINTER (class_name));
3368
3369   return error_mark_node;
3370 }
3371
3372 /* Used by: build_private_template, continue_class,
3373    and for @defs constructs.  */
3374
3375 static tree
3376 get_class_ivars (tree interface, bool inherited)
3377 {
3378   tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
3379
3380   /* Both CLASS_RAW_IVARS and CLASS_IVARS contain a list of ivars declared
3381      by the current class (i.e., they do not include super-class ivars).
3382      However, the CLASS_IVARS list will be side-effected by a call to
3383      finish_struct(), which will fill in field offsets.  */
3384   if (!CLASS_IVARS (interface))
3385     CLASS_IVARS (interface) = ivar_chain;
3386
3387   if (!inherited)
3388     return ivar_chain;
3389
3390   while (CLASS_SUPER_NAME (interface))
3391     {
3392       /* Prepend super-class ivars.  */
3393       interface = lookup_interface (CLASS_SUPER_NAME (interface));
3394       ivar_chain = chainon (copy_list (CLASS_RAW_IVARS (interface)),
3395                             ivar_chain);
3396     }
3397
3398   return ivar_chain;
3399 }
3400
3401 static tree
3402 objc_create_temporary_var (tree type)
3403 {
3404   tree decl;
3405  
3406   decl = build_decl (VAR_DECL, NULL_TREE, type);
3407   TREE_USED (decl) = 1;
3408   DECL_ARTIFICIAL (decl) = 1;
3409   DECL_IGNORED_P (decl) = 1;
3410   DECL_CONTEXT (decl) = current_function_decl;
3411
3412   return decl;
3413 }
3414 \f
3415 /* Exception handling constructs.  We begin by having the parser do most
3416    of the work and passing us blocks.  What we do next depends on whether
3417    we're doing "native" exception handling or legacy Darwin setjmp exceptions.
3418    We abstract all of this in a handful of appropriately named routines.  */
3419
3420 /* Stack of open try blocks.  */
3421
3422 struct objc_try_context
3423 {
3424   struct objc_try_context *outer;
3425
3426   /* Statements (or statement lists) as processed by the parser.  */
3427   tree try_body;
3428   tree finally_body;
3429
3430   /* Some file position locations.  */
3431   location_t try_locus;
3432   location_t end_try_locus;
3433   location_t end_catch_locus;
3434   location_t finally_locus;
3435   location_t end_finally_locus;
3436
3437   /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
3438      of a TRY_CATCH_EXPR.  Even when doing Darwin setjmp.  */
3439   tree catch_list;
3440
3441   /* The CATCH_EXPR of an open @catch clause.  */
3442   tree current_catch;
3443
3444   /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR.  */
3445   tree caught_decl;
3446   tree stack_decl;
3447   tree rethrow_decl;
3448 };
3449
3450 static struct objc_try_context *cur_try_context;
3451
3452 /* This hook, called via lang_eh_runtime_type, generates a runtime object
3453    that represents TYPE.  For Objective-C, this is just the class name.  */
3454 /* ??? Isn't there a class object or some such?  Is it easy to get?  */
3455
3456 #ifndef OBJCPLUS
3457 static tree
3458 objc_eh_runtime_type (tree type)
3459 {
3460   return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
3461 }
3462 #endif
3463
3464 /* Initialize exception handling.  */
3465
3466 static void
3467 objc_init_exceptions (void)
3468 {
3469   static bool done = false;
3470   if (done)
3471     return;
3472   done = true;
3473
3474   if (flag_objc_sjlj_exceptions)
3475     {
3476       /* On Darwin, ObjC exceptions require a sufficiently recent
3477          version of the runtime, so the user must ask for them explicitly.  */
3478       if (!flag_objc_exceptions)
3479         warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
3480                  "exception syntax");
3481     }
3482 #ifndef OBJCPLUS
3483   else
3484     {
3485       c_eh_initialized_p = true;
3486       eh_personality_libfunc
3487         = init_one_libfunc (USING_SJLJ_EXCEPTIONS
3488                             ? "__gnu_objc_personality_sj0"
3489                             : "__gnu_objc_personality_v0");
3490       default_init_unwind_resume_libfunc ();
3491       using_eh_for_cleanups ();
3492       lang_eh_runtime_type = objc_eh_runtime_type;
3493     }
3494 #endif
3495 }
3496
3497 /* Build an EXC_PTR_EXPR, or the moral equivalent.  In the case of Darwin,
3498    we'll arrange for it to be initialized (and associated with a binding)
3499    later.  */
3500
3501 static tree
3502 objc_build_exc_ptr (void)
3503 {
3504   if (flag_objc_sjlj_exceptions)
3505     {
3506       tree var = cur_try_context->caught_decl;
3507       if (!var)
3508         {
3509           var = objc_create_temporary_var (objc_object_type);
3510           cur_try_context->caught_decl = var;
3511         }
3512       return var;
3513     }
3514   else
3515     return build (EXC_PTR_EXPR, objc_object_type);
3516 }
3517
3518 /* Build "objc_exception_try_exit(&_stack)".  */
3519
3520 static tree
3521 next_sjlj_build_try_exit (void)
3522 {
3523   tree t;
3524   t = build_fold_addr_expr (cur_try_context->stack_decl);
3525   t = tree_cons (NULL, t, NULL);
3526   t = build_function_call (objc_exception_try_exit_decl, t);
3527   return t;
3528 }
3529
3530 /* Build
3531         objc_exception_try_enter (&_stack);
3532         if (_setjmp(&_stack.buf))
3533           ;
3534         else
3535           ;
3536    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
3537    empty, ready for the caller to fill them in.  */
3538
3539 static tree
3540 next_sjlj_build_enter_and_setjmp (void)
3541 {
3542   tree t, enter, sj, cond;
3543
3544   t = build_fold_addr_expr (cur_try_context->stack_decl);
3545   t = tree_cons (NULL, t, NULL);
3546   enter = build_function_call (objc_exception_try_enter_decl, t);
3547
3548   t = objc_build_component_ref (cur_try_context->stack_decl,
3549                                 get_identifier ("buf"));
3550   t = build_fold_addr_expr (t);
3551 #ifdef OBJCPLUS
3552   /* Convert _setjmp argument to type that is expected.  */
3553   if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
3554     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
3555   else
3556     t = convert (ptr_type_node, t);
3557 #else
3558   t = convert (ptr_type_node, t);
3559 #endif
3560   t = tree_cons (NULL, t, NULL);
3561   sj = build_function_call (objc_setjmp_decl, t);
3562
3563   cond = build (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
3564   cond = c_common_truthvalue_conversion (cond);
3565
3566   return build (COND_EXPR, void_type_node, cond, NULL, NULL);
3567 }
3568
3569 /* Build
3570         DECL = objc_exception_extract(&_stack);
3571 */
3572    
3573 static tree
3574 next_sjlj_build_exc_extract (tree decl)
3575 {
3576   tree t;
3577
3578   t = build_fold_addr_expr (cur_try_context->stack_decl);
3579   t = tree_cons (NULL, t, NULL);
3580   t = build_function_call (objc_exception_extract_decl, t);
3581   t = convert (TREE_TYPE (decl), t);
3582   t = build (MODIFY_EXPR, void_type_node, decl, t);
3583
3584   return t;
3585 }
3586
3587 /* Build
3588         if (objc_exception_match(obj_get_class(TYPE), _caught)
3589           BODY
3590         else if (...)
3591           ...
3592         else
3593           {
3594             _rethrow = _caught;
3595             objc_exception_try_exit(&_stack);
3596           }
3597    from the sequence of CATCH_EXPRs in the current try context.  */
3598
3599 static tree
3600 next_sjlj_build_catch_list (void)
3601 {
3602   tre