OSDN Git Service

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