OSDN Git Service

In gcc/objc/:
[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, 2010
4    Free Software Foundation, Inc.
5    Contributed by Steve Naroff.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28
29 #ifdef OBJCPLUS
30 #include "cp-tree.h"
31 #else
32 #include "c-tree.h"
33 #include "c-lang.h"
34 #endif
35
36 #include "c-family/c-common.h"
37 #include "c-family/c-pragma.h"
38 #include "flags.h"
39 #include "langhooks.h"
40 #include "objc-act.h"
41 #include "input.h"
42 #include "function.h"
43 #include "output.h"
44 #include "toplev.h"
45 #include "ggc.h"
46 #include "debug.h"
47 #include "target.h"
48 #include "diagnostic-core.h"
49 #include "intl.h"
50 #include "cgraph.h"
51 #include "tree-iterator.h"
52 #include "hashtab.h"
53 #include "langhooks-def.h"
54
55 /* For default_tree_printer ().  */
56 #include "tree-pretty-print.h"
57
58 /* For enum gimplify_status */
59 #include "gimple.h"
60
61 #define OBJC_VOID_AT_END        void_list_node
62
63 static unsigned int should_call_super_dealloc = 0;
64
65 /* When building Objective-C++, we need in_late_binary_op.  */
66 #ifdef OBJCPLUS
67 bool in_late_binary_op = false;
68 #endif  /* OBJCPLUS */
69
70 /* When building Objective-C++, we are not linking against the C front-end
71    and so need to replicate the C tree-construction functions in some way.  */
72 #ifdef OBJCPLUS
73 #define OBJCP_REMAP_FUNCTIONS
74 #include "objcp-decl.h"
75 #endif  /* OBJCPLUS */
76
77 /* This is the default way of generating a method name.  */
78 /* This has the problem that "test_method:argument:" and
79    "test:method_argument:" will generate the same name
80    ("_i_Test__test_method_argument_" for an instance method of the
81    class "Test"), so you can't have them both in the same class!
82    Moreover, the demangling (going from
83    "_i_Test__test_method_argument" back to the original name) is
84    undefined because there are two correct ways of demangling the
85    name.  */
86 #ifndef OBJC_GEN_METHOD_LABEL
87 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
88   do {                                      \
89     char *temp;                             \
90     sprintf ((BUF), "_%s_%s_%s_%s",         \
91              ((IS_INST) ? "i" : "c"),       \
92              (CLASS_NAME),                  \
93              ((CAT_NAME)? (CAT_NAME) : ""), \
94              (SEL_NAME));                   \
95     for (temp = (BUF); *temp; temp++)       \
96       if (*temp == ':') *temp = '_';        \
97   } while (0)
98 #endif
99
100 /* These need specifying.  */
101 #ifndef OBJC_FORWARDING_STACK_OFFSET
102 #define OBJC_FORWARDING_STACK_OFFSET 0
103 #endif
104
105 #ifndef OBJC_FORWARDING_MIN_OFFSET
106 #define OBJC_FORWARDING_MIN_OFFSET 0
107 #endif
108 \f
109 /* Set up for use of obstacks.  */
110
111 #include "obstack.h"
112
113 /* This obstack is used to accumulate the encoding of a data type.  */
114 static struct obstack util_obstack;
115
116 /* This points to the beginning of obstack contents, so we can free
117    the whole contents.  */
118 char *util_firstobj;
119
120 /* The version identifies which language generation and runtime
121    the module (file) was compiled for, and is recorded in the
122    module descriptor.  */
123
124 #define OBJC_VERSION    (flag_next_runtime ? 6 : 8)
125 #define PROTOCOL_VERSION 2
126
127 /* (Decide if these can ever be validly changed.) */
128 #define OBJC_ENCODE_INLINE_DEFS         0
129 #define OBJC_ENCODE_DONT_INLINE_DEFS    1
130
131 /*** Private Interface (procedures) ***/
132
133 /* Used by compile_file.  */
134
135 static void init_objc (void);
136 static void finish_objc (void);
137
138 /* Code generation.  */
139
140 static tree objc_build_constructor (tree, VEC(constructor_elt,gc) *);
141 static tree build_objc_method_call (location_t, int, tree, tree, tree, tree);
142 static tree get_proto_encoding (tree);
143 static tree lookup_interface (tree);
144 static tree objc_add_static_instance (tree, tree);
145
146 static tree start_class (enum tree_code, tree, tree, tree);
147 static tree continue_class (tree);
148 static void finish_class (tree);
149 static void start_method_def (tree);
150 #ifdef OBJCPLUS
151 static void objc_start_function (tree, tree, tree, tree);
152 #else
153 static void objc_start_function (tree, tree, tree, struct c_arg_info *);
154 #endif
155 static tree start_protocol (enum tree_code, tree, tree);
156 static tree build_method_decl (enum tree_code, tree, tree, tree, bool);
157 static tree objc_add_method (tree, tree, int, bool);
158 static tree add_instance_variable (tree, objc_ivar_visibility_kind, tree);
159 static tree build_ivar_reference (tree);
160 static tree is_ivar (tree, tree);
161
162 static void build_objc_exception_stuff (void);
163 static void build_next_objc_exception_stuff (void);
164
165 /* We only need the following for ObjC; ObjC++ will use C++'s definition
166    of DERIVED_FROM_P.  */
167 #ifndef OBJCPLUS
168 static bool objc_derived_from_p (tree, tree);
169 #define DERIVED_FROM_P(PARENT, CHILD) objc_derived_from_p (PARENT, CHILD)
170 #endif
171
172 /* Property.  */
173 static void objc_gen_property_data (tree, tree);
174 static void objc_synthesize_getter (tree, tree, tree);
175 static void objc_synthesize_setter (tree, tree, tree);
176 static char *objc_build_property_setter_name (tree);
177 static int match_proto_with_proto (tree, tree, int);
178 static tree lookup_property (tree, tree);
179 static tree lookup_property_in_list (tree, tree);
180 static tree lookup_property_in_protocol_list (tree, tree);
181 static void build_objc_property_accessor_helpers (void);
182
183 static void objc_xref_basetypes (tree, tree);
184
185 static void build_class_template (void);
186 static void build_selector_template (void);
187 static void build_category_template (void);
188 static void build_super_template (void);
189 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
190 static tree get_class_ivars (tree, bool);
191 static tree generate_protocol_list (tree);
192 static void build_protocol_reference (tree);
193
194 static void build_fast_enumeration_state_template (void);
195
196 #ifdef OBJCPLUS
197 static void objc_generate_cxx_cdtors (void);
198 #endif
199
200 /* objc attribute */
201 static void objc_decl_method_attributes (tree*, tree, int); 
202 static tree build_keyword_selector (tree);
203 static const char *synth_id_with_class_suffix (const char *, tree);
204
205 /* Hash tables to manage the global pool of method prototypes.  */
206
207 hash *nst_method_hash_list = 0;
208 hash *cls_method_hash_list = 0;
209
210 /* Hash tables to manage the global pool of class names.  */
211
212 hash *cls_name_hash_list = 0;
213 hash *als_name_hash_list = 0;
214
215 static void hash_class_name_enter (hash *, tree, tree);
216 static hash hash_class_name_lookup (hash *, tree);
217
218 static hash hash_lookup (hash *, tree);
219 static tree lookup_method (tree, tree);
220 static tree lookup_method_static (tree, tree, int);
221
222 static tree add_class (tree, tree);
223 static void add_category (tree, tree);
224 static inline tree lookup_category (tree, tree);
225
226 enum string_section
227 {
228   class_names,          /* class, category, protocol, module names */
229   meth_var_names,       /* method and variable names */
230   meth_var_types        /* method and variable type descriptors */
231 };
232
233 static tree add_objc_string (tree, enum string_section);
234 static void build_selector_table_decl (void);
235
236 /* Protocol additions.  */
237
238 static tree lookup_protocol (tree);
239 static tree lookup_and_install_protocols (tree);
240
241 /* Type encoding.  */
242
243 static void encode_type_qualifiers (tree);
244 static void encode_type (tree, int, int);
245 static void encode_field_decl (tree, int, int);
246
247 #ifdef OBJCPLUS
248 static void really_start_method (tree, tree);
249 #else
250 static void really_start_method (tree, struct c_arg_info *);
251 #endif
252 static int comp_proto_with_proto (tree, tree, int);
253 static tree get_arg_type_list (tree, int, int);
254 static tree objc_decay_parm_type (tree);
255 static void objc_push_parm (tree);
256 #ifdef OBJCPLUS
257 static tree objc_get_parm_info (int);
258 #else
259 static struct c_arg_info *objc_get_parm_info (int);
260 #endif
261
262 /* Utilities for debugging and error diagnostics.  */
263
264 static char *gen_type_name (tree);
265 static char *gen_type_name_0 (tree);
266 static char *gen_method_decl (tree);
267 static char *gen_declaration (tree);
268
269 /* Everything else.  */
270
271 static tree create_field_decl (tree, const char *);
272 static void add_class_reference (tree);
273 static void build_protocol_template (void);
274 static tree encode_method_prototype (tree);
275 static void generate_classref_translation_entry (tree);
276 static void handle_class_ref (tree);
277 static void generate_struct_by_value_array (void)
278      ATTRIBUTE_NORETURN;
279 static void mark_referenced_methods (void);
280 static void generate_objc_image_info (void);
281 static bool objc_type_valid_for_messaging (tree typ);
282
283 /*** Private Interface (data) ***/
284
285 /* Reserved tag definitions.  */
286
287 #define OBJECT_TYPEDEF_NAME             "id"
288 #define CLASS_TYPEDEF_NAME              "Class"
289
290 #define TAG_OBJECT                      "objc_object"
291 #define TAG_CLASS                       "objc_class"
292 #define TAG_SUPER                       "objc_super"
293 #define TAG_SELECTOR                    "objc_selector"
294
295 #define UTAG_CLASS                      "_objc_class"
296 #define UTAG_IVAR                       "_objc_ivar"
297 #define UTAG_IVAR_LIST                  "_objc_ivar_list"
298 #define UTAG_METHOD                     "_objc_method"
299 #define UTAG_METHOD_LIST                "_objc_method_list"
300 #define UTAG_CATEGORY                   "_objc_category"
301 #define UTAG_MODULE                     "_objc_module"
302 #define UTAG_SYMTAB                     "_objc_symtab"
303 #define UTAG_SUPER                      "_objc_super"
304 #define UTAG_SELECTOR                   "_objc_selector"
305
306 #define UTAG_PROTOCOL                   "_objc_protocol"
307 #define UTAG_METHOD_PROTOTYPE           "_objc_method_prototype"
308 #define UTAG_METHOD_PROTOTYPE_LIST      "_objc__method_prototype_list"
309
310 /* Note that the string object global name is only needed for the
311    NeXT runtime.  */
312 #define STRING_OBJECT_GLOBAL_FORMAT     "_%sClassReference"
313
314 #define PROTOCOL_OBJECT_CLASS_NAME      "Protocol"
315
316 #define TAG_ENUMERATION_MUTATION        "objc_enumerationMutation"
317 #define TAG_FAST_ENUMERATION_STATE      "__objcFastEnumerationState"
318
319 static const char *TAG_GETCLASS;
320 static const char *TAG_GETMETACLASS;
321 static const char *TAG_MSGSEND;
322 static const char *TAG_MSGSENDSUPER;
323 /* The NeXT Objective-C messenger may have two extra entry points, for use
324    when returning a structure. */
325 static const char *TAG_MSGSEND_STRET;
326 static const char *TAG_MSGSENDSUPER_STRET;
327 static const char *default_constant_string_class_name;
328
329 /* Runtime metadata flags.  */
330 #define CLS_FACTORY                     0x0001L
331 #define CLS_META                        0x0002L
332 #define CLS_HAS_CXX_STRUCTORS           0x2000L
333
334 #define OBJC_MODIFIER_STATIC            0x00000001
335 #define OBJC_MODIFIER_FINAL             0x00000002
336 #define OBJC_MODIFIER_PUBLIC            0x00000004
337 #define OBJC_MODIFIER_PRIVATE           0x00000008
338 #define OBJC_MODIFIER_PROTECTED         0x00000010
339 #define OBJC_MODIFIER_NATIVE            0x00000020
340 #define OBJC_MODIFIER_SYNCHRONIZED      0x00000040
341 #define OBJC_MODIFIER_ABSTRACT          0x00000080
342 #define OBJC_MODIFIER_VOLATILE          0x00000100
343 #define OBJC_MODIFIER_TRANSIENT         0x00000200
344 #define OBJC_MODIFIER_NONE_SPECIFIED    0x80000000
345
346 /* NeXT-specific tags.  */
347
348 #define TAG_MSGSEND_NONNIL              "objc_msgSendNonNil"
349 #define TAG_MSGSEND_NONNIL_STRET        "objc_msgSendNonNil_stret"
350 #define TAG_EXCEPTIONEXTRACT            "objc_exception_extract"
351 #define TAG_EXCEPTIONTRYENTER           "objc_exception_try_enter"
352 #define TAG_EXCEPTIONTRYEXIT            "objc_exception_try_exit"
353 #define TAG_EXCEPTIONMATCH              "objc_exception_match"
354 #define TAG_EXCEPTIONTHROW              "objc_exception_throw"
355 #define TAG_SYNCENTER                   "objc_sync_enter"
356 #define TAG_SYNCEXIT                    "objc_sync_exit"
357 #define TAG_SETJMP                      "_setjmp"
358 #define UTAG_EXCDATA                    "_objc_exception_data"
359
360 #define TAG_ASSIGNIVAR                  "objc_assign_ivar"
361 #define TAG_ASSIGNGLOBAL                "objc_assign_global"
362 #define TAG_ASSIGNSTRONGCAST            "objc_assign_strongCast"
363
364 /* Branch entry points.  All that matters here are the addresses;
365    functions with these names do not really exist in libobjc.  */
366
367 #define TAG_MSGSEND_FAST                "objc_msgSend_Fast"
368 #define TAG_ASSIGNIVAR_FAST             "objc_assign_ivar_Fast"
369
370 #define TAG_CXX_CONSTRUCT               ".cxx_construct"
371 #define TAG_CXX_DESTRUCT                ".cxx_destruct"
372
373 /* GNU-specific tags.  */
374
375 #define TAG_EXECCLASS                   "__objc_exec_class"
376 #define TAG_GNUINIT                     "__objc_gnu_init"
377
378 /* Flags for lookup_method_static().  */
379 #define OBJC_LOOKUP_CLASS       1       /* Look for class methods.  */
380 #define OBJC_LOOKUP_NO_SUPER    2       /* Do not examine superclasses.  */
381
382 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
383 tree objc_global_trees[OCTI_MAX];
384
385 static void handle_impent (struct imp_entry *);
386
387 struct imp_entry *imp_list = 0;
388 int imp_count = 0;      /* `@implementation' */
389 int cat_count = 0;      /* `@category' */
390
391 objc_ivar_visibility_kind objc_ivar_visibility;
392
393 /* Use to generate method labels.  */
394 static int method_slot = 0;
395
396 /* Flag to say whether methods in a protocol are optional or
397    required.  */
398 static bool objc_method_optional_flag = false;
399
400 static int objc_collecting_ivars = 0;
401
402 #define BUFSIZE         1024
403
404 static char *errbuf;    /* Buffer for error diagnostics */
405
406 /* Data imported from tree.c.  */
407
408 extern enum debug_info_type write_symbols;
409
410 /* Data imported from toplev.c.  */
411
412 extern const char *dump_base_name;
413 \f
414 static int flag_typed_selectors;
415
416 /* Store all constructed constant strings in a hash table so that
417    they get uniqued properly.  */
418
419 struct GTY(()) string_descriptor {
420   /* The literal argument .  */
421   tree literal;
422
423   /* The resulting constant string.  */
424   tree constructor;
425 };
426
427 static GTY((param_is (struct string_descriptor))) htab_t string_htab;
428
429 FILE *gen_declaration_file;
430
431 /* Tells "encode_pointer/encode_aggregate" whether we are generating
432    type descriptors for instance variables (as opposed to methods).
433    Type descriptors for instance variables contain more information
434    than methods (for static typing and embedded structures).  */
435
436 static int generating_instance_variables = 0;
437
438 /* For building an objc struct.  These may not be used when this file
439    is compiled as part of obj-c++.  */
440
441 static bool objc_building_struct;
442 static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
443
444 /* Start building a struct for objc.  */
445
446 static tree
447 objc_start_struct (tree name)
448 {
449   gcc_assert (!objc_building_struct);
450   objc_building_struct = true;
451   return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
452 }
453
454 /* Finish building a struct for objc.  */
455
456 static tree
457 objc_finish_struct (tree type, tree fieldlist)
458 {
459   gcc_assert (objc_building_struct);
460   objc_building_struct = false;
461   return finish_struct (input_location, type, fieldlist, NULL_TREE,
462                         objc_struct_info);
463 }
464
465 static tree
466 build_sized_array_type (tree base_type, int size)
467 {
468   tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
469   return build_array_type (base_type, index_type);
470 }
471
472 static tree
473 add_field_decl (tree type, const char *name, tree **chain)
474 {
475   tree field = create_field_decl (type, name);
476
477   if (*chain != NULL)
478     **chain = field;
479   *chain = &DECL_CHAIN (field);
480
481   return field;
482 }
483
484 /* Some platforms pass small structures through registers versus
485    through an invisible pointer.  Determine at what size structure is
486    the transition point between the two possibilities.  */
487
488 static void
489 generate_struct_by_value_array (void)
490 {
491   tree type;
492   tree decls;
493   int i, j;
494   int aggregate_in_mem[32];
495   int found = 0;
496
497   /* Presumably no platform passes 32 byte structures in a register.  */
498   for (i = 1; i < 32; i++)
499     {
500       char buffer[5];
501       tree *chain = NULL;
502
503       /* Create an unnamed struct that has `i' character components */
504       type = objc_start_struct (NULL_TREE);
505
506       strcpy (buffer, "c1");
507       decls = add_field_decl (char_type_node, buffer, &chain);
508
509       for (j = 1; j < i; j++)
510         {
511           sprintf (buffer, "c%d", j + 1);
512           add_field_decl (char_type_node, buffer, &chain);
513         }
514       objc_finish_struct (type, decls);
515
516       aggregate_in_mem[i] = aggregate_value_p (type, 0);
517       if (!aggregate_in_mem[i])
518         found = 1;
519     }
520
521   /* We found some structures that are returned in registers instead of memory
522      so output the necessary data.  */
523   if (found)
524     {
525       for (i = 31; i >= 0;  i--)
526         if (!aggregate_in_mem[i])
527           break;
528       printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
529
530       /* The first member of the structure is always 0 because we don't handle
531          structures with 0 members */
532       printf ("static int struct_forward_array[] = {\n  0");
533
534       for (j = 1; j <= i; j++)
535         printf (", %d", aggregate_in_mem[j]);
536       printf ("\n};\n");
537     }
538
539   exit (0);
540 }
541
542 bool
543 objc_init (void)
544 {
545 #ifdef OBJCPLUS
546   if (cxx_init () == false)
547 #else
548   if (c_objc_common_init () == false)
549 #endif
550     return false;
551
552   /* If gen_declaration desired, open the output file.  */
553   if (flag_gen_declaration)
554     {
555       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
556       gen_declaration_file = fopen (dumpname, "w");
557       if (gen_declaration_file == 0)
558         fatal_error ("can't open %s: %m", dumpname);
559       free (dumpname);
560     }
561
562   if (flag_next_runtime)
563     {
564       TAG_GETCLASS = "objc_getClass";
565       TAG_GETMETACLASS = "objc_getMetaClass";
566       TAG_MSGSEND = "objc_msgSend";
567       TAG_MSGSENDSUPER = "objc_msgSendSuper";
568       TAG_MSGSEND_STRET = "objc_msgSend_stret";
569       TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
570       default_constant_string_class_name = "NSConstantString";
571     }
572   else
573     {
574       TAG_GETCLASS = "objc_get_class";
575       TAG_GETMETACLASS = "objc_get_meta_class";
576       TAG_MSGSEND = "objc_msg_lookup";
577       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
578       /* GNU runtime does not provide special functions to support
579          structure-returning methods.  */
580       default_constant_string_class_name = "NXConstantString";
581       flag_typed_selectors = 1;
582       /* GNU runtime does not need the compiler to change code
583          in order to do GC. */
584       if (flag_objc_gc)
585         {
586           warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
587           flag_objc_gc=0;
588         }
589     }
590
591   init_objc ();
592
593   if (print_struct_values && !flag_compare_debug)
594     generate_struct_by_value_array ();
595
596   return true;
597 }
598
599 /* This is called automatically (at the very end of compilation) by
600    c_write_global_declarations and cp_write_global_declarations.  */
601 void
602 objc_write_global_declarations (void)
603 {
604   mark_referenced_methods ();
605
606   /* Finalize Objective-C runtime data.  */
607   finish_objc ();
608
609   if (gen_declaration_file)
610     fclose (gen_declaration_file);
611 }
612 \f
613 /* Return the first occurrence of a method declaration corresponding
614    to sel_name in rproto_list.  Search rproto_list recursively.
615    If is_class is 0, search for instance methods, otherwise for class
616    methods.  */
617 static tree
618 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
619                                 int is_class)
620 {
621    tree rproto, p;
622    tree fnd = 0;
623
624    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
625      {
626         p = TREE_VALUE (rproto);
627
628         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
629           {
630             if ((fnd = lookup_method (is_class
631                                       ? PROTOCOL_CLS_METHODS (p)
632                                       : PROTOCOL_NST_METHODS (p), sel_name)))
633               ;
634             else if (PROTOCOL_LIST (p))
635               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
636                                                     sel_name, is_class);
637           }
638         else
639           {
640             ; /* An identifier...if we could not find a protocol.  */
641           }
642
643         if (fnd)
644           return fnd;
645      }
646
647    return 0;
648 }
649
650 static tree
651 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
652 {
653   tree rproto, p;
654
655   /* Make sure the protocol is supported by the object on the rhs.  */
656   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
657     {
658       tree fnd = 0;
659       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
660         {
661           p = TREE_VALUE (rproto);
662
663           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
664             {
665               if (lproto == p)
666                 fnd = lproto;
667
668               else if (PROTOCOL_LIST (p))
669                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
670             }
671
672           if (fnd)
673             return fnd;
674         }
675     }
676   else
677     {
678       ; /* An identifier...if we could not find a protocol.  */
679     }
680
681   return 0;
682 }
683
684 void
685 objc_start_class_interface (tree klass, tree super_class,
686                             tree protos, tree attributes)
687 {
688   if (attributes)
689     warning_at (input_location, OPT_Wattributes, 
690                 "class attributes are not available in this version"
691                 " of the compiler, (ignored)");
692   objc_interface_context
693     = objc_ivar_context
694     = start_class (CLASS_INTERFACE_TYPE, klass, super_class, protos);
695   objc_ivar_visibility = OBJC_IVAR_VIS_PROTECTED;
696 }
697
698 void
699 objc_start_category_interface (tree klass, tree categ,
700                                tree protos, tree attributes)
701 {
702   if (attributes)
703     warning_at (input_location, OPT_Wattributes, 
704                 "category attributes are not available in this version"
705                 " of the compiler, (ignored)");
706   objc_interface_context
707     = start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos);
708   objc_ivar_chain
709     = continue_class (objc_interface_context);
710 }
711
712 void
713 objc_start_protocol (tree name, tree protos, tree attributes)
714 {
715   if (attributes)
716     warning_at (input_location, OPT_Wattributes, 
717                 "protocol attributes are not available in this version"
718                 " of the compiler, (ignored)");
719   objc_interface_context
720     = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
721   objc_method_optional_flag = false;
722 }
723
724 void
725 objc_continue_interface (void)
726 {
727   objc_ivar_chain
728     = continue_class (objc_interface_context);
729 }
730
731 void
732 objc_finish_interface (void)
733 {
734   finish_class (objc_interface_context);
735   objc_interface_context = NULL_TREE;
736   objc_method_optional_flag = false;
737 }
738
739 void
740 objc_start_class_implementation (tree klass, tree super_class)
741 {
742   objc_implementation_context
743     = objc_ivar_context
744     = start_class (CLASS_IMPLEMENTATION_TYPE, klass, super_class, NULL_TREE);
745   objc_ivar_visibility = OBJC_IVAR_VIS_PROTECTED;
746 }
747
748 void
749 objc_start_category_implementation (tree klass, tree categ)
750 {
751   objc_implementation_context
752     = start_class (CATEGORY_IMPLEMENTATION_TYPE, klass, categ, NULL_TREE);
753   objc_ivar_chain
754     = continue_class (objc_implementation_context);
755 }
756
757 void
758 objc_continue_implementation (void)
759 {
760   objc_ivar_chain
761     = continue_class (objc_implementation_context);
762 }
763
764 void
765 objc_finish_implementation (void)
766 {
767 #ifdef OBJCPLUS
768   if (flag_objc_call_cxx_cdtors)
769     objc_generate_cxx_cdtors ();
770 #endif
771
772   if (objc_implementation_context)
773     {
774       finish_class (objc_implementation_context);
775       objc_ivar_chain = NULL_TREE;
776       objc_implementation_context = NULL_TREE;
777     }
778   else
779     warning (0, "%<@end%> must appear in an @implementation context");
780 }
781
782 void
783 objc_set_visibility (objc_ivar_visibility_kind visibility)
784 {
785   if (visibility == OBJC_IVAR_VIS_PACKAGE)
786     warning (0, "%<@package%> presently has the same effect as %<@public%>");
787   objc_ivar_visibility = visibility;
788 }
789
790 void
791 objc_set_method_opt (bool optional)
792 {
793   objc_method_optional_flag = optional;
794   if (!objc_interface_context 
795       || TREE_CODE (objc_interface_context) != PROTOCOL_INTERFACE_TYPE)
796     {
797       error ("@optional/@required is allowed in @protocol context only.");
798       objc_method_optional_flag = false;
799     }
800 }
801
802 /* This routine is called by the parser when a
803    @property... declaration is found.  'decl' is the declaration of
804    the property (type/identifier), and the other arguments represent
805    property attributes that may have been specified in the Objective-C
806    declaration.  'parsed_property_readonly' is 'true' if the attribute
807    'readonly' was specified, and 'false' if not; similarly for the
808    other bool parameters.  'parsed_property_getter_ident' is NULL_TREE
809    if the attribute 'getter' was not specified, and is the identifier
810    corresponding to the specified getter if it was; similarly for
811    'parsed_property_setter_ident'.  */
812 void
813 objc_add_property_declaration (location_t location, tree decl,
814                                bool parsed_property_readonly, bool parsed_property_readwrite,
815                                bool parsed_property_assign, bool parsed_property_retain,
816                                bool parsed_property_copy, bool parsed_property_nonatomic,
817                                tree parsed_property_getter_ident, tree parsed_property_setter_ident)
818 {
819   tree property_decl;
820   tree x;
821   /* 'property_readonly' and 'property_assign_semantics' are the final
822      attributes of the property after all parsed attributes have been
823      considered (eg, if we parsed no 'readonly' and no 'readwrite', ie
824      parsed_property_readonly = false and parsed_property_readwrite =
825      false, then property_readonly will be false because the default
826      is readwrite).  */
827   bool property_readonly = false;
828   objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
829
830   if (parsed_property_readonly && parsed_property_readwrite)
831     {
832       error_at (location, "%<readonly%> attribute conflicts with %<readwrite%> attribute");
833       /* In case of conflicting attributes (here and below), after
834          producing an error, we pick one of the attributes and keep
835          going.  */
836       property_readonly = false;
837     }
838   else
839     {
840       if (parsed_property_readonly)
841         property_readonly = true;
842   
843       if (parsed_property_readwrite)
844         property_readonly = false;
845     }
846
847   if (parsed_property_readonly && parsed_property_setter_ident)
848     {
849       /* Maybe this should be an error ?  The Apple documentation says it is a warning.  */
850       warning_at (location, 0, "%<readonly%> attribute conflicts with %<setter%> attribute");
851       property_readonly = false;
852     }
853
854   if (parsed_property_assign && parsed_property_retain)
855     {
856       error_at (location, "%<assign%> attribute conflicts with %<retain%> attribute");
857       property_assign_semantics = OBJC_PROPERTY_RETAIN;
858     }
859   else if (parsed_property_assign && parsed_property_copy)
860     {
861       error_at (location, "%<assign%> attribute conflicts with %<copy%> attribute");
862       property_assign_semantics = OBJC_PROPERTY_COPY;
863     }
864   else if (parsed_property_retain && parsed_property_copy)
865     {
866       error_at (location, "%<retain%> attribute conflicts with %<copy%> attribute");
867       property_assign_semantics = OBJC_PROPERTY_COPY;
868     }
869   else
870     {
871       if (parsed_property_assign)
872         property_assign_semantics = OBJC_PROPERTY_ASSIGN;
873
874       if (parsed_property_retain)
875         property_assign_semantics = OBJC_PROPERTY_RETAIN;
876
877       if (parsed_property_copy)
878         property_assign_semantics = OBJC_PROPERTY_COPY;
879     }
880
881   if (!objc_interface_context)
882     {
883       error_at (location, "property declaration not in @interface or @protocol context");
884       return;
885     }
886
887   /* At this point we know that we are either in an interface, a
888      category, or a protocol.  */
889
890   if (parsed_property_setter_ident)
891     {
892       /* The setter should be terminated by ':', but the parser only
893          gives us an identifier without ':'.  So, we need to add ':'
894          at the end.  */
895       const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
896       size_t length = strlen (parsed_setter);
897       char *final_setter = (char *)alloca (length + 2);
898
899       sprintf (final_setter, "%s:", parsed_setter);
900       parsed_property_setter_ident = get_identifier (final_setter);
901     }
902
903   /* Check that the property does not have an initial value specified.
904      This should never happen as the parser doesn't allow this, but
905      it's just in case.  */
906   if (DECL_INITIAL (decl))
907     {
908       error_at (location, "property can not have an initial value");
909       return;
910     }
911
912   /* TODO: Check that the property type is an Objective-C object or a "POD".  */
913
914   if (property_assign_semantics == OBJC_PROPERTY_ASSIGN)
915     {
916       /* If garbage collection is not being used, then 'assign' is
917          valid for objects (and typically used for delegates) but it
918          is wrong in most cases (since most objects need to be
919          retained or copied in setters).  Warn users when 'assign' is
920          used implicitly.  */
921       /* Please note that it would make sense to default to 'assign'
922          for non-{Objective-C objects}, and to 'retain' for
923          Objective-C objects.  But that would break compatibility with
924          other compilers.  */
925       if (!flag_objc_gc)
926         {
927           if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy)
928             {
929               if (objc_type_valid_for_messaging (TREE_TYPE (decl)))
930                 {
931                   warning_at (location, 
932                               0,
933                               "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>", 
934                               decl);
935                   inform (location, 
936                           "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
937                 }
938             }
939         }
940     }
941   
942   if (property_assign_semantics == OBJC_PROPERTY_RETAIN
943       && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
944     error_at (location, "%<retain%> attribute is only valid for Objective-C objects");
945   
946   if (property_assign_semantics == OBJC_PROPERTY_COPY
947       && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
948     error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
949
950   /* Check for duplicate property declarations.  We first check the
951      immediate context for a property with the same name.  */
952   for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
953     {
954       if (PROPERTY_NAME (x) == DECL_NAME (decl))
955         {
956           location_t original_location = DECL_SOURCE_LOCATION (x);
957           
958           error_at (location, "redeclaration of property %qD", decl);
959
960           if (original_location != UNKNOWN_LOCATION)
961             inform (original_location, "originally declared here");
962           return;
963       }
964     }
965
966   /* TODO: Shall we check here for other property declaractions (in
967      the superclass, other categories or protocols) with the same name
968      and conflicting types ?  */
969
970   /* Create a PROPERTY_DECL node.  */
971   property_decl = make_node (PROPERTY_DECL);
972
973   /* Copy the basic information from the original decl.  */
974   TREE_TYPE (property_decl) = TREE_TYPE (decl);
975   DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
976   TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
977   
978   /* Add property-specific information.  */
979   PROPERTY_NAME (property_decl) = DECL_NAME (decl);
980   PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
981   PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
982   PROPERTY_READONLY (property_decl) = property_readonly;
983   PROPERTY_NONATOMIC (property_decl) = parsed_property_nonatomic;
984   PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics;
985   PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
986   PROPERTY_DYNAMIC (property_decl) = 0;
987
988   /* Add the PROPERTY_DECL to the list of properties for the class.  */
989   TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
990   CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
991 }
992
993 /* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or
994    PROTOCOL.  */
995 static tree
996 lookup_property_in_list (tree chain, tree property)
997 {
998   tree x;
999   for (x = CLASS_PROPERTY_DECL (chain); x; x = TREE_CHAIN (x))
1000     if (PROPERTY_NAME (x) == property)
1001       return x;
1002   return NULL_TREE;
1003 }
1004
1005 /* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */
1006 static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
1007 {
1008   tree rproto, x;
1009   for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
1010     {
1011       tree p = TREE_VALUE (rproto);
1012       if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
1013         {
1014           if ((x = lookup_property_in_list (p, property)))
1015             return x;
1016           if (PROTOCOL_LIST (p))
1017             return lookup_property_in_protocol_list (PROTOCOL_LIST (p), property);
1018         }
1019       else
1020         {
1021           ; /* An identifier...if we could not find a protocol.  */
1022         }
1023     }
1024   return NULL_TREE;
1025 }
1026
1027 /* This routine looks up the PROPERTY in current INTERFACE, its categories and up the
1028    chain of interface hierarchy.  */
1029 static tree
1030 lookup_property (tree interface_type, tree property)
1031 {
1032   tree inter = interface_type;
1033   while (inter)
1034     {
1035       tree x, category;
1036       if ((x = lookup_property_in_list (inter, property)))
1037         return x;
1038       /* Failing that, look for the property in each category of the class.  */
1039       category = inter;
1040       while ((category = CLASS_CATEGORY_LIST (category)))
1041         if ((x = lookup_property_in_list (category, property)))
1042           return x;
1043
1044       /*  Failing to find in categories, look for property in protocol list. */
1045       if (CLASS_PROTOCOL_LIST (inter) 
1046           && (x = lookup_property_in_protocol_list (
1047                     CLASS_PROTOCOL_LIST (inter), property)))
1048         return x;
1049       
1050       /* Failing that, climb up the inheritance hierarchy.  */
1051       inter = lookup_interface (CLASS_SUPER_NAME (inter));
1052     }
1053   return inter;
1054 }
1055
1056
1057 /* This hook routine is invoked by the parser when an expression such
1058    as 'xxx.yyy' is parsed.  We get a chance to process these
1059    expressions in a way that is specified to Objective-C (to implement
1060    properties, or non-fragile ivars).  If the expression is not an
1061    Objective-C specified expression, we should return NULL_TREE; else
1062    we return the expression.
1063
1064    At the moment this only implements properties (not non-fragile
1065    ivars yet), ie 'object.property'.  */
1066 tree
1067 objc_maybe_build_component_ref (tree object, tree property_ident)
1068 {
1069   tree x = NULL_TREE;
1070   tree rtype;
1071
1072   /* Try to determine quickly if 'object' is an Objective-C object or
1073      not.  If not, return.  */
1074   if (object == NULL_TREE || object == error_mark_node 
1075       || (rtype = TREE_TYPE (object)) == NULL_TREE)
1076     return NULL_TREE;
1077   
1078   if (property_ident == NULL_TREE || property_ident == error_mark_node
1079       || TREE_CODE (property_ident) != IDENTIFIER_NODE)
1080     return NULL_TREE;
1081
1082   /* TODO: Implement super.property.  */
1083   
1084   /* TODO: Carefully review the following code.  */
1085   if (objc_is_id (rtype))
1086     {
1087       tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
1088                       ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
1089                       : NULL_TREE);
1090       if (rprotos)
1091         x = lookup_property_in_protocol_list (rprotos, property_ident);
1092     }
1093   else
1094     {
1095       tree basetype = TYPE_MAIN_VARIANT (rtype);
1096
1097       if (basetype != NULL_TREE && TREE_CODE (basetype) == POINTER_TYPE)
1098         basetype = TREE_TYPE (basetype);
1099       else
1100         return NULL_TREE;
1101
1102       while (basetype != NULL_TREE
1103              && TREE_CODE (basetype) == RECORD_TYPE 
1104              && OBJC_TYPE_NAME (basetype)
1105              && TREE_CODE (OBJC_TYPE_NAME (basetype)) == TYPE_DECL
1106              && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (basetype)))
1107         basetype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (basetype));
1108
1109       if (basetype != NULL_TREE && TYPED_OBJECT (basetype))
1110         {
1111           tree interface_type = TYPE_OBJC_INTERFACE (basetype);
1112           tree protocol_list = TYPE_OBJC_PROTOCOL_LIST (basetype);
1113           
1114           x = lookup_property (interface_type, property_ident);
1115
1116           if (x == NULL_TREE)
1117             x = lookup_property_in_protocol_list (protocol_list, property_ident);
1118         }
1119     }
1120
1121   if (x)
1122     {
1123       tree expression;
1124
1125       expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
1126       SET_EXPR_LOCATION (expression, input_location);
1127       TREE_SIDE_EFFECTS (expression) = 1;
1128
1129       /* We have an additional nasty problem here; if this
1130          PROPERTY_REF needs to become a 'getter', then the conversion
1131          from PROPERTY_REF into a getter call happens in gimplify,
1132          after the selector table has already been generated and it is
1133          too late to add another selector to it.  To work around the
1134          problem, we always put the selector in the table at this
1135          stage, as if we were building the method call here.  And the
1136          easiest way to do this is precisely to build the method call,
1137          then discard it.  Note that if the PROPERTY_REF becomes a
1138          'setter' instead of a 'getter', then we have added a selector
1139          too many to the selector table.  This is a little
1140          inefficient.
1141
1142          TODO: This can be made more efficient; in particular we don't
1143          need to build the whole message call, we could just work on
1144          the selector.  */
1145       objc_finish_message_expr (object,
1146                                 PROPERTY_GETTER_NAME (x),
1147                                 NULL_TREE);
1148       
1149       return expression;
1150     }
1151
1152   return NULL_TREE;
1153 }
1154
1155 /* This is used because we don't want to expose PROPERTY_REF to the
1156    C/C++ frontends.  Maybe we should!  */
1157 bool
1158 objc_is_property_ref (tree node)
1159 {
1160   if (node  &&  TREE_CODE (node) == PROPERTY_REF)
1161     return true;
1162   else
1163     return false;
1164 }
1165
1166 /* This hook routine is called when a MODIFY_EXPR is being built.  We
1167    check what is being modified; if it is a PROPERTY_REF, we need to
1168    generate a 'setter' function call for the property.  If this is not
1169    a PROPERTY_REF, we return NULL_TREE and the C/C++ frontend will go
1170    on creating their MODIFY_EXPR.
1171
1172    This is used for example if you write
1173
1174    object.count = 1;
1175
1176    where 'count' is a property.  The left-hand side creates a
1177    PROPERTY_REF, and then the compiler tries to generate a MODIFY_EXPR
1178    to assign something to it.  We intercept that here, and generate a
1179    call to the 'setter' method instead.  */
1180 tree
1181 objc_maybe_build_modify_expr (tree lhs, tree rhs)
1182 {
1183   if (lhs && TREE_CODE (lhs) == PROPERTY_REF)
1184     {
1185       tree object_expr = PROPERTY_REF_OBJECT (lhs);
1186       tree property_decl = PROPERTY_REF_PROPERTY_DECL (lhs);
1187
1188       if (PROPERTY_READONLY (property_decl))
1189         {
1190           error ("readonly property can not be set");     
1191           return error_mark_node;
1192         }
1193       else
1194         {
1195           tree setter_argument = build_tree_list (NULL_TREE, rhs);
1196           tree setter;
1197           /* TODO: Decay argument in C.  */
1198           setter = objc_finish_message_expr (object_expr, 
1199                                              PROPERTY_SETTER_NAME (property_decl),
1200                                              setter_argument);
1201           return setter;
1202         }
1203     }
1204   else
1205     return NULL_TREE;
1206 }
1207
1208 tree
1209 objc_build_method_signature (bool is_class_method, tree rettype, tree selector,
1210                              tree optparms, bool ellipsis)
1211 {
1212   if (is_class_method)
1213     return build_method_decl (CLASS_METHOD_DECL, rettype, selector,
1214                               optparms, ellipsis);
1215   else
1216     return build_method_decl (INSTANCE_METHOD_DECL, rettype, selector,
1217                               optparms, ellipsis);
1218 }
1219
1220 void
1221 objc_add_method_declaration (bool is_class_method, tree decl, tree attributes)
1222 {
1223   if (!objc_interface_context)
1224     {
1225       /* PS: At the moment, due to how the parser works, it should be
1226          impossible to get here.  But it's good to have the check in
1227          case the parser changes.
1228       */
1229       fatal_error ("method declaration not in @interface context");
1230     }
1231
1232   objc_decl_method_attributes (&decl, attributes, 0);
1233   objc_add_method (objc_interface_context,
1234                    decl,
1235                    is_class_method,
1236                    objc_method_optional_flag);
1237 }
1238
1239 /* Return 'true' if the method definition could be started, and
1240    'false' if not (because we are outside an @implementation context).
1241 */
1242 bool
1243 objc_start_method_definition (bool is_class_method, tree decl, tree attributes)
1244 {
1245   if (!objc_implementation_context)
1246     {
1247       error ("method definition not in @implementation context");
1248       return false;
1249     }
1250
1251   if (decl != NULL_TREE  && METHOD_SEL_NAME (decl) == error_mark_node)
1252     return false;
1253
1254 #ifndef OBJCPLUS
1255   /* Indicate no valid break/continue context by setting these variables
1256      to some non-null, non-label value.  We'll notice and emit the proper
1257      error message in c_finish_bc_stmt.  */
1258   c_break_label = c_cont_label = size_zero_node;
1259 #endif
1260
1261   objc_decl_method_attributes (&decl, attributes, 0);
1262   objc_add_method (objc_implementation_context,
1263                    decl,
1264                    is_class_method,
1265                    /* is optional */ false);
1266   start_method_def (decl);
1267   return true;
1268 }
1269
1270 void
1271 objc_add_instance_variable (tree decl)
1272 {
1273   (void) add_instance_variable (objc_ivar_context,
1274                                 objc_ivar_visibility,
1275                                 decl);
1276 }
1277
1278 /* Return true if TYPE is 'id'.  */
1279
1280 static bool
1281 objc_is_object_id (tree type)
1282 {
1283   return OBJC_TYPE_NAME (type) == objc_object_id;
1284 }
1285
1286 static bool
1287 objc_is_class_id (tree type)
1288 {
1289   return OBJC_TYPE_NAME (type) == objc_class_id;
1290 }
1291
1292 /* Construct a C struct with same name as KLASS, a base struct with tag
1293    SUPER_NAME (if any), and FIELDS indicated.  */
1294
1295 static tree
1296 objc_build_struct (tree klass, tree fields, tree super_name)
1297 {
1298   tree name = CLASS_NAME (klass);
1299   tree s = objc_start_struct (name);
1300   tree super = (super_name ? xref_tag (RECORD_TYPE, super_name) : NULL_TREE);
1301   tree t;
1302   VEC(tree,heap) *objc_info = NULL;
1303   int i;
1304
1305   if (super)
1306     {
1307       /* Prepend a packed variant of the base class into the layout.  This
1308          is necessary to preserve ObjC ABI compatibility.  */
1309       tree base = build_decl (input_location,
1310                               FIELD_DECL, NULL_TREE, super);
1311       tree field = TYPE_FIELDS (super);
1312
1313       while (field && DECL_CHAIN (field)
1314              && TREE_CODE (DECL_CHAIN (field)) == FIELD_DECL)
1315         field = DECL_CHAIN (field);
1316
1317       /* For ObjC ABI purposes, the "packed" size of a base class is
1318          the sum of the offset and the size (in bits) of the last field
1319          in the class.  */
1320       DECL_SIZE (base)
1321         = (field && TREE_CODE (field) == FIELD_DECL
1322            ? size_binop (PLUS_EXPR,
1323                          size_binop (PLUS_EXPR,
1324                                      size_binop
1325                                      (MULT_EXPR,
1326                                       convert (bitsizetype,
1327                                                DECL_FIELD_OFFSET (field)),
1328                                       bitsize_int (BITS_PER_UNIT)),
1329                                      DECL_FIELD_BIT_OFFSET (field)),
1330                          DECL_SIZE (field))
1331            : bitsize_zero_node);
1332       DECL_SIZE_UNIT (base)
1333         = size_binop (FLOOR_DIV_EXPR, convert (sizetype, DECL_SIZE (base)),
1334                       size_int (BITS_PER_UNIT));
1335       DECL_ARTIFICIAL (base) = 1;
1336       DECL_ALIGN (base) = 1;
1337       DECL_FIELD_CONTEXT (base) = s;
1338 #ifdef OBJCPLUS
1339       DECL_FIELD_IS_BASE (base) = 1;
1340
1341       if (fields)
1342         TREE_NO_WARNING (fields) = 1;   /* Suppress C++ ABI warnings -- we   */
1343 #endif                                  /* are following the ObjC ABI here.  */
1344       DECL_CHAIN (base) = fields;
1345       fields = base;
1346     }
1347
1348   /* NB: Calling finish_struct() may cause type TYPE_LANG_SPECIFIC fields
1349      in all variants of this RECORD_TYPE to be clobbered, but it is therein
1350      that we store protocol conformance info (e.g., 'NSObject <MyProtocol>').
1351      Hence, we must squirrel away the ObjC-specific information before calling
1352      finish_struct(), and then reinstate it afterwards.  */
1353
1354   for (t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t))
1355     {
1356       if (!TYPE_HAS_OBJC_INFO (t))
1357         {
1358           INIT_TYPE_OBJC_INFO (t);
1359           TYPE_OBJC_INTERFACE (t) = klass;
1360         }
1361       VEC_safe_push (tree, heap, objc_info, TYPE_OBJC_INFO (t));
1362     }
1363
1364   /* Point the struct at its related Objective-C class.  */
1365   INIT_TYPE_OBJC_INFO (s);
1366   TYPE_OBJC_INTERFACE (s) = klass;
1367
1368   s = objc_finish_struct (s, fields);
1369
1370   for (i = 0, t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t), i++)
1371     {
1372       TYPE_OBJC_INFO (t) = VEC_index (tree, objc_info, i);
1373       /* Replace the IDENTIFIER_NODE with an actual @interface.  */
1374       TYPE_OBJC_INTERFACE (t) = klass;
1375     }
1376   VEC_free (tree, heap, objc_info);
1377
1378   /* Use TYPE_BINFO structures to point at the super class, if any.  */
1379   objc_xref_basetypes (s, super);
1380
1381   /* Mark this struct as a class template.  */
1382   CLASS_STATIC_TEMPLATE (klass) = s;
1383
1384   return s;
1385 }
1386
1387 /* Build a type differing from TYPE only in that TYPE_VOLATILE is set.
1388    Unlike tree.c:build_qualified_type(), preserve TYPE_LANG_SPECIFIC in the
1389    process.  */
1390 static tree
1391 objc_build_volatilized_type (tree type)
1392 {
1393   tree t;
1394
1395   /* Check if we have not constructed the desired variant already.  */
1396   for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
1397     {
1398       /* The type qualifiers must (obviously) match up.  */
1399       if (!TYPE_VOLATILE (t)
1400           || (TYPE_READONLY (t) != TYPE_READONLY (type))
1401           || (TYPE_RESTRICT (t) != TYPE_RESTRICT (type)))
1402         continue;
1403
1404       /* For pointer types, the pointees (and hence their TYPE_LANG_SPECIFIC
1405          info, if any) must match up.  */
1406       if (POINTER_TYPE_P (t)
1407           && (TREE_TYPE (t) != TREE_TYPE (type)))
1408         continue;
1409
1410       /* Only match up the types which were previously volatilized in similar fashion and not
1411          because they were declared as such. */
1412       if (!lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (t)))
1413         continue;
1414
1415       /* Everything matches up!  */
1416       return t;
1417     }
1418
1419   /* Ok, we could not re-use any of the pre-existing variants.  Create
1420      a new one.  */
1421   t = build_variant_type_copy (type);
1422   TYPE_VOLATILE (t) = 1;
1423
1424   TYPE_ATTRIBUTES (t) = merge_attributes (TYPE_ATTRIBUTES (type),
1425                                           tree_cons (get_identifier ("objc_volatilized"),
1426                                           NULL_TREE,
1427                                           NULL_TREE));
1428   if (TREE_CODE (t) == ARRAY_TYPE)
1429     TREE_TYPE (t) = objc_build_volatilized_type (TREE_TYPE (t));
1430
1431   /* Set up the canonical type information. */
1432   if (TYPE_STRUCTURAL_EQUALITY_P (type))
1433     SET_TYPE_STRUCTURAL_EQUALITY (t);
1434   else if (TYPE_CANONICAL (type) != type)
1435     TYPE_CANONICAL (t) = objc_build_volatilized_type (TYPE_CANONICAL (type));
1436   else
1437     TYPE_CANONICAL (t) = t;
1438
1439   return t;
1440 }
1441
1442 /* Mark DECL as being 'volatile' for purposes of Darwin
1443    _setjmp()/_longjmp() exception handling.  Called from
1444    objc_mark_locals_volatile().  */
1445 void
1446 objc_volatilize_decl (tree decl)
1447 {
1448   /* Do not mess with variables that are 'static' or (already)
1449      'volatile'.  */
1450   if (!TREE_THIS_VOLATILE (decl) && !TREE_STATIC (decl)
1451       && (TREE_CODE (decl) == VAR_DECL
1452           || TREE_CODE (decl) == PARM_DECL))
1453     {
1454       tree t = TREE_TYPE (decl);
1455
1456       t = objc_build_volatilized_type (t);
1457
1458       TREE_TYPE (decl) = t;
1459       TREE_THIS_VOLATILE (decl) = 1;
1460       TREE_SIDE_EFFECTS (decl) = 1;
1461       DECL_REGISTER (decl) = 0;
1462 #ifndef OBJCPLUS
1463       C_DECL_REGISTER (decl) = 0;
1464 #endif
1465     }
1466 }
1467
1468 /* Check if protocol PROTO is adopted (directly or indirectly) by class CLS
1469    (including its categories and superclasses) or by object type TYP.
1470    Issue a warning if PROTO is not adopted anywhere and WARN is set.  */
1471
1472 static bool
1473 objc_lookup_protocol (tree proto, tree cls, tree typ, bool warn)
1474 {
1475   bool class_type = (cls != NULL_TREE);
1476
1477   while (cls)
1478     {
1479       tree c;
1480
1481       /* Check protocols adopted by the class and its categories.  */
1482       for (c = cls; c; c = CLASS_CATEGORY_LIST (c))
1483         {
1484           if (lookup_protocol_in_reflist (CLASS_PROTOCOL_LIST (c), proto))
1485             return true;
1486         }
1487
1488       /* Repeat for superclasses.  */
1489       cls = lookup_interface (CLASS_SUPER_NAME (cls));
1490     }
1491
1492   /* Check for any protocols attached directly to the object type.  */
1493   if (TYPE_HAS_OBJC_INFO (typ))
1494     {
1495       if (lookup_protocol_in_reflist (TYPE_OBJC_PROTOCOL_LIST (typ), proto))
1496         return true;
1497     }
1498
1499   if (warn)
1500     {
1501       *errbuf = 0;
1502       gen_type_name_0 (class_type ? typ : TYPE_POINTER_TO (typ));
1503       /* NB: Types 'id' and 'Class' cannot reasonably be described as
1504          "implementing" a given protocol, since they do not have an
1505          implementation.  */
1506       if (class_type)
1507         warning (0, "class %qs does not implement the %qE protocol",
1508                  identifier_to_locale (errbuf), PROTOCOL_NAME (proto));
1509       else
1510         warning (0, "type %qs does not conform to the %qE protocol",
1511                  identifier_to_locale (errbuf), PROTOCOL_NAME (proto));
1512     }
1513
1514   return false;
1515 }
1516
1517 /* Check if class RCLS and instance struct type RTYP conform to at least the
1518    same protocols that LCLS and LTYP conform to.  */
1519
1520 static bool
1521 objc_compare_protocols (tree lcls, tree ltyp, tree rcls, tree rtyp, bool warn)
1522 {
1523   tree p;
1524   bool have_lproto = false;
1525
1526   while (lcls)
1527     {
1528       /* NB: We do _not_ look at categories defined for LCLS; these may or
1529          may not get loaded in, and therefore it is unreasonable to require
1530          that RCLS/RTYP must implement any of their protocols.  */
1531       for (p = CLASS_PROTOCOL_LIST (lcls); p; p = TREE_CHAIN (p))
1532         {
1533           have_lproto = true;
1534
1535           if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1536             return warn;
1537         }
1538
1539       /* Repeat for superclasses.  */
1540       lcls = lookup_interface (CLASS_SUPER_NAME (lcls));
1541     }
1542
1543   /* Check for any protocols attached directly to the object type.  */
1544   if (TYPE_HAS_OBJC_INFO (ltyp))
1545     {
1546       for (p = TYPE_OBJC_PROTOCOL_LIST (ltyp); p; p = TREE_CHAIN (p))
1547         {
1548           have_lproto = true;
1549
1550           if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1551             return warn;
1552         }
1553     }
1554
1555   /* NB: If LTYP and LCLS have no protocols to search for, return 'true'
1556      vacuously, _unless_ RTYP is a protocol-qualified 'id'.  We can get
1557      away with simply checking for 'id' or 'Class' (!RCLS), since this
1558      routine will not get called in other cases.  */
1559   return have_lproto || (rcls != NULL_TREE);
1560 }
1561
1562 /* Given two types TYPE1 and TYPE2, return their least common ancestor.
1563    Both TYPE1 and TYPE2 must be pointers, and already determined to be
1564    compatible by objc_compare_types() below.  */
1565
1566 tree
1567 objc_common_type (tree type1, tree type2)
1568 {
1569   tree inner1 = TREE_TYPE (type1), inner2 = TREE_TYPE (type2);
1570
1571   while (POINTER_TYPE_P (inner1))
1572     {
1573       inner1 = TREE_TYPE (inner1);
1574       inner2 = TREE_TYPE (inner2);
1575     }
1576
1577   /* If one type is derived from another, return the base type.  */
1578   if (DERIVED_FROM_P (inner1, inner2))
1579     return type1;
1580   else if (DERIVED_FROM_P (inner2, inner1))
1581     return type2;
1582
1583   /* If both types are 'Class', return 'Class'.  */
1584   if (objc_is_class_id (inner1) && objc_is_class_id (inner2))
1585     return objc_class_type;
1586
1587   /* Otherwise, return 'id'.  */
1588   return objc_object_type;
1589 }
1590
1591 /* Determine if it is permissible to assign (if ARGNO is greater than -3)
1592    an instance of RTYP to an instance of LTYP or to compare the two
1593    (if ARGNO is equal to -3), per ObjC type system rules.  Before
1594    returning 'true', this routine may issue warnings related to, e.g.,
1595    protocol conformance.  When returning 'false', the routine must
1596    produce absolutely no warnings; the C or C++ front-end will do so
1597    instead, if needed.  If either LTYP or RTYP is not an Objective-C type,
1598    the routine must return 'false'.
1599
1600    The ARGNO parameter is encoded as follows:
1601      >= 1       Parameter number (CALLEE contains function being called);
1602      0          Return value;
1603      -1         Assignment;
1604      -2         Initialization;
1605      -3         Comparison (LTYP and RTYP may match in either direction);
1606      -4         Silent comparison (for C++ overload resolution).
1607   */
1608
1609 bool
1610 objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
1611 {
1612   tree lcls, rcls, lproto, rproto;
1613   bool pointers_compatible;
1614
1615   /* We must be dealing with pointer types */
1616   if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
1617     return false;
1618
1619   do
1620     {
1621       ltyp = TREE_TYPE (ltyp);  /* Remove indirections.  */
1622       rtyp = TREE_TYPE (rtyp);
1623     }
1624   while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
1625
1626   /* We must also handle function pointers, since ObjC is a bit more
1627      lenient than C or C++ on this.  */
1628   if (TREE_CODE (ltyp) == FUNCTION_TYPE && TREE_CODE (rtyp) == FUNCTION_TYPE)
1629     {
1630       /* Return types must be covariant.  */
1631       if (!comptypes (TREE_TYPE (ltyp), TREE_TYPE (rtyp))
1632           && !objc_compare_types (TREE_TYPE (ltyp), TREE_TYPE (rtyp),
1633                                   argno, callee))
1634       return false;
1635
1636       /* Argument types must be contravariant.  */
1637       for (ltyp = TYPE_ARG_TYPES (ltyp), rtyp = TYPE_ARG_TYPES (rtyp);
1638            ltyp && rtyp; ltyp = TREE_CHAIN (ltyp), rtyp = TREE_CHAIN (rtyp))
1639         {
1640           if (!comptypes (TREE_VALUE (rtyp), TREE_VALUE (ltyp))
1641               && !objc_compare_types (TREE_VALUE (rtyp), TREE_VALUE (ltyp),
1642                                       argno, callee))
1643             return false;
1644       }
1645
1646       return (ltyp == rtyp);
1647     }
1648
1649   /* Past this point, we are only interested in ObjC class instances,
1650      or 'id' or 'Class'.  */
1651   if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
1652     return false;
1653
1654   if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
1655       && !TYPE_HAS_OBJC_INFO (ltyp))
1656     return false;
1657
1658   if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
1659       && !TYPE_HAS_OBJC_INFO (rtyp))
1660     return false;
1661
1662   /* Past this point, we are committed to returning 'true' to the caller
1663      (unless performing a silent comparison; see below).  However, we can
1664      still warn about type and/or protocol mismatches.  */
1665
1666   if (TYPE_HAS_OBJC_INFO (ltyp))
1667     {
1668       lcls = TYPE_OBJC_INTERFACE (ltyp);
1669       lproto = TYPE_OBJC_PROTOCOL_LIST (ltyp);
1670     }
1671   else
1672     lcls = lproto = NULL_TREE;
1673
1674   if (TYPE_HAS_OBJC_INFO (rtyp))
1675     {
1676       rcls = TYPE_OBJC_INTERFACE (rtyp);
1677       rproto = TYPE_OBJC_PROTOCOL_LIST (rtyp);
1678     }
1679   else
1680     rcls = rproto = NULL_TREE;
1681
1682   /* If we could not find an @interface declaration, we must have
1683      only seen a @class declaration; for purposes of type comparison,
1684      treat it as a stand-alone (root) class.  */
1685
1686   if (lcls && TREE_CODE (lcls) == IDENTIFIER_NODE)
1687     lcls = NULL_TREE;
1688
1689   if (rcls && TREE_CODE (rcls) == IDENTIFIER_NODE)
1690     rcls = NULL_TREE;
1691
1692   /* If either type is an unqualified 'id', we're done.  */
1693   if ((!lproto && objc_is_object_id (ltyp))
1694       || (!rproto && objc_is_object_id (rtyp)))
1695     return true;
1696
1697   pointers_compatible = (TYPE_MAIN_VARIANT (ltyp) == TYPE_MAIN_VARIANT (rtyp));
1698
1699   /* If the underlying types are the same, and at most one of them has
1700      a protocol list, we do not need to issue any diagnostics.  */
1701   if (pointers_compatible && (!lproto || !rproto))
1702     return true;
1703
1704   /* If exactly one of the types is 'Class', issue a diagnostic; any
1705      exceptions of this rule have already been handled.  */
1706   if (objc_is_class_id (ltyp) ^ objc_is_class_id (rtyp))
1707     pointers_compatible = false;
1708   /* Otherwise, check for inheritance relations.  */
1709   else
1710     {
1711       if (!pointers_compatible)
1712         pointers_compatible
1713           = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp));
1714
1715       if (!pointers_compatible)
1716         pointers_compatible = DERIVED_FROM_P (ltyp, rtyp);
1717
1718       if (!pointers_compatible && argno <= -3)
1719         pointers_compatible = DERIVED_FROM_P (rtyp, ltyp);
1720     }
1721
1722   /* If the pointers match modulo protocols, check for protocol conformance
1723      mismatches.  */
1724   if (pointers_compatible)
1725     {
1726       pointers_compatible = objc_compare_protocols (lcls, ltyp, rcls, rtyp,
1727                                                     argno != -3);
1728
1729       if (!pointers_compatible && argno == -3)
1730         pointers_compatible = objc_compare_protocols (rcls, rtyp, lcls, ltyp,
1731                                                       argno != -3);
1732     }
1733
1734   if (!pointers_compatible)
1735     {
1736       /* The two pointers are not exactly compatible.  Issue a warning, unless
1737          we are performing a silent comparison, in which case return 'false'
1738          instead.  */
1739       /* NB: For the time being, we shall make our warnings look like their
1740          C counterparts.  In the future, we may wish to make them more
1741          ObjC-specific.  */
1742       switch (argno)
1743         {
1744         case -4:
1745           return false;
1746
1747         case -3:
1748           warning (0, "comparison of distinct Objective-C types lacks a cast");
1749           break;
1750
1751         case -2:
1752           warning (0, "initialization from distinct Objective-C type");
1753           break;
1754
1755         case -1:
1756           warning (0, "assignment from distinct Objective-C type");
1757           break;
1758
1759         case 0:
1760           warning (0, "distinct Objective-C type in return");
1761           break;
1762
1763         default:
1764           warning (0, "passing argument %d of %qE from distinct "
1765                    "Objective-C type", argno, callee);
1766           break;
1767         }
1768     }
1769
1770   return true;
1771 }
1772
1773 /* This routine is similar to objc_compare_types except that function-pointers are
1774    excluded. This is because, caller assumes that common types are of (id, Object*)
1775    variety and calls objc_common_type to obtain a common type. There is no commonolty
1776    between two function-pointers in this regard. */
1777
1778 bool 
1779 objc_have_common_type (tree ltyp, tree rtyp, int argno, tree callee)
1780 {
1781   if (objc_compare_types (ltyp, rtyp, argno, callee))
1782     {
1783       /* exclude function-pointer types. */
1784       do
1785         {
1786           ltyp = TREE_TYPE (ltyp);  /* Remove indirections.  */
1787           rtyp = TREE_TYPE (rtyp);
1788         }
1789       while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
1790       return !(TREE_CODE (ltyp) == FUNCTION_TYPE && TREE_CODE (rtyp) == FUNCTION_TYPE);
1791     }
1792   return false;
1793 }
1794
1795 /* Check if LTYP and RTYP have the same type qualifiers.  If either type
1796    lives in the volatilized hash table, ignore the 'volatile' bit when
1797    making the comparison.  */
1798
1799 bool
1800 objc_type_quals_match (tree ltyp, tree rtyp)
1801 {
1802   int lquals = TYPE_QUALS (ltyp), rquals = TYPE_QUALS (rtyp);
1803
1804   if (lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (ltyp)))
1805     lquals &= ~TYPE_QUAL_VOLATILE;
1806
1807   if (lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (rtyp)))
1808     rquals &= ~TYPE_QUAL_VOLATILE;
1809
1810   return (lquals == rquals);
1811 }
1812
1813 #ifndef OBJCPLUS
1814 /* Determine if CHILD is derived from PARENT.  The routine assumes that
1815    both parameters are RECORD_TYPEs, and is non-reflexive.  */
1816
1817 static bool
1818 objc_derived_from_p (tree parent, tree child)
1819 {
1820   parent = TYPE_MAIN_VARIANT (parent);
1821
1822   for (child = TYPE_MAIN_VARIANT (child);
1823        TYPE_BINFO (child) && BINFO_N_BASE_BINFOS (TYPE_BINFO (child));)
1824     {
1825       child = TYPE_MAIN_VARIANT (BINFO_TYPE (BINFO_BASE_BINFO
1826                                              (TYPE_BINFO (child),
1827                                               0)));
1828
1829       if (child == parent)
1830         return true;
1831     }
1832
1833   return false;
1834 }
1835 #endif
1836
1837 static tree
1838 objc_build_component_ref (tree datum, tree component)
1839 {
1840   /* If COMPONENT is NULL, the caller is referring to the anonymous
1841      base class field.  */
1842   if (!component)
1843     {
1844       tree base = TYPE_FIELDS (TREE_TYPE (datum));
1845
1846       return build3 (COMPONENT_REF, TREE_TYPE (base), datum, base, NULL_TREE);
1847     }
1848
1849   /* The 'build_component_ref' routine has been removed from the C++
1850      front-end, but 'finish_class_member_access_expr' seems to be
1851      a worthy substitute.  */
1852 #ifdef OBJCPLUS
1853   return finish_class_member_access_expr (datum, component, false,
1854                                           tf_warning_or_error);
1855 #else
1856   return build_component_ref (input_location, datum, component);
1857 #endif
1858 }
1859
1860 /* Recursively copy inheritance information rooted at BINFO.  To do this,
1861    we emulate the song and dance performed by cp/tree.c:copy_binfo().  */
1862
1863 static tree
1864 objc_copy_binfo (tree binfo)
1865 {
1866   tree btype = BINFO_TYPE (binfo);
1867   tree binfo2 = make_tree_binfo (BINFO_N_BASE_BINFOS (binfo));
1868   tree base_binfo;
1869   int ix;
1870
1871   BINFO_TYPE (binfo2) = btype;
1872   BINFO_OFFSET (binfo2) = BINFO_OFFSET (binfo);
1873   BINFO_BASE_ACCESSES (binfo2) = BINFO_BASE_ACCESSES (binfo);
1874
1875   /* Recursively copy base binfos of BINFO.  */
1876   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
1877     {
1878       tree base_binfo2 = objc_copy_binfo (base_binfo);
1879
1880       BINFO_INHERITANCE_CHAIN (base_binfo2) = binfo2;
1881       BINFO_BASE_APPEND (binfo2, base_binfo2);
1882     }
1883
1884   return binfo2;
1885 }
1886
1887 /* Record superclass information provided in BASETYPE for ObjC class REF.
1888    This is loosely based on cp/decl.c:xref_basetypes().  */
1889
1890 static void
1891 objc_xref_basetypes (tree ref, tree basetype)
1892 {
1893   tree binfo = make_tree_binfo (basetype ? 1 : 0);
1894
1895   TYPE_BINFO (ref) = binfo;
1896   BINFO_OFFSET (binfo) = size_zero_node;
1897   BINFO_TYPE (binfo) = ref;
1898
1899   if (basetype)
1900     {
1901       tree base_binfo = objc_copy_binfo (TYPE_BINFO (basetype));
1902
1903       BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
1904       BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, 1);
1905       BINFO_BASE_APPEND (binfo, base_binfo);
1906       BINFO_BASE_ACCESS_APPEND (binfo, access_public_node);
1907     }
1908 }
1909
1910 /* Called from finish_decl.  */
1911
1912 void
1913 objc_check_decl (tree decl)
1914 {
1915   tree type = TREE_TYPE (decl);
1916
1917   if (TREE_CODE (type) != RECORD_TYPE)
1918     return;
1919   if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
1920     error ("statically allocated instance of Objective-C class %qE",
1921            type);
1922 }
1923
1924 void
1925 objc_check_global_decl (tree decl)
1926 {
1927   tree id = DECL_NAME (decl);
1928   if (objc_is_class_name (id) && global_bindings_p())
1929     error ("redeclaration of Objective-C class %qs", IDENTIFIER_POINTER (id));
1930 }
1931
1932 /* Return a non-volatalized version of TYPE. */
1933
1934 tree
1935 objc_non_volatilized_type (tree type)
1936 {
1937   if (lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (type)))
1938     type = build_qualified_type (type, (TYPE_QUALS (type) & ~TYPE_QUAL_VOLATILE));
1939   return type;
1940 }
1941
1942 /* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
1943    either name an Objective-C class, or refer to the special 'id' or 'Class'
1944    types.  If INTERFACE is not a valid ObjC type, just return it unchanged.  */
1945
1946 tree
1947 objc_get_protocol_qualified_type (tree interface, tree protocols)
1948 {
1949   /* If INTERFACE is not provided, default to 'id'.  */
1950   tree type = (interface ? objc_is_id (interface) : objc_object_type);
1951   bool is_ptr = (type != NULL_TREE);
1952
1953   if (!is_ptr)
1954     {
1955       type = objc_is_class_name (interface);
1956
1957       if (type)
1958         {
1959           /* If looking at a typedef, retrieve the precise type it
1960              describes.  */
1961           if (TREE_CODE (interface) == IDENTIFIER_NODE)
1962             interface = identifier_global_value (interface);
1963
1964           type = ((interface && TREE_CODE (interface) == TYPE_DECL
1965                    && DECL_ORIGINAL_TYPE (interface))
1966                   ? DECL_ORIGINAL_TYPE (interface)
1967                   : xref_tag (RECORD_TYPE, type));
1968         }
1969       else
1970         return interface;
1971     }
1972
1973   if (protocols)
1974     {
1975       type = build_variant_type_copy (type);
1976
1977       /* For pointers (i.e., 'id' or 'Class'), attach the protocol(s)
1978          to the pointee.  */
1979       if (is_ptr)
1980         {
1981           tree orig_pointee_type = TREE_TYPE (type);
1982           TREE_TYPE (type) = build_variant_type_copy (orig_pointee_type);
1983
1984           /* Set up the canonical type information. */
1985           TYPE_CANONICAL (type) 
1986             = TYPE_CANONICAL (TYPE_POINTER_TO (orig_pointee_type));
1987
1988           TYPE_POINTER_TO (TREE_TYPE (type)) = type;
1989           type = TREE_TYPE (type);
1990         }
1991
1992       /* Look up protocols and install in lang specific list.  */
1993       DUP_TYPE_OBJC_INFO (type, TYPE_MAIN_VARIANT (type));
1994       TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols (protocols);
1995
1996       /* For RECORD_TYPEs, point to the @interface; for 'id' and 'Class',
1997          return the pointer to the new pointee variant.  */
1998       if (is_ptr)
1999         type = TYPE_POINTER_TO (type);
2000       else
2001         TYPE_OBJC_INTERFACE (type)
2002           = TYPE_OBJC_INTERFACE (TYPE_MAIN_VARIANT (type));
2003     }
2004
2005   return type;
2006 }
2007
2008 /* Check for circular dependencies in protocols.  The arguments are
2009    PROTO, the protocol to check, and LIST, a list of protocol it
2010    conforms to.  */
2011
2012 static void
2013 check_protocol_recursively (tree proto, tree list)
2014 {
2015   tree p;
2016
2017   for (p = list; p; p = TREE_CHAIN (p))
2018     {
2019       tree pp = TREE_VALUE (p);
2020
2021       if (TREE_CODE (pp) == IDENTIFIER_NODE)
2022         pp = lookup_protocol (pp);
2023
2024       if (pp == proto)
2025         fatal_error ("protocol %qE has circular dependency",
2026                      PROTOCOL_NAME (pp));
2027       if (pp)
2028         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
2029     }
2030 }
2031
2032 /* Look up PROTOCOLS, and return a list of those that are found.
2033    If none are found, return NULL.  */
2034
2035 static tree
2036 lookup_and_install_protocols (tree protocols)
2037 {
2038   tree proto;
2039   tree return_value = NULL_TREE;
2040
2041   if (protocols == error_mark_node)
2042     return NULL;
2043
2044   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
2045     {
2046       tree ident = TREE_VALUE (proto);
2047       tree p = lookup_protocol (ident);
2048
2049       if (p)
2050         return_value = chainon (return_value,
2051                                 build_tree_list (NULL_TREE, p));
2052       else if (ident != error_mark_node)
2053         error ("cannot find protocol declaration for %qE",
2054                ident);
2055     }
2056
2057   return return_value;
2058 }
2059
2060 /* Create a declaration for field NAME of a given TYPE.  */
2061
2062 static tree
2063 create_field_decl (tree type, const char *name)
2064 {
2065   return build_decl (input_location,
2066                      FIELD_DECL, get_identifier (name), type);
2067 }
2068
2069 /* Create a global, static declaration for variable NAME of a given TYPE.  The
2070    finish_var_decl() routine will need to be called on it afterwards.  */
2071
2072 static tree
2073 start_var_decl (tree type, const char *name)
2074 {
2075   tree var = build_decl (input_location,
2076                          VAR_DECL, get_identifier (name), type);
2077
2078   TREE_STATIC (var) = 1;
2079   DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
2080   DECL_IGNORED_P (var) = 1;
2081   DECL_ARTIFICIAL (var) = 1;
2082   DECL_CONTEXT (var) = NULL_TREE;
2083 #ifdef OBJCPLUS
2084   DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
2085 #endif
2086
2087   return var;
2088 }
2089
2090 /* Finish off the variable declaration created by start_var_decl().  */
2091
2092 static void
2093 finish_var_decl (tree var, tree initializer)
2094 {
2095   finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
2096 }
2097
2098 /* Find the decl for the constant string class reference.  This is only
2099    used for the NeXT runtime.  */
2100
2101 static tree
2102 setup_string_decl (void)
2103 {
2104   char *name;
2105   size_t length;
2106
2107   /* %s in format will provide room for terminating null */
2108   length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
2109            + strlen (constant_string_class_name);
2110   name = XNEWVEC (char, length);
2111   sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
2112            constant_string_class_name);
2113   constant_string_global_id = get_identifier (name);
2114   string_class_decl = lookup_name (constant_string_global_id);
2115
2116   return string_class_decl;
2117 }
2118
2119 /* Purpose: "play" parser, creating/installing representations
2120    of the declarations that are required by Objective-C.
2121
2122    Model:
2123
2124         type_spec--------->sc_spec
2125         (tree_list)        (tree_list)
2126             |                  |
2127             |                  |
2128         identifier_node    identifier_node  */
2129
2130 static void
2131 synth_module_prologue (void)
2132 {
2133   tree type;
2134   enum debug_info_type save_write_symbols = write_symbols;
2135   const struct gcc_debug_hooks *const save_hooks = debug_hooks;
2136
2137   /* Suppress outputting debug symbols, because
2138      dbxout_init hasn't been called yet.  */
2139   write_symbols = NO_DEBUG;
2140   debug_hooks = &do_nothing_debug_hooks;
2141
2142 #ifdef OBJCPLUS
2143   push_lang_context (lang_name_c); /* extern "C" */
2144 #endif
2145
2146   /* The following are also defined in <objc/objc.h> and friends.  */
2147
2148   objc_object_id = get_identifier (TAG_OBJECT);
2149   objc_class_id = get_identifier (TAG_CLASS);
2150
2151   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
2152   objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
2153
2154   objc_object_type = build_pointer_type (objc_object_reference);
2155   objc_class_type = build_pointer_type (objc_class_reference);
2156
2157   objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
2158   objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
2159
2160   /* Declare the 'id' and 'Class' typedefs.  */
2161
2162   type = lang_hooks.decls.pushdecl (build_decl (input_location,
2163                                                 TYPE_DECL,
2164                                                 objc_object_name,
2165                                                 objc_object_type));
2166   TREE_NO_WARNING (type) = 1;
2167   type = lang_hooks.decls.pushdecl (build_decl (input_location,
2168                                                 TYPE_DECL,
2169                                                 objc_class_name,
2170                                                 objc_class_type));
2171   TREE_NO_WARNING (type) = 1;
2172
2173   /* Forward-declare '@interface Protocol'.  */
2174
2175   type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
2176   objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
2177   objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
2178                                 type));
2179
2180   /* Declare type of selector-objects that represent an operation name.  */
2181
2182   if (flag_next_runtime)
2183     /* `struct objc_selector *' */
2184     objc_selector_type
2185       = build_pointer_type (xref_tag (RECORD_TYPE,
2186                                       get_identifier (TAG_SELECTOR)));
2187   else
2188     /* `const struct objc_selector *' */
2189     objc_selector_type
2190       = build_pointer_type
2191         (build_qualified_type (xref_tag (RECORD_TYPE,
2192                                          get_identifier (TAG_SELECTOR)),
2193                                TYPE_QUAL_CONST));
2194
2195   /* Declare receiver type used for dispatching messages to 'super'.  */
2196
2197   /* `struct objc_super *' */
2198   objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
2199                                                   get_identifier (TAG_SUPER)));
2200
2201   /* Declare pointers to method and ivar lists.  */
2202   objc_method_list_ptr = build_pointer_type
2203                          (xref_tag (RECORD_TYPE,
2204                                     get_identifier (UTAG_METHOD_LIST)));
2205   objc_method_proto_list_ptr
2206     = build_pointer_type (xref_tag (RECORD_TYPE,
2207                                     get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2208   objc_ivar_list_ptr = build_pointer_type
2209                        (xref_tag (RECORD_TYPE,
2210                                   get_identifier (UTAG_IVAR_LIST)));
2211
2212   /* TREE_NOTHROW is cleared for the message-sending functions,
2213      because the function that gets called can throw in Obj-C++, or
2214      could itself call something that can throw even in Obj-C.  */
2215
2216   if (flag_next_runtime)
2217     {
2218       /* NB: In order to call one of the ..._stret (struct-returning)
2219       functions, the function *MUST* first be cast to a signature that
2220       corresponds to the actual ObjC method being invoked.  This is
2221       what is done by the build_objc_method_call() routine below.  */
2222
2223       /* id objc_msgSend (id, SEL, ...); */
2224       /* id objc_msgSendNonNil (id, SEL, ...); */
2225       /* id objc_msgSend_stret (id, SEL, ...); */
2226       /* id objc_msgSendNonNil_stret (id, SEL, ...); */
2227       type
2228         = build_varargs_function_type_list (objc_object_type,
2229                                             objc_object_type,
2230                                             objc_selector_type,
2231                                             NULL_TREE);
2232       umsg_decl = add_builtin_function (TAG_MSGSEND,
2233                                         type, 0, NOT_BUILT_IN,
2234                                         NULL, NULL_TREE);
2235       umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
2236                                                type, 0, NOT_BUILT_IN,
2237                                                NULL, NULL_TREE);
2238       umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
2239                                               type, 0, NOT_BUILT_IN,
2240                                               NULL, NULL_TREE);
2241       umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
2242                                                      type, 0, NOT_BUILT_IN,
2243                                                      NULL, NULL_TREE);
2244
2245       /* These can throw, because the function that gets called can throw
2246          in Obj-C++, or could itself call something that can throw even
2247          in Obj-C.  */
2248       TREE_NOTHROW (umsg_decl) = 0;
2249       TREE_NOTHROW (umsg_nonnil_decl) = 0;
2250       TREE_NOTHROW (umsg_stret_decl) = 0;
2251       TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
2252
2253       /* id objc_msgSend_Fast (id, SEL, ...)
2254            __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
2255 #ifdef OFFS_MSGSEND_FAST
2256       umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
2257                                              type, 0, NOT_BUILT_IN,
2258                                              NULL, NULL_TREE);
2259       TREE_NOTHROW (umsg_fast_decl) = 0;
2260       DECL_ATTRIBUTES (umsg_fast_decl)
2261         = tree_cons (get_identifier ("hard_coded_address"),
2262                      build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
2263                      NULL_TREE);
2264 #else
2265       /* No direct dispatch available.  */
2266       umsg_fast_decl = umsg_decl;
2267 #endif
2268
2269       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
2270       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
2271       type
2272         = build_varargs_function_type_list (objc_object_type,
2273                                             objc_super_type,
2274                                             objc_selector_type,
2275                                             NULL_TREE);
2276       umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
2277                                               type, 0, NOT_BUILT_IN,
2278                                               NULL, NULL_TREE);
2279       umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
2280                                                     type, 0, NOT_BUILT_IN, 0,
2281                                                     NULL_TREE);
2282       TREE_NOTHROW (umsg_super_decl) = 0;
2283       TREE_NOTHROW (umsg_super_stret_decl) = 0;
2284     }
2285   else
2286     {
2287       /* GNU runtime messenger entry points.  */
2288
2289       /* typedef id (*IMP)(id, SEL, ...); */
2290       tree ftype =
2291         build_varargs_function_type_list (objc_object_type,
2292                                           objc_object_type,
2293                                           objc_selector_type,
2294                                           NULL_TREE);
2295       tree IMP_type = build_pointer_type (ftype);
2296
2297       /* IMP objc_msg_lookup (id, SEL); */
2298       type = build_function_type_list (IMP_type,
2299                                        objc_object_type,
2300                                        objc_selector_type,
2301                                        NULL_TREE);
2302       umsg_decl = add_builtin_function (TAG_MSGSEND,
2303                                         type, 0, NOT_BUILT_IN,
2304                                         NULL, NULL_TREE);
2305       TREE_NOTHROW (umsg_decl) = 0;
2306
2307       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
2308       type
2309         = build_function_type_list (IMP_type,
2310                                     objc_super_type,
2311                                     objc_selector_type,
2312                                     NULL_TREE);
2313       umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
2314                                               type, 0, NOT_BUILT_IN,
2315                                               NULL, NULL_TREE);
2316       TREE_NOTHROW (umsg_super_decl) = 0;
2317
2318       /* The following GNU runtime entry point is called to initialize
2319          each module:
2320
2321          __objc_exec_class (void *); */
2322       type
2323         = build_function_type_list (void_type_node,
2324                                     ptr_type_node,
2325                                     NULL_TREE);
2326       execclass_decl = add_builtin_function (TAG_EXECCLASS,
2327                                              type, 0, NOT_BUILT_IN,
2328                                              NULL, NULL_TREE);
2329     }
2330
2331   /* id objc_getClass (const char *); */
2332
2333   type = build_function_type_list (objc_object_type,
2334                                    const_string_type_node,
2335                                    NULL_TREE);
2336
2337   objc_get_class_decl
2338     = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
2339                             NULL, NULL_TREE);
2340
2341   /* id objc_getMetaClass (const char *); */
2342
2343   objc_get_meta_class_decl
2344     = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2345
2346   build_class_template ();
2347   build_super_template ();
2348   build_protocol_template ();
2349   build_category_template ();
2350   build_objc_exception_stuff ();
2351
2352   /* Declare objc_getProperty, object_setProperty and other property
2353      accessor helpers.  */
2354   build_objc_property_accessor_helpers ();
2355
2356   if (flag_next_runtime)
2357     build_next_objc_exception_stuff ();
2358
2359   /* static SEL _OBJC_SELECTOR_TABLE[]; */
2360
2361   if (! flag_next_runtime)
2362     build_selector_table_decl ();
2363
2364   /* Forward declare constant_string_id and constant_string_type.  */
2365   if (!constant_string_class_name)
2366     constant_string_class_name = default_constant_string_class_name;
2367
2368   constant_string_id = get_identifier (constant_string_class_name);
2369   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
2370
2371   /* Pre-build the following entities - for speed/convenience.  */
2372   self_id = get_identifier ("self");
2373   ucmd_id = get_identifier ("_cmd");
2374
2375   /* Declare struct _objc_fast_enumeration_state { ... };  */
2376   build_fast_enumeration_state_template ();
2377   
2378   /* void objc_enumeration_mutation (id) */
2379   type = build_function_type (void_type_node,
2380                               tree_cons (NULL_TREE, objc_object_type, NULL_TREE));
2381   objc_enumeration_mutation_decl 
2382     = add_builtin_function (TAG_ENUMERATION_MUTATION, type, 0, NOT_BUILT_IN, 
2383                             NULL, NULL_TREE);
2384   TREE_NOTHROW (objc_enumeration_mutation_decl) = 0;
2385
2386 #ifdef OBJCPLUS
2387   pop_lang_context ();
2388 #endif
2389
2390   write_symbols = save_write_symbols;
2391   debug_hooks = save_hooks;
2392 }
2393
2394 /* Ensure that the ivar list for NSConstantString/NXConstantString
2395    (or whatever was specified via `-fconstant-string-class')
2396    contains fields at least as large as the following three, so that
2397    the runtime can stomp on them with confidence:
2398
2399    struct STRING_OBJECT_CLASS_NAME
2400    {
2401      Object isa;
2402      char *cString;
2403      unsigned int length;
2404    }; */
2405
2406 static int
2407 check_string_class_template (void)
2408 {
2409   tree field_decl = objc_get_class_ivars (constant_string_id);
2410
2411 #define AT_LEAST_AS_LARGE_AS(F, T) \
2412   (F && TREE_CODE (F) == FIELD_DECL \
2413      && (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (F))) \
2414          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
2415
2416   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
2417     return 0;
2418
2419   field_decl = DECL_CHAIN (field_decl);
2420   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
2421     return 0;
2422
2423   field_decl = DECL_CHAIN (field_decl);
2424   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
2425
2426 #undef AT_LEAST_AS_LARGE_AS
2427 }
2428
2429 /* Avoid calling `check_string_class_template ()' more than once.  */
2430 static GTY(()) int string_layout_checked;
2431
2432 /* Construct an internal string layout to be used as a template for
2433    creating NSConstantString/NXConstantString instances.  */
2434
2435 static tree
2436 objc_build_internal_const_str_type (void)
2437 {
2438   tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
2439   tree fields = build_decl (input_location,
2440                             FIELD_DECL, NULL_TREE, ptr_type_node);
2441   tree field = build_decl (input_location,
2442                            FIELD_DECL, NULL_TREE, ptr_type_node);
2443
2444   DECL_CHAIN (field) = fields; fields = field;
2445   field = build_decl (input_location,
2446                       FIELD_DECL, NULL_TREE, unsigned_type_node);
2447   DECL_CHAIN (field) = fields; fields = field;
2448   /* NB: The finish_builtin_struct() routine expects FIELD_DECLs in
2449      reverse order!  */
2450   finish_builtin_struct (type, "__builtin_ObjCString",
2451                          fields, NULL_TREE);
2452
2453   return type;
2454 }
2455
2456 /* Custom build_string which sets TREE_TYPE!  */
2457
2458 static tree
2459 my_build_string (int len, const char *str)
2460 {
2461   return fix_string_type (build_string (len, str));
2462 }
2463
2464 /* Build a string with contents STR and length LEN and convert it to a
2465    pointer.  */
2466
2467 static tree
2468 my_build_string_pointer (int len, const char *str)
2469 {
2470   tree string = my_build_string (len, str);
2471   tree ptrtype = build_pointer_type (TREE_TYPE (TREE_TYPE (string)));
2472   return build1 (ADDR_EXPR, ptrtype, string);
2473 }
2474
2475 static hashval_t
2476 string_hash (const void *ptr)
2477 {
2478   const_tree const str = ((const struct string_descriptor *)ptr)->literal;
2479   const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
2480   int i, len = TREE_STRING_LENGTH (str);
2481   hashval_t h = len;
2482
2483   for (i = 0; i < len; i++)
2484     h = ((h * 613) + p[i]);
2485
2486   return h;
2487 }
2488
2489 static int
2490 string_eq (const void *ptr1, const void *ptr2)
2491 {
2492   const_tree const str1 = ((const struct string_descriptor *)ptr1)->literal;
2493   const_tree const str2 = ((const struct string_descriptor *)ptr2)->literal;
2494   int len1 = TREE_STRING_LENGTH (str1);
2495
2496   return (len1 == TREE_STRING_LENGTH (str2)
2497           && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
2498                       len1));
2499 }
2500
2501 /* Given a chain of STRING_CST's, build a static instance of
2502    NXConstantString which points at the concatenation of those
2503    strings.  We place the string object in the __string_objects
2504    section of the __OBJC segment.  The Objective-C runtime will
2505    initialize the isa pointers of the string objects to point at the
2506    NXConstantString class object.  */
2507
2508 tree
2509 objc_build_string_object (tree string)
2510 {
2511   tree constant_string_class;
2512   int length;
2513   tree fields, addr;
2514   struct string_descriptor *desc, key;
2515   void **loc;
2516
2517   /* Prep the string argument.  */
2518   string = fix_string_type (string);
2519   TREE_SET_CODE (string, STRING_CST);
2520   length = TREE_STRING_LENGTH (string) - 1;
2521
2522   /* The target may have different ideas on how to construct an ObjC string 
2523      literal.  On Darwin (Mac OS X), for example, we may wish to obtain a 
2524      constant CFString reference instead.
2525      At present, this is only supported for the NeXT runtime.  */
2526   if (flag_next_runtime && targetcm.objc_construct_string)
2527     {
2528       tree constructor = (*targetcm.objc_construct_string) (string);
2529       if (constructor)
2530         return build1 (NOP_EXPR, objc_object_type, constructor);
2531     }
2532
2533   /* Check whether the string class being used actually exists and has the
2534      correct ivar layout.  */
2535   if (!string_layout_checked)
2536     {
2537       string_layout_checked = -1;
2538       constant_string_class = lookup_interface (constant_string_id);
2539       internal_const_str_type = objc_build_internal_const_str_type ();
2540
2541       if (!constant_string_class
2542           || !(constant_string_type
2543                = CLASS_STATIC_TEMPLATE (constant_string_class)))
2544         error ("cannot find interface declaration for %qE",
2545                constant_string_id);
2546       /* The NSConstantString/NXConstantString ivar layout is now known.  */
2547       else if (!check_string_class_template ())
2548         error ("interface %qE does not have valid constant string layout",
2549                constant_string_id);
2550       /* For the NeXT runtime, we can generate a literal reference
2551          to the string class, don't need to run a constructor.  */
2552       else if (flag_next_runtime && !setup_string_decl ())
2553         error ("cannot find reference tag for class %qE",
2554                constant_string_id);
2555       else
2556         {
2557           string_layout_checked = 1;  /* Success!  */
2558           add_class_reference (constant_string_id);
2559         }
2560     }
2561
2562   if (string_layout_checked == -1)
2563     return error_mark_node;
2564
2565   /* Perhaps we already constructed a constant string just like this one? */
2566   key.literal = string;
2567   loc = htab_find_slot (string_htab, &key, INSERT);
2568   desc = (struct string_descriptor *) *loc;
2569
2570   if (!desc)
2571     {
2572       tree var, constructor;
2573       VEC(constructor_elt,gc) *v = NULL;
2574       *loc = desc = ggc_alloc_string_descriptor ();
2575       desc->literal = string;
2576
2577       /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
2578       /* NeXT:   (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length })   */
2579       fields = TYPE_FIELDS (internal_const_str_type);
2580       CONSTRUCTOR_APPEND_ELT (v, fields,
2581                               flag_next_runtime
2582                               ? build_unary_op (input_location,
2583                                                 ADDR_EXPR, string_class_decl, 0)
2584                               : build_int_cst (NULL_TREE, 0));
2585       fields = DECL_CHAIN (fields);
2586       CONSTRUCTOR_APPEND_ELT (v, fields,
2587                               build_unary_op (input_location,
2588                                               ADDR_EXPR, string, 1));
2589       fields = DECL_CHAIN (fields);
2590       CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
2591       constructor = objc_build_constructor (internal_const_str_type, v);
2592
2593       if (!flag_next_runtime)
2594         constructor
2595           = objc_add_static_instance (constructor, constant_string_type);
2596       else
2597         {
2598           var = build_decl (input_location,
2599                             CONST_DECL, NULL, TREE_TYPE (constructor));
2600           DECL_INITIAL (var) = constructor;
2601           TREE_STATIC (var) = 1;
2602           pushdecl_top_level (var);
2603           constructor = var;
2604         }
2605       desc->constructor = constructor;
2606     }
2607
2608   addr = convert (build_pointer_type (constant_string_type),
2609                   build_unary_op (input_location,
2610                                   ADDR_EXPR, desc->constructor, 1));
2611
2612   return addr;
2613 }
2614
2615 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
2616
2617 static GTY(()) int num_static_inst;
2618
2619 static tree
2620 objc_add_static_instance (tree constructor, tree class_decl)
2621 {
2622   tree *chain, decl;
2623   char buf[256];
2624
2625   /* Find the list of static instances for the CLASS_DECL.  Create one if
2626      not found.  */
2627   for (chain = &objc_static_instances;
2628        *chain && TREE_VALUE (*chain) != class_decl;
2629        chain = &TREE_CHAIN (*chain));
2630   if (!*chain)
2631     {
2632       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
2633       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
2634     }
2635
2636   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
2637   decl = build_decl (input_location,
2638                      VAR_DECL, get_identifier (buf), class_decl);
2639   TREE_STATIC (decl) = 1;
2640   DECL_ARTIFICIAL (decl) = 1;
2641   TREE_USED (decl) = 1;
2642   DECL_INITIAL (decl) = constructor;
2643
2644   /* We may be writing something else just now.
2645      Postpone till end of input.  */
2646   DECL_DEFER_OUTPUT (decl) = 1;
2647   pushdecl_top_level (decl);
2648   rest_of_decl_compilation (decl, 1, 0);
2649
2650   /* Add the DECL to the head of this CLASS' list.  */
2651   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
2652
2653   return decl;
2654 }
2655
2656 /* Build a static constant CONSTRUCTOR
2657    with type TYPE and elements ELTS.  */
2658
2659 static tree
2660 objc_build_constructor (tree type, VEC(constructor_elt,gc) *elts)
2661 {
2662   tree constructor = build_constructor (type, elts);
2663
2664   TREE_CONSTANT (constructor) = 1;
2665   TREE_STATIC (constructor) = 1;
2666   TREE_READONLY (constructor) = 1;
2667
2668 #ifdef OBJCPLUS
2669   /* Adjust for impedance mismatch.  We should figure out how to build
2670      CONSTRUCTORs that consistently please both the C and C++ gods.  */
2671   if (!VEC_index (constructor_elt, elts, 0)->index)
2672     TREE_TYPE (constructor) = init_list_type_node;
2673 #endif
2674
2675   return constructor;
2676 }
2677 \f
2678 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
2679
2680 /* Predefine the following data type:
2681
2682    struct _objc_symtab
2683    {
2684      long sel_ref_cnt;
2685      SEL *refs;
2686      short cls_def_cnt;
2687      short cat_def_cnt;
2688      void *defs[cls_def_cnt + cat_def_cnt];
2689    }; */
2690
2691 static void
2692 build_objc_symtab_template (void)
2693 {
2694   tree fields, *chain = NULL;
2695
2696   objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
2697
2698   /* long sel_ref_cnt; */
2699   fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
2700
2701   /* SEL *refs; */
2702   add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
2703
2704   /* short cls_def_cnt; */
2705   add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
2706
2707   /* short cat_def_cnt; */
2708   add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2709
2710   if (imp_count || cat_count || !flag_next_runtime)
2711     {
2712       /* void *defs[imp_count + cat_count (+ 1)]; */
2713       /* NB: The index is one less than the size of the array.  */
2714       int index = imp_count + cat_count + (flag_next_runtime ? -1: 0);
2715       tree array_type = build_sized_array_type (ptr_type_node, index + 1);
2716       add_field_decl (array_type, "defs", &chain);
2717     }
2718
2719   objc_finish_struct (objc_symtab_template, fields);
2720 }
2721
2722 /* Create the initial value for the `defs' field of _objc_symtab.
2723    This is a CONSTRUCTOR.  */
2724
2725 static tree
2726 init_def_list (tree type)
2727 {
2728   tree expr;
2729   struct imp_entry *impent;
2730   VEC(constructor_elt,gc) *v = NULL;
2731
2732   if (imp_count)
2733     for (impent = imp_list; impent; impent = impent->next)
2734       {
2735         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2736           {
2737             expr = build_unary_op (input_location,
2738                                    ADDR_EXPR, impent->class_decl, 0);
2739             CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2740           }
2741       }
2742
2743   if (cat_count)
2744     for (impent = imp_list; impent; impent = impent->next)
2745       {
2746         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2747           {
2748             expr = build_unary_op (input_location,
2749                                    ADDR_EXPR, impent->class_decl, 0);
2750             CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2751           }
2752       }
2753
2754   if (!flag_next_runtime)
2755     {
2756       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
2757       if (static_instances_decl)
2758         expr = build_unary_op (input_location,
2759                                ADDR_EXPR, static_instances_decl, 0);
2760       else
2761         expr = integer_zero_node;
2762
2763       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2764     }
2765
2766   return objc_build_constructor (type, v);
2767 }
2768
2769 /* Construct the initial value for all of _objc_symtab.  */
2770
2771 static tree
2772 init_objc_symtab (tree type)
2773 {
2774   VEC(constructor_elt,gc) *v = NULL;
2775
2776   /* sel_ref_cnt = { ..., 5, ... } */
2777
2778   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2779                           build_int_cst (long_integer_type_node, 0));
2780
2781   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2782
2783   if (flag_next_runtime || ! sel_ref_chain)
2784     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (
2785                                         build_pointer_type (objc_selector_type),
2786                                                         integer_zero_node));
2787   else
2788     {
2789       tree expr = build_unary_op (input_location, ADDR_EXPR,
2790                                   UOBJC_SELECTOR_TABLE_decl, 1);
2791
2792       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2793                               convert (build_pointer_type (objc_selector_type),
2794                                        expr));
2795     }
2796
2797   /* cls_def_cnt = { ..., 5, ... } */
2798
2799   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 
2800                           build_int_cst (short_integer_type_node, imp_count));
2801
2802   /* cat_def_cnt = { ..., 5, ... } */
2803
2804   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 
2805                           build_int_cst (short_integer_type_node, cat_count));
2806
2807   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2808
2809   if (imp_count || cat_count || !flag_next_runtime)
2810     {
2811
2812       tree field = TYPE_FIELDS (type);
2813       field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2814
2815       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2816     }
2817
2818   return objc_build_constructor (type, v);
2819 }
2820
2821 /* Generate forward declarations for metadata such as
2822   'OBJC_CLASS_...'.  */
2823
2824 static tree
2825 build_metadata_decl (const char *name, tree type)
2826 {
2827   tree decl;
2828
2829   /* struct TYPE NAME_<name>; */
2830   decl = start_var_decl (type, synth_id_with_class_suffix
2831                                (name,
2832                                 objc_implementation_context));
2833
2834   return decl;
2835 }
2836
2837 /* Push forward-declarations of all the categories so that
2838    init_def_list can use them in a CONSTRUCTOR.  */
2839
2840 static void
2841 forward_declare_categories (void)
2842 {
2843   struct imp_entry *impent;
2844   tree sav = objc_implementation_context;
2845
2846   for (impent = imp_list; impent; impent = impent->next)
2847     {
2848       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2849         {
2850           /* Set an invisible arg to synth_id_with_class_suffix.  */
2851           objc_implementation_context = impent->imp_context;
2852           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
2853           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
2854                                                     objc_category_template);
2855         }
2856     }
2857   objc_implementation_context = sav;
2858 }
2859
2860 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2861    and initialized appropriately.  */
2862
2863 static void
2864 generate_objc_symtab_decl (void)
2865 {
2866  
2867   build_objc_symtab_template ();
2868   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2869   finish_var_decl (UOBJC_SYMBOLS_decl,
2870                    init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2871 }
2872 \f
2873 static tree
2874 init_module_descriptor (tree type)
2875 {
2876   tree expr;
2877   VEC(constructor_elt,gc) *v = NULL;
2878
2879   /* version = { 1, ... } */
2880
2881   expr = build_int_cst (long_integer_type_node, OBJC_VERSION);
2882   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2883
2884   /* size = { ..., sizeof (struct _objc_module), ... } */
2885
2886   expr = convert (long_integer_type_node,
2887                   size_in_bytes (objc_module_template));
2888   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2889
2890   /* Don't provide any file name for security reasons. */
2891   /* name = { ..., "", ... } */
2892
2893   expr = add_objc_string (get_identifier (""), class_names);
2894   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2895
2896   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
2897
2898   if (UOBJC_SYMBOLS_decl)
2899     expr = build_unary_op (input_location,
2900                            ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
2901   else
2902     expr = null_pointer_node;
2903   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2904
2905   return objc_build_constructor (type, v);
2906 }
2907
2908 /* Write out the data structures to describe Objective C classes defined.
2909
2910    struct _objc_module { ... } _OBJC_MODULE = { ... };   */
2911
2912 static void
2913 build_module_descriptor (void)
2914 {
2915   tree decls, *chain = NULL;
2916
2917 #ifdef OBJCPLUS
2918   push_lang_context (lang_name_c); /* extern "C" */
2919 #endif
2920
2921   objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
2922
2923   /* long version; */
2924   decls = add_field_decl (long_integer_type_node, "version", &chain);
2925
2926   /* long size; */
2927   add_field_decl (long_integer_type_node, "size", &chain);
2928
2929   /* char *name; */
2930   add_field_decl (string_type_node, "name", &chain);
2931
2932   /* struct _objc_symtab *symtab; */
2933   add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
2934                                                 get_identifier (UTAG_SYMTAB))),
2935                   "symtab", &chain);
2936
2937   objc_finish_struct (objc_module_template, decls);
2938
2939   /* Create an instance of "_objc_module".  */
2940   UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
2941   /* This is the root of the metadata for defined classes and categories, it
2942      is referenced by the runtime and, therefore, needed.  */
2943   DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
2944   finish_var_decl (UOBJC_MODULES_decl,
2945                    init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
2946
2947 #ifdef OBJCPLUS
2948   pop_lang_context ();
2949 #endif
2950 }
2951
2952 /* The GNU runtime requires us to provide a static initializer function
2953    for each module:
2954
2955    static void __objc_gnu_init (void) {
2956      __objc_exec_class (&L_OBJC_MODULES);
2957    }  */
2958
2959 static void
2960 build_module_initializer_routine (void)
2961 {
2962   tree body;
2963
2964 #ifdef OBJCPLUS
2965   push_lang_context (lang_name_c); /* extern "C" */
2966 #endif
2967
2968   objc_push_parm (build_decl (input_location,
2969                               PARM_DECL, NULL_TREE, void_type_node));
2970 #ifdef OBJCPLUS
2971   objc_start_function (get_identifier (TAG_GNUINIT),
2972                        build_function_type_list (void_type_node, NULL_TREE),
2973                        NULL_TREE, NULL_TREE);
2974 #else
2975   objc_start_function (get_identifier (TAG_GNUINIT),
2976                        build_function_type_list (void_type_node, NULL_TREE),
2977                        NULL_TREE, objc_get_parm_info (0));
2978 #endif
2979   body = c_begin_compound_stmt (true);
2980   add_stmt (build_function_call
2981             (input_location,
2982              execclass_decl,
2983              build_tree_list
2984              (NULL_TREE,
2985               build_unary_op (input_location, ADDR_EXPR,
2986                               UOBJC_MODULES_decl, 0))));
2987   add_stmt (c_end_compound_stmt (input_location, body, true));
2988
2989   TREE_PUBLIC (current_function_decl) = 0;
2990
2991 #ifndef OBJCPLUS
2992   /* For Objective-C++, we will need to call __objc_gnu_init
2993      from objc_generate_static_init_call() below.  */
2994   DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
2995 #endif
2996
2997   GNU_INIT_decl = current_function_decl;
2998   finish_function ();
2999
3000 #ifdef OBJCPLUS
3001     pop_lang_context ();
3002 #endif
3003 }
3004
3005 #ifdef OBJCPLUS
3006 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
3007    to be called by the module initializer routine.  */
3008
3009 int
3010 objc_static_init_needed_p (void)
3011 {
3012   return (GNU_INIT_decl != NULL_TREE);
3013 }
3014
3015 /* Generate a call to the __objc_gnu_init initializer function.  */
3016
3017 tree
3018 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
3019 {
3020   add_stmt (build_stmt (input_location, EXPR_STMT,
3021                         build_function_call (input_location,
3022                                              GNU_INIT_decl, NULL_TREE)));
3023
3024   return ctors;
3025 }
3026 #endif /* OBJCPLUS */
3027
3028 /* Return the DECL of the string IDENT in the SECTION.  */
3029
3030 static tree
3031 get_objc_string_decl (tree ident, enum string_section section)
3032 {
3033   tree chain;
3034
3035   switch (section)
3036     {
3037     case class_names:
3038       chain = class_names_chain;
3039       break;
3040     case meth_var_names:
3041       chain = meth_var_names_chain;
3042       break;
3043     case meth_var_types:
3044       chain = meth_var_types_chain;
3045       break;
3046     default:
3047       gcc_unreachable ();
3048     }
3049
3050   for (; chain != 0; chain = TREE_CHAIN (chain))
3051     if (TREE_VALUE (chain) == ident)
3052       return (TREE_PURPOSE (chain));
3053
3054   gcc_unreachable ();
3055   return NULL_TREE;
3056 }
3057
3058 /* Output references to all statically allocated objects.  Return the DECL
3059    for the array built.  */
3060
3061 static void
3062 generate_static_references (void)
3063 {
3064   tree expr = NULL_TREE;
3065   tree class_name, klass, decl;
3066   tree cl_chain, in_chain, type
3067     = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
3068   int num_inst, num_class;
3069   char buf[256];
3070   VEC(constructor_elt,gc) *decls = NULL;
3071
3072   if (flag_next_runtime)
3073     gcc_unreachable ();
3074
3075   for (cl_chain = objc_static_instances, num_class = 0;
3076        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
3077     {
3078       VEC(constructor_elt,gc) *v = NULL;
3079
3080       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
3081            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
3082
3083       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
3084       decl = start_var_decl (type, buf);
3085
3086       /* Output {class_name, ...}.  */
3087       klass = TREE_VALUE (cl_chain);
3088       class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
3089       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
3090                               build_unary_op (input_location, 
3091                                               ADDR_EXPR, class_name, 1));
3092
3093       /* Output {..., instance, ...}.  */
3094       for (in_chain = TREE_PURPOSE (cl_chain);
3095            in_chain; in_chain = TREE_CHAIN (in_chain))
3096         {
3097           expr = build_unary_op (input_location,
3098                                  ADDR_EXPR, TREE_VALUE (in_chain), 1);
3099           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
3100         }
3101
3102       /* Output {..., NULL}.  */
3103       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
3104
3105       expr = objc_build_constructor (TREE_TYPE (decl), v);
3106       finish_var_decl (decl, expr);
3107       CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
3108                               build_unary_op (input_location,
3109                                               ADDR_EXPR, decl, 1));
3110     }
3111
3112   CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
3113   expr = objc_build_constructor (type, decls);
3114   static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
3115   finish_var_decl (static_instances_decl, expr);
3116 }
3117
3118 static GTY(()) int selector_reference_idx;
3119
3120 static tree
3121 build_selector_reference_decl (void)
3122 {
3123   tree decl;
3124   char buf[256];
3125
3126   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
3127   decl = start_var_decl (objc_selector_type, buf);
3128
3129   return decl;
3130 }
3131
3132 static void
3133 build_selector_table_decl (void)
3134 {
3135   tree temp;
3136
3137   if (flag_typed_selectors)
3138     {
3139       build_selector_template ();
3140       temp = build_array_type (objc_selector_template, NULL_TREE);
3141     }
3142   else
3143     temp = build_array_type (objc_selector_type, NULL_TREE);
3144
3145   UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
3146 }
3147
3148 /* Just a handy wrapper for add_objc_string.  */
3149
3150 static tree
3151 build_selector (tree ident)
3152 {
3153   return convert (objc_selector_type,
3154                   add_objc_string (ident, meth_var_names));
3155 }
3156
3157 /* Used only by build_*_selector_translation_table (). */
3158 static void
3159 diagnose_missing_method (tree meth, location_t here)
3160 {
3161   tree method_chain;
3162   bool found = false;
3163   for (method_chain = meth_var_names_chain;
3164        method_chain;
3165        method_chain = TREE_CHAIN (method_chain))
3166     {
3167       if (TREE_VALUE (method_chain) == meth)
3168         {
3169           found = true;
3170           break;
3171         }
3172      }
3173
3174   if (!found)
3175     warning_at (here, 0, "creating selector for nonexistent method %qE",
3176                         meth);
3177 }
3178
3179 static void
3180 build_next_selector_translation_table (void)
3181 {
3182   tree chain;
3183   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
3184     {
3185       tree expr;
3186       tree decl = TREE_PURPOSE (chain);
3187       if (warn_selector && objc_implementation_context)
3188         {
3189           location_t loc;
3190           if (decl) 
3191             loc = DECL_SOURCE_LOCATION (decl);
3192           else
3193             loc = input_location;
3194           diagnose_missing_method (TREE_VALUE (chain), loc);
3195         }
3196
3197       expr = build_selector (TREE_VALUE (chain));
3198
3199       if (decl)
3200         {
3201           /* Entries of this form are used for references to methods.
3202           The runtime re-writes these on start-up, but the compiler can't see 
3203           that and optimizes it away unless we force it.  */
3204           DECL_PRESERVE_P (decl) = 1;
3205           finish_var_decl (decl, expr);
3206         }
3207     }
3208 }
3209
3210 static void
3211 build_gnu_selector_translation_table (void)
3212 {
3213   tree chain;
3214 /*  int offset = 0;
3215   tree decl = NULL_TREE;*/
3216   VEC(constructor_elt,gc) *inits = NULL;
3217
3218   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
3219     {
3220       tree expr;
3221
3222       if (warn_selector && objc_implementation_context)
3223         diagnose_missing_method (TREE_VALUE (chain), input_location);
3224
3225       expr = build_selector (TREE_VALUE (chain));
3226       /* add one for the '\0' character 
3227       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;*/
3228
3229         {
3230           if (flag_typed_selectors)
3231             {
3232               VEC(constructor_elt,gc) *v = NULL;
3233               tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
3234               CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
3235               CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
3236               expr = objc_build_constructor (objc_selector_template, v);
3237             }
3238
3239           CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
3240         }
3241     } /* each element in the chain */
3242
3243     {
3244       /* Cause the selector table (previously forward-declared)
3245          to be actually output.  */
3246       tree expr;
3247
3248       if (flag_typed_selectors)
3249         {
3250           VEC(constructor_elt,gc) *v = NULL;
3251           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
3252           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
3253           expr = objc_build_constructor (objc_selector_template, v);
3254         }
3255       else
3256         expr = integer_zero_node;
3257
3258       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
3259       expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
3260                                      inits);
3261       finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
3262     }
3263 }
3264
3265 static tree
3266 get_proto_encoding (tree proto)
3267 {
3268   tree encoding;
3269   if (proto)
3270     {
3271       if (! METHOD_ENCODING (proto))
3272         {
3273           encoding = encode_method_prototype (proto);
3274           METHOD_ENCODING (proto) = encoding;
3275         }
3276       else
3277         encoding = METHOD_ENCODING (proto);
3278
3279       return add_objc_string (encoding, meth_var_types);
3280     }
3281   else
3282     return build_int_cst (NULL_TREE, 0);
3283 }
3284
3285 /* sel_ref_chain is a list whose "value" fields will be instances of
3286    identifier_node that represent the selector.  LOC is the location of
3287    the @selector.  */
3288
3289 static tree
3290 build_typed_selector_reference (location_t loc, tree ident, tree prototype)
3291 {
3292   tree *chain = &sel_ref_chain;
3293   tree expr;
3294   int index = 0;
3295
3296   while (*chain)
3297     {
3298       if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
3299         goto return_at_index;
3300
3301       index++;
3302       chain = &TREE_CHAIN (*chain);
3303     }
3304
3305   *chain = tree_cons (prototype, ident, NULL_TREE);
3306
3307  return_at_index:
3308   expr = build_unary_op (loc, ADDR_EXPR,
3309                          build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
3310                                           build_int_cst (NULL_TREE, index)),
3311                          1);
3312   return convert (objc_selector_type, expr);
3313 }
3314
3315 static tree
3316 build_selector_reference (location_t loc, tree ident)
3317 {
3318   tree *chain = &sel_ref_chain;
3319   tree expr;
3320   int index = 0;
3321
3322   while (*chain)
3323     {
3324       if (TREE_VALUE (*chain) == ident)
3325         return (flag_next_runtime
3326                 ? TREE_PURPOSE (*chain)
3327                 : build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
3328                                    build_int_cst (NULL_TREE, index)));
3329
3330       index++;
3331       chain = &TREE_CHAIN (*chain);
3332     }
3333
3334   expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
3335
3336   *chain = tree_cons (expr, ident, NULL_TREE);
3337
3338   return (flag_next_runtime
3339           ? expr
3340           : build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
3341                              build_int_cst (NULL_TREE, index)));
3342 }
3343
3344 static GTY(()) int class_reference_idx;
3345
3346 static tree
3347 build_class_reference_decl (void)
3348 {
3349   tree decl;
3350   char buf[256];
3351
3352   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
3353   decl = start_var_decl (objc_class_type, buf);
3354
3355   return decl;
3356 }
3357
3358 /* Create a class reference, but don't create a variable to reference
3359    it.  */
3360
3361 static void
3362 add_class_reference (tree ident)
3363 {
3364   tree chain;
3365
3366   if ((chain = cls_ref_chain))
3367     {
3368       tree tail;
3369       do
3370         {
3371           if (ident == TREE_VALUE (chain))
3372             return;
3373
3374           tail = chain;
3375           chain = TREE_CHAIN (chain);
3376         }
3377       while (chain);
3378
3379       /* Append to the end of the list */
3380       TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
3381     }
3382   else
3383     cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
3384 }
3385
3386 /* Get a class reference, creating it if necessary.  Also create the
3387    reference variable.  */
3388
3389 tree
3390 objc_get_class_reference (tree ident)
3391 {
3392   tree orig_ident = (DECL_P (ident)
3393                      ? DECL_NAME (ident)
3394                      : TYPE_P (ident)
3395                      ? OBJC_TYPE_NAME (ident)
3396                      : ident);
3397   bool local_scope = false;
3398
3399 #ifdef OBJCPLUS
3400   if (processing_template_decl)
3401     /* Must wait until template instantiation time.  */
3402     return build_min_nt (CLASS_REFERENCE_EXPR, ident);
3403 #endif
3404
3405   if (TREE_CODE (ident) == TYPE_DECL)
3406     ident = (DECL_ORIGINAL_TYPE (ident)
3407              ? DECL_ORIGINAL_TYPE (ident)
3408              : TREE_TYPE (ident));
3409
3410 #ifdef OBJCPLUS
3411   if (TYPE_P (ident)
3412       && CP_TYPE_CONTEXT (ident) != global_namespace)
3413     local_scope = true;
3414 #endif
3415
3416   if (local_scope || !(ident = objc_is_class_name (ident)))
3417     {
3418       error ("%qE is not an Objective-C class name or alias",
3419              orig_ident);
3420       return error_mark_node;
3421     }
3422
3423   if (flag_next_runtime && !flag_zero_link)
3424     {
3425       tree *chain;
3426       tree decl;
3427
3428       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
3429         if (TREE_VALUE (*chain) == ident)
3430           {
3431             if (! TREE_PURPOSE (*chain))
3432               TREE_PURPOSE (*chain) = build_class_reference_decl ();
3433
3434             return TREE_PURPOSE (*chain);
3435           }
3436
3437       decl = build_class_reference_decl ();
3438       *chain = tree_cons (decl, ident, NULL_TREE);
3439       return decl;
3440     }
3441   else
3442     {
3443       tree params;
3444
3445       add_class_reference (ident);
3446
3447       params = build_tree_list (NULL_TREE,
3448                                 my_build_string_pointer
3449                                 (IDENTIFIER_LENGTH (ident) + 1,
3450                                  IDENTIFIER_POINTER (ident)));
3451
3452       assemble_external (objc_get_class_decl);
3453       return build_function_call (input_location, objc_get_class_decl, params);
3454     }
3455 }
3456
3457 /* For each string section we have a chain which maps identifier nodes
3458    to decls for the strings.  */
3459
3460 static GTY(()) int class_names_idx;
3461 static GTY(()) int meth_var_names_idx;
3462 static GTY(()) int meth_var_types_idx;
3463
3464 static tree
3465 add_objc_string (tree ident, enum string_section section)
3466 {
3467   tree *chain, decl, type, string_expr;
3468   char buf[256];
3469   
3470   buf[0] = 0;
3471   switch (section)
3472     {
3473     case class_names:
3474       chain = &class_names_chain;
3475       sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
3476       break;
3477     case meth_var_names:
3478       chain = &meth_var_names_chain;
3479       sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
3480       break;
3481     case meth_var_types:
3482       chain = &meth_var_types_chain;
3483       sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
3484       break;
3485     default:
3486       gcc_unreachable ();
3487     }
3488
3489   while (*chain)
3490     {
3491       if (TREE_VALUE (*chain) == ident)
3492         return convert (string_type_node,
3493                         build_unary_op (input_location,
3494                                         ADDR_EXPR, TREE_PURPOSE (*chain), 1));
3495
3496       chain = &TREE_CHAIN (*chain);
3497     }
3498
3499   type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
3500   decl = start_var_decl (type, buf);
3501   string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
3502                                  IDENTIFIER_POINTER (ident));
3503   TREE_CONSTANT (decl) = 1;
3504   finish_var_decl (decl, string_expr);
3505
3506   *chain = tree_cons (decl, ident, NULL_TREE);
3507
3508   return convert (string_type_node, build_unary_op (input_location,
3509                                                     ADDR_EXPR, decl, 1));
3510 }
3511
3512 void
3513 objc_declare_alias (tree alias_ident, tree class_ident)
3514 {
3515   tree underlying_class;
3516
3517 #ifdef OBJCPLUS
3518   if (current_namespace != global_namespace) {
3519     error ("Objective-C declarations may only appear in global scope");
3520   }
3521 #endif /* OBJCPLUS */
3522
3523   if (!(underlying_class = objc_is_class_name (class_ident)))
3524     warning (0, "cannot find class %qE", class_ident);
3525   else if (objc_is_class_name (alias_ident))
3526     warning (0, "class %qE already exists", alias_ident);
3527   else
3528     {
3529       /* Implement @compatibility_alias as a typedef.  */
3530 #ifdef OBJCPLUS
3531       push_lang_context (lang_name_c); /* extern "C" */
3532 #endif
3533       lang_hooks.decls.pushdecl (build_decl
3534                                  (input_location,
3535                                   TYPE_DECL,
3536                                   alias_ident,
3537                                   xref_tag (RECORD_TYPE, underlying_class)));
3538 #ifdef OBJCPLUS
3539       pop_lang_context ();
3540 #endif
3541       hash_class_name_enter (als_name_hash_list, alias_ident, 
3542                              underlying_class);
3543     }
3544 }
3545
3546 void
3547 objc_declare_class (tree ident_list)
3548 {
3549   tree list;
3550 #ifdef OBJCPLUS
3551   if (current_namespace != global_namespace) {
3552     error ("Objective-C declarations may only appear in global scope");
3553   }
3554 #endif /* OBJCPLUS */
3555
3556   for (list = ident_list; list; list = TREE_CHAIN (list))
3557     {
3558       tree ident = TREE_VALUE (list);
3559
3560       if (! objc_is_class_name (ident))
3561         {
3562           tree record = lookup_name (ident), type = record;
3563
3564           if (record)
3565             {
3566               if (TREE_CODE (record) == TYPE_DECL)
3567                 type = DECL_ORIGINAL_TYPE (record) ? 
3568                         DECL_ORIGINAL_TYPE (record) : 
3569                         TREE_TYPE (record);
3570
3571               if (!TYPE_HAS_OBJC_INFO (type)
3572                   || !TYPE_OBJC_INTERFACE (type))
3573                 {
3574                   error ("%qE redeclared as different kind of symbol",
3575                          ident);
3576                   error ("previous declaration of %q+D",
3577                          record);
3578                 }
3579             }
3580
3581           record = xref_tag (RECORD_TYPE, ident);
3582           INIT_TYPE_OBJC_INFO (record);
3583           TYPE_OBJC_INTERFACE (record) = ident;
3584           hash_class_name_enter (cls_name_hash_list, ident, NULL_TREE);
3585         }
3586     }
3587 }
3588
3589 tree
3590 objc_is_class_name (tree ident)
3591 {
3592   hash target;
3593
3594   if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
3595       && identifier_global_value (ident))
3596     ident = identifier_global_value (ident);
3597   while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
3598     ident = OBJC_TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
3599
3600   if (ident && TREE_CODE (ident) == RECORD_TYPE)
3601     ident = OBJC_TYPE_NAME (ident);
3602 #ifdef OBJCPLUS
3603   if (ident && TREE_CODE (ident) == TYPE_DECL)
3604     {
3605       tree type = TREE_TYPE (ident);
3606       if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
3607         return NULL_TREE;
3608       ident = DECL_NAME (ident);
3609     }
3610 #endif
3611   if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
3612     return NULL_TREE;
3613
3614   if (lookup_interface (ident))
3615     return ident;
3616
3617   target = hash_class_name_lookup (cls_name_hash_list, ident);
3618   if (target)
3619     return target->key;
3620
3621   target = hash_class_name_lookup (als_name_hash_list, ident);
3622   if (target)
3623     {
3624       gcc_assert (target->list && target->list->value);
3625       return target->list->value;
3626     }
3627
3628   return 0;
3629 }
3630
3631 /* Check whether TYPE is either 'id' or 'Class'.  */
3632
3633 tree
3634 objc_is_id (tree type)
3635 {
3636   if (type && TREE_CODE (type) == IDENTIFIER_NODE
3637       && identifier_global_value (type))
3638     type = identifier_global_value (type);
3639
3640   if (type && TREE_CODE (type) == TYPE_DECL)
3641     type = TREE_TYPE (type);
3642
3643   /* NB: This function may be called before the ObjC front-end has
3644      been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL.  */
3645   return (objc_object_type && type
3646           && (IS_ID (type) || IS_CLASS (type) || IS_SUPER (type))
3647           ? type
3648           : NULL_TREE);
3649 }
3650
3651 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
3652    class instance.  This is needed by other parts of the compiler to
3653    handle ObjC types gracefully.  */
3654
3655 tree
3656 objc_is_object_ptr (tree type)
3657 {
3658   tree ret;
3659
3660   type = TYPE_MAIN_VARIANT (type);
3661   if (!POINTER_TYPE_P (type))
3662     return 0;
3663
3664   ret = objc_is_id (type);
3665   if (!ret)
3666     ret = objc_is_class_name (TREE_TYPE (type));
3667
3668   return ret;
3669 }
3670
3671 static int
3672 objc_is_gcable_type (tree type, int or_strong_p)
3673 {
3674   tree name;
3675
3676   if (!TYPE_P (type))
3677     return 0;
3678   if (objc_is_id (TYPE_MAIN_VARIANT (type)))
3679     return 1;
3680   if (or_strong_p && lookup_attribute ("objc_gc", TYPE_ATTRIBUTES (type)))
3681     return 1;
3682   if (TREE_CODE (type) != POINTER_TYPE && TREE_CODE (type) != INDIRECT_REF)
3683     return 0;
3684   type = TREE_TYPE (type);
3685   if (TREE_CODE (type) != RECORD_TYPE)
3686     return 0;
3687   name = TYPE_NAME (type);
3688   return (objc_is_class_name (name) != NULL_TREE);
3689 }
3690
3691 static tree
3692 objc_substitute_decl (tree expr, tree oldexpr, tree newexpr)
3693 {
3694   if (expr == oldexpr)
3695     return newexpr;
3696
3697   switch (TREE_CODE (expr))
3698     {
3699     case COMPONENT_REF:
3700       return objc_build_component_ref
3701              (objc_substitute_decl (TREE_OPERAND (expr, 0),
3702                                     oldexpr,
3703                                     newexpr),
3704               DECL_NAME (TREE_OPERAND (expr, 1)));
3705     case ARRAY_REF:
3706       return build_array_ref (input_location,
3707                               objc_substitute_decl (TREE_OPERAND (expr, 0),
3708                                                     oldexpr,
3709                                                     newexpr),
3710                               TREE_OPERAND (expr, 1));
3711     case INDIRECT_REF:
3712       return build_indirect_ref (input_location,
3713                                  objc_substitute_decl (TREE_OPERAND (expr, 0),
3714                                                        oldexpr,
3715                                                        newexpr), RO_ARROW);
3716     default:
3717       return expr;
3718     }
3719 }
3720
3721 static tree
3722 objc_build_ivar_assignment (tree outervar, tree lhs, tree rhs)
3723 {
3724   tree func_params;
3725   /* The LHS parameter contains the expression 'outervar->memberspec';
3726      we need to transform it into '&((typeof(outervar) *) 0)->memberspec',
3727      where memberspec may be arbitrarily complex (e.g., 'g->f.d[2].g[3]').
3728   */
3729   tree offs
3730     = objc_substitute_decl
3731       (lhs, outervar, convert (TREE_TYPE (outervar), integer_zero_node));
3732   tree func
3733     = (flag_objc_direct_dispatch
3734        ? objc_assign_ivar_fast_decl
3735        : objc_assign_ivar_decl);
3736
3737   offs = convert (integer_type_node, build_unary_op (input_location,
3738                                                      ADDR_EXPR, offs, 0));
3739   offs = fold (offs);
3740   func_params = tree_cons (NULL_TREE,
3741         convert (objc_object_type, rhs),
3742             tree_cons (NULL_TREE, convert (objc_object_type, outervar),
3743                 tree_cons (NULL_TREE, offs,
3744                     NULL_TREE)));
3745
3746   assemble_external (func);
3747   return build_function_call (input_location, func, func_params);
3748 }
3749
3750 static tree
3751 objc_build_global_assignment (tree lhs, tree rhs)
3752 {
3753   tree func_params = tree_cons (NULL_TREE,
3754         convert (objc_object_type, rhs),
3755             tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3756                       build_unary_op (input_location, ADDR_EXPR, lhs, 0)),
3757                     NULL_TREE));
3758
3759   assemble_external (objc_assign_global_decl);
3760   return build_function_call (input_location, 
3761                               objc_assign_global_decl, func_params);
3762 }
3763
3764 static tree
3765 objc_build_strong_cast_assignment (tree lhs, tree rhs)
3766 {
3767   tree func_params = tree_cons (NULL_TREE,
3768         convert (objc_object_type, rhs),
3769             tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3770                       build_unary_op (input_location, ADDR_EXPR, lhs, 0)),
3771                     NULL_TREE));
3772
3773   assemble_external (objc_assign_strong_cast_decl);
3774   return build_function_call (input_location,
3775                               objc_assign_strong_cast_decl, func_params);
3776 }
3777
3778 static int
3779 objc_is_gcable_p (tree expr)
3780 {
3781   return (TREE_CODE (expr) == COMPONENT_REF
3782           ? objc_is_gcable_p (TREE_OPERAND (expr, 1))
3783           : TREE_CODE (expr) == ARRAY_REF
3784           ? (objc_is_gcable_p (TREE_TYPE (expr))
3785              || objc_is_gcable_p (TREE_OPERAND (expr, 0)))
3786           : TREE_CODE (expr) == ARRAY_TYPE
3787           ? objc_is_gcable_p (TREE_TYPE (expr))
3788           : TYPE_P (expr)
3789           ? objc_is_gcable_type (expr, 1)
3790           : (objc_is_gcable_p (TREE_TYPE (expr))
3791              || (DECL_P (expr)
3792                  && lookup_attribute ("objc_gc", DECL_ATTRIBUTES (expr)))));
3793 }
3794
3795 static int
3796 objc_is_ivar_reference_p (tree expr)
3797 {
3798   return (TREE_CODE (expr) == ARRAY_REF
3799           ? objc_is_ivar_reference_p (TREE_OPERAND (expr, 0))
3800           : TREE_CODE (expr) == COMPONENT_REF
3801           ? TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL
3802           : 0);
3803 }
3804
3805 static int
3806 objc_is_global_reference_p (tree expr)
3807 {
3808   return (TREE_CODE (expr) == INDIRECT_REF || TREE_CODE (expr) == PLUS_EXPR
3809           ? objc_is_global_reference_p (TREE_OPERAND (expr, 0))
3810           : DECL_P (expr)
3811           ? (DECL_FILE_SCOPE_P (expr) || TREE_STATIC (expr))
3812           : 0);
3813 }
3814
3815 tree
3816 objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
3817 {
3818   tree result = NULL_TREE, outer;
3819   int strong_cast_p = 0, outer_gc_p = 0, indirect_p = 0;
3820
3821   /* See if we have any lhs casts, and strip them out.  NB: The lvalue casts
3822      will have been transformed to the form '*(type *)&expr'.  */
3823   if (TREE_CODE (lhs) == INDIRECT_REF)
3824     {
3825       outer = TREE_OPERAND (lhs, 0);
3826
3827       while (!strong_cast_p
3828              && (CONVERT_EXPR_P (outer)
3829                  || TREE_CODE (outer) == NON_LVALUE_EXPR))
3830         {
3831           tree lhstype = TREE_TYPE (outer);
3832
3833           /* Descend down the cast chain, and record the first objc_gc
3834              attribute found.  */
3835           if (POINTER_TYPE_P (lhstype))
3836             {
3837               tree attr
3838                 = lookup_attribute ("objc_gc",
3839                                     TYPE_ATTRIBUTES (TREE_TYPE (lhstype)));
3840
3841               if (attr)
3842                 strong_cast_p = 1;
3843             }
3844
3845           outer = TREE_OPERAND (outer, 0);
3846         }
3847     }
3848
3849   /* If we have a __strong cast, it trumps all else.  */
3850   if (strong_cast_p)
3851     {
3852       if (modifycode != NOP_EXPR)
3853         goto invalid_pointer_arithmetic;
3854
3855       if (warn_assign_intercept)
3856         warning (0, "strong-cast assignment has been intercepted");
3857
3858       result = objc_build_strong_cast_assignment (lhs, rhs);
3859
3860       goto exit_point;
3861     }
3862
3863   /* the lhs must be of a suitable type, regardless of its underlying
3864      structure.  */
3865   if (!objc_is_gcable_p (lhs))
3866     goto exit_point;
3867
3868   outer = lhs;
3869
3870   while (outer
3871          && (TREE_CODE (outer) == COMPONENT_REF
3872              || TREE_CODE (outer) == ARRAY_REF))
3873     outer = TREE_OPERAND (outer, 0);
3874
3875   if (TREE_CODE (outer) == INDIRECT_REF)
3876     {
3877       outer = TREE_OPERAND (outer, 0);
3878       indirect_p = 1;
3879     }
3880
3881   outer_gc_p = objc_is_gcable_p (outer);
3882
3883   /* Handle ivar assignments. */
3884   if (objc_is_ivar_reference_p (lhs))
3885     {
3886       /* if the struct to the left of the ivar is not an Objective-C object (__strong
3887          doesn't cut it here), the best we can do here is suggest a cast.  */
3888       if (!objc_is_gcable_type (TREE_TYPE (outer), 0))
3889         {
3890           /* We may still be able to use the global write barrier... */
3891           if (!indirect_p && objc_is_global_reference_p (outer))
3892             goto global_reference;
3893
3894          suggest_cast:
3895           if (modifycode == NOP_EXPR)
3896             {
3897               if (warn_assign_intercept)
3898                 warning (0, "strong-cast may possibly be needed");
3899             }
3900
3901           goto exit_point;
3902         }
3903
3904       if (modifycode != NOP_EXPR)
3905         goto invalid_pointer_arithmetic;
3906
3907       if (warn_assign_intercept)
3908         warning (0, "instance variable assignment has been intercepted");
3909
3910       result = objc_build_ivar_assignment (outer, lhs, rhs);
3911
3912       goto exit_point;
3913     }
3914
3915   /* Likewise, intercept assignment to global/static variables if their type is
3916      GC-marked.  */
3917   if (objc_is_global_reference_p (outer))
3918     {
3919       if (indirect_p)
3920         goto suggest_cast;
3921
3922      global_reference:
3923       if (modifycode != NOP_EXPR)
3924         {
3925          invalid_pointer_arithmetic:
3926           if (outer_gc_p)
3927             warning (0, "pointer arithmetic for garbage-collected objects not allowed");
3928
3929           goto exit_point;
3930         }
3931
3932       if (warn_assign_intercept)
3933         warning (0, "global/static variable assignment has been intercepted");
3934
3935       result = objc_build_global_assignment (lhs, rhs);
3936     }
3937
3938   /* In all other cases, fall back to the normal mechanism.  */
3939  exit_point:
3940   return result;
3941 }
3942
3943 struct GTY(()) interface_tuple {
3944   tree id;
3945   tree class_name;
3946 };
3947
3948 static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
3949
3950 static hashval_t
3951 hash_interface (const void *p)
3952 {
3953   const struct interface_tuple *d = (const struct interface_tuple *) p;
3954   return IDENTIFIER_HASH_VALUE (d->id);
3955 }
3956
3957 static int
3958 eq_interface (const void *p1, const void *p2)
3959 {
3960   const struct interface_tuple *d = (const struct interface_tuple *) p1;
3961   return d->id == p2;
3962 }
3963
3964 static tree
3965 lookup_interface (tree ident)
3966 {
3967 #ifdef OBJCPLUS
3968   if (ident && TREE_CODE (ident) == TYPE_DECL)
3969     ident = DECL_NAME (ident);
3970 #endif
3971
3972   if (ident == NULL_TREE || TREE_CODE (ident) != IDENTIFIER_NODE)
3973     return NULL_TREE;
3974
3975   {
3976     struct interface_tuple **slot;
3977     tree i = NULL_TREE;
3978
3979     if (interface_htab)
3980       {
3981         slot = (struct interface_tuple **)
3982           htab_find_slot_with_hash (interface_htab, ident,
3983                                     IDENTIFIER_HASH_VALUE (ident),
3984                                     NO_INSERT);
3985         if (slot && *slot)
3986           i = (*slot)->class_name;
3987       }
3988     return i;
3989   }
3990 }
3991
3992 /* Implement @defs (<classname>) within struct bodies.  */
3993
3994 tree
3995 objc_get_class_ivars (tree class_name)
3996 {
3997   tree interface = lookup_interface (class_name);
3998
3999   if (interface)
4000     return get_class_ivars (interface, true);
4001
4002   error ("cannot find interface declaration for %qE",
4003          class_name);
4004
4005   return error_mark_node;
4006 }
4007
4008 /* Called when checking the variables in a struct.  If we are not
4009    doing the ivars list inside an @interface context, then returns
4010    fieldlist unchanged.  Else, returns the list of class ivars.
4011 */
4012 tree
4013 objc_get_interface_ivars (tree fieldlist)
4014 {
4015   if (!objc_collecting_ivars || !objc_interface_context 
4016       || TREE_CODE (objc_interface_context) != CLASS_INTERFACE_TYPE
4017       || CLASS_SUPER_NAME (objc_interface_context) == NULL_TREE)
4018     return fieldlist;
4019
4020   return get_class_ivars (objc_interface_context, true);
4021 }
4022
4023 /* Used by: build_private_template, continue_class,
4024    and for @defs constructs.  */
4025
4026 static tree
4027 get_class_ivars (tree interface, bool inherited)
4028 {
4029   tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
4030
4031   /* Both CLASS_RAW_IVARS and CLASS_IVARS contain a list of ivars declared
4032      by the current class (i.e., they do not include super-class ivars).
4033      However, the CLASS_IVARS list will be side-effected by a call to
4034      finish_struct(), which will fill in field offsets.  */
4035   if (!CLASS_IVARS (interface))
4036     CLASS_IVARS (interface) = ivar_chain;
4037
4038   if (!inherited)
4039     return ivar_chain;
4040
4041   while (CLASS_SUPER_NAME (interface))
4042     {
4043       /* Prepend super-class ivars.  */
4044       interface = lookup_interface (CLASS_SUPER_NAME (interface));
4045       ivar_chain = chainon (copy_list (CLASS_RAW_IVARS (interface)),
4046                             ivar_chain);
4047     }
4048
4049   return ivar_chain;
4050 }
4051
4052 /* Create a temporary variable of type 'type'.  If 'name' is set, uses
4053    the specified name, else use no name.  Returns the declaration of
4054    the type.  The 'name' is mostly useful for debugging.
4055 */
4056 static tree
4057 objc_create_temporary_var (tree type, const char *name)
4058 {
4059   tree decl;
4060
4061   if (name != NULL)
4062     {
4063       decl = build_decl (input_location,
4064                          VAR_DECL, get_identifier (name), type);
4065     }
4066   else
4067     {
4068       decl = build_decl (input_location,
4069                          VAR_DECL, NULL_TREE, type);
4070     }
4071   TREE_USED (decl) = 1;
4072   DECL_ARTIFICIAL (decl) = 1;
4073   DECL_IGNORED_P (decl) = 1;
4074   DECL_CONTEXT (decl) = current_function_decl;
4075
4076   return decl;
4077 }
4078 \f
4079 /* Exception handling constructs.  We begin by having the parser do most
4080    of the work and passing us blocks.  What we do next depends on whether
4081    we're doing "native" exception handling or legacy Darwin setjmp exceptions.
4082    We abstract all of this in a handful of appropriately named routines.  */
4083
4084 /* Stack of open try blocks.  */
4085
4086 struct objc_try_context
4087 {
4088   struct objc_try_context *outer;
4089
4090   /* Statements (or statement lists) as processed by the parser.  */
4091   tree try_body;
4092   tree finally_body;
4093
4094   /* Some file position locations.  */
4095   location_t try_locus;
4096   location_t end_try_locus;
4097   location_t end_catch_locus;
4098   location_t finally_locus;
4099   location_t end_finally_locus;
4100
4101   /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
4102      of a TRY_CATCH_EXPR.  Even when doing Darwin setjmp.  */
4103   tree catch_list;
4104
4105   /* The CATCH_EXPR of an open @catch clause.  */
4106   tree current_catch;
4107
4108   /* The VAR_DECL holding the Darwin equivalent of __builtin_eh_pointer.  */
4109   tree caught_decl;
4110   tree stack_decl;
4111   tree rethrow_decl;
4112 };
4113
4114 static struct objc_try_context *cur_try_context;
4115
4116 static GTY(()) tree objc_eh_personality_decl;
4117
4118 /* This hook, called via lang_eh_runtime_type, generates a runtime object
4119    that represents TYPE.  For Objective-C, this is just the class name.  */
4120 /* ??? Isn't there a class object or some such?  Is it easy to get?  */
4121
4122 #ifndef OBJCPLUS
4123 tree
4124 objc_eh_runtime_type (tree type)
4125 {
4126   return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
4127 }
4128
4129 tree
4130 objc_eh_personality (void)
4131 {
4132   if (!flag_objc_sjlj_exceptions && !objc_eh_personality_decl)
4133     objc_eh_personality_decl = build_personality_function ("gnu_objc");
4134   return objc_eh_personality_decl;
4135 }
4136 #endif
4137
4138 /* Build __builtin_eh_pointer, or the moral equivalent.  In the case
4139    of Darwin, we'll arrange for it to be initialized (and associated
4140    with a binding) later.  */
4141
4142 static tree
4143 objc_build_exc_ptr (void)
4144 {
4145   if (flag_objc_sjlj_exceptions)
4146     {
4147       tree var = cur_try_context->caught_decl;
4148       if (!var)
4149         {
4150           var = objc_create_temporary_var (objc_object_type, NULL);
4151           cur_try_context->caught_decl = var;
4152         }
4153       return var;
4154     }
4155   else
4156     {
4157       tree t;
4158       t = built_in_decls[BUILT_IN_EH_POINTER];
4159       t = build_call_expr (t, 1, integer_zero_node);
4160       return fold_convert (objc_object_type, t);
4161     }
4162 }
4163
4164 /* Build "objc_exception_try_exit(&_stack)".  */
4165
4166 static tree
4167 next_sjlj_build_try_exit (void)
4168 {
4169   tree t;
4170   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
4171   t = tree_cons (NULL, t, NULL);
4172   t = build_function_call (input_location,
4173                            objc_exception_try_exit_decl, t);
4174   return t;
4175 }
4176
4177 /* Build
4178         objc_exception_try_enter (&_stack);
4179         if (_setjmp(&_stack.buf))
4180           ;
4181         else
4182           ;
4183    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
4184    empty, ready for the caller to fill them in.  */
4185
4186 static tree
4187 next_sjlj_build_enter_and_setjmp (void)
4188 {
4189   tree t, enter, sj, cond;
4190
4191   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
4192   t = tree_cons (NULL, t, NULL);
4193   enter = build_function_call (input_location,
4194                                objc_exception_try_enter_decl, t);
4195
4196   t = objc_build_component_ref (cur_try_context->stack_decl,
4197                                 get_identifier ("buf"));
4198   t = build_fold_addr_expr_loc (input_location, t);
4199 #ifdef OBJCPLUS
4200   /* Convert _setjmp argument to type that is expected.  */
4201   if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
4202     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
4203   else
4204     t = convert (ptr_type_node, t);
4205 #else
4206   t = convert (ptr_type_node, t);
4207 #endif
4208   t = tree_cons (NULL, t, NULL);
4209   sj = build_function_call (input_location,
4210                             objc_setjmp_decl, t);
4211
4212   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
4213   cond = c_common_truthvalue_conversion (input_location, cond);
4214
4215   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
4216 }
4217
4218 /* Build:
4219
4220    DECL = objc_exception_extract(&_stack);  */
4221
4222 static tree
4223 next_sjlj_build_exc_extract (tree decl)
4224 {
4225   tree t;
4226
4227   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
4228   t = tree_cons (NULL, t, NULL);
4229   t = build_function_call (input_location,
4230                            objc_exception_extract_decl, t);
4231   t = convert (TREE_TYPE (decl), t);
4232   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
4233
4234   return t;
4235 }
4236
4237 /* Build
4238         if (objc_exception_match(obj_get_class(TYPE), _caught)
4239           BODY
4240         else if (...)
4241           ...
4242         else
4243           {
4244             _rethrow = _caught;
4245             objc_exception_try_exit(&_stack);
4246           }
4247    from the sequence of CATCH_EXPRs in the current try context.  */
4248
4249 static tree
4250 next_sjlj_build_catch_list (void)
4251 {
4252   tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
4253   tree catch_seq, t;
4254   tree *last = &catch_seq;
4255   bool saw_id = false;
4256
4257   for (; !tsi_end_p (i); tsi_next (&i))
4258     {
4259       tree stmt = tsi_stmt (i);
4260       tree type = CATCH_TYPES (stmt);
4261       tree body = CATCH_BODY (stmt);
4262
4263       if (type == NULL)
4264         {
4265           *last = body;
4266           saw_id = true;
4267           break;
4268         }
4269       else
4270         {
4271           tree args, cond;
4272
4273           if (type == error_mark_node)
4274             cond = error_mark_node;
4275           else
4276             {
4277               args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
4278               t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
4279               args = tree_cons (NULL, t, args);
4280               t = build_function_call (input_location,
4281                                        objc_exception_match_decl, args);
4282               cond = c_common_truthvalue_conversion (input_location, t);
4283             }
4284           t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
4285           SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
4286
4287           *last = t;
4288           last = &COND_EXPR_ELSE (t);
4289         }
4290     }
4291
4292   if (!saw_id)
4293     {
4294       t = build2 (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
4295                   cur_try_context->caught_decl);
4296       SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
4297       append_to_statement_list (t, last);
4298
4299       t = next_sjlj_build_try_exit ();
4300       SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
4301       append_to_statement_list (t, last);
4302     }
4303
4304   return catch_seq;
4305 }
4306
4307 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
4308    exception handling.  We aim to build:
4309
4310         {
4311           struct _objc_exception_data _stack;
4312           id _rethrow = 0;
4313           try
4314             {
4315               objc_exception_try_enter (&_stack);
4316               if (_setjmp(&_stack.buf))
4317                 {
4318                   id _caught = objc_exception_extract(&_stack);
4319                   objc_exception_try_enter (&_stack);
4320                   if (_setjmp(&_stack.buf))
4321                     _rethrow = objc_exception_extract(&_stack);
4322                   else
4323                     CATCH-LIST
4324                 }
4325               else
4326                 TRY-BLOCK
4327             }
4328           finally
4329             {
4330               if (!_rethrow)
4331                 objc_exception_try_exit(&_stack);
4332               FINALLY-BLOCK
4333               if (_rethrow)
4334                 objc_exception_throw(_rethrow);
4335             }
4336         }
4337
4338    If CATCH-LIST is empty, we can omit all of the block containing
4339    "_caught" except for the setting of _rethrow.  Note the use of
4340    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
4341    but handles goto and other exits from the block.  */
4342
4343 static tree
4344 next_sjlj_build_try_catch_finally (void)
4345 {
4346   tree rethrow_decl, stack_decl, t;
4347   tree catch_seq, try_fin, bind;
4348
4349   /* Create the declarations involved.  */
4350   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
4351   stack_decl = objc_create_temporary_var (t, NULL);
4352   cur_try_context->stack_decl = stack_decl;
4353
4354   rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
4355   cur_try_context->rethrow_decl = rethrow_decl;
4356   TREE_CHAIN (rethrow_decl) = stack_decl;
4357
4358   /* Build the outermost variable binding level.  */
4359   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
4360   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
4361   TREE_SIDE_EFFECTS (bind) = 1;
4362
4363   /* Initialize rethrow_decl.  */
4364   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
4365               convert (objc_object_type, null_pointer_node));
4366   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
4367   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4368
4369   /* Build the outermost TRY_FINALLY_EXPR.  */
4370   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
4371   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
4372   TREE_SIDE_EFFECTS (try_fin) = 1;
4373   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
4374
4375   /* Create the complete catch sequence.  */
4376   if (cur_try_context->catch_list)
4377     {
4378       tree caught_decl = objc_build_exc_ptr ();
4379       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
4380       TREE_SIDE_EFFECTS (catch_seq) = 1;
4381
4382       t = next_sjlj_build_exc_extract (caught_decl);
4383       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
4384
4385       t = next_sjlj_build_enter_and_setjmp ();
4386       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
4387       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
4388       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
4389     }
4390   else
4391     catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
4392   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
4393
4394   /* Build the main register-and-try if statement.  */
4395   t = next_sjlj_build_enter_and_setjmp ();
4396   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
4397   COND_EXPR_THEN (t) = catch_seq;
4398   COND_EXPR_ELSE (t) = cur_try_context->try_body;
4399   TREE_OPERAND (try_fin, 0) = t;
4400
4401   /* Build the complete FINALLY statement list.  */
4402   t = next_sjlj_build_try_exit ();
4403   t = build_stmt (input_location, COND_EXPR,
4404                   c_common_truthvalue_conversion 
4405                     (input_location, rethrow_decl),
4406                   NULL, t);
4407   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
4408   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
4409
4410   append_to_statement_list (cur_try_context->finally_body,
4411                             &TREE_OPERAND (try_fin, 1));
4412
4413   t = tree_cons (NULL, rethrow_decl, NULL);
4414   t = build_function_call (input_location,
4415                            objc_exception_throw_decl, t);
4416   t = build_stmt (input_location, COND_EXPR,
4417                   c_common_truthvalue_conversion (input_location, 
4418                                                   rethrow_decl),
4419                   t, NULL);
4420   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
4421   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
4422
4423   return bind;
4424 }
4425
4426 /* Called just after parsing the @try and its associated BODY.  We now
4427    must prepare for the tricky bits -- handling the catches and finally.  */
4428
4429 void
4430 objc_begin_try_stmt (location_t try_locus, tree body)
4431 {
4432   struct objc_try_context *c = XCNEW (struct objc_try_context);
4433   c->outer = cur_try_context;
4434   c->try_body = body;
4435   c->try_locus = try_locus;
4436   c->end_try_locus = input_location;
4437   cur_try_context = c;
4438
4439   /* -fobjc-exceptions is required to enable Objective-C exceptions.
4440      For example, on Darwin, ObjC exceptions require a sufficiently
4441      recent version of the runtime, so the user must ask for them
4442      explicitly.  On other platforms, at the moment -fobjc-exceptions
4443      triggers -fexceptions which again is required for exceptions to
4444      work.
4445   */
4446   if (!flag_objc_exceptions)
4447     {
4448       error_at (try_locus, "%<-fobjc-exceptions%> is required to enable Objective-C exception syntax");
4449     }
4450
4451   if (flag_objc_sjlj_exceptions)
4452     objc_mark_locals_volatile (NULL);
4453 }
4454
4455 /* Called just after parsing "@catch (parm)".  Open a binding level,
4456    enter DECL into the binding level, and initialize it.  Leave the
4457    binding level open while the body of the compound statement is parsed.  */
4458
4459 void
4460 objc_begin_catch_clause (tree decl)
4461 {
4462   tree compound, type, t;
4463
4464   /* Begin a new scope that the entire catch clause will live in.  */
4465   compound = c_begin_compound_stmt (true);
4466
4467   /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL.  */
4468   decl = build_decl (input_location,
4469                      VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
4470   lang_hooks.decls.pushdecl (decl);
4471
4472   /* Since a decl is required here by syntax, don't warn if its unused.  */
4473   /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
4474      be what the previous objc implementation did.  */
4475   TREE_USED (decl) = 1;
4476   DECL_READ_P (decl) = 1;
4477
4478   /* Verify that the type of the catch is valid.  It must be a pointer
4479      to an Objective-C class, or "id" (which is catch-all).  */
4480   type = TREE_TYPE (decl);
4481
4482   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
4483     type = NULL;
4484   else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
4485     {
4486       error ("@catch parameter is not a known Objective-C class type");
4487       type = error_mark_node;
4488     }
4489   else if (cur_try_context->catch_list)
4490     {
4491       /* Examine previous @catch clauses and see if we've already
4492          caught the type in question.  */
4493       tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
4494       for (; !tsi_end_p (i); tsi_next (&i))
4495         {
4496           tree stmt = tsi_stmt (i);
4497           t = CATCH_TYPES (stmt);
4498           if (t == error_mark_node)
4499             continue;
4500           if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
4501             {
4502               warning (0, "exception of type %<%T%> will be caught",
4503                        TREE_TYPE (type));
4504               warning_at  (EXPR_LOCATION (stmt), 0, "   by earlier handler for %<%T%>",
4505                            TREE_TYPE (t ? t : objc_object_type));
4506               break;
4507             }
4508         }
4509     }
4510
4511   /* Record the data for the catch in the try context so that we can
4512      finalize it later.  */
4513   t = build_stmt (input_location, CATCH_EXPR, type, compound);
4514   cur_try_context->current_catch = t;
4515
4516   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
4517   t = objc_build_exc_ptr ();
4518   t = convert (TREE_TYPE (decl), t);
4519   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
4520   add_stmt (t);
4521 }
4522
4523 /* Called just after parsing the closing brace of a @catch clause.  Close
4524    the open binding level, and record a CATCH_EXPR for it.  */
4525
4526 void
4527 objc_finish_catch_clause (void)
4528 {
4529   tree c = cur_try_context->current_catch;
4530   cur_try_context->current_catch = NULL;
4531   cur_try_context->end_catch_locus = input_location;
4532
4533   CATCH_BODY (c) = c_end_compound_stmt (input_location, CATCH_BODY (c), 1);
4534   append_to_statement_list (c, &cur_try_context->catch_list);
4535 }
4536
4537 /* Called after parsing a @finally clause and its associated BODY.
4538    Record the body for later placement.  */
4539
4540 void
4541 objc_build_finally_clause (location_t finally_locus, tree body)
4542 {
4543   cur_try_context->finally_body = body;
4544   cur_try_context->finally_locus = finally_locus;
4545   cur_try_context->end_finally_locus = input_location;
4546 }
4547
4548 /* Called to finalize a @try construct.  */
4549
4550 tree
4551 objc_finish_try_stmt (void)
4552 {
4553   struct objc_try_context *c = cur_try_context;
4554   tree stmt;
4555
4556   if (c->catch_list == NULL && c->finally_body == NULL)
4557     error ("%<@try%> without %<@catch%> or %<@finally%>");
4558
4559   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
4560   if (flag_objc_sjlj_exceptions)
4561     {
4562       bool save = in_late_binary_op;
4563       in_late_binary_op = true;
4564       if (!cur_try_context->finally_body)
4565         {
4566           cur_try_context->finally_locus = input_location;
4567           cur_try_context->end_finally_locus = input_location;
4568         }
4569       stmt = next_sjlj_build_try_catch_finally ();
4570       in_late_binary_op = save;
4571     }
4572   else
4573     {
4574       /* Otherwise, nest the CATCH inside a FINALLY.  */
4575       stmt = c->try_body;
4576       if (c->catch_list)
4577         {
4578           stmt = build_stmt (input_location, TRY_CATCH_EXPR, stmt, c->catch_list);
4579           SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
4580         }
4581       if (c->finally_body)
4582         {
4583           stmt = build_stmt (input_location, TRY_FINALLY_EXPR, stmt, c->finally_body);
4584           SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
4585         }
4586     }
4587   add_stmt (stmt);
4588
4589   cur_try_context = c->outer;
4590   free (c);
4591   return stmt;
4592 }
4593
4594 tree
4595 objc_build_throw_stmt (location_t loc, tree throw_expr)
4596 {
4597   tree args;
4598
4599   if (!flag_objc_exceptions)
4600     {
4601       error_at (loc, "%<-fobjc-exceptions%> is required to enable Objective-C exception syntax");
4602     }
4603
4604   if (throw_expr == NULL)
4605     {
4606       /* If we're not inside a @catch block, there is no "current
4607          exception" to be rethrown.  */
4608       if (cur_try_context == NULL
4609           || cur_try_context->current_catch == NULL)
4610         {
4611           error_at (loc, "%<@throw%> (rethrow) used outside of a @catch block");
4612           return NULL_TREE;
4613         }
4614
4615       /* Otherwise the object is still sitting in the EXC_PTR_EXPR
4616          value that we get from the runtime.  */
4617       throw_expr = objc_build_exc_ptr ();
4618     }
4619
4620   /* A throw is just a call to the runtime throw function with the
4621      object as a parameter.  */
4622   args = tree_cons (NULL, throw_expr, NULL);
4623   return add_stmt (build_function_call (loc,
4624                                         objc_exception_throw_decl, args));
4625 }
4626
4627 tree
4628 objc_build_synchronized (location_t start_locus, tree mutex, tree body)
4629 {
4630   tree args, call;
4631
4632   /* First lock the mutex.  */
4633   mutex = save_expr (mutex);
4634   args = tree_cons (NULL, mutex, NULL);
4635   call = build_function_call (input_location,
4636                               objc_sync_enter_decl, args);
4637   SET_EXPR_LOCATION (call, start_locus);
4638   add_stmt (call);
4639
4640   /* Build the mutex unlock.  */
4641   args = tree_cons (NULL, mutex, NULL);
4642   call = build_function_call (input_location,
4643                               objc_sync_exit_decl, args);
4644   SET_EXPR_LOCATION (call, input_location);
4645
4646   /* Put the that and the body in a TRY_FINALLY.  */
4647   objc_begin_try_stmt (start_locus, body);
4648   objc_build_finally_clause (input_location, call);
4649   return objc_finish_try_stmt ();
4650 }
4651
4652 \f
4653 /* Predefine the following data type:
4654
4655    struct _objc_exception_data
4656    {
4657      int buf[OBJC_JBLEN];
4658      void *pointers[4];
4659    }; */
4660
4661 /* The following yuckiness should prevent users from having to #include
4662    <setjmp.h> in their code... */
4663
4664 /* Define to a harmless positive value so the below code doesn't die.  */
4665 #ifndef OBJC_JBLEN
4666 #define OBJC_JBLEN 18
4667 #endif
4668
4669 static void
4670 build_next_objc_exception_stuff (void)
4671 {
4672   tree decls, temp_type, *chain = NULL;
4673
4674   objc_exception_data_template
4675     = objc_start_struct (get_identifier (UTAG_EXCDATA));
4676
4677   /* int buf[OBJC_JBLEN]; */
4678
4679   temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
4680   decls = add_field_decl (temp_type, "buf", &chain);
4681
4682   /* void *pointers[4]; */
4683
4684   temp_type = build_sized_array_type (ptr_type_node, 4);
4685   add_field_decl (temp_type, "pointers", &chain);
4686
4687   objc_finish_struct (objc_exception_data_template, decls);
4688
4689   /* int _setjmp(...); */
4690   /* If the user includes <setjmp.h>, this shall be superseded by
4691      'int _setjmp(jmp_buf);' */
4692   temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
4693   objc_setjmp_decl
4694     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4695
4696   /* id objc_exception_extract(struct _objc_exception_data *); */
4697   temp_type
4698     = build_function_type_list (objc_object_type,
4699                                 build_pointer_type (objc_exception_data_template),
4700                                 NULL_TREE);
4701   objc_exception_extract_decl
4702     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
4703                             NULL_TREE);
4704   /* void objc_exception_try_enter(struct _objc_exception_data *); */
4705   /* void objc_exception_try_exit(struct _objc_exception_data *); */
4706   temp_type
4707     = build_function_type_list (void_type_node,
4708                                 build_pointer_type (objc_exception_data_template),
4709                                 NULL_TREE);
4710   objc_exception_try_enter_decl
4711     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
4712                             NULL_TREE);
4713   objc_exception_try_exit_decl
4714     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
4715                             NULL_TREE);
4716
4717   /* int objc_exception_match(id, id); */
4718   temp_type
4719     = build_function_type_list (integer_type_node,
4720                                 objc_object_type, objc_object_type, NULL_TREE);
4721   objc_exception_match_decl
4722     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
4723                             NULL_TREE);
4724
4725   /* id objc_assign_ivar (id, id, unsigned int); */
4726   /* id objc_assign_ivar_Fast (id, id, unsigned int)
4727        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
4728   temp_type
4729     = build_function_type_list (objc_object_type,
4730                                 objc_object_type,
4731                                 objc_object_type,
4732                                 unsigned_type_node,
4733                                 NULL_TREE);
4734   objc_assign_ivar_decl
4735     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
4736                             NULL, NULL_TREE);
4737 #ifdef OFFS_ASSIGNIVAR_FAST
4738   objc_assign_ivar_fast_decl
4739     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
4740                             NOT_BUILT_IN, NULL, NULL_TREE);
4741   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
4742     = tree_cons (get_identifier ("hard_coded_address"),
4743                  build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
4744                  NULL_TREE);
4745 #else
4746   /* Default to slower ivar method.  */
4747   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
4748 #endif
4749
4750   /* id objc_assign_global (id, id *); */
4751   /* id objc_assign_strongCast (id, id *); */
4752   temp_type = build_function_type_list (objc_object_type,
4753                                         objc_object_type,
4754                                         build_pointer_type (objc_object_type),
4755                                         NULL_TREE);
4756   objc_assign_global_decl
4757         = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
4758                                 NULL_TREE);
4759   objc_assign_strong_cast_decl
4760         = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
4761                                 NULL_TREE);
4762 }
4763
4764 static void
4765 build_objc_exception_stuff (void)
4766 {
4767   tree noreturn_list, nothrow_list, temp_type;
4768
4769   noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
4770   nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
4771
4772   /* void objc_exception_throw(id) __attribute__((noreturn)); */
4773   /* void objc_sync_enter(id); */
4774   /* void objc_sync_exit(id); */
4775   temp_type = build_function_type_list (void_type_node,
4776                                         objc_object_type,
4777                                         NULL_TREE);
4778   objc_exception_throw_decl
4779     = add_builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
4780                             noreturn_list);
4781   objc_sync_enter_decl
4782     = add_builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
4783                             NULL, nothrow_list);
4784   objc_sync_exit_decl
4785     = add_builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
4786                             NULL, nothrow_list);
4787 }
4788
4789 /* Construct a C struct corresponding to ObjC class CLASS, with the same
4790    name as the class:
4791
4792    struct <classname> {
4793      struct _objc_class *isa;
4794      ...
4795    };  */
4796
4797 static void
4798 build_private_template (tree klass)
4799 {
4800   if (!CLASS_STATIC_TEMPLATE (klass))
4801     {
4802       tree record = objc_build_struct (klass,
4803                                        get_class_ivars (klass, false),
4804                                        CLASS_SUPER_NAME (klass));
4805
4806       /* Set the TREE_USED bit for this struct, so that stab generator
4807          can emit stabs for this struct type.  */
4808       if (flag_debug_only_used_symbols && TYPE_STUB_DECL (record))
4809         TREE_USED (TYPE_STUB_DECL (record)) = 1;
4810     }
4811 }
4812 \f
4813 /* Begin code generation for protocols...  */
4814
4815 /* struct _objc_protocol {
4816      struct _objc_class *isa;
4817      char *protocol_name;
4818      struct _objc_protocol **protocol_list;
4819      struct _objc__method_prototype_list *instance_methods;
4820      struct _objc__method_prototype_list *class_methods;
4821    };  */
4822
4823 static void
4824 build_protocol_template (void)
4825 {
4826   tree ptype, decls, *chain = NULL;
4827
4828   objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
4829
4830   /* struct _objc_class *isa; */
4831   ptype = build_pointer_type (xref_tag (RECORD_TYPE,
4832                                         get_identifier (UTAG_CLASS)));
4833   decls = add_field_decl (ptype, "isa", &chain);
4834
4835   /* char *protocol_name; */
4836   add_field_decl (string_type_node, "protocol_name", &chain);
4837
4838   /* struct _objc_protocol **protocol_list; */
4839   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
4840   add_field_decl (ptype, "protocol_list", &chain);
4841
4842   /* struct _objc__method_prototype_list *instance_methods; */
4843   add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
4844
4845   /* struct _objc__method_prototype_list *class_methods; */
4846   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
4847
4848   objc_finish_struct (objc_protocol_template, decls);
4849 }
4850
4851 static tree
4852 build_descriptor_table_initializer (tree type, tree entries)
4853 {
4854   VEC(constructor_elt,gc) *inits = NULL;
4855
4856   do
4857     {
4858       VEC(constructor_elt,gc) *elts = NULL;
4859
4860       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
4861                               build_selector (METHOD_SEL_NAME (entries)));
4862       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
4863                               add_objc_string (METHOD_ENCODING (entries),
4864                                                meth_var_types));
4865
4866       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
4867                               objc_build_constructor (type, elts));
4868
4869       entries = DECL_CHAIN (entries);
4870     }
4871   while (entries);
4872
4873   return objc_build_constructor (build_array_type (type, 0), inits);
4874 }
4875
4876 /* struct objc_method_prototype_list {
4877      int count;
4878      struct objc_method_prototype {
4879         SEL name;
4880         char *types;
4881      } list[1];
4882    };  */
4883
4884 static tree
4885 build_method_prototype_list_template (tree list_type, int size)
4886 {
4887   tree objc_ivar_list_record;
4888   tree array_type, decls, *chain = NULL;
4889
4890   /* Generate an unnamed struct definition.  */
4891
4892   objc_ivar_list_record = objc_start_struct (NULL_TREE);
4893
4894   /* int method_count; */
4895   decls = add_field_decl (integer_type_node, "method_count", &chain);
4896
4897   /* struct objc_method method_list[]; */
4898   array_type = build_sized_array_type (list_type, size);
4899   add_field_decl (array_type, "method_list", &chain);
4900
4901   objc_finish_struct (objc_ivar_list_record, decls);
4902
4903   return objc_ivar_list_record;
4904 }
4905
4906 static tree
4907 build_method_prototype_template (void)
4908 {
4909   tree proto_record;
4910   tree decls, *chain = NULL;
4911
4912   proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
4913
4914   /* SEL _cmd; */
4915   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
4916
4917   /* char *method_types; */
4918   add_field_decl (string_type_node, "method_types", &chain);
4919
4920   objc_finish_struct (proto_record, decls);
4921
4922   return proto_record;
4923 }
4924
4925 static tree
4926 objc_method_parm_type (tree type)
4927 {
4928   type = TREE_VALUE (TREE_TYPE (type));
4929   if (TREE_CODE (type) == TYPE_DECL)
4930     type = TREE_TYPE (type);
4931   return type;
4932 }
4933
4934 static int
4935 objc_encoded_type_size (tree type)
4936 {
4937   int sz = int_size_in_bytes (type);
4938
4939   /* Make all integer and enum types at least as large
4940      as an int.  */
4941   if (sz > 0 && INTEGRAL_TYPE_P (type))
4942     sz = MAX (sz, int_size_in_bytes (integer_type_node));
4943   /* Treat arrays as pointers, since that's how they're
4944      passed in.  */
4945   else if (TREE_CODE (type) == ARRAY_TYPE)
4946     sz = int_size_in_bytes (ptr_type_node);
4947   return sz;
4948 }
4949
4950 /* Encode a method prototype.
4951
4952    The format is described in gcc/doc/objc.texi, section 'Method
4953    signatures'.
4954  */
4955 static tree
4956 encode_method_prototype (tree method_decl)
4957 {
4958   tree parms;
4959   int parm_offset, i;
4960   char buf[40];
4961   tree result;
4962
4963   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
4964   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
4965
4966   /* Encode return type.  */
4967   encode_type (objc_method_parm_type (method_decl),
4968                obstack_object_size (&util_obstack),
4969                OBJC_ENCODE_INLINE_DEFS);
4970
4971   /* Stack size.  */
4972   /* The first two arguments (self and _cmd) are pointers; account for
4973      their size.  */
4974   i = int_size_in_bytes (ptr_type_node);
4975   parm_offset = 2 * i;
4976   for (parms = METHOD_SEL_ARGS (method_decl); parms;
4977        parms = DECL_CHAIN (parms))
4978     {
4979       tree type = objc_method_parm_type (parms);
4980       int sz = objc_encoded_type_size (type);
4981
4982       /* If a type size is not known, bail out.  */
4983       if (sz < 0)
4984         {
4985           error ("type %q+D does not have a known size",
4986                  type);
4987           /* Pretend that the encoding succeeded; the compilation will
4988              fail nevertheless.  */
4989           goto finish_encoding;
4990         }
4991       parm_offset += sz;
4992     }
4993
4994   sprintf (buf, "%d@0:%d", parm_offset, i);
4995   obstack_grow (&util_obstack, buf, strlen (buf));
4996
4997   /* Argument types.  */
4998   parm_offset = 2 * i;
4999   for (parms = METHOD_SEL_ARGS (method_decl); parms;
5000        parms = DECL_CHAIN (parms))
5001     {
5002       tree type = objc_method_parm_type (parms);
5003
5004       /* Process argument qualifiers for user supplied arguments.  */
5005       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
5006
5007       /* Type.  */
5008       encode_type (type, obstack_object_size (&util_obstack),
5009                    OBJC_ENCODE_INLINE_DEFS);
5010
5011       /* Compute offset.  */
5012       sprintf (buf, "%d", parm_offset);
5013       parm_offset += objc_encoded_type_size (type);
5014
5015       obstack_grow (&util_obstack, buf, strlen (buf));
5016     }
5017
5018   finish_encoding:
5019   obstack_1grow (&util_obstack, '\0');
5020   result = get_identifier (XOBFINISH (&util_obstack, char *));
5021   obstack_free (&util_obstack, util_firstobj);
5022   return result;
5023 }
5024
5025 static tree
5026 generate_descriptor_table (tree type, const char *name, int size, tree list,
5027                            tree proto)
5028 {
5029   tree decl;
5030   VEC(constructor_elt,gc) *v = NULL;
5031
5032   decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
5033
5034   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
5035   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
5036
5037   finish_var_decl (decl, objc_build_constructor (type, v));
5038
5039   return decl;
5040 }
5041
5042 static void
5043 generate_method_descriptors (tree protocol)
5044 {
5045   tree initlist, chain, method_list_template;
5046   int size;
5047
5048   if (!objc_method_prototype_template)
5049     objc_method_prototype_template = build_method_prototype_template ();
5050
5051   chain = PROTOCOL_CLS_METHODS (protocol);
5052   if (chain)
5053     {
5054       size = list_length (chain);
5055
5056       method_list_template
5057         = build_method_prototype_list_template (objc_method_prototype_template,
5058                                                 size);
5059
5060       initlist
5061         = build_descriptor_table_initializer (objc_method_prototype_template,
5062                                               chain);
5063
5064       UOBJC_CLASS_METHODS_decl
5065         = generate_descriptor_table (method_list_template,
5066                                      "_OBJC_PROTOCOL_CLASS_METHODS",
5067                                      size, initlist, protocol);
5068     }
5069   else
5070     UOBJC_CLASS_METHODS_decl = 0;
5071
5072   chain = PROTOCOL_NST_METHODS (protocol);
5073   if (chain)
5074     {
5075       size = list_length (chain);
5076
5077       method_list_template
5078         = build_method_prototype_list_template (objc_method_prototype_template,
5079                                                 size);
5080       initlist
5081         = build_descriptor_table_initializer (objc_method_prototype_template,
5082                                               chain);
5083
5084       UOBJC_INSTANCE_METHODS_decl
5085         = generate_descriptor_table (method_list_template,
5086                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
5087                                      size, initlist, protocol);
5088     }
5089   else
5090     UOBJC_INSTANCE_METHODS_decl = 0;
5091 }
5092
5093 static void
5094 generate_protocol_references (tree plist)
5095 {
5096   tree lproto;
5097
5098   /* Forward declare protocols referenced.  */
5099   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
5100     {
5101       tree proto = TREE_VALUE (lproto);
5102
5103       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
5104           && PROTOCOL_NAME (proto))
5105         {
5106           if (! PROTOCOL_FORWARD_DECL (proto))
5107             build_protocol_reference (proto);
5108
5109           if (PROTOCOL_LIST (proto))
5110             generate_protocol_references (PROTOCOL_LIST (proto));
5111         }
5112     }
5113 }
5114
5115 /* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
5116    current class.  */
5117 #ifdef OBJCPLUS
5118 static void
5119 objc_generate_cxx_ctor_or_dtor (bool dtor)
5120 {
5121   tree fn, body, compound_stmt, ivar;
5122
5123   /* - (id) .cxx_construct { ... return self; } */
5124   /* - (void) .cxx_construct { ... }            */
5125
5126   objc_start_method_definition
5127     (false /* is_class_method */,
5128      objc_build_method_signature (false /* is_class_method */,
5129                                   build_tree_list (NULL_TREE,
5130                                                    dtor
5131                                                    ? void_type_node
5132                                                    : objc_object_type),
5133                                   get_identifier (dtor
5134                                                   ? TAG_CXX_DESTRUCT
5135                                                   : TAG_CXX_CONSTRUCT),
5136                                   make_node (TREE_LIST),
5137                                   false), NULL);
5138   body = begin_function_body ();
5139   compound_stmt = begin_compound_stmt (0);
5140
5141   ivar = CLASS_IVARS (implementation_template);
5142   /* Destroy ivars in reverse order.  */
5143   if (dtor)
5144     ivar = nreverse (copy_list (ivar));
5145
5146   for (; ivar; ivar = TREE_CHAIN (ivar))
5147     {
5148       if (TREE_CODE (ivar) == FIELD_DECL)
5149         {
5150           tree type = TREE_TYPE (ivar);
5151
5152           /* Call the ivar's default constructor or destructor.  Do not
5153              call the destructor unless a corresponding constructor call
5154              has also been made (or is not needed).  */
5155           if (MAYBE_CLASS_TYPE_P (type)
5156               && (dtor
5157                   ? (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
5158                      && (!TYPE_NEEDS_CONSTRUCTING (type)
5159                          || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
5160                   : (TYPE_NEEDS_CONSTRUCTING (type)
5161                      && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))))
5162             finish_expr_stmt
5163              (build_special_member_call
5164               (build_ivar_reference (DECL_NAME (ivar)),
5165                dtor ? complete_dtor_identifier : complete_ctor_identifier,
5166                NULL, type, LOOKUP_NORMAL, tf_warning_or_error));
5167         }
5168     }
5169
5170   /* The constructor returns 'self'.  */
5171   if (!dtor)
5172     finish_return_stmt (self_decl);
5173
5174   finish_compound_stmt (compound_stmt);
5175   finish_function_body (body);
5176   fn = current_function_decl;
5177   finish_function ();
5178   objc_finish_method_definition (fn);
5179 }
5180
5181 /* The following routine will examine the current @interface for any
5182    non-POD C++ ivars requiring non-trivial construction and/or
5183    destruction, and then synthesize special '- .cxx_construct' and/or
5184    '- .cxx_destruct' methods which will run the appropriate
5185    construction or destruction code.  Note that ivars inherited from
5186    super-classes are _not_ considered.  */
5187 static void
5188 objc_generate_cxx_cdtors (void)
5189 {
5190   bool need_ctor = false, need_dtor = false;
5191   tree ivar;
5192
5193   /* Error case, due to possibly an extra @end. */
5194   if (!objc_implementation_context)
5195     return;
5196
5197   /* We do not want to do this for categories, since they do not have
5198      their own ivars.  */
5199
5200   if (TREE_CODE (objc_implementation_context) != CLASS_IMPLEMENTATION_TYPE)
5201     return;
5202
5203   /* First, determine if we even need a constructor and/or destructor.  */
5204
5205   for (ivar = CLASS_IVARS (implementation_template); ivar;
5206        ivar = TREE_CHAIN (ivar))
5207     {
5208       if (TREE_CODE (ivar) == FIELD_DECL)
5209         {
5210           tree type = TREE_TYPE (ivar);
5211
5212           if (MAYBE_CLASS_TYPE_P (type))
5213             {
5214               if (TYPE_NEEDS_CONSTRUCTING (type)
5215                   && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
5216                 /* NB: If a default constructor is not available, we will not
5217                    be able to initialize this ivar; the add_instance_variable()
5218                    routine will already have warned about this.  */
5219                 need_ctor = true;
5220
5221               if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
5222                   && (!TYPE_NEEDS_CONSTRUCTING (type)
5223                       || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
5224                 /* NB: If a default constructor is not available, we will not
5225                    call the destructor either, for symmetry.  */
5226                 need_dtor = true;
5227             }
5228         }
5229     }
5230
5231   /* Generate '- .cxx_construct' if needed.  */
5232
5233   if (need_ctor)
5234     objc_generate_cxx_ctor_or_dtor (false);
5235
5236   /* Generate '- .cxx_destruct' if needed.  */
5237
5238   if (need_dtor)
5239     objc_generate_cxx_ctor_or_dtor (true);
5240
5241   /* The 'imp_list' variable points at an imp_entry record for the current
5242      @implementation.  Record the existence of '- .cxx_construct' and/or
5243      '- .cxx_destruct' methods therein; it will be included in the
5244      metadata for the class.  */
5245   if (flag_next_runtime)
5246     imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
5247 }
5248 #endif
5249
5250 /* For each protocol which was referenced either from a @protocol()
5251    expression, or because a class/category implements it (then a
5252    pointer to the protocol is stored in the struct describing the
5253    class/category), we create a statically allocated instance of the
5254    Protocol class.  The code is written in such a way as to generate
5255    as few Protocol objects as possible; we generate a unique Protocol
5256    instance for each protocol, and we don't generate a Protocol
5257    instance if the protocol is never referenced (either from a
5258    @protocol() or from a class/category implementation).  These
5259    statically allocated objects can be referred to via the static
5260    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
5261
5262    The statically allocated Protocol objects that we generate here
5263    need to be fixed up at runtime in order to be used: the 'isa'
5264    pointer of the objects need to be set up to point to the 'Protocol'
5265    class, as known at runtime.
5266
5267    The NeXT runtime fixes up all protocols at program startup time,
5268    before main() is entered.  It uses a low-level trick to look up all
5269    those symbols, then loops on them and fixes them up.
5270
5271    The GNU runtime as well fixes up all protocols before user code
5272    from the module is executed; it requires pointers to those symbols
5273    to be put in the objc_symtab (which is then passed as argument to
5274    the function __objc_exec_class() which the compiler sets up to be
5275    executed automatically when the module is loaded); setup of those
5276    Protocol objects happen in two ways in the GNU runtime: all
5277    Protocol objects referred to by a class or category implementation
5278    are fixed up when the class/category is loaded; all Protocol
5279    objects referred to by a @protocol() expression are added by the
5280    compiler to the list of statically allocated instances to fixup
5281    (the same list holding the statically allocated constant string
5282    objects).  Because, as explained above, the compiler generates as
5283    few Protocol objects as possible, some Protocol object might end up
5284    being referenced multiple times when compiled with the GNU runtime,
5285    and end up being fixed up multiple times at runtime initialization.
5286    But that doesn't hurt, it's just a little inefficient.  */
5287
5288 static void
5289 generate_protocols (void)
5290 {
5291   tree p, encoding;
5292   tree decl;
5293   tree initlist, protocol_name_expr, refs_decl, refs_expr;
5294
5295   /* If a protocol was directly referenced, pull in indirect references.  */
5296   for (p = protocol_chain; p; p = TREE_CHAIN (p))
5297     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
5298       generate_protocol_references (PROTOCOL_LIST (p));
5299
5300   for (p = protocol_chain; p; p = TREE_CHAIN (p))
5301     {
5302       tree nst_methods = PROTOCOL_NST_METHODS (p);
5303       tree cls_methods = PROTOCOL_CLS_METHODS (p);
5304
5305       /* If protocol wasn't referenced, don't generate any code.  */
5306       decl = PROTOCOL_FORWARD_DECL (p);
5307
5308       if (!decl)
5309         continue;
5310
5311       /* Make sure we link in the Protocol class.  */
5312       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
5313
5314       while (nst_methods)
5315         {
5316           if (! METHOD_ENCODING (nst_methods))
5317             {
5318               encoding = encode_method_prototype (nst_methods);
5319               METHOD_ENCODING (nst_methods) = encoding;
5320             }
5321           nst_methods = DECL_CHAIN (nst_methods);
5322         }
5323
5324       while (cls_methods)
5325         {
5326           if (! METHOD_ENCODING (cls_methods))
5327             {
5328               encoding = encode_method_prototype (cls_methods);
5329               METHOD_ENCODING (cls_methods) = encoding;
5330             }
5331
5332           cls_methods = DECL_CHAIN (cls_methods);
5333         }
5334       generate_method_descriptors (p);
5335
5336       if (PROTOCOL_LIST (p))
5337         refs_decl = generate_protocol_list (p);
5338       else
5339         refs_decl = 0;
5340
5341       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5342       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
5343
5344       if (refs_decl)
5345         refs_expr = convert (build_pointer_type (build_pointer_type
5346                                                  (objc_protocol_template)),
5347                              build_unary_op (input_location,
5348                                              ADDR_EXPR, refs_decl, 0));
5349       else
5350         refs_expr = build_int_cst (NULL_TREE, 0);
5351
5352       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
5353          by generate_method_descriptors, which is called above.  */
5354       initlist = build_protocol_initializer (TREE_TYPE (decl),
5355                                              protocol_name_expr, refs_expr,
5356                                              UOBJC_INSTANCE_METHODS_decl,
5357                                              UOBJC_CLASS_METHODS_decl);
5358       finish_var_decl (decl, initlist);
5359     }
5360 }
5361
5362 static tree
5363 build_protocol_initializer (tree type, tree protocol_name,
5364                             tree protocol_list, tree instance_methods,
5365                             tree class_methods)
5366 {
5367   tree expr;
5368   tree cast_type = build_pointer_type
5369                    (xref_tag (RECORD_TYPE,
5370                               get_identifier (UTAG_CLASS)));
5371   VEC(constructor_elt,gc) *inits = NULL;
5372
5373   /* Filling the "isa" in with one allows the runtime system to
5374      detect that the version change...should remove before final release.  */
5375
5376   expr = build_int_cst (cast_type, PROTOCOL_VERSION);
5377   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
5378   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
5379   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
5380
5381   if (!instance_methods)
5382     CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, 0));
5383   else
5384     {
5385       expr = convert (objc_method_proto_list_ptr,
5386                       build_unary_op (input_location, 
5387                                       ADDR_EXPR, instance_methods, 0));
5388       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
5389     }
5390
5391   if (!class_methods)
5392     CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, 0));
5393   else
5394     {
5395       expr = convert (objc_method_proto_list_ptr,
5396                       build_unary_op (input_location, 
5397                                       ADDR_EXPR, class_methods, 0));
5398       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
5399     }
5400
5401   return objc_build_constructor (type, inits);
5402 }
5403 \f
5404 /* struct _objc_category {
5405      char *category_name;
5406      char *class_name;
5407      struct _objc_method_list *instance_methods;
5408      struct _objc_method_list *class_methods;
5409      struct _objc_protocol_list *protocols;
5410    };   */
5411
5412 static void
5413 build_category_template (void)
5414 {
5415   tree ptype, decls, *chain = NULL;
5416
5417   objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
5418
5419   /* char *category_name; */
5420   decls = add_field_decl (string_type_node, "category_name", &chain);
5421
5422   /* char *class_name; */
5423   add_field_decl (string_type_node, "class_name", &chain);
5424
5425   /* struct _objc_method_list *instance_methods; */
5426   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
5427
5428   /* struct _objc_method_list *class_methods; */
5429   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
5430
5431   /* struct _objc_protocol **protocol_list; */
5432   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
5433   add_field_decl (ptype, "protocol_list", &chain);
5434
5435   objc_finish_struct (objc_category_template, decls);
5436 }
5437
5438 /* struct _objc_selector {
5439      SEL sel_id;
5440      char *sel_type;
5441    }; */
5442
5443 static void
5444 build_selector_template (void)
5445 {
5446   tree decls, *chain = NULL;
5447
5448   objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
5449
5450   /* SEL sel_id; */
5451   decls = add_field_decl (objc_selector_type, "sel_id", &chain);
5452
5453   /* char *sel_type; */
5454   add_field_decl (string_type_node, "sel_type", &chain);
5455
5456   objc_finish_struct (objc_selector_template, decls);
5457 }
5458
5459 /* struct _objc_class {
5460      struct _objc_class *isa;
5461      struct _objc_class *super_class;
5462      char *name;
5463      long version;
5464      long info;
5465      long instance_size;
5466      struct _objc_ivar_list *ivars;
5467      struct _objc_method_list *methods;
5468      #ifdef __NEXT_RUNTIME__
5469        struct objc_cache *cache;
5470      #else
5471        struct sarray *dtable;
5472        struct _objc_class *subclass_list;
5473        struct _objc_class *sibling_class;
5474      #endif
5475      struct _objc_protocol_list *protocols;
5476      #ifdef __NEXT_RUNTIME__
5477        void *sel_id;
5478      #endif
5479      void *gc_object_type;
5480    };  */
5481
5482 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
5483    the NeXT/Apple runtime; still, the compiler must generate them to
5484    maintain backward binary compatibility (and to allow for future
5485    expansion).  */
5486
5487 static void
5488 build_class_template (void)
5489 {
5490   tree ptype, decls, *chain = NULL;
5491
5492   objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
5493
5494   /* struct _objc_class *isa; */
5495   decls = add_field_decl (build_pointer_type (objc_class_template),
5496                           "isa", &chain);
5497
5498   /* struct _objc_class *super_class; */
5499   add_field_decl (build_pointer_type (objc_class_template),
5500                   "super_class", &chain);
5501
5502   /* char *name; */
5503   add_field_decl (string_type_node, "name", &chain);
5504
5505   /* long version; */
5506   add_field_decl (long_integer_type_node, "version", &chain);
5507
5508   /* long info; */
5509   add_field_decl (long_integer_type_node, "info", &chain);
5510
5511   /* long instance_size; */
5512   add_field_decl (long_integer_type_node, "instance_size", &chain);
5513
5514   /* struct _objc_ivar_list *ivars; */
5515   add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
5516
5517   /* struct _objc_method_list *methods; */
5518   add_field_decl (objc_method_list_ptr, "methods", &chain);
5519
5520   if (flag_next_runtime)
5521     {
5522       /* struct objc_cache *cache; */
5523       ptype = build_pointer_type (xref_tag (RECORD_TYPE,
5524                                             get_identifier ("objc_cache")));
5525       add_field_decl (ptype, "cache", &chain);
5526     }
5527   else
5528     {
5529       /* struct sarray *dtable; */
5530       ptype = build_pointer_type(xref_tag (RECORD_TYPE,
5531                                            get_identifier ("sarray")));
5532       add_field_decl (ptype, "dtable", &chain);
5533
5534       /* struct objc_class *subclass_list; */
5535       ptype = build_pointer_type (objc_class_template);
5536       add_field_decl (ptype, "subclass_list", &chain);
5537
5538       /* struct objc_class *sibling_class; */
5539       ptype = build_pointer_type (objc_class_template);
5540       add_field_decl (ptype, "sibling_class", &chain);
5541     }
5542
5543   /* struct _objc_protocol **protocol_list; */
5544   ptype = build_pointer_type (build_pointer_type
5545                               (xref_tag (RECORD_TYPE,
5546                                          get_identifier (UTAG_PROTOCOL))));
5547   add_field_decl (ptype, "protocol_list", &chain);
5548
5549   if (flag_next_runtime)
5550     {
5551       /* void *sel_id; */
5552       add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
5553     }
5554
5555   /* void *gc_object_type; */
5556   add_field_decl (build_pointer_type (void_type_node),
5557                   "gc_object_type", &chain);
5558
5559   objc_finish_struct (objc_class_template, decls);
5560 }
5561
5562 /* Generate appropriate forward declarations for an implementation.  */
5563
5564 static void
5565 synth_forward_declarations (void)
5566 {
5567   tree an_id;
5568
5569   /* static struct objc_class _OBJC_CLASS_<my_name>; */
5570   UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
5571                                           objc_class_template);
5572
5573   /* static struct objc_class _OBJC_METACLASS_<my_name>; */
5574   UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
5575                                                   objc_class_template);
5576
5577   /* Pre-build the following entities - for speed/convenience.  */
5578
5579   an_id = get_identifier ("super_class");
5580   ucls_super_ref = objc_build_component_ref (UOBJC_CLASS_decl, an_id);
5581   uucls_super_ref = objc_build_component_ref (UOBJC_METACLASS_decl, an_id);
5582 }
5583
5584 static void
5585 error_with_ivar (const char *message, tree decl)
5586 {
5587   error_at (DECL_SOURCE_LOCATION (decl), "%s %qs",
5588             message, identifier_to_locale (gen_declaration (decl)));
5589
5590 }
5591
5592 static void
5593 check_ivars (tree inter, tree imp)
5594 {
5595   tree intdecls = CLASS_RAW_IVARS (inter);
5596   tree impdecls = CLASS_RAW_IVARS (imp);
5597
5598   while (1)
5599     {
5600       tree t1, t2;
5601
5602 #ifdef OBJCPLUS
5603       if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
5604         intdecls = TREE_CHAIN (intdecls);
5605 #endif
5606       if (intdecls == 0 && impdecls == 0)
5607         break;
5608       if (intdecls == 0 || impdecls == 0)
5609         {
5610           error ("inconsistent instance variable specification");
5611           break;
5612         }
5613
5614       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
5615
5616       if (!comptypes (t1, t2)
5617           || !tree_int_cst_equal (DECL_INITIAL (intdecls),
5618                                   DECL_INITIAL (impdecls)))
5619         {
5620           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
5621             {
5622               error_with_ivar ("conflicting instance variable type",
5623                                impdecls);
5624               error_with_ivar ("previous declaration of",
5625                                intdecls);
5626             }
5627           else                  /* both the type and the name don't match */
5628             {
5629               error ("inconsistent instance variable specification");
5630               break;
5631             }
5632         }
5633
5634       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
5635         {
5636           error_with_ivar ("conflicting instance variable name",
5637                            impdecls);
5638           error_with_ivar ("previous declaration of",
5639                            intdecls);
5640         }
5641
5642       intdecls = DECL_CHAIN (intdecls);
5643       impdecls = DECL_CHAIN (impdecls);
5644     }
5645 }
5646
5647 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
5648    This needs to be done just once per compilation.  */
5649
5650 /* struct _objc_super {
5651      struct _objc_object *self;
5652      struct _objc_class *super_class;
5653    };  */
5654
5655 static void
5656 build_super_template (void)
5657 {
5658   tree decls, *chain = NULL;
5659
5660   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
5661
5662   /* struct _objc_object *self; */
5663   decls = add_field_decl (objc_object_type, "self", &chain);
5664
5665   /* struct _objc_class *super_class; */
5666   add_field_decl (build_pointer_type (objc_class_template),
5667                   "super_class", &chain);
5668
5669   objc_finish_struct (objc_super_template, decls);
5670 }
5671
5672 /* struct _objc_ivar {
5673      char *ivar_name;
5674      char *ivar_type;
5675      int ivar_offset;
5676    };  */
5677
5678 static tree
5679 build_ivar_template (void)
5680 {
5681   tree objc_ivar_id, objc_ivar_record;
5682   tree decls, *chain = NULL;
5683
5684   objc_ivar_id = get_identifier (UTAG_IVAR);
5685   objc_ivar_record = objc_start_struct (objc_ivar_id);
5686
5687   /* char *ivar_name; */
5688   decls = add_field_decl (string_type_node, "ivar_name", &chain);
5689
5690   /* char *ivar_type; */
5691   add_field_decl (string_type_node, "ivar_type", &chain);
5692
5693   /* int ivar_offset; */
5694   add_field_decl (integer_type_node, "ivar_offset", &chain);
5695
5696   objc_finish_struct (objc_ivar_record, decls);
5697
5698   return objc_ivar_record;
5699 }
5700
5701 /* struct {
5702      int ivar_count;
5703      struct objc_ivar ivar_list[ivar_count];
5704    };  */
5705
5706 static tree
5707 build_ivar_list_template (tree list_type, int size)
5708 {
5709   tree objc_ivar_list_record;
5710   tree array_type, decls, *chain = NULL;
5711
5712   objc_ivar_list_record = objc_start_struct (NULL_TREE);
5713
5714   /* int ivar_count; */
5715   decls = add_field_decl (integer_type_node, "ivar_count", &chain);
5716
5717   /* struct objc_ivar ivar_list[]; */
5718   array_type = build_sized_array_type (list_type, size);
5719   add_field_decl (array_type, "ivar_list", &chain);
5720
5721   objc_finish_struct (objc_ivar_list_record, decls);
5722
5723   return objc_ivar_list_record;
5724 }
5725
5726 /* struct {
5727      struct _objc__method_prototype_list *method_next;
5728      int method_count;
5729      struct objc_method method_list[method_count];
5730    };  */
5731
5732 static tree
5733 build_method_list_template (tree list_type, int size)
5734 {
5735   tree objc_ivar_list_record;
5736   tree array_type, decls, *chain = NULL;
5737
5738   objc_ivar_list_record = objc_start_struct (NULL_TREE);
5739
5740   /* struct _objc__method_prototype_list *method_next; */
5741   decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
5742
5743   /* int method_count; */
5744   add_field_decl (integer_type_node, "method_count", &chain);
5745
5746   /* struct objc_method method_list[]; */
5747   array_type = build_sized_array_type (list_type, size);
5748   add_field_decl (array_type, "method_list", &chain);
5749
5750   objc_finish_struct (objc_ivar_list_record, decls);
5751
5752   return objc_ivar_list_record;
5753 }
5754
5755 static tree
5756 build_ivar_list_initializer (tree type, tree field_decl)
5757 {
5758   VEC(constructor_elt,gc) *inits = NULL;
5759
5760   do
5761     {
5762       VEC(constructor_elt,gc) *ivar = NULL;
5763       tree id;
5764
5765       /* Set name.  */
5766       if (DECL_NAME (field_decl))
5767         CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
5768                                 add_objc_string (DECL_NAME (field_decl),
5769                                                  meth_var_names));
5770       else
5771         /* Unnamed bit-field ivar (yuck).  */
5772         CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
5773
5774       /* Set type.  */
5775       encode_field_decl (field_decl,
5776                          obstack_object_size (&util_obstack),
5777                          OBJC_ENCODE_DONT_INLINE_DEFS);
5778
5779       /* Null terminate string.  */
5780       obstack_1grow (&util_obstack, 0);
5781       id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
5782                             meth_var_types);
5783       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
5784       obstack_free (&util_obstack, util_firstobj);
5785
5786       /* Set offset.  */
5787       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
5788       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
5789                               objc_build_constructor (type, ivar));
5790       do
5791         field_decl = DECL_CHAIN (field_decl);
5792       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
5793     }
5794   while (field_decl);
5795
5796   return objc_build_constructor (build_array_type (type, 0), inits);
5797 }
5798
5799 static tree
5800 generate_ivars_list (tree type, const char *name, int size, tree list)
5801 {
5802   tree decl;
5803   VEC(constructor_elt,gc) *inits = NULL;
5804
5805   decl = start_var_decl (type, synth_id_with_class_suffix
5806                                (name, objc_implementation_context));
5807
5808   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
5809   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, list);
5810
5811   finish_var_decl (decl,
5812                    objc_build_constructor (TREE_TYPE (decl), inits));
5813
5814   return decl;
5815 }
5816
5817 /* Count only the fields occurring in T.  */
5818
5819 static int
5820 ivar_list_length (tree t)
5821 {
5822   int count = 0;
5823
5824   for (; t; t = DECL_CHAIN (t))
5825     if (TREE_CODE (t) == FIELD_DECL)
5826       ++count;
5827
5828   return count;
5829 }
5830
5831 static void
5832 generate_ivar_lists (void)
5833 {
5834   tree initlist, ivar_list_template, chain;
5835   int size;
5836
5837   generating_instance_variables = 1;
5838
5839   if (!objc_ivar_template)
5840     objc_ivar_template = build_ivar_template ();
5841
5842   /* Only generate class variables for the root of the inheritance
5843      hierarchy since these will be the same for every class.  */
5844
5845   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
5846       && (chain = TYPE_FIELDS (objc_class_template)))
5847     {
5848       size = ivar_list_length (chain);
5849
5850       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5851       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5852
5853       UOBJC_CLASS_VARIABLES_decl
5854         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
5855                                size, initlist);
5856     }
5857   else
5858     UOBJC_CLASS_VARIABLES_decl = 0;
5859
5860   chain = CLASS_IVARS (implementation_template);
5861   if (chain)
5862     {
5863       size = ivar_list_length (chain);
5864       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5865       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5866
5867       UOBJC_INSTANCE_VARIABLES_decl
5868         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
5869                                size, initlist);
5870     }
5871   else
5872     UOBJC_INSTANCE_VARIABLES_decl = 0;
5873
5874   generating_instance_variables = 0;
5875 }
5876
5877 static tree
5878 build_dispatch_table_initializer (tree type, tree entries)
5879 {
5880   VEC(constructor_elt,gc) *inits = NULL;
5881
5882   do
5883     {
5884       VEC(constructor_elt,gc) *elems = NULL;
5885       tree expr;
5886
5887       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
5888                               build_selector (METHOD_SEL_NAME (entries)));
5889
5890       /* Generate the method encoding if we don't have one already.  */
5891       if (! METHOD_ENCODING (entries))
5892         METHOD_ENCODING (entries) =
5893           encode_method_prototype (entries);
5894
5895       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
5896                               add_objc_string (METHOD_ENCODING (entries),
5897                                                meth_var_types));
5898
5899       expr = convert (ptr_type_node,
5900                       build_unary_op (input_location, ADDR_EXPR,
5901                                       METHOD_DEFINITION (entries), 1));
5902       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
5903
5904       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
5905                               objc_build_constructor (type, elems));
5906
5907       entries = DECL_CHAIN (entries);
5908     }
5909   while (entries);
5910
5911   return objc_build_constructor (build_array_type (type, 0), inits);
5912 }
5913
5914 /* To accomplish method prototyping without generating all kinds of
5915    inane warnings, the definition of the dispatch table entries were
5916    changed from:
5917
5918         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
5919    to:
5920         struct objc_method { SEL _cmd; ...; void *_imp; };  */
5921
5922 static tree
5923 build_method_template (void)
5924 {
5925   tree _SLT_record;
5926   tree decls, *chain = NULL;
5927
5928   _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
5929
5930   /* SEL _cmd; */
5931   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
5932
5933   /* char *method_types; */
5934   add_field_decl (string_type_node, "method_types", &chain);
5935
5936   /* void *_imp; */
5937   add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
5938
5939   objc_finish_struct (_SLT_record, decls);
5940
5941   return _SLT_record;
5942 }
5943
5944
5945 static tree
5946 generate_dispatch_table (tree type, const char *name, int size, tree list)
5947 {
5948   tree decl;
5949   VEC(constructor_elt,gc) *v = NULL;
5950
5951   decl = start_var_decl (type, synth_id_with_class_suffix
5952                                (name, objc_implementation_context));
5953
5954   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
5955   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, size));
5956   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
5957
5958   finish_var_decl (decl,
5959                    objc_build_constructor (TREE_TYPE (decl), v));
5960
5961   return decl;
5962 }
5963
5964 static void
5965 mark_referenced_methods (void)
5966 {
5967   struct imp_entry *impent;
5968   tree chain;
5969
5970   for (impent = imp_list; impent; impent = impent->next)
5971     {
5972       chain = CLASS_CLS_METHODS (impent->imp_context);
5973       while (chain)
5974         {
5975           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5976           chain = DECL_CHAIN (chain);
5977         }
5978
5979       chain = CLASS_NST_METHODS (impent->imp_context);
5980       while (chain)
5981         {
5982           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5983           chain = DECL_CHAIN (chain);
5984         }
5985     }
5986 }
5987
5988 static void
5989 generate_dispatch_tables (void)
5990 {
5991   tree initlist, chain, method_list_template;
5992   int size;
5993
5994   if (!objc_method_template)
5995     objc_method_template = build_method_template ();
5996
5997   chain = CLASS_CLS_METHODS (objc_implementation_context);
5998   if (chain)
5999     {
6000       size = list_length (chain);
6001
6002       method_list_template
6003         = build_method_list_template (objc_method_template, size);
6004       initlist
6005         = build_dispatch_table_initializer (objc_method_template, chain);
6006
6007       UOBJC_CLASS_METHODS_decl
6008         = generate_dispatch_table (method_list_template,
6009                                    ((TREE_CODE (objc_implementation_context)
6010                                      == CLASS_IMPLEMENTATION_TYPE)
6011                                     ? "_OBJC_CLASS_METHODS"
6012                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
6013                                    size, initlist);
6014     }
6015   else
6016     UOBJC_CLASS_METHODS_decl = 0;
6017
6018   chain = CLASS_NST_METHODS (objc_implementation_context);
6019   if (chain)
6020     {
6021       size = list_length (chain);
6022
6023       method_list_template
6024         = build_method_list_template (objc_method_template, size);
6025       initlist
6026         = build_dispatch_table_initializer (objc_method_template, chain);
6027
6028       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
6029         UOBJC_INSTANCE_METHODS_decl
6030           = generate_dispatch_table (method_list_template,
6031                                      "_OBJC_INSTANCE_METHODS",
6032                                      size, initlist);
6033       else
6034         /* We have a category.  */
6035         UOBJC_INSTANCE_METHODS_decl
6036           = generate_dispatch_table (method_list_template,
6037                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
6038                                      size, initlist);
6039     }
6040   else
6041     UOBJC_INSTANCE_METHODS_decl = 0;
6042 }
6043
6044 static tree
6045 generate_protocol_list (tree i_or_p)
6046 {
6047   tree array_type, ptype, refs_decl, lproto, e, plist;
6048   int size = 0;
6049   const char *ref_name;
6050   VEC(constructor_elt,gc) *v = NULL;
6051
6052   switch (TREE_CODE (i_or_p))
6053     {
6054     case CLASS_INTERFACE_TYPE:
6055     case CATEGORY_INTERFACE_TYPE:
6056       plist = CLASS_PROTOCOL_LIST (i_or_p);
6057       break;
6058     case PROTOCOL_INTERFACE_TYPE:
6059       plist = PROTOCOL_LIST (i_or_p);
6060       break;
6061     default:
6062       gcc_unreachable ();
6063     }
6064
6065   /* Compute size.  */
6066   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
6067     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
6068         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
6069       size++;
6070
6071   /* Build initializer.  */
6072   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6073   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
6074   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
6075
6076   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
6077     {
6078       tree pval = TREE_VALUE (lproto);
6079
6080       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
6081           && PROTOCOL_FORWARD_DECL (pval))
6082         {
6083           e = build_unary_op (input_location, ADDR_EXPR, 
6084                               PROTOCOL_FORWARD_DECL (pval), 0);
6085           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
6086         }
6087     }
6088
6089   /* static struct objc_protocol *refs[n]; */
6090
6091   switch (TREE_CODE (i_or_p))
6092     {
6093     case PROTOCOL_INTERFACE_TYPE:
6094       ref_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p);
6095       break;
6096     case CLASS_INTERFACE_TYPE:
6097       ref_name = synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p);
6098       break;
6099     case CATEGORY_INTERFACE_TYPE:
6100       ref_name = synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p);
6101       break;
6102     default:
6103       gcc_unreachable ();
6104     }
6105
6106   ptype = build_pointer_type (objc_protocol_template);
6107   array_type = build_sized_array_type (ptype, size + 3);
6108   refs_decl = start_var_decl (array_type, ref_name);
6109
6110   finish_var_decl (refs_decl,
6111                    objc_build_constructor (TREE_TYPE (refs_decl), v));
6112
6113   return refs_decl;
6114 }
6115
6116 static tree
6117 build_category_initializer (tree type, tree cat_name, tree class_name,
6118                             tree instance_methods, tree class_methods,
6119                             tree protocol_list)
6120 {
6121   tree expr;
6122   VEC(constructor_elt,gc) *v = NULL;
6123
6124   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
6125   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
6126
6127   if (!instance_methods)
6128     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6129   else
6130     {
6131       expr = convert (objc_method_list_ptr,
6132                       build_unary_op (input_location, ADDR_EXPR, 
6133                                       instance_methods, 0));
6134       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6135     }
6136   if (!class_methods)
6137     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6138   else
6139     {
6140       expr = convert (objc_method_list_ptr,
6141                       build_unary_op (input_location, ADDR_EXPR, 
6142                                       class_methods, 0));
6143       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6144     }
6145
6146   /* protocol_list = */
6147   if (!protocol_list)
6148     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6149   else
6150     {
6151       expr = convert (build_pointer_type
6152                       (build_pointer_type
6153                        (objc_protocol_template)),
6154                       build_unary_op (input_location, ADDR_EXPR, 
6155                                       protocol_list, 0));
6156       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6157     }
6158
6159   return objc_build_constructor (type, v);
6160 }
6161
6162 /* struct _objc_class {
6163      struct objc_class *isa;
6164      struct objc_class *super_class;
6165      char *name;
6166      long version;
6167      long info;
6168      long instance_size;
6169      struct objc_ivar_list *ivars;
6170      struct objc_method_list *methods;
6171      if (flag_next_runtime)
6172        struct objc_cache *cache;
6173      else {
6174        struct sarray *dtable;
6175        struct objc_class *subclass_list;
6176        struct objc_class *sibling_class;
6177      }
6178      struct objc_protocol_list *protocols;
6179      if (flag_next_runtime)
6180        void *sel_id;
6181      void *gc_object_type;
6182    };  */
6183
6184 static tree
6185 build_shared_structure_initializer (tree type, tree isa, tree super,
6186                                     tree name, tree size, int status,
6187                                     tree dispatch_table, tree ivar_list,
6188                                     tree protocol_list)
6189 {
6190   tree expr;
6191   VEC(constructor_elt,gc) *v = NULL;
6192
6193   /* isa = */
6194   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
6195
6196   /* super_class = */
6197   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
6198
6199   /* name = */
6200   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
6201
6202   /* version = */
6203   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
6204                           build_int_cst (long_integer_type_node, 0));
6205
6206   /* info = */
6207   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
6208                           build_int_cst (long_integer_type_node, status));
6209
6210   /* instance_size = */
6211   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
6212                           convert (long_integer_type_node, size));
6213
6214   /* objc_ivar_list = */
6215   if (!ivar_list)
6216     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6217   else
6218     {
6219       expr = convert (objc_ivar_list_ptr,
6220                       build_unary_op (input_location, ADDR_EXPR, 
6221                                       ivar_list, 0));
6222       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6223     }
6224
6225   /* objc_method_list = */
6226   if (!dispatch_table)
6227     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6228   else
6229     {
6230       expr = convert (objc_method_list_ptr,
6231                       build_unary_op (input_location, ADDR_EXPR, 
6232                                       dispatch_table, 0));
6233       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6234     }
6235
6236   if (flag_next_runtime)
6237     /* method_cache = */
6238     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6239   else
6240     {
6241       /* dtable = */
6242       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6243
6244       /* subclass_list = */
6245       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6246
6247       /* sibling_class = */
6248       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6249     }
6250
6251   /* protocol_list = */
6252   if (! protocol_list)
6253     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6254   else
6255     {
6256       expr = convert (build_pointer_type
6257                       (build_pointer_type
6258                        (objc_protocol_template)),
6259                       build_unary_op (input_location, ADDR_EXPR, 
6260                                       protocol_list, 0));
6261       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6262     }
6263
6264   if (flag_next_runtime)
6265     /* sel_id = NULL */
6266     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6267
6268   /* gc_object_type = NULL */
6269   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
6270
6271   return objc_build_constructor (type, v);
6272 }
6273
6274 /* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
6275
6276 static inline tree
6277 lookup_category (tree klass, tree cat_name)
6278 {
6279   tree category = CLASS_CATEGORY_LIST (klass);
6280
6281   while (category && CLASS_SUPER_NAME (category) != cat_name)
6282     category = CLASS_CATEGORY_LIST (category);
6283   return category;
6284 }
6285
6286 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
6287
6288 static void
6289 generate_category (struct imp_entry *impent)
6290 {
6291   tree initlist, cat_name_expr, class_name_expr;
6292   tree protocol_decl, category;
6293   tree cat = impent->imp_context;
6294
6295   implementation_template = impent->imp_template;
6296   UOBJC_CLASS_decl = impent->class_decl;
6297   UOBJC_METACLASS_decl = impent->meta_decl;
6298
6299   add_class_reference (CLASS_NAME (cat));
6300   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
6301
6302   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
6303
6304   category = lookup_category (implementation_template,
6305                                 CLASS_SUPER_NAME (cat));
6306
6307   if (category && CLASS_PROTOCOL_LIST (category))
6308     {
6309       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
6310       protocol_decl = generate_protocol_list (category);
6311     }
6312   else
6313     protocol_decl = 0;
6314
6315   initlist = build_category_initializer (TREE_TYPE (UOBJC_CLASS_decl),
6316                                          cat_name_expr, class_name_expr,
6317                                          UOBJC_INSTANCE_METHODS_decl,
6318                                          UOBJC_CLASS_METHODS_decl,
6319                                          protocol_decl);
6320   /* Finish and initialize the forward decl.  */
6321   finish_var_decl (UOBJC_CLASS_decl, initlist);
6322 }
6323
6324 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
6325    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
6326
6327 static void
6328 generate_shared_structures (struct imp_entry *impent)
6329 {
6330   tree name_expr, super_expr, root_expr;
6331   tree my_root_id, my_super_id;
6332   tree cast_type, initlist, protocol_decl;
6333   int cls_flags;
6334   
6335   objc_implementation_context = impent->imp_context;
6336   implementation_template = impent->imp_template;
6337   UOBJC_CLASS_decl = impent->class_decl;
6338   UOBJC_METACLASS_decl = impent->meta_decl;
6339   cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
6340   
6341   my_super_id = CLASS_SUPER_NAME (implementation_template);
6342   if (my_super_id)
6343     {
6344       add_class_reference (my_super_id);
6345
6346       /* Compute "my_root_id" - this is required for code generation.
6347          the "isa" for all meta class structures points to the root of
6348          the inheritance hierarchy (e.g. "__Object")...  */
6349       my_root_id = my_super_id;
6350       do
6351         {
6352           tree my_root_int = lookup_interface (my_root_id);
6353
6354           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
6355             my_root_id = CLASS_SUPER_NAME (my_root_int);
6356           else
6357             break;
6358         }
6359       while (1);
6360     }
6361   else
6362     /* No super class.  */
6363     my_root_id = CLASS_NAME (implementation_template);
6364
6365   cast_type = build_pointer_type (objc_class_template);
6366   name_expr = add_objc_string (CLASS_NAME (implementation_template),
6367                                class_names);
6368
6369   /* Install class `isa' and `super' pointers at runtime.  */
6370   if (my_super_id)
6371     super_expr = add_objc_string (my_super_id, class_names);
6372   else
6373     super_expr = integer_zero_node;
6374     
6375   super_expr = build_c_cast (input_location,
6376                                  cast_type, super_expr); /* cast! */
6377
6378   root_expr = add_objc_string (my_root_id, class_names);
6379   root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */
6380
6381   if (CLASS_PROTOCOL_LIST (implementation_template))
6382     {
6383       generate_protocol_references
6384         (CLASS_PROTOCOL_LIST (implementation_template));
6385       protocol_decl = generate_protocol_list (implementation_template);
6386     }
6387   else
6388     protocol_decl = 0;
6389
6390   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
6391
6392   initlist
6393     = build_shared_structure_initializer
6394       (TREE_TYPE (UOBJC_METACLASS_decl),
6395        root_expr, super_expr, name_expr,
6396        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
6397        2 /*CLS_META*/,
6398        UOBJC_CLASS_METHODS_decl,
6399        UOBJC_CLASS_VARIABLES_decl,
6400        protocol_decl);
6401
6402   finish_var_decl (UOBJC_METACLASS_decl, initlist);
6403
6404   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
6405
6406   initlist
6407     = build_shared_structure_initializer
6408       (TREE_TYPE (UOBJC_CLASS_decl),
6409        build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0),
6410        super_expr, name_expr,
6411        convert (integer_type_node,
6412                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
6413                                 (implementation_template))),
6414        1 /*CLS_FACTORY*/ | cls_flags,
6415        UOBJC_INSTANCE_METHODS_decl,
6416        UOBJC_INSTANCE_VARIABLES_decl,
6417        protocol_decl);
6418
6419   finish_var_decl (UOBJC_CLASS_decl, initlist);
6420 }
6421
6422
6423 static const char *
6424 synth_id_with_class_suffix (const char *preamble, tree ctxt)
6425 {
6426   static char string[BUFSIZE];
6427
6428   switch (TREE_CODE (ctxt))
6429     {
6430     case CLASS_IMPLEMENTATION_TYPE:
6431     case CLASS_INTERFACE_TYPE:
6432       sprintf (string, "%s_%s", preamble,
6433                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
6434       break;
6435     case CATEGORY_IMPLEMENTATION_TYPE:
6436     case CATEGORY_INTERFACE_TYPE:
6437       {
6438         /* We have a category.  */
6439         const char *const class_name
6440           = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
6441         const char *const class_super_name
6442           = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
6443         sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
6444         break;
6445     }
6446     case PROTOCOL_INTERFACE_TYPE:
6447       {
6448         const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
6449         sprintf (string, "%s_%s", preamble, protocol_name);
6450         break;
6451       }
6452     default:
6453       gcc_unreachable ();
6454     }
6455
6456   return string;
6457 }
6458
6459 /* If type is empty or only type qualifiers are present, add default
6460    type of id (otherwise grokdeclarator will default to int).  */
6461 static inline tree
6462 adjust_type_for_id_default (tree type)
6463 {
6464   if (!type)
6465     type = make_node (TREE_LIST);
6466
6467   if (!TREE_VALUE (type))
6468     TREE_VALUE (type) = objc_object_type;
6469   else if (TREE_CODE (TREE_VALUE (type)) == RECORD_TYPE
6470            && TYPED_OBJECT (TREE_VALUE (type)))
6471     error ("can not use an object as parameter to a method");
6472
6473   return type;
6474 }
6475
6476 /* Return a KEYWORD_DECL built using the specified key_name, arg_type,
6477    arg_name and attributes. (TODO: Rename KEYWORD_DECL to
6478    OBJC_METHOD_PARM_DECL ?)
6479
6480    A KEYWORD_DECL is a tree representing the declaration of a
6481    parameter of an Objective-C method.  It is produced when parsing a
6482    fragment of Objective-C method declaration of the form
6483
6484    keyworddecl:
6485      selector ':' '(' typename ')' identifier
6486
6487    For example, take the Objective-C method
6488
6489    -(NSString *)pathForResource:(NSString *)resource ofType:(NSString *)type; 
6490
6491    the two fragments "pathForResource:(NSString *)resource" and
6492    "ofType:(NSString *)type" will generate a KEYWORD_DECL each.  The
6493    KEYWORD_DECL stores the 'key_name' (eg, identifier for
6494    "pathForResource"), the 'arg_type' (eg, tree representing a
6495    NSString *), the 'arg_name' (eg identifier for "resource") and
6496    potentially some attributes (for example, a tree representing
6497    __attribute__ ((unused)) if such an attribute was attached to a
6498    certain parameter).  You can access this information using the
6499    TREE_TYPE (for arg_type), KEYWORD_ARG_NAME (for arg_name),
6500    KEYWORD_KEY_NAME (for key_name), DECL_ATTRIBUTES (for attributes).
6501
6502    'key_name' is an identifier node (and is optional as you can omit
6503    it in Objective-C methods).
6504    'arg_type' is a tree list (and is optional too if no parameter type
6505    was specified).
6506    'arg_name' is an identifier node and is required.
6507    'attributes' is an optional tree containing parameter attributes.  */
6508 tree
6509 objc_build_keyword_decl (tree key_name, tree arg_type, 
6510                          tree arg_name, tree attributes)
6511 {
6512   tree keyword_decl;
6513
6514   /* If no type is specified, default to "id".  */
6515   arg_type = adjust_type_for_id_default (arg_type);
6516
6517   keyword_decl = make_node (KEYWORD_DECL);
6518
6519   TREE_TYPE (keyword_decl) = arg_type;
6520   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
6521   KEYWORD_KEY_NAME (keyword_decl) = key_name;
6522   DECL_ATTRIBUTES (keyword_decl) = attributes;
6523
6524   return keyword_decl;
6525 }
6526
6527 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
6528 static tree
6529 build_keyword_selector (tree selector)
6530 {
6531   int len = 0;
6532   tree key_chain, key_name;
6533   char *buf;
6534
6535   /* Scan the selector to see how much space we'll need.  */
6536   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
6537     {
6538       switch (TREE_CODE (selector))
6539         {
6540         case KEYWORD_DECL:
6541           key_name = KEYWORD_KEY_NAME (key_chain);
6542           break;
6543         case TREE_LIST:
6544           key_name = TREE_PURPOSE (key_chain);
6545           break;
6546         default:
6547           gcc_unreachable ();
6548         }
6549
6550       if (key_name)
6551         len += IDENTIFIER_LENGTH (key_name) + 1;
6552       else
6553         /* Just a ':' arg.  */
6554         len++;
6555     }
6556
6557   buf = (char *) alloca (len + 1);
6558   /* Start the buffer out as an empty string.  */
6559   buf[0] = '\0';
6560
6561   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
6562     {
6563       switch (TREE_CODE (selector))
6564         {
6565         case KEYWORD_DECL:
6566           key_name = KEYWORD_KEY_NAME (key_chain);
6567           break;
6568         case TREE_LIST:
6569           key_name = TREE_PURPOSE (key_chain);
6570           /* The keyword decl chain will later be used as a function
6571              argument chain.  Unhook the selector itself so as to not
6572              confuse other parts of the compiler.  */
6573           TREE_PURPOSE (key_chain) = NULL_TREE;
6574           break;
6575         default:
6576           gcc_unreachable ();
6577         }
6578
6579       if (key_name)
6580         strcat (buf, IDENTIFIER_POINTER (key_name));
6581       strcat (buf, ":");
6582     }
6583
6584   return get_identifier (buf);
6585 }
6586
6587 /* Used for declarations and definitions.  */
6588
6589 static tree
6590 build_method_decl (enum tree_code code, tree ret_type, tree selector,
6591                    tree add_args, bool ellipsis)
6592 {
6593   tree method_decl;
6594
6595   /* If no type is specified, default to "id".  */
6596   ret_type = adjust_type_for_id_default (ret_type);
6597
6598   method_decl = make_node (code);
6599   TREE_TYPE (method_decl) = ret_type;
6600
6601   /* If we have a keyword selector, create an identifier_node that
6602      represents the full selector name (`:' included)...  */
6603   if (TREE_CODE (selector) == KEYWORD_DECL)
6604     {
6605       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
6606       METHOD_SEL_ARGS (method_decl) = selector;
6607       METHOD_ADD_ARGS (method_decl) = add_args;
6608       METHOD_ADD_ARGS_ELLIPSIS_P (method_decl) = ellipsis;
6609     }
6610   else
6611     {
6612       METHOD_SEL_NAME (method_decl) = selector;
6613       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
6614       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
6615     }
6616
6617   return method_decl;
6618 }
6619
6620 #define METHOD_DEF 0
6621 #define METHOD_REF 1
6622
6623 /* This routine processes objective-c method attributes. */
6624
6625 static void
6626 objc_decl_method_attributes (tree *node, tree attributes, int flags)
6627 {
6628   tree sentinel_attr = lookup_attribute ("sentinel", attributes);
6629   if (sentinel_attr)
6630     {
6631       /* hackery to make an obj method look like a function type. */
6632       tree rettype = TREE_TYPE (*node);
6633       TREE_TYPE (*node) = build_function_type (TREE_VALUE (rettype), 
6634                             get_arg_type_list (*node, METHOD_REF, 0));
6635       decl_attributes (node, attributes, flags);
6636       METHOD_TYPE_ATTRIBUTES (*node) = TYPE_ATTRIBUTES (TREE_TYPE (*node));
6637       TREE_TYPE (*node) = rettype;
6638     }
6639   else
6640     decl_attributes (node, attributes, flags);
6641 }
6642
6643 bool 
6644 objc_method_decl (enum tree_code opcode)
6645 {
6646   return opcode == INSTANCE_METHOD_DECL || opcode == CLASS_METHOD_DECL;
6647 }
6648
6649 /* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
6650    an argument list for method METH.  CONTEXT is either METHOD_DEF or
6651    METHOD_REF, saying whether we are trying to define a method or call
6652    one.  SUPERFLAG says this is for a send to super; this makes a
6653    difference for the NeXT calling sequence in which the lookup and
6654    the method call are done together.  If METH is null, user-defined
6655    arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
6656
6657 static tree
6658 get_arg_type_list (tree meth, int context, int superflag)
6659 {
6660   tree arglist, akey;
6661
6662   /* Receiver type.  */
6663   if (flag_next_runtime && superflag)
6664     arglist = build_tree_list (NULL_TREE, objc_super_type);
6665   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
6666     arglist = build_tree_list (NULL_TREE, objc_instance_type);
6667   else
6668     arglist = build_tree_list (NULL_TREE, objc_object_type);
6669
6670   /* Selector type - will eventually change to `int'.  */
6671   chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
6672
6673   /* No actual method prototype given -- assume that remaining arguments
6674      are `...'.  */
6675   if (!meth)
6676     return arglist;
6677
6678   /* Build a list of argument types.  */
6679   for (akey = METHOD_SEL_ARGS (meth); akey; akey = DECL_CHAIN (akey))
6680     {
6681       tree arg_type = TREE_VALUE (TREE_TYPE (akey));
6682
6683       /* Decay argument types for the underlying C function as appropriate.  */
6684       arg_type = objc_decay_parm_type (arg_type);
6685
6686       chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6687     }
6688
6689   if (METHOD_ADD_ARGS (meth))
6690     {
6691       for (akey = TREE_CHAIN (METHOD_ADD_ARGS (meth));
6692            akey; akey = TREE_CHAIN (akey))
6693         {
6694           tree arg_type = TREE_TYPE (TREE_VALUE (akey));
6695
6696           arg_type = objc_decay_parm_type (arg_type);
6697
6698           chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6699         }
6700
6701       if (!METHOD_ADD_ARGS_ELLIPSIS_P (meth))
6702         goto lack_of_ellipsis;
6703     }
6704   else
6705     {
6706      lack_of_ellipsis:
6707       chainon (arglist, OBJC_VOID_AT_END);
6708     }
6709
6710   return arglist;
6711 }
6712
6713 static tree
6714 check_duplicates (hash hsh, int methods, int is_class)
6715 {
6716   tree meth = NULL_TREE;
6717
6718   if (hsh)
6719     {
6720       meth = hsh->key;
6721
6722       if (hsh->list)
6723         {
6724           /* We have two or more methods with the same name but
6725              different types.  */
6726           attr loop;
6727
6728           /* But just how different are those types?  If
6729              -Wno-strict-selector-match is specified, we shall not
6730              complain if the differences are solely among types with
6731              identical size and alignment.  */
6732           if (!warn_strict_selector_match)
6733             {
6734               for (loop = hsh->list; loop; loop = loop->next)
6735                 if (!comp_proto_with_proto (meth, loop->value, 0))
6736                   goto issue_warning;
6737
6738               return meth;
6739             }
6740
6741         issue_warning:
6742           if (methods)
6743             {
6744               bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
6745
6746               warning_at (input_location, 0,
6747                           "multiple methods named %<%c%E%> found",
6748                           (is_class ? '+' : '-'),
6749                           METHOD_SEL_NAME (meth));
6750               inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>",
6751                       (type ? '-' : '+'),
6752                       identifier_to_locale (gen_method_decl (meth)));
6753             }
6754           else
6755             {
6756               bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
6757
6758               warning_at (input_location, 0,
6759                           "multiple selectors named %<%c%E%> found",
6760                           (is_class ? '+' : '-'),
6761                           METHOD_SEL_NAME (meth));
6762               inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>",
6763                       (type ? '-' : '+'),
6764                       identifier_to_locale (gen_method_decl (meth)));
6765             }
6766
6767           for (loop = hsh->list; loop; loop = loop->next)
6768             {
6769               bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL;
6770
6771               inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
6772                       (type ? '-' : '+'),
6773                       identifier_to_locale (gen_method_decl (loop->value)));
6774             }
6775         }
6776     }
6777   return meth;
6778 }
6779
6780 /* If RECEIVER is a class reference, return the identifier node for
6781    the referenced class.  RECEIVER is created by objc_get_class_reference,
6782    so we check the exact form created depending on which runtimes are
6783    used.  */
6784
6785 static tree
6786 receiver_is_class_object (tree receiver, int self, int super)
6787 {
6788   tree chain, exp, arg;
6789
6790   /* The receiver is 'self' or 'super' in the context of a class method.  */
6791   if (objc_method_context
6792       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
6793       && (self || super))
6794     return (super
6795             ? CLASS_SUPER_NAME (implementation_template)
6796             : CLASS_NAME (implementation_template));
6797
6798   if (flag_next_runtime)
6799     {
6800       /* The receiver is a variable created by
6801          build_class_reference_decl.  */
6802       if (TREE_CODE (receiver) == VAR_DECL && IS_CLASS (TREE_TYPE (receiver)))
6803         /* Look up the identifier.  */
6804         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
6805           if (TREE_PURPOSE (chain) == receiver)
6806             return TREE_VALUE (chain);
6807     }
6808
6809   /* The receiver is a function call that returns an id.  Check if
6810      it is a call to objc_getClass, if so, pick up the class name.  */
6811   if (TREE_CODE (receiver) == CALL_EXPR
6812       && (exp = CALL_EXPR_FN (receiver))
6813       && TREE_CODE (exp) == ADDR_EXPR
6814       && (exp = TREE_OPERAND (exp, 0))
6815       && TREE_CODE (exp) == FUNCTION_DECL
6816       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
6817          prototypes for objc_get_class().  Thankfully, they seem to share the
6818          same function type.  */
6819       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
6820       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
6821       /* We have a call to objc_get_class/objc_getClass!  */
6822       && (arg = CALL_EXPR_ARG (receiver, 0)))
6823     {
6824       STRIP_NOPS (arg);
6825       if (TREE_CODE (arg) == ADDR_EXPR
6826           && (arg = TREE_OPERAND (arg, 0))
6827           && TREE_CODE (arg) == STRING_CST)
6828         /* Finally, we have the class name.  */
6829         return get_identifier (TREE_STRING_POINTER (arg));
6830     }
6831   return 0;
6832 }
6833 \f
6834 /* If we are currently building a message expr, this holds
6835    the identifier of the selector of the message.  This is
6836    used when printing warnings about argument mismatches.  */
6837
6838 static tree current_objc_message_selector = 0;
6839
6840 tree
6841 objc_message_selector (void)
6842 {
6843   return current_objc_message_selector;
6844 }
6845
6846 /* Construct an expression for sending a message.
6847    MESS has the object to send to in TREE_PURPOSE
6848    and the argument list (including selector) in TREE_VALUE.
6849
6850    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
6851    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
6852
6853 tree
6854 objc_build_message_expr (tree mess)
6855 {
6856   tree receiver = TREE_PURPOSE (mess);
6857   tree sel_name;
6858 #ifdef OBJCPLUS
6859   tree args = TREE_PURPOSE (TREE_VALUE (mess));
6860 #else
6861   tree args = TREE_VALUE (mess);
6862 #endif
6863   tree method_params = NULL_TREE;
6864
6865   if (TREE_CODE (receiver) == ERROR_MARK || TREE_CODE (args) == ERROR_MARK)
6866     return error_mark_node;
6867
6868   /* Obtain the full selector name.  */
6869   switch (TREE_CODE (args))
6870     {
6871     case IDENTIFIER_NODE:
6872       /* A unary selector.  */
6873       sel_name = args;
6874       break;
6875     case TREE_LIST:
6876       sel_name = build_keyword_selector (args);
6877       break;
6878     default:
6879       gcc_unreachable ();
6880     }
6881
6882   /* Build the parameter list to give to the method.  */
6883   if (TREE_CODE (args) == TREE_LIST)
6884 #ifdef OBJCPLUS
6885     method_params = chainon (args, TREE_VALUE (TREE_VALUE (mess)));
6886 #else
6887     {
6888       tree chain = args, prev = NULL_TREE;
6889
6890       /* We have a keyword selector--check for comma expressions.  */
6891       while (chain)
6892         {
6893           tree element = TREE_VALUE (chain);
6894
6895           /* We have a comma expression, must collapse...  */
6896           if (TREE_CODE (element) == TREE_LIST)
6897             {
6898               if (prev)
6899                 TREE_CHAIN (prev) = element;
6900               else
6901                 args = element;
6902             }
6903           prev = chain;
6904           chain = TREE_CHAIN (chain);
6905         }
6906       method_params = args;
6907     }
6908 #endif
6909
6910 #ifdef OBJCPLUS
6911   if (processing_template_decl)
6912     /* Must wait until template instantiation time.  */
6913     return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
6914                          method_params);
6915 #endif
6916
6917   return objc_finish_message_expr (receiver, sel_name, method_params);
6918 }
6919
6920 /* Look up method SEL_NAME that would be suitable for receiver
6921    of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
6922    nonzero), and report on any duplicates.  */
6923
6924 static tree
6925 lookup_method_in_hash_lists (tree sel_name, int is_class)
6926 {
6927   hash method_prototype = NULL;
6928
6929   if (!is_class)
6930     method_prototype = hash_lookup (nst_method_hash_list,
6931                                     sel_name);
6932
6933   if (!method_prototype)
6934     {
6935       method_prototype = hash_lookup (cls_method_hash_list,
6936                                       sel_name);
6937       is_class = 1;
6938     }
6939
6940   return check_duplicates (method_prototype, 1, is_class);
6941 }
6942
6943 /* The 'objc_finish_message_expr' routine is called from within
6944    'objc_build_message_expr' for non-template functions.  In the case of
6945    C++ template functions, it is called from 'build_expr_from_tree'
6946    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
6947
6948 tree
6949 objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
6950 {
6951   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
6952   tree selector, retval, class_tree;
6953   int self, super, have_cast;
6954
6955   /* We have used the receiver, so mark it as read.  */
6956   mark_exp_read (receiver);
6957
6958   /* Extract the receiver of the message, as well as its type
6959      (where the latter may take the form of a cast or be inferred
6960      from the implementation context).  */
6961   rtype = receiver;
6962   while (TREE_CODE (rtype) == COMPOUND_EXPR
6963               || TREE_CODE (rtype) == MODIFY_EXPR
6964               || CONVERT_EXPR_P (rtype)
6965               || TREE_CODE (rtype) == COMPONENT_REF)
6966     rtype = TREE_OPERAND (rtype, 0);
6967
6968   self = (rtype == self_decl);
6969   super = (rtype == UOBJC_SUPER_decl);
6970   rtype = TREE_TYPE (receiver);
6971
6972   have_cast = (TREE_CODE (receiver) == NOP_EXPR
6973                || (TREE_CODE (receiver) == COMPOUND_EXPR
6974                    && !IS_SUPER (rtype)));
6975
6976   /* If we are calling [super dealloc], reset our warning flag.  */
6977   if (super && !strcmp ("dealloc", IDENTIFIER_POINTER (sel_name)))
6978     should_call_super_dealloc = 0;
6979
6980   /* If the receiver is a class object, retrieve the corresponding
6981      @interface, if one exists. */
6982   class_tree = receiver_is_class_object (receiver, self, super);
6983
6984   /* Now determine the receiver type (if an explicit cast has not been
6985      provided).  */
6986   if (!have_cast)
6987     {
6988       if (class_tree)
6989         rtype = lookup_interface (class_tree);
6990       /* Handle `self' and `super'.  */
6991       else if (super)
6992         {
6993           if (!CLASS_SUPER_NAME (implementation_template))
6994             {
6995               error ("no super class declared in @interface for %qE",
6996                      CLASS_NAME (implementation_template));
6997               return error_mark_node;
6998             }
6999           rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
7000         }
7001       else if (self)
7002         rtype = lookup_interface (CLASS_NAME (implementation_template));
7003     }
7004
7005   /* If receiver is of type `id' or `Class' (or if the @interface for a
7006      class is not visible), we shall be satisfied with the existence of
7007      any instance or class method. */
7008   if (objc_is_id (rtype))
7009     {
7010       class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE);
7011       rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
7012                  ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
7013                  : NULL_TREE);
7014       rtype = NULL_TREE;
7015
7016       if (rprotos)
7017         {
7018           /* If messaging 'id <Protos>' or 'Class <Proto>', first search
7019              in protocols themselves for the method prototype.  */
7020           method_prototype
7021             = lookup_method_in_protocol_list (rprotos, sel_name,
7022                                               class_tree != NULL_TREE);
7023
7024           /* If messaging 'Class <Proto>' but did not find a class method
7025              prototype, search for an instance method instead, and warn
7026              about having done so.  */
7027           if (!method_prototype && !rtype && class_tree != NULL_TREE)
7028             {
7029               method_prototype
7030                 = lookup_method_in_protocol_list (rprotos, sel_name, 0);
7031
7032               if (method_prototype)
7033                 warning (0, "found %<-%E%> instead of %<+%E%> in protocol(s)",
7034                          sel_name, sel_name);
7035             }
7036         }
7037     }
7038   else if (rtype)
7039     {
7040       tree orig_rtype = rtype;
7041
7042       if (TREE_CODE (rtype) == POINTER_TYPE)
7043         rtype = TREE_TYPE (rtype);
7044       /* Traverse typedef aliases */
7045       while (TREE_CODE (rtype) == RECORD_TYPE && OBJC_TYPE_NAME (rtype)
7046              && TREE_CODE (OBJC_TYPE_NAME (rtype)) == TYPE_DECL
7047              && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype)))
7048         rtype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype));
7049       if (TYPED_OBJECT (rtype))
7050         {
7051           rprotos = TYPE_OBJC_PROTOCOL_LIST (rtype);
7052           rtype = TYPE_OBJC_INTERFACE (rtype);
7053         }
7054       /* If we could not find an @interface declaration, we must have
7055          only seen a @class declaration; so, we cannot say anything
7056          more intelligent about which methods the receiver will
7057          understand. */
7058       if (!rtype || TREE_CODE (rtype) == IDENTIFIER_NODE)
7059         {
7060           rtype = NULL_TREE;
7061           /* We could not find an @interface declaration, yet Message maybe in a 
7062              @class's protocol. */
7063           if (!method_prototype && rprotos)
7064             method_prototype
7065               = lookup_method_in_protocol_list (rprotos, sel_name, 0);
7066         }
7067       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
7068           || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
7069         {
7070           /* We have a valid ObjC class name.  Look up the method name
7071              in the published @interface for the class (and its
7072              superclasses). */
7073           method_prototype
7074             = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
7075
7076           /* If the method was not found in the @interface, it may still
7077              exist locally as part of the @implementation.  */
7078           if (!method_prototype && objc_implementation_context
7079              && CLASS_NAME (objc_implementation_context)
7080                 == OBJC_TYPE_NAME (rtype))
7081             method_prototype
7082               = lookup_method
7083                 ((class_tree
7084                   ? CLASS_CLS_METHODS (objc_implementation_context)
7085                   : CLASS_NST_METHODS (objc_implementation_context)),
7086                   sel_name);
7087
7088           /* If we haven't found a candidate method by now, try looking for
7089              it in the protocol list.  */
7090           if (!method_prototype && rprotos)
7091             method_prototype
7092               = lookup_method_in_protocol_list (rprotos, sel_name,
7093                                                 class_tree != NULL_TREE);
7094         }
7095       else
7096         {
7097           warning (0, "invalid receiver type %qs",
7098                    identifier_to_locale (gen_type_name (orig_rtype)));
7099           /* After issuing the "invalid receiver" warning, perform method
7100              lookup as if we were messaging 'id'.  */
7101           rtype = rprotos = NULL_TREE;
7102         }
7103     }
7104
7105
7106   /* For 'id' or 'Class' receivers, search in the global hash table
7107      as a last resort.  For all receivers, warn if protocol searches
7108      have failed.  */
7109   if (!method_prototype)
7110     {
7111       if (rprotos)
7112         warning (0, "%<%c%E%> not found in protocol(s)",
7113                  (class_tree ? '+' : '-'),
7114                  sel_name);
7115
7116       if (!rtype)
7117         method_prototype
7118           = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
7119     }
7120
7121   if (!method_prototype) 
7122     {
7123       static bool warn_missing_methods = false;
7124
7125       if (rtype)
7126         warning (0, "%qE may not respond to %<%c%E%>",
7127                  OBJC_TYPE_NAME (rtype),
7128                  (class_tree ? '+' : '-'),
7129                  sel_name);
7130       /* If we are messaging an 'id' or 'Class' object and made it here,
7131          then we have failed to find _any_ instance or class method,
7132          respectively.  */
7133       else
7134         warning (0, "no %<%c%E%> method found",
7135                  (class_tree ? '+' : '-'),
7136                  sel_name);
7137
7138       if (!warn_missing_methods)
7139         {
7140           warning_at (input_location, 
7141                       0, "(Messages without a matching method signature");
7142           warning_at (input_location, 
7143                       0, "will be assumed to return %<id%> and accept");
7144           warning_at (input_location, 
7145                       0, "%<...%> as arguments.)");
7146           warn_missing_methods = true;
7147         }
7148     }
7149
7150   /* Save the selector name for printing error messages.  */
7151   current_objc_message_selector = sel_name;
7152
7153   /* Build the parameters list for looking up the method.
7154      These are the object itself and the selector.  */
7155
7156   if (flag_typed_selectors)
7157     selector = build_typed_selector_reference (input_location,
7158                                                sel_name, method_prototype);
7159   else
7160     selector = build_selector_reference (input_location, sel_name);
7161
7162   retval = build_objc_method_call (input_location, super, method_prototype,
7163                                    receiver,
7164                                    selector, method_params);
7165
7166   current_objc_message_selector = 0;
7167
7168   return retval;
7169 }
7170 \f
7171 /* Build a tree expression to send OBJECT the operation SELECTOR,
7172    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
7173    assuming the method has prototype METHOD_PROTOTYPE.
7174    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
7175    LOC is the location of the expression to build.
7176    Use METHOD_PARAMS as list of args to pass to the method.
7177    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
7178
7179 static tree
7180 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
7181                         tree lookup_object, tree selector,
7182                         tree method_params)
7183 {
7184   tree sender = (super_flag ? umsg_super_decl :
7185                  (!flag_next_runtime || flag_nil_receivers
7186                   ? (flag_objc_direct_dispatch
7187                      ? umsg_fast_decl
7188                      : umsg_decl)
7189                   : umsg_nonnil_decl));
7190   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
7191   VEC(tree, gc) *parms = NULL;
7192   unsigned nparm = (method_params ? list_length (method_params) : 0);
7193
7194   /* If a prototype for the method to be called exists, then cast
7195      the sender's return type and arguments to match that of the method.
7196      Otherwise, leave sender as is.  */
7197   tree ret_type
7198     = (method_prototype
7199        ? TREE_VALUE (TREE_TYPE (method_prototype))
7200        : objc_object_type);
7201
7202   tree method_param_types = 
7203                 get_arg_type_list (method_prototype, METHOD_REF, super_flag);
7204   tree ftype = build_function_type (ret_type, method_param_types);
7205   tree sender_cast;
7206   tree method, t;
7207
7208   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
7209     ftype = build_type_attribute_variant (
7210               ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
7211
7212   sender_cast = build_pointer_type (ftype);
7213
7214   if (method_prototype && TREE_DEPRECATED (method_prototype))
7215     warn_deprecated_use (method_prototype, NULL_TREE);
7216
7217   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
7218
7219   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
7220   lookup_object = save_expr (lookup_object);
7221
7222   /* Param list + 2 slots for object and selector.  */
7223   parms = VEC_alloc (tree, gc, nparm + 2);
7224
7225   if (flag_next_runtime)
7226     {
7227       /* If we are returning a struct in memory, and the address
7228          of that memory location is passed as a hidden first
7229          argument, then change which messenger entry point this
7230          expr will call.  NB: Note that sender_cast remains
7231          unchanged (it already has a struct return type).  */
7232       if (!targetm.calls.struct_value_rtx (0, 0)
7233           && (TREE_CODE (ret_type) == RECORD_TYPE
7234               || TREE_CODE (ret_type) == UNION_TYPE)
7235           && targetm.calls.return_in_memory (ret_type, 0))
7236         sender = (super_flag ? umsg_super_stret_decl :
7237                 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
7238
7239       method = build_fold_addr_expr_loc (input_location, sender);
7240       /* Pass the object to the method.  */
7241       VEC_quick_push (tree, parms, lookup_object);
7242     }
7243   else
7244     {
7245       /* This is the portable (GNU) way.  */
7246       /* First, call the lookup function to get a pointer to the method,
7247          then cast the pointer, then call it with the method arguments.  */
7248       VEC(tree, gc) *tv = VEC_alloc (tree, gc, 2);
7249       VEC_quick_push (tree, tv, lookup_object);
7250       VEC_quick_push (tree, tv, selector);
7251       method = build_function_call_vec (loc, sender, tv, NULL);
7252       VEC_free (tree, gc, tv);
7253
7254       /* Pass the appropriate object to the method.  */
7255       VEC_quick_push (tree, parms, (super_flag ? self_decl : lookup_object));
7256     }
7257
7258   /* Pass the selector to the method.  */
7259   VEC_quick_push (tree, parms, selector);
7260   /* Now append the remainder of the parms.  */
7261   if (nparm)
7262     for (; method_params; method_params = TREE_CHAIN (method_params))
7263       VEC_quick_push (tree, parms, TREE_VALUE (method_params));
7264
7265   /* Build an obj_type_ref, with the correct cast for the method call.  */
7266   t = build3 (OBJ_TYPE_REF, sender_cast, method, 
7267                             lookup_object, size_zero_node);
7268   t = build_function_call_vec (loc, t, parms, NULL);\
7269   VEC_free (tree, gc, parms);
7270   return t;
7271 }
7272
7273 static void
7274 build_protocol_reference (tree p)
7275 {
7276   tree decl;
7277   const char *proto_name;
7278
7279   /* static struct _objc_protocol _OBJC_PROTOCOL_<mumble>; */
7280
7281   proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
7282   decl = start_var_decl (objc_protocol_template, proto_name);
7283
7284   PROTOCOL_FORWARD_DECL (p) = decl;
7285 }
7286
7287 /* This function is called by the parser when (and only when) a
7288    @protocol() expression is found, in order to compile it.  */
7289 tree
7290 objc_build_protocol_expr (tree protoname)
7291 {
7292   tree expr;
7293   tree p = lookup_protocol (protoname);
7294
7295   if (!p)
7296     {
7297       error ("cannot find protocol declaration for %qE",
7298              protoname);
7299       return error_mark_node;
7300     }
7301
7302   if (!PROTOCOL_FORWARD_DECL (p))
7303     build_protocol_reference (p);
7304
7305   expr = build_unary_op (input_location, 
7306                          ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
7307
7308   /* ??? Ideally we'd build the reference with objc_protocol_type directly,
7309      if we have it, rather than converting it here.  */
7310   expr = convert (objc_protocol_type, expr);
7311
7312   /* The @protocol() expression is being compiled into a pointer to a
7313      statically allocated instance of the Protocol class.  To become
7314      usable at runtime, the 'isa' pointer of the instance need to be
7315      fixed up at runtime by the runtime library, to point to the
7316      actual 'Protocol' class.  */
7317
7318   /* For the GNU runtime, put the static Protocol instance in the list
7319      of statically allocated instances, so that we make sure that its
7320      'isa' pointer is fixed up at runtime by the GNU runtime library
7321      to point to the Protocol class (at runtime, when loading the
7322      module, the GNU runtime library loops on the statically allocated
7323      instances (as found in the defs field in objc_symtab) and fixups
7324      all the 'isa' pointers of those objects).  */
7325   if (! flag_next_runtime)
7326     {
7327       /* This type is a struct containing the fields of a Protocol
7328         object.  (Cfr. objc_protocol_type instead is the type of a pointer
7329         to such a struct).  */
7330       tree protocol_struct_type = xref_tag
7331        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
7332       tree *chain;
7333
7334       /* Look for the list of Protocol statically allocated instances
7335         to fixup at runtime.  Create a new list to hold Protocol
7336         statically allocated instances, if the list is not found.  At
7337         present there is only another list, holding NSConstantString
7338         static instances to be fixed up at runtime.  */
7339       for (chain = &objc_static_instances;
7340            *chain && TREE_VALUE (*chain) != protocol_struct_type;
7341            chain = &TREE_CHAIN (*chain));
7342       if (!*chain)
7343         {
7344          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
7345          add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
7346                           class_names);
7347        }
7348
7349       /* Add this statically allocated instance to the Protocol list.  */
7350       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
7351                                          PROTOCOL_FORWARD_DECL (p),
7352                                          TREE_PURPOSE (*chain));
7353     }
7354
7355
7356   return expr;
7357 }
7358
7359 /* This function is called by the parser when a @selector() expression
7360    is found, in order to compile it.  It is only called by the parser
7361    and only to compile a @selector().  LOC is the location of the
7362    @selector.  */
7363 tree
7364 objc_build_selector_expr (location_t loc, tree selnamelist)
7365 {
7366   tree selname;
7367
7368   /* Obtain the full selector name.  */
7369   switch (TREE_CODE (selnamelist))
7370     {
7371     case IDENTIFIER_NODE:
7372       /* A unary selector.  */
7373       selname = selnamelist;
7374       break;
7375     case TREE_LIST:
7376       selname = build_keyword_selector (selnamelist);
7377       break;
7378     default:
7379       gcc_unreachable ();
7380     }
7381
7382   /* If we are required to check @selector() expressions as they
7383      are found, check that the selector has been declared.  */
7384   if (warn_undeclared_selector)
7385     {
7386       /* Look the selector up in the list of all known class and
7387          instance methods (up to this line) to check that the selector
7388          exists.  */
7389       hash hsh;
7390
7391       /* First try with instance methods.  */
7392       hsh = hash_lookup (nst_method_hash_list, selname);
7393
7394       /* If not found, try with class methods.  */
7395       if (!hsh)
7396         {
7397           hsh = hash_lookup (cls_method_hash_list, selname);
7398         }
7399
7400       /* If still not found, print out a warning.  */
7401       if (!hsh)
7402         {
7403           warning (0, "undeclared selector %qE", selname);
7404         }
7405     }
7406
7407
7408   if (flag_typed_selectors)
7409     return build_typed_selector_reference (loc, selname, 0);
7410   else
7411     return build_selector_reference (loc, selname);
7412 }
7413
7414 /* This is used to implement @encode().  See gcc/doc/objc.texi,
7415    section '@encode'.  */
7416 tree
7417 objc_build_encode_expr (tree type)
7418 {
7419   tree result;
7420   const char *string;
7421
7422   encode_type (type, obstack_object_size (&util_obstack),
7423                OBJC_ENCODE_INLINE_DEFS);
7424   obstack_1grow (&util_obstack, 0);    /* null terminate string */
7425   string = XOBFINISH (&util_obstack, const char *);
7426
7427   /* Synthesize a string that represents the encoded struct/union.  */
7428   result = my_build_string (strlen (string) + 1, string);
7429   obstack_free (&util_obstack, util_firstobj);
7430   return result;
7431 }
7432
7433 static tree
7434 build_ivar_reference (tree id)
7435 {
7436   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7437     {
7438       /* Historically, a class method that produced objects (factory
7439          method) would assign `self' to the instance that it
7440          allocated.  This would effectively turn the class method into
7441          an instance method.  Following this assignment, the instance
7442          variables could be accessed.  That practice, while safe,
7443          violates the simple rule that a class method should not refer
7444          to an instance variable.  It's better to catch the cases
7445          where this is done unknowingly than to support the above
7446          paradigm.  */
7447       warning (0, "instance variable %qE accessed in class method",
7448                id);
7449       self_decl = convert (objc_instance_type, self_decl); /* cast */
7450     }
7451
7452   return objc_build_component_ref (build_indirect_ref (input_location,
7453                                                        self_decl, RO_ARROW),
7454                                    id);
7455 }
7456 \f
7457 /* Compute a hash value for a given method SEL_NAME.  */
7458
7459 static size_t
7460 hash_func (tree sel_name)
7461 {
7462   const unsigned char *s
7463     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
7464   size_t h = 0;
7465
7466   while (*s)
7467     h = h * 67 + *s++ - 113;
7468   return h;
7469 }
7470
7471 static void
7472 hash_init (void)
7473 {
7474   nst_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
7475   cls_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
7476
7477   cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
7478   als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
7479
7480   /* Initialize the hash table used to hold the constant string objects.  */
7481   string_htab = htab_create_ggc (31, string_hash,
7482                                    string_eq, NULL);
7483 }
7484
7485 /* This routine adds sel_name to the hash list. sel_name  is a class or alias
7486    name for the class. If alias name, then value is its underlying class.
7487    If class, the value is NULL_TREE. */
7488
7489 static void
7490 hash_class_name_enter (hash *hashlist, tree sel_name, tree value)
7491 {
7492   hash obj;
7493   int slot = hash_func (sel_name) % SIZEHASHTABLE;
7494
7495   obj = ggc_alloc_hashed_entry ();
7496   if (value != NULL_TREE)
7497     {
7498       /* Save the underlying class for the 'alias' in the hash table */
7499       attr obj_attr = ggc_alloc_hashed_attribute ();
7500       obj_attr->value = value;
7501       obj->list = obj_attr;
7502     }
7503   else
7504     obj->list = 0;
7505   obj->next = hashlist[slot];
7506   obj->key = sel_name;
7507
7508   hashlist[slot] = obj;         /* append to front */
7509
7510 }
7511
7512 /*
7513    Searches in the hash table looking for a match for class or alias name.
7514 */
7515
7516 static hash
7517 hash_class_name_lookup (hash *hashlist, tree sel_name)
7518 {
7519   hash target;
7520
7521   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
7522
7523   while (target)
7524     {
7525       if (sel_name == target->key)
7526         return target;
7527
7528       target = target->next;
7529     }
7530   return 0;
7531 }
7532
7533 /* WARNING!!!!  hash_enter is called with a method, and will peek
7534    inside to find its selector!  But hash_lookup is given a selector
7535    directly, and looks for the selector that's inside the found
7536    entry's key (method) for comparison.  */
7537
7538 static void
7539 hash_enter (hash *hashlist, tree method)
7540 {
7541   hash obj;
7542   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
7543
7544   obj = ggc_alloc_hashed_entry ();
7545   obj->list = 0;
7546   obj->next = hashlist[slot];
7547   obj->key = method;
7548
7549   hashlist[slot] = obj;         /* append to front */
7550 }
7551
7552 static hash
7553 hash_lookup (hash *hashlist, tree sel_name)
7554 {
7555   hash target;
7556
7557   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
7558
7559   while (target)
7560     {
7561       if (sel_name == METHOD_SEL_NAME (target->key))
7562         return target;
7563
7564       target = target->next;
7565     }
7566   return 0;
7567 }
7568
7569 static void
7570 hash_add_attr (hash entry, tree value)
7571 {
7572   attr obj;
7573
7574   obj = ggc_alloc_hashed_attribute ();
7575   obj->next = entry->list;
7576   obj->value = value;
7577
7578   entry->list = obj;            /* append to front */
7579 }
7580 \f
7581 static tree
7582 lookup_method (tree mchain, tree method)
7583 {
7584   tree key;
7585
7586   if (TREE_CODE (method) == IDENTIFIER_NODE)
7587     key = method;
7588   else
7589     key = METHOD_SEL_NAME (method);
7590
7591   while (mchain)
7592     {
7593       if (METHOD_SEL_NAME (mchain) == key)
7594         return mchain;
7595
7596       mchain = DECL_CHAIN (mchain);
7597     }
7598   return NULL_TREE;
7599 }
7600
7601 /* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
7602    in INTERFACE, along with any categories and protocols attached thereto.
7603    If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
7604    recursively examine the INTERFACE's superclass.  If OBJC_LOOKUP_CLASS is
7605    set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
7606    be found in INTERFACE or any of its superclasses, look for an _instance_
7607    method of the same name in the root class as a last resort.
7608
7609    If a suitable method cannot be found, return NULL_TREE.  */
7610
7611 static tree
7612 lookup_method_static (tree interface, tree ident, int flags)
7613 {
7614   tree meth = NULL_TREE, root_inter = NULL_TREE;
7615   tree inter = interface;
7616   int is_class = (flags & OBJC_LOOKUP_CLASS);
7617   int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
7618
7619   while (inter)
7620     {
7621       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
7622       tree category = inter;
7623
7624       /* First, look up the method in the class itself.  */
7625       if ((meth = lookup_method (chain, ident)))
7626         return meth;
7627
7628       /* Failing that, look for the method in each category of the class.  */
7629       while ((category = CLASS_CATEGORY_LIST (category)))
7630         {
7631           chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
7632
7633           /* Check directly in each category.  */
7634           if ((meth = lookup_method (chain, ident)))
7635             return meth;
7636
7637           /* Failing that, check in each category's protocols.  */
7638           if (CLASS_PROTOCOL_LIST (category))
7639             {
7640               if ((meth = (lookup_method_in_protocol_list
7641                            (CLASS_PROTOCOL_LIST (category), ident, is_class))))
7642                 return meth;
7643             }
7644         }
7645
7646       /* If not found in categories, check in protocols of the main class.  */
7647       if (CLASS_PROTOCOL_LIST (inter))
7648         {
7649           if ((meth = (lookup_method_in_protocol_list
7650                        (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
7651             return meth;
7652         }
7653
7654       /* If we were instructed not to look in superclasses, don't.  */
7655       if (no_superclasses)
7656         return NULL_TREE;
7657
7658       /* Failing that, climb up the inheritance hierarchy.  */
7659       root_inter = inter;
7660       inter = lookup_interface (CLASS_SUPER_NAME (inter));
7661     }
7662   while (inter);
7663
7664   /* If no class (factory) method was found, check if an _instance_
7665      method of the same name exists in the root class.  This is what
7666      the Objective-C runtime will do.  If an instance method was not
7667      found, return 0.  */
7668   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
7669 }
7670
7671 /* Add the method to the hash list if it doesn't contain an identical
7672    method already. */
7673
7674 static void
7675 add_method_to_hash_list (hash *hash_list, tree method)
7676 {
7677   hash hsh;
7678
7679   if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
7680     {
7681       /* Install on a global chain.  */
7682       hash_enter (hash_list, method);
7683     }
7684   else
7685     {
7686       /* Check types against those; if different, add to a list.  */
7687       attr loop;
7688       int already_there = comp_proto_with_proto (method, hsh->key, 1);
7689       for (loop = hsh->list; !already_there && loop; loop = loop->next)
7690         already_there |= comp_proto_with_proto (method, loop->value, 1);
7691       if (!already_there)
7692         hash_add_attr (hsh, method);
7693     }
7694 }
7695
7696 static tree
7697 objc_add_method (tree klass, tree method, int is_class, bool is_optional)
7698 {
7699   tree mth;
7700
7701   /* @optional methods are added to protocol's OPTIONAL list */
7702   if (is_optional)
7703     {
7704       gcc_assert (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE);
7705       if (!(mth = lookup_method (is_class
7706                                 ? PROTOCOL_OPTIONAL_CLS_METHODS (klass)
7707                                 : PROTOCOL_OPTIONAL_NST_METHODS (klass), 
7708                                                                 method)))
7709         {
7710           if (is_class)
7711             {
7712               TREE_CHAIN (method) = PROTOCOL_OPTIONAL_CLS_METHODS (klass);
7713               PROTOCOL_OPTIONAL_CLS_METHODS (klass) = method;
7714             }
7715           else
7716             {
7717               TREE_CHAIN (method) = PROTOCOL_OPTIONAL_NST_METHODS (klass);
7718               PROTOCOL_OPTIONAL_NST_METHODS (klass) = method;
7719             }
7720         }
7721     }
7722   else if (!(mth = lookup_method (is_class
7723                              ? CLASS_CLS_METHODS (klass)
7724                              : CLASS_NST_METHODS (klass), method)))
7725     {
7726       /* put method on list in reverse order */
7727       if (is_class)
7728         {
7729           DECL_CHAIN (method) = CLASS_CLS_METHODS (klass);
7730           CLASS_CLS_METHODS (klass) = method;
7731         }
7732       else
7733         {
7734           DECL_CHAIN (method) = CLASS_NST_METHODS (klass);
7735           CLASS_NST_METHODS (klass) = method;
7736         }
7737     }
7738   else
7739     {
7740       /* When processing an @interface for a class or category, give hard
7741          errors on methods with identical selectors but differing argument
7742          and/or return types. We do not do this for @implementations, because
7743          C/C++ will do it for us (i.e., there will be duplicate function
7744          definition errors).  */
7745       if ((TREE_CODE (klass) == CLASS_INTERFACE_TYPE
7746            || TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE)
7747           && !comp_proto_with_proto (method, mth, 1))
7748         error ("duplicate declaration of method %<%c%E%>",
7749                 is_class ? '+' : '-',
7750                 METHOD_SEL_NAME (mth));
7751     }
7752
7753   if (is_class)
7754     add_method_to_hash_list (cls_method_hash_list, method);
7755   else
7756     {
7757       add_method_to_hash_list (nst_method_hash_list, method);
7758
7759       /* Instance methods in root classes (and categories thereof)
7760          may act as class methods as a last resort.  We also add
7761          instance methods listed in @protocol declarations to
7762          the class hash table, on the assumption that @protocols
7763          may be adopted by root classes or categories.  */
7764       if (TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE
7765           || TREE_CODE (klass) == CATEGORY_IMPLEMENTATION_TYPE)
7766         klass = lookup_interface (CLASS_NAME (klass));
7767
7768       if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE
7769           || !CLASS_SUPER_NAME (klass))
7770         add_method_to_hash_list (cls_method_hash_list, method);
7771     }
7772
7773   return method;
7774 }
7775
7776 static tree
7777 add_class (tree class_name, tree name)
7778 {
7779   struct interface_tuple **slot;
7780
7781   /* Put interfaces on list in reverse order.  */
7782   TREE_CHAIN (class_name) = interface_chain;
7783   interface_chain = class_name;
7784
7785   if (interface_htab == NULL)
7786     interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
7787   slot = (struct interface_tuple **)
7788     htab_find_slot_with_hash (interface_htab, name,
7789                               IDENTIFIER_HASH_VALUE (name),
7790                               INSERT);
7791   if (!*slot)
7792     {
7793       *slot = ggc_alloc_cleared_interface_tuple ();
7794       (*slot)->id = name;
7795     }
7796   (*slot)->class_name = class_name;
7797
7798   return interface_chain;
7799 }
7800
7801 static void
7802 add_category (tree klass, tree category)
7803 {
7804   /* Put categories on list in reverse order.  */
7805   tree cat = lookup_category (klass, CLASS_SUPER_NAME (category));
7806
7807   if (cat)
7808     {
7809       warning (0, "duplicate interface declaration for category %<%E(%E)%>",
7810                CLASS_NAME (klass),
7811                CLASS_SUPER_NAME (category));
7812     }
7813   else
7814     {
7815       CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (klass);
7816       CLASS_CATEGORY_LIST (klass) = category;
7817     }
7818 }
7819
7820 /* Called after parsing each instance variable declaration. Necessary to
7821    preserve typedefs and implement public/private...
7822
7823    VISIBILITY is 1 for public, 0 for protected, and 2 for private.  */
7824
7825 static tree
7826 add_instance_variable (tree klass, objc_ivar_visibility_kind visibility, 
7827                        tree field_decl)
7828 {
7829   tree field_type = TREE_TYPE (field_decl);
7830   const char *ivar_name = DECL_NAME (field_decl)
7831                           ? identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (field_decl)))
7832                           : _("<unnamed>");
7833
7834 #ifdef OBJCPLUS
7835   if (TREE_CODE (field_type) == REFERENCE_TYPE)
7836     {
7837       error ("illegal reference type specified for instance variable %qs",
7838              ivar_name);
7839       /* Return class as is without adding this ivar.  */
7840       return klass;
7841     }
7842 #endif
7843
7844   if (field_type == error_mark_node || !TYPE_SIZE (field_type)
7845       || TYPE_SIZE (field_type) == error_mark_node)
7846       /* 'type[0]' is allowed, but 'type[]' is not! */
7847     {
7848       error ("instance variable %qs has unknown size", ivar_name);
7849       /* Return class as is without adding this ivar.  */
7850       return klass;
7851     }
7852
7853 #ifdef OBJCPLUS
7854   /* Check if the ivar being added has a non-POD C++ type.   If so, we will
7855      need to either (1) warn the user about it or (2) generate suitable
7856      constructor/destructor call from '- .cxx_construct' or '- .cxx_destruct'
7857      methods (if '-fobjc-call-cxx-cdtors' was specified).  */
7858   if (MAYBE_CLASS_TYPE_P (field_type)
7859       && (TYPE_NEEDS_CONSTRUCTING (field_type)
7860           || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)
7861           || TYPE_POLYMORPHIC_P (field_type)))
7862     {
7863       tree type_name = OBJC_TYPE_NAME (field_type);
7864
7865       if (flag_objc_call_cxx_cdtors)
7866         {
7867           /* Since the ObjC runtime will be calling the constructors and
7868              destructors for us, the only thing we can't handle is the lack
7869              of a default constructor.  */
7870           if (TYPE_NEEDS_CONSTRUCTING (field_type)
7871               && !TYPE_HAS_DEFAULT_CONSTRUCTOR (field_type))
7872             {
7873               warning (0, "type %qE has no default constructor to call",
7874                        type_name);
7875
7876               /* If we cannot call a constructor, we should also avoid
7877                  calling the destructor, for symmetry.  */
7878               if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7879                 warning (0, "destructor for %qE shall not be run either",
7880                          type_name);
7881             }
7882         }
7883       else
7884         {
7885           static bool warn_cxx_ivars = false;
7886
7887           if (TYPE_POLYMORPHIC_P (field_type))
7888             {
7889               /* Vtable pointers are Real Bad(tm), since Obj-C cannot
7890                  initialize them.  */
7891               error ("type %qE has virtual member functions", type_name);
7892               error ("illegal aggregate type %qE specified "
7893                      "for instance variable %qs",
7894                      type_name, ivar_name);
7895               /* Return class as is without adding this ivar.  */
7896               return klass;
7897             }
7898
7899           /* User-defined constructors and destructors are not known to Obj-C
7900              and hence will not be called.  This may or may not be a problem. */
7901           if (TYPE_NEEDS_CONSTRUCTING (field_type))
7902             warning (0, "type %qE has a user-defined constructor", type_name);
7903           if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7904             warning (0, "type %qE has a user-defined destructor", type_name);
7905
7906           if (!warn_cxx_ivars)
7907             {
7908               warning (0, "C++ constructors and destructors will not "
7909                        "be invoked for Objective-C fields");
7910               warn_cxx_ivars = true;
7911             }
7912         }
7913     }
7914 #endif
7915
7916   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
7917   switch (visibility)
7918     {
7919     case OBJC_IVAR_VIS_PROTECTED:
7920       TREE_PUBLIC (field_decl) = 0;
7921       TREE_PRIVATE (field_decl) = 0;
7922       TREE_PROTECTED (field_decl) = 1;
7923       break;
7924
7925     case OBJC_IVAR_VIS_PACKAGE:
7926     /* TODO: Implement the package variant.  */
7927     case OBJC_IVAR_VIS_PUBLIC:
7928       TREE_PUBLIC (field_decl) = 1;
7929       TREE_PRIVATE (field_decl) = 0;
7930       TREE_PROTECTED (field_decl) = 0;
7931       break;
7932
7933     case OBJC_IVAR_VIS_PRIVATE:
7934       TREE_PUBLIC (field_decl) = 0;
7935       TREE_PRIVATE (field_decl) = 1;
7936       TREE_PROTECTED (field_decl) = 0;
7937       break;
7938
7939     }
7940
7941   CLASS_RAW_IVARS (klass) = chainon (CLASS_RAW_IVARS (klass), field_decl);
7942
7943   return klass;
7944 }
7945 \f
7946
7947 static tree
7948 is_ivar (tree decl_chain, tree ident)
7949 {
7950   for ( ; decl_chain; decl_chain = DECL_CHAIN (decl_chain))
7951     if (DECL_NAME (decl_chain) == ident)
7952       return decl_chain;
7953   return NULL_TREE;
7954 }
7955
7956 /* True if the ivar is private and we are not in its implementation.  */
7957
7958 static int
7959 is_private (tree decl)
7960 {
7961   return (TREE_PRIVATE (decl)
7962           && ! is_ivar (CLASS_IVARS (implementation_template),
7963                         DECL_NAME (decl)));
7964 }
7965
7966 /* We have an instance variable reference;, check to see if it is public.  */
7967
7968 int
7969 objc_is_public (tree expr, tree identifier)
7970 {
7971   tree basetype, decl;
7972
7973 #ifdef OBJCPLUS
7974   if (processing_template_decl)
7975     return 1;
7976 #endif
7977
7978   if (TREE_TYPE (expr) == error_mark_node)
7979     return 1;
7980
7981   basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
7982
7983   if (basetype && TREE_CODE (basetype) == RECORD_TYPE)
7984     {
7985       if (TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
7986         {
7987           tree klass = lookup_interface (OBJC_TYPE_NAME (basetype));
7988
7989           if (!klass)
7990             {
7991               error ("cannot find interface declaration for %qE",
7992                      OBJC_TYPE_NAME (basetype));
7993               return 0;
7994             }
7995
7996           if ((decl = is_ivar (get_class_ivars (klass, true), identifier)))
7997             {
7998               if (TREE_PUBLIC (decl))
7999                 return 1;
8000
8001               /* Important difference between the Stepstone translator:
8002                  all instance variables should be public within the context
8003                  of the implementation.  */
8004               if (objc_implementation_context
8005                  && ((TREE_CODE (objc_implementation_context)
8006                       == CLASS_IMPLEMENTATION_TYPE)
8007                      || (TREE_CODE (objc_implementation_context)
8008                          == CATEGORY_IMPLEMENTATION_TYPE)))
8009                 {
8010                   tree curtype = TYPE_MAIN_VARIANT
8011                                  (CLASS_STATIC_TEMPLATE
8012                                   (implementation_template));
8013
8014                   if (basetype == curtype
8015                       || DERIVED_FROM_P (basetype, curtype))
8016                     {
8017                       int priv = is_private (decl);
8018
8019                       if (priv)
8020                         error ("instance variable %qE is declared private",
8021                                DECL_NAME (decl));
8022
8023                       return !priv;
8024                     }
8025                 }
8026
8027               /* The 2.95.2 compiler sometimes allowed C functions to access
8028                  non-@public ivars.  We will let this slide for now...  */
8029               if (!objc_method_context)
8030               {
8031                 warning (0, "instance variable %qE is %s; "
8032                          "this will be a hard error in the future",
8033                          identifier,
8034                          TREE_PRIVATE (decl) ? "@private" : "@protected");
8035                 return 1;
8036               }
8037
8038               error ("instance variable %qE is declared %s",
8039                      identifier,
8040                      TREE_PRIVATE (decl) ? "private" : "protected");
8041               return 0;
8042             }
8043         }
8044     }
8045
8046   return 1;
8047 }
8048 \f
8049 /* Make sure all entries in CHAIN are also in LIST.  */
8050
8051 static int
8052 check_methods (tree chain, tree list, int mtype)
8053 {
8054   int first = 1;
8055
8056   while (chain)
8057     {
8058       /* If the method is associated with a dynamic property, then it
8059          is Ok not to have the method implementation, as it will be
8060          generated dynamically at runtime.  */
8061       tree property = METHOD_PROPERTY_CONTEXT (chain);
8062       if (property != NULL_TREE  &&  PROPERTY_DYNAMIC (property))
8063         {
8064           chain = TREE_CHAIN (chain); /* next method...  */
8065           continue;
8066         }
8067
8068       if (!lookup_method (list, chain))
8069         {
8070           if (first)
8071             {
8072               switch (TREE_CODE (objc_implementation_context))
8073                 {
8074                 case CLASS_IMPLEMENTATION_TYPE:
8075                   warning (0, "incomplete implementation of class %qE",
8076                            CLASS_NAME (objc_implementation_context));
8077                   break;
8078                 case CATEGORY_IMPLEMENTATION_TYPE:
8079                   warning (0, "incomplete implementation of category %qE",
8080                            CLASS_SUPER_NAME (objc_implementation_context));
8081                   break;
8082                 default:
8083                   gcc_unreachable ();
8084                 }
8085               first = 0;
8086             }
8087
8088           warning (0, "method definition for %<%c%E%> not found",
8089                    mtype, METHOD_SEL_NAME (chain));
8090         }
8091
8092       chain = DECL_CHAIN (chain);
8093     }
8094
8095     return first;
8096 }
8097
8098 /* Check if KLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
8099
8100 static int
8101 conforms_to_protocol (tree klass, tree protocol)
8102 {
8103    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
8104      {
8105        tree p = CLASS_PROTOCOL_LIST (klass);
8106        while (p && TREE_VALUE (p) != protocol)
8107          p = TREE_CHAIN (p);
8108
8109        if (!p)
8110          {
8111            tree super = (CLASS_SUPER_NAME (klass)
8112                          ? lookup_interface (CLASS_SUPER_NAME (klass))
8113                          : NULL_TREE);
8114            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
8115            if (!tmp)
8116              return 0;
8117          }
8118      }
8119
8120    return 1;
8121 }
8122
8123 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
8124    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
8125
8126 static int
8127 check_methods_accessible (tree chain, tree context, int mtype)
8128 {
8129   int first = 1;
8130   tree list;
8131   tree base_context = context;
8132
8133   while (chain)
8134     {
8135       /* If the method is associated with a dynamic property, then it
8136          is Ok not to have the method implementation, as it will be
8137          generated dynamically at runtime.  */
8138       tree property = METHOD_PROPERTY_CONTEXT (chain);
8139       if (property != NULL_TREE  &&  PROPERTY_DYNAMIC (property))
8140         {
8141           chain = TREE_CHAIN (chain); /* next method...  */
8142           continue;
8143         }
8144
8145       context = base_context;
8146       while (context)
8147         {
8148           if (mtype == '+')
8149             list = CLASS_CLS_METHODS (context);
8150           else
8151             list = CLASS_NST_METHODS (context);
8152
8153           if (lookup_method (list, chain))
8154               break;
8155
8156           switch (TREE_CODE (context))
8157             {
8158             case CLASS_IMPLEMENTATION_TYPE:
8159             case CLASS_INTERFACE_TYPE:
8160               context = (CLASS_SUPER_NAME (context)
8161                          ? lookup_interface (CLASS_SUPER_NAME (context))
8162                          : NULL_TREE);
8163               break;
8164             case CATEGORY_IMPLEMENTATION_TYPE:
8165             case CATEGORY_INTERFACE_TYPE:
8166               context = (CLASS_NAME (context)
8167                          ? lookup_interface (CLASS_NAME (context))
8168                          : NULL_TREE);
8169               break;
8170             default:
8171               gcc_unreachable ();
8172             }
8173         }
8174
8175       if (context == NULL_TREE)
8176         {
8177           if (first)
8178             {
8179               switch (TREE_CODE (objc_implementation_context))
8180                 {
8181                 case CLASS_IMPLEMENTATION_TYPE:
8182                   warning (0, "incomplete implementation of class %qE",
8183                            CLASS_NAME (objc_implementation_context));
8184                   break;
8185                 case CATEGORY_IMPLEMENTATION_TYPE:
8186                   warning (0, "incomplete implementation of category %qE",
8187                            CLASS_SUPER_NAME (objc_implementation_context));
8188                   break;
8189                 default:
8190                   gcc_unreachable ();
8191                 }
8192               first = 0;
8193             }
8194           warning (0, "method definition for %<%c%E%> not found",
8195                    mtype, METHOD_SEL_NAME (chain));
8196         }
8197
8198       chain = TREE_CHAIN (chain); /* next method...  */
8199     }
8200   return first;
8201 }
8202
8203 /* Check whether the current interface (accessible via
8204    'objc_implementation_context') actually implements protocol P, along
8205    with any protocols that P inherits.  */
8206
8207 static void
8208 check_protocol (tree p, const char *type, tree name)
8209 {
8210   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
8211     {
8212       int f1, f2;
8213
8214       /* Ensure that all protocols have bodies!  */
8215       if (warn_protocol)
8216         {
8217           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
8218                               CLASS_CLS_METHODS (objc_implementation_context),
8219                               '+');
8220           f2 = check_methods (PROTOCOL_NST_METHODS (p),
8221                               CLASS_NST_METHODS (objc_implementation_context),
8222                               '-');
8223         }
8224       else
8225         {
8226           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
8227                                          objc_implementation_context,
8228                                          '+');
8229           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
8230                                          objc_implementation_context,
8231                                          '-');
8232         }
8233
8234       if (!f1 || !f2)
8235         warning (0, "%s %qE does not fully implement the %qE protocol",
8236                  type, name, PROTOCOL_NAME (p));
8237     }
8238
8239   /* Check protocols recursively.  */
8240   if (PROTOCOL_LIST (p))
8241     {
8242       tree subs = PROTOCOL_LIST (p);
8243       tree super_class =
8244         lookup_interface (CLASS_SUPER_NAME (implementation_template));
8245
8246       while (subs)
8247         {
8248           tree sub = TREE_VALUE (subs);
8249
8250           /* If the superclass does not conform to the protocols
8251              inherited by P, then we must!  */
8252           if (!super_class || !conforms_to_protocol (super_class, sub))
8253             check_protocol (sub, type, name);
8254           subs = TREE_CHAIN (subs);
8255         }
8256     }
8257 }
8258
8259 /* Check whether the current interface (accessible via
8260    'objc_implementation_context') actually implements the protocols listed
8261    in PROTO_LIST.  */
8262
8263 static void
8264 check_protocols (tree proto_list, const char *type, tree name)
8265 {
8266   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
8267     {
8268       tree p = TREE_VALUE (proto_list);
8269
8270       check_protocol (p, type, name);
8271     }
8272 }
8273 \f
8274 /* Make sure that the class CLASS_NAME is defined
8275    CODE says which kind of thing CLASS_NAME ought to be.
8276    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
8277    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
8278
8279 static tree
8280 start_class (enum tree_code code, tree class_name, tree super_name,
8281              tree protocol_list)
8282 {
8283   tree klass, decl;
8284
8285 #ifdef OBJCPLUS
8286   if (current_namespace != global_namespace) {
8287     error ("Objective-C declarations may only appear in global scope");
8288   }
8289 #endif /* OBJCPLUS */
8290
8291   if (objc_implementation_context)
8292     {
8293       warning (0, "%<@end%> missing in implementation context");
8294       finish_class (objc_implementation_context);
8295       objc_ivar_chain = NULL_TREE;
8296       objc_implementation_context = NULL_TREE;
8297     }
8298
8299   klass = make_node (code);
8300   TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
8301
8302   /* Check for existence of the super class, if one was specified.  Note
8303      that we must have seen an @interface, not just a @class.  If we
8304      are looking at a @compatibility_alias, traverse it first.  */
8305   if ((code == CLASS_INTERFACE_TYPE || code == CLASS_IMPLEMENTATION_TYPE)
8306       && super_name)
8307     {
8308       tree super = objc_is_class_name (super_name);
8309
8310       if (!super || !lookup_interface (super))
8311         {
8312           error ("cannot find interface declaration for %qE, superclass of %qE",
8313                  super ? super : super_name,
8314                  class_name);
8315           super_name = NULL_TREE;
8316         }
8317       else
8318         super_name = super;
8319     }
8320
8321   CLASS_NAME (klass) = class_name;
8322   CLASS_SUPER_NAME (klass) = super_name;
8323   CLASS_CLS_METHODS (klass) = NULL_TREE;
8324
8325   if (! objc_is_class_name (class_name)
8326       && (decl = lookup_name (class_name)))
8327     {
8328       error ("%qE redeclared as different kind of symbol",
8329              class_name);
8330       error ("previous declaration of %q+D",
8331              decl);
8332     }
8333
8334   switch (code)
8335     {
8336     case CLASS_IMPLEMENTATION_TYPE:
8337       {
8338         tree chain;
8339         
8340         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
8341           if (TREE_VALUE (chain) == class_name)
8342             {
8343               error ("reimplementation of class %qE",
8344                      class_name);
8345               return error_mark_node;
8346             }
8347         implemented_classes = tree_cons (NULL_TREE, class_name,
8348                                          implemented_classes);
8349       }
8350
8351       /* Reset for multiple classes per file.  */
8352       method_slot = 0;
8353
8354       objc_implementation_context = klass;
8355
8356       /* Lookup the interface for this implementation.  */
8357
8358       if (!(implementation_template = lookup_interface (class_name)))
8359         {
8360           warning (0, "cannot find interface declaration for %qE",
8361                    class_name);
8362           add_class (implementation_template = objc_implementation_context,
8363                      class_name);
8364         }
8365
8366       /* If a super class has been specified in the implementation,
8367          insure it conforms to the one specified in the interface.  */
8368
8369       if (super_name
8370           && (super_name != CLASS_SUPER_NAME (implementation_template)))
8371         {
8372           tree previous_name = CLASS_SUPER_NAME (implementation_template);
8373           error ("conflicting super class name %qE",
8374                  super_name);
8375           if (previous_name)
8376             error ("previous declaration of %qE", previous_name);
8377           else
8378             error ("previous declaration");
8379         }
8380
8381       else if (! super_name)
8382         {
8383           CLASS_SUPER_NAME (objc_implementation_context)
8384             = CLASS_SUPER_NAME (implementation_template);
8385         }
8386       break;
8387
8388     case CLASS_INTERFACE_TYPE:
8389       if (lookup_interface (class_name))
8390 #ifdef OBJCPLUS
8391         error ("duplicate interface declaration for class %qE", class_name);
8392 #else
8393         warning (0, "duplicate interface declaration for class %qE", class_name);
8394 #endif
8395       else
8396         add_class (klass, class_name);
8397        
8398       if (protocol_list)
8399         CLASS_PROTOCOL_LIST (klass)
8400           = lookup_and_install_protocols (protocol_list);
8401       break;     
8402
8403     case CATEGORY_INTERFACE_TYPE:
8404       {
8405         tree class_category_is_assoc_with;
8406         
8407         /* For a category, class_name is really the name of the class that
8408            the following set of methods will be associated with. We must
8409            find the interface so that can derive the objects template.  */
8410         if (!(class_category_is_assoc_with = lookup_interface (class_name)))
8411           {
8412             error ("cannot find interface declaration for %qE",
8413                    class_name);
8414             exit (FATAL_EXIT_CODE);
8415           }
8416         else
8417           add_category (class_category_is_assoc_with, klass);
8418         
8419         if (protocol_list)
8420           CLASS_PROTOCOL_LIST (klass)
8421             = lookup_and_install_protocols (protocol_list);
8422       }
8423       break;
8424
8425     case CATEGORY_IMPLEMENTATION_TYPE:
8426       /* Reset for multiple classes per file.  */
8427       method_slot = 0;
8428
8429       objc_implementation_context = klass;
8430
8431       /* For a category, class_name is really the name of the class that
8432          the following set of methods will be associated with.  We must
8433          find the interface so that can derive the objects template.  */
8434
8435       if (!(implementation_template = lookup_interface (class_name)))
8436         {
8437           error ("cannot find interface declaration for %qE",
8438                  class_name);
8439           exit (FATAL_EXIT_CODE);
8440         }
8441       break;
8442     default:
8443       gcc_unreachable ();
8444     }
8445   return klass;
8446 }
8447
8448 static tree
8449 continue_class (tree klass)
8450 {
8451   switch (TREE_CODE (klass))
8452     {
8453     case CLASS_IMPLEMENTATION_TYPE:
8454     case CATEGORY_IMPLEMENTATION_TYPE:
8455       {
8456         struct imp_entry *imp_entry;
8457
8458         /* Check consistency of the instance variables.  */
8459
8460         if (CLASS_RAW_IVARS (klass))
8461           check_ivars (implementation_template, klass);
8462         
8463         /* code generation */
8464 #ifdef OBJCPLUS
8465         push_lang_context (lang_name_c);
8466 #endif
8467         build_private_template (implementation_template);
8468         uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
8469         objc_instance_type = build_pointer_type (uprivate_record);
8470
8471         imp_entry = ggc_alloc_imp_entry ();
8472
8473         imp_entry->next = imp_list;
8474         imp_entry->imp_context = klass;
8475         imp_entry->imp_template = implementation_template;
8476
8477         synth_forward_declarations ();
8478         imp_entry->class_decl = UOBJC_CLASS_decl;
8479         imp_entry->meta_decl = UOBJC_METACLASS_decl;
8480         imp_entry->has_cxx_cdtors = 0;
8481
8482         /* Append to front and increment count.  */
8483         imp_list = imp_entry;
8484         if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
8485           imp_count++;
8486         else
8487           cat_count++;
8488 #ifdef OBJCPLUS
8489         pop_lang_context ();
8490 #endif /* OBJCPLUS */
8491         
8492         return get_class_ivars (implementation_template, true);
8493         break;
8494       }
8495     case CLASS_INTERFACE_TYPE:
8496       {
8497 #ifdef OBJCPLUS
8498         push_lang_context (lang_name_c);
8499 #endif /* OBJCPLUS */
8500         objc_collecting_ivars = 1;
8501         build_private_template (klass);
8502         objc_collecting_ivars = 0;
8503 #ifdef OBJCPLUS
8504         pop_lang_context ();
8505 #endif /* OBJCPLUS */
8506         return NULL_TREE;
8507         break;
8508       }
8509     default:
8510       return error_mark_node;
8511     }
8512 }
8513
8514 /* This routine builds name of the setter synthesized function. */
8515 static char *
8516 objc_build_property_setter_name (tree ident)
8517 {
8518   /* TODO: Use alloca to allocate buffer of appropriate size.  */
8519   static char string[BUFSIZE];
8520   sprintf (string, "set%s:", IDENTIFIER_POINTER (ident));
8521   string[3] = TOUPPER (string[3]);
8522   return string;
8523 }
8524
8525 /* This routine prepares the declarations of the property accessor
8526    helper functions (objc_getProperty(), etc) that are used when
8527    @synthesize is used.  */
8528 static void 
8529 build_objc_property_accessor_helpers (void)
8530 {
8531   tree type;
8532
8533   /* Declare the following function:
8534      id
8535      objc_getProperty (id self, SEL _cmd, 
8536                        ptrdiff_t offset, BOOL is_atomic);  */
8537   type = build_function_type_list (objc_object_type,
8538                                    objc_object_type,
8539                                    objc_selector_type,
8540                                    ptrdiff_type_node,
8541                                    boolean_type_node,
8542                                    NULL_TREE);
8543   objc_getProperty_decl = add_builtin_function ("objc_getProperty",
8544                                                 type, 0, NOT_BUILT_IN,
8545                                                 NULL, NULL_TREE);
8546   TREE_NOTHROW (objc_getProperty_decl) = 0;
8547   
8548   /* Declare the following function:
8549      void
8550      objc_setProperty (id self, SEL _cmd, 
8551                        ptrdiff_t offset, id new_value, 
8552                        BOOL is_atomic, BOOL should_copy);  */
8553   type = build_function_type_list (void_type_node,
8554                                    objc_object_type,
8555                                    objc_selector_type,
8556                                    ptrdiff_type_node,
8557                                    objc_object_type,
8558                                    boolean_type_node,
8559                                    boolean_type_node,
8560                                    NULL_TREE);
8561   objc_setProperty_decl = add_builtin_function ("objc_setProperty",
8562                                                 type, 0, NOT_BUILT_IN,
8563                                                 NULL, NULL_TREE);
8564   TREE_NOTHROW (objc_setProperty_decl) = 0;
8565
8566   /* This is the type of all of the following functions
8567      (objc_copyStruct(), objc_getPropertyStruct() and
8568      objc_setPropertyStruct()).  */
8569   type = build_function_type_list (void_type_node,
8570                                    ptr_type_node,
8571                                    const_ptr_type_node,
8572                                    ptrdiff_type_node,       
8573                                    boolean_type_node,
8574                                    boolean_type_node,
8575                                    NULL_TREE);
8576
8577   if (flag_next_runtime)
8578     {
8579       /* Declare the following function:
8580          void
8581          objc_copyStruct (void *destination, const void *source, 
8582                           ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
8583       objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
8584                                                    type, 0, NOT_BUILT_IN,
8585                                                    NULL, NULL_TREE);
8586       TREE_NOTHROW (objc_copyStruct_decl) = 0;
8587       objc_getPropertyStruct_decl = NULL_TREE;
8588       objc_setPropertyStruct_decl = NULL_TREE;
8589     }
8590   else
8591     {
8592       objc_copyStruct_decl = NULL_TREE;
8593
8594       /* Declare the following function:
8595          void
8596          objc_getPropertyStruct (void *destination, const void *source, 
8597                                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
8598       objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
8599                                                           type, 0, NOT_BUILT_IN,
8600                                                           NULL, NULL_TREE);
8601       TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
8602       /* Declare the following function:
8603          void
8604          objc_setPropertyStruct (void *destination, const void *source, 
8605                                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
8606       objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
8607                                                           type, 0, NOT_BUILT_IN,
8608                                                           NULL, NULL_TREE);
8609       TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
8610     }
8611 }
8612
8613 /* This looks up an ivar in a class (including superclasses).  */
8614 static tree
8615 lookup_ivar (tree interface, tree instance_variable_name)
8616 {
8617   while (interface)
8618     {
8619       tree decl_chain;
8620       
8621       for (decl_chain = CLASS_IVARS (interface); decl_chain; decl_chain = DECL_CHAIN (decl_chain))
8622         if (DECL_NAME (decl_chain) == instance_variable_name)
8623           return decl_chain;
8624       
8625       /* Not found.  Search superclass if any.  */
8626       if (CLASS_SUPER_NAME (interface))
8627         interface = lookup_interface (CLASS_SUPER_NAME (interface));
8628     }
8629   
8630   return NULL_TREE;
8631 }
8632
8633 /* This routine synthesizes a 'getter' method.  This is only called
8634    for @synthesize properties.  */
8635 static void
8636 objc_synthesize_getter (tree klass, tree class_method, tree property)
8637 {
8638   location_t location = DECL_SOURCE_LOCATION (property);
8639   tree fn, decl;
8640   tree body;
8641   tree ret_val;
8642
8643   /* If user has implemented a getter with same name then do nothing.  */
8644   if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
8645                      PROPERTY_GETTER_NAME (property)))
8646     return;
8647
8648   /* Find declaration of the property getter in the interface. There
8649      must be one.  TODO: Search superclasses as well.  */
8650   decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_GETTER_NAME (property));
8651
8652   /* If one not declared in the interface, this condition has already
8653      been reported as user error (because property was not declared in
8654      the interface).  */
8655   if (!decl)
8656     return;
8657
8658   /* Adapt the 'decl'.  Use the source location of the @synthesize
8659      statement for error messages.  */
8660   decl = copy_node (decl);
8661   DECL_SOURCE_LOCATION (decl) = location;
8662
8663   objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
8664   body = c_begin_compound_stmt (true);
8665
8666   /* Now we need to decide how we build the getter.  There are three
8667      cases:
8668
8669      for 'copy' or 'retain' properties we need to use the
8670      objc_getProperty() accessor helper which knows about retain and
8671      copy.  It supports both 'nonatomic' and 'atomic' access.
8672
8673      for 'nonatomic, assign' properties we can access the instance
8674      variable directly.  'nonatomic' means we don't have to use locks,
8675      and 'assign' means we don't have to worry about retain or copy.
8676      If you combine the two, it means we can just access the instance
8677      variable directly.
8678
8679      for 'atomic, assign' properties we use objc_copyStruct() (for the
8680      next runtime) or objc_getPropertyStruct() (for the GNU runtime).  */
8681   switch (PROPERTY_ASSIGN_SEMANTICS (property))
8682     {
8683     case OBJC_PROPERTY_RETAIN:
8684     case OBJC_PROPERTY_COPY:
8685       {
8686         /* We build "return objc_getProperty (self, _cmd, offset, is_atomic);"  */
8687         tree cmd, ivar, offset, is_atomic;
8688         cmd = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
8689
8690         /* Find the ivar to compute the offset.  */
8691         ivar = lookup_ivar (klass, PROPERTY_IVAR_NAME (property));
8692         if (!ivar || is_private (ivar))
8693           {
8694             /* This should never happen.  */
8695             error_at (location,
8696                       "can not find instance variable associated with property");
8697             ret_val = error_mark_node;
8698             break;
8699           }
8700         offset = byte_position (ivar);
8701
8702         if (PROPERTY_NONATOMIC (property))
8703           is_atomic = boolean_false_node;
8704         else
8705           is_atomic = boolean_true_node;
8706
8707         ret_val = build_function_call
8708           (location,
8709            /* Function prototype.  */
8710            objc_getProperty_decl,
8711            /* Parameters.  */
8712            tree_cons    /* self */
8713            (NULL_TREE, self_decl,
8714             tree_cons   /* _cmd */
8715             (NULL_TREE, cmd,
8716              tree_cons  /* offset */
8717              (NULL_TREE, offset,
8718               tree_cons /* is_atomic */
8719               (NULL_TREE, is_atomic, NULL_TREE)))));
8720       }
8721       break;
8722     case OBJC_PROPERTY_ASSIGN:    
8723       if (PROPERTY_NONATOMIC (property))
8724         {
8725           /* We build "return self->PROPERTY_IVAR_NAME;"  */
8726           ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
8727           break;
8728         }
8729       else
8730         {
8731           /* We build
8732                <property type> __objc_property_temp;
8733                objc_getPropertyStruct (&__objc_property_temp,
8734                                        &(self->PROPERTY_IVAR_NAME),
8735                                        sizeof (type of self->PROPERTY_IVAR_NAME),
8736                                        is_atomic,
8737                                        false)
8738                return __objc_property_temp;
8739
8740              For the NeXT runtime, we need to use objc_copyStruct
8741              instead of objc_getPropertyStruct.  */
8742           tree objc_property_temp_decl, function_decl, function_call;
8743           tree size_of, is_atomic;
8744
8745           objc_property_temp_decl = objc_create_temporary_var (TREE_TYPE (property), "__objc_property_temp");
8746           DECL_SOURCE_LOCATION (objc_property_temp_decl) = location;
8747           objc_property_temp_decl = lang_hooks.decls.pushdecl (objc_property_temp_decl);
8748
8749           /* sizeof (ivar type).  Since the ivar and the property have
8750              the same type, there is no need to lookup the ivar.  */
8751           size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property),
8752                                               true /* is_sizeof */,
8753                                               false /* complain */);
8754           
8755           if (PROPERTY_NONATOMIC (property))
8756             is_atomic = boolean_false_node;
8757           else
8758             is_atomic = boolean_true_node;
8759           
8760           if (flag_next_runtime)
8761             function_decl = objc_copyStruct_decl;
8762           else
8763             function_decl = objc_getPropertyStruct_decl;
8764
8765           function_call = build_function_call
8766             (location,
8767              /* Function prototype.  */
8768              function_decl,
8769              /* Parameters.  */
8770              tree_cons /* &__objc_property_temp_decl */
8771              /* Warning: note that using build_fold_addr_expr_loc()
8772                 here causes invalid code to be generated.  */
8773              (NULL_TREE, build_unary_op (location, ADDR_EXPR, objc_property_temp_decl, 0),
8774               tree_cons /* &(self->PROPERTY_IVAR_NAME); */
8775               (NULL_TREE, build_fold_addr_expr_loc (location, 
8776                                                     objc_lookup_ivar 
8777                                                     (NULL_TREE, PROPERTY_IVAR_NAME (property))),
8778                tree_cons /* sizeof (PROPERTY_IVAR) */
8779                (NULL_TREE, size_of,
8780                 tree_cons /* is_atomic */
8781                 (NULL_TREE, is_atomic,
8782                  /* TODO: This is currently ignored by the GNU
8783                     runtime, but what about the next one ? */
8784                  tree_cons /* has_strong */
8785                  (NULL_TREE, boolean_true_node, NULL_TREE))))));
8786
8787           add_stmt (function_call);
8788
8789           ret_val = objc_property_temp_decl;
8790         }
8791       break;
8792     default:
8793       gcc_unreachable ();
8794     }
8795
8796   gcc_assert (ret_val);
8797
8798 #ifdef OBJCPLUS
8799   finish_return_stmt (ret_val);
8800 #else
8801   c_finish_return (location, ret_val, NULL_TREE);
8802 #endif
8803
8804   add_stmt (c_end_compound_stmt (location, body, true));
8805   fn = current_function_decl;
8806 #ifdef OBJCPLUS
8807   finish_function ();
8808 #endif
8809   objc_finish_method_definition (fn);
8810 }
8811
8812 /* This routine synthesizes a 'setter' method.  */
8813
8814 static void
8815 objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
8816 {
8817   location_t location = DECL_SOURCE_LOCATION (property);
8818   tree fn, decl;
8819   tree body;
8820   tree new_value, statement;
8821
8822   /* If user has implemented a setter with same name then do nothing.  */
8823   if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
8824                      PROPERTY_SETTER_NAME (property)))
8825     return;
8826
8827   /* Find declaration of the property setter in the interface. There
8828      must be one.  TODO: Search superclasses as well.  */
8829   decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_SETTER_NAME (property));
8830
8831   /* If one not declared in the interface, this condition has already
8832      been reported as user error (because property was not declared in
8833      the interface).  */
8834   if (!decl)
8835     return;
8836
8837   /* Adapt the 'decl'.  Use the source location of the @synthesize
8838      statement for error messages.  */
8839   decl = copy_node (decl);
8840   DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
8841
8842   objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
8843
8844   body = c_begin_compound_stmt (true);
8845
8846   /* The 'new_value' is the only argument to the method, which is the
8847      3rd argument of the function, after self and _cmd.  We use twice
8848      TREE_CHAIN to move forward two arguments.  */
8849   new_value = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)));
8850
8851   /* This would presumably happen if the user has specified a
8852      prototype for the setter that does not have an argument!  */
8853   if (new_value == NULL_TREE)
8854     {
8855       /* TODO: This should be caught much earlier than this.  */
8856       error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, it must have one argument");
8857       /* Try to recover somehow.  */
8858       new_value = error_mark_node;
8859     }
8860
8861   /* Now we need to decide how we build the setter.  There are three
8862      cases:
8863
8864      for 'copy' or 'retain' properties we need to use the
8865      objc_setProperty() accessor helper which knows about retain and
8866      copy.  It supports both 'nonatomic' and 'atomic' access.
8867
8868      for 'nonatomic, assign' properties we can access the instance
8869      variable directly.  'nonatomic' means we don't have to use locks,
8870      and 'assign' means we don't have to worry about retain or copy.
8871      If you combine the two, it means we can just access the instance
8872      variable directly.
8873
8874      for 'atomic, assign' properties we use objc_copyStruct() (for the
8875      next runtime) or objc_setPropertyStruct() (for the GNU runtime).  */
8876   switch (PROPERTY_ASSIGN_SEMANTICS (property))
8877     {
8878     case OBJC_PROPERTY_RETAIN:
8879     case OBJC_PROPERTY_COPY:
8880       {
8881         /* We build "objc_setProperty (self, _cmd, new_value, offset, is_atomic, should_copy);"  */
8882         tree cmd, ivar, offset, is_atomic, should_copy;
8883         cmd = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
8884
8885         /* Find the ivar to compute the offset.  */
8886         ivar = lookup_ivar (klass, PROPERTY_IVAR_NAME (property));
8887         if (!ivar || is_private (ivar))
8888           {
8889             error_at (location,
8890                       "can not find instance variable associated with property");
8891             statement = error_mark_node;
8892             break;
8893           }
8894         offset = byte_position (ivar);
8895
8896         if (PROPERTY_NONATOMIC (property))
8897           is_atomic = boolean_false_node;
8898         else
8899           is_atomic = boolean_true_node;
8900         
8901         if (PROPERTY_ASSIGN_SEMANTICS (property) == OBJC_PROPERTY_COPY)
8902           should_copy = boolean_true_node;
8903         else
8904           should_copy = boolean_false_node;
8905
8906         statement = build_function_call
8907           (location,
8908            /* Function prototype.  */
8909            objc_setProperty_decl,
8910            /* Parameters.  */
8911            tree_cons    /* self */
8912            (NULL_TREE, self_decl,
8913             tree_cons   /* _cmd */
8914             (NULL_TREE, cmd,
8915              tree_cons  /* offset */
8916              (NULL_TREE, offset,
8917               tree_cons /* new_value */
8918               (NULL_TREE, new_value,
8919                tree_cons /* is_atomic */
8920                (NULL_TREE, is_atomic, 
8921                 tree_cons /* should_copy */
8922                 (NULL_TREE, should_copy, NULL_TREE)))))));
8923       }
8924       break;
8925     case OBJC_PROPERTY_ASSIGN:    
8926       if (PROPERTY_NONATOMIC (property))
8927         {
8928           /* We build "self->PROPERTY_IVAR_NAME = new_value;"  */
8929           statement = build_modify_expr
8930             (location,
8931              objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)),
8932              NULL_TREE, NOP_EXPR, 
8933              location, new_value, NULL_TREE);
8934           break;
8935         }
8936       else
8937         {
8938           /* We build
8939                objc_setPropertyStruct (&(self->PROPERTY_IVAR_NAME),
8940                                        &new_value,
8941                                        sizeof (type of self->PROPERTY_IVAR_NAME),
8942                                        is_atomic,
8943                                        false)
8944
8945              For the NeXT runtime, we need to use objc_copyStruct
8946              instead of objc_getPropertyStruct.  */
8947           tree function_decl, size_of, is_atomic;
8948
8949           /* sizeof (ivar type).  Since the ivar and the property have
8950              the same type, there is no need to lookup the ivar.  */
8951           size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property),
8952                                               true /* is_sizeof */,
8953                                               false /* complain */);
8954           
8955           if (PROPERTY_NONATOMIC (property))
8956             is_atomic = boolean_false_node;
8957           else
8958             is_atomic = boolean_true_node;
8959           
8960           if (flag_next_runtime)
8961             function_decl = objc_copyStruct_decl;
8962           else
8963             function_decl = objc_setPropertyStruct_decl;
8964
8965           statement = build_function_call 
8966             (location,
8967              /* Function prototype.  */
8968              function_decl,
8969              /* Parameters.  */
8970              tree_cons /* &(self->PROPERTY_IVAR_NAME); */
8971              (NULL_TREE, build_fold_addr_expr_loc (location, 
8972                                                    objc_lookup_ivar 
8973                                                    (NULL_TREE, PROPERTY_IVAR_NAME (property))),
8974               tree_cons /* &new_value */
8975               (NULL_TREE, build_fold_addr_expr_loc (location, new_value),
8976                tree_cons /* sizeof (PROPERTY_IVAR) */
8977                (NULL_TREE, size_of,
8978                 tree_cons /* is_atomic */
8979                 (NULL_TREE, is_atomic,
8980                  /* TODO: This is currently ignored by the GNU
8981                     runtime, but what about the next one ? */
8982                  tree_cons /* has_strong */
8983                  (NULL_TREE, boolean_true_node, NULL_TREE))))));
8984         }
8985       break;
8986     default:
8987       gcc_unreachable ();
8988     }
8989   gcc_assert (statement);
8990
8991   add_stmt (statement);  
8992   add_stmt (c_end_compound_stmt (location, body, true));
8993   fn = current_function_decl;
8994 #ifdef OBJCPLUS
8995   finish_function ();
8996 #endif
8997   objc_finish_method_definition (fn);
8998 }
8999
9000 /* This function is a sub-routine of objc_add_synthesize_declaration.
9001    It is called for each property to synthesize once we have
9002    determined that the context is Ok.  */
9003 static void
9004 objc_add_synthesize_declaration_for_property (location_t location, tree interface,
9005                                               tree property_name, tree ivar_name)
9006 {
9007   /* Find the @property declaration.  */
9008   tree property;
9009
9010   /* Check that synthesize or dynamic has not already been used for
9011      the same property.  */
9012   for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
9013     if (PROPERTY_NAME (property) == property_name)
9014       {
9015         location_t original_location = DECL_SOURCE_LOCATION (property);
9016         
9017         if (PROPERTY_DYNAMIC (property))
9018           error_at (location, "property %qs already specified in %<@dynamic%>", 
9019                     IDENTIFIER_POINTER (property_name));
9020         else
9021           error_at (location, "property %qs already specified in %<@synthesize%>", 
9022                     IDENTIFIER_POINTER (property_name));
9023         
9024         if (original_location != UNKNOWN_LOCATION)
9025           inform (original_location, "originally specified here");
9026         return;
9027       }
9028
9029   /* Check that the property is declared in the interface.  */
9030   /* TODO: This only check the immediate class; we need to check the
9031      superclass (and categories ?) as well.  */
9032   for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
9033     if (PROPERTY_NAME (property) == property_name)
9034       break;
9035
9036   if (!property)
9037     {
9038       error_at (location, "no declaration of property %qs found in the interface", 
9039                 IDENTIFIER_POINTER (property_name));
9040       return;
9041     }
9042   else
9043     {
9044       /* We have to copy the property, because we want to chain it to
9045          the implementation context, and we want to store the source
9046          location of the @synthesize, not of the original
9047          @property.  */
9048       property = copy_node (property);
9049       DECL_SOURCE_LOCATION (property) = location;
9050     }
9051
9052   /* Determine PROPERTY_IVAR_NAME.  */
9053   if (ivar_name == NULL_TREE)
9054     ivar_name = property_name;
9055
9056   /* Check that the instance variable exists.  You can only use an
9057      instance variable from the same class, not one from the
9058      superclass.  */
9059   if (!is_ivar (CLASS_IVARS (interface), ivar_name))
9060     error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", 
9061               IDENTIFIER_POINTER (property_name));
9062
9063   /* TODO: Check that the types of the instance variable and of the
9064      property match.  */
9065
9066   /* TODO: Check that no other property is using the same instance
9067      variable.  */
9068
9069   /* Note that a @synthesize (and only a @synthesize) always sets
9070      PROPERTY_IVAR_NAME to a non-NULL_TREE.  You can recognize a
9071      @synthesize by that.  */
9072   PROPERTY_IVAR_NAME (property) = ivar_name;
9073   
9074   /* PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME are copied from the
9075      original declaration; they are always set (with the exception of
9076      PROPERTY_SETTER_NAME not being set if PROPERTY_READONLY == 1).  */
9077
9078   /* Add the property to the list of properties for current implementation. */
9079   TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
9080   IMPL_PROPERTY_DECL (objc_implementation_context) = property;
9081
9082   /* Note how we don't actually synthesize the getter/setter here; it
9083      would be very natural, but we may miss the fact that the user has
9084      implemented his own getter/setter later on in the @implementation
9085      (in which case we shouldn't generate getter/setter).  We wait
9086      until we have parsed it all before generating the code.  */
9087 }
9088
9089 /* This function is called by the parser after a @synthesize
9090    expression is parsed.  'location' is the location of the
9091    @synthesize expression, and 'property_and_ivar_list' is a chained
9092    list of the property and ivar names.  */
9093 void
9094 objc_add_synthesize_declaration (location_t location, tree property_and_ivar_list)
9095 {
9096   tree interface, chain;
9097
9098   if (property_and_ivar_list == error_mark_node)
9099     return;
9100
9101   if (!objc_implementation_context)
9102     {
9103       /* We can get here only in Objective-C; the Objective-C++ parser
9104          detects the problem while parsing, outputs the error
9105          "misplaced '@synthesize' Objective-C++ construct" and skips
9106          the declaration.  */
9107       error_at (location, "%<@synthesize%> not in @implementation context");
9108       return;
9109     }
9110
9111   if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
9112     {
9113       /* TODO: Maybe we should allow @synthesize in categories ?  */
9114       error_at (location, "%<@synthesize%> can not be used in categories");
9115       return;
9116     }
9117
9118   interface = lookup_interface (CLASS_NAME (objc_implementation_context));
9119   if (!interface)
9120     {
9121       /* I can't see how this could happen, but it is good as a safety check.  */
9122       error_at (location, 
9123                 "%<@synthesize%> requires the @interface of the class to be available");
9124       return;
9125     }
9126
9127   /* Now, iterate over the properties and do each of them.  */
9128   for (chain = property_and_ivar_list; chain; chain = TREE_CHAIN (chain))
9129     {
9130       objc_add_synthesize_declaration_for_property (location, interface, TREE_VALUE (chain), 
9131                                                     TREE_PURPOSE (chain));
9132     }
9133 }
9134
9135 /* This function is a sub-routine of objc_add_dynamic_declaration.  It
9136    is called for each property to mark as dynamic once we have
9137    determined that the context is Ok.  */
9138 static void
9139 objc_add_dynamic_declaration_for_property (location_t location, tree interface,
9140                                            tree property_name)
9141 {
9142   /* Find the @property declaration.  */
9143   tree property;
9144
9145   /* Check that synthesize or dynamic has not already been used for
9146      the same property.  */
9147   for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
9148     if (PROPERTY_NAME (property) == property_name)
9149       {
9150         location_t original_location = DECL_SOURCE_LOCATION (property);
9151         
9152         if (PROPERTY_DYNAMIC (property))
9153           error_at (location, "property %qs already specified in %<@dynamic%>", 
9154                     IDENTIFIER_POINTER (property_name));
9155         else
9156           error_at (location, "property %qs already specified in %<@synthesize%>",
9157                     IDENTIFIER_POINTER (property_name));
9158
9159         if (original_location != UNKNOWN_LOCATION)
9160           inform (original_location, "originally specified here");
9161         return;
9162       }
9163
9164   /* Check that the property is declared in the interface.  */
9165   /* TODO: This only check the immediate class; we need to check the
9166      superclass (and categories ?) as well.  */
9167   for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
9168     if (PROPERTY_NAME (property) == property_name)
9169       break;
9170
9171   if (!property)
9172     {
9173       error_at (location, "no declaration of property %qs found in the interface",
9174                 IDENTIFIER_POINTER (property_name));
9175       return;
9176     }
9177   else
9178     {
9179       /* Mark the original PROPERTY_DECL as dynamic.  The reason is
9180          that the setter and getter methods in the interface have a
9181          METHOD_PROPERTY_CONTEXT that points to the original
9182          PROPERTY_DECL; when we check that these methods have been
9183          implemented, we need to easily find that they are associated
9184          with a dynamic property.  TODO: Clean this up; maybe the
9185          @property PROPERTY_DECL should contain a reference to the
9186          @dynamic PROPERTY_DECL ? */
9187       PROPERTY_DYNAMIC (property) = 1;
9188
9189       /* We have to copy the property, because we want to chain it to
9190          the implementation context, and we want to store the source
9191          location of the @synthesize, not of the original
9192          @property.  */
9193       property = copy_node (property);
9194       DECL_SOURCE_LOCATION (property) = location;
9195     }
9196
9197   /* Note that a @dynamic (and only a @dynamic) always sets
9198      PROPERTY_DYNAMIC to 1.  You can recognize a @dynamic by that.
9199      (actually, as explained above, PROPERTY_DECL generated by
9200      @property and associated with a @dynamic property are also marked
9201      as PROPERTY_DYNAMIC).  */
9202   PROPERTY_DYNAMIC (property) = 1;
9203
9204   /* Add the property to the list of properties for current implementation. */
9205   TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
9206   IMPL_PROPERTY_DECL (objc_implementation_context) = property;
9207 }
9208
9209 /* This function is called by the parser after a @dynamic expression
9210    is parsed.  'location' is the location of the @dynamic expression,
9211    and 'property_list' is a chained list of all the property
9212    names.  */
9213 void
9214 objc_add_dynamic_declaration (location_t location, tree property_list)
9215 {
9216   tree interface, chain;
9217
9218   if (property_list == error_mark_node)
9219     return;
9220
9221   if (!objc_implementation_context)
9222     {
9223       /* We can get here only in Objective-C; the Objective-C++ parser
9224          detects the problem while parsing, outputs the error
9225          "misplaced '@dynamic' Objective-C++ construct" and skips the
9226          declaration.  */
9227       error_at (location, "%<@dynamic%> not in @implementation context");
9228       return;
9229     }
9230
9231   if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
9232     {
9233       /* TODO: Maybe we should allow @dynamic in categories ?  */
9234       error_at (location, "%<@dynamic%> can not be used in categories");
9235       return;
9236     }
9237   
9238   interface = lookup_interface (CLASS_NAME (objc_implementation_context));
9239   if (!interface)
9240     {
9241       /* I can't see how this could happen, but it is good as a safety check.  */
9242       error_at (location, 
9243                 "%<@dynamic%> requires the @interface of the class to be available");
9244       return;
9245     }
9246
9247   /* Now, iterate over the properties and do each of them.  */
9248   for (chain = property_list; chain; chain = TREE_CHAIN (chain))
9249     {
9250       objc_add_dynamic_declaration_for_property (location, interface, TREE_VALUE (chain));
9251     }
9252 }
9253
9254 /* Main routine to generate code/data for all the property information for 
9255    current implementation (class or category). CLASS is the interface where
9256    ivars are declared.  CLASS_METHODS is where methods are found which
9257    could be a class or a category depending on whether we are implementing
9258    property of a class or a category.  */
9259
9260 static void
9261 objc_gen_property_data (tree klass, tree class_methods)
9262 {
9263   tree x;
9264
9265   for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
9266     {
9267       /* @dynamic property - nothing to check or synthesize.  */
9268       if (PROPERTY_DYNAMIC (x))
9269         continue;
9270       
9271       /* @synthesize property - need to synthesize the accessors.  */
9272       if (PROPERTY_IVAR_NAME (x))
9273         {
9274           objc_synthesize_getter (klass, class_methods, x);
9275           
9276           if (PROPERTY_READONLY (x) == 0)
9277             objc_synthesize_setter (klass, class_methods, x);
9278
9279           continue;
9280         }
9281
9282       gcc_unreachable ();
9283     }
9284 }
9285
9286 /* This is called once we see the "@end" in an interface/implementation.  */
9287
9288 static void
9289 finish_class (tree klass)
9290 {
9291   switch (TREE_CODE (klass))
9292     {
9293     case CLASS_IMPLEMENTATION_TYPE:
9294       {
9295         /* All code generation is done in finish_objc.  */
9296         
9297         /* Generate what needed for property; setters, getters, etc. */
9298         objc_gen_property_data (implementation_template, implementation_template);
9299
9300         if (implementation_template != objc_implementation_context)
9301           {
9302             /* Ensure that all method listed in the interface contain bodies.  */
9303             check_methods (CLASS_CLS_METHODS (implementation_template),
9304                            CLASS_CLS_METHODS (objc_implementation_context), '+');
9305             check_methods (CLASS_NST_METHODS (implementation_template),
9306                            CLASS_NST_METHODS (objc_implementation_context), '-');
9307
9308             if (CLASS_PROTOCOL_LIST (implementation_template))
9309               check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
9310                                "class",
9311                                CLASS_NAME (objc_implementation_context));
9312           }
9313         break;
9314       }
9315     case CATEGORY_IMPLEMENTATION_TYPE:
9316       {
9317         tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (klass));
9318         
9319         if (category)
9320           {
9321             /* Generate what needed for property; setters, getters, etc. */
9322             objc_gen_property_data (implementation_template, category);
9323             
9324             /* Ensure all method listed in the interface contain bodies.  */
9325             check_methods (CLASS_CLS_METHODS (category),
9326                            CLASS_CLS_METHODS (objc_implementation_context), '+');
9327             check_methods (CLASS_NST_METHODS (category),
9328                            CLASS_NST_METHODS (objc_implementation_context), '-');
9329             
9330             if (CLASS_PROTOCOL_LIST (category))
9331               check_protocols (CLASS_PROTOCOL_LIST (category),
9332                                "category",
9333                                CLASS_SUPER_NAME (objc_implementation_context));
9334           }
9335         break;
9336       }
9337     case CLASS_INTERFACE_TYPE:
9338     case CATEGORY_INTERFACE_TYPE:
9339     case PROTOCOL_INTERFACE_TYPE:
9340       {
9341         /* Process properties of the class. */
9342         tree x;
9343         for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
9344           {
9345             /* Store the getter name that we used into the property.
9346                It is used to generate the right getter calls;
9347                moreover, when a @synthesize is processed, it copies
9348                everything from the property, including the
9349                PROPERTY_GETTER_NAME.  We want to be sure that
9350                @synthesize will get exactly the right
9351                PROPERTY_GETTER_NAME.  */
9352             if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
9353               PROPERTY_GETTER_NAME (x) = PROPERTY_NAME (x);
9354
9355             /* Now we check that the appropriate getter is declared,
9356                and if not, we declare one ourselves.  */
9357             {
9358               tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
9359                                                 PROPERTY_GETTER_NAME (x));
9360               
9361               if (getter_decl)
9362                 {
9363                   /* TODO: Check that the declaration is consistent with the property.  */
9364                   ;
9365                 }
9366               else
9367                 {
9368                   /* Generate an instance method declaration for the
9369                      getter; for example "- (id) name;".  In general
9370                      it will be of the form
9371                      -(type)property_getter_name;  */
9372                   tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
9373                   getter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
9374                                                    rettype, PROPERTY_GETTER_NAME (x), 
9375                                                    NULL_TREE, false);
9376                   objc_add_method (objc_interface_context, getter_decl, false, false);
9377                   METHOD_PROPERTY_CONTEXT (getter_decl) = x;
9378                 }
9379             }
9380
9381             if (PROPERTY_READONLY (x) == 0)
9382               {
9383                 /* Store the setter name that we used into the
9384                    property.  It is used when generating setter calls;
9385                    moreover, when a @synthesize is processed, it
9386                    copies everything from the property, including the
9387                    PROPERTY_SETTER_NAME.  We want to be sure that
9388                    @synthesize will get exactly the right
9389                    PROPERTY_SETTER_NAME.  */
9390                 if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
9391                   PROPERTY_SETTER_NAME (x) = get_identifier (objc_build_property_setter_name 
9392                                                              (PROPERTY_NAME (x)));
9393
9394                 /* Now we check that the appropriate setter is declared,
9395                    and if not, we declare on ourselves.  */
9396                 {
9397                   tree setter_decl = lookup_method (CLASS_NST_METHODS (klass), 
9398                                                     PROPERTY_SETTER_NAME (x));
9399                   
9400                   if (setter_decl)
9401                     {
9402                       /* TODO: Check that the declaration is consistent with the property.  */
9403                       ;
9404                     }
9405                   else
9406                     {
9407                       /* The setter name is something like 'setName:'.
9408                          We need the substring 'setName' to build the
9409                          method declaration due to how the declaration
9410                          works.  TODO: build_method_decl() will then
9411                          generate back 'setName:' from 'setName'; it
9412                          would be more efficient to hook into
9413                          there.  */
9414                       const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
9415                       size_t length = strlen (full_setter_name);
9416                       char *setter_name = (char *) alloca (length);
9417                       tree ret_type, selector, arg_type, arg_name;
9418
9419                       strcpy (setter_name, full_setter_name);
9420                       setter_name[length - 1] = '\0';
9421                       ret_type = build_tree_list (NULL_TREE, void_type_node);
9422                       arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
9423                       arg_name = get_identifier ("_value");
9424                       selector = objc_build_keyword_decl (get_identifier (setter_name),
9425                                                           arg_type, arg_name, NULL);
9426                       setter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
9427                                                        ret_type, selector,
9428                                                        build_tree_list (NULL_TREE, NULL_TREE),
9429                                                        false);
9430                       objc_add_method (objc_interface_context, setter_decl, false, false);
9431                       METHOD_PROPERTY_CONTEXT (setter_decl) = x;
9432                     }
9433                 }
9434
9435             /* Note how at this point (once an @interface or @protocol
9436                have been processed), PROPERTY_GETTER_NAME is always
9437                set for all PROPERTY_DECLs, and PROPERTY_SETTER_NAME is
9438                always set for all PROPERTY_DECLs where
9439                PROPERTY_READONLY == 0.  Any time we deal with a getter
9440                or setter, we should get the PROPERTY_DECL and use
9441                PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME to know
9442                the correct names.  */
9443               }
9444           }
9445         break;
9446       }
9447     default:
9448       gcc_unreachable ();
9449       break;
9450     }
9451 }
9452
9453 static tree
9454 add_protocol (tree protocol)
9455 {
9456   /* Put protocol on list in reverse order.  */
9457   TREE_CHAIN (protocol) = protocol_chain;
9458   protocol_chain = protocol;
9459   return protocol_chain;
9460 }
9461
9462 static tree
9463 lookup_protocol (tree ident)
9464 {
9465   tree chain;
9466
9467   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
9468     if (ident == PROTOCOL_NAME (chain))
9469       return chain;
9470
9471   return NULL_TREE;
9472 }
9473
9474 /* This function forward declares the protocols named by NAMES.  If
9475    they are already declared or defined, the function has no effect.  */
9476
9477 void
9478 objc_declare_protocols (tree names)
9479 {
9480   tree list;
9481
9482 #ifdef OBJCPLUS
9483   if (current_namespace != global_namespace) {
9484     error ("Objective-C declarations may only appear in global scope");
9485   }
9486 #endif /* OBJCPLUS */
9487
9488   for (list = names; list; list = TREE_CHAIN (list))
9489     {
9490       tree name = TREE_VALUE (list);
9491
9492       if (lookup_protocol (name) == NULL_TREE)
9493         {
9494           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
9495
9496           TYPE_LANG_SLOT_1 (protocol)
9497             = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
9498           PROTOCOL_NAME (protocol) = name;
9499           PROTOCOL_LIST (protocol) = NULL_TREE;
9500           add_protocol (protocol);
9501           PROTOCOL_DEFINED (protocol) = 0;
9502           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
9503         }
9504     }
9505 }
9506
9507 static tree
9508 start_protocol (enum tree_code code, tree name, tree list)
9509 {
9510   tree protocol;
9511
9512 #ifdef OBJCPLUS
9513   if (current_namespace != global_namespace) {
9514     error ("Objective-C declarations may only appear in global scope");
9515   }
9516 #endif /* OBJCPLUS */
9517
9518   protocol = lookup_protocol (name);
9519
9520   if (!protocol)
9521     {
9522       protocol = make_node (code);
9523       TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
9524
9525       PROTOCOL_NAME (protocol) = name;
9526       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
9527       add_protocol (protocol);
9528       PROTOCOL_DEFINED (protocol) = 1;
9529       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
9530
9531       check_protocol_recursively (protocol, list);
9532     }
9533   else if (! PROTOCOL_DEFINED (protocol))
9534     {
9535       PROTOCOL_DEFINED (protocol) = 1;
9536       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
9537
9538       check_protocol_recursively (protocol, list);
9539     }
9540   else
9541     {
9542       warning (0, "duplicate declaration for protocol %qE",
9543                name);
9544     }
9545   return protocol;
9546 }
9547
9548 \f
9549 /* "Encode" a data type into a string, which grows in util_obstack.
9550
9551    The format is described in gcc/doc/objc.texi, section 'Type
9552    encoding'.
9553
9554    Most of the encode_xxx functions have a 'type' argument, which is
9555    the type to encode, and an integer 'curtype' argument, which is the
9556    index in the encoding string of the beginning of the encoding of
9557    the current type, and allows you to find what characters have
9558    already been written for the current type (they are the ones in the
9559    current encoding string starting from 'curtype').
9560
9561    For example, if we are encoding a method which returns 'int' and
9562    takes a 'char **' argument, then when we get to the point of
9563    encoding the 'char **' argument, the encoded string already
9564    contains 'i12@0:4' (assuming a pointer size of 4 bytes).  So,
9565    'curtype' will be set to 7 when starting to encode 'char **'.
9566    During the whole of the encoding of 'char **', 'curtype' will be
9567    fixed at 7, so the routine encoding the second pointer can find out
9568    that it's actually encoding a pointer to a pointer by looking
9569    backwards at what has already been encoded for the current type,
9570    and seeing there is a "^" (meaning a pointer) in there.
9571 */
9572
9573
9574 /* Encode type qualifiers encodes one of the "PQ" Objective-C
9575    keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
9576    'const', instead, is encoded directly as part of the type.
9577  */
9578
9579 static void
9580 encode_type_qualifiers (tree declspecs)
9581 {
9582   tree spec;
9583
9584   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
9585     {
9586       /* FIXME: Shouldn't we use token->keyword here ? */
9587       if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
9588         obstack_1grow (&util_obstack, 'n');
9589       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
9590         obstack_1grow (&util_obstack, 'N');
9591       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
9592         obstack_1grow (&util_obstack, 'o');
9593       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
9594         obstack_1grow (&util_obstack, 'O');
9595       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
9596         obstack_1grow (&util_obstack, 'R');
9597       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
9598         obstack_1grow (&util_obstack, 'V');
9599       else
9600         gcc_unreachable ();
9601     }
9602 }
9603
9604 /* Determine if a pointee is marked read-only.  Only used by the NeXT
9605    runtime to be compatible with gcc-3.3.  */
9606
9607 static bool
9608 pointee_is_readonly (tree pointee)
9609 {
9610   while (POINTER_TYPE_P (pointee))
9611     pointee = TREE_TYPE (pointee);
9612
9613   return TYPE_READONLY (pointee);
9614 }
9615
9616 /* Encode a pointer type.  */
9617
9618 static void
9619 encode_pointer (tree type, int curtype, int format)
9620 {
9621   tree pointer_to = TREE_TYPE (type);
9622
9623   if (flag_next_runtime)
9624     {
9625       /* This code is used to be compatible with gcc-3.3.  */
9626       /* For historical/compatibility reasons, the read-only qualifier
9627          of the pointee gets emitted _before_ the '^'.  The read-only
9628          qualifier of the pointer itself gets ignored, _unless_ we are
9629          looking at a typedef!  Also, do not emit the 'r' for anything
9630          but the outermost type!  */
9631       if (!generating_instance_variables
9632           && (obstack_object_size (&util_obstack) - curtype <= 1)
9633           && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
9634               ? TYPE_READONLY (type)
9635               : pointee_is_readonly (pointer_to)))
9636         obstack_1grow (&util_obstack, 'r');
9637     }
9638
9639   if (TREE_CODE (pointer_to) == RECORD_TYPE)
9640     {
9641       if (OBJC_TYPE_NAME (pointer_to)
9642           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
9643         {
9644           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
9645
9646           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
9647             {
9648               obstack_1grow (&util_obstack, '@');
9649               return;
9650             }
9651           else if (TYPE_HAS_OBJC_INFO (pointer_to)
9652                    && TYPE_OBJC_INTERFACE (pointer_to))
9653             {
9654               if (generating_instance_variables)
9655                 {
9656                   obstack_1grow (&util_obstack, '@');
9657                   obstack_1grow (&util_obstack, '"');
9658                   obstack_grow (&util_obstack, name, strlen (name));
9659                   obstack_1grow (&util_obstack, '"');
9660                   return;
9661                 }
9662               else
9663                 {
9664                   obstack_1grow (&util_obstack, '@');
9665                   return;
9666                 }
9667             }
9668           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
9669             {
9670               obstack_1grow (&util_obstack, '#');
9671               return;
9672             }
9673           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
9674             {
9675               obstack_1grow (&util_obstack, ':');
9676               return;
9677             }
9678         }
9679     }
9680   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
9681            && TYPE_MODE (pointer_to) == QImode)
9682     {
9683       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
9684                   ? OBJC_TYPE_NAME (pointer_to)
9685                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
9686
9687       /* (BOOL *) are an exception and are encoded as ^c, while all
9688          other pointers to char are encoded as *.   */
9689       if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
9690         {
9691           if (!flag_next_runtime)
9692             {
9693               /* The NeXT runtime adds the 'r' before getting here.  */
9694
9695               /* It appears that "r*" means "const char *" rather than
9696                  "char *const".  "char *const" is encoded as "*",
9697                  which is identical to "char *", so the "const" is
9698                  unfortunately lost.  */                 
9699               if (TYPE_READONLY (pointer_to))
9700                 obstack_1grow (&util_obstack, 'r');
9701             }
9702
9703           obstack_1grow (&util_obstack, '*');
9704           return;
9705         }
9706     }
9707
9708   /* We have a normal pointer type that does not get special treatment.  */
9709   obstack_1grow (&util_obstack, '^');
9710   encode_type (pointer_to, curtype, format);
9711 }
9712
9713 static void
9714 encode_array (tree type, int curtype, int format)
9715 {
9716   tree an_int_cst = TYPE_SIZE (type);
9717   tree array_of = TREE_TYPE (type);
9718   char buffer[40];
9719   
9720   if (an_int_cst == NULL)
9721     {
9722       /* We are trying to encode an incomplete array.  An incomplete
9723          array is forbidden as part of an instance variable.  */
9724       if (generating_instance_variables)
9725         {
9726           /* TODO: Detect this error earlier.  */
9727           error ("instance variable has unknown size");
9728           return;
9729         }
9730
9731       /* So the only case in which an incomplete array could occur is
9732          if we are encoding the arguments or return value of a method.
9733          In that case, an incomplete array argument or return value
9734          (eg, -(void)display: (char[])string) is treated like a
9735          pointer because that is how the compiler does the function
9736          call.  A special, more complicated case, is when the
9737          incomplete array is the last member of a struct (eg, if we
9738          are encoding "struct { unsigned long int a;double b[];}"),
9739          which is again part of a method argument/return value.  In
9740          that case, we really need to communicate to the runtime that
9741          there is an incomplete array (not a pointer!) there.  So, we
9742          detect that special case and encode it as a zero-length
9743          array.
9744
9745          Try to detect that we are part of a struct.  We do this by
9746          searching for '=' in the type encoding for the current type.
9747          NB: This hack assumes that you can't use '=' as part of a C
9748          identifier.
9749       */
9750       {
9751         char *enc = obstack_base (&util_obstack) + curtype;
9752         if (memchr (enc, '=', 
9753                     obstack_object_size (&util_obstack) - curtype) == NULL)
9754           {
9755             /* We are not inside a struct.  Encode the array as a
9756                pointer.  */
9757             encode_pointer (type, curtype, format);
9758             return;
9759           }
9760       }
9761
9762       /* Else, we are in a struct, and we encode it as a zero-length
9763          array.  */
9764       sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
9765     }
9766   else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
9767    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
9768   else
9769     sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
9770              TREE_INT_CST_LOW (an_int_cst)
9771               / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
9772
9773   obstack_grow (&util_obstack, buffer, strlen (buffer));
9774   encode_type (array_of, curtype, format);
9775   obstack_1grow (&util_obstack, ']');
9776   return;
9777 }
9778
9779 /* Encode a vector.  The vector type is a GCC extension to C.  */
9780 static void
9781 encode_vector (tree type, int curtype, int format)
9782 {
9783   tree vector_of = TREE_TYPE (type);
9784   char buffer[40];
9785
9786   /* Vectors are like simple fixed-size arrays.  */
9787
9788   /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
9789      alignment of the vector, and <code> is the base type.  Eg, int
9790      __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
9791      assuming that the alignment is 32 bytes.  We include size and
9792      alignment in bytes so that the runtime does not have to have any
9793      knowledge of the actual types.
9794   */
9795   sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
9796            /* We want to compute the equivalent of sizeof (<vector>).
9797               Code inspired by c_sizeof_or_alignof_type.  */
9798            ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)) 
9799              / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
9800            /* We want to compute the equivalent of __alignof__
9801               (<vector>).  Code inspired by
9802               c_sizeof_or_alignof_type.  */
9803            TYPE_ALIGN_UNIT (type));
9804   obstack_grow (&util_obstack, buffer, strlen (buffer));
9805   encode_type (vector_of, curtype, format);
9806   obstack_1grow (&util_obstack, ']');
9807   return;
9808 }
9809 \f
9810 static void
9811 encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
9812 {
9813   tree field = TYPE_FIELDS (type);
9814
9815   for (; field; field = DECL_CHAIN (field))
9816     {
9817 #ifdef OBJCPLUS
9818       /* C++ static members, and things that are not field at all,
9819          should not appear in the encoding.  */
9820       if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
9821         continue;
9822 #endif
9823
9824       /* Recursively encode fields of embedded base classes.  */
9825       if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
9826           && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
9827         {
9828           encode_aggregate_fields (TREE_TYPE (field),
9829                                    pointed_to, curtype, format);
9830           continue;
9831         }
9832
9833       if (generating_instance_variables && !pointed_to)
9834         {
9835           tree fname = DECL_NAME (field);
9836
9837           obstack_1grow (&util_obstack, '"');
9838
9839           if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
9840             obstack_grow (&util_obstack,
9841                           IDENTIFIER_POINTER (fname),
9842                           strlen (IDENTIFIER_POINTER (fname)));
9843
9844           obstack_1grow (&util_obstack, '"');
9845         }
9846
9847       encode_field_decl (field, curtype, format);
9848     }
9849 }
9850
9851 static void
9852 encode_aggregate_within (tree type, int curtype, int format, int left,
9853                          int right)
9854 {
9855   tree name;
9856   /* NB: aggregates that are pointed to have slightly different encoding
9857      rules in that you never encode the names of instance variables.  */
9858   int ob_size = obstack_object_size (&util_obstack);
9859   bool inline_contents = false;
9860   bool pointed_to = false;
9861
9862   if (flag_next_runtime)
9863     {
9864       if (ob_size > 0  &&  *(obstack_next_free (&util_obstack) - 1) == '^')
9865         pointed_to = true;
9866
9867       if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
9868           && (!pointed_to || ob_size - curtype == 1
9869               || (ob_size - curtype == 2
9870                   && *(obstack_next_free (&util_obstack) - 2) == 'r')))
9871         inline_contents = true;
9872     }
9873   else
9874     {
9875       /* c0 and c1 are the last two characters in the encoding of the
9876          current type; if the last two characters were '^' or '^r',
9877          then we are encoding an aggregate that is "pointed to".  The
9878          comment above applies: in that case we should avoid encoding
9879          the names of instance variables.
9880       */
9881       char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
9882       char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
9883       
9884       if (c0 == '^' || (c1 == '^' && c0 == 'r'))
9885         pointed_to = true;
9886       
9887       if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
9888         {
9889           if (!pointed_to)
9890             inline_contents = true;
9891           else
9892             {
9893               /* Note that the check (ob_size - curtype < 2) prevents
9894                  infinite recursion when encoding a structure which is
9895                  a linked list (eg, struct node { struct node *next;
9896                  }).  Each time we follow a pointer, we add one
9897                  character to ob_size, and curtype is fixed, so after
9898                  at most two pointers we stop inlining contents and
9899                  break the loop.
9900
9901                  The other case where we don't inline is "^r", which
9902                  is a pointer to a constant struct.
9903               */
9904               if ((ob_size - curtype <= 2) && !(c0 == 'r'))
9905                 inline_contents = true;
9906             }
9907         }
9908     }
9909
9910   /* Traverse struct aliases; it is important to get the
9911      original struct and its tag name (if any).  */
9912   type = TYPE_MAIN_VARIANT (type);
9913   name = OBJC_TYPE_NAME (type);
9914   /* Open parenth/bracket.  */
9915   obstack_1grow (&util_obstack, left);
9916
9917   /* Encode the struct/union tag name, or '?' if a tag was
9918      not provided.  Typedef aliases do not qualify.  */
9919 #ifdef OBJCPLUS
9920   /* For compatibility with the NeXT runtime, ObjC++ encodes template
9921      args as a composite struct tag name. */
9922   if (name && TREE_CODE (name) == IDENTIFIER_NODE
9923       /* Did this struct have a tag?  */
9924       && !TYPE_WAS_ANONYMOUS (type))
9925     obstack_grow (&util_obstack,
9926                   decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
9927                   strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
9928 #else
9929   if (name && TREE_CODE (name) == IDENTIFIER_NODE)
9930     obstack_grow (&util_obstack,
9931                   IDENTIFIER_POINTER (name),
9932                   strlen (IDENTIFIER_POINTER (name)));
9933 #endif
9934   else
9935     obstack_1grow (&util_obstack, '?');
9936
9937   /* Encode the types (and possibly names) of the inner fields,
9938      if required.  */
9939   if (inline_contents)
9940     {
9941       obstack_1grow (&util_obstack, '=');
9942       encode_aggregate_fields (type, pointed_to, curtype, format);
9943     }
9944   /* Close parenth/bracket.  */
9945   obstack_1grow (&util_obstack, right);
9946 }
9947
9948 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
9949    field type.  */
9950
9951 static void
9952 encode_next_bitfield (int width)
9953 {
9954   char buffer[40];
9955   sprintf (buffer, "b%d", width);
9956   obstack_grow (&util_obstack, buffer, strlen (buffer));
9957 }
9958 \f
9959
9960 /* Encodes 'type', ignoring type qualifiers (which you should encode
9961    beforehand if needed) with the exception of 'const', which is
9962    encoded by encode_type.  See above for the explanation of
9963    'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
9964    OBJC_ENCODE_DONT_INLINE_DEFS.
9965 */
9966 static void
9967 encode_type (tree type, int curtype, int format)
9968 {
9969   enum tree_code code = TREE_CODE (type);
9970
9971   /* Ignore type qualifiers other than 'const' when encoding a
9972      type.  */
9973
9974   if (type == error_mark_node)
9975     return;
9976
9977   if (!flag_next_runtime)
9978     {
9979       if (TYPE_READONLY (type))
9980         obstack_1grow (&util_obstack, 'r');
9981     }
9982
9983   switch (code)
9984     {
9985     case ENUMERAL_TYPE:
9986       if (flag_next_runtime)
9987         {
9988           /* Kludge for backwards-compatibility with gcc-3.3: enums
9989              are always encoded as 'i' no matter what type they
9990              actually are (!).  */
9991           obstack_1grow (&util_obstack, 'i');
9992           break;
9993         }
9994       /* Else, they are encoded exactly like the integer type that is
9995          used by the compiler to store them.  */
9996     case INTEGER_TYPE:
9997       {
9998         char c;
9999         switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
10000           {
10001           case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
10002           case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
10003           case 32:
10004             {
10005               tree int_type = type;
10006               if (flag_next_runtime)
10007                 {
10008                   /* Another legacy kludge for compatiblity with
10009                      gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
10010                      but not always.  For typedefs, we need to use 'i'
10011                      or 'I' instead if encoding a struct field, or a
10012                      pointer!  */
10013                   int_type =  ((!generating_instance_variables
10014                                 && (obstack_object_size (&util_obstack)
10015                                     == (unsigned) curtype))
10016                                ? TYPE_MAIN_VARIANT (type)
10017                                : type);
10018                 }
10019               if (int_type == long_unsigned_type_node
10020                   || int_type == long_integer_type_node)
10021                 c = TYPE_UNSIGNED (type) ? 'L' : 'l';
10022               else
10023                 c = TYPE_UNSIGNED (type) ? 'I' : 'i';
10024             }
10025             break;
10026           case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
10027           case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
10028           default: gcc_unreachable ();
10029           }
10030         obstack_1grow (&util_obstack, c);
10031         break;
10032       }
10033     case REAL_TYPE:
10034       {
10035         char c;
10036         /* Floating point types.  */
10037         switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
10038           {
10039           case 32:  c = 'f'; break;
10040           case 64:  c = 'd'; break;
10041           case 96:
10042           case 128: c = 'D'; break;
10043           default: gcc_unreachable ();
10044           }
10045         obstack_1grow (&util_obstack, c);
10046         break;
10047       }
10048     case VOID_TYPE:
10049       obstack_1grow (&util_obstack, 'v');
10050       break;
10051
10052     case BOOLEAN_TYPE:
10053       obstack_1grow (&util_obstack, 'B');
10054       break;
10055
10056     case ARRAY_TYPE:
10057       encode_array (type, curtype, format);
10058       break;
10059
10060     case POINTER_TYPE:
10061 #ifdef OBJCPLUS
10062     case REFERENCE_TYPE:
10063 #endif
10064       encode_pointer (type, curtype, format);
10065       break;
10066
10067     case RECORD_TYPE:
10068       encode_aggregate_within (type, curtype, format, '{', '}');
10069       break;
10070
10071     case UNION_TYPE:
10072       encode_aggregate_within (type, curtype, format, '(', ')');
10073       break;
10074
10075     case FUNCTION_TYPE: /* '?' means an unknown type.  */
10076       obstack_1grow (&util_obstack, '?');
10077       break;
10078
10079     case COMPLEX_TYPE:
10080       /* A complex is encoded as 'j' followed by the inner type (eg,
10081          "_Complex int" is encoded as 'ji').  */
10082       obstack_1grow (&util_obstack, 'j');
10083       encode_type (TREE_TYPE (type), curtype, format);
10084       break;
10085
10086     case VECTOR_TYPE:
10087       encode_vector (type, curtype, format);
10088       break;
10089
10090     default:
10091       warning (0, "unknown type %s found during Objective-C encoding",
10092                gen_type_name (type));
10093       obstack_1grow (&util_obstack, '?');
10094       break;
10095     }
10096   
10097   if (flag_next_runtime)
10098     {
10099       /* Super-kludge.  Some ObjC qualifier and type combinations need
10100          to be rearranged for compatibility with gcc-3.3.  */
10101       if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
10102         {
10103           char *enc = obstack_base (&util_obstack) + curtype;
10104           
10105           /* Rewrite "in const" from "nr" to "rn".  */
10106           if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
10107             strncpy (enc - 1, "rn", 2);
10108         }
10109     }
10110 }
10111
10112 static void
10113 encode_gnu_bitfield (int position, tree type, int size)
10114 {
10115   enum tree_code code = TREE_CODE (type);
10116   char buffer[40];
10117   char charType = '?';
10118
10119   /* This code is only executed for the GNU runtime, so we can ignore
10120      the NeXT runtime kludge of always encoding enums as 'i' no matter
10121      what integers they actually are.  */
10122   if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
10123     {
10124       if (integer_zerop (TYPE_MIN_VALUE (type)))
10125         /* Unsigned integer types.  */
10126         {
10127           switch (TYPE_MODE (type))
10128             {
10129             case QImode:
10130               charType = 'C'; break;
10131             case HImode:
10132               charType = 'S'; break;
10133             case SImode:
10134               {
10135                 if (type == long_unsigned_type_node)
10136                   charType = 'L';
10137                 else
10138                   charType = 'I';
10139                 break;
10140               }
10141             case DImode:
10142               charType = 'Q'; break;
10143             default:
10144               gcc_unreachable ();
10145             }
10146         }
10147       else
10148         /* Signed integer types.  */
10149         {
10150           switch (TYPE_MODE (type))
10151             {
10152             case QImode:
10153               charType = 'c'; break;
10154             case HImode:
10155               charType = 's'; break;
10156             case SImode:
10157               {
10158                 if (type == long_integer_type_node)
10159                   charType = 'l';
10160                 else
10161                   charType = 'i';
10162                 break;
10163               }
10164             case DImode:
10165               charType = 'q'; break;
10166             default:
10167               gcc_unreachable ();
10168             }
10169         }
10170     }
10171   else
10172     {
10173       /* Do not do any encoding, produce an error and keep going.  */
10174       error ("trying to encode non-integer type as a bitfield");
10175       return;
10176     }
10177
10178   sprintf (buffer, "b%d%c%d", position, charType, size);
10179   obstack_grow (&util_obstack, buffer, strlen (buffer));
10180 }
10181
10182 static void
10183 encode_field_decl (tree field_decl, int curtype, int format)
10184 {
10185 #ifdef OBJCPLUS
10186   /* C++ static members, and things that are not fields at all,
10187      should not appear in the encoding.  */
10188   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
10189     return;
10190 #endif
10191
10192   /* Generate the bitfield typing information, if needed.  Note the difference
10193      between GNU and NeXT runtimes.  */
10194   if (DECL_BIT_FIELD_TYPE (field_decl))
10195     {
10196       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
10197
10198       if (flag_next_runtime)
10199         encode_next_bitfield (size);
10200       else
10201         encode_gnu_bitfield (int_bit_position (field_decl),
10202                              DECL_BIT_FIELD_TYPE (field_decl), size);
10203     }
10204   else
10205     encode_type (TREE_TYPE (field_decl), curtype, format);
10206 }
10207
10208 /* Decay array and function parameters into pointers.  */
10209
10210 static tree
10211 objc_decay_parm_type (tree type)
10212 {
10213   if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE)
10214     type = build_pointer_type (TREE_CODE (type) == ARRAY_TYPE
10215                                ? TREE_TYPE (type)
10216                                : type);
10217
10218   return type;
10219 }
10220
10221 static GTY(()) tree objc_parmlist = NULL_TREE;
10222
10223 /* Append PARM to a list of formal parameters of a method, making a necessary
10224    array-to-pointer adjustment along the way.  */
10225
10226 static void
10227 objc_push_parm (tree parm)
10228 {
10229   tree type;
10230
10231   if (TREE_TYPE (parm) == error_mark_node)
10232     {
10233       objc_parmlist = chainon (objc_parmlist, parm);
10234       return;
10235     }
10236
10237   /* Decay arrays and functions into pointers.  */
10238   type = objc_decay_parm_type (TREE_TYPE (parm));
10239
10240   /* If the parameter type has been decayed, a new PARM_DECL needs to be
10241      built as well.  */
10242   if (type != TREE_TYPE (parm))
10243     parm = build_decl (input_location, PARM_DECL, DECL_NAME (parm), type);
10244
10245   DECL_ARG_TYPE (parm)
10246     = lang_hooks.types.type_promotes_to (TREE_TYPE (parm));
10247
10248   /* Record constancy and volatility.  */
10249   c_apply_type_quals_to_decl
10250   ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
10251    | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
10252    | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
10253
10254   objc_parmlist = chainon (objc_parmlist, parm);
10255 }
10256
10257 /* Retrieve the formal parameter list constructed via preceding calls to
10258    objc_push_parm().  */
10259
10260 #ifdef OBJCPLUS
10261 static tree
10262 objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
10263 #else
10264 static struct c_arg_info *
10265 objc_get_parm_info (int have_ellipsis)
10266 #endif
10267 {
10268 #ifdef OBJCPLUS
10269   tree parm_info = objc_parmlist;
10270   objc_parmlist = NULL_TREE;
10271
10272   return parm_info;
10273 #else
10274   tree parm_info = objc_parmlist;
10275   struct c_arg_info *arg_info;
10276   /* The C front-end requires an elaborate song and dance at
10277      this point.  */
10278   push_scope ();
10279   declare_parm_level ();
10280   while (parm_info)
10281     {
10282       tree next = DECL_CHAIN (parm_info);
10283
10284       DECL_CHAIN (parm_info) = NULL_TREE;
10285       parm_info = pushdecl (parm_info);
10286       finish_decl (parm_info, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
10287       parm_info = next;
10288     }
10289   arg_info = get_parm_info (have_ellipsis);
10290   pop_scope ();
10291   objc_parmlist = NULL_TREE;
10292   return arg_info;
10293 #endif
10294 }
10295
10296 /* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
10297    method definitions.  In the case of instance methods, we can be more
10298    specific as to the type of 'self'.  */
10299
10300 static void
10301 synth_self_and_ucmd_args (void)
10302 {
10303   tree self_type;
10304
10305   if (objc_method_context
10306       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
10307     self_type = objc_instance_type;
10308   else
10309     /* Really a `struct objc_class *'. However, we allow people to
10310        assign to self, which changes its type midstream.  */
10311     self_type = objc_object_type;
10312
10313   /* id self; */
10314   objc_push_parm (build_decl (input_location,
10315                               PARM_DECL, self_id, self_type));
10316
10317   /* SEL _cmd; */
10318   objc_push_parm (build_decl (input_location,
10319                               PARM_DECL, ucmd_id, objc_selector_type));
10320 }
10321
10322 /* Transform an Objective-C method definition into a static C function
10323    definition, synthesizing the first two arguments, "self" and "_cmd",
10324    in the process.  */
10325
10326 static void
10327 start_method_def (tree method)
10328 {
10329   tree parmlist;
10330 #ifdef OBJCPLUS
10331   tree parm_info;
10332 #else
10333   struct c_arg_info *parm_info;
10334 #endif
10335   int have_ellipsis = 0;
10336
10337   /* If we are defining a "dealloc" method in a non-root class, we
10338      will need to check if a [super dealloc] is missing, and warn if
10339      it is.  */
10340   if(CLASS_SUPER_NAME (objc_implementation_context)
10341      && !strcmp ("dealloc", IDENTIFIER_POINTER (METHOD_SEL_NAME (method))))
10342     should_call_super_dealloc = 1;
10343   else
10344     should_call_super_dealloc = 0;
10345
10346   /* Required to implement _msgSuper.  */
10347   objc_method_context = method;
10348   UOBJC_SUPER_decl = NULL_TREE;
10349
10350   /* Generate prototype declarations for arguments..."new-style".  */
10351   synth_self_and_ucmd_args ();
10352
10353   /* Generate argument declarations if a keyword_decl.  */
10354   parmlist = METHOD_SEL_ARGS (method);
10355   while (parmlist)
10356     {
10357       /* parmlist is a KEYWORD_DECL.  */
10358       tree type = TREE_VALUE (TREE_TYPE (parmlist));
10359       tree parm;
10360
10361       parm = build_decl (input_location,
10362                          PARM_DECL, KEYWORD_ARG_NAME (parmlist), type);
10363       decl_attributes (&parm, DECL_ATTRIBUTES (parmlist), 0);
10364       objc_push_parm (parm);
10365       parmlist = DECL_CHAIN (parmlist);
10366     }
10367
10368   if (METHOD_ADD_ARGS (method))
10369     {
10370       tree akey;
10371
10372       for (akey = TREE_CHAIN (METHOD_ADD_ARGS (method));
10373            akey; akey = TREE_CHAIN (akey))
10374         {
10375           objc_push_parm (TREE_VALUE (akey));
10376         }
10377
10378       if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
10379         have_ellipsis = 1;
10380     }
10381
10382   parm_info = objc_get_parm_info (have_ellipsis);
10383
10384   really_start_method (objc_method_context, parm_info);
10385 }
10386
10387 /* Return 1 if TYPE1 is equivalent to TYPE2
10388    for purposes of method overloading.  */
10389
10390 static int
10391 objc_types_are_equivalent (tree type1, tree type2)
10392 {
10393   if (type1 == type2)
10394     return 1;
10395
10396   /* Strip away indirections.  */
10397   while ((TREE_CODE (type1) == ARRAY_TYPE || TREE_CODE (type1) == POINTER_TYPE)
10398          && (TREE_CODE (type1) == TREE_CODE (type2)))
10399     type1 = TREE_TYPE (type1), type2 = TREE_TYPE (type2);
10400   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
10401     return 0;
10402
10403   type1 = (TYPE_HAS_OBJC_INFO (type1)
10404            ? TYPE_OBJC_PROTOCOL_LIST (type1)
10405            : NULL_TREE);
10406   type2 = (TYPE_HAS_OBJC_INFO (type2)
10407            ? TYPE_OBJC_PROTOCOL_LIST (type2)
10408            : NULL_TREE);
10409
10410   if (list_length (type1) == list_length (type2))
10411     {
10412       for (; type2; type2 = TREE_CHAIN (type2))
10413         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
10414           return 0;
10415       return 1;
10416     }
10417   return 0;
10418 }
10419
10420 /* Return 1 if TYPE1 has the same size and alignment as TYPE2.  */
10421
10422 static int
10423 objc_types_share_size_and_alignment (tree type1, tree type2)
10424 {
10425   return (simple_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
10426           && TYPE_ALIGN (type1) == TYPE_ALIGN (type2));
10427 }
10428
10429 /* Return 1 if PROTO1 is equivalent to PROTO2
10430    for purposes of method overloading.  Ordinarily, the type signatures
10431    should match up exactly, unless STRICT is zero, in which case we
10432    shall allow differences in which the size and alignment of a type
10433    is the same.  */
10434
10435 static int
10436 comp_proto_with_proto (tree proto1, tree proto2, int strict)
10437 {
10438   /* The following test is needed in case there are hashing
10439      collisions.  */
10440   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
10441     return 0;
10442
10443   return match_proto_with_proto (proto1, proto2, strict);
10444 }
10445
10446 static int
10447 match_proto_with_proto (tree proto1, tree proto2, int strict)
10448 {
10449   tree type1, type2;
10450
10451   /* Compare return types.  */
10452   type1 = TREE_VALUE (TREE_TYPE (proto1));
10453   type2 = TREE_VALUE (TREE_TYPE (proto2));
10454
10455   if (!objc_types_are_equivalent (type1, type2)
10456       && (strict || !objc_types_share_size_and_alignment (type1, type2)))
10457     return 0;
10458
10459   /* Compare argument types.  */
10460   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
10461        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
10462        type1 && type2;
10463        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
10464     {
10465       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2))
10466           && (strict
10467               || !objc_types_share_size_and_alignment (TREE_VALUE (type1),
10468                                                        TREE_VALUE (type2))))
10469         return 0;
10470     }
10471
10472   return (!type1 && !type2);
10473 }
10474
10475 /* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
10476    this occurs.  ObjC method dispatches are _not_ like C++ virtual
10477    member function dispatches, and we account for the difference here.  */
10478 tree
10479 #ifdef OBJCPLUS
10480 objc_fold_obj_type_ref (tree ref, tree known_type)
10481 #else
10482 objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
10483                         tree known_type ATTRIBUTE_UNUSED)
10484 #endif
10485 {
10486 #ifdef OBJCPLUS
10487   tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
10488
10489   /* If the receiver does not have virtual member functions, there
10490      is nothing we can (or need to) do here.  */
10491   if (!v)
10492     return NULL_TREE;
10493
10494   /* Let C++ handle C++ virtual functions.  */
10495   return cp_fold_obj_type_ref (ref, known_type);
10496 #else
10497   /* For plain ObjC, we currently do not need to do anything.  */
10498   return NULL_TREE;
10499 #endif
10500 }
10501
10502 static void
10503 objc_start_function (tree name, tree type, tree attrs,
10504 #ifdef OBJCPLUS
10505                      tree params
10506 #else
10507                      struct c_arg_info *params
10508 #endif
10509                      )
10510 {
10511   tree fndecl = build_decl (input_location,
10512                             FUNCTION_DECL, name, type);
10513
10514 #ifdef OBJCPLUS
10515   DECL_ARGUMENTS (fndecl) = params;
10516   DECL_INITIAL (fndecl) = error_mark_node;
10517   DECL_EXTERNAL (fndecl) = 0;
10518   TREE_STATIC (fndecl) = 1;
10519   retrofit_lang_decl (fndecl);
10520   cplus_decl_attributes (&fndecl, attrs, 0);
10521   start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
10522 #else
10523   current_function_returns_value = 0;  /* Assume, until we see it does.  */
10524   current_function_returns_null = 0;
10525   decl_attributes (&fndecl, attrs, 0);
10526   announce_function (fndecl);
10527   DECL_INITIAL (fndecl) = error_mark_node;
10528   DECL_EXTERNAL (fndecl) = 0;
10529   TREE_STATIC (fndecl) = 1;
10530   current_function_decl = pushdecl (fndecl);
10531   push_scope ();
10532   declare_parm_level ();
10533   DECL_RESULT (current_function_decl)
10534     = build_decl (input_location,
10535                   RESULT_DECL, NULL_TREE,
10536                   TREE_TYPE (TREE_TYPE (current_function_decl)));
10537   DECL_ARTIFICIAL (DECL_RESULT (current_function_decl)) = 1;
10538   DECL_IGNORED_P (DECL_RESULT (current_function_decl)) = 1;
10539   start_fname_decls ();
10540   store_parm_decls_from (params);
10541 #endif
10542
10543   TREE_USED (current_function_decl) = 1;
10544 }
10545
10546 /* - Generate an identifier for the function. the format is "_n_cls",
10547      where 1 <= n <= nMethods, and cls is the name the implementation we
10548      are processing.
10549    - Install the return type from the method declaration.
10550    - If we have a prototype, check for type consistency.  */
10551
10552 static void
10553 really_start_method (tree method,
10554 #ifdef OBJCPLUS
10555                      tree parmlist
10556 #else
10557                      struct c_arg_info *parmlist
10558 #endif
10559                      )
10560 {
10561   tree ret_type, meth_type;
10562   tree method_id;
10563   const char *sel_name, *class_name, *cat_name;
10564   char *buf;
10565
10566   /* Synth the storage class & assemble the return type.  */
10567   ret_type = TREE_VALUE (TREE_TYPE (method));
10568
10569   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
10570   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
10571   cat_name = ((TREE_CODE (objc_implementation_context)
10572                == CLASS_IMPLEMENTATION_TYPE)
10573               ? NULL
10574               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
10575   method_slot++;
10576
10577   /* Make sure this is big enough for any plausible method label.  */
10578   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
10579                          + (cat_name ? strlen (cat_name) : 0));
10580
10581   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
10582                          class_name, cat_name, sel_name, method_slot);
10583
10584   method_id = get_identifier (buf);
10585
10586 #ifdef OBJCPLUS
10587   /* Objective-C methods cannot be overloaded, so we don't need
10588      the type encoding appended.  It looks bad anyway... */
10589   push_lang_context (lang_name_c);
10590 #endif
10591
10592   meth_type
10593     = build_function_type (ret_type,
10594                            get_arg_type_list (method, METHOD_DEF, 0));
10595   objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
10596
10597   /* Set self_decl from the first argument.  */
10598   self_decl = DECL_ARGUMENTS (current_function_decl);
10599
10600   /* Suppress unused warnings.  */
10601   TREE_USED (self_decl) = 1;
10602   DECL_READ_P (self_decl) = 1;
10603   TREE_USED (DECL_CHAIN (self_decl)) = 1;
10604   DECL_READ_P (DECL_CHAIN (self_decl)) = 1;
10605 #ifdef OBJCPLUS
10606   pop_lang_context ();
10607 #endif
10608
10609   METHOD_DEFINITION (method) = current_function_decl;
10610
10611   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
10612
10613   if (implementation_template != objc_implementation_context)
10614     {
10615       tree proto
10616         = lookup_method_static (implementation_template,
10617                                 METHOD_SEL_NAME (method),
10618                                 ((TREE_CODE (method) == CLASS_METHOD_DECL)
10619                                  | OBJC_LOOKUP_NO_SUPER));
10620
10621       if (proto)
10622         {
10623           if (!comp_proto_with_proto (method, proto, 1))
10624             {
10625               bool type = TREE_CODE (method) == INSTANCE_METHOD_DECL;
10626
10627               warning_at (DECL_SOURCE_LOCATION (method), 0,
10628                           "conflicting types for %<%c%s%>",
10629                           (type ? '-' : '+'),
10630                           identifier_to_locale (gen_method_decl (method)));
10631               inform (DECL_SOURCE_LOCATION (proto),
10632                       "previous declaration of %<%c%s%>",
10633                       (type ? '-' : '+'),
10634                       identifier_to_locale (gen_method_decl (proto)));
10635             }
10636         }
10637       else
10638         {
10639           /* We have a method @implementation even though we did not
10640              see a corresponding @interface declaration (which is allowed
10641              by Objective-C rules).  Go ahead and place the method in
10642              the @interface anyway, so that message dispatch lookups
10643              will see it.  */
10644           tree interface = implementation_template;
10645
10646           if (TREE_CODE (objc_implementation_context)
10647               == CATEGORY_IMPLEMENTATION_TYPE)
10648             interface = lookup_category
10649                         (interface,
10650                          CLASS_SUPER_NAME (objc_implementation_context));
10651
10652           if (interface)
10653             objc_add_method (interface, copy_node (method),
10654                              TREE_CODE (method) == CLASS_METHOD_DECL, 
10655                              /* is_optional= */ false);
10656         }
10657     }
10658 }
10659
10660 static void *UOBJC_SUPER_scope = 0;
10661
10662 /* _n_Method (id self, SEL sel, ...)
10663      {
10664        struct objc_super _S;
10665        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
10666      }  */
10667
10668 static tree
10669 get_super_receiver (void)
10670 {
10671   if (objc_method_context)
10672     {
10673       tree super_expr, super_expr_list;
10674
10675       if (!UOBJC_SUPER_decl)
10676       {
10677         UOBJC_SUPER_decl = build_decl (input_location,
10678                                        VAR_DECL, get_identifier (TAG_SUPER),
10679                                        objc_super_template);
10680         /* This prevents `unused variable' warnings when compiling with -Wall.  */
10681         TREE_USED (UOBJC_SUPER_decl) = 1;
10682         DECL_READ_P (UOBJC_SUPER_decl) = 1;
10683         lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
10684         finish_decl (UOBJC_SUPER_decl, input_location, NULL_TREE, NULL_TREE,
10685                      NULL_TREE);
10686         UOBJC_SUPER_scope = objc_get_current_scope ();
10687       }
10688
10689       /* Set receiver to self.  */
10690       super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id);
10691       super_expr = build_modify_expr (input_location, super_expr, NULL_TREE,
10692                                       NOP_EXPR, input_location, self_decl,
10693                                       NULL_TREE);
10694       super_expr_list = super_expr;
10695
10696       /* Set class to begin searching.  */
10697       super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
10698                                              get_identifier ("super_class"));
10699
10700       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
10701         {
10702           /* [_cls, __cls]Super are "pre-built" in
10703              synth_forward_declarations.  */
10704
10705           super_expr = build_modify_expr (input_location, super_expr,
10706                                           NULL_TREE, NOP_EXPR,
10707                                           input_location,
10708                                           ((TREE_CODE (objc_method_context)
10709                                             == INSTANCE_METHOD_DECL)
10710                                            ? ucls_super_ref
10711                                            : uucls_super_ref),
10712                                           NULL_TREE);
10713         }
10714
10715       else
10716         /* We have a category.  */
10717         {
10718           tree super_name = CLASS_SUPER_NAME (implementation_template);
10719           tree super_class;
10720
10721           /* Barf if super used in a category of Object.  */
10722           if (!super_name)
10723             {
10724               error ("no super class declared in interface for %qE",
10725                      CLASS_NAME (implementation_template));
10726               return error_mark_node;
10727             }
10728
10729           if (flag_next_runtime && !flag_zero_link)
10730             {
10731               super_class = objc_get_class_reference (super_name);
10732               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
10733                 /* If we are in a class method, we must retrieve the
10734                    _metaclass_ for the current class, pointed at by
10735                    the class's "isa" pointer.  The following assumes that
10736                    "isa" is the first ivar in a class (which it must be).  */
10737                 super_class
10738                   = build_indirect_ref
10739                       (input_location,
10740                        build_c_cast (input_location,
10741                                      build_pointer_type (objc_class_type),
10742                                      super_class), RO_UNARY_STAR);
10743             }
10744           else
10745             {
10746               add_class_reference (super_name);
10747               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
10748                              ? objc_get_class_decl : objc_get_meta_class_decl);
10749               assemble_external (super_class);
10750               super_class
10751                 = build_function_call
10752                   (input_location,
10753                    super_class,
10754                    build_tree_list
10755                    (NULL_TREE,
10756                     my_build_string_pointer
10757                     (IDENTIFIER_LENGTH (super_name) + 1,
10758                      IDENTIFIER_POINTER (super_name))));
10759             }
10760
10761           super_expr
10762             = build_modify_expr (input_location, super_expr, NULL_TREE,
10763                                  NOP_EXPR,
10764                                  input_location,
10765                                  build_c_cast (input_location, 
10766                                                TREE_TYPE (super_expr),
10767                                                super_class),
10768                                  NULL_TREE);
10769         }
10770
10771       super_expr_list = build_compound_expr (input_location, 
10772                                              super_expr_list, super_expr);
10773
10774       super_expr = build_unary_op (input_location, 
10775                                    ADDR_EXPR, UOBJC_SUPER_decl, 0);
10776       super_expr_list = build_compound_expr (input_location,
10777                                              super_expr_list, super_expr);
10778
10779       return super_expr_list;
10780     }
10781   else
10782     {
10783       error ("[super ...] must appear in a method context");
10784       return error_mark_node;
10785     }
10786 }
10787
10788 /* When exiting a scope, sever links to a 'super' declaration (if any)
10789    therein contained.  */
10790
10791 void
10792 objc_clear_super_receiver (void)
10793 {
10794   if (objc_method_context
10795       && UOBJC_SUPER_scope == objc_get_current_scope ()) {
10796     UOBJC_SUPER_decl = 0;
10797     UOBJC_SUPER_scope = 0;
10798   }
10799 }
10800
10801 void
10802 objc_finish_method_definition (tree fndecl)
10803 {
10804   /* We cannot validly inline ObjC methods, at least not without a language
10805      extension to declare that a method need not be dynamically
10806      dispatched, so suppress all thoughts of doing so.  */
10807   DECL_UNINLINABLE (fndecl) = 1;
10808
10809 #ifndef OBJCPLUS
10810   /* The C++ front-end will have called finish_function() for us.  */
10811   finish_function ();
10812 #endif
10813
10814   METHOD_ENCODING (objc_method_context)
10815     = encode_method_prototype (objc_method_context);
10816
10817   /* Required to implement _msgSuper. This must be done AFTER finish_function,
10818      since the optimizer may find "may be used before set" errors.  */
10819   objc_method_context = NULL_TREE;
10820
10821   if (should_call_super_dealloc)
10822     warning (0, "method possibly missing a [super dealloc] call");
10823 }
10824
10825 /* Given a tree DECL node, produce a printable description of it in the given
10826    buffer, overwriting the buffer.  */
10827
10828 static char *
10829 gen_declaration (tree decl)
10830 {
10831   errbuf[0] = '\0';
10832
10833   if (DECL_P (decl))
10834     {
10835       gen_type_name_0 (TREE_TYPE (decl));
10836
10837       if (DECL_NAME (decl))
10838         {
10839           if (!POINTER_TYPE_P (TREE_TYPE (decl)))
10840             strcat (errbuf, " ");
10841
10842           strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
10843         }
10844
10845       if (DECL_INITIAL (decl)
10846           && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
10847         sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
10848                  TREE_INT_CST_LOW (DECL_INITIAL (decl)));
10849     }
10850
10851   return errbuf;
10852 }
10853
10854 /* Given a tree TYPE node, produce a printable description of it in the given
10855    buffer, overwriting the buffer.  */
10856
10857 static char *
10858 gen_type_name_0 (tree type)
10859 {
10860   tree orig = type, proto;
10861
10862   if (TYPE_P (type) && TYPE_NAME (type))
10863     type = TYPE_NAME (type);
10864   else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
10865     {
10866       tree inner = TREE_TYPE (type);
10867
10868       while (TREE_CODE (inner) == ARRAY_TYPE)
10869         inner = TREE_TYPE (inner);
10870
10871       gen_type_name_0 (inner);
10872
10873       if (!POINTER_TYPE_P (inner))
10874         strcat (errbuf, " ");
10875
10876       if (POINTER_TYPE_P (type))
10877         strcat (errbuf, "*");
10878       else
10879         while (type != inner)
10880           {
10881             strcat (errbuf, "[");
10882
10883             if (TYPE_DOMAIN (type))
10884               {
10885                 char sz[20];
10886
10887                 sprintf (sz, HOST_WIDE_INT_PRINT_DEC,
10888                          (TREE_INT_CST_LOW
10889                           (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1));
10890                 strcat (errbuf, sz);
10891               }
10892
10893             strcat (errbuf, "]");
10894             type = TREE_TYPE (type);
10895           }
10896
10897       goto exit_function;
10898     }
10899
10900   if (TREE_CODE (type) == TYPE_DECL && DECL_NAME (type))
10901     type = DECL_NAME (type);
10902
10903   strcat (errbuf, TREE_CODE (type) == IDENTIFIER_NODE
10904                   ? IDENTIFIER_POINTER (type)
10905                   : "");
10906
10907   /* For 'id' and 'Class', adopted protocols are stored in the pointee.  */
10908   if (objc_is_id (orig))
10909     orig = TREE_TYPE (orig);
10910
10911   proto = TYPE_HAS_OBJC_INFO (orig) ? TYPE_OBJC_PROTOCOL_LIST (orig) : NULL_TREE;
10912
10913   if (proto)
10914     {
10915       strcat (errbuf, " <");
10916
10917       while (proto) {
10918         strcat (errbuf,
10919                 IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (proto))));
10920         proto = TREE_CHAIN (proto);
10921         strcat (errbuf, proto ? ", " : ">");
10922       }
10923     }
10924
10925  exit_function:
10926   return errbuf;
10927 }
10928
10929 static char *
10930 gen_type_name (tree type)
10931 {
10932   errbuf[0] = '\0';
10933
10934   return gen_type_name_0 (type);
10935 }
10936
10937 /* Given a method tree, put a printable description into the given
10938    buffer (overwriting) and return a pointer to the buffer.  */
10939
10940 static char *
10941 gen_method_decl (tree method)
10942 {
10943   tree chain;
10944
10945   strcpy (errbuf, "(");  /* NB: Do _not_ call strcat() here.  */
10946   gen_type_name_0 (TREE_VALUE (TREE_TYPE (method)));
10947   strcat (errbuf, ")");
10948   chain = METHOD_SEL_ARGS (method);
10949
10950   if (chain)
10951     {
10952       /* We have a chain of keyword_decls.  */
10953       do
10954         {
10955           if (KEYWORD_KEY_NAME (chain))
10956             strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
10957
10958           strcat (errbuf, ":(");
10959           gen_type_name_0 (TREE_VALUE (TREE_TYPE (chain)));
10960           strcat (errbuf, ")");
10961
10962           strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
10963           if ((chain = DECL_CHAIN (chain)))
10964             strcat (errbuf, " ");
10965         }
10966       while (chain);
10967
10968       if (METHOD_ADD_ARGS (method))
10969         {
10970           chain = TREE_CHAIN (METHOD_ADD_ARGS (method));
10971
10972           /* Know we have a chain of parm_decls.  */
10973           while (chain)
10974             {
10975               strcat (errbuf, ", ");
10976               gen_type_name_0 (TREE_TYPE (TREE_VALUE (chain)));
10977               chain = TREE_CHAIN (chain);
10978             }
10979
10980           if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
10981             strcat (errbuf, ", ...");
10982         }
10983     }
10984
10985   else
10986     /* We have a unary selector.  */
10987     strcat (errbuf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
10988
10989   return errbuf;
10990 }
10991 \f
10992 /* Debug info.  */
10993
10994
10995 /* Dump an @interface declaration of the supplied class CHAIN to the
10996    supplied file FP.  Used to implement the -gen-decls option (which
10997    prints out an @interface declaration of all classes compiled in
10998    this run); potentially useful for debugging the compiler too.  */
10999 static void
11000 dump_interface (FILE *fp, tree chain)
11001 {
11002   /* FIXME: A heap overflow here whenever a method (or ivar)
11003      declaration is so long that it doesn't fit in the buffer.  The
11004      code and all the related functions should be rewritten to avoid
11005      using fixed size buffers.  */
11006   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
11007   tree ivar_decls = CLASS_RAW_IVARS (chain);
11008   tree nst_methods = CLASS_NST_METHODS (chain);
11009   tree cls_methods = CLASS_CLS_METHODS (chain);
11010
11011   fprintf (fp, "\n@interface %s", my_name);
11012
11013   /* CLASS_SUPER_NAME is used to store the superclass name for
11014      classes, and the category name for categories.  */
11015   if (CLASS_SUPER_NAME (chain))
11016     {
11017       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
11018
11019       switch (TREE_CODE (chain))
11020         {
11021         case CATEGORY_IMPLEMENTATION_TYPE:
11022         case CATEGORY_INTERFACE_TYPE:
11023           fprintf (fp, " (%s)\n", name);
11024           break;
11025         default:
11026           fprintf (fp, " : %s\n", name);
11027           break;
11028         }
11029     }
11030   else
11031     fprintf (fp, "\n");
11032
11033   /* FIXME - the following doesn't seem to work at the moment.  */
11034   if (ivar_decls)
11035     {
11036       fprintf (fp, "{\n");
11037       do
11038         {
11039           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls));
11040           ivar_decls = TREE_CHAIN (ivar_decls);
11041         }
11042       while (ivar_decls);
11043       fprintf (fp, "}\n");
11044     }
11045
11046   while (nst_methods)
11047     {
11048       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods));
11049       nst_methods = TREE_CHAIN (nst_methods);
11050     }
11051
11052   while (cls_methods)
11053     {
11054       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods));
11055       cls_methods = TREE_CHAIN (cls_methods);
11056     }
11057
11058   fprintf (fp, "@end\n");
11059 }
11060
11061 #if 0
11062 /* Produce the pretty printing for an Objective-C method.  This is
11063    currently unused, but could be handy while reorganizing the pretty
11064    printing to be more robust.  */
11065 static const char *
11066 objc_pretty_print_method (bool is_class_method,
11067                           const char *class_name,
11068                           const char *category_name,
11069                           const char *selector)
11070 {
11071   if (category_name)
11072     {
11073       char *result = XNEWVEC (char, strlen (class_name) + strlen (category_name) 
11074                               + strlen (selector) + 7);
11075
11076       if (is_class_method)
11077         sprintf (result, "+[%s(%s) %s]", class_name, category_name, selector);
11078       else
11079         sprintf (result, "-[%s(%s) %s]", class_name, category_name, selector);
11080
11081       return result;
11082     }
11083   else
11084     {
11085       char *result = XNEWVEC (char, strlen (class_name)
11086                               + strlen (selector) + 5);
11087
11088       if (is_class_method)
11089         sprintf (result, "+[%s %s]", class_name, selector);
11090       else
11091         sprintf (result, "-[%s %s]", class_name, selector);
11092
11093       return result;      
11094     }
11095 }
11096 #endif
11097
11098 /* Demangle function for Objective-C.  Attempt to demangle the
11099    function name associated with a method (eg, going from
11100    "_i_NSObject__class" to "-[NSObject class]"); usually for the
11101    purpose of pretty printing or error messages.  Return the demangled
11102    name, or NULL if the string is not an Objective-C mangled method
11103    name.
11104
11105    Because of how the mangling is done, any method that has a '_' in
11106    its original name is at risk of being demangled incorrectly.  In
11107    some cases there are multiple valid ways to demangle a method name
11108    and there is no way we can decide.
11109
11110    TODO: objc_demangle() can't always get it right; the right way to
11111    get this correct for all method names would be to store the
11112    Objective-C method name somewhere in the function decl.  Then,
11113    there is no demangling to do; we'd just pull the method name out of
11114    the decl.  As an additional bonus, when printing error messages we
11115    could check for such a method name, and if we find it, we know the
11116    function is actually an Objective-C method and we could print error
11117    messages saying "In method '+[NSObject class]" instead of "In
11118    function '+[NSObject class]" as we do now.  */
11119 static const char *
11120 objc_demangle (const char *mangled)
11121 {
11122   char *demangled, *cp;
11123
11124   if (mangled[0] == '_' &&
11125       (mangled[1] == 'i' || mangled[1] == 'c') &&
11126       mangled[2] == '_')
11127     {
11128       cp = demangled = XNEWVEC (char, strlen(mangled) + 2);
11129       if (mangled[1] == 'i')
11130         *cp++ = '-';            /* for instance method */
11131       else
11132         *cp++ = '+';            /* for class method */
11133       *cp++ = '[';              /* opening left brace */
11134       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
11135       while (*cp && *cp == '_')
11136         cp++;                   /* skip any initial underbars in class name */
11137       cp = strchr(cp, '_');     /* find first non-initial underbar */
11138       if (cp == NULL)
11139         {
11140           free(demangled);      /* not mangled name */
11141           return NULL;
11142         }
11143       if (cp[1] == '_')  /* easy case: no category name */
11144         {
11145           *cp++ = ' ';            /* replace two '_' with one ' ' */
11146           strcpy(cp, mangled + (cp - demangled) + 2);
11147         }
11148       else
11149         {
11150           *cp++ = '(';            /* less easy case: category name */
11151           cp = strchr(cp, '_');
11152           if (cp == 0)
11153             {
11154               free(demangled);    /* not mangled name */
11155               return NULL;
11156             }
11157           *cp++ = ')';
11158           *cp++ = ' ';            /* overwriting 1st char of method name... */
11159           strcpy(cp, mangled + (cp - demangled)); /* get it back */
11160         }
11161       /* Now we have the method name.  We need to generally replace
11162          '_' with ':' but trying to preserve '_' if it could only have
11163          been in the mangled string because it was already in the
11164          original name.  In cases where it's ambiguous, we assume that
11165          any '_' originated from a ':'.  */
11166
11167       /* Initial '_'s in method name can't have been generating by
11168          converting ':'s.  Skip them.  */
11169       while (*cp && *cp == '_')
11170         cp++;
11171
11172       /* If the method name does not end with '_', then it has no
11173          arguments and there was no replacement of ':'s with '_'s
11174          during mangling.  Check for that case, and skip any
11175          replacement if so.  This at least guarantees that methods
11176          with no arguments are always demangled correctly (unless the
11177          original name ends with '_').  */
11178       if (*(mangled + strlen (mangled) - 1) != '_')
11179         {
11180           /* Skip to the end.  */
11181           for (; *cp; cp++)
11182             ;
11183         }
11184       else
11185         {
11186           /* Replace remaining '_' with ':'.  This may get it wrong if
11187              there were '_'s in the original name.  In most cases it
11188              is impossible to disambiguate.  */
11189           for (; *cp; cp++)
11190             if (*cp == '_')
11191               *cp = ':';         
11192         }
11193       *cp++ = ']';              /* closing right brace */
11194       *cp++ = 0;                /* string terminator */
11195       return demangled;
11196     }
11197   else
11198     return NULL;             /* not an objc mangled name */
11199 }
11200
11201 /* Try to pretty-print a decl.  If the 'decl' is an Objective-C
11202    specific decl, return the printable name for it.  If not, return
11203    NULL.  */
11204 const char *
11205 objc_maybe_printable_name (tree decl, int v ATTRIBUTE_UNUSED)
11206 {
11207   switch (TREE_CODE (decl))
11208     {
11209     case FUNCTION_DECL:
11210       return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
11211       break;
11212
11213       /* The following happens when we are printing a deprecation
11214          warning for a method.  The warn_deprecation() will end up
11215          trying to print the decl for INSTANCE_METHOD_DECL or
11216          CLASS_METHOD_DECL.  It would be nice to be able to print
11217          "-[NSObject autorelease] is deprecated", but to do that, we'd
11218          need to store the class and method name in the method decl,
11219          which we currently don't do.  For now, just return the name
11220          of the method.  We don't return NULL, because that may
11221          trigger further attempts to pretty-print the decl in C/C++,
11222          but they wouldn't know how to pretty-print it.  */
11223     case INSTANCE_METHOD_DECL:
11224     case CLASS_METHOD_DECL:
11225       return IDENTIFIER_POINTER (DECL_NAME (decl));
11226       break;
11227     default:
11228       return NULL;
11229       break;
11230     }
11231 }
11232
11233 /* Return a printable name for 'decl'.  This first tries
11234    objc_maybe_printable_name(), and if that fails, it returns the name
11235    in the decl.  This is used as LANG_HOOKS_DECL_PRINTABLE_NAME for
11236    Objective-C; in Objective-C++, setting the hook is not enough
11237    because lots of C++ Front-End code calls cxx_printable_name,
11238    dump_decl and other C++ functions directly.  So instead we have
11239    modified dump_decl to call objc_maybe_printable_name directly.  */
11240 const char *
11241 objc_printable_name (tree decl, int v)
11242 {
11243   const char *demangled_name = objc_maybe_printable_name (decl, v);
11244
11245   if (demangled_name != NULL)
11246     return demangled_name;
11247   else
11248     return IDENTIFIER_POINTER (DECL_NAME (decl));
11249 }
11250
11251 static void
11252 init_objc (void)
11253 {
11254   gcc_obstack_init (&util_obstack);
11255   util_firstobj = (char *) obstack_finish (&util_obstack);
11256
11257   errbuf = XNEWVEC (char, 1024 * 10);
11258   hash_init ();
11259   synth_module_prologue ();
11260 }
11261 \f
11262 static void
11263 finish_objc (void)
11264 {
11265   struct imp_entry *impent;
11266   tree chain;
11267   /* The internally generated initializers appear to have missing braces.
11268      Don't warn about this.  */
11269   int save_warn_missing_braces = warn_missing_braces;
11270   warn_missing_braces = 0;
11271
11272   /* A missing @end may not be detected by the parser.  */
11273   if (objc_implementation_context)
11274     {
11275       warning (0, "%<@end%> missing in implementation context");
11276       finish_class (objc_implementation_context);
11277       objc_ivar_chain = NULL_TREE;
11278       objc_implementation_context = NULL_TREE;
11279     }
11280
11281   /* Process the static instances here because initialization of objc_symtab
11282      depends on them.  */
11283   if (objc_static_instances)
11284     generate_static_references ();
11285
11286   /* forward declare categories */
11287   if (cat_count)
11288     forward_declare_categories ();
11289
11290   for (impent = imp_list; impent; impent = impent->next)
11291     {
11292       objc_implementation_context = impent->imp_context;
11293       implementation_template = impent->imp_template;
11294
11295       /* FIXME: This needs reworking to be more obvious.  */
11296
11297       UOBJC_CLASS_decl = impent->class_decl;
11298       UOBJC_METACLASS_decl = impent->meta_decl;
11299
11300       /* Dump the @interface of each class as we compile it, if the
11301          -gen-decls option is in use.  TODO: Dump the classes in the
11302          order they were found, rather than in reverse order as we
11303          are doing now.  */
11304       if (flag_gen_declaration)
11305         {
11306           dump_interface (gen_declaration_file, objc_implementation_context);
11307         }
11308
11309       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
11310         {
11311           /* all of the following reference the string pool...  */
11312           generate_ivar_lists ();
11313           generate_dispatch_tables ();
11314           generate_shared_structures (impent);
11315         }
11316       else
11317         {
11318           generate_dispatch_tables ();
11319           generate_category (impent);
11320         }
11321
11322       impent->class_decl = UOBJC_CLASS_decl;
11323       impent->meta_decl = UOBJC_METACLASS_decl;
11324     }
11325
11326   /* If we are using an array of selectors, we must always
11327      finish up the array decl even if no selectors were used.  */
11328   if (flag_next_runtime)
11329     build_next_selector_translation_table ();
11330   else
11331     build_gnu_selector_translation_table ();
11332
11333   if (protocol_chain)
11334     generate_protocols ();
11335
11336   if (flag_next_runtime)
11337     generate_objc_image_info ();
11338
11339   if (imp_list || class_names_chain
11340       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
11341     generate_objc_symtab_decl ();
11342
11343   /* Arrange for ObjC data structures to be initialized at run time.  */
11344   if (objc_implementation_context || class_names_chain || objc_static_instances
11345       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
11346     {
11347       build_module_descriptor ();
11348
11349       if (!flag_next_runtime)
11350         build_module_initializer_routine ();
11351     }
11352
11353   /* Dump the class references.  This forces the appropriate classes
11354      to be linked into the executable image, preserving unix archive
11355      semantics.  This can be removed when we move to a more dynamically
11356      linked environment.  */
11357
11358   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
11359     {
11360       handle_class_ref (chain);
11361       if (TREE_PURPOSE (chain))
11362         generate_classref_translation_entry (chain);
11363     }
11364
11365   for (impent = imp_list; impent; impent = impent->next)
11366     handle_impent (impent);
11367
11368   if (warn_selector)
11369     {
11370       int slot;
11371       hash hsh;
11372
11373       /* Run through the selector hash tables and print a warning for any
11374          selector which has multiple methods.  */
11375
11376       for (slot = 0; slot < SIZEHASHTABLE; slot++)
11377         {
11378           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
11379             check_duplicates (hsh, 0, 1);
11380           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
11381             check_duplicates (hsh, 0, 1);
11382         }
11383     }
11384
11385   warn_missing_braces = save_warn_missing_braces;
11386 }
11387 \f
11388 /* Subroutines of finish_objc.  */
11389
11390 static void
11391 generate_classref_translation_entry (tree chain)
11392 {
11393   tree expr, decl, type;
11394
11395   decl = TREE_PURPOSE (chain);
11396   type = TREE_TYPE (decl);
11397
11398   expr = add_objc_string (TREE_VALUE (chain), class_names);
11399   expr = convert (type, expr); /* cast! */
11400
11401   /* This is a class reference.  It is re-written by the runtime,
11402      but will be optimized away unless we force it.  */
11403   DECL_PRESERVE_P (decl) = 1;
11404   finish_var_decl (decl, expr);
11405   return;
11406 }
11407
11408 static void
11409 handle_class_ref (tree chain)
11410 {
11411   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
11412   char *string = (char *) alloca (strlen (name) + 30);
11413   tree decl;
11414   tree exp;
11415
11416   sprintf (string, "%sobjc_class_name_%s",
11417            (flag_next_runtime ? "." : "__"), name);
11418
11419 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
11420   if (flag_next_runtime)
11421     {
11422       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
11423       return;
11424     }
11425 #endif
11426
11427   /* Make a decl for this name, so we can use its address in a tree.  */
11428   decl = build_decl (input_location,
11429                      VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
11430   DECL_EXTERNAL (decl) = 1;
11431   TREE_PUBLIC (decl) = 1;
11432   pushdecl (decl);
11433   finish_var_decl (decl, 0);
11434
11435   /* Make a decl for the address.  */
11436   sprintf (string, "%sobjc_class_ref_%s",
11437            (flag_next_runtime ? "." : "__"), name);
11438   exp = build1 (ADDR_EXPR, string_type_node, decl);
11439   decl = build_decl (input_location,
11440                      VAR_DECL, get_identifier (string), string_type_node);
11441   TREE_STATIC (decl) = 1;
11442   TREE_USED (decl) = 1;
11443   DECL_READ_P (decl) = 1;
11444   DECL_ARTIFICIAL (decl) = 1;
11445   DECL_INITIAL (decl) = error_mark_node;
11446  
11447   /* We must force the reference.  */
11448   DECL_PRESERVE_P (decl) = 1;
11449
11450   pushdecl (decl);
11451   finish_var_decl (decl, exp);
11452 }
11453
11454 static void
11455 handle_impent (struct imp_entry *impent)
11456 {
11457   char *string;
11458
11459   objc_implementation_context = impent->imp_context;
11460   implementation_template = impent->imp_template;
11461
11462   switch (TREE_CODE (impent->imp_context))
11463     {
11464     case CLASS_IMPLEMENTATION_TYPE:
11465       {
11466         const char *const class_name =
11467           IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
11468         
11469         string = (char *) alloca (strlen (class_name) + 30);
11470         
11471         sprintf (string, "%sobjc_class_name_%s",
11472                  (flag_next_runtime ? "." : "__"), class_name);
11473         break;
11474       }
11475     case CATEGORY_IMPLEMENTATION_TYPE:
11476       {
11477         const char *const class_name =
11478           IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
11479         const char *const class_super_name =
11480           IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
11481         
11482         string = (char *) alloca (strlen (class_name)
11483                                   + strlen (class_super_name) + 30);
11484         
11485         /* Do the same for categories.  Even though no references to
11486            these symbols are generated automatically by the compiler,
11487            it gives you a handle to pull them into an archive by
11488            hand.  */
11489         sprintf (string, "*%sobjc_category_name_%s_%s",
11490                  (flag_next_runtime ? "." : "__"), class_name, class_super_name);
11491         break;
11492       }
11493     default:
11494       return;
11495     }
11496
11497 #ifdef ASM_DECLARE_CLASS_REFERENCE
11498   if (flag_next_runtime)
11499     {
11500       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
11501       return;
11502     }
11503   else
11504 #endif
11505     {
11506       tree decl, init;
11507
11508       init = integer_zero_node;
11509       decl = build_decl (input_location,
11510                          VAR_DECL, get_identifier (string), TREE_TYPE (init));
11511       TREE_PUBLIC (decl) = 1;
11512       TREE_READONLY (decl) = 1;
11513       TREE_USED (decl) = 1;
11514       TREE_CONSTANT (decl) = 1;
11515       DECL_CONTEXT (decl) = NULL_TREE;
11516       DECL_ARTIFICIAL (decl) = 1;
11517       TREE_STATIC (decl) = 1;
11518       DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
11519       /* We must force the reference.  */
11520       DECL_PRESERVE_P (decl) = 1;
11521
11522       finish_var_decl(decl, init) ;
11523     }
11524 }
11525 \f
11526 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
11527    later requires that ObjC translation units participating in F&C be
11528    specially marked.  The following routine accomplishes this.  */
11529
11530 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
11531
11532 static void
11533 generate_objc_image_info (void)
11534 {
11535   tree decl;
11536   int flags
11537     = ((flag_replace_objc_classes && imp_count ? 1 : 0)
11538        | (flag_objc_gc ? 2 : 0));
11539   VEC(constructor_elt,gc) *v = NULL;
11540   tree array_type;
11541   
11542    if (!flags)
11543     return; /* No need for an image_info entry.  */
11544   
11545   array_type  = build_sized_array_type (integer_type_node, 2);
11546
11547   decl = start_var_decl (array_type, "_OBJC_IMAGE_INFO");
11548
11549   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
11550   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
11551   /* If we need this (determined above) it is because the runtime wants to
11552      refer to it in a manner hidden from the compiler.  So we must force the 
11553      output.  */
11554   DECL_PRESERVE_P (decl) = 1;
11555   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
11556 }
11557
11558 /* Routine is called to issue diagnostic when reference to a private 
11559    ivar is made and no other variable with same name is found in 
11560    current scope.  */
11561 bool
11562 objc_diagnose_private_ivar (tree id)
11563 {
11564   tree ivar;
11565   if (!objc_method_context)
11566     return false;
11567   ivar = is_ivar (objc_ivar_chain, id);
11568   if (ivar && is_private (ivar))
11569     {
11570       error ("instance variable %qs is declared private", 
11571              IDENTIFIER_POINTER (id));
11572       return true;
11573     }
11574   return false;
11575 }
11576
11577 /* Look up ID as an instance variable.  OTHER contains the result of
11578    the C or C++ lookup, which we may want to use instead.  */
11579 /* To use properties inside an instance method, use self.property.  */
11580 tree
11581 objc_lookup_ivar (tree other, tree id)
11582 {
11583   tree ivar;
11584
11585   /* If we are not inside of an ObjC method, ivar lookup makes no sense.  */
11586   if (!objc_method_context)
11587     return other;
11588
11589   if (!strcmp (IDENTIFIER_POINTER (id), "super"))
11590     /* We have a message to super.  */
11591     return get_super_receiver ();
11592
11593   /* In a class method, look up an instance variable only as a last
11594      resort.  */
11595   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
11596       && other && other != error_mark_node)
11597     return other;
11598
11599   /* Look up the ivar, but do not use it if it is not accessible.  */
11600   ivar = is_ivar (objc_ivar_chain, id);
11601   
11602   if (!ivar || is_private (ivar))
11603     return other;
11604
11605   /* In an instance method, a local variable (or parameter) may hide the
11606      instance variable.  */
11607   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
11608       && other && other != error_mark_node
11609 #ifdef OBJCPLUS
11610       && CP_DECL_CONTEXT (other) != global_namespace)
11611 #else
11612       && !DECL_FILE_SCOPE_P (other))
11613 #endif
11614     {
11615       warning (0, "local declaration of %qE hides instance variable", id);
11616
11617       return other;
11618     }
11619
11620   /* At this point, we are either in an instance method with no obscuring
11621      local definitions, or in a class method with no alternate definitions
11622      at all.  */
11623   return build_ivar_reference (id);
11624 }
11625
11626 /* Possibly rewrite a function CALL into an OBJ_TYPE_REF expression.  This
11627    needs to be done if we are calling a function through a cast.  */
11628
11629 tree
11630 objc_rewrite_function_call (tree function, tree first_param)
11631 {
11632   if (TREE_CODE (function) == NOP_EXPR
11633       && TREE_CODE (TREE_OPERAND (function, 0)) == ADDR_EXPR
11634       && TREE_CODE (TREE_OPERAND (TREE_OPERAND (function, 0), 0))
11635          == FUNCTION_DECL)
11636     {
11637       function = build3 (OBJ_TYPE_REF, TREE_TYPE (function),
11638                          TREE_OPERAND (function, 0),
11639                          first_param, size_zero_node);
11640     }
11641
11642   return function;
11643 }
11644
11645 /* This is called to "gimplify" a PROPERTY_REF node.  It builds the
11646    corresponding 'getter' function call.  Note that we assume the
11647    PROPERTY_REF to be valid since we generated it while parsing.  */
11648 static void
11649 objc_gimplify_property_ref (tree *expr_p)
11650 {
11651   tree object_expression = PROPERTY_REF_OBJECT (*expr_p);
11652   tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
11653   tree call_exp, getter;
11654
11655   /* TODO: Implement super.property.  */
11656
11657   getter = objc_finish_message_expr (object_expression, 
11658                                      PROPERTY_GETTER_NAME (property_decl),
11659                                      NULL_TREE);
11660   call_exp = getter;
11661 #ifdef OBJCPLUS
11662   /* In C++, a getter which returns an aggregate value results in a
11663      target_expr which initializes a temporary to the call
11664      expression.  */
11665   if (TREE_CODE (getter) == TARGET_EXPR)
11666     {
11667       gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter)));
11668       gcc_assert (TREE_CODE (TREE_OPERAND (getter, 0)) == VAR_DECL);
11669       call_exp = TREE_OPERAND (getter, 1);
11670     }
11671 #endif
11672   gcc_assert (TREE_CODE (call_exp) == CALL_EXPR);
11673   
11674   *expr_p = call_exp;
11675 }
11676
11677 /* This is called when "gimplifying" the trees.  We need to gimplify
11678    the Objective-C/Objective-C++ specific trees, then hand over the
11679    process to C/C++.  */
11680 int
11681 objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
11682 {
11683   enum tree_code code = TREE_CODE (*expr_p);
11684   switch (code)
11685     {
11686       /* Look for the special case of OBJC_TYPE_REF with the address
11687          of a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend
11688          or one of its cousins).  */
11689     case OBJ_TYPE_REF:
11690       if (TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
11691           && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
11692           == FUNCTION_DECL)
11693         {
11694           enum gimplify_status r0, r1;
11695
11696           /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
11697              value of the OBJ_TYPE_REF, so force them to be emitted
11698              during subexpression evaluation rather than after the
11699              OBJ_TYPE_REF. This permits objc_msgSend calls in
11700              Objective C to use direct rather than indirect calls when
11701              the object expression has a postincrement.  */
11702           r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
11703                               is_gimple_val, fb_rvalue);
11704           r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
11705                               is_gimple_val, fb_rvalue);
11706           
11707           return MIN (r0, r1);
11708         }
11709       break;
11710     case PROPERTY_REF:
11711       objc_gimplify_property_ref (expr_p);
11712       /* Do not return yet; let C/C++ gimplify the resulting expression.  */
11713       break;
11714     default:
11715       break;
11716     }
11717
11718 #ifdef OBJCPLUS
11719   return (enum gimplify_status) cp_gimplify_expr (expr_p, pre_p, post_p);
11720 #else
11721   return (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
11722 #endif
11723 }
11724
11725 /* This routine returns true if TYP is a valid objc object type, 
11726    suitable for messaging; false otherwise.
11727 */
11728
11729 static bool
11730 objc_type_valid_for_messaging (tree typ)
11731 {
11732   if (!POINTER_TYPE_P (typ))
11733     return false;
11734
11735   do
11736     typ = TREE_TYPE (typ);  /* Remove indirections.  */
11737   while (POINTER_TYPE_P (typ));
11738
11739   if (TREE_CODE (typ) != RECORD_TYPE)
11740     return false;
11741
11742   return objc_is_object_id (typ) || TYPE_HAS_OBJC_INFO (typ);
11743 }
11744
11745 /* Begin code generation for fast enumeration (foreach) ... */
11746
11747 /* Defines
11748
11749   struct __objcFastEnumerationState
11750    {
11751      unsigned long state;
11752      id            *itemsPtr;
11753      unsigned long *mutationsPtr;
11754      unsigned long extra[5];
11755    };
11756
11757    Confusingly enough, NSFastEnumeration is then defined by libraries
11758    to be the same structure.  
11759 */
11760
11761 static void
11762 build_fast_enumeration_state_template (void)
11763 {
11764   tree decls, *chain = NULL;
11765
11766   /* { */
11767   objc_fast_enumeration_state_template = objc_start_struct (get_identifier 
11768                                                             (TAG_FAST_ENUMERATION_STATE));
11769
11770   /* unsigned long state; */
11771   decls = add_field_decl (long_unsigned_type_node, "state", &chain);
11772
11773   /* id            *itemsPtr; */
11774   add_field_decl (build_pointer_type (objc_object_type), 
11775                   "itemsPtr", &chain);
11776
11777   /* unsigned long *mutationsPtr; */
11778   add_field_decl (build_pointer_type (long_unsigned_type_node), 
11779                   "mutationsPtr", &chain);
11780
11781   /* unsigned long extra[5]; */
11782   add_field_decl (build_sized_array_type (long_unsigned_type_node, 5), 
11783                   "extra", &chain);
11784
11785   /* } */
11786   objc_finish_struct (objc_fast_enumeration_state_template, decls);
11787 }
11788
11789 /*
11790   'objc_finish_foreach_loop()' generates the code for an Objective-C
11791   foreach loop.  The 'location' argument is the location of the 'for'
11792   that starts the loop.  The 'object_expression' is the expression of
11793   the 'object' that iterates; the 'collection_expression' is the
11794   expression of the collection that we iterate over (we need to make
11795   sure we evaluate this only once); the 'for_body' is the set of
11796   statements to be executed in each iteration; 'break_label' and
11797   'continue_label' are the break and continue labels which we need to
11798   emit since the <statements> may be jumping to 'break_label' (if they
11799   contain 'break') or to 'continue_label' (if they contain
11800   'continue').
11801
11802   The syntax is
11803   
11804   for (<object expression> in <collection expression>)
11805     <statements>
11806
11807   which is compiled into the following blurb:
11808
11809   {
11810     id __objc_foreach_collection;
11811     __objc_fast_enumeration_state __objc_foreach_enum_state;
11812     unsigned long __objc_foreach_batchsize;
11813     id __objc_foreach_items[16];
11814     __objc_foreach_collection = <collection expression>;
11815     __objc_foreach_enum_state = { 0 };
11816     __objc_foreach_batchsize = [__objc_foreach_collection countByEnumeratingWithState: &__objc_foreach_enum_state  objects: __objc_foreach_items  count: 16];
11817     
11818     if (__objc_foreach_batchsize == 0)
11819       <object expression> = nil;
11820     else
11821       {
11822         unsigned long __objc_foreach_mutations_pointer = *__objc_foreach_enum_state.mutationsPtr;
11823         next_batch:
11824           {
11825             unsigned long __objc_foreach_index;
11826             __objc_foreach_index = 0;
11827
11828             next_object:
11829             if (__objc_foreach_mutation_pointer != *__objc_foreach_enum_state.mutationsPtr) objc_enumeration_mutation (<collection expression>);
11830             <object expression> = enumState.itemsPtr[__objc_foreach_index];
11831             <statements> [PS: inside <statments>, 'break' jumps to break_label and 'continue' jumps to continue_label]
11832
11833             continue_label:
11834             __objc_foreach_index++;
11835             if (__objc_foreach_index < __objc_foreach_batchsize) goto next_object;
11836             __objc_foreach_batchsize = [__objc_foreach_collection countByEnumeratingWithState: &__objc_foreach_enum_state  objects: __objc_foreach_items  count: 16];
11837          }
11838        if (__objc_foreach_batchsize != 0) goto next_batch;
11839        <object expression> = nil;
11840        break_label:
11841       }
11842   }
11843
11844   'statements' may contain a 'continue' or 'break' instruction, which
11845   the user expects to 'continue' or 'break' the entire foreach loop.
11846   We are provided the labels that 'break' and 'continue' jump to, so
11847   we place them where we want them to jump to when they pick them.
11848   
11849   Optimization TODO: we could cache the IMP of
11850   countByEnumeratingWithState:objects:count:.
11851 */
11852
11853 /* If you need to debug objc_finish_foreach_loop(), uncomment the following line.  */
11854 /* #define DEBUG_OBJC_FINISH_FOREACH_LOOP 1 */
11855
11856 #ifdef DEBUG_OBJC_FINISH_FOREACH_LOOP
11857 #include "tree-pretty-print.h"
11858 #endif
11859
11860 void
11861 objc_finish_foreach_loop (location_t location, tree object_expression, tree collection_expression, tree for_body, 
11862                           tree break_label, tree continue_label)
11863 {
11864   /* A tree representing the __objcFastEnumerationState struct type,
11865      or NSFastEnumerationState struct, whatever we are using.  */
11866   tree objc_fast_enumeration_state_type;
11867
11868   /* The trees representing the declarations of each of the local variables.  */
11869   tree objc_foreach_collection_decl;
11870   tree objc_foreach_enum_state_decl;
11871   tree objc_foreach_items_decl;
11872   tree objc_foreach_batchsize_decl;
11873   tree objc_foreach_mutations_pointer_decl;
11874   tree objc_foreach_index_decl;
11875
11876   /* A tree representing the selector countByEnumeratingWithState:objects:count:.  */
11877   tree selector_name;
11878
11879   /* A tree representing the local bind.  */
11880   tree bind;
11881
11882   /* A tree representing the external 'if (__objc_foreach_batchsize)' */
11883   tree first_if;
11884
11885   /* A tree representing the 'else' part of 'first_if'  */
11886   tree first_else;
11887
11888   /* A tree representing the 'next_batch' label.  */
11889   tree next_batch_label_decl;
11890
11891   /* A tree representing the binding after the 'next_batch' label.  */
11892   tree next_batch_bind;
11893
11894   /* A tree representing the 'next_object' label.  */
11895   tree next_object_label_decl;
11896
11897   /* Temporary variables.  */
11898   tree t;
11899   int i;
11900
11901   if (object_expression == error_mark_node)
11902     return;
11903
11904   if (collection_expression == error_mark_node)
11905     return;
11906
11907   if (!objc_type_valid_for_messaging (TREE_TYPE (object_expression)))
11908     {
11909       error ("iterating variable in fast enumeration is not an object");
11910       return;
11911     }
11912
11913   if (!objc_type_valid_for_messaging (TREE_TYPE (collection_expression)))
11914     {
11915       error ("collection in fast enumeration is not an object");
11916       return;
11917     }
11918
11919   /* TODO: Check that object_expression is either a variable
11920      declaration, or an lvalue.  */
11921
11922   /* This kludge is an idea from apple.  We use the
11923      __objcFastEnumerationState struct implicitly defined by the
11924      compiler, unless a NSFastEnumerationState struct has been defined
11925      (by a Foundation library such as GNUstep Base) in which case, we
11926      use that one.
11927   */
11928   objc_fast_enumeration_state_type = objc_fast_enumeration_state_template;
11929   {
11930     tree objc_NSFastEnumeration_type = lookup_name (get_identifier ("NSFastEnumerationState"));
11931
11932     if (objc_NSFastEnumeration_type)
11933       {
11934         /* TODO: We really need to check that
11935            objc_NSFastEnumeration_type is the same as ours!  */
11936         if (TREE_CODE (objc_NSFastEnumeration_type) == TYPE_DECL)
11937           {
11938             /* If it's a typedef, use the original type.  */
11939             if (DECL_ORIGINAL_TYPE (objc_NSFastEnumeration_type))
11940               objc_fast_enumeration_state_type = DECL_ORIGINAL_TYPE (objc_NSFastEnumeration_type);
11941             else
11942               objc_fast_enumeration_state_type = TREE_TYPE (objc_NSFastEnumeration_type);             
11943           }
11944       }
11945   }
11946
11947   /* { */
11948   /* Done by c-parser.c.  */
11949
11950   /* type object; */
11951   /* Done by c-parser.c.  */
11952
11953   /*  id __objc_foreach_collection */
11954   objc_foreach_collection_decl = objc_create_temporary_var (objc_object_type, "__objc_foreach_collection");
11955
11956   /*  __objcFastEnumerationState __objc_foreach_enum_state; */
11957   objc_foreach_enum_state_decl = objc_create_temporary_var (objc_fast_enumeration_state_type, "__objc_foreach_enum_state");
11958   TREE_CHAIN (objc_foreach_enum_state_decl) = objc_foreach_collection_decl;
11959
11960   /* id __objc_foreach_items[16]; */
11961   objc_foreach_items_decl = objc_create_temporary_var (build_sized_array_type (objc_object_type, 16), "__objc_foreach_items");
11962   TREE_CHAIN (objc_foreach_items_decl) = objc_foreach_enum_state_decl;
11963
11964   /* unsigned long __objc_foreach_batchsize; */
11965   objc_foreach_batchsize_decl = objc_create_temporary_var (long_unsigned_type_node, "__objc_foreach_batchsize");
11966   TREE_CHAIN (objc_foreach_batchsize_decl) = objc_foreach_items_decl;
11967
11968   /* Generate the local variable binding.  */
11969   bind = build3 (BIND_EXPR, void_type_node, objc_foreach_batchsize_decl, NULL, NULL);
11970   SET_EXPR_LOCATION (bind, location);
11971   TREE_SIDE_EFFECTS (bind) = 1;
11972   
11973   /*  __objc_foreach_collection = <collection expression>; */
11974   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_collection_decl, collection_expression);
11975   SET_EXPR_LOCATION (t, location);
11976   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
11977
11978   /*  __objc_foreach_enum_state.state = 0; */
11979   t = build2 (MODIFY_EXPR, void_type_node, objc_build_component_ref (objc_foreach_enum_state_decl, 
11980                                                                      get_identifier ("state")),
11981               build_int_cst (long_unsigned_type_node, 0));
11982   SET_EXPR_LOCATION (t, location);
11983   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
11984
11985   /*  __objc_foreach_enum_state.itemsPtr = NULL; */
11986   t = build2 (MODIFY_EXPR, void_type_node, objc_build_component_ref (objc_foreach_enum_state_decl, 
11987                                                                      get_identifier ("itemsPtr")),
11988               null_pointer_node);
11989   SET_EXPR_LOCATION (t, location);
11990   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
11991
11992   /*  __objc_foreach_enum_state.mutationsPtr = NULL; */
11993   t = build2 (MODIFY_EXPR, void_type_node, objc_build_component_ref (objc_foreach_enum_state_decl, 
11994                                                                      get_identifier ("mutationsPtr")),
11995               null_pointer_node);
11996   SET_EXPR_LOCATION (t, location);
11997   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
11998
11999   /*  __objc_foreach_enum_state.extra[0] = 0; */
12000   /*  __objc_foreach_enum_state.extra[1] = 0; */
12001   /*  __objc_foreach_enum_state.extra[2] = 0; */
12002   /*  __objc_foreach_enum_state.extra[3] = 0; */
12003   /*  __objc_foreach_enum_state.extra[4] = 0; */
12004   for (i = 0; i < 5 ; i++)
12005     {
12006       t = build2 (MODIFY_EXPR, void_type_node,
12007                   build_array_ref (location, objc_build_component_ref (objc_foreach_enum_state_decl, 
12008                                                                        get_identifier ("extra")),
12009                                    build_int_cst (NULL_TREE, i)),
12010                   build_int_cst (long_unsigned_type_node, 0));
12011       SET_EXPR_LOCATION (t, location);
12012       append_to_statement_list (t, &BIND_EXPR_BODY (bind));
12013     }
12014     
12015   /* __objc_foreach_batchsize = [__objc_foreach_collection countByEnumeratingWithState: &__objc_foreach_enum_state  objects: __objc_foreach_items  count: 16]; */
12016   selector_name = get_identifier ("countByEnumeratingWithState:objects:count:");
12017 #ifdef OBJCPLUS
12018   t = objc_finish_message_expr (objc_foreach_collection_decl, selector_name,
12019                                 /* Parameters.  */
12020                                 tree_cons    /* &__objc_foreach_enum_state */
12021                                 (NULL_TREE, build_fold_addr_expr_loc (location, objc_foreach_enum_state_decl),
12022                                  tree_cons   /* __objc_foreach_items  */
12023                                  (NULL_TREE, objc_foreach_items_decl,
12024                                   tree_cons  /* 16 */
12025                                   (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))));
12026 #else
12027   /* In C, we need to decay the __objc_foreach_items array that we are passing.  */
12028   {
12029     struct c_expr array;
12030     array.value = objc_foreach_items_decl;
12031     t = objc_finish_message_expr (objc_foreach_collection_decl, selector_name,
12032                                   /* Parameters.  */
12033                                   tree_cons    /* &__objc_foreach_enum_state */
12034                                   (NULL_TREE, build_fold_addr_expr_loc (location, objc_foreach_enum_state_decl),
12035                                    tree_cons   /* __objc_foreach_items  */
12036                                    (NULL_TREE, default_function_array_conversion (location, array).value,
12037                                     tree_cons  /* 16 */
12038                                     (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))));
12039   }
12040 #endif
12041   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_batchsize_decl,
12042               convert (long_unsigned_type_node, t));
12043   SET_EXPR_LOCATION (t, location);
12044   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
12045
12046   /* if (__objc_foreach_batchsize == 0) */
12047   first_if = build3 (COND_EXPR, void_type_node, 
12048                      /* Condition.  */
12049                      c_fully_fold 
12050                      (c_common_truthvalue_conversion 
12051                       (location, 
12052                        build_binary_op (location,
12053                                         EQ_EXPR, 
12054                                         objc_foreach_batchsize_decl,
12055                                         build_int_cst (long_unsigned_type_node, 0), 1)),
12056                       false, NULL),
12057                      /* Then block (we fill it in later).  */
12058                      NULL_TREE,
12059                      /* Else block (we fill it in later).  */
12060                      NULL_TREE);
12061   SET_EXPR_LOCATION (first_if, location);
12062   append_to_statement_list (first_if, &BIND_EXPR_BODY (bind));
12063
12064   /* then <object expression> = nil; */
12065   t = build2 (MODIFY_EXPR, void_type_node, object_expression, convert (objc_object_type, null_pointer_node));
12066   SET_EXPR_LOCATION (t, location);
12067   COND_EXPR_THEN (first_if) = t;
12068
12069   /* Now we build the 'else' part of the if; once we finish building
12070      it, we attach it to first_if as the 'else' part.  */
12071
12072   /* else */
12073   /* { */
12074
12075   /* unsigned long __objc_foreach_mutations_pointer; */
12076   objc_foreach_mutations_pointer_decl = objc_create_temporary_var (long_unsigned_type_node, "__objc_foreach_mutations_pointer");
12077
12078   /* Generate the local variable binding.  */
12079   first_else = build3 (BIND_EXPR, void_type_node, objc_foreach_mutations_pointer_decl, NULL, NULL);
12080   SET_EXPR_LOCATION (first_else, location);
12081   TREE_SIDE_EFFECTS (first_else) = 1;
12082
12083   /* __objc_foreach_mutations_pointer = *__objc_foreach_enum_state.mutationsPtr; */
12084   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_mutations_pointer_decl, 
12085               build_indirect_ref (location, objc_build_component_ref (objc_foreach_enum_state_decl, 
12086                                                                       get_identifier ("mutationsPtr")),
12087                                   RO_UNARY_STAR));
12088   SET_EXPR_LOCATION (t, location);
12089   append_to_statement_list (t, &BIND_EXPR_BODY (first_else));
12090
12091   /* next_batch: */
12092   next_batch_label_decl = create_artificial_label (location);
12093   t = build1 (LABEL_EXPR, void_type_node, next_batch_label_decl); 
12094   SET_EXPR_LOCATION (t, location);
12095   append_to_statement_list (t, &BIND_EXPR_BODY (first_else));
12096   
12097   /* { */
12098
12099   /* unsigned long __objc_foreach_index; */
12100   objc_foreach_index_decl = objc_create_temporary_var (long_unsigned_type_node, "__objc_foreach_index");
12101
12102   /* Generate the local variable binding.  */
12103   next_batch_bind = build3 (BIND_EXPR, void_type_node, objc_foreach_index_decl, NULL, NULL);
12104   SET_EXPR_LOCATION (next_batch_bind, location);
12105   TREE_SIDE_EFFECTS (next_batch_bind) = 1;
12106   append_to_statement_list (next_batch_bind, &BIND_EXPR_BODY (first_else));
12107
12108   /* __objc_foreach_index = 0; */
12109   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_index_decl,
12110               build_int_cst (long_unsigned_type_node, 0));
12111   SET_EXPR_LOCATION (t, location);
12112   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12113
12114   /* next_object: */
12115   next_object_label_decl = create_artificial_label (location);
12116   t = build1 (LABEL_EXPR, void_type_node, next_object_label_decl);
12117   SET_EXPR_LOCATION (t, location);
12118   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12119
12120   /* if (__objc_foreach_mutation_pointer != *__objc_foreach_enum_state.mutationsPtr) objc_enumeration_mutation (<collection expression>); */
12121   t = build3 (COND_EXPR, void_type_node, 
12122               /* Condition.  */
12123               c_fully_fold 
12124               (c_common_truthvalue_conversion 
12125                (location, 
12126                 build_binary_op 
12127                 (location,
12128                  NE_EXPR, 
12129                  objc_foreach_mutations_pointer_decl,
12130                  build_indirect_ref (location, 
12131                                      objc_build_component_ref (objc_foreach_enum_state_decl, 
12132                                                                get_identifier ("mutationsPtr")),
12133                                      RO_UNARY_STAR), 1)),
12134                false, NULL),
12135               /* Then block.  */
12136               build_function_call (input_location,
12137                                    objc_enumeration_mutation_decl,
12138                                    tree_cons (NULL, collection_expression, NULL)),
12139               /* Else block.  */
12140               NULL_TREE);
12141   SET_EXPR_LOCATION (t, location);
12142   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12143
12144   /* <object expression> = enumState.itemsPtr[__objc_foreach_index]; */
12145   t = build2 (MODIFY_EXPR, void_type_node, object_expression, 
12146               build_array_ref (location, objc_build_component_ref (objc_foreach_enum_state_decl, 
12147                                                                    get_identifier ("itemsPtr")),
12148                                objc_foreach_index_decl));
12149   SET_EXPR_LOCATION (t, location);
12150   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12151
12152   /* <statements> [PS: in <statments>, 'break' jumps to break_label and 'continue' jumps to continue_label] */
12153   append_to_statement_list (for_body, &BIND_EXPR_BODY (next_batch_bind));
12154
12155   /* continue_label: */
12156   if (continue_label)
12157     {
12158       t = build1 (LABEL_EXPR, void_type_node, continue_label);
12159       SET_EXPR_LOCATION (t, location);
12160       append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12161     }
12162
12163   /* __objc_foreach_index++; */
12164   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_index_decl, 
12165               build_binary_op (location,
12166                                PLUS_EXPR,
12167                                objc_foreach_index_decl,
12168                                build_int_cst (long_unsigned_type_node, 1), 1));
12169   SET_EXPR_LOCATION (t, location);
12170   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12171
12172   /* if (__objc_foreach_index < __objc_foreach_batchsize) goto next_object; */
12173   t = build3 (COND_EXPR, void_type_node, 
12174               /* Condition.  */
12175               c_fully_fold 
12176               (c_common_truthvalue_conversion 
12177                (location, 
12178                 build_binary_op (location,
12179                                  LT_EXPR, 
12180                                  objc_foreach_index_decl,
12181                                  objc_foreach_batchsize_decl, 1)),
12182                false, NULL),
12183               /* Then block.  */
12184               build1 (GOTO_EXPR, void_type_node, next_object_label_decl),
12185               /* Else block.  */
12186               NULL_TREE);
12187   SET_EXPR_LOCATION (t, location);
12188   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12189   
12190   /* __objc_foreach_batchsize = [__objc_foreach_collection countByEnumeratingWithState: &__objc_foreach_enum_state  objects: __objc_foreach_items  count: 16]; */
12191 #ifdef OBJCPLUS
12192   t = objc_finish_message_expr (objc_foreach_collection_decl, selector_name,
12193                                 /* Parameters.  */
12194                                 tree_cons    /* &__objc_foreach_enum_state */
12195                                 (NULL_TREE, build_fold_addr_expr_loc (location, objc_foreach_enum_state_decl),
12196                                  tree_cons   /* __objc_foreach_items  */
12197                                  (NULL_TREE, objc_foreach_items_decl,
12198                                   tree_cons  /* 16 */
12199                                   (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))));
12200 #else
12201   /* In C, we need to decay the __objc_foreach_items array that we are passing.  */
12202   {
12203     struct c_expr array;
12204     array.value = objc_foreach_items_decl;
12205     t = objc_finish_message_expr (objc_foreach_collection_decl, selector_name,
12206                                   /* Parameters.  */
12207                                   tree_cons    /* &__objc_foreach_enum_state */
12208                                   (NULL_TREE, build_fold_addr_expr_loc (location, objc_foreach_enum_state_decl),
12209                                    tree_cons   /* __objc_foreach_items  */
12210                                    (NULL_TREE, default_function_array_conversion (location, array).value,
12211                                     tree_cons  /* 16 */
12212                                     (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))));
12213   }
12214 #endif
12215   t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_batchsize_decl, 
12216               convert (long_unsigned_type_node, t));
12217   SET_EXPR_LOCATION (t, location);
12218   append_to_statement_list (t, &BIND_EXPR_BODY (next_batch_bind));
12219
12220   /* } */
12221
12222   /* if (__objc_foreach_batchsize != 0) goto next_batch; */
12223   t = build3 (COND_EXPR, void_type_node, 
12224               /* Condition.  */
12225               c_fully_fold 
12226               (c_common_truthvalue_conversion 
12227                (location, 
12228                 build_binary_op (location,
12229                                  NE_EXPR, 
12230                                  objc_foreach_batchsize_decl,
12231                                  build_int_cst (long_unsigned_type_node, 0), 1)),
12232                false, NULL),
12233               /* Then block.  */
12234               build1 (GOTO_EXPR, void_type_node, next_batch_label_decl),
12235               /* Else block.  */
12236               NULL_TREE);
12237   SET_EXPR_LOCATION (t, location);
12238   append_to_statement_list (t, &BIND_EXPR_BODY (first_else));
12239
12240   /* <object expression> = nil; */
12241   t = build2 (MODIFY_EXPR, void_type_node, object_expression, convert (objc_object_type, null_pointer_node));
12242   SET_EXPR_LOCATION (t, location);
12243   append_to_statement_list (t, &BIND_EXPR_BODY (first_else));
12244
12245   /* break_label: */
12246   if (break_label)
12247     {
12248       t = build1 (LABEL_EXPR, void_type_node, break_label);
12249       SET_EXPR_LOCATION (t, location);
12250       append_to_statement_list (t, &BIND_EXPR_BODY (first_else));
12251     }
12252
12253   /* } */
12254   COND_EXPR_ELSE (first_if) = first_else;
12255
12256   /* Do the whole thing.  */
12257   add_stmt (bind);
12258
12259 #ifdef DEBUG_OBJC_FINISH_FOREACH_LOOP
12260   /* This will print to stderr the whole blurb generated by the
12261      compiler while compiling (assuming the compiler doesn't crash
12262      before getting here).
12263    */
12264   debug_generic_stmt (bind);
12265 #endif
12266
12267   /* } */
12268   /* Done by c-parser.c  */
12269 }
12270
12271 #include "gt-objc-objc-act.h"