OSDN Git Service

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