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