OSDN Git Service

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