OSDN Git Service

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