OSDN Git Service

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