OSDN Git Service

8b1a596c3237859e11c73906e42cf9870fee960b
[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 /* This hook, called via lang_eh_runtime_type, generates a runtime object
3487    that represents TYPE.  For Objective-C, this is just the class name.  */
3488 /* ??? Isn't there a class object or some such?  Is it easy to get?  */
3489
3490 #ifndef OBJCPLUS
3491 static tree
3492 objc_eh_runtime_type (tree type)
3493 {
3494   return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
3495 }
3496 #endif
3497
3498 /* Initialize exception handling.  */
3499
3500 static void
3501 objc_init_exceptions (void)
3502 {
3503   static bool done = false;
3504   if (done)
3505     return;
3506   done = true;
3507
3508   if (flag_objc_sjlj_exceptions)
3509     {
3510       /* On Darwin, ObjC exceptions require a sufficiently recent
3511          version of the runtime, so the user must ask for them explicitly.  */
3512       if (!flag_objc_exceptions)
3513         warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
3514                  "exception syntax");
3515     }
3516 #ifndef OBJCPLUS
3517   else
3518     {
3519       c_eh_initialized_p = true;
3520       eh_personality_libfunc
3521         = init_one_libfunc (USING_SJLJ_EXCEPTIONS
3522                             ? "__gnu_objc_personality_sj0"
3523                             : "__gnu_objc_personality_v0");
3524       default_init_unwind_resume_libfunc ();
3525       using_eh_for_cleanups ();
3526       lang_eh_runtime_type = objc_eh_runtime_type;
3527     }
3528 #endif
3529 }
3530
3531 /* Build an EXC_PTR_EXPR, or the moral equivalent.  In the case of Darwin,
3532    we'll arrange for it to be initialized (and associated with a binding)
3533    later.  */
3534
3535 static tree
3536 objc_build_exc_ptr (void)
3537 {
3538   if (flag_objc_sjlj_exceptions)
3539     {
3540       tree var = cur_try_context->caught_decl;
3541       if (!var)
3542         {
3543           var = objc_create_temporary_var (objc_object_type);
3544           cur_try_context->caught_decl = var;
3545         }
3546       return var;
3547     }
3548   else
3549     return build0 (EXC_PTR_EXPR, objc_object_type);
3550 }
3551
3552 /* Build "objc_exception_try_exit(&_stack)".  */
3553
3554 static tree
3555 next_sjlj_build_try_exit (void)
3556 {
3557   tree t;
3558   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
3559   t = tree_cons (NULL, t, NULL);
3560   t = build_function_call (input_location,
3561                            objc_exception_try_exit_decl, t);
3562   return t;
3563 }
3564
3565 /* Build
3566         objc_exception_try_enter (&_stack);
3567         if (_setjmp(&_stack.buf))
3568           ;
3569         else
3570           ;
3571    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
3572    empty, ready for the caller to fill them in.  */
3573
3574 static tree
3575 next_sjlj_build_enter_and_setjmp (void)
3576 {
3577   tree t, enter, sj, cond;
3578
3579   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
3580   t = tree_cons (NULL, t, NULL);
3581   enter = build_function_call (input_location,
3582                                objc_exception_try_enter_decl, t);
3583
3584   t = objc_build_component_ref (cur_try_context->stack_decl,
3585                                 get_identifier ("buf"));
3586   t = build_fold_addr_expr_loc (input_location, t);
3587 #ifdef OBJCPLUS
3588   /* Convert _setjmp argument to type that is expected.  */
3589   if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
3590     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
3591   else
3592     t = convert (ptr_type_node, t);
3593 #else
3594   t = convert (ptr_type_node, t);
3595 #endif
3596   t = tree_cons (NULL, t, NULL);
3597   sj = build_function_call (input_location,
3598                             objc_setjmp_decl, t);
3599
3600   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
3601   cond = c_common_truthvalue_conversion (input_location, cond);
3602
3603   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
3604 }
3605
3606 /* Build:
3607
3608    DECL = objc_exception_extract(&_stack);  */
3609
3610 static tree
3611 next_sjlj_build_exc_extract (tree decl)
3612 {
3613   tree t;
3614
3615   t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
3616   t = tree_cons (NULL, t, NULL);
3617   t = build_function_call (input_location,
3618                            objc_exception_extract_decl, t);
3619   t = convert (TREE_TYPE (decl), t);
3620   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
3621
3622   return t;
3623 }
3624
3625 /* Build
3626         if (objc_exception_match(obj_get_class(TYPE), _caught)
3627           BODY
3628         else if (...)
3629           ...
3630         else
3631           {
3632             _rethrow = _caught;
3633             objc_exception_try_exit(&_stack);
3634           }
3635    from the sequence of CATCH_EXPRs in the current try context.  */
3636
3637 static tree
3638 next_sjlj_build_catch_list (void)
3639 {
3640   tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3641   tree catch_seq, t;
3642   tree *last = &catch_seq;
3643   bool saw_id = false;
3644
3645   for (; !tsi_end_p (i); tsi_next (&i))
3646     {
3647       tree stmt = tsi_stmt (i);
3648       tree type = CATCH_TYPES (stmt);
3649       tree body = CATCH_BODY (stmt);
3650
3651       if (type == NULL)
3652         {
3653           *last = body;
3654           saw_id = true;
3655           break;
3656         }
3657       else
3658         {
3659           tree args, cond;
3660
3661           if (type == error_mark_node)
3662             cond = error_mark_node;
3663           else
3664             {
3665               args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
3666               t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
3667               args = tree_cons (NULL, t, args);
3668               t = build_function_call (input_location,
3669                                        objc_exception_match_decl, args);
3670               cond = c_common_truthvalue_conversion (input_location, t);
3671             }
3672           t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
3673           SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
3674
3675           *last = t;
3676           last = &COND_EXPR_ELSE (t);
3677         }
3678     }
3679
3680   if (!saw_id)
3681     {
3682       t = build2 (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
3683                   cur_try_context->caught_decl);
3684       SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3685       append_to_statement_list (t, last);
3686
3687       t = next_sjlj_build_try_exit ();
3688       SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3689       append_to_statement_list (t, last);
3690     }
3691
3692   return catch_seq;
3693 }
3694
3695 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
3696    exception handling.  We aim to build:
3697
3698         {
3699           struct _objc_exception_data _stack;
3700           id _rethrow = 0;
3701           try
3702             {
3703               objc_exception_try_enter (&_stack);
3704               if (_setjmp(&_stack.buf))
3705                 {
3706                   id _caught = objc_exception_extract(&_stack);
3707                   objc_exception_try_enter (&_stack);
3708                   if (_setjmp(&_stack.buf))
3709                     _rethrow = objc_exception_extract(&_stack);
3710                   else
3711                     CATCH-LIST
3712                 }
3713               else
3714                 TRY-BLOCK
3715             }
3716           finally
3717             {
3718               if (!_rethrow)
3719                 objc_exception_try_exit(&_stack);
3720               FINALLY-BLOCK
3721               if (_rethrow)
3722                 objc_exception_throw(_rethrow);
3723             }
3724         }
3725
3726    If CATCH-LIST is empty, we can omit all of the block containing
3727    "_caught" except for the setting of _rethrow.  Note the use of
3728    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
3729    but handles goto and other exits from the block.  */
3730
3731 static tree
3732 next_sjlj_build_try_catch_finally (void)
3733 {
3734   tree rethrow_decl, stack_decl, t;
3735   tree catch_seq, try_fin, bind;
3736
3737   /* Create the declarations involved.  */
3738   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3739   stack_decl = objc_create_temporary_var (t);
3740   cur_try_context->stack_decl = stack_decl;
3741
3742   rethrow_decl = objc_create_temporary_var (objc_object_type);
3743   cur_try_context->rethrow_decl = rethrow_decl;
3744   TREE_CHAIN (rethrow_decl) = stack_decl;
3745
3746   /* Build the outermost variable binding level.  */
3747   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
3748   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
3749   TREE_SIDE_EFFECTS (bind) = 1;
3750
3751   /* Initialize rethrow_decl.  */
3752   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
3753               convert (objc_object_type, null_pointer_node));
3754   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3755   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3756
3757   /* Build the outermost TRY_FINALLY_EXPR.  */
3758   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
3759   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
3760   TREE_SIDE_EFFECTS (try_fin) = 1;
3761   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
3762
3763   /* Create the complete catch sequence.  */
3764   if (cur_try_context->catch_list)
3765     {
3766       tree caught_decl = objc_build_exc_ptr ();
3767       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
3768       TREE_SIDE_EFFECTS (catch_seq) = 1;
3769
3770       t = next_sjlj_build_exc_extract (caught_decl);
3771       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3772
3773       t = next_sjlj_build_enter_and_setjmp ();
3774       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
3775       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
3776       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3777     }
3778   else
3779     catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
3780   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
3781
3782   /* Build the main register-and-try if statement.  */
3783   t = next_sjlj_build_enter_and_setjmp ();
3784   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3785   COND_EXPR_THEN (t) = catch_seq;
3786   COND_EXPR_ELSE (t) = cur_try_context->try_body;
3787   TREE_OPERAND (try_fin, 0) = t;
3788
3789   /* Build the complete FINALLY statement list.  */
3790   t = next_sjlj_build_try_exit ();
3791   t = build_stmt (input_location, COND_EXPR,
3792                   c_common_truthvalue_conversion 
3793                     (input_location, rethrow_decl),
3794                   NULL, t);
3795   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
3796   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3797
3798   append_to_statement_list (cur_try_context->finally_body,
3799                             &TREE_OPERAND (try_fin, 1));
3800
3801   t = tree_cons (NULL, rethrow_decl, NULL);
3802   t = build_function_call (input_location,
3803                            objc_exception_throw_decl, t);
3804   t = build_stmt (input_location, COND_EXPR,
3805                   c_common_truthvalue_conversion (input_location, 
3806                                                   rethrow_decl),
3807                   t, NULL);
3808   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
3809   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3810
3811   return bind;
3812 }
3813
3814 /* Called just after parsing the @try and its associated BODY.  We now
3815    must prepare for the tricky bits -- handling the catches and finally.  */
3816
3817 void
3818 objc_begin_try_stmt (location_t try_locus, tree body)
3819 {
3820   struct objc_try_context *c = XCNEW (struct objc_try_context);
3821   c->outer = cur_try_context;
3822   c->try_body = body;
3823   c->try_locus = try_locus;
3824   c->end_try_locus = input_location;
3825   cur_try_context = c;
3826
3827   objc_init_exceptions ();
3828
3829   if (flag_objc_sjlj_exceptions)
3830     objc_mark_locals_volatile (NULL);
3831 }
3832
3833 /* Called just after parsing "@catch (parm)".  Open a binding level,
3834    enter DECL into the binding level, and initialize it.  Leave the
3835    binding level open while the body of the compound statement is parsed.  */
3836
3837 void
3838 objc_begin_catch_clause (tree decl)
3839 {
3840   tree compound, type, t;
3841
3842   /* Begin a new scope that the entire catch clause will live in.  */
3843   compound = c_begin_compound_stmt (true);
3844
3845   /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL.  */
3846   decl = build_decl (input_location,
3847                      VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
3848   lang_hooks.decls.pushdecl (decl);
3849
3850   /* Since a decl is required here by syntax, don't warn if its unused.  */
3851   /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
3852      be what the previous objc implementation did.  */
3853   TREE_USED (decl) = 1;
3854
3855   /* Verify that the type of the catch is valid.  It must be a pointer
3856      to an Objective-C class, or "id" (which is catch-all).  */
3857   type = TREE_TYPE (decl);
3858
3859   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3860     type = NULL;
3861   else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3862     {
3863       error ("@catch parameter is not a known Objective-C class type");
3864       type = error_mark_node;
3865     }
3866   else if (cur_try_context->catch_list)
3867     {
3868       /* Examine previous @catch clauses and see if we've already
3869          caught the type in question.  */
3870       tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3871       for (; !tsi_end_p (i); tsi_next (&i))
3872         {
3873           tree stmt = tsi_stmt (i);
3874           t = CATCH_TYPES (stmt);
3875           if (t == error_mark_node)
3876             continue;
3877           if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
3878             {
3879               warning (0, "exception of type %<%T%> will be caught",
3880                        TREE_TYPE (type));
3881               warning_at  (EXPR_LOCATION (stmt), 0, "   by earlier handler for %<%T%>",
3882                            TREE_TYPE (t ? t : objc_object_type));
3883               break;
3884             }
3885         }
3886     }
3887
3888   /* Record the data for the catch in the try context so that we can
3889      finalize it later.  */
3890   t = build_stmt (input_location, CATCH_EXPR, type, compound);
3891   cur_try_context->current_catch = t;
3892
3893   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3894   t = objc_build_exc_ptr ();
3895   t = convert (TREE_TYPE (decl), t);
3896   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
3897   add_stmt (t);
3898 }
3899
3900 /* Called just after parsing the closing brace of a @catch clause.  Close
3901    the open binding level, and record a CATCH_EXPR for it.  */
3902
3903 void
3904 objc_finish_catch_clause (void)
3905 {
3906   tree c = cur_try_context->current_catch;
3907   cur_try_context->current_catch = NULL;
3908   cur_try_context->end_catch_locus = input_location;
3909
3910   CATCH_BODY (c) = c_end_compound_stmt (input_location, CATCH_BODY (c), 1);
3911   append_to_statement_list (c, &cur_try_context->catch_list);
3912 }
3913
3914 /* Called after parsing a @finally clause and its associated BODY.
3915    Record the body for later placement.  */
3916
3917 void
3918 objc_build_finally_clause (location_t finally_locus, tree body)
3919 {
3920   cur_try_context->finally_body = body;
3921   cur_try_context->finally_locus = finally_locus;
3922   cur_try_context->end_finally_locus = input_location;
3923 }
3924
3925 /* Called to finalize a @try construct.  */
3926
3927 tree
3928 objc_finish_try_stmt (void)
3929 {
3930   struct objc_try_context *c = cur_try_context;
3931   tree stmt;
3932
3933   if (c->catch_list == NULL && c->finally_body == NULL)
3934     error ("%<@try%> without %<@catch%> or %<@finally%>");
3935
3936   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
3937   if (flag_objc_sjlj_exceptions)
3938     {
3939       bool save = in_late_binary_op;
3940       in_late_binary_op = true;
3941       if (!cur_try_context->finally_body)
3942         {
3943           cur_try_context->finally_locus = input_location;
3944           cur_try_context->end_finally_locus = input_location;
3945         }
3946       stmt = next_sjlj_build_try_catch_finally ();
3947       in_late_binary_op = save;
3948     }
3949   else
3950     {
3951       /* Otherwise, nest the CATCH inside a FINALLY.  */
3952       stmt = c->try_body;
3953       if (c->catch_list)
3954         {
3955           stmt = build_stmt (input_location, TRY_CATCH_EXPR, stmt, c->catch_list);
3956           SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3957         }
3958       if (c->finally_body)
3959         {
3960           stmt = build_stmt (input_location, TRY_FINALLY_EXPR, stmt, c->finally_body);
3961           SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3962         }
3963     }
3964   add_stmt (stmt);
3965
3966   cur_try_context = c->outer;
3967   free (c);
3968   return stmt;
3969 }
3970
3971 tree
3972 objc_build_throw_stmt (location_t loc, tree throw_expr)
3973 {
3974   tree args;
3975
3976   objc_init_exceptions ();
3977
3978   if (throw_expr == NULL)
3979     {
3980       /* If we're not inside a @catch block, there is no "current
3981          exception" to be rethrown.  */
3982       if (cur_try_context == NULL
3983           || cur_try_context->current_catch == NULL)
3984         {
3985           error_at (loc, "%<@throw%> (rethrow) used outside of a @catch block");
3986           return NULL_TREE;
3987         }
3988
3989       /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3990          value that we get from the runtime.  */
3991       throw_expr = objc_build_exc_ptr ();
3992     }
3993
3994   /* A throw is just a call to the runtime throw function with the
3995      object as a parameter.  */
3996   args = tree_cons (NULL, throw_expr, NULL);
3997   return add_stmt (build_function_call (loc,
3998                                         objc_exception_throw_decl, args));
3999 }
4000
4001 tree
4002 objc_build_synchronized (location_t start_locus, tree mutex, tree body)
4003 {
4004   tree args, call;
4005
4006   /* First lock the mutex.  */
4007   mutex = save_expr (mutex);
4008   args = tree_cons (NULL, mutex, NULL);
4009   call = build_function_call (input_location,
4010                               objc_sync_enter_decl, args);
4011   SET_EXPR_LOCATION (call, start_locus);
4012   add_stmt (call);
4013
4014   /* Build the mutex unlock.  */
4015   args = tree_cons (NULL, mutex, NULL);
4016   call = build_function_call (input_location,
4017                               objc_sync_exit_decl, args);
4018   SET_EXPR_LOCATION (call, input_location);
4019
4020   /* Put the that and the body in a TRY_FINALLY.  */
4021   objc_begin_try_stmt (start_locus, body);
4022   objc_build_finally_clause (input_location, call);
4023   return objc_finish_try_stmt ();
4024 }
4025
4026 \f
4027 /* Predefine the following data type:
4028
4029    struct _objc_exception_data
4030    {
4031      int buf[OBJC_JBLEN];
4032      void *pointers[4];
4033    }; */
4034
4035 /* The following yuckiness should prevent users from having to #include
4036    <setjmp.h> in their code... */
4037
4038 /* Define to a harmless positive value so the below code doesn't die.  */
4039 #ifndef OBJC_JBLEN
4040 #define OBJC_JBLEN 18
4041 #endif
4042
4043 static void
4044 build_next_objc_exception_stuff (void)
4045 {
4046   tree field_decl, field_decl_chain, index, temp_type;
4047
4048   objc_exception_data_template
4049     = objc_start_struct (get_identifier (UTAG_EXCDATA));
4050
4051   /* int buf[OBJC_JBLEN]; */
4052
4053   index = build_index_type (build_int_cst (NULL_TREE, OBJC_JBLEN - 1));
4054   field_decl = create_field_decl (build_array_type (integer_type_node, index),
4055                                   "buf");
4056   field_decl_chain = field_decl;
4057
4058   /* void *pointers[4]; */
4059
4060   index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
4061   field_decl = create_field_decl (build_array_type (ptr_type_node, index),
4062                                   "pointers");
4063   chainon (field_decl_chain, field_decl);
4064
4065   objc_finish_struct (objc_exception_data_template, field_decl_chain);
4066
4067   /* int _setjmp(...); */
4068   /* If the user includes <setjmp.h>, this shall be superseded by
4069      'int _setjmp(jmp_buf);' */
4070   temp_type = build_function_type (integer_type_node, NULL_TREE);
4071   objc_setjmp_decl
4072     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4073
4074   /* id objc_exception_extract(struct _objc_exception_data *); */
4075   temp_type
4076     = build_function_type (objc_object_type,
4077                            tree_cons (NULL_TREE,
4078                                       build_pointer_type (objc_exception_data_template),
4079                                       OBJC_VOID_AT_END));
4080   objc_exception_extract_decl
4081     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
4082                             NULL_TREE);
4083   /* void objc_exception_try_enter(struct _objc_exception_data *); */
4084   /* void objc_exception_try_exit(struct _objc_exception_data *); */
4085   temp_type
4086     = build_function_type (void_type_node,
4087                            tree_cons (NULL_TREE,
4088                                       build_pointer_type (objc_exception_data_template),
4089                                       OBJC_VOID_AT_END));
4090   objc_exception_try_enter_decl
4091     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
4092                             NULL_TREE);
4093   objc_exception_try_exit_decl
4094     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
4095                             NULL_TREE);
4096
4097   /* int objc_exception_match(id, id); */
4098   temp_type
4099     = build_function_type (integer_type_node,
4100                            tree_cons (NULL_TREE, objc_object_type,
4101                                       tree_cons (NULL_TREE, objc_object_type,
4102                                                  OBJC_VOID_AT_END)));
4103   objc_exception_match_decl
4104     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
4105                             NULL_TREE);
4106
4107   /* id objc_assign_ivar (id, id, unsigned int); */
4108   /* id objc_assign_ivar_Fast (id, id, unsigned int)
4109        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
4110   temp_type
4111     = build_function_type (objc_object_type,
4112                            tree_cons
4113                            (NULL_TREE, objc_object_type,
4114                             tree_cons (NULL_TREE, objc_object_type,
4115                                        tree_cons (NULL_TREE,
4116                                                   unsigned_type_node,
4117                                                   OBJC_VOID_AT_END))));
4118   objc_assign_ivar_decl
4119     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
4120                             NULL, NULL_TREE);
4121 #ifdef OFFS_ASSIGNIVAR_FAST
4122   objc_assign_ivar_fast_decl
4123     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
4124                             NOT_BUILT_IN, NULL, NULL_TREE);
4125   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
4126     = tree_cons (get_identifier ("hard_coded_address"),
4127                  build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
4128                  NULL_TREE);
4129 #else
4130   /* Default to slower ivar method.  */
4131   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
4132 #endif
4133
4134   /* id objc_assign_global (id, id *); */
4135   /* id objc_assign_strongCast (id, id *); */
4136   temp_type = build_function_type (objc_object_type,
4137                 tree_cons (NULL_TREE, objc_object_type,
4138                     tree_cons (NULL_TREE, build_pointer_type (objc_object_type),
4139                         OBJC_VOID_AT_END)));
4140   objc_assign_global_decl
4141         = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
4142                                 NULL_TREE);
4143   objc_assign_strong_cast_decl
4144         = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
4145                                 NULL_TREE);
4146 }
4147
4148 static void
4149 build_objc_exception_stuff (void)
4150 {
4151   tree noreturn_list, nothrow_list, temp_type;
4152
4153   noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
4154   nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
4155
4156   /* void objc_exception_throw(id) __attribute__((noreturn)); */
4157   /* void objc_sync_enter(id); */
4158   /* void objc_sync_exit(id); */
4159   temp_type = build_function_type (void_type_node,
4160                                    tree_cons (NULL_TREE, objc_object_type,
4161                                               OBJC_VOID_AT_END));
4162   objc_exception_throw_decl
4163     = add_builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
4164                             noreturn_list);
4165   objc_sync_enter_decl
4166     = add_builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
4167                             NULL, nothrow_list);
4168   objc_sync_exit_decl
4169     = add_builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
4170                             NULL, nothrow_list);
4171 }
4172
4173 /* Construct a C struct corresponding to ObjC class CLASS, with the same
4174    name as the class:
4175
4176    struct <classname> {
4177      struct _objc_class *isa;
4178      ...
4179    };  */
4180
4181 static void
4182 build_private_template (tree klass)
4183 {
4184   if (!CLASS_STATIC_TEMPLATE (klass))
4185     {
4186       tree record = objc_build_struct (klass,
4187                                        get_class_ivars (klass, false),
4188                                        CLASS_SUPER_NAME (klass));
4189
4190       /* Set the TREE_USED bit for this struct, so that stab generator
4191          can emit stabs for this struct type.  */
4192       if (flag_debug_only_used_symbols && TYPE_STUB_DECL (record))
4193         TREE_USED (TYPE_STUB_DECL (record)) = 1;
4194     }
4195 }
4196 \f
4197 /* Begin code generation for protocols...  */
4198
4199 /* struct _objc_protocol {
4200      struct _objc_class *isa;
4201      char *protocol_name;
4202      struct _objc_protocol **protocol_list;
4203      struct _objc__method_prototype_list *instance_methods;
4204      struct _objc__method_prototype_list *class_methods;
4205    };  */
4206
4207 static void
4208 build_protocol_template (void)
4209 {
4210   tree field_decl, field_decl_chain;
4211
4212   objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
4213
4214   /* struct _objc_class *isa; */
4215   field_decl = create_field_decl (build_pointer_type
4216                                   (xref_tag (RECORD_TYPE,
4217                                              get_identifier (UTAG_CLASS))),
4218                                   "isa");
4219   field_decl_chain = field_decl;
4220
4221   /* char *protocol_name; */
4222   field_decl = create_field_decl (string_type_node, "protocol_name");
4223   chainon (field_decl_chain, field_decl);
4224
4225   /* struct _objc_protocol **protocol_list; */
4226   field_decl = create_field_decl (build_pointer_type
4227                                   (build_pointer_type
4228                                    (objc_protocol_template)),
4229                                   "protocol_list");
4230   chainon (field_decl_chain, field_decl);
4231
4232   /* struct _objc__method_prototype_list *instance_methods; */
4233   field_decl = create_field_decl (objc_method_proto_list_ptr,
4234                                   "instance_methods");
4235   chainon (field_decl_chain, field_decl);
4236
4237   /* struct _objc__method_prototype_list *class_methods; */
4238   field_decl = create_field_decl (objc_method_proto_list_ptr,
4239                                   "class_methods");
4240   chainon (field_decl_chain, field_decl);
4241
4242   objc_finish_struct (objc_protocol_template, field_decl_chain);
4243 }
4244
4245 static tree
4246 build_descriptor_table_initializer (tree type, tree entries)
4247 {
4248   tree initlist = NULL_TREE;
4249
4250   do
4251     {
4252       tree eltlist = NULL_TREE;
4253
4254       eltlist
4255         = tree_cons (NULL_TREE,
4256                      build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
4257       eltlist
4258         = tree_cons (NULL_TREE,
4259                      add_objc_string (METHOD_ENCODING (entries),
4260                                       meth_var_types),
4261                      eltlist);
4262
4263       initlist
4264         = tree_cons (NULL_TREE,
4265                      objc_build_constructor (type, nreverse (eltlist)),
4266                      initlist);
4267
4268       entries = TREE_CHAIN (entries);
4269     }
4270   while (entries);
4271
4272   return objc_build_constructor (build_array_type (type, 0),
4273                                  nreverse (initlist));
4274 }
4275
4276 /* struct objc_method_prototype_list {
4277      int count;
4278      struct objc_method_prototype {
4279         SEL name;
4280         char *types;
4281      } list[1];
4282    };  */
4283
4284 static tree
4285 build_method_prototype_list_template (tree list_type, int size)
4286 {
4287   tree objc_ivar_list_record;
4288   tree field_decl, field_decl_chain;
4289
4290   /* Generate an unnamed struct definition.  */
4291
4292   objc_ivar_list_record = objc_start_struct (NULL_TREE);
4293
4294   /* int method_count; */
4295   field_decl = create_field_decl (integer_type_node, "method_count");
4296   field_decl_chain = field_decl;
4297
4298   /* struct objc_method method_list[]; */
4299   field_decl = create_field_decl (build_array_type
4300                                   (list_type,
4301                                    build_index_type
4302                                    (build_int_cst (NULL_TREE, size - 1))),
4303                                   "method_list");
4304   chainon (field_decl_chain, field_decl);
4305
4306   objc_finish_struct (objc_ivar_list_record, field_decl_chain);
4307
4308   return objc_ivar_list_record;
4309 }
4310
4311 static tree
4312 build_method_prototype_template (void)
4313 {
4314   tree proto_record;
4315   tree field_decl, field_decl_chain;
4316
4317   proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
4318
4319   /* SEL _cmd; */
4320   field_decl = create_field_decl (objc_selector_type, "_cmd");
4321   field_decl_chain = field_decl;
4322
4323   /* char *method_types; */
4324   field_decl = create_field_decl (string_type_node, "method_types");
4325   chainon (field_decl_chain, field_decl);
4326
4327   objc_finish_struct (proto_record, field_decl_chain);
4328
4329   return proto_record;
4330 }
4331
4332 static tree
4333 objc_method_parm_type (tree type)
4334 {
4335   type = TREE_VALUE (TREE_TYPE (type));
4336   if (TREE_CODE (type) == TYPE_DECL)
4337     type = TREE_TYPE (type);
4338   return type;
4339 }
4340
4341 static int
4342 objc_encoded_type_size (tree type)
4343 {
4344   int sz = int_size_in_bytes (type);
4345
4346   /* Make all integer and enum types at least as large
4347      as an int.  */
4348   if (sz > 0 && INTEGRAL_TYPE_P (type))
4349     sz = MAX (sz, int_size_in_bytes (integer_type_node));
4350   /* Treat arrays as pointers, since that's how they're
4351      passed in.  */
4352   else if (TREE_CODE (type) == ARRAY_TYPE)
4353     sz = int_size_in_bytes (ptr_type_node);
4354   return sz;
4355 }
4356
4357 static tree
4358 encode_method_prototype (tree method_decl)
4359 {
4360   tree parms;
4361   int parm_offset, i;
4362   char buf[40];
4363   tree result;
4364
4365   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
4366   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
4367
4368   /* Encode return type.  */
4369   encode_type (objc_method_parm_type (method_decl),
4370                obstack_object_size (&util_obstack),
4371                OBJC_ENCODE_INLINE_DEFS);
4372
4373   /* Stack size.  */
4374   /* The first two arguments (self and _cmd) are pointers; account for
4375      their size.  */
4376   i = int_size_in_bytes (ptr_type_node);
4377   parm_offset = 2 * i;
4378   for (parms = METHOD_SEL_ARGS (method_decl); parms;
4379        parms = TREE_CHAIN (parms))
4380     {
4381       tree type = objc_method_parm_type (parms);
4382       int sz = objc_encoded_type_size (type);
4383
4384       /* If a type size is not known, bail out.  */
4385       if (sz < 0)
4386         {
4387           error ("type %q+D does not have a known size",
4388                  type);
4389           /* Pretend that the encoding succeeded; the compilation will
4390              fail nevertheless.  */
4391           goto finish_encoding;
4392         }
4393       parm_offset += sz;
4394     }
4395
4396   sprintf (buf, "%d@0:%d", parm_offset, i);
4397   obstack_grow (&util_obstack, buf, strlen (buf));
4398
4399   /* Argument types.  */
4400   parm_offset = 2 * i;
4401   for (parms = METHOD_SEL_ARGS (method_decl); parms;
4402        parms = TREE_CHAIN (parms))
4403     {
4404       tree type = objc_method_parm_type (parms);
4405
4406       /* Process argument qualifiers for user supplied arguments.  */
4407       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
4408
4409       /* Type.  */
4410       encode_type (type, obstack_object_size (&util_obstack),
4411                    OBJC_ENCODE_INLINE_DEFS);
4412
4413       /* Compute offset.  */
4414       sprintf (buf, "%d", parm_offset);
4415       parm_offset += objc_encoded_type_size (type);
4416
4417       obstack_grow (&util_obstack, buf, strlen (buf));
4418     }
4419
4420   finish_encoding:
4421   obstack_1grow (&util_obstack, '\0');
4422   result = get_identifier (XOBFINISH (&util_obstack, char *));
4423   obstack_free (&util_obstack, util_firstobj);
4424   return result;
4425 }
4426
4427 static tree
4428 generate_descriptor_table (tree type, const char *name, int size, tree list,
4429                            tree proto)
4430 {
4431   tree decl, initlist;
4432
4433   decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
4434
4435   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
4436   initlist = tree_cons (NULL_TREE, list, initlist);
4437
4438   finish_var_decl (decl, objc_build_constructor (type, nreverse (initlist)));
4439
4440   return decl;
4441 }
4442
4443 static void
4444 generate_method_descriptors (tree protocol)
4445 {
4446   tree initlist, chain, method_list_template;
4447   int size;
4448
4449   if (!objc_method_prototype_template)
4450     objc_method_prototype_template = build_method_prototype_template ();
4451
4452   chain = PROTOCOL_CLS_METHODS (protocol);
4453   if (chain)
4454     {
4455       size = list_length (chain);
4456
4457       method_list_template
4458         = build_method_prototype_list_template (objc_method_prototype_template,
4459                                                 size);
4460
4461       initlist
4462         = build_descriptor_table_initializer (objc_method_prototype_template,
4463                                               chain);
4464
4465       UOBJC_CLASS_METHODS_decl
4466         = generate_descriptor_table (method_list_template,
4467                                      "_OBJC_PROTOCOL_CLASS_METHODS",
4468                                      size, initlist, protocol);
4469     }
4470   else
4471     UOBJC_CLASS_METHODS_decl = 0;
4472
4473   chain = PROTOCOL_NST_METHODS (protocol);
4474   if (chain)
4475     {
4476       size = list_length (chain);
4477
4478       method_list_template
4479         = build_method_prototype_list_template (objc_method_prototype_template,
4480                                                 size);
4481       initlist
4482         = build_descriptor_table_initializer (objc_method_prototype_template,
4483                                               chain);
4484
4485       UOBJC_INSTANCE_METHODS_decl
4486         = generate_descriptor_table (method_list_template,
4487                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
4488                                      size, initlist, protocol);
4489     }
4490   else
4491     UOBJC_INSTANCE_METHODS_decl = 0;
4492 }
4493
4494 static void
4495 generate_protocol_references (tree plist)
4496 {
4497   tree lproto;
4498
4499   /* Forward declare protocols referenced.  */
4500   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4501     {
4502       tree proto = TREE_VALUE (lproto);
4503
4504       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
4505           && PROTOCOL_NAME (proto))
4506         {
4507           if (! PROTOCOL_FORWARD_DECL (proto))
4508             build_protocol_reference (proto);
4509
4510           if (PROTOCOL_LIST (proto))
4511             generate_protocol_references (PROTOCOL_LIST (proto));
4512         }
4513     }
4514 }
4515
4516 /* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
4517    current class.  */
4518 #ifdef OBJCPLUS
4519 static void
4520 objc_generate_cxx_ctor_or_dtor (bool dtor)
4521 {
4522   tree fn, body, compound_stmt, ivar;
4523
4524   /* - (id) .cxx_construct { ... return self; } */
4525   /* - (void) .cxx_construct { ... }            */
4526
4527   objc_set_method_type (MINUS_EXPR);
4528   objc_start_method_definition
4529    (objc_build_method_signature (build_tree_list (NULL_TREE,
4530                                                   dtor
4531                                                   ? void_type_node
4532                                                   : objc_object_type),
4533                                  get_identifier (dtor
4534                                                  ? TAG_CXX_DESTRUCT
4535                                                  : TAG_CXX_CONSTRUCT),
4536                                  make_node (TREE_LIST),
4537                                  false));
4538   body = begin_function_body ();
4539   compound_stmt = begin_compound_stmt (0);
4540
4541   ivar = CLASS_IVARS (implementation_template);
4542   /* Destroy ivars in reverse order.  */
4543   if (dtor)
4544     ivar = nreverse (copy_list (ivar));
4545
4546   for (; ivar; ivar = TREE_CHAIN (ivar))
4547     {
4548       if (TREE_CODE (ivar) == FIELD_DECL)
4549         {
4550           tree type = TREE_TYPE (ivar);
4551
4552           /* Call the ivar's default constructor or destructor.  Do not
4553              call the destructor unless a corresponding constructor call
4554              has also been made (or is not needed).  */
4555           if (MAYBE_CLASS_TYPE_P (type)
4556               && (dtor
4557                   ? (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
4558                      && (!TYPE_NEEDS_CONSTRUCTING (type)
4559                          || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
4560                   : (TYPE_NEEDS_CONSTRUCTING (type)
4561                      && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))))
4562             finish_expr_stmt
4563              (build_special_member_call
4564               (build_ivar_reference (DECL_NAME (ivar)),
4565                dtor ? complete_dtor_identifier : complete_ctor_identifier,
4566                NULL, type, LOOKUP_NORMAL, tf_warning_or_error));
4567         }
4568     }
4569
4570   /* The constructor returns 'self'.  */
4571   if (!dtor)
4572     finish_return_stmt (self_decl);
4573
4574   finish_compound_stmt (compound_stmt);
4575   finish_function_body (body);
4576   fn = current_function_decl;
4577   finish_function ();
4578   objc_finish_method_definition (fn);
4579 }
4580
4581 /* The following routine will examine the current @interface for any
4582    non-POD C++ ivars requiring non-trivial construction and/or
4583    destruction, and then synthesize special '- .cxx_construct' and/or
4584    '- .cxx_destruct' methods which will run the appropriate
4585    construction or destruction code.  Note that ivars inherited from
4586    super-classes are _not_ considered.  */
4587 static void
4588 objc_generate_cxx_cdtors (void)
4589 {
4590   bool need_ctor = false, need_dtor = false;
4591   tree ivar;
4592
4593   /* We do not want to do this for categories, since they do not have
4594      their own ivars.  */
4595
4596   if (TREE_CODE (objc_implementation_context) != CLASS_IMPLEMENTATION_TYPE)
4597     return;
4598
4599   /* First, determine if we even need a constructor and/or destructor.  */
4600
4601   for (ivar = CLASS_IVARS (implementation_template); ivar;
4602        ivar = TREE_CHAIN (ivar))
4603     {
4604       if (TREE_CODE (ivar) == FIELD_DECL)
4605         {
4606           tree type = TREE_TYPE (ivar);
4607
4608           if (MAYBE_CLASS_TYPE_P (type))
4609             {
4610               if (TYPE_NEEDS_CONSTRUCTING (type)
4611                   && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
4612                 /* NB: If a default constructor is not available, we will not
4613                    be able to initialize this ivar; the add_instance_variable()
4614                    routine will already have warned about this.  */
4615                 need_ctor = true;
4616
4617               if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
4618                   && (!TYPE_NEEDS_CONSTRUCTING (type)
4619                       || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
4620                 /* NB: If a default constructor is not available, we will not
4621                    call the destructor either, for symmetry.  */
4622                 need_dtor = true;
4623             }
4624         }
4625     }
4626
4627   /* Generate '- .cxx_construct' if needed.  */
4628
4629   if (need_ctor)
4630     objc_generate_cxx_ctor_or_dtor (false);
4631
4632   /* Generate '- .cxx_destruct' if needed.  */
4633
4634   if (need_dtor)
4635     objc_generate_cxx_ctor_or_dtor (true);
4636
4637   /* The 'imp_list' variable points at an imp_entry record for the current
4638      @implementation.  Record the existence of '- .cxx_construct' and/or
4639      '- .cxx_destruct' methods therein; it will be included in the
4640      metadata for the class.  */
4641   if (flag_next_runtime)
4642     imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
4643 }
4644 #endif
4645
4646 /* For each protocol which was referenced either from a @protocol()
4647    expression, or because a class/category implements it (then a
4648    pointer to the protocol is stored in the struct describing the
4649    class/category), we create a statically allocated instance of the
4650    Protocol class.  The code is written in such a way as to generate
4651    as few Protocol objects as possible; we generate a unique Protocol
4652    instance for each protocol, and we don't generate a Protocol
4653    instance if the protocol is never referenced (either from a
4654    @protocol() or from a class/category implementation).  These
4655    statically allocated objects can be referred to via the static
4656    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
4657
4658    The statically allocated Protocol objects that we generate here
4659    need to be fixed up at runtime in order to be used: the 'isa'
4660    pointer of the objects need to be set up to point to the 'Protocol'
4661    class, as known at runtime.
4662
4663    The NeXT runtime fixes up all protocols at program startup time,
4664    before main() is entered.  It uses a low-level trick to look up all
4665    those symbols, then loops on them and fixes them up.
4666
4667    The GNU runtime as well fixes up all protocols before user code
4668    from the module is executed; it requires pointers to those symbols
4669    to be put in the objc_symtab (which is then passed as argument to
4670    the function __objc_exec_class() which the compiler sets up to be
4671    executed automatically when the module is loaded); setup of those
4672    Protocol objects happen in two ways in the GNU runtime: all
4673    Protocol objects referred to by a class or category implementation
4674    are fixed up when the class/category is loaded; all Protocol
4675    objects referred to by a @protocol() expression are added by the
4676    compiler to the list of statically allocated instances to fixup
4677    (the same list holding the statically allocated constant string
4678    objects).  Because, as explained above, the compiler generates as
4679    few Protocol objects as possible, some Protocol object might end up
4680    being referenced multiple times when compiled with the GNU runtime,
4681    and end up being fixed up multiple times at runtime initialization.
4682    But that doesn't hurt, it's just a little inefficient.  */
4683
4684 static void
4685 generate_protocols (void)
4686 {
4687   tree p, encoding;
4688   tree decl;
4689   tree initlist, protocol_name_expr, refs_decl, refs_expr;
4690
4691   /* If a protocol was directly referenced, pull in indirect references.  */
4692   for (p = protocol_chain; p; p = TREE_CHAIN (p))
4693     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
4694       generate_protocol_references (PROTOCOL_LIST (p));
4695
4696   for (p = protocol_chain; p; p = TREE_CHAIN (p))
4697     {
4698       tree nst_methods = PROTOCOL_NST_METHODS (p);
4699       tree cls_methods = PROTOCOL_CLS_METHODS (p);
4700
4701       /* If protocol wasn't referenced, don't generate any code.  */
4702       decl = PROTOCOL_FORWARD_DECL (p);
4703
4704       if (!decl)
4705         continue;
4706
4707       /* Make sure we link in the Protocol class.  */
4708       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
4709
4710       while (nst_methods)
4711         {
4712           if (! METHOD_ENCODING (nst_methods))
4713             {
4714               encoding = encode_method_prototype (nst_methods);
4715               METHOD_ENCODING (nst_methods) = encoding;
4716             }
4717           nst_methods = TREE_CHAIN (nst_methods);
4718         }
4719
4720       while (cls_methods)
4721         {
4722           if (! METHOD_ENCODING (cls_methods))
4723             {
4724               encoding = encode_method_prototype (cls_methods);
4725               METHOD_ENCODING (cls_methods) = encoding;
4726             }
4727
4728           cls_methods = TREE_CHAIN (cls_methods);
4729         }
4730       generate_method_descriptors (p);
4731
4732       if (PROTOCOL_LIST (p))
4733         refs_decl = generate_protocol_list (p);
4734       else
4735         refs_decl = 0;
4736
4737       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
4738       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
4739
4740       if (refs_decl)
4741         refs_expr = convert (build_pointer_type (build_pointer_type
4742                                                  (objc_protocol_template)),
4743                              build_unary_op (input_location,
4744                                              ADDR_EXPR, refs_decl, 0));
4745       else
4746         refs_expr = build_int_cst (NULL_TREE, 0);
4747
4748       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
4749          by generate_method_descriptors, which is called above.  */
4750       initlist = build_protocol_initializer (TREE_TYPE (decl),
4751                                              protocol_name_expr, refs_expr,
4752                                              UOBJC_INSTANCE_METHODS_decl,
4753                                              UOBJC_CLASS_METHODS_decl);
4754       finish_var_decl (decl, initlist);
4755     }
4756 }
4757
4758 static tree
4759 build_protocol_initializer (tree type, tree protocol_name,
4760                             tree protocol_list, tree instance_methods,
4761                             tree class_methods)
4762 {
4763   tree initlist = NULL_TREE, expr;
4764   tree cast_type = build_pointer_type
4765                    (xref_tag (RECORD_TYPE,
4766                               get_identifier (UTAG_CLASS)));
4767
4768   /* Filling the "isa" in with one allows the runtime system to
4769      detect that the version change...should remove before final release.  */
4770
4771   expr = build_int_cst (cast_type, PROTOCOL_VERSION);
4772   initlist = tree_cons (NULL_TREE, expr, initlist);
4773   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
4774   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
4775
4776   if (!instance_methods)
4777     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4778   else
4779     {
4780       expr = convert (objc_method_proto_list_ptr,
4781                       build_unary_op (input_location, 
4782                                       ADDR_EXPR, instance_methods, 0));
4783       initlist = tree_cons (NULL_TREE, expr, initlist);
4784     }
4785
4786   if (!class_methods)
4787     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4788   else
4789     {
4790       expr = convert (objc_method_proto_list_ptr,
4791                       build_unary_op (input_location, 
4792                                       ADDR_EXPR, class_methods, 0));
4793       initlist = tree_cons (NULL_TREE, expr, initlist);
4794     }
4795
4796   return objc_build_constructor (type, nreverse (initlist));
4797 }
4798 \f
4799 /* struct _objc_category {
4800      char *category_name;
4801      char *class_name;
4802      struct _objc_method_list *instance_methods;
4803      struct _objc_method_list *class_methods;
4804      struct _objc_protocol_list *protocols;
4805    };   */
4806
4807 static void
4808 build_category_template (void)
4809 {
4810   tree field_decl, field_decl_chain;
4811
4812   objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
4813
4814   /* char *category_name; */
4815   field_decl = create_field_decl (string_type_node, "category_name");
4816   field_decl_chain = field_decl;
4817
4818   /* char *class_name; */
4819   field_decl = create_field_decl (string_type_node, "class_name");
4820   chainon (field_decl_chain, field_decl);
4821
4822   /* struct _objc_method_list *instance_methods; */
4823   field_decl = create_field_decl (objc_method_list_ptr,
4824                                   "instance_methods");
4825   chainon (field_decl_chain, field_decl);
4826
4827   /* struct _objc_method_list *class_methods; */
4828   field_decl = create_field_decl (objc_method_list_ptr,
4829                                   "class_methods");
4830   chainon (field_decl_chain, field_decl);
4831
4832   /* struct _objc_protocol **protocol_list; */
4833   field_decl = create_field_decl (build_pointer_type
4834                                   (build_pointer_type
4835                                    (objc_protocol_template)),
4836                                   "protocol_list");
4837   chainon (field_decl_chain, field_decl);
4838
4839   objc_finish_struct (objc_category_template, field_decl_chain);
4840 }
4841
4842 /* struct _objc_selector {
4843      SEL sel_id;
4844      char *sel_type;
4845    }; */
4846
4847 static void
4848 build_selector_template (void)
4849 {
4850   tree field_decl, field_decl_chain;
4851
4852   objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
4853
4854   /* SEL sel_id; */
4855   field_decl = create_field_decl (objc_selector_type, "sel_id");
4856   field_decl_chain = field_decl;
4857
4858   /* char *sel_type; */
4859   field_decl = create_field_decl (string_type_node, "sel_type");
4860   chainon (field_decl_chain, field_decl);
4861
4862   objc_finish_struct (objc_selector_template, field_decl_chain);
4863 }
4864
4865 /* struct _objc_class {
4866      struct _objc_class *isa;
4867      struct _objc_class *super_class;
4868      char *name;
4869      long version;
4870      long info;
4871      long instance_size;
4872      struct _objc_ivar_list *ivars;
4873      struct _objc_method_list *methods;
4874      #ifdef __NEXT_RUNTIME__
4875        struct objc_cache *cache;
4876      #else
4877        struct sarray *dtable;
4878        struct _objc_class *subclass_list;
4879        struct _objc_class *sibling_class;
4880      #endif
4881      struct _objc_protocol_list *protocols;
4882      #ifdef __NEXT_RUNTIME__
4883        void *sel_id;
4884      #endif
4885      void *gc_object_type;
4886    };  */
4887
4888 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4889    the NeXT/Apple runtime; still, the compiler must generate them to
4890    maintain backward binary compatibility (and to allow for future
4891    expansion).  */
4892
4893 static void
4894 build_class_template (void)
4895 {
4896   tree field_decl, field_decl_chain;
4897
4898   objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
4899
4900   /* struct _objc_class *isa; */
4901   field_decl = create_field_decl (build_pointer_type (objc_class_template),
4902                                   "isa");
4903   field_decl_chain = field_decl;
4904
4905   /* struct _objc_class *super_class; */
4906   field_decl = create_field_decl (build_pointer_type (objc_class_template),
4907                                   "super_class");
4908   chainon (field_decl_chain, field_decl);
4909
4910   /* char *name; */
4911   field_decl = create_field_decl (string_type_node, "name");
4912   chainon (field_decl_chain, field_decl);
4913
4914   /* long version; */
4915   field_decl = create_field_decl (long_integer_type_node, "version");
4916   chainon (field_decl_chain, field_decl);
4917
4918   /* long info; */
4919   field_decl = create_field_decl (long_integer_type_node, "info");
4920   chainon (field_decl_chain, field_decl);
4921
4922   /* long instance_size; */
4923   field_decl = create_field_decl (long_integer_type_node, "instance_size");
4924   chainon (field_decl_chain, field_decl);
4925
4926   /* struct _objc_ivar_list *ivars; */
4927   field_decl = create_field_decl (objc_ivar_list_ptr,
4928                                   "ivars");
4929   chainon (field_decl_chain, field_decl);
4930
4931   /* struct _objc_method_list *methods; */
4932   field_decl = create_field_decl (objc_method_list_ptr,
4933                                   "methods");
4934   chainon (field_decl_chain, field_decl);
4935
4936   if (flag_next_runtime)
4937     {
4938       /* struct objc_cache *cache; */
4939       field_decl = create_field_decl (build_pointer_type
4940                                       (xref_tag (RECORD_TYPE,
4941                                                  get_identifier
4942                                                  ("objc_cache"))),
4943                                       "cache");
4944       chainon (field_decl_chain, field_decl);
4945     }
4946   else
4947     {
4948       /* struct sarray *dtable; */
4949       field_decl = create_field_decl (build_pointer_type
4950                                       (xref_tag (RECORD_TYPE,
4951                                                  get_identifier
4952                                                  ("sarray"))),
4953                                       "dtable");
4954       chainon (field_decl_chain, field_decl);
4955
4956       /* struct objc_class *subclass_list; */
4957       field_decl = create_field_decl (build_pointer_type
4958                                       (objc_class_template),
4959                                       "subclass_list");
4960       chainon (field_decl_chain, field_decl);
4961
4962       /* struct objc_class *sibling_class; */
4963       field_decl = create_field_decl (build_pointer_type
4964                                       (objc_class_template),
4965                                       "sibling_class");
4966       chainon (field_decl_chain, field_decl);
4967     }
4968
4969   /* struct _objc_protocol **protocol_list; */
4970   field_decl = create_field_decl (build_pointer_type
4971                                   (build_pointer_type
4972                                    (xref_tag (RECORD_TYPE,
4973                                              get_identifier
4974                                              (UTAG_PROTOCOL)))),
4975                                   "protocol_list");
4976   chainon (field_decl_chain, field_decl);
4977
4978   if (flag_next_runtime)
4979     {
4980       /* void *sel_id; */
4981       field_decl = create_field_decl (build_pointer_type (void_type_node),
4982                                       "sel_id");
4983       chainon (field_decl_chain, field_decl);
4984     }
4985
4986   /* void *gc_object_type; */
4987   field_decl = create_field_decl (build_pointer_type (void_type_node),
4988                                   "gc_object_type");
4989   chainon (field_decl_chain, field_decl);
4990
4991   objc_finish_struct (objc_class_template, field_decl_chain);
4992 }
4993
4994 /* Generate appropriate forward declarations for an implementation.  */
4995
4996 static void
4997 synth_forward_declarations (void)
4998 {
4999   tree an_id;
5000
5001   /* static struct objc_class _OBJC_CLASS_<my_name>; */
5002   UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
5003                                           objc_class_template);
5004
5005   /* static struct objc_class _OBJC_METACLASS_<my_name>; */
5006   UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
5007                                                   objc_class_template);
5008
5009   /* Pre-build the following entities - for speed/convenience.  */
5010
5011   an_id = get_identifier ("super_class");
5012   ucls_super_ref = objc_build_component_ref (UOBJC_CLASS_decl, an_id);
5013   uucls_super_ref = objc_build_component_ref (UOBJC_METACLASS_decl, an_id);
5014 }
5015
5016 static void
5017 error_with_ivar (const char *message, tree decl)
5018 {
5019   error_at (DECL_SOURCE_LOCATION (decl), "%s %qs",
5020             message, identifier_to_locale (gen_declaration (decl)));
5021
5022 }
5023
5024 static void
5025 check_ivars (tree inter, tree imp)
5026 {
5027   tree intdecls = CLASS_RAW_IVARS (inter);
5028   tree impdecls = CLASS_RAW_IVARS (imp);
5029
5030   while (1)
5031     {
5032       tree t1, t2;
5033
5034 #ifdef OBJCPLUS
5035       if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
5036         intdecls = TREE_CHAIN (intdecls);
5037 #endif
5038       if (intdecls == 0 && impdecls == 0)
5039         break;
5040       if (intdecls == 0 || impdecls == 0)
5041         {
5042           error ("inconsistent instance variable specification");
5043           break;
5044         }
5045
5046       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
5047
5048       if (!comptypes (t1, t2)
5049           || !tree_int_cst_equal (DECL_INITIAL (intdecls),
5050                                   DECL_INITIAL (impdecls)))
5051         {
5052           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
5053             {
5054               error_with_ivar ("conflicting instance variable type",
5055                                impdecls);
5056               error_with_ivar ("previous declaration of",
5057                                intdecls);
5058             }
5059           else                  /* both the type and the name don't match */
5060             {
5061               error ("inconsistent instance variable specification");
5062               break;
5063             }
5064         }
5065
5066       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
5067         {
5068           error_with_ivar ("conflicting instance variable name",
5069                            impdecls);
5070           error_with_ivar ("previous declaration of",
5071                            intdecls);
5072         }
5073
5074       intdecls = TREE_CHAIN (intdecls);
5075       impdecls = TREE_CHAIN (impdecls);
5076     }
5077 }
5078
5079 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
5080    This needs to be done just once per compilation.  */
5081
5082 /* struct _objc_super {
5083      struct _objc_object *self;
5084      struct _objc_class *super_class;
5085    };  */
5086
5087 static void
5088 build_super_template (void)
5089 {
5090   tree field_decl, field_decl_chain;
5091
5092   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
5093
5094   /* struct _objc_object *self; */
5095   field_decl = create_field_decl (objc_object_type, "self");
5096   field_decl_chain = field_decl;
5097
5098   /* struct _objc_class *super_class; */
5099   field_decl = create_field_decl (build_pointer_type (objc_class_template),
5100                                   "super_class");
5101   chainon (field_decl_chain, field_decl);
5102
5103   objc_finish_struct (objc_super_template, field_decl_chain);
5104 }
5105
5106 /* struct _objc_ivar {
5107      char *ivar_name;
5108      char *ivar_type;
5109      int ivar_offset;
5110    };  */
5111
5112 static tree
5113 build_ivar_template (void)
5114 {
5115   tree objc_ivar_id, objc_ivar_record;
5116   tree field_decl, field_decl_chain;
5117
5118   objc_ivar_id = get_identifier (UTAG_IVAR);
5119   objc_ivar_record = objc_start_struct (objc_ivar_id);
5120
5121   /* char *ivar_name; */
5122   field_decl = create_field_decl (string_type_node, "ivar_name");
5123   field_decl_chain = field_decl;
5124
5125   /* char *ivar_type; */
5126   field_decl = create_field_decl (string_type_node, "ivar_type");
5127   chainon (field_decl_chain, field_decl);
5128
5129   /* int ivar_offset; */
5130   field_decl = create_field_decl (integer_type_node, "ivar_offset");
5131   chainon (field_decl_chain, field_decl);
5132
5133   objc_finish_struct (objc_ivar_record, field_decl_chain);
5134
5135   return objc_ivar_record;
5136 }
5137
5138 /* struct {
5139      int ivar_count;
5140      struct objc_ivar ivar_list[ivar_count];
5141    };  */
5142
5143 static tree
5144 build_ivar_list_template (tree list_type, int size)
5145 {
5146   tree objc_ivar_list_record;
5147   tree field_decl, field_decl_chain;
5148
5149   objc_ivar_list_record = objc_start_struct (NULL_TREE);
5150
5151   /* int ivar_count; */
5152   field_decl = create_field_decl (integer_type_node, "ivar_count");
5153   field_decl_chain = field_decl;
5154
5155   /* struct objc_ivar ivar_list[]; */
5156   field_decl = create_field_decl (build_array_type
5157                                   (list_type,
5158                                    build_index_type
5159                                    (build_int_cst (NULL_TREE, size - 1))),
5160                                   "ivar_list");
5161   chainon (field_decl_chain, field_decl);
5162
5163   objc_finish_struct (objc_ivar_list_record, field_decl_chain);
5164
5165   return objc_ivar_list_record;
5166 }
5167
5168 /* struct {
5169      struct _objc__method_prototype_list *method_next;
5170      int method_count;
5171      struct objc_method method_list[method_count];
5172    };  */
5173
5174 static tree
5175 build_method_list_template (tree list_type, int size)
5176 {
5177   tree objc_ivar_list_record;
5178   tree field_decl, field_decl_chain;
5179
5180   objc_ivar_list_record = objc_start_struct (NULL_TREE);
5181
5182   /* struct _objc__method_prototype_list *method_next; */
5183   field_decl = create_field_decl (objc_method_proto_list_ptr,
5184                                   "method_next");
5185   field_decl_chain = field_decl;
5186
5187   /* int method_count; */
5188   field_decl = create_field_decl (integer_type_node, "method_count");
5189   chainon (field_decl_chain, field_decl);
5190
5191   /* struct objc_method method_list[]; */
5192   field_decl = create_field_decl (build_array_type
5193                                   (list_type,
5194                                    build_index_type
5195                                    (build_int_cst (NULL_TREE, size - 1))),
5196                                   "method_list");
5197   chainon (field_decl_chain, field_decl);
5198
5199   objc_finish_struct (objc_ivar_list_record, field_decl_chain);
5200
5201   return objc_ivar_list_record;
5202 }
5203
5204 static tree
5205 build_ivar_list_initializer (tree type, tree field_decl)
5206 {
5207   tree initlist = NULL_TREE;
5208
5209   do
5210     {
5211       tree ivar = NULL_TREE;
5212
5213       /* Set name.  */
5214       if (DECL_NAME (field_decl))
5215         ivar = tree_cons (NULL_TREE,
5216                           add_objc_string (DECL_NAME (field_decl),
5217                                            meth_var_names),
5218                           ivar);
5219       else
5220         /* Unnamed bit-field ivar (yuck).  */
5221         ivar = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), ivar);
5222
5223       /* Set type.  */
5224       encode_field_decl (field_decl,
5225                          obstack_object_size (&util_obstack),
5226                          OBJC_ENCODE_DONT_INLINE_DEFS);
5227
5228       /* Null terminate string.  */
5229       obstack_1grow (&util_obstack, 0);
5230       ivar
5231         = tree_cons
5232           (NULL_TREE,
5233            add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
5234                             meth_var_types),
5235            ivar);
5236       obstack_free (&util_obstack, util_firstobj);
5237
5238       /* Set offset.  */
5239       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
5240       initlist = tree_cons (NULL_TREE,
5241                             objc_build_constructor (type, nreverse (ivar)),
5242                             initlist);
5243       do
5244         field_decl = TREE_CHAIN (field_decl);
5245       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
5246     }
5247   while (field_decl);
5248
5249   return objc_build_constructor (build_array_type (type, 0),
5250                                  nreverse (initlist));
5251 }
5252
5253 static tree
5254 generate_ivars_list (tree type, const char *name, int size, tree list)
5255 {
5256   tree decl, initlist;
5257
5258   decl = start_var_decl (type, synth_id_with_class_suffix
5259                                (name, objc_implementation_context));
5260
5261   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
5262   initlist = tree_cons (NULL_TREE, list, initlist);
5263
5264   finish_var_decl (decl,
5265                    objc_build_constructor (TREE_TYPE (decl),
5266                                            nreverse (initlist)));
5267
5268   return decl;
5269 }
5270
5271 /* Count only the fields occurring in T.  */
5272
5273 static int
5274 ivar_list_length (tree t)
5275 {
5276   int count = 0;
5277
5278   for (; t; t = TREE_CHAIN (t))
5279     if (TREE_CODE (t) == FIELD_DECL)
5280       ++count;
5281
5282   return count;
5283 }
5284
5285 static void
5286 generate_ivar_lists (void)
5287 {
5288   tree initlist, ivar_list_template, chain;
5289   int size;
5290
5291   generating_instance_variables = 1;
5292
5293   if (!objc_ivar_template)
5294     objc_ivar_template = build_ivar_template ();
5295
5296   /* Only generate class variables for the root of the inheritance
5297      hierarchy since these will be the same for every class.  */
5298
5299   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
5300       && (chain = TYPE_FIELDS (objc_class_template)))
5301     {
5302       size = ivar_list_length (chain);
5303
5304       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5305       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5306
5307       UOBJC_CLASS_VARIABLES_decl
5308         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
5309                                size, initlist);
5310     }
5311   else
5312     UOBJC_CLASS_VARIABLES_decl = 0;
5313
5314   chain = CLASS_IVARS (implementation_template);
5315   if (chain)
5316     {
5317       size = ivar_list_length (chain);
5318       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5319       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5320
5321       UOBJC_INSTANCE_VARIABLES_decl
5322         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
5323                                size, initlist);
5324     }
5325   else
5326     UOBJC_INSTANCE_VARIABLES_decl = 0;
5327
5328   generating_instance_variables = 0;
5329 }
5330
5331 static tree
5332 build_dispatch_table_initializer (tree type, tree entries)
5333 {
5334   tree initlist = NULL_TREE;
5335
5336   do
5337     {
5338       tree elemlist = NULL_TREE;
5339
5340       elemlist = tree_cons (NULL_TREE,
5341                             build_selector (METHOD_SEL_NAME (entries)),
5342                             NULL_TREE);
5343
5344       /* Generate the method encoding if we don't have one already.  */
5345       if (! METHOD_ENCODING (entries))
5346         METHOD_ENCODING (entries) =
5347           encode_method_prototype (entries);
5348
5349       elemlist = tree_cons (NULL_TREE,
5350                             add_objc_string (METHOD_ENCODING (entries),
5351                                              meth_var_types),
5352                             elemlist);
5353
5354       elemlist
5355         = tree_cons (NULL_TREE,
5356                      convert (ptr_type_node,
5357                               build_unary_op (input_location, ADDR_EXPR,
5358                                               METHOD_DEFINITION (entries), 1)),
5359                      elemlist);
5360
5361       initlist = tree_cons (NULL_TREE,
5362                             objc_build_constructor (type, nreverse (elemlist)),
5363                             initlist);
5364
5365       entries = TREE_CHAIN (entries);
5366     }
5367   while (entries);
5368
5369   return objc_build_constructor (build_array_type (type, 0),
5370                                  nreverse (initlist));
5371 }
5372
5373 /* To accomplish method prototyping without generating all kinds of
5374    inane warnings, the definition of the dispatch table entries were
5375    changed from:
5376
5377         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
5378    to:
5379         struct objc_method { SEL _cmd; ...; void *_imp; };  */
5380
5381 static tree
5382 build_method_template (void)
5383 {
5384   tree _SLT_record;
5385   tree field_decl, field_decl_chain;
5386
5387   _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
5388
5389   /* SEL _cmd; */
5390   field_decl = create_field_decl (objc_selector_type, "_cmd");
5391   field_decl_chain = field_decl;
5392
5393   /* char *method_types; */
5394   field_decl = create_field_decl (string_type_node, "method_types");
5395   chainon (field_decl_chain, field_decl);
5396
5397   /* void *_imp; */
5398   field_decl = create_field_decl (build_pointer_type (void_type_node),
5399                                   "_imp");
5400   chainon (field_decl_chain, field_decl);
5401
5402   objc_finish_struct (_SLT_record, field_decl_chain);
5403
5404   return _SLT_record;
5405 }
5406
5407
5408 static tree
5409 generate_dispatch_table (tree type, const char *name, int size, tree list)
5410 {
5411   tree decl, initlist;
5412
5413   decl = start_var_decl (type, synth_id_with_class_suffix
5414                                (name, objc_implementation_context));
5415
5416   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
5417   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
5418   initlist = tree_cons (NULL_TREE, list, initlist);
5419
5420   finish_var_decl (decl,
5421                    objc_build_constructor (TREE_TYPE (decl),
5422                                            nreverse (initlist)));
5423
5424   return decl;
5425 }
5426
5427 static void
5428 mark_referenced_methods (void)
5429 {
5430   struct imp_entry *impent;
5431   tree chain;
5432
5433   for (impent = imp_list; impent; impent = impent->next)
5434     {
5435       chain = CLASS_CLS_METHODS (impent->imp_context);
5436       while (chain)
5437         {
5438           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5439           chain = TREE_CHAIN (chain);
5440         }
5441
5442       chain = CLASS_NST_METHODS (impent->imp_context);
5443       while (chain)
5444         {
5445           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5446           chain = TREE_CHAIN (chain);
5447         }
5448     }
5449 }
5450
5451 static void
5452 generate_dispatch_tables (void)
5453 {
5454   tree initlist, chain, method_list_template;
5455   int size;
5456
5457   if (!objc_method_template)
5458     objc_method_template = build_method_template ();
5459
5460   chain = CLASS_CLS_METHODS (objc_implementation_context);
5461   if (chain)
5462     {
5463       size = list_length (chain);
5464
5465       method_list_template
5466         = build_method_list_template (objc_method_template, size);
5467       initlist
5468         = build_dispatch_table_initializer (objc_method_template, chain);
5469
5470       UOBJC_CLASS_METHODS_decl
5471         = generate_dispatch_table (method_list_template,
5472                                    ((TREE_CODE (objc_implementation_context)
5473                                      == CLASS_IMPLEMENTATION_TYPE)
5474                                     ? "_OBJC_CLASS_METHODS"
5475                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
5476                                    size, initlist);
5477     }
5478   else
5479     UOBJC_CLASS_METHODS_decl = 0;
5480
5481   chain = CLASS_NST_METHODS (objc_implementation_context);
5482   if (chain)
5483     {
5484       size = list_length (chain);
5485
5486       method_list_template
5487         = build_method_list_template (objc_method_template, size);
5488       initlist
5489         = build_dispatch_table_initializer (objc_method_template, chain);
5490
5491       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
5492         UOBJC_INSTANCE_METHODS_decl
5493           = generate_dispatch_table (method_list_template,
5494                                      "_OBJC_INSTANCE_METHODS",
5495                                      size, initlist);
5496       else
5497         /* We have a category.  */
5498         UOBJC_INSTANCE_METHODS_decl
5499           = generate_dispatch_table (method_list_template,
5500                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
5501                                      size, initlist);
5502     }
5503   else
5504     UOBJC_INSTANCE_METHODS_decl = 0;
5505 }
5506
5507 static tree
5508 generate_protocol_list (tree i_or_p)
5509 {
5510   tree initlist;
5511   tree refs_decl, lproto, e, plist;
5512   int size = 0;
5513   const char *ref_name;
5514
5515   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
5516       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
5517     plist = CLASS_PROTOCOL_LIST (i_or_p);
5518   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
5519     plist = PROTOCOL_LIST (i_or_p);
5520   else
5521     abort ();
5522
5523   /* Compute size.  */
5524   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
5525     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
5526         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
5527       size++;
5528
5529   /* Build initializer.  */
5530   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), NULL_TREE);
5531   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
5532   initlist = tree_cons (NULL_TREE, e, initlist);
5533
5534   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
5535     {
5536       tree pval = TREE_VALUE (lproto);
5537
5538       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
5539           && PROTOCOL_FORWARD_DECL (pval))
5540         {
5541           e = build_unary_op (input_location, ADDR_EXPR, 
5542                               PROTOCOL_FORWARD_DECL (pval), 0);
5543           initlist = tree_cons (NULL_TREE, e, initlist);
5544         }
5545     }
5546
5547   /* static struct objc_protocol *refs[n]; */
5548
5549   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
5550     ref_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p);
5551   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
5552     ref_name = synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p);
5553   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
5554     ref_name = synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p);
5555   else
5556     abort ();
5557
5558   refs_decl = start_var_decl
5559               (build_array_type
5560                (build_pointer_type (objc_protocol_template),
5561                 build_index_type (build_int_cst (NULL_TREE, size + 2))),
5562                ref_name);
5563
5564   finish_var_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
5565                                                       nreverse (initlist)));
5566
5567   return refs_decl;
5568 }
5569
5570 static tree
5571 build_category_initializer (tree type, tree cat_name, tree class_name,
5572                             tree instance_methods, tree class_methods,
5573                             tree protocol_list)
5574 {
5575   tree initlist = NULL_TREE, expr;
5576
5577   initlist = tree_cons (NULL_TREE, cat_name, initlist);
5578   initlist = tree_cons (NULL_TREE, class_name, initlist);
5579
5580   if (!instance_methods)
5581     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5582   else
5583     {
5584       expr = convert (objc_method_list_ptr,
5585                       build_unary_op (input_location, ADDR_EXPR, 
5586                                       instance_methods, 0));
5587       initlist = tree_cons (NULL_TREE, expr, initlist);
5588     }
5589   if (!class_methods)
5590     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5591   else
5592     {
5593       expr = convert (objc_method_list_ptr,
5594                       build_unary_op (input_location, ADDR_EXPR, 
5595                                       class_methods, 0));
5596       initlist = tree_cons (NULL_TREE, expr, initlist);
5597     }
5598
5599   /* protocol_list = */
5600   if (!protocol_list)
5601      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5602   else
5603     {
5604       expr = convert (build_pointer_type
5605                       (build_pointer_type
5606                        (objc_protocol_template)),
5607                       build_unary_op (input_location, ADDR_EXPR, 
5608                                       protocol_list, 0));
5609       initlist = tree_cons (NULL_TREE, expr, initlist);
5610     }
5611
5612   return objc_build_constructor (type, nreverse (initlist));
5613 }
5614
5615 /* struct _objc_class {
5616      struct objc_class *isa;
5617      struct objc_class *super_class;
5618      char *name;
5619      long version;
5620      long info;
5621      long instance_size;
5622      struct objc_ivar_list *ivars;
5623      struct objc_method_list *methods;
5624      if (flag_next_runtime)
5625        struct objc_cache *cache;
5626      else {
5627        struct sarray *dtable;
5628        struct objc_class *subclass_list;
5629        struct objc_class *sibling_class;
5630      }
5631      struct objc_protocol_list *protocols;
5632      if (flag_next_runtime)
5633        void *sel_id;
5634      void *gc_object_type;
5635    };  */
5636
5637 static tree
5638 build_shared_structure_initializer (tree type, tree isa, tree super,
5639                                     tree name, tree size, int status,
5640                                     tree dispatch_table, tree ivar_list,
5641                                     tree protocol_list)
5642 {
5643   tree initlist = NULL_TREE, expr;
5644
5645   /* isa = */
5646   initlist = tree_cons (NULL_TREE, isa, initlist);
5647
5648   /* super_class = */
5649   initlist = tree_cons (NULL_TREE, super, initlist);
5650
5651   /* name = */
5652   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
5653
5654   /* version = */
5655   initlist = tree_cons (NULL_TREE, build_int_cst (long_integer_type_node, 0),
5656                         initlist);
5657
5658   /* info = */
5659   initlist = tree_cons (NULL_TREE,
5660                         build_int_cst (long_integer_type_node, status),
5661                         initlist);
5662
5663   /* instance_size = */
5664   initlist = tree_cons (NULL_TREE, convert (long_integer_type_node, size),
5665                         initlist);
5666
5667   /* objc_ivar_list = */
5668   if (!ivar_list)
5669     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5670   else
5671     {
5672       expr = convert (objc_ivar_list_ptr,
5673                       build_unary_op (input_location, ADDR_EXPR, 
5674                                       ivar_list, 0));
5675       initlist = tree_cons (NULL_TREE, expr, initlist);
5676     }
5677
5678   /* objc_method_list = */
5679   if (!dispatch_table)
5680     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5681   else
5682     {
5683       expr = convert (objc_method_list_ptr,
5684                       build_unary_op (input_location, ADDR_EXPR, 
5685                                       dispatch_table, 0));
5686       initlist = tree_cons (NULL_TREE, expr, initlist);
5687     }
5688
5689   if (flag_next_runtime)
5690     /* method_cache = */
5691     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5692   else
5693     {
5694       /* dtable = */
5695       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5696
5697       /* subclass_list = */
5698       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5699
5700       /* sibling_class = */
5701       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5702     }
5703
5704   /* protocol_list = */
5705   if (! protocol_list)
5706     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5707   else
5708     {
5709       expr = convert (build_pointer_type
5710                       (build_pointer_type
5711                        (objc_protocol_template)),
5712                       build_unary_op (input_location, ADDR_EXPR, 
5713                                       protocol_list, 0));
5714       initlist = tree_cons (NULL_TREE, expr, initlist);
5715     }
5716
5717   if (flag_next_runtime)
5718     /* sel_id = NULL */
5719     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5720
5721   /* gc_object_type = NULL */
5722   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5723
5724   return objc_build_constructor (type, nreverse (initlist));
5725 }
5726
5727 /* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
5728
5729 static inline tree
5730 lookup_category (tree klass, tree cat_name)
5731 {
5732   tree category = CLASS_CATEGORY_LIST (klass);
5733
5734   while (category && CLASS_SUPER_NAME (category) != cat_name)
5735     category = CLASS_CATEGORY_LIST (category);
5736   return category;
5737 }
5738
5739 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
5740
5741 static void
5742 generate_category (tree cat)
5743 {
5744   tree decl;
5745   tree initlist, cat_name_expr, class_name_expr;
5746   tree protocol_decl, category;
5747
5748   add_class_reference (CLASS_NAME (cat));
5749   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5750
5751   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5752
5753   category = lookup_category (implementation_template,
5754                                 CLASS_SUPER_NAME (cat));
5755
5756   if (category && CLASS_PROTOCOL_LIST (category))
5757     {
5758       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5759       protocol_decl = generate_protocol_list (category);
5760     }
5761   else
5762     protocol_decl = 0;
5763
5764   decl = start_var_decl (objc_category_template,
5765                          synth_id_with_class_suffix
5766                          ("_OBJC_CATEGORY", objc_implementation_context));
5767
5768   initlist = build_category_initializer (TREE_TYPE (decl),
5769                                          cat_name_expr, class_name_expr,
5770                                          UOBJC_INSTANCE_METHODS_decl,
5771                                          UOBJC_CLASS_METHODS_decl,
5772                                          protocol_decl);
5773
5774   finish_var_decl (decl, initlist);
5775 }
5776
5777 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5778    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
5779
5780 static void
5781 generate_shared_structures (int cls_flags)
5782 {
5783   tree sc_spec, decl_specs, decl;
5784   tree name_expr, super_expr, root_expr;
5785   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5786   tree cast_type, initlist, protocol_decl;
5787
5788   my_super_id = CLASS_SUPER_NAME (implementation_template);
5789   if (my_super_id)
5790     {
5791       add_class_reference (my_super_id);
5792
5793       /* Compute "my_root_id" - this is required for code generation.
5794          the "isa" for all meta class structures points to the root of
5795          the inheritance hierarchy (e.g. "__Object")...  */
5796       my_root_id = my_super_id;
5797       do
5798         {
5799           tree my_root_int = lookup_interface (my_root_id);
5800
5801           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5802             my_root_id = CLASS_SUPER_NAME (my_root_int);
5803           else
5804             break;
5805         }
5806       while (1);
5807     }
5808   else
5809     /* No super class.  */
5810     my_root_id = CLASS_NAME (implementation_template);
5811
5812   cast_type = build_pointer_type (objc_class_template);
5813   name_expr = add_objc_string (CLASS_NAME (implementation_template),
5814                                class_names);
5815
5816   /* Install class `isa' and `super' pointers at runtime.  */
5817   if (my_super_id)
5818     {
5819       super_expr = add_objc_string (my_super_id, class_names);
5820       super_expr = build_c_cast (input_location,
5821                                  cast_type, super_expr); /* cast! */
5822     }
5823   else
5824     super_expr = build_int_cst (NULL_TREE, 0);
5825
5826   root_expr = add_objc_string (my_root_id, class_names);
5827   root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */
5828
5829   if (CLASS_PROTOCOL_LIST (implementation_template))
5830     {
5831       generate_protocol_references
5832         (CLASS_PROTOCOL_LIST (implementation_template));
5833       protocol_decl = generate_protocol_list (implementation_template);
5834     }
5835   else
5836     protocol_decl = 0;
5837
5838   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5839
5840   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5841   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5842
5843   decl = start_var_decl (objc_class_template,
5844                          IDENTIFIER_POINTER
5845                          (DECL_NAME (UOBJC_METACLASS_decl)));
5846
5847   initlist
5848     = build_shared_structure_initializer
5849       (TREE_TYPE (decl),
5850        root_expr, super_expr, name_expr,
5851        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5852        2 /*CLS_META*/,
5853        UOBJC_CLASS_METHODS_decl,
5854        UOBJC_CLASS_VARIABLES_decl,
5855        protocol_decl);
5856
5857   finish_var_decl (decl, initlist);
5858
5859   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5860
5861   decl = start_var_decl (objc_class_template,
5862                          IDENTIFIER_POINTER
5863                          (DECL_NAME (UOBJC_CLASS_decl)));
5864
5865   initlist
5866     = build_shared_structure_initializer
5867       (TREE_TYPE (decl),
5868        build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5869        super_expr, name_expr,
5870        convert (integer_type_node,
5871                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5872                                 (implementation_template))),
5873        1 /*CLS_FACTORY*/ | cls_flags,
5874        UOBJC_INSTANCE_METHODS_decl,
5875        UOBJC_INSTANCE_VARIABLES_decl,
5876        protocol_decl);
5877
5878   finish_var_decl (decl, initlist);
5879 }
5880
5881
5882 static const char *
5883 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5884 {
5885   static char string[BUFSIZE];
5886
5887   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5888       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5889     {
5890       sprintf (string, "%s_%s", preamble,
5891                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5892     }
5893   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5894            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5895     {
5896       /* We have a category.  */
5897       const char *const class_name
5898         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5899       const char *const class_super_name
5900         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5901       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5902     }
5903   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5904     {
5905       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5906       sprintf (string, "%s_%s", preamble, protocol_name);
5907     }
5908   else
5909     abort ();
5910
5911   return string;
5912 }
5913
5914 /* If type is empty or only type qualifiers are present, add default
5915    type of id (otherwise grokdeclarator will default to int).  */
5916
5917 static tree
5918 adjust_type_for_id_default (tree type)
5919 {
5920   if (!type)
5921     type = make_node (TREE_LIST);
5922
5923   if (!TREE_VALUE (type))
5924     TREE_VALUE (type) = objc_object_type;
5925   else if (TREE_CODE (TREE_VALUE (type)) == RECORD_TYPE
5926            && TYPED_OBJECT (TREE_VALUE (type)))
5927     error ("can not use an object as parameter to a method");
5928
5929   return type;
5930 }
5931
5932 /*   Usage:
5933                 keyworddecl:
5934                         selector ':' '(' typename ')' identifier
5935
5936      Purpose:
5937                 Transform an Objective-C keyword argument into
5938                 the C equivalent parameter declarator.
5939
5940      In:        key_name, an "identifier_node" (optional).
5941                 arg_type, a  "tree_list" (optional).
5942                 arg_name, an "identifier_node".
5943
5944      Note:      It would be really nice to strongly type the preceding
5945                 arguments in the function prototype; however, then I
5946                 could not use the "accessor" macros defined in "tree.h".
5947
5948      Out:       an instance of "keyword_decl".  */
5949
5950 tree
5951 objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5952 {
5953   tree keyword_decl;
5954
5955   /* If no type is specified, default to "id".  */
5956   arg_type = adjust_type_for_id_default (arg_type);
5957
5958   keyword_decl = make_node (KEYWORD_DECL);
5959
5960   TREE_TYPE (keyword_decl) = arg_type;
5961   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5962   KEYWORD_KEY_NAME (keyword_decl) = key_name;
5963
5964   return keyword_decl;
5965 }
5966
5967 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
5968
5969 static tree
5970 build_keyword_selector (tree selector)
5971 {
5972   int len = 0;
5973   tree key_chain, key_name;
5974   char *buf;
5975
5976   /* Scan the selector to see how much space we'll need.  */
5977   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5978     {
5979       if (TREE_CODE (selector) == KEYWORD_DECL)
5980         key_name = KEYWORD_KEY_NAME (key_chain);
5981       else if (TREE_CODE (selector) == TREE_LIST)
5982         key_name = TREE_PURPOSE (key_chain);
5983       else
5984         abort ();
5985
5986       if (key_name)
5987         len += IDENTIFIER_LENGTH (key_name) + 1;
5988       else
5989         /* Just a ':' arg.  */
5990         len++;
5991     }
5992
5993   buf = (char *) alloca (len + 1);
5994   /* Start the buffer out as an empty string.  */
5995   buf[0] = '\0';
5996
5997   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5998     {
5999       if (TREE_CODE (selector) == KEYWORD_DECL)
6000         key_name = KEYWORD_KEY_NAME (key_chain);
6001       else if (TREE_CODE (selector) == TREE_LIST)
6002         {
6003           key_name = TREE_PURPOSE (key_chain);
6004           /* The keyword decl chain will later be used as a function argument
6005              chain.  Unhook the selector itself so as to not confuse other
6006              parts of the compiler.  */
6007           TREE_PURPOSE (key_chain) = NULL_TREE;
6008         }
6009       else
6010         abort ();
6011
6012       if (key_name)
6013         strcat (buf, IDENTIFIER_POINTER (key_name));
6014       strcat (buf, ":");
6015     }
6016
6017   return get_identifier (buf);
6018 }
6019
6020 /* Used for declarations and definitions.  */
6021
6022 static tree
6023 build_method_decl (enum tree_code code, tree ret_type, tree selector,
6024                    tree add_args, bool ellipsis)
6025 {
6026   tree method_decl;
6027
6028   /* If no type is specified, default to "id".  */
6029   ret_type = adjust_type_for_id_default (ret_type);
6030
6031   method_decl = make_node (code);
6032   TREE_TYPE (method_decl) = ret_type;
6033
6034   /* If we have a keyword selector, create an identifier_node that
6035      represents the full selector name (`:' included)...  */
6036   if (TREE_CODE (selector) == KEYWORD_DECL)
6037     {
6038       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
6039       METHOD_SEL_ARGS (method_decl) = selector;
6040       METHOD_ADD_ARGS (method_decl) = add_args;
6041       METHOD_ADD_ARGS_ELLIPSIS_P (method_decl) = ellipsis;
6042     }
6043   else
6044     {
6045       METHOD_SEL_NAME (method_decl) = selector;
6046       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
6047       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
6048     }
6049
6050   return method_decl;
6051 }
6052
6053 #define METHOD_DEF 0
6054 #define METHOD_REF 1
6055
6056 /* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
6057    an argument list for method METH.  CONTEXT is either METHOD_DEF or
6058    METHOD_REF, saying whether we are trying to define a method or call
6059    one.  SUPERFLAG says this is for a send to super; this makes a
6060    difference for the NeXT calling sequence in which the lookup and
6061    the method call are done together.  If METH is null, user-defined
6062    arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
6063
6064 static tree
6065 get_arg_type_list (tree meth, int context, int superflag)
6066 {
6067   tree arglist, akey;
6068
6069   /* Receiver type.  */
6070   if (flag_next_runtime && superflag)
6071     arglist = build_tree_list (NULL_TREE, objc_super_type);
6072   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
6073     arglist = build_tree_list (NULL_TREE, objc_instance_type);
6074   else
6075     arglist = build_tree_list (NULL_TREE, objc_object_type);
6076
6077   /* Selector type - will eventually change to `int'.  */
6078   chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
6079
6080   /* No actual method prototype given -- assume that remaining arguments
6081      are `...'.  */
6082   if (!meth)
6083     return arglist;
6084
6085   /* Build a list of argument types.  */
6086   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
6087     {
6088       tree arg_type = TREE_VALUE (TREE_TYPE (akey));
6089
6090       /* Decay arrays and functions into pointers.  */
6091       if (TREE_CODE (arg_type) == ARRAY_TYPE)
6092         arg_type = build_pointer_type (TREE_TYPE (arg_type));
6093       else if (TREE_CODE (arg_type) == FUNCTION_TYPE)
6094         arg_type = build_pointer_type (arg_type);
6095
6096       chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6097     }
6098
6099   if (METHOD_ADD_ARGS (meth))
6100     {
6101       for (akey = TREE_CHAIN (METHOD_ADD_ARGS (meth));
6102            akey; akey = TREE_CHAIN (akey))
6103         {
6104           tree arg_type = TREE_TYPE (TREE_VALUE (akey));
6105
6106           chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6107         }
6108
6109       if (!METHOD_ADD_ARGS_ELLIPSIS_P (meth))
6110         goto lack_of_ellipsis;
6111     }
6112   else
6113     {
6114      lack_of_ellipsis:
6115       chainon (arglist, OBJC_VOID_AT_END);
6116     }
6117
6118   return arglist;
6119 }
6120
6121 static tree
6122 check_duplicates (hash hsh, int methods, int is_class)
6123 {
6124   tree meth = NULL_TREE;
6125
6126   if (hsh)
6127     {
6128       meth = hsh->key;
6129
6130       if (hsh->list)
6131         {
6132           /* We have two or more methods with the same name but
6133              different types.  */
6134           attr loop;
6135
6136           /* But just how different are those types?  If
6137              -Wno-strict-selector-match is specified, we shall not
6138              complain if the differences are solely among types with
6139              identical size and alignment.  */
6140           if (!warn_strict_selector_match)
6141             {
6142               for (loop = hsh->list; loop; loop = loop->next)
6143                 if (!comp_proto_with_proto (meth, loop->value, 0))
6144                   goto issue_warning;
6145
6146               return meth;
6147             }
6148
6149         issue_warning:
6150           if (methods)
6151             {
6152               bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
6153
6154               warning_at (input_location, 0,
6155                           "multiple methods named %<%c%E%> found",
6156                           (is_class ? '+' : '-'),
6157                           METHOD_SEL_NAME (meth));
6158               inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>",
6159                       (type ? '-' : '+'),
6160                       identifier_to_locale (gen_method_decl (meth)));
6161             }
6162           else
6163             {
6164               bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
6165
6166               warning_at (input_location, 0,
6167                           "multiple selectors named %<%c%E%> found",
6168                           (is_class ? '+' : '-'),
6169                           METHOD_SEL_NAME (meth));
6170               inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>",
6171                       (type ? '-' : '+'),
6172                       identifier_to_locale (gen_method_decl (meth)));
6173             }
6174
6175           for (loop = hsh->list; loop; loop = loop->next)
6176             {
6177               bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL;
6178
6179               inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
6180                       (type ? '-' : '+'),
6181                       identifier_to_locale (gen_method_decl (loop->value)));
6182             }
6183         }
6184     }
6185   return meth;
6186 }
6187
6188 /* If RECEIVER is a class reference, return the identifier node for
6189    the referenced class.  RECEIVER is created by objc_get_class_reference,
6190    so we check the exact form created depending on which runtimes are
6191    used.  */
6192
6193 static tree
6194 receiver_is_class_object (tree receiver, int self, int super)
6195 {
6196   tree chain, exp, arg;
6197
6198   /* The receiver is 'self' or 'super' in the context of a class method.  */
6199   if (objc_method_context
6200       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
6201       && (self || super))
6202     return (super
6203             ? CLASS_SUPER_NAME (implementation_template)
6204             : CLASS_NAME (implementation_template));
6205
6206   if (flag_next_runtime)
6207     {
6208       /* The receiver is a variable created by
6209          build_class_reference_decl.  */
6210       if (TREE_CODE (receiver) == VAR_DECL && IS_CLASS (TREE_TYPE (receiver)))
6211         /* Look up the identifier.  */
6212         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
6213           if (TREE_PURPOSE (chain) == receiver)
6214             return TREE_VALUE (chain);
6215     }
6216
6217   /* The receiver is a function call that returns an id.  Check if
6218      it is a call to objc_getClass, if so, pick up the class name.  */
6219   if (TREE_CODE (receiver) == CALL_EXPR
6220       && (exp = CALL_EXPR_FN (receiver))
6221       && TREE_CODE (exp) == ADDR_EXPR
6222       && (exp = TREE_OPERAND (exp, 0))
6223       && TREE_CODE (exp) == FUNCTION_DECL
6224       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
6225          prototypes for objc_get_class().  Thankfully, they seem to share the
6226          same function type.  */
6227       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
6228       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
6229       /* We have a call to objc_get_class/objc_getClass!  */
6230       && (arg = CALL_EXPR_ARG (receiver, 0)))
6231     {
6232       STRIP_NOPS (arg);
6233       if (TREE_CODE (arg) == ADDR_EXPR
6234           && (arg = TREE_OPERAND (arg, 0))
6235           && TREE_CODE (arg) == STRING_CST)
6236         /* Finally, we have the class name.  */
6237         return get_identifier (TREE_STRING_POINTER (arg));
6238     }
6239   return 0;
6240 }
6241 \f
6242 /* If we are currently building a message expr, this holds
6243    the identifier of the selector of the message.  This is
6244    used when printing warnings about argument mismatches.  */
6245
6246 static tree current_objc_message_selector = 0;
6247
6248 tree
6249 objc_message_selector (void)
6250 {
6251   return current_objc_message_selector;
6252 }
6253
6254 /* Construct an expression for sending a message.
6255    MESS has the object to send to in TREE_PURPOSE
6256    and the argument list (including selector) in TREE_VALUE.
6257
6258    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
6259    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
6260
6261 tree
6262 objc_build_message_expr (tree mess)
6263 {
6264   tree receiver = TREE_PURPOSE (mess);
6265   location_t loc;
6266   tree sel_name;
6267 #ifdef OBJCPLUS
6268   tree args = TREE_PURPOSE (TREE_VALUE (mess));
6269 #else
6270   tree args = TREE_VALUE (mess);
6271 #endif
6272   tree method_params = NULL_TREE;
6273
6274   if (TREE_CODE (receiver) == ERROR_MARK || TREE_CODE (args) == ERROR_MARK)
6275     return error_mark_node;
6276
6277   if (CAN_HAVE_LOCATION_P (receiver))
6278     loc = EXPR_LOCATION (receiver);
6279   else
6280     loc = input_location;
6281
6282   /* Obtain the full selector name.  */
6283   if (TREE_CODE (args) == IDENTIFIER_NODE)
6284     /* A unary selector.  */
6285     sel_name = args;
6286   else if (TREE_CODE (args) == TREE_LIST)
6287     sel_name = build_keyword_selector (args);
6288   else
6289     abort ();
6290
6291   /* Build the parameter list to give to the method.  */
6292   if (TREE_CODE (args) == TREE_LIST)
6293 #ifdef OBJCPLUS
6294     method_params = chainon (args, TREE_VALUE (TREE_VALUE (mess)));
6295 #else
6296     {
6297       tree chain = args, prev = NULL_TREE;
6298
6299       /* We have a keyword selector--check for comma expressions.  */
6300       while (chain)
6301         {
6302           tree element = TREE_VALUE (chain);
6303
6304           /* We have a comma expression, must collapse...  */
6305           if (TREE_CODE (element) == TREE_LIST)
6306             {
6307               if (prev)
6308                 TREE_CHAIN (prev) = element;
6309               else
6310                 args = element;
6311             }
6312           prev = chain;
6313           chain = TREE_CHAIN (chain);
6314         }
6315       method_params = args;
6316     }
6317 #endif
6318
6319 #ifdef OBJCPLUS
6320   if (processing_template_decl)
6321     /* Must wait until template instantiation time.  */
6322     return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
6323                          method_params);
6324 #endif
6325
6326   return objc_finish_message_expr (receiver, sel_name, method_params);
6327 }
6328
6329 /* Look up method SEL_NAME that would be suitable for receiver
6330    of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
6331    nonzero), and report on any duplicates.  */
6332
6333 static tree
6334 lookup_method_in_hash_lists (tree sel_name, int is_class)
6335 {
6336   hash method_prototype = NULL;
6337
6338   if (!is_class)
6339     method_prototype = hash_lookup (nst_method_hash_list,
6340                                     sel_name);
6341
6342   if (!method_prototype)
6343     {
6344       method_prototype = hash_lookup (cls_method_hash_list,
6345                                       sel_name);
6346       is_class = 1;
6347     }
6348
6349   return check_duplicates (method_prototype, 1, is_class);
6350 }
6351
6352 /* The 'objc_finish_message_expr' routine is called from within
6353    'objc_build_message_expr' for non-template functions.  In the case of
6354    C++ template functions, it is called from 'build_expr_from_tree'
6355    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
6356
6357 tree
6358 objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
6359 {
6360   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
6361   tree selector, retval, class_tree;
6362   int self, super, have_cast;
6363
6364   /* Extract the receiver of the message, as well as its type
6365      (where the latter may take the form of a cast or be inferred
6366      from the implementation context).  */
6367   rtype = receiver;
6368   while (TREE_CODE (rtype) == COMPOUND_EXPR
6369               || TREE_CODE (rtype) == MODIFY_EXPR
6370               || CONVERT_EXPR_P (rtype)
6371               || TREE_CODE (rtype) == COMPONENT_REF)
6372     rtype = TREE_OPERAND (rtype, 0);
6373   self = (rtype == self_decl);
6374   super = (rtype == UOBJC_SUPER_decl);
6375   rtype = TREE_TYPE (receiver);
6376   have_cast = (TREE_CODE (receiver) == NOP_EXPR
6377                || (TREE_CODE (receiver) == COMPOUND_EXPR
6378                    && !IS_SUPER (rtype)));
6379
6380   /* If we are calling [super dealloc], reset our warning flag.  */
6381   if (super && !strcmp ("dealloc", IDENTIFIER_POINTER (sel_name)))
6382     should_call_super_dealloc = 0;
6383
6384   /* If the receiver is a class object, retrieve the corresponding
6385      @interface, if one exists. */
6386   class_tree = receiver_is_class_object (receiver, self, super);
6387
6388   /* Now determine the receiver type (if an explicit cast has not been
6389      provided).  */
6390   if (!have_cast)
6391     {
6392       if (class_tree)
6393         rtype = lookup_interface (class_tree);
6394       /* Handle `self' and `super'.  */
6395       else if (super)
6396         {
6397           if (!CLASS_SUPER_NAME (implementation_template))
6398             {
6399               error ("no super class declared in @interface for %qE",
6400                      CLASS_NAME (implementation_template));
6401               return error_mark_node;
6402             }
6403           rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6404         }
6405       else if (self)
6406         rtype = lookup_interface (CLASS_NAME (implementation_template));
6407     }
6408
6409   /* If receiver is of type `id' or `Class' (or if the @interface for a
6410      class is not visible), we shall be satisfied with the existence of
6411      any instance or class method. */
6412   if (objc_is_id (rtype))
6413     {
6414       class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE);
6415       rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
6416                  ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
6417                  : NULL_TREE);
6418       rtype = NULL_TREE;
6419
6420       if (rprotos)
6421         {
6422           /* If messaging 'id <Protos>' or 'Class <Proto>', first search
6423              in protocols themselves for the method prototype.  */
6424           method_prototype
6425             = lookup_method_in_protocol_list (rprotos, sel_name,
6426                                               class_tree != NULL_TREE);
6427
6428           /* If messaging 'Class <Proto>' but did not find a class method
6429              prototype, search for an instance method instead, and warn
6430              about having done so.  */
6431           if (!method_prototype && !rtype && class_tree != NULL_TREE)
6432             {
6433               method_prototype
6434                 = lookup_method_in_protocol_list (rprotos, sel_name, 0);
6435
6436               if (method_prototype)
6437                 warning (0, "found %<-%E%> instead of %<+%E%> in protocol(s)",
6438                          sel_name, sel_name);
6439             }
6440         }
6441     }
6442   else if (rtype)
6443     {
6444       tree orig_rtype = rtype, saved_rtype;
6445
6446       if (TREE_CODE (rtype) == POINTER_TYPE)
6447         rtype = TREE_TYPE (rtype);
6448       /* Traverse typedef aliases */
6449       while (TREE_CODE (rtype) == RECORD_TYPE && OBJC_TYPE_NAME (rtype)
6450              && TREE_CODE (OBJC_TYPE_NAME (rtype)) == TYPE_DECL
6451              && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype)))
6452         rtype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype));
6453       saved_rtype = rtype;
6454       if (TYPED_OBJECT (rtype))
6455         {
6456           rprotos = TYPE_OBJC_PROTOCOL_LIST (rtype);
6457           rtype = TYPE_OBJC_INTERFACE (rtype);
6458         }
6459       /* If we could not find an @interface declaration, we must have
6460          only seen a @class declaration; so, we cannot say anything
6461          more intelligent about which methods the receiver will
6462          understand. */
6463       if (!rtype || TREE_CODE (rtype) == IDENTIFIER_NODE)
6464         rtype = NULL_TREE;
6465       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
6466           || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
6467         {
6468           /* We have a valid ObjC class name.  Look up the method name
6469              in the published @interface for the class (and its
6470              superclasses). */
6471           method_prototype
6472             = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
6473
6474           /* If the method was not found in the @interface, it may still
6475              exist locally as part of the @implementation.  */
6476           if (!method_prototype && objc_implementation_context
6477              && CLASS_NAME (objc_implementation_context)
6478                 == OBJC_TYPE_NAME (rtype))
6479             method_prototype
6480               = lookup_method
6481                 ((class_tree
6482                   ? CLASS_CLS_METHODS (objc_implementation_context)
6483                   : CLASS_NST_METHODS (objc_implementation_context)),
6484                   sel_name);
6485
6486           /* If we haven't found a candidate method by now, try looking for
6487              it in the protocol list.  */
6488           if (!method_prototype && rprotos)
6489             method_prototype
6490               = lookup_method_in_protocol_list (rprotos, sel_name,
6491                                                 class_tree != NULL_TREE);
6492         }
6493       else
6494         {
6495           warning (0, "invalid receiver type %qs",
6496                    identifier_to_locale (gen_type_name (orig_rtype)));
6497           /* After issuing the "invalid receiver" warning, perform method
6498              lookup as if we were messaging 'id'.  */
6499           rtype = rprotos = NULL_TREE;
6500         }
6501     }
6502
6503
6504   /* For 'id' or 'Class' receivers, search in the global hash table
6505      as a last resort.  For all receivers, warn if protocol searches
6506      have failed.  */
6507   if (!method_prototype)
6508     {
6509       if (rprotos)
6510         warning (0, "%<%c%E%> not found in protocol(s)",
6511                  (class_tree ? '+' : '-'),
6512                  sel_name);
6513
6514       if (!rtype)
6515         method_prototype
6516           = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
6517     }
6518
6519   if (!method_prototype)
6520     {
6521       static bool warn_missing_methods = false;
6522
6523       if (rtype)
6524         warning (0, "%qE may not respond to %<%c%E%>",
6525                  OBJC_TYPE_NAME (rtype),
6526                  (class_tree ? '+' : '-'),
6527                  sel_name);
6528       /* If we are messaging an 'id' or 'Class' object and made it here,
6529          then we have failed to find _any_ instance or class method,
6530          respectively.  */
6531       else
6532         warning (0, "no %<%c%E%> method found",
6533                  (class_tree ? '+' : '-'),
6534                  sel_name);
6535
6536       if (!warn_missing_methods)
6537         {
6538           warning_at (input_location, 
6539                       0, "(Messages without a matching method signature");
6540           warning_at (input_location, 
6541                       0, "will be assumed to return %<id%> and accept");
6542           warning_at (input_location, 
6543                       0, "%<...%> as arguments.)");
6544           warn_missing_methods = true;
6545         }
6546     }
6547
6548   /* Save the selector name for printing error messages.  */
6549   current_objc_message_selector = sel_name;
6550
6551   /* Build the parameters list for looking up the method.
6552      These are the object itself and the selector.  */
6553
6554   if (flag_typed_selectors)
6555     selector = build_typed_selector_reference (input_location,
6556                                                sel_name, method_prototype);
6557   else
6558     selector = build_selector_reference (input_location, sel_name);
6559
6560   retval = build_objc_method_call (input_location, super, method_prototype,
6561                                    receiver,
6562                                    selector, method_params);
6563
6564   current_objc_message_selector = 0;
6565
6566   return retval;
6567 }
6568 \f
6569 /* Build a tree expression to send OBJECT the operation SELECTOR,
6570    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
6571    assuming the method has prototype METHOD_PROTOTYPE.
6572    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
6573    LOC is the location of the expression to build.
6574    Use METHOD_PARAMS as list of args to pass to the method.
6575    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
6576
6577 static tree
6578 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
6579                         tree lookup_object, tree selector,
6580                         tree method_params)
6581 {
6582   tree sender = (super_flag ? umsg_super_decl :
6583                  (!flag_next_runtime || flag_nil_receivers
6584                   ? (flag_objc_direct_dispatch
6585                      ? umsg_fast_decl
6586                      : umsg_decl)
6587                   : umsg_nonnil_decl));
6588   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
6589
6590   /* If a prototype for the method to be called exists, then cast
6591      the sender's return type and arguments to match that of the method.
6592      Otherwise, leave sender as is.  */
6593   tree ret_type
6594     = (method_prototype
6595        ? TREE_VALUE (TREE_TYPE (method_prototype))
6596        : objc_object_type);
6597   tree sender_cast
6598     = build_pointer_type
6599       (build_function_type
6600        (ret_type,
6601         get_arg_type_list
6602         (method_prototype, METHOD_REF, super_flag)));
6603   tree method, t;
6604
6605   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
6606
6607   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
6608   lookup_object = save_expr (lookup_object);
6609
6610   if (flag_next_runtime)
6611     {
6612       /* If we are returning a struct in memory, and the address
6613          of that memory location is passed as a hidden first
6614          argument, then change which messenger entry point this
6615          expr will call.  NB: Note that sender_cast remains
6616          unchanged (it already has a struct return type).  */
6617       if (!targetm.calls.struct_value_rtx (0, 0)
6618           && (TREE_CODE (ret_type) == RECORD_TYPE
6619               || TREE_CODE (ret_type) == UNION_TYPE)
6620           && targetm.calls.return_in_memory (ret_type, 0))
6621         sender = (super_flag ? umsg_super_stret_decl :
6622                 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
6623
6624       method_params = tree_cons (NULL_TREE, lookup_object,
6625                                  tree_cons (NULL_TREE, selector,
6626                                             method_params));
6627       method = build_fold_addr_expr_loc (input_location, sender);
6628     }
6629   else
6630     {
6631       /* This is the portable (GNU) way.  */
6632       tree object;
6633
6634       /* First, call the lookup function to get a pointer to the method,
6635          then cast the pointer, then call it with the method arguments.  */
6636
6637       object = (super_flag ? self_decl : lookup_object);
6638
6639       t = tree_cons (NULL_TREE, selector, NULL_TREE);
6640       t = tree_cons (NULL_TREE, lookup_object, t);
6641       method = build_function_call (loc, sender, t);
6642
6643       /* Pass the object to the method.  */
6644       method_params = tree_cons (NULL_TREE, object,
6645                                  tree_cons (NULL_TREE, selector,
6646                                             method_params));
6647     }
6648
6649   /* ??? Selector is not at this point something we can use inside
6650      the compiler itself.  Set it to garbage for the nonce.  */
6651   t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
6652   return build_function_call (loc,
6653                               t, method_params);
6654 }
6655 \f
6656 static void
6657 build_protocol_reference (tree p)
6658 {
6659   tree decl;
6660   const char *proto_name;
6661
6662   /* static struct _objc_protocol _OBJC_PROTOCOL_<mumble>; */
6663
6664   proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
6665   decl = start_var_decl (objc_protocol_template, proto_name);
6666
6667   PROTOCOL_FORWARD_DECL (p) = decl;
6668 }
6669
6670 /* This function is called by the parser when (and only when) a
6671    @protocol() expression is found, in order to compile it.  */
6672 tree
6673 objc_build_protocol_expr (tree protoname)
6674 {
6675   tree expr;
6676   tree p = lookup_protocol (protoname);
6677
6678   if (!p)
6679     {
6680       error ("cannot find protocol declaration for %qE",
6681              protoname);
6682       return error_mark_node;
6683     }
6684
6685   if (!PROTOCOL_FORWARD_DECL (p))
6686     build_protocol_reference (p);
6687
6688   expr = build_unary_op (input_location, 
6689                          ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
6690
6691   /* ??? Ideally we'd build the reference with objc_protocol_type directly,
6692      if we have it, rather than converting it here.  */
6693   expr = convert (objc_protocol_type, expr);
6694
6695   /* The @protocol() expression is being compiled into a pointer to a
6696      statically allocated instance of the Protocol class.  To become
6697      usable at runtime, the 'isa' pointer of the instance need to be
6698      fixed up at runtime by the runtime library, to point to the
6699      actual 'Protocol' class.  */
6700
6701   /* For the GNU runtime, put the static Protocol instance in the list
6702      of statically allocated instances, so that we make sure that its
6703      'isa' pointer is fixed up at runtime by the GNU runtime library
6704      to point to the Protocol class (at runtime, when loading the
6705      module, the GNU runtime library loops on the statically allocated
6706      instances (as found in the defs field in objc_symtab) and fixups
6707      all the 'isa' pointers of those objects).  */
6708   if (! flag_next_runtime)
6709     {
6710       /* This type is a struct containing the fields of a Protocol
6711         object.  (Cfr. objc_protocol_type instead is the type of a pointer
6712         to such a struct).  */
6713       tree protocol_struct_type = xref_tag
6714        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
6715       tree *chain;
6716
6717       /* Look for the list of Protocol statically allocated instances
6718         to fixup at runtime.  Create a new list to hold Protocol
6719         statically allocated instances, if the list is not found.  At
6720         present there is only another list, holding NSConstantString
6721         static instances to be fixed up at runtime.  */
6722       for (chain = &objc_static_instances;
6723            *chain && TREE_VALUE (*chain) != protocol_struct_type;
6724            chain = &TREE_CHAIN (*chain));
6725       if (!*chain)
6726         {
6727          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6728          add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6729                           class_names);
6730        }
6731
6732       /* Add this statically allocated instance to the Protocol list.  */
6733       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6734                                          PROTOCOL_FORWARD_DECL (p),
6735                                          TREE_PURPOSE (*chain));
6736     }
6737
6738
6739   return expr;
6740 }
6741
6742 /* This function is called by the parser when a @selector() expression
6743    is found, in order to compile it.  It is only called by the parser
6744    and only to compile a @selector().  LOC is the location of the
6745    @selector.  */
6746 tree
6747 objc_build_selector_expr (location_t loc, tree selnamelist)
6748 {
6749   tree selname;
6750
6751   /* Obtain the full selector name.  */
6752   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6753     /* A unary selector.  */
6754     selname = selnamelist;
6755   else if (TREE_CODE (selnamelist) == TREE_LIST)
6756     selname = build_keyword_selector (selnamelist);
6757   else
6758     abort ();
6759
6760   /* If we are required to check @selector() expressions as they
6761      are found, check that the selector has been declared.  */
6762   if (warn_undeclared_selector)
6763     {
6764       /* Look the selector up in the list of all known class and
6765          instance methods (up to this line) to check that the selector
6766          exists.  */
6767       hash hsh;
6768
6769       /* First try with instance methods.  */
6770       hsh = hash_lookup (nst_method_hash_list, selname);
6771
6772       /* If not found, try with class methods.  */
6773       if (!hsh)
6774         {
6775           hsh = hash_lookup (cls_method_hash_list, selname);
6776         }
6777
6778       /* If still not found, print out a warning.  */
6779       if (!hsh)
6780         {
6781           warning (0, "undeclared selector %qE", selname);
6782         }
6783     }
6784
6785
6786   if (flag_typed_selectors)
6787     return build_typed_selector_reference (loc, selname, 0);
6788   else
6789     return build_selector_reference (loc, selname);
6790 }
6791
6792 tree
6793 objc_build_encode_expr (tree type)
6794 {
6795   tree result;
6796   const char *string;
6797
6798   encode_type (type, obstack_object_size (&util_obstack),
6799                OBJC_ENCODE_INLINE_DEFS);
6800   obstack_1grow (&util_obstack, 0);    /* null terminate string */
6801   string = XOBFINISH (&util_obstack, const char *);
6802
6803   /* Synthesize a string that represents the encoded struct/union.  */
6804   result = my_build_string (strlen (string) + 1, string);
6805   obstack_free (&util_obstack, util_firstobj);
6806   return result;
6807 }
6808
6809 static tree
6810 build_ivar_reference (tree id)
6811 {
6812   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6813     {
6814       /* Historically, a class method that produced objects (factory
6815          method) would assign `self' to the instance that it
6816          allocated.  This would effectively turn the class method into
6817          an instance method.  Following this assignment, the instance
6818          variables could be accessed.  That practice, while safe,
6819          violates the simple rule that a class method should not refer
6820          to an instance variable.  It's better to catch the cases
6821          where this is done unknowingly than to support the above
6822          paradigm.  */
6823       warning (0, "instance variable %qE accessed in class method",
6824                id);
6825       self_decl = convert (objc_instance_type, self_decl); /* cast */
6826     }
6827
6828   return objc_build_component_ref (build_indirect_ref (input_location,
6829                                                        self_decl, "->"), id);
6830 }
6831 \f
6832 /* Compute a hash value for a given method SEL_NAME.  */
6833
6834 static size_t
6835 hash_func (tree sel_name)
6836 {
6837   const unsigned char *s
6838     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6839   size_t h = 0;
6840
6841   while (*s)
6842     h = h * 67 + *s++ - 113;
6843   return h;
6844 }
6845
6846 static void
6847 hash_init (void)
6848 {
6849   nst_method_hash_list
6850     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6851   cls_method_hash_list
6852     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6853
6854   /* Initialize the hash table used to hold the constant string objects.  */
6855   string_htab = htab_create_ggc (31, string_hash,
6856                                    string_eq, NULL);
6857
6858   /* Initialize the hash table used to hold EH-volatilized types.  */
6859   volatilized_htab = htab_create_ggc (31, volatilized_hash,
6860                                       volatilized_eq, NULL);
6861 }
6862
6863 /* WARNING!!!!  hash_enter is called with a method, and will peek
6864    inside to find its selector!  But hash_lookup is given a selector
6865    directly, and looks for the selector that's inside the found
6866    entry's key (method) for comparison.  */
6867
6868 static void
6869 hash_enter (hash *hashlist, tree method)
6870 {
6871   hash obj;
6872   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6873
6874   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6875   obj->list = 0;
6876   obj->next = hashlist[slot];
6877   obj->key = method;
6878
6879   hashlist[slot] = obj;         /* append to front */
6880 }
6881
6882 static hash
6883 hash_lookup (hash *hashlist, tree sel_name)
6884 {
6885   hash target;
6886
6887   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6888
6889   while (target)
6890     {
6891       if (sel_name == METHOD_SEL_NAME (target->key))
6892         return target;
6893
6894       target = target->next;
6895     }
6896   return 0;
6897 }
6898
6899 static void
6900 hash_add_attr (hash entry, tree value)
6901 {
6902   attr obj;
6903
6904   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6905   obj->next = entry->list;
6906   obj->value = value;
6907
6908   entry->list = obj;            /* append to front */
6909 }
6910 \f
6911 static tree
6912 lookup_method (tree mchain, tree method)
6913 {
6914   tree key;
6915
6916   if (TREE_CODE (method) == IDENTIFIER_NODE)
6917     key = method;
6918   else
6919     key = METHOD_SEL_NAME (method);
6920
6921   while (mchain)
6922     {
6923       if (METHOD_SEL_NAME (mchain) == key)
6924         return mchain;
6925
6926       mchain = TREE_CHAIN (mchain);
6927     }
6928   return NULL_TREE;
6929 }
6930
6931 /* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
6932    in INTERFACE, along with any categories and protocols attached thereto.
6933    If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
6934    recursively examine the INTERFACE's superclass.  If OBJC_LOOKUP_CLASS is
6935    set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
6936    be found in INTERFACE or any of its superclasses, look for an _instance_
6937    method of the same name in the root class as a last resort.
6938
6939    If a suitable method cannot be found, return NULL_TREE.  */
6940
6941 static tree
6942 lookup_method_static (tree interface, tree ident, int flags)
6943 {
6944   tree meth = NULL_TREE, root_inter = NULL_TREE;
6945   tree inter = interface;
6946   int is_class = (flags & OBJC_LOOKUP_CLASS);
6947   int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
6948
6949   while (inter)
6950     {
6951       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6952       tree category = inter;
6953
6954       /* First, look up the method in the class itself.  */
6955       if ((meth = lookup_method (chain, ident)))
6956         return meth;
6957
6958       /* Failing that, look for the method in each category of the class.  */
6959       while ((category = CLASS_CATEGORY_LIST (category)))
6960         {
6961           chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6962
6963           /* Check directly in each category.  */
6964           if ((meth = lookup_method (chain, ident)))
6965             return meth;
6966
6967           /* Failing that, check in each category's protocols.  */
6968           if (CLASS_PROTOCOL_LIST (category))
6969             {
6970               if ((meth = (lookup_method_in_protocol_list
6971                            (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6972                 return meth;
6973             }
6974         }
6975
6976       /* If not found in categories, check in protocols of the main class.  */
6977       if (CLASS_PROTOCOL_LIST (inter))
6978         {
6979           if ((meth = (lookup_method_in_protocol_list
6980                        (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6981             return meth;
6982         }
6983
6984       /* If we were instructed not to look in superclasses, don't.  */
6985       if (no_superclasses)
6986         return NULL_TREE;
6987
6988       /* Failing that, climb up the inheritance hierarchy.  */
6989       root_inter = inter;
6990       inter = lookup_interface (CLASS_SUPER_NAME (inter));
6991     }
6992   while (inter);
6993
6994   /* If no class (factory) method was found, check if an _instance_
6995      method of the same name exists in the root class.  This is what
6996      the Objective-C runtime will do.  If an instance method was not
6997      found, return 0.  */
6998   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6999 }
7000
7001 /* Add the method to the hash list if it doesn't contain an identical
7002    method already. */
7003
7004 static void
7005 add_method_to_hash_list (hash *hash_list, tree method)
7006 {
7007   hash hsh;
7008
7009   if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
7010     {
7011       /* Install on a global chain.  */
7012       hash_enter (hash_list, method);
7013     }
7014   else
7015     {
7016       /* Check types against those; if different, add to a list.  */
7017       attr loop;
7018       int already_there = comp_proto_with_proto (method, hsh->key, 1);
7019       for (loop = hsh->list; !already_there && loop; loop = loop->next)
7020         already_there |= comp_proto_with_proto (method, loop->value, 1);
7021       if (!already_there)
7022         hash_add_attr (hsh, method);
7023     }
7024 }
7025
7026 static tree
7027 objc_add_method (tree klass, tree method, int is_class)
7028 {
7029   tree mth;
7030
7031   if (!(mth = lookup_method (is_class
7032                              ? CLASS_CLS_METHODS (klass)
7033                              : CLASS_NST_METHODS (klass), method)))
7034     {
7035       /* put method on list in reverse order */
7036       if (is_class)
7037         {
7038           TREE_CHAIN (method) = CLASS_CLS_METHODS (klass);
7039           CLASS_CLS_METHODS (klass) = method;
7040         }
7041       else
7042         {
7043           TREE_CHAIN (method) = CLASS_NST_METHODS (klass);
7044           CLASS_NST_METHODS (klass) = method;
7045         }
7046     }
7047   else
7048     {
7049       /* When processing an @interface for a class or category, give hard
7050          errors on methods with identical selectors but differing argument
7051          and/or return types. We do not do this for @implementations, because
7052          C/C++ will do it for us (i.e., there will be duplicate function
7053          definition errors).  */
7054       if ((TREE_CODE (klass) == CLASS_INTERFACE_TYPE
7055            || TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE)
7056           && !comp_proto_with_proto (method, mth, 1))
7057         error ("duplicate declaration of method %<%c%E%>",
7058                 is_class ? '+' : '-',
7059                 METHOD_SEL_NAME (mth));
7060     }
7061
7062   if (is_class)
7063     add_method_to_hash_list (cls_method_hash_list, method);
7064   else
7065     {
7066       add_method_to_hash_list (nst_method_hash_list, method);
7067
7068       /* Instance methods in root classes (and categories thereof)
7069          may act as class methods as a last resort.  We also add
7070          instance methods listed in @protocol declarations to
7071          the class hash table, on the assumption that @protocols
7072          may be adopted by root classes or categories.  */
7073       if (TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE
7074           || TREE_CODE (klass) == CATEGORY_IMPLEMENTATION_TYPE)
7075         klass = lookup_interface (CLASS_NAME (klass));
7076
7077       if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE
7078           || !CLASS_SUPER_NAME (klass))
7079         add_method_to_hash_list (cls_method_hash_list, method);
7080     }
7081
7082   return method;
7083 }
7084
7085 static tree
7086 add_class (tree class_name, tree name)
7087 {
7088   struct interface_tuple **slot;
7089
7090   /* Put interfaces on list in reverse order.  */
7091   TREE_CHAIN (class_name) = interface_chain;
7092   interface_chain = class_name;
7093
7094   if (interface_htab == NULL)
7095     interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
7096   slot = (struct interface_tuple **)
7097     htab_find_slot_with_hash (interface_htab, name,
7098                               IDENTIFIER_HASH_VALUE (name),
7099                               INSERT);
7100   if (!*slot)
7101     {
7102       *slot = (struct interface_tuple *) ggc_alloc_cleared (sizeof (struct interface_tuple));
7103       (*slot)->id = name;
7104     }
7105   (*slot)->class_name = class_name;
7106
7107   return interface_chain;
7108 }
7109
7110 static void
7111 add_category (tree klass, tree category)
7112 {
7113   /* Put categories on list in reverse order.  */
7114   tree cat = lookup_category (klass, CLASS_SUPER_NAME (category));
7115
7116   if (cat)
7117     {
7118       warning (0, "duplicate interface declaration for category %<%E(%E)%>",
7119                CLASS_NAME (klass),
7120                CLASS_SUPER_NAME (category));
7121     }
7122   else
7123     {
7124       CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (klass);
7125       CLASS_CATEGORY_LIST (klass) = category;
7126     }
7127 }
7128
7129 /* Called after parsing each instance variable declaration. Necessary to
7130    preserve typedefs and implement public/private...
7131
7132    VISIBILITY is 1 for public, 0 for protected, and 2 for private.  */
7133
7134 static tree
7135 add_instance_variable (tree klass, int visibility, tree field_decl)
7136 {
7137   tree field_type = TREE_TYPE (field_decl);
7138   const char *ivar_name = DECL_NAME (field_decl)
7139                           ? identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (field_decl)))
7140                           : _("<unnamed>");
7141
7142 #ifdef OBJCPLUS
7143   if (TREE_CODE (field_type) == REFERENCE_TYPE)
7144     {
7145       error ("illegal reference type specified for instance variable %qs",
7146              ivar_name);
7147       /* Return class as is without adding this ivar.  */
7148       return klass;
7149     }
7150 #endif
7151
7152   if (field_type == error_mark_node || !TYPE_SIZE (field_type)
7153       || TYPE_SIZE (field_type) == error_mark_node)
7154       /* 'type[0]' is allowed, but 'type[]' is not! */
7155     {
7156       error ("instance variable %qs has unknown size", ivar_name);
7157       /* Return class as is without adding this ivar.  */
7158       return klass;
7159     }
7160
7161 #ifdef OBJCPLUS
7162   /* Check if the ivar being added has a non-POD C++ type.   If so, we will
7163      need to either (1) warn the user about it or (2) generate suitable
7164      constructor/destructor call from '- .cxx_construct' or '- .cxx_destruct'
7165      methods (if '-fobjc-call-cxx-cdtors' was specified).  */
7166   if (MAYBE_CLASS_TYPE_P (field_type)
7167       && (TYPE_NEEDS_CONSTRUCTING (field_type)
7168           || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)
7169           || TYPE_POLYMORPHIC_P (field_type)))
7170     {
7171       tree type_name = OBJC_TYPE_NAME (field_type);
7172
7173       if (flag_objc_call_cxx_cdtors)
7174         {
7175           /* Since the ObjC runtime will be calling the constructors and
7176              destructors for us, the only thing we can't handle is the lack
7177              of a default constructor.  */
7178           if (TYPE_NEEDS_CONSTRUCTING (field_type)
7179               && !TYPE_HAS_DEFAULT_CONSTRUCTOR (field_type))
7180             {
7181               warning (0, "type %qE has no default constructor to call",
7182                        type_name);
7183
7184               /* If we cannot call a constructor, we should also avoid
7185                  calling the destructor, for symmetry.  */
7186               if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7187                 warning (0, "destructor for %qE shall not be run either",
7188                          type_name);
7189             }
7190         }
7191       else
7192         {
7193           static bool warn_cxx_ivars = false;
7194
7195           if (TYPE_POLYMORPHIC_P (field_type))
7196             {
7197               /* Vtable pointers are Real Bad(tm), since Obj-C cannot
7198                  initialize them.  */
7199               error ("type %qE has virtual member functions", type_name);
7200               error ("illegal aggregate type %qE specified "
7201                      "for instance variable %qs",
7202                      type_name, ivar_name);
7203               /* Return class as is without adding this ivar.  */
7204               return klass;
7205             }
7206
7207           /* User-defined constructors and destructors are not known to Obj-C
7208              and hence will not be called.  This may or may not be a problem. */
7209           if (TYPE_NEEDS_CONSTRUCTING (field_type))
7210             warning (0, "type %qE has a user-defined constructor", type_name);
7211           if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7212             warning (0, "type %qE has a user-defined destructor", type_name);
7213
7214           if (!warn_cxx_ivars)
7215             {
7216               warning (0, "C++ constructors and destructors will not "
7217                        "be invoked for Objective-C fields");
7218               warn_cxx_ivars = true;
7219             }
7220         }
7221     }
7222 #endif
7223
7224   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
7225   switch (visibility)
7226     {
7227     case 0:
7228       TREE_PUBLIC (field_decl) = 0;
7229       TREE_PRIVATE (field_decl) = 0;
7230       TREE_PROTECTED (field_decl) = 1;
7231       break;
7232
7233     case 1:
7234       TREE_PUBLIC (field_decl) = 1;
7235       TREE_PRIVATE (field_decl) = 0;
7236       TREE_PROTECTED (field_decl) = 0;
7237       break;
7238
7239     case 2:
7240       TREE_PUBLIC (field_decl) = 0;
7241       TREE_PRIVATE (field_decl) = 1;
7242       TREE_PROTECTED (field_decl) = 0;
7243       break;
7244
7245     }
7246
7247   CLASS_RAW_IVARS (klass) = chainon (CLASS_RAW_IVARS (klass), field_decl);
7248
7249   return klass;
7250 }
7251 \f
7252 static tree
7253 is_ivar (tree decl_chain, tree ident)
7254 {
7255   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
7256     if (DECL_NAME (decl_chain) == ident)
7257       return decl_chain;
7258   return NULL_TREE;
7259 }
7260
7261 /* True if the ivar is private and we are not in its implementation.  */
7262
7263 static int
7264 is_private (tree decl)
7265 {
7266   return (TREE_PRIVATE (decl)
7267           && ! is_ivar (CLASS_IVARS (implementation_template),
7268                         DECL_NAME (decl)));
7269 }
7270
7271 /* We have an instance variable reference;, check to see if it is public.  */
7272
7273 int
7274 objc_is_public (tree expr, tree identifier)
7275 {
7276   tree basetype, decl;
7277
7278 #ifdef OBJCPLUS
7279   if (processing_template_decl)
7280     return 1;
7281 #endif
7282
7283   if (TREE_TYPE (expr) == error_mark_node)
7284     return 1;
7285
7286   basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
7287
7288   if (basetype && TREE_CODE (basetype) == RECORD_TYPE)
7289     {
7290       if (TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
7291         {
7292           tree klass = lookup_interface (OBJC_TYPE_NAME (basetype));
7293
7294           if (!klass)
7295             {
7296               error ("cannot find interface declaration for %qE",
7297                      OBJC_TYPE_NAME (basetype));
7298               return 0;
7299             }
7300
7301           if ((decl = is_ivar (get_class_ivars (klass, true), identifier)))
7302             {
7303               if (TREE_PUBLIC (decl))
7304                 return 1;
7305
7306               /* Important difference between the Stepstone translator:
7307                  all instance variables should be public within the context
7308                  of the implementation.  */
7309               if (objc_implementation_context
7310                  && ((TREE_CODE (objc_implementation_context)
7311                       == CLASS_IMPLEMENTATION_TYPE)
7312                      || (TREE_CODE (objc_implementation_context)
7313                          == CATEGORY_IMPLEMENTATION_TYPE)))
7314                 {
7315                   tree curtype = TYPE_MAIN_VARIANT
7316                                  (CLASS_STATIC_TEMPLATE
7317                                   (implementation_template));
7318
7319                   if (basetype == curtype
7320                       || DERIVED_FROM_P (basetype, curtype))
7321                     {
7322                       int priv = is_private (decl);
7323
7324                       if (priv)
7325                         error ("instance variable %qE is declared private",
7326                                DECL_NAME (decl));
7327
7328                       return !priv;
7329                     }
7330                 }
7331
7332               /* The 2.95.2 compiler sometimes allowed C functions to access
7333                  non-@public ivars.  We will let this slide for now...  */
7334               if (!objc_method_context)
7335               {
7336                 warning (0, "instance variable %qE is %s; "
7337                          "this will be a hard error in the future",
7338                          identifier,
7339                          TREE_PRIVATE (decl) ? "@private" : "@protected");
7340                 return 1;
7341               }
7342
7343               error ("instance variable %qE is declared %s",
7344                      identifier,
7345                      TREE_PRIVATE (decl) ? "private" : "protected");
7346               return 0;
7347             }
7348         }
7349     }
7350
7351   return 1;
7352 }
7353 \f
7354 /* Make sure all entries in CHAIN are also in LIST.  */
7355
7356 static int
7357 check_methods (tree chain, tree list, int mtype)
7358 {
7359   int first = 1;
7360
7361   while (chain)
7362     {
7363       if (!lookup_method (list, chain))
7364         {
7365           if (first)
7366             {
7367               if (TREE_CODE (objc_implementation_context)
7368                   == CLASS_IMPLEMENTATION_TYPE)
7369                 warning (0, "incomplete implementation of class %qE",
7370                          CLASS_NAME (objc_implementation_context));
7371               else if (TREE_CODE (objc_implementation_context)
7372                        == CATEGORY_IMPLEMENTATION_TYPE)
7373                 warning (0, "incomplete implementation of category %qE",
7374                          CLASS_SUPER_NAME (objc_implementation_context));
7375               first = 0;
7376             }
7377
7378           warning (0, "method definition for %<%c%E%> not found",
7379                    mtype, METHOD_SEL_NAME (chain));
7380         }
7381
7382       chain = TREE_CHAIN (chain);
7383     }
7384
7385     return first;
7386 }
7387
7388 /* Check if KLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
7389
7390 static int
7391 conforms_to_protocol (tree klass, tree protocol)
7392 {
7393    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
7394      {
7395        tree p = CLASS_PROTOCOL_LIST (klass);
7396        while (p && TREE_VALUE (p) != protocol)
7397          p = TREE_CHAIN (p);
7398
7399        if (!p)
7400          {
7401            tree super = (CLASS_SUPER_NAME (klass)
7402                          ? lookup_interface (CLASS_SUPER_NAME (klass))
7403                          : NULL_TREE);
7404            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
7405            if (!tmp)
7406              return 0;
7407          }
7408      }
7409
7410    return 1;
7411 }
7412
7413 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
7414    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
7415
7416 static int
7417 check_methods_accessible (tree chain, tree context, int mtype)
7418 {
7419   int first = 1;
7420   tree list;
7421   tree base_context = context;
7422
7423   while (chain)
7424     {
7425       context = base_context;
7426       while (context)
7427         {
7428           if (mtype == '+')
7429             list = CLASS_CLS_METHODS (context);
7430           else
7431             list = CLASS_NST_METHODS (context);
7432
7433           if (lookup_method (list, chain))
7434               break;
7435
7436           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
7437                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
7438             context = (CLASS_SUPER_NAME (context)
7439                        ? lookup_interface (CLASS_SUPER_NAME (context))
7440                        : NULL_TREE);
7441
7442           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
7443                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
7444             context = (CLASS_NAME (context)
7445                        ? lookup_interface (CLASS_NAME (context))
7446                        : NULL_TREE);
7447           else
7448             abort ();
7449         }
7450
7451       if (context == NULL_TREE)
7452         {
7453           if (first)
7454             {
7455               if (TREE_CODE (objc_implementation_context)
7456                   == CLASS_IMPLEMENTATION_TYPE)
7457                 warning (0, "incomplete implementation of class %qE",
7458                          CLASS_NAME (objc_implementation_context));
7459               else if (TREE_CODE (objc_implementation_context)
7460                        == CATEGORY_IMPLEMENTATION_TYPE)
7461                 warning (0, "incomplete implementation of category %qE",
7462                          CLASS_SUPER_NAME (objc_implementation_context));
7463               first = 0;
7464             }
7465           warning (0, "method definition for %<%c%E%> not found",
7466                    mtype, METHOD_SEL_NAME (chain));
7467         }
7468
7469       chain = TREE_CHAIN (chain); /* next method...  */
7470     }
7471   return first;
7472 }
7473
7474 /* Check whether the current interface (accessible via
7475    'objc_implementation_context') actually implements protocol P, along
7476    with any protocols that P inherits.  */
7477
7478 static void
7479 check_protocol (tree p, const char *type, tree name)
7480 {
7481   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
7482     {
7483       int f1, f2;
7484
7485       /* Ensure that all protocols have bodies!  */
7486       if (warn_protocol)
7487         {
7488           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
7489                               CLASS_CLS_METHODS (objc_implementation_context),
7490                               '+');
7491           f2 = check_methods (PROTOCOL_NST_METHODS (p),
7492                               CLASS_NST_METHODS (objc_implementation_context),
7493                               '-');
7494         }
7495       else
7496         {
7497           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
7498                                          objc_implementation_context,
7499                                          '+');
7500           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
7501                                          objc_implementation_context,
7502                                          '-');
7503         }
7504
7505       if (!f1 || !f2)
7506         warning (0, "%s %qE does not fully implement the %qE protocol",
7507                  type, name, PROTOCOL_NAME (p));
7508     }
7509
7510   /* Check protocols recursively.  */
7511   if (PROTOCOL_LIST (p))
7512     {
7513       tree subs = PROTOCOL_LIST (p);
7514       tree super_class =
7515         lookup_interface (CLASS_SUPER_NAME (implementation_template));
7516
7517       while (subs)
7518         {
7519           tree sub = TREE_VALUE (subs);
7520
7521           /* If the superclass does not conform to the protocols
7522              inherited by P, then we must!  */
7523           if (!super_class || !conforms_to_protocol (super_class, sub))
7524             check_protocol (sub, type, name);
7525           subs = TREE_CHAIN (subs);
7526         }
7527     }
7528 }
7529
7530 /* Check whether the current interface (accessible via
7531    'objc_implementation_context') actually implements the protocols listed
7532    in PROTO_LIST.  */
7533
7534 static void
7535 check_protocols (tree proto_list, const char *type, tree name)
7536 {
7537   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
7538     {
7539       tree p = TREE_VALUE (proto_list);
7540
7541       check_protocol (p, type, name);
7542     }
7543 }
7544 \f
7545 /* Make sure that the class CLASS_NAME is defined
7546    CODE says which kind of thing CLASS_NAME ought to be.
7547    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
7548    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
7549
7550 static tree
7551 start_class (enum tree_code code, tree class_name, tree super_name,
7552              tree protocol_list)
7553 {
7554   tree klass, decl;
7555
7556 #ifdef OBJCPLUS
7557   if (current_namespace != global_namespace) {
7558     error ("Objective-C declarations may only appear in global scope");
7559   }
7560 #endif /* OBJCPLUS */
7561
7562   if (objc_implementation_context)
7563     {
7564       warning (0, "%<@end%> missing in implementation context");
7565       finish_class (objc_implementation_context);
7566       objc_ivar_chain = NULL_TREE;
7567       objc_implementation_context = NULL_TREE;
7568     }
7569
7570   klass = make_node (code);
7571   TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
7572
7573   /* Check for existence of the super class, if one was specified.  Note
7574      that we must have seen an @interface, not just a @class.  If we
7575      are looking at a @compatibility_alias, traverse it first.  */
7576   if ((code == CLASS_INTERFACE_TYPE || code == CLASS_IMPLEMENTATION_TYPE)
7577       && super_name)
7578     {
7579       tree super = objc_is_class_name (super_name);
7580
7581       if (!super || !lookup_interface (super))
7582         {
7583           error ("cannot find interface declaration for %qE, superclass of %qE",
7584                  super ? super : super_name,
7585                  class_name);
7586           super_name = NULL_TREE;
7587         }
7588       else
7589         super_name = super;
7590     }
7591
7592   CLASS_NAME (klass) = class_name;
7593   CLASS_SUPER_NAME (klass) = super_name;
7594   CLASS_CLS_METHODS (klass) = NULL_TREE;
7595
7596   if (! objc_is_class_name (class_name)
7597       && (decl = lookup_name (class_name)))
7598     {
7599       error ("%qE redeclared as different kind of symbol",
7600              class_name);
7601       error ("previous declaration of %q+D",
7602              decl);
7603     }
7604
7605   if (code == CLASS_IMPLEMENTATION_TYPE)
7606     {
7607       {
7608         tree chain;
7609
7610         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
7611            if (TREE_VALUE (chain) == class_name)
7612              {
7613                error ("reimplementation of class %qE",
7614                       class_name);
7615                return error_mark_node;
7616              }
7617         implemented_classes = tree_cons (NULL_TREE, class_name,
7618                                          implemented_classes);
7619       }
7620
7621       /* Reset for multiple classes per file.  */
7622       method_slot = 0;
7623
7624       objc_implementation_context = klass;
7625
7626       /* Lookup the interface for this implementation.  */
7627
7628       if (!(implementation_template = lookup_interface (class_name)))
7629         {
7630           warning (0, "cannot find interface declaration for %qE",
7631                    class_name);
7632           add_class (implementation_template = objc_implementation_context,
7633                      class_name);
7634         }
7635
7636       /* If a super class has been specified in the implementation,
7637          insure it conforms to the one specified in the interface.  */
7638
7639       if (super_name
7640           && (super_name != CLASS_SUPER_NAME (implementation_template)))
7641         {
7642           tree previous_name = CLASS_SUPER_NAME (implementation_template);
7643           error ("conflicting super class name %qE",
7644                  super_name);
7645           if (previous_name)
7646             error ("previous declaration of %qE", previous_name);
7647           else
7648             error ("previous declaration");
7649         }
7650
7651       else if (! super_name)
7652         {
7653           CLASS_SUPER_NAME (objc_implementation_context)
7654             = CLASS_SUPER_NAME (implementation_template);
7655         }
7656     }
7657
7658   else if (code == CLASS_INTERFACE_TYPE)
7659     {
7660       if (lookup_interface (class_name))
7661 #ifdef OBJCPLUS
7662         error ("duplicate interface declaration for class %qE",
7663 #else
7664         warning (0, "duplicate interface declaration for class %qE",
7665 #endif
7666         class_name);
7667       else
7668         add_class (klass, class_name);
7669
7670       if (protocol_list)
7671         CLASS_PROTOCOL_LIST (klass)
7672           = lookup_and_install_protocols (protocol_list);
7673     }
7674
7675   else if (code == CATEGORY_INTERFACE_TYPE)
7676     {
7677       tree class_category_is_assoc_with;
7678
7679       /* For a category, class_name is really the name of the class that
7680          the following set of methods will be associated with. We must
7681          find the interface so that can derive the objects template.  */
7682
7683       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
7684         {
7685           error ("cannot find interface declaration for %qE",
7686                  class_name);
7687           exit (FATAL_EXIT_CODE);
7688         }
7689       else
7690         add_category (class_category_is_assoc_with, klass);
7691
7692       if (protocol_list)
7693         CLASS_PROTOCOL_LIST (klass)
7694           = lookup_and_install_protocols (protocol_list);
7695     }
7696
7697   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
7698     {
7699       /* Reset for multiple classes per file.  */
7700       method_slot = 0;
7701
7702       objc_implementation_context = klass;
7703
7704       /* For a category, class_name is really the name of the class that
7705          the following set of methods will be associated with.  We must
7706          find the interface so that can derive the objects template.  */
7707
7708       if (!(implementation_template = lookup_interface (class_name)))
7709         {
7710           error ("cannot find interface declaration for %qE",
7711                  class_name);
7712           exit (FATAL_EXIT_CODE);
7713         }
7714     }
7715   return klass;
7716 }
7717
7718 static tree
7719 continue_class (tree klass)
7720 {
7721   if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE
7722       || TREE_CODE (klass) == CATEGORY_IMPLEMENTATION_TYPE)
7723     {
7724       struct imp_entry *imp_entry;
7725
7726       /* Check consistency of the instance variables.  */
7727
7728       if (CLASS_RAW_IVARS (klass))
7729         check_ivars (implementation_template, klass);
7730
7731       /* code generation */
7732
7733 #ifdef OBJCPLUS
7734       push_lang_context (lang_name_c);
7735 #endif
7736
7737       build_private_template (implementation_template);
7738       uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
7739       objc_instance_type = build_pointer_type (uprivate_record);
7740
7741       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
7742
7743       imp_entry->next = imp_list;
7744       imp_entry->imp_context = klass;
7745       imp_entry->imp_template = implementation_template;
7746
7747       synth_forward_declarations ();
7748       imp_entry->class_decl = UOBJC_CLASS_decl;
7749       imp_entry->meta_decl = UOBJC_METACLASS_decl;
7750       imp_entry->has_cxx_cdtors = 0;
7751
7752       /* Append to front and increment count.  */
7753       imp_list = imp_entry;
7754       if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
7755         imp_count++;
7756       else
7757         cat_count++;
7758
7759 #ifdef OBJCPLUS
7760       pop_lang_context ();
7761 #endif /* OBJCPLUS */
7762
7763       return get_class_ivars (implementation_template, true);
7764     }
7765
7766   else if (TREE_CODE (klass) == CLASS_INTERFACE_TYPE)
7767     {
7768 #ifdef OBJCPLUS
7769       push_lang_context (lang_name_c);
7770 #endif /* OBJCPLUS */
7771
7772       build_private_template (klass);
7773
7774 #ifdef OBJCPLUS
7775       pop_lang_context ();
7776 #endif /* OBJCPLUS */
7777
7778       return NULL_TREE;
7779     }
7780
7781   else
7782     return error_mark_node;
7783 }
7784
7785 /* This is called once we see the "@end" in an interface/implementation.  */
7786
7787 static void
7788 finish_class (tree klass)
7789 {
7790   if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
7791     {
7792       /* All code generation is done in finish_objc.  */
7793
7794       if (implementation_template != objc_implementation_context)
7795         {
7796           /* Ensure that all method listed in the interface contain bodies.  */
7797           check_methods (CLASS_CLS_METHODS (implementation_template),
7798                          CLASS_CLS_METHODS (objc_implementation_context), '+');
7799           check_methods (CLASS_NST_METHODS (implementation_template),
7800                          CLASS_NST_METHODS (objc_implementation_context), '-');
7801
7802           if (CLASS_PROTOCOL_LIST (implementation_template))
7803             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
7804                              "class",
7805                              CLASS_NAME (objc_implementation_context));
7806         }
7807     }
7808
7809   else if (TREE_CODE (klass) == CATEGORY_IMPLEMENTATION_TYPE)
7810     {
7811       tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (klass));
7812
7813       if (category)
7814         {
7815           /* Ensure all method listed in the interface contain bodies.  */
7816           check_methods (CLASS_CLS_METHODS (category),
7817                          CLASS_CLS_METHODS (objc_implementation_context), '+');
7818           check_methods (CLASS_NST_METHODS (category),
7819                          CLASS_NST_METHODS (objc_implementation_context), '-');
7820
7821           if (CLASS_PROTOCOL_LIST (category))
7822             check_protocols (CLASS_PROTOCOL_LIST (category),
7823                              "category",
7824                              CLASS_SUPER_NAME (objc_implementation_context));
7825         }
7826     }
7827 }
7828
7829 static tree
7830 add_protocol (tree protocol)
7831 {
7832   /* Put protocol on list in reverse order.  */
7833   TREE_CHAIN (protocol) = protocol_chain;
7834   protocol_chain = protocol;
7835   return protocol_chain;
7836 }
7837
7838 static tree
7839 lookup_protocol (tree ident)
7840 {
7841   tree chain;
7842
7843   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7844     if (ident == PROTOCOL_NAME (chain))
7845       return chain;
7846
7847   return NULL_TREE;
7848 }
7849
7850 /* This function forward declares the protocols named by NAMES.  If
7851    they are already declared or defined, the function has no effect.  */
7852
7853 void
7854 objc_declare_protocols (tree names)
7855 {
7856   tree list;
7857
7858 #ifdef OBJCPLUS
7859   if (current_namespace != global_namespace) {
7860     error ("Objective-C declarations may only appear in global scope");
7861   }
7862 #endif /* OBJCPLUS */
7863
7864   for (list = names; list; list = TREE_CHAIN (list))
7865     {
7866       tree name = TREE_VALUE (list);
7867
7868       if (lookup_protocol (name) == NULL_TREE)
7869         {
7870           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7871
7872           TYPE_LANG_SLOT_1 (protocol)
7873             = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7874           PROTOCOL_NAME (protocol) = name;
7875           PROTOCOL_LIST (protocol) = NULL_TREE;
7876           add_protocol (protocol);
7877           PROTOCOL_DEFINED (protocol) = 0;
7878           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7879         }
7880     }
7881 }
7882
7883 static tree
7884 start_protocol (enum tree_code code, tree name, tree list)
7885 {
7886   tree protocol;
7887
7888 #ifdef OBJCPLUS
7889   if (current_namespace != global_namespace) {
7890     error ("Objective-C declarations may only appear in global scope");
7891   }
7892 #endif /* OBJCPLUS */
7893
7894   protocol = lookup_protocol (name);
7895
7896   if (!protocol)
7897     {
7898       protocol = make_node (code);
7899       TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7900
7901       PROTOCOL_NAME (protocol) = name;
7902       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7903       add_protocol (protocol);
7904       PROTOCOL_DEFINED (protocol) = 1;
7905       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7906
7907       check_protocol_recursively (protocol, list);
7908     }
7909   else if (! PROTOCOL_DEFINED (protocol))
7910     {
7911       PROTOCOL_DEFINED (protocol) = 1;
7912       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7913
7914       check_protocol_recursively (protocol, list);
7915     }
7916   else
7917     {
7918       warning (0, "duplicate declaration for protocol %qE",
7919                name);
7920     }
7921   return protocol;
7922 }
7923
7924 \f
7925 /* "Encode" a data type into a string, which grows in util_obstack.
7926    ??? What is the FORMAT?  Someone please document this!  */
7927
7928 static void
7929 encode_type_qualifiers (tree declspecs)
7930 {
7931   tree spec;
7932
7933   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7934     {
7935       if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7936         obstack_1grow (&util_obstack, 'n');
7937       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7938         obstack_1grow (&util_obstack, 'N');
7939       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7940         obstack_1grow (&util_obstack, 'o');
7941       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7942         obstack_1grow (&util_obstack, 'O');
7943       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7944         obstack_1grow (&util_obstack, 'R');
7945       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7946         obstack_1grow (&util_obstack, 'V');
7947     }
7948 }
7949
7950 /* Encode a pointer type.  */
7951
7952 static void
7953 encode_pointer (tree type, int curtype, int format)
7954 {
7955   tree pointer_to = TREE_TYPE (type);
7956
7957   if (TREE_CODE (pointer_to) == RECORD_TYPE)
7958     {
7959       if (OBJC_TYPE_NAME (pointer_to)
7960           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7961         {
7962           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7963
7964           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7965             {
7966               obstack_1grow (&util_obstack, '@');
7967               return;
7968             }
7969           else if (TYPE_HAS_OBJC_INFO (pointer_to)
7970                    && TYPE_OBJC_INTERFACE (pointer_to))
7971             {
7972               if (generating_instance_variables)
7973                 {
7974                   obstack_1grow (&util_obstack, '@');
7975                   obstack_1grow (&util_obstack, '"');
7976                   obstack_grow (&util_obstack, name, strlen (name));
7977                   obstack_1grow (&util_obstack, '"');
7978                   return;
7979                 }
7980               else
7981                 {
7982                   obstack_1grow (&util_obstack, '@');
7983                   return;
7984                 }
7985             }
7986           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7987             {
7988               obstack_1grow (&util_obstack, '#');
7989               return;
7990             }
7991           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7992             {
7993               obstack_1grow (&util_obstack, ':');
7994               return;
7995             }
7996         }
7997     }
7998   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7999            && TYPE_MODE (pointer_to) == QImode)
8000     {
8001       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
8002                   ? OBJC_TYPE_NAME (pointer_to)
8003                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
8004
8005       if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
8006         {
8007           /* It appears that "r*" means "const char *" rather than
8008              "char *const".  */
8009           if (TYPE_READONLY (pointer_to))
8010             obstack_1grow (&util_obstack, 'r');
8011
8012           obstack_1grow (&util_obstack, '*');
8013           return;
8014         }
8015     }
8016
8017   /* We have a type that does not get special treatment.  */
8018
8019   /* NeXT extension */
8020   obstack_1grow (&util_obstack, '^');
8021   encode_type (pointer_to, curtype, format);
8022 }
8023
8024 static void
8025 encode_array (tree type, int curtype, int format)
8026 {
8027   tree an_int_cst = TYPE_SIZE (type);
8028   tree array_of = TREE_TYPE (type);
8029   char buffer[40];
8030
8031   /* An incomplete array is treated like a pointer.  */
8032   if (an_int_cst == NULL)
8033     {
8034       encode_pointer (type, curtype, format);
8035       return;
8036     }
8037
8038   if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
8039    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
8040   else
8041     sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
8042              TREE_INT_CST_LOW (an_int_cst)
8043               / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
8044
8045   obstack_grow (&util_obstack, buffer, strlen (buffer));
8046   encode_type (array_of, curtype, format);
8047   obstack_1grow (&util_obstack, ']');
8048   return;
8049 }
8050 \f
8051 static void
8052 encode_aggregate_fields (tree type, int pointed_to, int curtype, int format)
8053 {
8054   tree field = TYPE_FIELDS (type);
8055
8056   for (; field; field = TREE_CHAIN (field))
8057     {
8058 #ifdef OBJCPLUS
8059       /* C++ static members, and things that are not field at all,
8060          should not appear in the encoding.  */
8061       if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
8062         continue;
8063 #endif
8064
8065       /* Recursively encode fields of embedded base classes.  */
8066       if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
8067           && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
8068         {
8069           encode_aggregate_fields (TREE_TYPE (field),
8070                                    pointed_to, curtype, format);
8071           continue;
8072         }
8073
8074       if (generating_instance_variables && !pointed_to)
8075         {
8076           tree fname = DECL_NAME (field);
8077
8078           obstack_1grow (&util_obstack, '"');
8079
8080           if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
8081             obstack_grow (&util_obstack,
8082                           IDENTIFIER_POINTER (fname),
8083                           strlen (IDENTIFIER_POINTER (fname)));
8084
8085           obstack_1grow (&util_obstack, '"');
8086         }
8087
8088       encode_field_decl (field, curtype, format);
8089     }
8090 }
8091
8092 static void
8093 encode_aggregate_within (tree type, int curtype, int format, int left,
8094                          int right)
8095 {
8096   tree name;
8097   /* NB: aggregates that are pointed to have slightly different encoding
8098      rules in that you never encode the names of instance variables.  */
8099   int ob_size = obstack_object_size (&util_obstack);
8100   char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
8101   char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
8102   int pointed_to = (c0 == '^' || (c1 == '^' && c0 == 'r'));
8103   int inline_contents
8104    = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
8105       && (!pointed_to || ob_size - curtype == (c1 == 'r' ? 2 : 1)));
8106
8107   /* Traverse struct aliases; it is important to get the
8108      original struct and its tag name (if any).  */
8109   type = TYPE_MAIN_VARIANT (type);
8110   name = OBJC_TYPE_NAME (type);
8111   /* Open parenth/bracket.  */
8112   obstack_1grow (&util_obstack, left);
8113
8114   /* Encode the struct/union tag name, or '?' if a tag was
8115      not provided.  Typedef aliases do not qualify.  */
8116   if (name && TREE_CODE (name) == IDENTIFIER_NODE
8117 #ifdef OBJCPLUS
8118       /* Did this struct have a tag?  */
8119       && !TYPE_WAS_ANONYMOUS (type)
8120 #endif
8121       )
8122     obstack_grow (&util_obstack,
8123                   IDENTIFIER_POINTER (name),
8124                   strlen (IDENTIFIER_POINTER (name)));
8125   else
8126     obstack_1grow (&util_obstack, '?');
8127
8128   /* Encode the types (and possibly names) of the inner fields,
8129      if required.  */
8130   if (inline_contents)
8131     {
8132       obstack_1grow (&util_obstack, '=');
8133       encode_aggregate_fields (type, pointed_to, curtype, format);
8134     }
8135   /* Close parenth/bracket.  */
8136   obstack_1grow (&util_obstack, right);
8137 }
8138
8139 static void
8140 encode_aggregate (tree type, int curtype, int format)
8141 {
8142   enum tree_code code = TREE_CODE (type);
8143
8144   switch (code)
8145     {
8146     case RECORD_TYPE:
8147       {
8148         encode_aggregate_within (type, curtype, format, '{', '}');
8149         break;
8150       }
8151     case UNION_TYPE:
8152       {
8153         encode_aggregate_within (type, curtype, format, '(', ')');
8154         break;
8155       }
8156
8157     case ENUMERAL_TYPE:
8158       obstack_1grow (&util_obstack, 'i');
8159       break;
8160
8161     default:
8162       break;
8163     }
8164 }
8165
8166 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
8167    field type.  */
8168
8169 static void
8170 encode_next_bitfield (int width)
8171 {
8172   char buffer[40];
8173   sprintf (buffer, "b%d", width);
8174   obstack_grow (&util_obstack, buffer, strlen (buffer));
8175 }
8176 \f
8177 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
8178 static void
8179 encode_type (tree type, int curtype, int format)
8180 {
8181   enum tree_code code = TREE_CODE (type);
8182   char c;
8183
8184   if (type == error_mark_node)
8185     return;
8186
8187   if (TYPE_READONLY (type))
8188     obstack_1grow (&util_obstack, 'r');
8189
8190   if (code == INTEGER_TYPE)
8191     {
8192       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
8193         {
8194         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
8195         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
8196         case 32:
8197           if (type == long_unsigned_type_node
8198               || type == long_integer_type_node)
8199                  c = TYPE_UNSIGNED (type) ? 'L' : 'l';
8200           else
8201                  c = TYPE_UNSIGNED (type) ? 'I' : 'i';
8202           break;
8203         case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
8204         default: abort ();
8205         }
8206       obstack_1grow (&util_obstack, c);
8207     }
8208
8209   else if (code == REAL_TYPE)
8210     {
8211       /* Floating point types.  */
8212       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
8213         {
8214         case 32:  c = 'f'; break;
8215         case 64:
8216         case 96:
8217         case 128: c = 'd'; break;
8218         default: abort ();
8219         }
8220       obstack_1grow (&util_obstack, c);
8221     }
8222
8223   else if (code == VOID_TYPE)
8224     obstack_1grow (&util_obstack, 'v');
8225
8226   else if (code == BOOLEAN_TYPE)
8227     obstack_1grow (&util_obstack, 'B');
8228
8229   else if (code == ARRAY_TYPE)
8230     encode_array (type, curtype, format);
8231
8232   else if (code == POINTER_TYPE)
8233     encode_pointer (type, curtype, format);
8234
8235   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
8236     encode_aggregate (type, curtype, format);
8237
8238   else if (code == FUNCTION_TYPE) /* '?' */
8239     obstack_1grow (&util_obstack, '?');
8240
8241   else if (code == COMPLEX_TYPE)
8242     {
8243       obstack_1grow (&util_obstack, 'j');
8244       encode_type (TREE_TYPE (type), curtype, format);
8245     }
8246 }
8247
8248 static void
8249 encode_gnu_bitfield (int position, tree type, int size)
8250 {
8251   enum tree_code code = TREE_CODE (type);
8252   char buffer[40];
8253   char charType = '?';
8254
8255   if (code == INTEGER_TYPE)
8256     {
8257       if (integer_zerop (TYPE_MIN_VALUE (type)))
8258         {
8259           /* Unsigned integer types.  */
8260
8261           if (TYPE_MODE (type) == QImode)
8262             charType = 'C';
8263           else if (TYPE_MODE (type) == HImode)
8264             charType = 'S';
8265           else if (TYPE_MODE (type) == SImode)
8266             {
8267               if (type == long_unsigned_type_node)
8268                 charType = 'L';
8269               else
8270                 charType = 'I';
8271             }
8272           else if (TYPE_MODE (type) == DImode)
8273             charType = 'Q';
8274         }
8275
8276       else
8277         /* Signed integer types.  */
8278         {
8279           if (TYPE_MODE (type) == QImode)
8280             charType = 'c';
8281           else if (TYPE_MODE (type) == HImode)
8282             charType = 's';
8283           else if (TYPE_MODE (type) == SImode)
8284             {
8285               if (type == long_integer_type_node)
8286                 charType = 'l';
8287               else
8288                 charType = 'i';
8289             }
8290
8291           else if (TYPE_MODE (type) == DImode)
8292             charType = 'q';
8293         }
8294     }
8295   else if (code == ENUMERAL_TYPE)
8296     charType = 'i';
8297   else
8298     abort ();
8299
8300   sprintf (buffer, "b%d%c%d", position, charType, size);
8301   obstack_grow (&util_obstack, buffer, strlen (buffer));
8302 }
8303
8304 static void
8305 encode_field_decl (tree field_decl, int curtype, int format)
8306 {
8307   tree type;
8308
8309 #ifdef OBJCPLUS
8310   /* C++ static members, and things that are not fields at all,
8311      should not appear in the encoding.  */
8312   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
8313     return;
8314 #endif
8315
8316   type = TREE_TYPE (field_decl);
8317
8318   /* Generate the bitfield typing information, if needed.  Note the difference
8319      between GNU and NeXT runtimes.  */
8320   if (DECL_BIT_FIELD_TYPE (field_decl))
8321     {
8322       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
8323
8324       if (flag_next_runtime)
8325         encode_next_bitfield (size);
8326       else
8327         encode_gnu_bitfield (int_bit_position (field_decl),
8328                                   DECL_BIT_FIELD_TYPE (field_decl), size);
8329     }
8330   else
8331     encode_type (TREE_TYPE (field_decl), curtype, format);
8332 }
8333
8334 static GTY(()) tree objc_parmlist = NULL_TREE;
8335
8336 /* Append PARM to a list of formal parameters of a method, making a necessary
8337    array-to-pointer adjustment along the way.  */
8338
8339 static void
8340 objc_push_parm (tree parm)
8341 {
8342   bool relayout_needed = false;
8343
8344   if (TREE_TYPE (parm) == error_mark_node)
8345     {
8346       objc_parmlist = chainon (objc_parmlist, parm);
8347       return;
8348     }
8349
8350   /* Decay arrays and functions into pointers.  */
8351   if (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE)
8352     {
8353       TREE_TYPE (parm) = build_pointer_type (TREE_TYPE (TREE_TYPE (parm)));
8354       relayout_needed = true;
8355     }
8356   else if (TREE_CODE (TREE_TYPE (parm)) == FUNCTION_TYPE)
8357     {
8358       TREE_TYPE (parm) = build_pointer_type (TREE_TYPE (parm));
8359       relayout_needed = true;
8360     }
8361
8362   if (relayout_needed)
8363     relayout_decl (parm);
8364   
8365
8366   DECL_ARG_TYPE (parm)
8367     = lang_hooks.types.type_promotes_to (TREE_TYPE (parm));
8368
8369   /* Record constancy and volatility.  */
8370   c_apply_type_quals_to_decl
8371   ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
8372    | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
8373    | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
8374
8375   objc_parmlist = chainon (objc_parmlist, parm);
8376 }
8377
8378 /* Retrieve the formal parameter list constructed via preceding calls to
8379    objc_push_parm().  */
8380
8381 #ifdef OBJCPLUS
8382 static tree
8383 objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
8384 #else
8385 static struct c_arg_info *
8386 objc_get_parm_info (int have_ellipsis)
8387 #endif
8388 {
8389 #ifdef OBJCPLUS
8390   tree parm_info = objc_parmlist;
8391   objc_parmlist = NULL_TREE;
8392
8393   return parm_info;
8394 #else
8395   tree parm_info = objc_parmlist;
8396   struct c_arg_info *arg_info;
8397   /* The C front-end requires an elaborate song and dance at
8398      this point.  */
8399   push_scope ();
8400   declare_parm_level ();
8401   while (parm_info)
8402     {
8403       tree next = TREE_CHAIN (parm_info);
8404
8405       TREE_CHAIN (parm_info) = NULL_TREE;
8406       parm_info = pushdecl (parm_info);
8407       finish_decl (parm_info, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
8408       parm_info = next;
8409     }
8410   arg_info = get_parm_info (have_ellipsis);
8411   pop_scope ();
8412   objc_parmlist = NULL_TREE;
8413   return arg_info;
8414 #endif
8415 }
8416
8417 /* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
8418    method definitions.  In the case of instance methods, we can be more
8419    specific as to the type of 'self'.  */
8420
8421 static void
8422 synth_self_and_ucmd_args (void)
8423 {
8424   tree self_type;
8425
8426   if (objc_method_context
8427       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
8428     self_type = objc_instance_type;
8429   else
8430     /* Really a `struct objc_class *'. However, we allow people to
8431        assign to self, which changes its type midstream.  */
8432     self_type = objc_object_type;
8433
8434   /* id self; */
8435   objc_push_parm (build_decl (input_location,
8436                               PARM_DECL, self_id, self_type));
8437
8438   /* SEL _cmd; */
8439   objc_push_parm (build_decl (input_location,
8440                               PARM_DECL, ucmd_id, objc_selector_type));
8441 }
8442
8443 /* Transform an Objective-C method definition into a static C function
8444    definition, synthesizing the first two arguments, "self" and "_cmd",
8445    in the process.  */
8446
8447 static void
8448 start_method_def (tree method)
8449 {
8450   tree parmlist;
8451 #ifdef OBJCPLUS
8452   tree parm_info;
8453 #else
8454   struct c_arg_info *parm_info;
8455 #endif
8456   int have_ellipsis = 0;
8457
8458   /* If we are defining a "dealloc" method in a non-root class, we
8459      will need to check if a [super dealloc] is missing, and warn if
8460      it is.  */
8461   if(CLASS_SUPER_NAME (objc_implementation_context)
8462      && !strcmp ("dealloc", IDENTIFIER_POINTER (METHOD_SEL_NAME (method))))
8463     should_call_super_dealloc = 1;
8464   else
8465     should_call_super_dealloc = 0;
8466
8467   /* Required to implement _msgSuper.  */
8468   objc_method_context = method;
8469   UOBJC_SUPER_decl = NULL_TREE;
8470
8471   /* Generate prototype declarations for arguments..."new-style".  */
8472   synth_self_and_ucmd_args ();
8473
8474   /* Generate argument declarations if a keyword_decl.  */
8475   parmlist = METHOD_SEL_ARGS (method);
8476   while (parmlist)
8477     {
8478       tree type = TREE_VALUE (TREE_TYPE (parmlist)), parm;
8479
8480       parm = build_decl (input_location,
8481                          PARM_DECL, KEYWORD_ARG_NAME (parmlist), type);
8482       objc_push_parm (parm);
8483       parmlist = TREE_CHAIN (parmlist);
8484     }
8485
8486   if (METHOD_ADD_ARGS (method))
8487     {
8488       tree akey;
8489
8490       for (akey = TREE_CHAIN (METHOD_ADD_ARGS (method));
8491            akey; akey = TREE_CHAIN (akey))
8492         {
8493           objc_push_parm (TREE_VALUE (akey));
8494         }
8495
8496       if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
8497         have_ellipsis = 1;
8498     }
8499
8500   parm_info = objc_get_parm_info (have_ellipsis);
8501
8502   really_start_method (objc_method_context, parm_info);
8503 }
8504
8505 /* Return 1 if TYPE1 is equivalent to TYPE2
8506    for purposes of method overloading.  */
8507
8508 static int
8509 objc_types_are_equivalent (tree type1, tree type2)
8510 {
8511   if (type1 == type2)
8512     return 1;
8513
8514   /* Strip away indirections.  */
8515   while ((TREE_CODE (type1) == ARRAY_TYPE || TREE_CODE (type1) == POINTER_TYPE)
8516          && (TREE_CODE (type1) == TREE_CODE (type2)))
8517     type1 = TREE_TYPE (type1), type2 = TREE_TYPE (type2);
8518   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
8519     return 0;
8520
8521   type1 = (TYPE_HAS_OBJC_INFO (type1)
8522            ? TYPE_OBJC_PROTOCOL_LIST (type1)
8523            : NULL_TREE);
8524   type2 = (TYPE_HAS_OBJC_INFO (type2)
8525            ? TYPE_OBJC_PROTOCOL_LIST (type2)
8526            : NULL_TREE);
8527
8528   if (list_length (type1) == list_length (type2))
8529     {
8530       for (; type2; type2 = TREE_CHAIN (type2))
8531         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
8532           return 0;
8533       return 1;
8534     }
8535   return 0;
8536 }
8537
8538 /* Return 1 if TYPE1 has the same size and alignment as TYPE2.  */
8539
8540 static int
8541 objc_types_share_size_and_alignment (tree type1, tree type2)
8542 {
8543   return (simple_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
8544           && TYPE_ALIGN (type1) == TYPE_ALIGN (type2));
8545 }
8546
8547 /* Return 1 if PROTO1 is equivalent to PROTO2
8548    for purposes of method overloading.  Ordinarily, the type signatures
8549    should match up exactly, unless STRICT is zero, in which case we
8550    shall allow differences in which the size and alignment of a type
8551    is the same.  */
8552
8553 static int
8554 comp_proto_with_proto (tree proto1, tree proto2, int strict)
8555 {
8556   tree type1, type2;
8557
8558   /* The following test is needed in case there are hashing
8559      collisions.  */
8560   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
8561     return 0;
8562
8563   /* Compare return types.  */
8564   type1 = TREE_VALUE (TREE_TYPE (proto1));
8565   type2 = TREE_VALUE (TREE_TYPE (proto2));
8566
8567   if (!objc_types_are_equivalent (type1, type2)
8568       && (strict || !objc_types_share_size_and_alignment (type1, type2)))
8569     return 0;
8570
8571   /* Compare argument types.  */
8572   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
8573        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
8574        type1 && type2;
8575        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
8576     {
8577       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2))
8578           && (strict
8579               || !objc_types_share_size_and_alignment (TREE_VALUE (type1),
8580                                                        TREE_VALUE (type2))))
8581         return 0;
8582     }
8583
8584   return (!type1 && !type2);
8585 }
8586
8587 /* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
8588    this occurs.  ObjC method dispatches are _not_ like C++ virtual
8589    member function dispatches, and we account for the difference here.  */
8590 tree
8591 #ifdef OBJCPLUS
8592 objc_fold_obj_type_ref (tree ref, tree known_type)
8593 #else
8594 objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
8595                         tree known_type ATTRIBUTE_UNUSED)
8596 #endif
8597 {
8598 #ifdef OBJCPLUS
8599   tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
8600
8601   /* If the receiver does not have virtual member functions, there
8602      is nothing we can (or need to) do here.  */
8603   if (!v)
8604     return NULL_TREE;
8605
8606   /* Let C++ handle C++ virtual functions.  */
8607   return cp_fold_obj_type_ref (ref, known_type);
8608 #else
8609   /* For plain ObjC, we currently do not need to do anything.  */
8610   return NULL_TREE;
8611 #endif
8612 }
8613
8614 static void
8615 objc_start_function (tree name, tree type, tree attrs,
8616 #ifdef OBJCPLUS
8617                      tree params
8618 #else
8619                      struct c_arg_info *params
8620 #endif
8621                      )
8622 {
8623   tree fndecl = build_decl (input_location,
8624                             FUNCTION_DECL, name, type);
8625
8626 #ifdef OBJCPLUS
8627   DECL_ARGUMENTS (fndecl) = params;
8628   DECL_INITIAL (fndecl) = error_mark_node;
8629   DECL_EXTERNAL (fndecl) = 0;
8630   TREE_STATIC (fndecl) = 1;
8631   retrofit_lang_decl (fndecl);
8632   cplus_decl_attributes (&fndecl, attrs, 0);
8633   start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
8634 #else
8635   current_function_returns_value = 0;  /* Assume, until we see it does.  */
8636   current_function_returns_null = 0;
8637
8638   decl_attributes (&fndecl, attrs, 0);
8639   announce_function (fndecl);
8640   DECL_INITIAL (fndecl) = error_mark_node;
8641   DECL_EXTERNAL (fndecl) = 0;
8642   TREE_STATIC (fndecl) = 1;
8643   current_function_decl = pushdecl (fndecl);
8644   push_scope ();
8645   declare_parm_level ();
8646   DECL_RESULT (current_function_decl)
8647     = build_decl (input_location,
8648                   RESULT_DECL, NULL_TREE,
8649                   TREE_TYPE (TREE_TYPE (current_function_decl)));
8650   DECL_ARTIFICIAL (DECL_RESULT (current_function_decl)) = 1;
8651   DECL_IGNORED_P (DECL_RESULT (current_function_decl)) = 1;
8652   start_fname_decls ();
8653   store_parm_decls_from (params);
8654 #endif
8655
8656   TREE_USED (current_function_decl) = 1;
8657 }
8658
8659 /* - Generate an identifier for the function. the format is "_n_cls",
8660      where 1 <= n <= nMethods, and cls is the name the implementation we
8661      are processing.
8662    - Install the return type from the method declaration.
8663    - If we have a prototype, check for type consistency.  */
8664
8665 static void
8666 really_start_method (tree method,
8667 #ifdef OBJCPLUS
8668                      tree parmlist
8669 #else
8670                      struct c_arg_info *parmlist
8671 #endif
8672                      )
8673 {
8674   tree ret_type, meth_type;
8675   tree method_id;
8676   const char *sel_name, *class_name, *cat_name;
8677   char *buf;
8678
8679   /* Synth the storage class & assemble the return type.  */
8680   ret_type = TREE_VALUE (TREE_TYPE (method));
8681
8682   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
8683   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
8684   cat_name = ((TREE_CODE (objc_implementation_context)
8685                == CLASS_IMPLEMENTATION_TYPE)
8686               ? NULL
8687               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
8688   method_slot++;
8689
8690   /* Make sure this is big enough for any plausible method label.  */
8691   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
8692                          + (cat_name ? strlen (cat_name) : 0));
8693
8694   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
8695                          class_name, cat_name, sel_name, method_slot);
8696
8697   method_id = get_identifier (buf);
8698
8699 #ifdef OBJCPLUS
8700   /* Objective-C methods cannot be overloaded, so we don't need
8701      the type encoding appended.  It looks bad anyway... */
8702   push_lang_context (lang_name_c);
8703 #endif
8704
8705   meth_type
8706     = build_function_type (ret_type,
8707                            get_arg_type_list (method, METHOD_DEF, 0));
8708   objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
8709
8710   /* Set self_decl from the first argument.  */
8711   self_decl = DECL_ARGUMENTS (current_function_decl);
8712
8713   /* Suppress unused warnings.  */
8714   TREE_USED (self_decl) = 1;
8715   TREE_USED (TREE_CHAIN (self_decl)) = 1;
8716 #ifdef OBJCPLUS
8717   pop_lang_context ();
8718 #endif
8719
8720   METHOD_DEFINITION (method) = current_function_decl;
8721
8722   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
8723
8724   if (implementation_template != objc_implementation_context)
8725     {
8726       tree proto
8727         = lookup_method_static (implementation_template,
8728                                 METHOD_SEL_NAME (method),
8729                                 ((TREE_CODE (method) == CLASS_METHOD_DECL)
8730                                  | OBJC_LOOKUP_NO_SUPER));
8731
8732       if (proto)
8733         {
8734           if (!comp_proto_with_proto (method, proto, 1))
8735             {
8736               bool type = TREE_CODE (method) == INSTANCE_METHOD_DECL;
8737
8738               warning_at (DECL_SOURCE_LOCATION (method), 0,
8739                           "conflicting types for %<%c%s%>",
8740                           (type ? '-' : '+'),
8741                           identifier_to_locale (gen_method_decl (method)));
8742               inform (DECL_SOURCE_LOCATION (proto),
8743                       "previous declaration of %<%c%s%>",
8744                       (type ? '-' : '+'),
8745                       identifier_to_locale (gen_method_decl (proto)));
8746             }
8747         }
8748       else
8749         {
8750           /* We have a method @implementation even though we did not
8751              see a corresponding @interface declaration (which is allowed
8752              by Objective-C rules).  Go ahead and place the method in
8753              the @interface anyway, so that message dispatch lookups
8754              will see it.  */
8755           tree interface = implementation_template;
8756
8757           if (TREE_CODE (objc_implementation_context)
8758               == CATEGORY_IMPLEMENTATION_TYPE)
8759             interface = lookup_category
8760                         (interface,
8761                          CLASS_SUPER_NAME (objc_implementation_context));
8762
8763           if (interface)
8764             objc_add_method (interface, copy_node (method),
8765                              TREE_CODE (method) == CLASS_METHOD_DECL);
8766         }
8767     }
8768 }
8769
8770 static void *UOBJC_SUPER_scope = 0;
8771
8772 /* _n_Method (id self, SEL sel, ...)
8773      {
8774        struct objc_super _S;
8775        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
8776      }  */
8777
8778 static tree
8779 get_super_receiver (void)
8780 {
8781   if (objc_method_context)
8782     {
8783       tree super_expr, super_expr_list;
8784
8785       if (!UOBJC_SUPER_decl)
8786       {
8787         UOBJC_SUPER_decl = build_decl (input_location,
8788                                        VAR_DECL, get_identifier (TAG_SUPER),
8789                                        objc_super_template);
8790         /* This prevents `unused variable' warnings when compiling with -Wall.  */
8791         TREE_USED (UOBJC_SUPER_decl) = 1;
8792         lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
8793         finish_decl (UOBJC_SUPER_decl, input_location, NULL_TREE, NULL_TREE,
8794                      NULL_TREE);
8795         UOBJC_SUPER_scope = objc_get_current_scope ();
8796       }
8797
8798       /* Set receiver to self.  */
8799       super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id);
8800       super_expr = build_modify_expr (input_location, super_expr, NULL_TREE,
8801                                       NOP_EXPR, input_location, self_decl,
8802                                       NULL_TREE);
8803       super_expr_list = super_expr;
8804
8805       /* Set class to begin searching.  */
8806       super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
8807                                              get_identifier ("super_class"));
8808
8809       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8810         {
8811           /* [_cls, __cls]Super are "pre-built" in
8812              synth_forward_declarations.  */
8813
8814           super_expr = build_modify_expr (input_location, super_expr,
8815                                           NULL_TREE, NOP_EXPR,
8816                                           input_location,
8817                                           ((TREE_CODE (objc_method_context)
8818                                             == INSTANCE_METHOD_DECL)
8819                                            ? ucls_super_ref
8820                                            : uucls_super_ref),
8821                                           NULL_TREE);
8822         }
8823
8824       else
8825         /* We have a category.  */
8826         {
8827           tree super_name = CLASS_SUPER_NAME (implementation_template);
8828           tree super_class;
8829
8830           /* Barf if super used in a category of Object.  */
8831           if (!super_name)
8832             {
8833               error ("no super class declared in interface for %qE",
8834                      CLASS_NAME (implementation_template));
8835               return error_mark_node;
8836             }
8837
8838           if (flag_next_runtime && !flag_zero_link)
8839             {
8840               super_class = objc_get_class_reference (super_name);
8841               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
8842                 /* If we are in a class method, we must retrieve the
8843                    _metaclass_ for the current class, pointed at by
8844                    the class's "isa" pointer.  The following assumes that
8845                    "isa" is the first ivar in a class (which it must be).  */
8846                 super_class
8847                   = build_indirect_ref
8848                       (input_location,
8849                        build_c_cast (input_location,
8850                                      build_pointer_type (objc_class_type),
8851                                      super_class), "unary *");
8852             }
8853           else
8854             {
8855               add_class_reference (super_name);
8856               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
8857                              ? objc_get_class_decl : objc_get_meta_class_decl);
8858               assemble_external (super_class);
8859               super_class
8860                 = build_function_call
8861                   (input_location,
8862                    super_class,
8863                    build_tree_list
8864                    (NULL_TREE,
8865                     my_build_string_pointer
8866                     (IDENTIFIER_LENGTH (super_name) + 1,
8867                      IDENTIFIER_POINTER (super_name))));
8868             }
8869
8870           super_expr
8871             = build_modify_expr (input_location, super_expr, NULL_TREE,
8872                                  NOP_EXPR,
8873                                  input_location,
8874                                  build_c_cast (input_location, 
8875                                                TREE_TYPE (super_expr),
8876                                                super_class),
8877                                  NULL_TREE);
8878         }
8879
8880       super_expr_list = build_compound_expr (input_location, 
8881                                              super_expr_list, super_expr);
8882
8883       super_expr = build_unary_op (input_location, 
8884                                    ADDR_EXPR, UOBJC_SUPER_decl, 0);
8885       super_expr_list = build_compound_expr (input_location,
8886                                              super_expr_list, super_expr);
8887
8888       return super_expr_list;
8889     }
8890   else
8891     {
8892       error ("[super ...] must appear in a method context");
8893       return error_mark_node;
8894     }
8895 }
8896
8897 /* When exiting a scope, sever links to a 'super' declaration (if any)
8898    therein contained.  */
8899
8900 void
8901 objc_clear_super_receiver (void)
8902 {
8903   if (objc_method_context
8904       && UOBJC_SUPER_scope == objc_get_current_scope ()) {
8905     UOBJC_SUPER_decl = 0;
8906     UOBJC_SUPER_scope = 0;
8907   }
8908 }
8909
8910 void
8911 objc_finish_method_definition (tree fndecl)
8912 {
8913   /* We cannot validly inline ObjC methods, at least not without a language
8914      extension to declare that a method need not be dynamically
8915      dispatched, so suppress all thoughts of doing so.  */
8916   DECL_UNINLINABLE (fndecl) = 1;
8917
8918 #ifndef OBJCPLUS
8919   /* The C++ front-end will have called finish_function() for us.  */
8920   finish_function ();
8921 #endif
8922
8923   METHOD_ENCODING (objc_method_context)
8924     = encode_method_prototype (objc_method_context);
8925
8926   /* Required to implement _msgSuper. This must be done AFTER finish_function,
8927      since the optimizer may find "may be used before set" errors.  */
8928   objc_method_context = NULL_TREE;
8929
8930   if (should_call_super_dealloc)
8931     warning (0, "method possibly missing a [super dealloc] call");
8932 }
8933
8934 /* Given a tree DECL node, produce a printable description of it in the given
8935    buffer, overwriting the buffer.  */
8936
8937 static char *
8938 gen_declaration (tree decl)
8939 {
8940   errbuf[0] = '\0';
8941
8942   if (DECL_P (decl))
8943     {
8944       gen_type_name_0 (TREE_TYPE (decl));
8945
8946       if (DECL_NAME (decl))
8947         {
8948           if (!POINTER_TYPE_P (TREE_TYPE (decl)))
8949             strcat (errbuf, " ");
8950
8951           strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
8952         }
8953
8954       if (DECL_INITIAL (decl)
8955           && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
8956         sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
8957                  TREE_INT_CST_LOW (DECL_INITIAL (decl)));
8958     }
8959
8960   return errbuf;
8961 }
8962
8963 /* Given a tree TYPE node, produce a printable description of it in the given
8964    buffer, overwriting the buffer.  */
8965
8966 static char *
8967 gen_type_name_0 (tree type)
8968 {
8969   tree orig = type, proto;
8970
8971   if (TYPE_P (type) && TYPE_NAME (type))
8972     type = TYPE_NAME (type);
8973   else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
8974     {
8975       tree inner = TREE_TYPE (type);
8976
8977       while (TREE_CODE (inner) == ARRAY_TYPE)
8978         inner = TREE_TYPE (inner);
8979
8980       gen_type_name_0 (inner);
8981
8982       if (!POINTER_TYPE_P (inner))
8983         strcat (errbuf, " ");
8984
8985       if (POINTER_TYPE_P (type))
8986         strcat (errbuf, "*");
8987       else
8988         while (type != inner)
8989           {
8990             strcat (errbuf, "[");
8991
8992             if (TYPE_DOMAIN (type))
8993               {
8994                 char sz[20];
8995
8996                 sprintf (sz, HOST_WIDE_INT_PRINT_DEC,
8997                          (TREE_INT_CST_LOW
8998                           (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1));
8999                 strcat (errbuf, sz);
9000               }
9001
9002             strcat (errbuf, "]");
9003             type = TREE_TYPE (type);
9004           }
9005
9006       goto exit_function;
9007     }
9008
9009   if (TREE_CODE (type) == TYPE_DECL && DECL_NAME (type))
9010     type = DECL_NAME (type);
9011
9012   strcat (errbuf, TREE_CODE (type) == IDENTIFIER_NODE
9013                   ? IDENTIFIER_POINTER (type)
9014                   : "");
9015
9016   /* For 'id' and 'Class', adopted protocols are stored in the pointee.  */
9017   if (objc_is_id (orig))
9018     orig = TREE_TYPE (orig);
9019
9020   proto = TYPE_HAS_OBJC_INFO (orig) ? TYPE_OBJC_PROTOCOL_LIST (orig) : NULL_TREE;
9021
9022   if (proto)
9023     {
9024       strcat (errbuf, " <");
9025
9026       while (proto) {
9027         strcat (errbuf,
9028                 IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (proto))));
9029         proto = TREE_CHAIN (proto);
9030         strcat (errbuf, proto ? ", " : ">");
9031       }
9032     }
9033
9034  exit_function:
9035   return errbuf;
9036 }
9037
9038 static char *
9039 gen_type_name (tree type)
9040 {
9041   errbuf[0] = '\0';
9042
9043   return gen_type_name_0 (type);
9044 }
9045
9046 /* Given a method tree, put a printable description into the given
9047    buffer (overwriting) and return a pointer to the buffer.  */
9048
9049 static char *
9050 gen_method_decl (tree method)
9051 {
9052   tree chain;
9053
9054   strcpy (errbuf, "(");  /* NB: Do _not_ call strcat() here.  */
9055   gen_type_name_0 (TREE_VALUE (TREE_TYPE (method)));
9056   strcat (errbuf, ")");
9057   chain = METHOD_SEL_ARGS (method);
9058
9059   if (chain)
9060     {
9061       /* We have a chain of keyword_decls.  */
9062       do
9063         {
9064           if (KEYWORD_KEY_NAME (chain))
9065             strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
9066
9067           strcat (errbuf, ":(");
9068           gen_type_name_0 (TREE_VALUE (TREE_TYPE (chain)));
9069           strcat (errbuf, ")");
9070
9071           strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
9072           if ((chain = TREE_CHAIN (chain)))
9073             strcat (errbuf, " ");
9074         }
9075       while (chain);
9076
9077       if (METHOD_ADD_ARGS (method))
9078         {
9079           chain = TREE_CHAIN (METHOD_ADD_ARGS (method));
9080
9081           /* Know we have a chain of parm_decls.  */
9082           while (chain)
9083             {
9084               strcat (errbuf, ", ");
9085               gen_type_name_0 (TREE_TYPE (TREE_VALUE (chain)));
9086               chain = TREE_CHAIN (chain);
9087             }
9088
9089           if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
9090             strcat (errbuf, ", ...");
9091         }
9092     }
9093
9094   else
9095     /* We have a unary selector.  */
9096     strcat (errbuf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
9097
9098   return errbuf;
9099 }
9100 \f
9101 /* Debug info.  */
9102
9103
9104 /* Dump an @interface declaration of the supplied class CHAIN to the
9105    supplied file FP.  Used to implement the -gen-decls option (which
9106    prints out an @interface declaration of all classes compiled in
9107    this run); potentially useful for debugging the compiler too.  */
9108 static void
9109 dump_interface (FILE *fp, tree chain)
9110 {
9111   /* FIXME: A heap overflow here whenever a method (or ivar)
9112      declaration is so long that it doesn't fit in the buffer.  The
9113      code and all the related functions should be rewritten to avoid
9114      using fixed size buffers.  */
9115   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
9116   tree ivar_decls = CLASS_RAW_IVARS (chain);
9117   tree nst_methods = CLASS_NST_METHODS (chain);
9118   tree cls_methods = CLASS_CLS_METHODS (chain);
9119
9120   fprintf (fp, "\n@interface %s", my_name);
9121
9122   /* CLASS_SUPER_NAME is used to store the superclass name for
9123      classes, and the category name for categories.  */
9124   if (CLASS_SUPER_NAME (chain))
9125     {
9126       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
9127
9128       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
9129           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
9130         {
9131           fprintf (fp, " (%s)\n", name);
9132         }
9133       else
9134         {
9135           fprintf (fp, " : %s\n", name);
9136         }
9137     }
9138   else
9139     fprintf (fp, "\n");
9140
9141   /* FIXME - the following doesn't seem to work at the moment.  */
9142   if (ivar_decls)
9143     {
9144       fprintf (fp, "{\n");
9145       do
9146         {
9147           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls));
9148           ivar_decls = TREE_CHAIN (ivar_decls);
9149         }
9150       while (ivar_decls);
9151       fprintf (fp, "}\n");
9152     }
9153
9154   while (nst_methods)
9155     {
9156       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods));
9157       nst_methods = TREE_CHAIN (nst_methods);
9158     }
9159
9160   while (cls_methods)
9161     {
9162       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods));
9163       cls_methods = TREE_CHAIN (cls_methods);
9164     }
9165
9166   fprintf (fp, "@end\n");
9167 }
9168
9169 /* Demangle function for Objective-C */
9170 static const char *
9171 objc_demangle (const char *mangled)
9172 {
9173   char *demangled, *cp;
9174
9175   if (mangled[0] == '_' &&
9176       (mangled[1] == 'i' || mangled[1] == 'c') &&
9177       mangled[2] == '_')
9178     {
9179       cp = demangled = XNEWVEC (char, strlen(mangled) + 2);
9180       if (mangled[1] == 'i')
9181         *cp++ = '-';            /* for instance method */
9182       else
9183         *cp++ = '+';            /* for class method */
9184       *cp++ = '[';              /* opening left brace */
9185       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
9186       while (*cp && *cp == '_')
9187         cp++;                   /* skip any initial underbars in class name */
9188       cp = strchr(cp, '_');     /* find first non-initial underbar */
9189       if (cp == NULL)
9190         {
9191           free(demangled);      /* not mangled name */
9192           return mangled;
9193         }
9194       if (cp[1] == '_')  /* easy case: no category name */
9195         {
9196           *cp++ = ' ';            /* replace two '_' with one ' ' */
9197           strcpy(cp, mangled + (cp - demangled) + 2);
9198         }
9199       else
9200         {
9201           *cp++ = '(';            /* less easy case: category name */
9202           cp = strchr(cp, '_');
9203           if (cp == 0)
9204             {
9205               free(demangled);    /* not mangled name */
9206               return mangled;
9207             }
9208           *cp++ = ')';
9209           *cp++ = ' ';            /* overwriting 1st char of method name... */
9210           strcpy(cp, mangled + (cp - demangled)); /* get it back */
9211         }
9212       while (*cp && *cp == '_')
9213         cp++;                   /* skip any initial underbars in method name */
9214       for (; *cp; cp++)
9215         if (*cp == '_')
9216           *cp = ':';            /* replace remaining '_' with ':' */
9217       *cp++ = ']';              /* closing right brace */
9218       *cp++ = 0;                /* string terminator */
9219       return demangled;
9220     }
9221   else
9222     return mangled;             /* not an objc mangled name */
9223 }
9224
9225 const char *
9226 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
9227 {
9228   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
9229 }
9230
9231 static void
9232 init_objc (void)
9233 {
9234   gcc_obstack_init (&util_obstack);
9235   util_firstobj = (char *) obstack_finish (&util_obstack);
9236
9237   errbuf = XNEWVEC (char, 1024 * 10);
9238   hash_init ();
9239   synth_module_prologue ();
9240 }
9241 \f
9242 static void
9243 finish_objc (void)
9244 {
9245   struct imp_entry *impent;
9246   tree chain;
9247   /* The internally generated initializers appear to have missing braces.
9248      Don't warn about this.  */
9249   int save_warn_missing_braces = warn_missing_braces;
9250   warn_missing_braces = 0;
9251
9252   /* A missing @end may not be detected by the parser.  */
9253   if (objc_implementation_context)
9254     {
9255       warning (0, "%<@end%> missing in implementation context");
9256       finish_class (objc_implementation_context);
9257       objc_ivar_chain = NULL_TREE;
9258       objc_implementation_context = NULL_TREE;
9259     }
9260
9261   /* Process the static instances here because initialization of objc_symtab
9262      depends on them.  */
9263   if (objc_static_instances)
9264     generate_static_references ();
9265
9266   if (imp_list || class_names_chain
9267       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
9268     generate_objc_symtab_decl ();
9269
9270   for (impent = imp_list; impent; impent = impent->next)
9271     {
9272       objc_implementation_context = impent->imp_context;
9273       implementation_template = impent->imp_template;
9274
9275       UOBJC_CLASS_decl = impent->class_decl;
9276       UOBJC_METACLASS_decl = impent->meta_decl;
9277
9278       /* Dump the @interface of each class as we compile it, if the
9279          -gen-decls option is in use.  TODO: Dump the classes in the
9280          order they were found, rather than in reverse order as we
9281          are doing now.  */
9282       if (flag_gen_declaration)
9283         {
9284           dump_interface (gen_declaration_file, objc_implementation_context);
9285         }
9286
9287       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
9288         {
9289           /* all of the following reference the string pool...  */
9290           generate_ivar_lists ();
9291           generate_dispatch_tables ();
9292           generate_shared_structures (impent->has_cxx_cdtors
9293                                       ? CLS_HAS_CXX_STRUCTORS
9294                                       : 0);
9295         }
9296       else
9297         {
9298           generate_dispatch_tables ();
9299           generate_category (objc_implementation_context);
9300         }
9301     }
9302
9303   /* If we are using an array of selectors, we must always
9304      finish up the array decl even if no selectors were used.  */
9305   if (! flag_next_runtime || sel_ref_chain)
9306     build_selector_translation_table ();
9307
9308   if (protocol_chain)
9309     generate_protocols ();
9310
9311   if ((flag_replace_objc_classes && imp_list) || flag_objc_gc)
9312     generate_objc_image_info ();
9313
9314   /* Arrange for ObjC data structures to be initialized at run time.  */
9315   if (objc_implementation_context || class_names_chain || objc_static_instances
9316       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
9317     {
9318       build_module_descriptor ();
9319
9320       if (!flag_next_runtime)
9321         build_module_initializer_routine ();
9322     }
9323
9324   /* Dump the class references.  This forces the appropriate classes
9325      to be linked into the executable image, preserving unix archive
9326      semantics.  This can be removed when we move to a more dynamically
9327      linked environment.  */
9328
9329   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
9330     {
9331       handle_class_ref (chain);
9332       if (TREE_PURPOSE (chain))
9333         generate_classref_translation_entry (chain);
9334     }
9335
9336   for (impent = imp_list; impent; impent = impent->next)
9337     handle_impent (impent);
9338
9339   if (warn_selector)
9340     {
9341       int slot;
9342       hash hsh;
9343
9344       /* Run through the selector hash tables and print a warning for any
9345          selector which has multiple methods.  */
9346
9347       for (slot = 0; slot < SIZEHASHTABLE; slot++)
9348         {
9349           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
9350             check_duplicates (hsh, 0, 1);
9351           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
9352             check_duplicates (hsh, 0, 1);
9353         }
9354     }
9355
9356   warn_missing_braces = save_warn_missing_braces;
9357 }
9358 \f
9359 /* Subroutines of finish_objc.  */
9360
9361 static void
9362 generate_classref_translation_entry (tree chain)
9363 {
9364   tree expr, decl, type;
9365
9366   decl = TREE_PURPOSE (chain);
9367   type = TREE_TYPE (decl);
9368
9369   expr = add_objc_string (TREE_VALUE (chain), class_names);
9370   expr = convert (type, expr); /* cast! */
9371
9372   /* The decl that is the one that we
9373      forward declared in build_class_reference.  */
9374   finish_var_decl (decl, expr);
9375   return;
9376 }
9377
9378 static void
9379 handle_class_ref (tree chain)
9380 {
9381   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
9382   char *string = (char *) alloca (strlen (name) + 30);
9383   tree decl;
9384   tree exp;
9385
9386   sprintf (string, "%sobjc_class_name_%s",
9387            (flag_next_runtime ? "." : "__"), name);
9388
9389 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
9390   if (flag_next_runtime)
9391     {
9392       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
9393       return;
9394     }
9395 #endif
9396
9397   /* Make a decl for this name, so we can use its address in a tree.  */
9398   decl = build_decl (input_location,
9399                      VAR_DECL, get_identifier (string), char_type_node);
9400   DECL_EXTERNAL (decl) = 1;
9401   TREE_PUBLIC (decl) = 1;
9402
9403   pushdecl (decl);
9404   rest_of_decl_compilation (decl, 0, 0);
9405
9406   /* Make a decl for the address.  */
9407   sprintf (string, "%sobjc_class_ref_%s",
9408            (flag_next_runtime ? "." : "__"), name);
9409   exp = build1 (ADDR_EXPR, string_type_node, decl);
9410   decl = build_decl (input_location,
9411                      VAR_DECL, get_identifier (string), string_type_node);
9412   DECL_INITIAL (decl) = exp;
9413   TREE_STATIC (decl) = 1;
9414   TREE_USED (decl) = 1;
9415   /* Force the output of the decl as this forces the reference of the class.  */
9416   mark_decl_referenced (decl);
9417
9418   pushdecl (decl);
9419   rest_of_decl_compilation (decl, 0, 0);
9420 }
9421
9422 static void
9423 handle_impent (struct imp_entry *impent)
9424 {
9425   char *string;
9426
9427   objc_implementation_context = impent->imp_context;
9428   implementation_template = impent->imp_template;
9429
9430   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
9431     {
9432       const char *const class_name =
9433         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
9434
9435       string = (char *) alloca (strlen (class_name) + 30);
9436
9437       sprintf (string, "%sobjc_class_name_%s",
9438                (flag_next_runtime ? "." : "__"), class_name);
9439     }
9440   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
9441     {
9442       const char *const class_name =
9443         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
9444       const char *const class_super_name =
9445         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
9446
9447       string = (char *) alloca (strlen (class_name)
9448                                 + strlen (class_super_name) + 30);
9449
9450       /* Do the same for categories.  Even though no references to
9451          these symbols are generated automatically by the compiler, it
9452          gives you a handle to pull them into an archive by hand.  */
9453       sprintf (string, "*%sobjc_category_name_%s_%s",
9454                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
9455     }
9456   else
9457     return;
9458
9459 #ifdef ASM_DECLARE_CLASS_REFERENCE
9460   if (flag_next_runtime)
9461     {
9462       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9463       return;
9464     }
9465   else
9466 #endif
9467     {
9468       tree decl, init;
9469
9470       init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0);
9471       decl = build_decl (input_location,
9472                          VAR_DECL, get_identifier (string), TREE_TYPE (init));
9473       TREE_PUBLIC (decl) = 1;
9474       TREE_READONLY (decl) = 1;
9475       TREE_USED (decl) = 1;
9476       TREE_CONSTANT (decl) = 1;
9477       DECL_CONTEXT (decl) = 0;
9478       DECL_ARTIFICIAL (decl) = 1;
9479       DECL_INITIAL (decl) = init;
9480       assemble_variable (decl, 1, 0, 0);
9481     }
9482 }
9483 \f
9484 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
9485    later requires that ObjC translation units participating in F&C be
9486    specially marked.  The following routine accomplishes this.  */
9487
9488 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9489
9490 static void
9491 generate_objc_image_info (void)
9492 {
9493   tree decl, initlist;
9494   int flags
9495     = ((flag_replace_objc_classes && imp_list ? 1 : 0)
9496        | (flag_objc_gc ? 2 : 0));
9497
9498   decl = start_var_decl (build_array_type
9499                          (integer_type_node,
9500                           build_index_type (build_int_cst (NULL_TREE, 2 - 1))),
9501                          "_OBJC_IMAGE_INFO");
9502
9503   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
9504   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), initlist);
9505   initlist = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
9506
9507   finish_var_decl (decl, initlist);
9508 }
9509
9510 /* Look up ID as an instance variable.  OTHER contains the result of
9511    the C or C++ lookup, which we may want to use instead.  */
9512
9513 tree
9514 objc_lookup_ivar (tree other, tree id)
9515 {
9516   tree ivar;
9517
9518   /* If we are not inside of an ObjC method, ivar lookup makes no sense.  */
9519   if (!objc_method_context)
9520     return other;
9521
9522   if (!strcmp (IDENTIFIER_POINTER (id), "super"))
9523     /* We have a message to super.  */
9524     return get_super_receiver ();
9525
9526   /* In a class method, look up an instance variable only as a last
9527      resort.  */
9528   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
9529       && other && other != error_mark_node)
9530     return other;
9531
9532   /* Look up the ivar, but do not use it if it is not accessible.  */
9533   ivar = is_ivar (objc_ivar_chain, id);
9534
9535   if (!ivar || is_private (ivar))
9536     return other;
9537
9538   /* In an instance method, a local variable (or parameter) may hide the
9539      instance variable.  */
9540   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
9541       && other && other != error_mark_node
9542 #ifdef OBJCPLUS
9543       && CP_DECL_CONTEXT (other) != global_namespace)
9544 #else
9545       && !DECL_FILE_SCOPE_P (other))
9546 #endif
9547     {
9548       warning (0, "local declaration of %qE hides instance variable",
9549                id);
9550
9551       return other;
9552     }
9553
9554   /* At this point, we are either in an instance method with no obscuring
9555      local definitions, or in a class method with no alternate definitions
9556      at all.  */
9557   return build_ivar_reference (id);
9558 }
9559
9560 /* Possibly rewrite a function CALL into an OBJ_TYPE_REF expression.  This
9561    needs to be done if we are calling a function through a cast.  */
9562
9563 tree
9564 objc_rewrite_function_call (tree function, tree first_param)
9565 {
9566   if (TREE_CODE (function) == NOP_EXPR
9567       && TREE_CODE (TREE_OPERAND (function, 0)) == ADDR_EXPR
9568       && TREE_CODE (TREE_OPERAND (TREE_OPERAND (function, 0), 0))
9569          == FUNCTION_DECL)
9570     {
9571       function = build3 (OBJ_TYPE_REF, TREE_TYPE (function),
9572                          TREE_OPERAND (function, 0),
9573                          first_param, size_zero_node);
9574     }
9575
9576   return function;
9577 }
9578
9579 /* Look for the special case of OBJC_TYPE_REF with the address of
9580    a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
9581    of its cousins).  */
9582
9583 int
9584 objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
9585 {
9586   enum gimplify_status r0, r1;
9587   if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
9588       && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
9589       && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
9590          == FUNCTION_DECL)
9591     {
9592       /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
9593          value of the OBJ_TYPE_REF, so force them to be emitted
9594          during subexpression evaluation rather than after the
9595          OBJ_TYPE_REF. This permits objc_msgSend calls in Objective
9596          C to use direct rather than indirect calls when the
9597          object expression has a postincrement.  */
9598       r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
9599                           is_gimple_val, fb_rvalue);
9600       r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
9601                           is_gimple_val, fb_rvalue);
9602
9603       return MIN (r0, r1);
9604     }
9605
9606 #ifdef OBJCPLUS
9607   return (enum gimplify_status) cp_gimplify_expr (expr_p, pre_p, post_p);
9608 #else
9609   return (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
9610 #endif
9611 }
9612
9613 #include "gt-objc-objc-act.h"