OSDN Git Service

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