OSDN Git Service

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