OSDN Git Service

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