OSDN Git Service

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