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