OSDN Git Service

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