OSDN Git Service

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