OSDN Git Service

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