OSDN Git Service

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