OSDN Git Service

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