OSDN Git Service

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