OSDN Git Service

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