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