c-tree.h (struct c_expr): Define.
[platform/upstream/gcc.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
523   /* Finalize Objective-C runtime data.  No need to generate tables
524      and code if only checking syntax.  */
525   if (!flag_syntax_only)
526     finish_objc ();
527
528   if (gen_declaration_file)
529     fclose (gen_declaration_file);
530 }
531 \f
532 static tree
533 define_decl (tree declarator, tree declspecs)
534 {
535   tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
536   finish_decl (decl, NULL_TREE, NULL_TREE);
537   return decl;
538 }
539
540 /* Return the first occurrence of a method declaration corresponding
541    to sel_name in rproto_list.  Search rproto_list recursively.
542    If is_class is 0, search for instance methods, otherwise for class
543    methods.  */
544 static tree
545 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
546                                 int is_class)
547 {
548    tree rproto, p;
549    tree fnd = 0;
550
551    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
552      {
553         p = TREE_VALUE (rproto);
554
555         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
556           {
557             if ((fnd = lookup_method (is_class
558                                       ? PROTOCOL_CLS_METHODS (p)
559                                       : PROTOCOL_NST_METHODS (p), sel_name)))
560               ;
561             else if (PROTOCOL_LIST (p))
562               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
563                                                     sel_name, is_class);
564           }
565         else
566           {
567             ; /* An identifier...if we could not find a protocol.  */
568           }
569
570         if (fnd)
571           return fnd;
572      }
573
574    return 0;
575 }
576
577 static tree
578 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
579 {
580   tree rproto, p;
581
582   /* Make sure the protocol is supported by the object on the rhs.  */
583   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
584     {
585       tree fnd = 0;
586       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
587         {
588           p = TREE_VALUE (rproto);
589
590           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
591             {
592               if (lproto == p)
593                 fnd = lproto;
594
595               else if (PROTOCOL_LIST (p))
596                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
597             }
598
599           if (fnd)
600             return fnd;
601         }
602     }
603   else
604     {
605       ; /* An identifier...if we could not find a protocol.  */
606     }
607
608   return 0;
609 }
610
611 /* Return true if TYPE is 'id'.  */
612
613 static bool
614 objc_is_object_id (tree type)
615 {
616   return OBJC_TYPE_NAME (type) == objc_object_id;
617 }
618
619 static bool
620 objc_is_class_id (tree type)
621 {
622   return OBJC_TYPE_NAME (type) == objc_class_id;
623 }
624
625 /* Return 1 if LHS and RHS are compatible types for assignment or
626    various other operations.  Return 0 if they are incompatible, and
627    return -1 if we choose to not decide (because the types are really
628    just C types, not ObjC specific ones).  When the operation is
629    REFLEXIVE (typically comparisons), check for compatibility in
630    either direction; when it's not (typically assignments), don't.
631
632    This function is called in two cases: when both lhs and rhs are
633    pointers to records (in which case we check protocols too), and
634    when both lhs and rhs are records (in which case we check class
635    inheritance only).
636
637    Warnings about classes/protocols not implementing a protocol are
638    emitted here (multiple of those warnings might be emitted for a
639    single line!); generic warnings about incompatible assignments and
640    lacks of casts in comparisons are/must be emitted by the caller if
641    we return 0.
642 */
643
644 int
645 objc_comptypes (tree lhs, tree rhs, int reflexive)
646 {
647   /* New clause for protocols.  */
648
649   /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE.  We only
650      manage the ObjC ones, and leave the rest to the C code.  */
651   if (TREE_CODE (lhs) == POINTER_TYPE
652       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
653       && TREE_CODE (rhs) == POINTER_TYPE
654       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
655     {
656       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
657       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
658
659       if (lhs_is_proto)
660         {
661           tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
662           tree rproto, rproto_list;
663           tree p;
664
665           /* <Protocol> = <Protocol>  */
666           if (rhs_is_proto)
667             {
668               rproto_list = TYPE_PROTOCOL_LIST (rhs);
669
670               if (!reflexive)
671                 {
672                   /* An assignment between objects of type 'id
673                      <Protocol>'; make sure the protocol on the lhs is
674                      supported by the object on the rhs.  */
675                   for (lproto = lproto_list; lproto;
676                        lproto = TREE_CHAIN (lproto))
677                     {
678                       p = TREE_VALUE (lproto);
679                       rproto = lookup_protocol_in_reflist (rproto_list, p);
680
681                       if (!rproto)
682                         warning
683                           ("object does not conform to the `%s' protocol",
684                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
685                     }
686                   return 1;
687                 }
688               else
689                 {
690                   /* Obscure case - a comparison between two objects
691                      of type 'id <Protocol>'.  Check that either the
692                      protocol on the lhs is supported by the object on
693                      the rhs, or viceversa.  */
694
695                   /* Check if the protocol on the lhs is supported by the
696                      object on the rhs.  */
697                   for (lproto = lproto_list; lproto;
698                        lproto = TREE_CHAIN (lproto))
699                     {
700                       p = TREE_VALUE (lproto);
701                       rproto = lookup_protocol_in_reflist (rproto_list, p);
702
703                       if (!rproto)
704                         {
705                           /* Check failed - check if the protocol on the rhs
706                              is supported by the object on the lhs.  */
707                           for (rproto = rproto_list; rproto;
708                                rproto = TREE_CHAIN (rproto))
709                             {
710                               p = TREE_VALUE (rproto);
711                               lproto = lookup_protocol_in_reflist (lproto_list,
712                                                                    p);
713
714                               if (!lproto)
715                                 {
716                                   /* This check failed too: incompatible  */
717                                   return 0;
718                                 }
719                             }
720                           return 1;
721                         }
722                     }
723                   return 1;
724                 }
725             }
726           /* <Protocol> = <class> *  */
727           else if (TYPED_OBJECT (TREE_TYPE (rhs)))
728             {
729               tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
730               tree rinter;
731
732               /* Make sure the protocol is supported by the object on
733                  the rhs.  */
734               for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
735                 {
736                   p = TREE_VALUE (lproto);
737                   rproto = 0;
738                   rinter = lookup_interface (rname);
739
740                   while (rinter && !rproto)
741                     {
742                       tree cat;
743
744                       rproto_list = CLASS_PROTOCOL_LIST (rinter);
745                       rproto = lookup_protocol_in_reflist (rproto_list, p);
746                       /* If the underlying ObjC class does not have
747                          the protocol we're looking for, check for "one-off"
748                          protocols (e.g., `NSObject<MyProt> *foo;') attached
749                          to the rhs.  */
750                       if (!rproto)
751                         {
752                           rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
753                           rproto = lookup_protocol_in_reflist (rproto_list, p);
754                         }
755
756                       /* Check for protocols adopted by categories.  */
757                       cat = CLASS_CATEGORY_LIST (rinter);
758                       while (cat && !rproto)
759                         {
760                           rproto_list = CLASS_PROTOCOL_LIST (cat);
761                           rproto = lookup_protocol_in_reflist (rproto_list, p);
762                           cat = CLASS_CATEGORY_LIST (cat);
763                         }
764
765                       rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
766                     }
767
768                   if (!rproto)
769                     warning ("class `%s' does not implement the `%s' protocol",
770                              IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
771                              IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
772                 }
773               return 1;
774             }
775           /* <Protocol> = id */
776           else if (objc_is_object_id (TREE_TYPE (rhs)))
777             {
778               return 1;
779             }
780           /* <Protocol> = Class */
781           else if (objc_is_class_id (TREE_TYPE (rhs)))
782             {
783               return 0;
784             }
785           /* <Protocol> = ?? : let comptypes decide.  */
786           return -1;
787         }
788       else if (rhs_is_proto)
789         {
790           /* <class> * = <Protocol> */
791           if (TYPED_OBJECT (TREE_TYPE (lhs)))
792             {
793               if (reflexive)
794                 {
795                   tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
796                   tree rinter;
797                   tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
798
799                   /* Make sure the protocol is supported by the object on
800                      the lhs.  */
801                   for (rproto = rproto_list; rproto;
802                        rproto = TREE_CHAIN (rproto))
803                     {
804                       tree p = TREE_VALUE (rproto);
805                       tree lproto = 0;
806                       rinter = lookup_interface (rname);
807
808                       while (rinter && !lproto)
809                         {
810                           tree cat;
811
812                           tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
813                           lproto = lookup_protocol_in_reflist (lproto_list, p);
814                           /* If the underlying ObjC class does not
815                              have the protocol we're looking for,
816                              check for "one-off" protocols (e.g.,
817                              `NSObject<MyProt> *foo;') attached to the
818                              lhs.  */
819                           if (!lproto)
820                             {
821                               lproto_list = TYPE_PROTOCOL_LIST
822                                 (TREE_TYPE (lhs));
823                               lproto = lookup_protocol_in_reflist
824                                 (lproto_list, p);
825                             }
826
827                           /* Check for protocols adopted by categories.  */
828                           cat = CLASS_CATEGORY_LIST (rinter);
829                           while (cat && !lproto)
830                             {
831                               lproto_list = CLASS_PROTOCOL_LIST (cat);
832                               lproto = lookup_protocol_in_reflist (lproto_list,
833                                                                    p);
834                               cat = CLASS_CATEGORY_LIST (cat);
835                             }
836                         
837                           rinter = lookup_interface (CLASS_SUPER_NAME
838                                                      (rinter));
839                         }
840                 
841                       if (!lproto)
842                         warning ("class `%s' does not implement the `%s' protocol",
843                                  IDENTIFIER_POINTER (OBJC_TYPE_NAME
844                                                      (TREE_TYPE (lhs))),
845                                  IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
846                     }
847                   return 1;
848                 }
849               else
850                 return 0;
851             }
852           /* id = <Protocol> */
853           else if (objc_is_object_id (TREE_TYPE (lhs)))
854             {
855               return 1;
856             }
857           /* Class = <Protocol> */
858           else if (objc_is_class_id (TREE_TYPE (lhs)))
859             {
860               return 0;
861             }
862           /* ??? = <Protocol> : let comptypes decide */
863           else
864             {
865               return -1;
866             }
867         }
868       else
869         {
870           /* Attention: we shouldn't defer to comptypes here.  One bad
871              side effect would be that we might loose the REFLEXIVE
872              information.
873           */
874           lhs = TREE_TYPE (lhs);
875           rhs = TREE_TYPE (rhs);
876         }
877     }
878
879   if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
880     {
881       /* Nothing to do with ObjC - let immediately comptypes take
882          responsibility for checking.  */
883       return -1;
884     }
885
886   /* `id' = `<class> *' `<class> *' = `id': always allow it.
887      Please note that
888      'Object *o = [[Object alloc] init]; falls
889      in the case <class> * = `id'.
890   */
891   if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
892       || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
893     return 1;
894
895   /* `id' = `Class', `Class' = `id' */
896
897   else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
898            || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
899     return 1;
900
901   /* `Class' != `<class> *' && `<class> *' != `Class'!  */
902   else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
903            || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
904     return 0;
905
906   /* `<class> *' = `<class> *' */
907
908   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
909     {
910       tree lname = OBJC_TYPE_NAME (lhs);
911       tree rname = OBJC_TYPE_NAME (rhs);
912       tree inter;
913
914       if (lname == rname)
915         return 1;
916
917       /* If the left hand side is a super class of the right hand side,
918          allow it.  */
919       for (inter = lookup_interface (rname); inter;
920            inter = lookup_interface (CLASS_SUPER_NAME (inter)))
921         if (lname == CLASS_SUPER_NAME (inter))
922           return 1;
923
924       /* Allow the reverse when reflexive.  */
925       if (reflexive)
926         for (inter = lookup_interface (lname); inter;
927              inter = lookup_interface (CLASS_SUPER_NAME (inter)))
928           if (rname == CLASS_SUPER_NAME (inter))
929             return 1;
930
931       return 0;
932     }
933   else
934     /* Not an ObjC type - let comptypes do the check.  */
935     return -1;
936 }
937
938 /* Called from finish_decl.  */
939
940 void
941 objc_check_decl (tree decl)
942 {
943   tree type = TREE_TYPE (decl);
944
945   if (TREE_CODE (type) != RECORD_TYPE)
946     return;
947   if (TYPE_NAME (type) && (type = is_class_name (TYPE_NAME (type))))
948     error ("statically allocated instance of Objective-C class `%s'",
949            IDENTIFIER_POINTER (type));
950 }
951
952 /* Implement static typing.  At this point, we know we have an interface.  */
953
954 tree
955 get_static_reference (tree interface, tree protocols)
956 {
957   tree type = xref_tag (RECORD_TYPE, interface);
958
959   if (protocols)
960     {
961       tree t, m = TYPE_MAIN_VARIANT (type);
962
963       t = copy_node (type);
964
965       /* Add this type to the chain of variants of TYPE.  */
966       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
967       TYPE_NEXT_VARIANT (m) = t;
968
969       /* Look up protocols and install in lang specific list.  Note
970          that the protocol list can have a different lifetime than T!  */
971       SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
972
973       /* This forces a new pointer type to be created later
974          (in build_pointer_type)...so that the new template
975          we just created will actually be used...what a hack!  */
976       if (TYPE_POINTER_TO (t))
977         TYPE_POINTER_TO (t) = NULL_TREE;
978
979       type = t;
980     }
981
982   return type;
983 }
984
985 /* Return a declaration corresponding to a protocol list qualified 'id'. */
986 tree
987 get_protocol_reference (tree protocols)
988 {
989   tree type_decl = lookup_name (objc_id_id);
990   tree type;
991
992   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
993     {
994       type = TREE_TYPE (type_decl);
995       if (TYPE_MAIN_VARIANT (type) != objc_id_type)
996         warning ("unexpected type for `id' (%s)",
997                  gen_declaration (type, errbuf));
998     }
999   else
1000     {
1001       error ("undefined type `id', please import <objc/objc.h>");
1002       return error_mark_node;
1003     }
1004
1005   /* This clause creates a new pointer type that is qualified with
1006      the protocol specification...this info is used later to do more
1007      elaborate type checking.  */
1008
1009   if (protocols)
1010     {
1011       tree t, m = TYPE_MAIN_VARIANT (type);
1012
1013       t = copy_node (type);
1014
1015       /* Add this type to the chain of variants of TYPE.  */
1016       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1017       TYPE_NEXT_VARIANT (m) = t;
1018
1019       /* Look up protocols...and install in lang specific list */
1020       SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
1021
1022       /* This forces a new pointer type to be created later
1023          (in build_pointer_type)...so that the new template
1024          we just created will actually be used...what a hack!  */
1025       if (TYPE_POINTER_TO (t))
1026         TYPE_POINTER_TO (t) = NULL_TREE;
1027
1028       type = t;
1029     }
1030   return type;
1031 }
1032
1033 /* Check for circular dependencies in protocols.  The arguments are
1034    PROTO, the protocol to check, and LIST, a list of protocol it
1035    conforms to.  */
1036
1037 static void
1038 check_protocol_recursively (tree proto, tree list)
1039 {
1040   tree p;
1041
1042   for (p = list; p; p = TREE_CHAIN (p))
1043     {
1044       tree pp = TREE_VALUE (p);
1045
1046       if (TREE_CODE (pp) == IDENTIFIER_NODE)
1047         pp = lookup_protocol (pp);
1048
1049       if (pp == proto)
1050         fatal_error ("protocol `%s' has circular dependency",
1051                      IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1052       if (pp)
1053         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1054     }
1055 }
1056
1057 /* Look up PROTOCOLS, and return a list of those that are found.
1058    If none are found, return NULL.  */
1059
1060 static tree
1061 lookup_and_install_protocols (tree protocols)
1062 {
1063   tree proto;
1064   tree return_value = NULL_TREE;
1065
1066   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1067     {
1068       tree ident = TREE_VALUE (proto);
1069       tree p = lookup_protocol (ident);
1070
1071       if (!p)
1072         error ("cannot find protocol declaration for `%s'",
1073                IDENTIFIER_POINTER (ident));
1074       else
1075         return_value = chainon (return_value,
1076                                 build_tree_list (NULL_TREE, p));
1077     }
1078
1079   return return_value;
1080 }
1081
1082 /* Create and push a decl for a built-in external variable or field NAME.
1083    CODE says which.
1084    TYPE is its data type.  */
1085
1086 static tree
1087 create_builtin_decl (enum tree_code code, tree type, const char *name)
1088 {
1089   tree decl = build_decl (code, get_identifier (name), type);
1090
1091   if (code == VAR_DECL)
1092     {
1093       TREE_STATIC (decl) = 1;
1094       make_decl_rtl (decl, 0);
1095       pushdecl (decl);
1096       DECL_ARTIFICIAL (decl) = 1;
1097     }
1098
1099   return decl;
1100 }
1101
1102 /* Find the decl for the constant string class.  */
1103
1104 static void
1105 setup_string_decl (void)
1106 {
1107   if (!string_class_decl)
1108     {
1109       if (!constant_string_global_id)
1110         {
1111           char *name;
1112           size_t length;
1113           /* %s in format will provide room for terminating null */
1114           length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1115                    + strlen (constant_string_class_name);
1116           name = xmalloc (length);
1117           sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1118                    constant_string_class_name);
1119           constant_string_global_id = get_identifier (name);
1120         }
1121       string_class_decl = lookup_name (constant_string_global_id);
1122     }
1123 }
1124
1125 /* Purpose: "play" parser, creating/installing representations
1126    of the declarations that are required by Objective-C.
1127
1128    Model:
1129
1130         type_spec--------->sc_spec
1131         (tree_list)        (tree_list)
1132             |                  |
1133             |                  |
1134         identifier_node    identifier_node  */
1135
1136 static void
1137 synth_module_prologue (void)
1138 {
1139   tree temp_type;
1140
1141   /* Defined in `objc.h' */
1142   objc_object_id = get_identifier (TAG_OBJECT);
1143
1144   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1145
1146   objc_id_type = build_pointer_type (objc_object_reference);
1147
1148   objc_id_id = get_identifier (TYPE_ID);
1149   objc_class_id = get_identifier (TAG_CLASS);
1150
1151   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1152   temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1153   objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
1154   objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, temp_type));
1155
1156   /* Declare type of selector-objects that represent an operation name.  */
1157
1158   if (flag_next_runtime)
1159     /* `struct objc_selector *' */
1160     objc_selector_type
1161       = build_pointer_type (xref_tag (RECORD_TYPE,
1162                                       get_identifier (TAG_SELECTOR)));
1163   else
1164     /* `const struct objc_selector *' */
1165     objc_selector_type
1166       = build_pointer_type
1167         (build_qualified_type (xref_tag (RECORD_TYPE,
1168                                          get_identifier (TAG_SELECTOR)),
1169                                TYPE_QUAL_CONST));
1170
1171   /* Declare receiver type used for dispatching messages to 'super'.  */
1172
1173   /* `struct objc_super *' */
1174   objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1175                                                   get_identifier (TAG_SUPER)));
1176
1177   if (flag_next_runtime)
1178     {
1179       /* NB: In order to call one of the ..._stret (struct-returning)
1180       functions, the function *MUST* first be cast to a signature that
1181       corresponds to the actual ObjC method being invoked.  This is
1182       what is done by the build_objc_method_call() routine below.  */
1183
1184       /* id objc_msgSend (id, SEL, ...); */
1185       /* id objc_msgSendNonNil (id, SEL, ...); */
1186       /* id objc_msgSend_stret (id, SEL, ...); */
1187       /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1188       temp_type
1189         = build_function_type (objc_id_type,
1190                                tree_cons (NULL_TREE, objc_id_type,
1191                                           tree_cons (NULL_TREE, 
1192                                                      objc_selector_type,
1193                                                      NULL_TREE)));
1194       umsg_decl = builtin_function (TAG_MSGSEND,
1195                                     temp_type, 0, NOT_BUILT_IN,
1196                                     NULL, NULL_TREE);
1197       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1198                                            temp_type, 0, NOT_BUILT_IN,
1199                                            NULL, NULL_TREE);
1200       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1201                                           temp_type, 0, NOT_BUILT_IN,
1202                                           NULL, NULL_TREE);
1203       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1204                                                  temp_type, 0, NOT_BUILT_IN,
1205                                                  NULL, NULL_TREE);
1206
1207       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1208       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1209       temp_type
1210         = build_function_type (objc_id_type,
1211                                tree_cons (NULL_TREE, objc_super_type,
1212                                           tree_cons (NULL_TREE,
1213                                                      objc_selector_type,
1214                                                      NULL_TREE)));
1215       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1216                                           temp_type, 0, NOT_BUILT_IN,
1217                                           NULL, NULL_TREE);
1218       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1219                                                 temp_type, 0, NOT_BUILT_IN, 0,
1220                                                 NULL_TREE);
1221     }
1222   else
1223     {
1224       /* GNU runtime messenger entry points.  */
1225
1226       /* typedef id (*IMP)(id, SEL, ...); */
1227       tree IMP_type
1228         = build_pointer_type
1229           (build_function_type (objc_id_type,      
1230                                 tree_cons (NULL_TREE, objc_id_type,      
1231                                            tree_cons (NULL_TREE,
1232                                                       objc_selector_type,      
1233                                                       NULL_TREE))));      
1234
1235       /* IMP objc_msg_lookup (id, SEL); */
1236       temp_type
1237         = build_function_type (IMP_type,
1238                                tree_cons (NULL_TREE, objc_id_type,
1239                                           tree_cons (NULL_TREE,
1240                                                      objc_selector_type,
1241                                                      void_list_node)));
1242       umsg_decl = builtin_function (TAG_MSGSEND,
1243                                     temp_type, 0, NOT_BUILT_IN,
1244                                     NULL, NULL_TREE);
1245
1246       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1247       temp_type
1248         = build_function_type (IMP_type,
1249                                tree_cons (NULL_TREE, objc_super_type,
1250                                           tree_cons (NULL_TREE,
1251                                                      objc_selector_type,
1252                                                      void_list_node)));
1253       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1254                                           temp_type, 0, NOT_BUILT_IN,
1255                                           NULL, NULL_TREE);
1256     }
1257
1258   /* id objc_getClass (const char *); */
1259
1260   temp_type = build_function_type (objc_id_type,
1261                                    tree_cons (NULL_TREE,
1262                                               const_string_type_node,
1263                                               void_list_node));
1264
1265   objc_get_class_decl
1266     = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
1267                         NULL, NULL_TREE);
1268
1269   /* id objc_getMetaClass (const char *); */
1270
1271   objc_get_meta_class_decl
1272     = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1273
1274   build_super_template ();
1275   build_objc_exception_stuff ();
1276   if (flag_next_runtime)
1277     build_next_objc_exception_stuff ();
1278
1279   /* static SEL _OBJC_SELECTOR_TABLE[]; */
1280
1281   if (! flag_next_runtime)
1282     {
1283       if (flag_typed_selectors)
1284         {
1285           /* Suppress outputting debug symbols, because
1286              dbxout_init hasn'r been called yet.  */
1287           enum debug_info_type save_write_symbols = write_symbols;
1288           const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1289           write_symbols = NO_DEBUG;
1290           debug_hooks = &do_nothing_debug_hooks;
1291
1292           build_selector_template ();
1293           temp_type = build_array_type (objc_selector_template, NULL_TREE);
1294
1295           write_symbols = save_write_symbols;
1296           debug_hooks = save_hooks;
1297         }
1298       else
1299         temp_type = build_array_type (objc_selector_type, NULL_TREE);
1300
1301       layout_type (temp_type);
1302       UOBJC_SELECTOR_TABLE_decl
1303         = create_builtin_decl (VAR_DECL, temp_type,
1304                                "_OBJC_SELECTOR_TABLE");
1305
1306       /* Avoid warning when not sending messages.  */
1307       TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1308     }
1309
1310   /* Forward declare constant_string_id and constant_string_type.  */
1311   if (!constant_string_class_name)
1312     constant_string_class_name = default_constant_string_class_name;
1313
1314   constant_string_id = get_identifier (constant_string_class_name);
1315   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1316
1317   /* Pre-build the following entities - for speed/convenience.  */
1318   self_id = get_identifier ("self");
1319   ucmd_id = get_identifier ("_cmd");
1320 #ifndef OBJCPLUS
1321   /* The C++ front-end does not appear to grok __attribute__((__unused__)).  */
1322   unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1323 #endif  
1324 }
1325
1326 /* Ensure that the ivar list for NSConstantString/NXConstantString
1327    (or whatever was specified via `-fconstant-string-class')
1328    contains fields at least as large as the following three, so that
1329    the runtime can stomp on them with confidence:
1330
1331    struct STRING_OBJECT_CLASS_NAME
1332    {
1333      Object isa;
1334      char *cString;
1335      unsigned int length;
1336    }; */
1337
1338 static int
1339 check_string_class_template (void)
1340 {
1341   tree field_decl = TYPE_FIELDS (constant_string_type);
1342
1343 #define AT_LEAST_AS_LARGE_AS(F, T) \
1344   (F && TREE_CODE (F) == FIELD_DECL \
1345      && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1346          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1347
1348   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1349     return 0;
1350
1351   field_decl = TREE_CHAIN (field_decl);
1352   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1353     return 0;
1354
1355   field_decl = TREE_CHAIN (field_decl);
1356   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1357
1358 #undef AT_LEAST_AS_LARGE_AS
1359 }
1360
1361 /* Avoid calling `check_string_class_template ()' more than once.  */
1362 static GTY(()) int string_layout_checked;
1363
1364 /* Custom build_string which sets TREE_TYPE!  */
1365
1366 static tree
1367 my_build_string (int len, const char *str)
1368 {
1369   return fix_string_type (build_string (len, str));
1370 }
1371
1372 /* Given a chain of STRING_CST's, build a static instance of
1373    NXConstantString which points at the concatenation of those
1374    strings.  We place the string object in the __string_objects
1375    section of the __OBJC segment.  The Objective-C runtime will
1376    initialize the isa pointers of the string objects to point at the
1377    NXConstantString class object.  */
1378
1379 tree
1380 build_objc_string_object (tree string)
1381 {
1382   tree initlist, constructor, constant_string_class;
1383   int length;
1384   tree fields;
1385
1386   string = fix_string_type (string);
1387
1388   constant_string_class = lookup_interface (constant_string_id);
1389   if (!constant_string_class
1390       || !(constant_string_type
1391              = CLASS_STATIC_TEMPLATE (constant_string_class)))
1392     {
1393       error ("cannot find interface declaration for `%s'",
1394              IDENTIFIER_POINTER (constant_string_id));
1395       return error_mark_node;
1396     }
1397
1398   /* Call to 'combine_strings' has been moved above.  */
1399   TREE_SET_CODE (string, STRING_CST);
1400   length = TREE_STRING_LENGTH (string) - 1;
1401
1402   if (!string_layout_checked)
1403     {
1404       /* The NSConstantString/NXConstantString ivar layout is now
1405          known.  */
1406       if (!check_string_class_template ())
1407         {
1408           error ("interface `%s' does not have valid constant string layout",
1409                  IDENTIFIER_POINTER (constant_string_id));
1410           return error_mark_node;
1411         }
1412       add_class_reference (constant_string_id);
1413     }
1414   fields = TYPE_FIELDS (constant_string_type);
1415
1416   /* & ((NXConstantString) { NULL, string, length })  */
1417
1418   if (flag_next_runtime)
1419     {
1420       /* For the NeXT runtime, we can generate a literal reference
1421          to the string class, don't need to run a constructor.  */
1422       setup_string_decl ();
1423       if (string_class_decl == NULL_TREE)
1424         {
1425           error ("cannot find reference tag for class `%s'",
1426                  IDENTIFIER_POINTER (constant_string_id));
1427           return error_mark_node;
1428         }
1429       initlist = build_tree_list
1430         (fields,
1431          copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
1432     }
1433   else
1434     {
1435       initlist = build_tree_list (fields, build_int_2 (0, 0));
1436     }
1437
1438   fields = TREE_CHAIN (fields);
1439   
1440   initlist
1441     = tree_cons (fields, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1442                  initlist);
1443                  
1444   fields = TREE_CHAIN (fields);
1445   
1446   initlist = tree_cons (fields, build_int_2 (length, 0), initlist);
1447   constructor = objc_build_constructor (constant_string_type,
1448                                         nreverse (initlist));
1449
1450   if (!flag_next_runtime)
1451     {
1452       constructor
1453         = objc_add_static_instance (constructor, constant_string_type);
1454     }
1455
1456   return (build_unary_op (ADDR_EXPR, constructor, 1));
1457 }
1458
1459 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1460
1461 static GTY(()) int num_static_inst;
1462
1463 static tree
1464 objc_add_static_instance (tree constructor, tree class_decl)
1465 {
1466   tree *chain, decl;
1467   char buf[256];
1468
1469   /* Find the list of static instances for the CLASS_DECL.  Create one if
1470      not found.  */
1471   for (chain = &objc_static_instances;
1472        *chain && TREE_VALUE (*chain) != class_decl;
1473        chain = &TREE_CHAIN (*chain));
1474   if (!*chain)
1475     {
1476       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1477       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1478     }
1479
1480   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1481   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1482   DECL_COMMON (decl) = 1;
1483   TREE_STATIC (decl) = 1;
1484   DECL_ARTIFICIAL (decl) = 1;
1485   DECL_INITIAL (decl) = constructor;
1486
1487   /* We may be writing something else just now.
1488      Postpone till end of input.  */
1489   DECL_DEFER_OUTPUT (decl) = 1;
1490   pushdecl_top_level (decl);
1491   rest_of_decl_compilation (decl, 0, 1, 0);
1492
1493   /* Add the DECL to the head of this CLASS' list.  */
1494   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1495
1496   return decl;
1497 }
1498
1499 /* Build a static constant CONSTRUCTOR
1500    with type TYPE and elements ELTS.  */
1501
1502 static tree
1503 objc_build_constructor (tree type, tree elts)
1504 {
1505   tree constructor, f, e;
1506
1507   /* ??? Most of the places that we build constructors, we don't fill in
1508      the type of integers properly.  Convert them all en masse.  */
1509   if (TREE_CODE (type) == ARRAY_TYPE)
1510     {
1511       f = TREE_TYPE (type);
1512       if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
1513         for (e = elts; e ; e = TREE_CHAIN (e))
1514           TREE_VALUE (e) = convert (f, TREE_VALUE (e));
1515     }
1516   else
1517     {
1518       f = TYPE_FIELDS (type);
1519       for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
1520         if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
1521             || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
1522           TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
1523     }
1524
1525   constructor = build_constructor (type, elts);
1526   TREE_CONSTANT (constructor) = 1;
1527   TREE_STATIC (constructor) = 1;
1528   TREE_READONLY (constructor) = 1;
1529
1530 #ifdef OBJCPLUS
1531   /* zlaski 2001-Apr-02: mark this as a call to a constructor, as required by
1532      build_unary_op (wasn't true in 2.7.2.1 days) */
1533   TREE_HAS_CONSTRUCTOR (constructor) = 1;
1534 #endif
1535   return constructor;
1536 }
1537 \f
1538 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1539
1540 /* Predefine the following data type:
1541
1542    struct _objc_symtab
1543    {
1544      long sel_ref_cnt;
1545      SEL *refs;
1546      short cls_def_cnt;
1547      short cat_def_cnt;
1548      void *defs[cls_def_cnt + cat_def_cnt];
1549    }; */
1550
1551 static void
1552 build_objc_symtab_template (void)
1553 {
1554   tree field_decl, field_decl_chain;
1555
1556   objc_symtab_template
1557     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1558
1559   /* long sel_ref_cnt; */
1560
1561   field_decl = create_builtin_decl (FIELD_DECL,
1562                                     long_integer_type_node,
1563                                     "sel_ref_cnt");
1564   field_decl_chain = field_decl;
1565
1566   /* SEL *refs; */
1567
1568   field_decl = create_builtin_decl (FIELD_DECL,
1569                                     build_pointer_type (objc_selector_type),
1570                                     "refs");
1571   chainon (field_decl_chain, field_decl);
1572
1573   /* short cls_def_cnt; */
1574
1575   field_decl = create_builtin_decl (FIELD_DECL,
1576                                     short_integer_type_node,
1577                                     "cls_def_cnt");
1578   chainon (field_decl_chain, field_decl);
1579
1580   /* short cat_def_cnt; */
1581
1582   field_decl = create_builtin_decl (FIELD_DECL,
1583                                     short_integer_type_node,
1584                                     "cat_def_cnt");
1585   chainon (field_decl_chain, field_decl);
1586
1587   if (imp_count || cat_count || !flag_next_runtime)
1588     {
1589       /* void *defs[imp_count + cat_count (+ 1)]; */
1590       /* NB: The index is one less than the size of the array.  */
1591       int index = imp_count + cat_count
1592                 + (flag_next_runtime? -1: 0);
1593       field_decl = create_builtin_decl
1594                    (FIELD_DECL,
1595                     build_array_type
1596                     (ptr_type_node,
1597                      build_index_type (build_int_2 (index, 0))),
1598                     "defs");
1599       chainon (field_decl_chain, field_decl);
1600     }
1601
1602   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1603 }
1604
1605 /* Create the initial value for the `defs' field of _objc_symtab.
1606    This is a CONSTRUCTOR.  */
1607
1608 static tree
1609 init_def_list (tree type)
1610 {
1611   tree expr, initlist = NULL_TREE;
1612   struct imp_entry *impent;
1613
1614   if (imp_count)
1615     for (impent = imp_list; impent; impent = impent->next)
1616       {
1617         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1618           {
1619             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1620             initlist = tree_cons (NULL_TREE, expr, initlist);
1621           }
1622       }
1623
1624   if (cat_count)
1625     for (impent = imp_list; impent; impent = impent->next)
1626       {
1627         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1628           {
1629             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1630             initlist = tree_cons (NULL_TREE, expr, initlist);
1631           }
1632       }
1633
1634   if (!flag_next_runtime)
1635     {
1636       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1637       tree expr;
1638
1639       if (static_instances_decl)
1640         expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1641       else
1642         expr = build_int_2 (0, 0);
1643
1644       initlist = tree_cons (NULL_TREE, expr, initlist);
1645     }
1646
1647   return objc_build_constructor (type, nreverse (initlist));
1648 }
1649
1650 /* Construct the initial value for all of _objc_symtab.  */
1651
1652 static tree
1653 init_objc_symtab (tree type)
1654 {
1655   tree initlist;
1656
1657   /* sel_ref_cnt = { ..., 5, ... } */
1658
1659   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1660
1661   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1662
1663   if (flag_next_runtime || ! sel_ref_chain)
1664     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1665   else
1666     initlist = tree_cons (NULL_TREE,
1667                           build_unary_op (ADDR_EXPR,
1668                                           UOBJC_SELECTOR_TABLE_decl, 1),
1669                           initlist);
1670
1671   /* cls_def_cnt = { ..., 5, ... } */
1672
1673   initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1674
1675   /* cat_def_cnt = { ..., 5, ... } */
1676
1677   initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1678
1679   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1680
1681   if (imp_count || cat_count || !flag_next_runtime)
1682     {
1683
1684       tree field = TYPE_FIELDS (type);
1685       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1686
1687       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1688                             initlist);
1689     }
1690
1691   return objc_build_constructor (type, nreverse (initlist));
1692 }
1693
1694 /* Generate forward declarations for metadata such as
1695   'OBJC_CLASS_...'.  */
1696
1697 static tree
1698 build_metadata_decl (const char *name, tree type)
1699 {
1700   tree decl, decl_specs;
1701   /* extern struct TYPE NAME_<name>; */
1702   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
1703   decl_specs = tree_cons (NULL_TREE, type, decl_specs);
1704   decl = define_decl (synth_id_with_class_suffix
1705                       (name,
1706                        objc_implementation_context),
1707                       decl_specs);
1708   TREE_USED (decl) = 1;
1709   DECL_ARTIFICIAL (decl) = 1;
1710   TREE_PUBLIC (decl) = 0;
1711   return decl;
1712 }
1713
1714 /* Push forward-declarations of all the categories so that
1715    init_def_list can use them in a CONSTRUCTOR.  */
1716
1717 static void
1718 forward_declare_categories (void)
1719 {
1720   struct imp_entry *impent;
1721   tree sav = objc_implementation_context;
1722
1723   for (impent = imp_list; impent; impent = impent->next)
1724     {
1725       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1726         {
1727           /* Set an invisible arg to synth_id_with_class_suffix.  */
1728           objc_implementation_context = impent->imp_context;
1729           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1730           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1731                                                     objc_category_template);                    
1732         }
1733     }
1734   objc_implementation_context = sav;
1735 }
1736
1737 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1738    and initialized appropriately.  */
1739
1740 static void
1741 generate_objc_symtab_decl (void)
1742 {
1743   tree sc_spec;
1744
1745   if (!objc_category_template)
1746     build_category_template ();
1747
1748   /* forward declare categories */
1749   if (cat_count)
1750     forward_declare_categories ();
1751
1752   if (!objc_symtab_template)
1753     build_objc_symtab_template ();
1754
1755   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1756
1757   UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1758                                    tree_cons (NULL_TREE,
1759                                               objc_symtab_template, sc_spec),
1760                                    1,
1761                                    NULL_TREE);
1762
1763   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1764   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1765   DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1766   finish_decl (UOBJC_SYMBOLS_decl,
1767                init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1768                NULL_TREE);
1769 }
1770 \f
1771 static tree
1772 init_module_descriptor (tree type)
1773 {
1774   tree initlist, expr;
1775
1776   /* version = { 1, ... } */
1777
1778   expr = build_int_2 (OBJC_VERSION, 0);
1779   initlist = build_tree_list (NULL_TREE, expr);
1780
1781   /* size = { ..., sizeof (struct objc_module), ... } */
1782
1783   expr = size_in_bytes (objc_module_template);
1784   initlist = tree_cons (NULL_TREE, expr, initlist);
1785
1786   /* name = { ..., "foo.m", ... } */
1787
1788   expr = add_objc_string (get_identifier (input_filename), class_names);
1789   initlist = tree_cons (NULL_TREE, expr, initlist);
1790
1791   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1792
1793   if (UOBJC_SYMBOLS_decl)
1794     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1795   else
1796     expr = build_int_2 (0, 0);
1797   initlist = tree_cons (NULL_TREE, expr, initlist);
1798
1799   return objc_build_constructor (type, nreverse (initlist));
1800 }
1801
1802 /* Write out the data structures to describe Objective C classes defined.
1803    If appropriate, compile and output a setup function to initialize them.
1804    Return a symbol_ref to the function to call to initialize the Objective C
1805    data structures for this file (and perhaps for other files also).
1806
1807    struct objc_module { ... } _OBJC_MODULE = { ... };   */
1808
1809 static rtx
1810 build_module_descriptor (void)
1811 {
1812   tree decl_specs, field_decl, field_decl_chain;
1813
1814   objc_module_template
1815     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1816
1817   /* Long version; */
1818
1819   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1820   field_decl = get_identifier ("version");
1821   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1822   field_decl_chain = field_decl;
1823
1824   /* long  size; */
1825
1826   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1827   field_decl = get_identifier ("size");
1828   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1829   chainon (field_decl_chain, field_decl);
1830
1831   /* char  *name; */
1832
1833   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1834   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1835   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1836   chainon (field_decl_chain, field_decl);
1837
1838   /* struct objc_symtab *symtab; */
1839
1840   decl_specs = get_identifier (UTAG_SYMTAB);
1841   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1842   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1843   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1844   chainon (field_decl_chain, field_decl);
1845
1846   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1847
1848   /* Create an instance of "objc_module".  */
1849
1850   decl_specs = tree_cons (NULL_TREE, objc_module_template,
1851                           build_tree_list (NULL_TREE,
1852                                            ridpointers[(int) RID_STATIC]));
1853
1854   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1855                                    decl_specs, 1, NULL_TREE);
1856
1857   DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1858   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1859   DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
1860
1861   finish_decl (UOBJC_MODULES_decl,
1862                init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1863                NULL_TREE);
1864
1865   /* Mark the decl to avoid "defined but not used" warning.  */
1866   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1867   
1868   mark_decl_referenced (UOBJC_MODULES_decl);
1869
1870   /* Generate a constructor call for the module descriptor.
1871      This code was generated by reading the grammar rules
1872      of c-parse.in;  Therefore, it may not be the most efficient
1873      way of generating the requisite code.  */
1874
1875   if (flag_next_runtime)
1876     return NULL_RTX;
1877
1878   {
1879     tree parms, execclass_decl, decelerator, void_list_node_1;
1880     tree init_function_name, init_function_decl, compound;
1881
1882     /* Declare void __objc_execClass (void *); */
1883
1884     void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1885     execclass_decl = build_decl (FUNCTION_DECL,
1886                                  get_identifier (TAG_EXECCLASS),
1887                                  build_function_type (void_type_node,
1888                                         tree_cons (NULL_TREE, ptr_type_node,
1889                                                    void_list_node)));
1890                                                 
1891     DECL_EXTERNAL (execclass_decl) = 1;
1892     DECL_ARTIFICIAL (execclass_decl) = 1;
1893     TREE_PUBLIC (execclass_decl) = 1;
1894     pushdecl (execclass_decl);
1895     rest_of_decl_compilation (execclass_decl, 0, 0, 0);
1896     assemble_external (execclass_decl);
1897
1898     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
1899
1900     init_function_name = get_file_function_name ('I');
1901     start_function (void_list_node_1,
1902                     build_nt (CALL_EXPR, init_function_name,
1903                               tree_cons (NULL_TREE, NULL_TREE,
1904                                          void_list_node),
1905                               NULL_TREE),
1906                     NULL_TREE);
1907     store_parm_decls ();
1908     compound = c_begin_compound_stmt (true);
1909
1910     init_function_decl = current_function_decl;
1911     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
1912     TREE_USED (init_function_decl) = 1;
1913     /* Don't let this one be deferred.  */
1914     DECL_INLINE (init_function_decl) = 0;
1915     DECL_UNINLINABLE (init_function_decl) = 1;
1916
1917     parms
1918       = build_tree_list (NULL_TREE,
1919                          build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1920     decelerator = build_function_call (execclass_decl, parms);
1921
1922     add_stmt (decelerator);
1923     add_stmt (c_end_compound_stmt (compound, true));
1924
1925     finish_function ();
1926
1927     return XEXP (DECL_RTL (init_function_decl), 0);
1928   }
1929 }
1930
1931 /* Return the DECL of the string IDENT in the SECTION.  */
1932
1933 static tree
1934 get_objc_string_decl (tree ident, enum string_section section)
1935 {
1936   tree chain;
1937
1938   if (section == class_names)
1939     chain = class_names_chain;
1940   else if (section == meth_var_names)
1941     chain = meth_var_names_chain;
1942   else if (section == meth_var_types)
1943     chain = meth_var_types_chain;
1944   else
1945     abort ();
1946
1947   for (; chain != 0; chain = TREE_CHAIN (chain))
1948     if (TREE_VALUE (chain) == ident)
1949       return (TREE_PURPOSE (chain));
1950
1951   abort ();
1952   return NULL_TREE;
1953 }
1954
1955 /* Output references to all statically allocated objects.  Return the DECL
1956    for the array built.  */
1957
1958 static void
1959 generate_static_references (void)
1960 {
1961   tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1962   tree class_name, class, decl, initlist;
1963   tree cl_chain, in_chain;
1964   int num_inst, num_class;
1965   char buf[256];
1966
1967   if (flag_next_runtime)
1968     abort ();
1969
1970   for (cl_chain = objc_static_instances, num_class = 0;
1971        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1972     {
1973       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1974            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1975
1976       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1977       ident = get_identifier (buf);
1978
1979       expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
1980       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1981                              build_tree_list (NULL_TREE,
1982                                               ridpointers[(int) RID_STATIC]));
1983       decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
1984       DECL_CONTEXT (decl) = 0;
1985       DECL_ARTIFICIAL (decl) = 1;
1986       TREE_USED (decl) = 1;
1987
1988       /* Output {class_name, ...}.  */
1989       class = TREE_VALUE (cl_chain);
1990       class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
1991       initlist = build_tree_list (NULL_TREE,
1992                                   build_unary_op (ADDR_EXPR, class_name, 1));
1993
1994       /* Output {..., instance, ...}.  */
1995       for (in_chain = TREE_PURPOSE (cl_chain);
1996            in_chain; in_chain = TREE_CHAIN (in_chain))
1997         {
1998           expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1999           initlist = tree_cons (NULL_TREE, expr, initlist);
2000         }
2001
2002       /* Output {..., NULL}.  */
2003       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2004
2005       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2006       finish_decl (decl, expr, NULL_TREE);
2007       decls
2008         = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2009     }
2010
2011   decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
2012   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
2013   expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
2014   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
2015                          build_tree_list (NULL_TREE,
2016                                           ridpointers[(int) RID_STATIC]));
2017   static_instances_decl
2018     = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
2019   TREE_USED (static_instances_decl) = 1;
2020   DECL_CONTEXT (static_instances_decl) = 0;
2021   DECL_ARTIFICIAL (static_instances_decl) = 1;
2022   expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
2023                             nreverse (decls));
2024   finish_decl (static_instances_decl, expr, NULL_TREE);
2025   rest_of_decl_compilation (static_instances_decl, 0, 0, 0);
2026 }
2027
2028 /* Output all strings.  */
2029
2030 static void
2031 generate_strings (void)
2032 {
2033   tree sc_spec, decl_specs, expr_decl;
2034   tree chain, string_expr;
2035   tree string, decl;
2036
2037   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2038     {
2039       string = TREE_VALUE (chain);
2040       decl = TREE_PURPOSE (chain);
2041       sc_spec
2042         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2043       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2044       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2045                             NULL_TREE, NULL_TREE);
2046       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2047       DECL_CONTEXT (decl) = NULL_TREE;
2048       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2049                                      IDENTIFIER_POINTER (string));
2050       finish_decl (decl, string_expr, NULL_TREE);
2051     }
2052
2053   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2054     {
2055       string = TREE_VALUE (chain);
2056       decl = TREE_PURPOSE (chain);
2057       sc_spec
2058         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2059       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2060       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2061                             NULL_TREE, NULL_TREE);
2062       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2063       DECL_CONTEXT (decl) = NULL_TREE;
2064       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2065                                      IDENTIFIER_POINTER (string));
2066       finish_decl (decl, string_expr, NULL_TREE);
2067     }
2068
2069   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2070     {
2071       string = TREE_VALUE (chain);
2072       decl = TREE_PURPOSE (chain);
2073       sc_spec
2074         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2075       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2076       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2077                             NULL_TREE, 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 tree
3189 objc_build_throw_stmt (tree throw_expr)
3190 {
3191   tree args;
3192
3193   objc_init_exceptions ();
3194
3195   if (throw_expr == NULL)
3196     {
3197       /* If we're not inside a @catch block, there is no "current
3198          exception" to be rethrown.  */
3199       if (cur_try_context == NULL
3200           || cur_try_context->current_catch == NULL)
3201         {
3202           error ("%<@throw%> (rethrow) used outside of a @catch block");
3203           return NULL_TREE;
3204         }
3205
3206       /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3207          value that we get from the runtime.  */
3208       throw_expr = objc_build_exc_ptr ();
3209     }
3210
3211   /* A throw is just a call to the runtime throw function with the
3212      object as a parameter.  */
3213   args = tree_cons (NULL, throw_expr, NULL);
3214   return add_stmt (build_function_call (objc_exception_throw_decl, args));
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), NULL_TREE, NULL_TREE);
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   mark_decl_referenced (UOBJC_CLASS_decl);
4217   mark_decl_referenced (UOBJC_METACLASS_decl);
4218
4219   /* Pre-build the following entities - for speed/convenience.  */
4220
4221   an_id = get_identifier ("super_class");
4222   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
4223   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
4224 }
4225
4226 static void
4227 error_with_ivar (const char *message, tree decl, tree rawdecl)
4228 {
4229   error ("%J%s `%s'", decl,
4230          message, gen_declaration (rawdecl, errbuf));
4231
4232 }
4233
4234 static void
4235 check_ivars (tree inter, tree imp)
4236 {
4237   tree intdecls = CLASS_IVARS (inter);
4238   tree impdecls = CLASS_IVARS (imp);
4239   tree rawintdecls = CLASS_RAW_IVARS (inter);
4240   tree rawimpdecls = CLASS_RAW_IVARS (imp);
4241
4242   while (1)
4243     {
4244       tree t1, t2;
4245
4246 #ifdef OBJCPLUS
4247       if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4248         intdecls = TREE_CHAIN (intdecls);
4249 #endif
4250       if (intdecls == 0 && impdecls == 0)
4251         break;
4252       if (intdecls == 0 || impdecls == 0)
4253         {
4254           error ("inconsistent instance variable specification");
4255           break;
4256         }
4257
4258       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4259
4260       if (TREE_VALUE (TREE_VALUE (rawimpdecls)))
4261         {
4262           /* t1 is the bit-field type, so t2 must be converted to the
4263              bit-field type for comparison as well.  */
4264           unsigned HOST_WIDE_INT width
4265             = tree_low_cst (TREE_VALUE (TREE_VALUE (rawimpdecls)), 1);
4266           if (width != TYPE_PRECISION (t2))
4267             t2 = build_nonstandard_integer_type (width, TYPE_UNSIGNED (t2));
4268         }
4269
4270       if (!comptypes (t1, t2)
4271           || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
4272                                   TREE_VALUE (TREE_VALUE (rawimpdecls))))
4273         {
4274           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4275             {
4276               error_with_ivar ("conflicting instance variable type",
4277                                impdecls, rawimpdecls);
4278               error_with_ivar ("previous declaration of",
4279                                intdecls, rawintdecls);
4280             }
4281           else                  /* both the type and the name don't match */
4282             {
4283               error ("inconsistent instance variable specification");
4284               break;
4285             }
4286         }
4287
4288       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4289         {
4290           error_with_ivar ("conflicting instance variable name",
4291                            impdecls, rawimpdecls);
4292           error_with_ivar ("previous declaration of",
4293                            intdecls, rawintdecls);
4294         }
4295
4296       intdecls = TREE_CHAIN (intdecls);
4297       impdecls = TREE_CHAIN (impdecls);
4298       rawintdecls = TREE_CHAIN (rawintdecls);
4299       rawimpdecls = TREE_CHAIN (rawimpdecls);
4300     }
4301 }
4302
4303 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
4304    This needs to be done just once per compilation.  */
4305
4306 static void
4307 build_super_template (void)
4308 {
4309   tree decl_specs, field_decl, field_decl_chain;
4310
4311   /* Suppress outputting debug symbols, because
4312      dbxout_init hasn't been called yet.  */
4313   enum debug_info_type save_write_symbols = write_symbols;
4314   const struct gcc_debug_hooks *save_hooks = debug_hooks;
4315
4316   write_symbols = NO_DEBUG;
4317   debug_hooks = &do_nothing_debug_hooks;
4318
4319   objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
4320
4321   /* struct objc_object *self; */
4322
4323   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
4324   field_decl = get_identifier ("self");
4325   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4326   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4327   field_decl_chain = field_decl;
4328
4329 #ifdef OBJCPLUS
4330   /* struct objc_class *super_class; */
4331 #else
4332   /* struct objc_class *class; */
4333 #endif
4334
4335   decl_specs = get_identifier (UTAG_CLASS);
4336   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
4337 #ifdef OBJCPLUS
4338   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4339 #else
4340   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
4341 #endif
4342
4343   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4344   chainon (field_decl_chain, field_decl);
4345
4346   finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
4347
4348   write_symbols = save_write_symbols;
4349   debug_hooks = save_hooks;
4350 }
4351
4352 /* struct objc_ivar {
4353      char *ivar_name;
4354      char *ivar_type;
4355      int ivar_offset;
4356    };  */
4357
4358 static tree
4359 build_ivar_template (void)
4360 {
4361   tree objc_ivar_id, objc_ivar_record;
4362   tree decl_specs, field_decl, field_decl_chain;
4363
4364   objc_ivar_id = get_identifier (UTAG_IVAR);
4365   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
4366
4367   /* char *ivar_name; */
4368
4369   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4370   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
4371
4372   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4373   field_decl_chain = field_decl;
4374
4375   /* char *ivar_type; */
4376
4377   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4378   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
4379
4380   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4381   chainon (field_decl_chain, field_decl);
4382
4383   /* int ivar_offset; */
4384
4385   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4386   field_decl = get_identifier ("ivar_offset");
4387
4388   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4389   chainon (field_decl_chain, field_decl);
4390
4391   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
4392
4393   return objc_ivar_record;
4394 }
4395
4396 /* struct {
4397      int ivar_count;
4398      struct objc_ivar ivar_list[ivar_count];
4399    };  */
4400
4401 static tree
4402 build_ivar_list_template (tree list_type, int size)
4403 {
4404   tree objc_ivar_list_record;
4405   tree decl_specs, field_decl, field_decl_chain;
4406
4407   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4408
4409   /* int ivar_count; */
4410
4411   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4412   field_decl = get_identifier ("ivar_count");
4413
4414   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4415   field_decl_chain = field_decl;
4416
4417   /* struct objc_ivar ivar_list[]; */
4418
4419   decl_specs = build_tree_list (NULL_TREE, list_type);
4420   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
4421                          build_int_2 (size, 0), NULL_TREE, NULL_TREE);
4422
4423   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4424   chainon (field_decl_chain, field_decl);
4425
4426   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4427
4428   return objc_ivar_list_record;
4429 }
4430
4431 /* struct {
4432      int method_next;
4433      int method_count;
4434      struct objc_method method_list[method_count];
4435    };  */
4436
4437 static tree
4438 build_method_list_template (tree list_type, int size)
4439 {
4440   tree objc_ivar_list_record;
4441   tree decl_specs, field_decl, field_decl_chain;
4442
4443   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4444
4445   /* int method_next; */
4446
4447   decl_specs
4448     = build_tree_list
4449       (NULL_TREE,
4450        xref_tag (RECORD_TYPE,
4451                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
4452   field_decl
4453     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
4454   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4455   field_decl_chain = field_decl;
4456
4457   /* int method_count; */
4458
4459   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4460   field_decl = get_identifier ("method_count");
4461
4462   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4463   chainon (field_decl_chain, field_decl);
4464
4465   /* struct objc_method method_list[]; */
4466
4467   decl_specs = build_tree_list (NULL_TREE, list_type);
4468   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
4469                          build_int_2 (size, 0), NULL_TREE, NULL_TREE);
4470
4471   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4472   chainon (field_decl_chain, field_decl);
4473
4474   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4475
4476   return objc_ivar_list_record;
4477 }
4478
4479 static tree
4480 build_ivar_list_initializer (tree type, tree field_decl)
4481 {
4482   tree initlist = NULL_TREE;
4483
4484   do
4485     {
4486       tree ivar = NULL_TREE;
4487
4488       /* Set name.  */
4489       if (DECL_NAME (field_decl))
4490         ivar = tree_cons (NULL_TREE,
4491                           add_objc_string (DECL_NAME (field_decl),
4492                                            meth_var_names),
4493                           ivar);
4494       else
4495         /* Unnamed bit-field ivar (yuck).  */
4496         ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
4497
4498       /* Set type.  */
4499       encode_field_decl (field_decl,
4500                          obstack_object_size (&util_obstack),
4501                          OBJC_ENCODE_DONT_INLINE_DEFS);
4502
4503       /* Null terminate string.  */
4504       obstack_1grow (&util_obstack, 0);
4505       ivar
4506         = tree_cons
4507           (NULL_TREE,
4508            add_objc_string (get_identifier (obstack_finish (&util_obstack)),
4509                             meth_var_types),
4510            ivar);
4511       obstack_free (&util_obstack, util_firstobj);
4512
4513       /* Set offset.  */
4514       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
4515       initlist = tree_cons (NULL_TREE,
4516                             objc_build_constructor (type, nreverse (ivar)),
4517                             initlist);
4518       do
4519         field_decl = TREE_CHAIN (field_decl);
4520       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
4521     }
4522   while (field_decl);
4523
4524   return objc_build_constructor (build_array_type (type, 0),
4525                                  nreverse (initlist));
4526 }
4527
4528 static tree
4529 generate_ivars_list (tree type, const char *name, int size, tree list)
4530 {
4531   tree sc_spec, decl_specs, decl, initlist;
4532
4533   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4534   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4535
4536   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4537                      decl_specs, 1, NULL_TREE);
4538
4539   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
4540   initlist = tree_cons (NULL_TREE, list, initlist);
4541
4542   finish_decl (decl,
4543                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4544                NULL_TREE);
4545
4546   return decl;
4547 }
4548
4549 /* Count only the fields occurring in T.  */
4550 static int
4551 ivar_list_length (tree t)
4552 {
4553   int count = 0;
4554
4555   for (; t; t = TREE_CHAIN (t))
4556     if (TREE_CODE (t) == FIELD_DECL)
4557       ++count;
4558
4559   return count;
4560 }
4561
4562 static void
4563 generate_ivar_lists (void)
4564 {
4565   tree initlist, ivar_list_template, chain;
4566   tree cast, variable_length_type;
4567   int size;
4568
4569   generating_instance_variables = 1;
4570
4571   if (!objc_ivar_template)
4572     objc_ivar_template = build_ivar_template ();
4573
4574   cast
4575     = build_tree_list
4576       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
4577                                          get_identifier (UTAG_IVAR_LIST))),
4578        NULL_TREE);
4579   variable_length_type = groktypename (cast);
4580
4581   /* Only generate class variables for the root of the inheritance
4582      hierarchy since these will be the same for every class.  */
4583
4584   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
4585       && (chain = TYPE_FIELDS (objc_class_template)))
4586     {
4587       size = ivar_list_length (chain);
4588
4589       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4590       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4591
4592       UOBJC_CLASS_VARIABLES_decl
4593         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
4594                                size, initlist);
4595       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
4596     }
4597   else
4598     UOBJC_CLASS_VARIABLES_decl = 0;
4599
4600   chain = CLASS_IVARS (implementation_template);
4601   if (chain)
4602     {
4603       size = ivar_list_length (chain);
4604       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4605       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4606
4607       UOBJC_INSTANCE_VARIABLES_decl
4608         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
4609                                size, initlist);
4610       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
4611     }
4612   else
4613     UOBJC_INSTANCE_VARIABLES_decl = 0;
4614
4615   generating_instance_variables = 0;
4616 }
4617
4618 static tree
4619 build_dispatch_table_initializer (tree type, tree entries)
4620 {
4621   tree initlist = NULL_TREE;
4622
4623   do
4624     {
4625       tree elemlist = NULL_TREE;
4626
4627       elemlist = tree_cons (NULL_TREE,
4628                             build_selector (METHOD_SEL_NAME (entries)),
4629                             NULL_TREE);
4630
4631       /* Generate the method encoding if we don't have one already.  */
4632       if (! METHOD_ENCODING (entries))
4633         METHOD_ENCODING (entries) =
4634           encode_method_prototype (entries);
4635
4636       elemlist = tree_cons (NULL_TREE,
4637                             add_objc_string (METHOD_ENCODING (entries),
4638                                              meth_var_types),
4639                             elemlist);
4640
4641       elemlist = tree_cons (NULL_TREE,
4642                             build_unary_op (ADDR_EXPR,
4643                                             METHOD_DEFINITION (entries), 1),
4644                             elemlist);
4645
4646       initlist = tree_cons (NULL_TREE,
4647                             objc_build_constructor (type, nreverse (elemlist)),
4648                             initlist);
4649
4650       entries = TREE_CHAIN (entries);
4651     }
4652   while (entries);
4653
4654   return objc_build_constructor (build_array_type (type, 0),
4655                                  nreverse (initlist));
4656 }
4657
4658 /* To accomplish method prototyping without generating all kinds of
4659    inane warnings, the definition of the dispatch table entries were
4660    changed from:
4661
4662         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4663    to:
4664         struct objc_method { SEL _cmd; ...; void *_imp; };  */
4665
4666 static tree
4667 build_method_template (void)
4668 {
4669   tree _SLT_record;
4670   tree decl_specs, field_decl, field_decl_chain;
4671
4672   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4673
4674   /* struct objc_selector *_cmd; */
4675   decl_specs = tree_cons (NULL_TREE,
4676                           xref_tag (RECORD_TYPE,
4677                                     get_identifier (TAG_SELECTOR)),
4678                           NULL_TREE);
4679   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4680
4681   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4682   field_decl_chain = field_decl;
4683
4684   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4685   field_decl = build1 (INDIRECT_REF, NULL_TREE,
4686                        get_identifier ("method_types"));
4687   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4688   chainon (field_decl_chain, field_decl);
4689
4690   /* void *_imp; */
4691
4692   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4693   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4694   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4695   chainon (field_decl_chain, field_decl);
4696
4697   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4698
4699   return _SLT_record;
4700 }
4701
4702
4703 static tree
4704 generate_dispatch_table (tree type, const char *name, int size, tree list)
4705 {
4706   tree sc_spec, decl_specs, decl, initlist;
4707
4708   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4709   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4710
4711   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4712                      decl_specs, 1, NULL_TREE);
4713
4714   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4715   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4716   initlist = tree_cons (NULL_TREE, list, initlist);
4717
4718   finish_decl (decl,
4719                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4720                NULL_TREE);
4721
4722   return decl;
4723 }
4724
4725 static void
4726 mark_referenced_methods (void)
4727 {
4728   struct imp_entry *impent;
4729   tree chain;
4730
4731   for (impent = imp_list; impent; impent = impent->next)
4732     {
4733       chain = CLASS_CLS_METHODS (impent->imp_context);
4734       while (chain)
4735         {
4736           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4737           chain = TREE_CHAIN (chain);
4738         }
4739
4740       chain = CLASS_NST_METHODS (impent->imp_context);
4741       while (chain)
4742         {
4743           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4744           chain = TREE_CHAIN (chain);
4745         }
4746     }
4747 }
4748
4749 static void
4750 generate_dispatch_tables (void)
4751 {
4752   tree initlist, chain, method_list_template;
4753   tree cast, variable_length_type;
4754   int size;
4755
4756   if (!objc_method_template)
4757     objc_method_template = build_method_template ();
4758
4759   cast
4760     = build_tree_list
4761       (build_tree_list (NULL_TREE,
4762                         xref_tag (RECORD_TYPE,
4763                                   get_identifier (UTAG_METHOD_LIST))),
4764        NULL_TREE);
4765
4766   variable_length_type = groktypename (cast);
4767
4768   chain = CLASS_CLS_METHODS (objc_implementation_context);
4769   if (chain)
4770     {
4771       size = list_length (chain);
4772
4773       method_list_template
4774         = build_method_list_template (objc_method_template, size);
4775       initlist
4776         = build_dispatch_table_initializer (objc_method_template, chain);
4777
4778       UOBJC_CLASS_METHODS_decl
4779         = generate_dispatch_table (method_list_template,
4780                                    ((TREE_CODE (objc_implementation_context)
4781                                      == CLASS_IMPLEMENTATION_TYPE)
4782                                     ? "_OBJC_CLASS_METHODS"
4783                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
4784                                    size, initlist);
4785       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4786     }
4787   else
4788     UOBJC_CLASS_METHODS_decl = 0;
4789
4790   chain = CLASS_NST_METHODS (objc_implementation_context);
4791   if (chain)
4792     {
4793       size = list_length (chain);
4794
4795       method_list_template
4796         = build_method_list_template (objc_method_template, size);
4797       initlist
4798         = build_dispatch_table_initializer (objc_method_template, chain);
4799
4800       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4801         UOBJC_INSTANCE_METHODS_decl
4802           = generate_dispatch_table (method_list_template,
4803                                      "_OBJC_INSTANCE_METHODS",
4804                                      size, initlist);
4805       else
4806         /* We have a category.  */
4807         UOBJC_INSTANCE_METHODS_decl
4808           = generate_dispatch_table (method_list_template,
4809                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
4810                                      size, initlist);
4811       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4812     }
4813   else
4814     UOBJC_INSTANCE_METHODS_decl = 0;
4815 }
4816
4817 static tree
4818 generate_protocol_list (tree i_or_p)
4819 {
4820   tree initlist, decl_specs, sc_spec;
4821   tree refs_decl, expr_decl, lproto, e, plist;
4822   tree cast_type;
4823   int size = 0;
4824
4825   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4826       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4827     plist = CLASS_PROTOCOL_LIST (i_or_p);
4828   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4829     plist = PROTOCOL_LIST (i_or_p);
4830   else
4831     abort ();
4832
4833   cast_type = groktypename
4834     (build_tree_list
4835      (build_tree_list (NULL_TREE,
4836                        xref_tag (RECORD_TYPE,
4837                                  get_identifier (UTAG_PROTOCOL))),
4838       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4839
4840   /* Compute size.  */
4841   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4842     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4843         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4844       size++;
4845
4846   /* Build initializer.  */
4847   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4848
4849   e = build_int_2 (size, 0);
4850   TREE_TYPE (e) = cast_type;
4851   initlist = tree_cons (NULL_TREE, e, initlist);
4852
4853   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4854     {
4855       tree pval = TREE_VALUE (lproto);
4856
4857       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4858           && PROTOCOL_FORWARD_DECL (pval))
4859         {
4860           e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4861           initlist = tree_cons (NULL_TREE, e, initlist);
4862         }
4863     }
4864
4865   /* static struct objc_protocol *refs[n]; */
4866
4867   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4868   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4869                                            get_identifier (UTAG_PROTOCOL)),
4870                           sc_spec);
4871
4872   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4873     expr_decl = build_nt (ARRAY_REF,
4874                           synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4875                                                       i_or_p),
4876                           build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
4877   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4878     expr_decl = build_nt (ARRAY_REF,
4879                           synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4880                                                       i_or_p),
4881                           build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
4882   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4883     expr_decl
4884       = build_nt (ARRAY_REF,
4885                   synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4886                                               i_or_p),
4887                   build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
4888   else
4889     abort ();
4890
4891   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4892
4893   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4894   DECL_CONTEXT (refs_decl) = NULL_TREE;
4895
4896   finish_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4897                                                   nreverse (initlist)),
4898                NULL_TREE);
4899
4900   return refs_decl;
4901 }
4902
4903 static tree
4904 build_category_initializer (tree type, tree cat_name, tree class_name,
4905                             tree instance_methods, tree class_methods,
4906                             tree protocol_list)
4907 {
4908   tree initlist = NULL_TREE, expr;
4909
4910   initlist = tree_cons (NULL_TREE, cat_name, initlist);
4911   initlist = tree_cons (NULL_TREE, class_name, initlist);
4912
4913   if (!instance_methods)
4914     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4915   else
4916     {
4917       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4918       initlist = tree_cons (NULL_TREE, expr, initlist);
4919     }
4920   if (!class_methods)
4921     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4922   else
4923     {
4924       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4925       initlist = tree_cons (NULL_TREE, expr, initlist);
4926     }
4927
4928   /* protocol_list = */
4929   if (!protocol_list)
4930      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4931   else
4932      {
4933        tree cast_type2 = groktypename
4934          (build_tree_list
4935           (build_tree_list (NULL_TREE,
4936                             xref_tag (RECORD_TYPE,
4937                                       get_identifier (UTAG_PROTOCOL))),
4938            build1 (INDIRECT_REF, NULL_TREE,
4939                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4940
4941         expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4942         TREE_TYPE (expr) = cast_type2;
4943         initlist = tree_cons (NULL_TREE, expr, initlist);
4944      }
4945
4946   return objc_build_constructor (type, nreverse (initlist));
4947 }
4948
4949 /* struct objc_class {
4950      struct objc_class *isa;
4951      struct objc_class *super_class;
4952      char *name;
4953      long version;
4954      long info;
4955      long instance_size;
4956      struct objc_ivar_list *ivars;
4957      struct objc_method_list *methods;
4958      if (flag_next_runtime)
4959        struct objc_cache *cache;
4960      else {
4961        struct sarray *dtable;
4962        struct objc_class *subclass_list;
4963        struct objc_class *sibling_class;
4964      }
4965      struct objc_protocol_list *protocols;
4966      if (flag_next_runtime)
4967        void *sel_id;
4968      void *gc_object_type;
4969    };  */
4970
4971 static tree
4972 build_shared_structure_initializer (tree type, tree isa, tree super,
4973                                     tree name, tree size, int status,
4974                                     tree dispatch_table, tree ivar_list,
4975                                     tree protocol_list)
4976 {
4977   tree initlist = NULL_TREE, expr;
4978
4979   /* isa = */
4980   initlist = tree_cons (NULL_TREE, isa, initlist);
4981
4982   /* super_class = */
4983   initlist = tree_cons (NULL_TREE, super, initlist);
4984
4985   /* name = */
4986   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4987
4988   /* version = */
4989   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4990
4991   /* info = */
4992   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4993
4994   /* instance_size = */
4995   initlist = tree_cons (NULL_TREE, size, initlist);
4996
4997   /* objc_ivar_list = */
4998   if (!ivar_list)
4999     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5000   else
5001     {
5002       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
5003       initlist = tree_cons (NULL_TREE, expr, initlist);
5004     }
5005
5006   /* objc_method_list = */
5007   if (!dispatch_table)
5008     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5009   else
5010     {
5011       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
5012       initlist = tree_cons (NULL_TREE, expr, initlist);
5013     }
5014
5015   if (flag_next_runtime)
5016     /* method_cache = */
5017     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5018   else
5019     {
5020       /* dtable = */
5021       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5022
5023       /* subclass_list = */
5024       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5025
5026       /* sibling_class = */
5027       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5028     }
5029
5030   /* protocol_list = */
5031   if (! protocol_list)
5032     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5033   else
5034      {
5035        tree cast_type2
5036          = groktypename
5037          (build_tree_list
5038           (build_tree_list (NULL_TREE,
5039                             xref_tag (RECORD_TYPE,
5040                                       get_identifier (UTAG_PROTOCOL))),
5041            build1 (INDIRECT_REF, NULL_TREE,
5042                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
5043
5044      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
5045      TREE_TYPE (expr) = cast_type2;
5046      initlist = tree_cons (NULL_TREE, expr, initlist);
5047      }
5048
5049   if (flag_next_runtime)
5050     /* sel_id = NULL */
5051     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5052
5053   /* gc_object_type = NULL */
5054   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5055
5056   return objc_build_constructor (type, nreverse (initlist));
5057 }
5058
5059 /* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
5060
5061 static inline tree
5062 lookup_category (tree class, tree cat_name)
5063 {
5064   tree category = CLASS_CATEGORY_LIST (class);
5065
5066   while (category && CLASS_SUPER_NAME (category) != cat_name)
5067     category = CLASS_CATEGORY_LIST (category);
5068   return category;
5069 }
5070
5071 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
5072
5073 static void
5074 generate_category (tree cat)
5075 {
5076   tree sc_spec, decl_specs, decl;
5077   tree initlist, cat_name_expr, class_name_expr;
5078   tree protocol_decl, category;
5079
5080   add_class_reference (CLASS_NAME (cat));
5081   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5082
5083   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5084
5085   category = lookup_category (implementation_template,
5086                                 CLASS_SUPER_NAME (cat));
5087
5088   if (category && CLASS_PROTOCOL_LIST (category))
5089     {
5090       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5091       protocol_decl = generate_protocol_list (category);
5092     }
5093   else
5094     protocol_decl = 0;
5095
5096   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
5097   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
5098
5099   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
5100                                                  objc_implementation_context),
5101                      decl_specs, 1, NULL_TREE);
5102
5103   initlist = build_category_initializer (TREE_TYPE (decl),
5104                                          cat_name_expr, class_name_expr,
5105                                          UOBJC_INSTANCE_METHODS_decl,
5106                                          UOBJC_CLASS_METHODS_decl,
5107                                          protocol_decl);
5108
5109   finish_decl (decl, initlist, NULL_TREE);
5110 }
5111
5112 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5113    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
5114
5115 static void
5116 generate_shared_structures (void)
5117 {
5118   tree sc_spec, decl_specs, decl;
5119   tree name_expr, super_expr, root_expr;
5120   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5121   tree cast_type, initlist, protocol_decl;
5122
5123   my_super_id = CLASS_SUPER_NAME (implementation_template);
5124   if (my_super_id)
5125     {
5126       add_class_reference (my_super_id);
5127
5128       /* Compute "my_root_id" - this is required for code generation.
5129          the "isa" for all meta class structures points to the root of
5130          the inheritance hierarchy (e.g. "__Object")...  */
5131       my_root_id = my_super_id;
5132       do
5133         {
5134           tree my_root_int = lookup_interface (my_root_id);
5135
5136           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5137             my_root_id = CLASS_SUPER_NAME (my_root_int);
5138           else
5139             break;
5140         }
5141       while (1);
5142     }
5143   else
5144     /* No super class.  */
5145     my_root_id = CLASS_NAME (implementation_template);
5146
5147   cast_type
5148     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5149                                                       objc_class_template),
5150                                      build1 (INDIRECT_REF,
5151                                              NULL_TREE, NULL_TREE)));
5152
5153   name_expr = add_objc_string (CLASS_NAME (implementation_template),
5154                                class_names);
5155
5156   /* Install class `isa' and `super' pointers at runtime.  */
5157   if (my_super_id)
5158     {
5159       super_expr = add_objc_string (my_super_id, class_names);
5160       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5161     }
5162   else
5163     super_expr = build_int_2 (0, 0);
5164
5165   root_expr = add_objc_string (my_root_id, class_names);
5166   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5167
5168   if (CLASS_PROTOCOL_LIST (implementation_template))
5169     {
5170       generate_protocol_references
5171         (CLASS_PROTOCOL_LIST (implementation_template));
5172       protocol_decl = generate_protocol_list (implementation_template);
5173     }
5174   else
5175     protocol_decl = 0;
5176
5177   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5178
5179   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5180   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5181
5182   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
5183                      NULL_TREE);
5184
5185   initlist
5186     = build_shared_structure_initializer
5187       (TREE_TYPE (decl),
5188        root_expr, super_expr, name_expr,
5189        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5190        2 /*CLS_META*/,
5191        UOBJC_CLASS_METHODS_decl,
5192        UOBJC_CLASS_VARIABLES_decl,
5193        protocol_decl);
5194
5195   finish_decl (decl, initlist, NULL_TREE);
5196
5197   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5198
5199   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
5200                      NULL_TREE);
5201
5202   initlist
5203     = build_shared_structure_initializer
5204       (TREE_TYPE (decl),
5205        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5206        super_expr, name_expr,
5207        convert (integer_type_node,
5208                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5209                                 (implementation_template))),
5210        1 /*CLS_FACTORY*/,
5211        UOBJC_INSTANCE_METHODS_decl,
5212        UOBJC_INSTANCE_VARIABLES_decl,
5213        protocol_decl);
5214
5215   finish_decl (decl, initlist, NULL_TREE);
5216 }
5217
5218 static tree
5219 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5220 {
5221   char *string;
5222   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5223       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5224     {
5225       const char *const class_name
5226         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5227       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
5228       sprintf (string, "%s_%s", preamble,
5229                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5230     }
5231   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5232            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5233     {
5234       /* We have a category.  */
5235       const char *const class_name
5236         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5237       const char *const class_super_name
5238         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5239       string = (char *) alloca (strlen (preamble)
5240                                 + strlen (class_name)
5241                                 + strlen (class_super_name)
5242                                 + 3);
5243       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5244     }
5245   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5246     {
5247       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5248       string
5249         = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
5250       sprintf (string, "%s_%s", preamble, protocol_name);
5251     }
5252   else
5253     abort ();
5254
5255   return get_identifier (string);
5256 }
5257
5258 static int
5259 is_objc_type_qualifier (tree node)
5260 {
5261   return (TREE_CODE (node) == IDENTIFIER_NODE
5262           && (node == ridpointers [(int) RID_CONST]
5263               || node == ridpointers [(int) RID_VOLATILE]
5264               || node == ridpointers [(int) RID_IN]
5265               || node == ridpointers [(int) RID_OUT]
5266               || node == ridpointers [(int) RID_INOUT]
5267               || node == ridpointers [(int) RID_BYCOPY]
5268               || node == ridpointers [(int) RID_BYREF]
5269               || node == ridpointers [(int) RID_ONEWAY]));
5270 }
5271
5272 /* If type is empty or only type qualifiers are present, add default
5273    type of id (otherwise grokdeclarator will default to int).  */
5274
5275 static tree
5276 adjust_type_for_id_default (tree type)
5277 {
5278   tree declspecs, chain;
5279
5280   if (!type)
5281     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
5282                             build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5283
5284   declspecs = TREE_PURPOSE (type);
5285
5286   /* Determine if a typespec is present.  */
5287   for (chain = declspecs;
5288        chain;
5289        chain = TREE_CHAIN (chain))
5290     {
5291       if (TYPED_OBJECT (TREE_VALUE (chain))
5292           && !(TREE_VALUE (type)
5293                && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
5294         error ("can not use an object as parameter to a method\n");
5295       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
5296         return type;
5297     }
5298
5299   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
5300                                      declspecs),
5301                           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5302 }
5303
5304 /*   Usage:
5305                 keyworddecl:
5306                         selector ':' '(' typename ')' identifier
5307
5308      Purpose:
5309                 Transform an Objective-C keyword argument into
5310                 the C equivalent parameter declarator.
5311
5312      In:        key_name, an "identifier_node" (optional).
5313                 arg_type, a  "tree_list" (optional).
5314                 arg_name, an "identifier_node".
5315
5316      Note:      It would be really nice to strongly type the preceding
5317                 arguments in the function prototype; however, then I
5318                 could not use the "accessor" macros defined in "tree.h".
5319
5320      Out:       an instance of "keyword_decl".  */
5321
5322 tree
5323 build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5324 {
5325   tree keyword_decl;
5326
5327   /* If no type is specified, default to "id".  */
5328   arg_type = adjust_type_for_id_default (arg_type);
5329
5330   keyword_decl = make_node (KEYWORD_DECL);
5331
5332   TREE_TYPE (keyword_decl) = arg_type;
5333   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5334   KEYWORD_KEY_NAME (keyword_decl) = key_name;
5335
5336   return keyword_decl;
5337 }
5338
5339 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
5340
5341 static tree
5342 build_keyword_selector (tree selector)
5343 {
5344   int len = 0;
5345   tree key_chain, key_name;
5346   char *buf;
5347
5348   /* Scan the selector to see how much space we'll need.  */
5349   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5350     {
5351       if (TREE_CODE (selector) == KEYWORD_DECL)
5352         key_name = KEYWORD_KEY_NAME (key_chain);
5353       else if (TREE_CODE (selector) == TREE_LIST)
5354         key_name = TREE_PURPOSE (key_chain);
5355       else
5356         abort ();
5357
5358       if (key_name)
5359         len += IDENTIFIER_LENGTH (key_name) + 1;
5360       else
5361         /* Just a ':' arg.  */
5362         len++;
5363     }
5364
5365   buf = (char *) alloca (len + 1);
5366   /* Start the buffer out as an empty string.  */
5367   buf[0] = '\0';
5368
5369   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5370     {
5371       if (TREE_CODE (selector) == KEYWORD_DECL)
5372         key_name = KEYWORD_KEY_NAME (key_chain);
5373       else if (TREE_CODE (selector) == TREE_LIST)
5374         {
5375           key_name = TREE_PURPOSE (key_chain);
5376           /* The keyword decl chain will later be used as a function argument
5377              chain.  Unhook the selector itself so as to not confuse other
5378              parts of the compiler.  */
5379           TREE_PURPOSE (key_chain) = NULL_TREE;
5380         }
5381       else
5382         abort ();
5383
5384       if (key_name)
5385         strcat (buf, IDENTIFIER_POINTER (key_name));
5386       strcat (buf, ":");
5387     }
5388
5389   return get_identifier (buf);
5390 }
5391
5392 /* Used for declarations and definitions.  */
5393
5394 tree
5395 build_method_decl (enum tree_code code, tree ret_type, tree selector,
5396                    tree add_args)
5397 {
5398   tree method_decl;
5399
5400   /* If no type is specified, default to "id".  */
5401   ret_type = adjust_type_for_id_default (ret_type);
5402
5403   method_decl = make_node (code);
5404   TREE_TYPE (method_decl) = ret_type;
5405
5406   /* If we have a keyword selector, create an identifier_node that
5407      represents the full selector name (`:' included)...  */
5408   if (TREE_CODE (selector) == KEYWORD_DECL)
5409     {
5410       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5411       METHOD_SEL_ARGS (method_decl) = selector;
5412       METHOD_ADD_ARGS (method_decl) = add_args;
5413     }
5414   else
5415     {
5416       METHOD_SEL_NAME (method_decl) = selector;
5417       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5418       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5419     }
5420
5421   return method_decl;
5422 }
5423
5424 #define METHOD_DEF 0
5425 #define METHOD_REF 1
5426
5427 /* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
5428    an argument list for method METH.  CONTEXT is either METHOD_DEF or
5429    METHOD_REF, saying whether we are trying to define a method or call
5430    one.  SUPERFLAG says this is for a send to super; this makes a
5431    difference for the NeXT calling sequence in which the lookup and
5432    the method call are done together.  If METH is null, user-defined
5433    arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
5434
5435 static tree
5436 get_arg_type_list (tree meth, int context, int superflag)
5437 {
5438   tree arglist, akey;
5439
5440   /* Receiver type.  */
5441   if (flag_next_runtime && superflag)
5442     arglist = build_tree_list (NULL_TREE, objc_super_type);
5443   else if (context == METHOD_DEF)
5444     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
5445   else
5446     arglist = build_tree_list (NULL_TREE, objc_id_type);
5447
5448   /* Selector type - will eventually change to `int'.  */
5449   chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
5450
5451   /* No actual method prototype given -- assume that remaining arguments
5452      are `...'.  */
5453   if (!meth)
5454     return arglist;
5455
5456   /* Build a list of argument types.  */
5457   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
5458     {
5459       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
5460       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
5461     }
5462
5463   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
5464     /* We have a `, ...' immediately following the selector,
5465        finalize the arglist...simulate get_parm_info (true).  */
5466     ;
5467   else if (METHOD_ADD_ARGS (meth))
5468     {
5469       /* we have a variable length selector */
5470       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
5471       chainon (arglist, add_arg_list);
5472     }
5473   else
5474     /* finalize the arglist...simulate get_parm_info (false) */
5475     chainon (arglist, void_list_node);
5476
5477   return arglist;
5478 }
5479
5480 static tree
5481 check_duplicates (hash hsh, int methods, int is_class)
5482 {
5483   tree meth = NULL_TREE;
5484
5485   if (hsh)
5486     {
5487       meth = hsh->key;
5488
5489       if (hsh->list)
5490         {
5491           /* We have two or more methods with the same name but
5492              different types.  */
5493           attr loop;
5494
5495           warning ("multiple %s named `%c%s' found",
5496                    methods ? "methods" : "selectors",
5497                    (is_class ? '+' : '-'),
5498                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5499
5500           warn_with_method (methods ? "using" : "found",
5501                             ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5502                              ? '-'
5503                              : '+'), 
5504                             meth);
5505           for (loop = hsh->list; loop; loop = loop->next)
5506             warn_with_method ("also found",
5507                               ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
5508                                ? '-' 
5509                                : '+'),
5510                               loop->value);
5511         }
5512     }
5513   return meth;
5514 }
5515
5516 /* If RECEIVER is a class reference, return the identifier node for
5517    the referenced class.  RECEIVER is created by get_class_reference,
5518    so we check the exact form created depending on which runtimes are
5519    used.  */
5520
5521 static tree
5522 receiver_is_class_object (tree receiver, int self, int super)
5523 {
5524   tree chain, exp, arg;
5525
5526   /* The receiver is 'self' or 'super' in the context of a class method.  */
5527   if (objc_method_context
5528       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
5529       && (self || super))
5530     return (super
5531             ? CLASS_SUPER_NAME (implementation_template)
5532             : CLASS_NAME (implementation_template));
5533
5534   if (flag_next_runtime)
5535     {
5536       /* The receiver is a variable created by
5537          build_class_reference_decl.  */
5538       if (TREE_CODE (receiver) == VAR_DECL
5539           && TREE_TYPE (TREE_TYPE (receiver)) == TREE_TYPE (objc_class_type))
5540         /* Look up the identifier.  */
5541         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5542           if (TREE_PURPOSE (chain) == receiver)
5543             return TREE_VALUE (chain);
5544     }
5545
5546   /* The receiver is a function call that returns an id.  Check if
5547      it is a call to objc_getClass, if so, pick up the class name.  */
5548   if (TREE_CODE (receiver) == CALL_EXPR
5549       && (exp = TREE_OPERAND (receiver, 0))
5550       && TREE_CODE (exp) == ADDR_EXPR
5551       && (exp = TREE_OPERAND (exp, 0))
5552       && TREE_CODE (exp) == FUNCTION_DECL
5553       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
5554          prototypes for objc_get_class().  Thankfully, they seem to share the
5555          same function type.  */
5556       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
5557       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
5558       /* We have a call to objc_get_class/objc_getClass!  */
5559       && (arg = TREE_OPERAND (receiver, 1))
5560       && TREE_CODE (arg) == TREE_LIST
5561       && (arg = TREE_VALUE (arg)))
5562     {
5563       STRIP_NOPS (arg);
5564       if (TREE_CODE (arg) == ADDR_EXPR
5565           && (arg = TREE_OPERAND (arg, 0))
5566           && TREE_CODE (arg) == STRING_CST)
5567         /* Finally, we have the class name.  */
5568         return get_identifier (TREE_STRING_POINTER (arg));
5569     }
5570   return 0;
5571 }
5572 \f
5573 /* If we are currently building a message expr, this holds
5574    the identifier of the selector of the message.  This is
5575    used when printing warnings about argument mismatches.  */
5576
5577 static tree current_objc_message_selector = 0;
5578
5579 tree
5580 objc_message_selector (void)
5581 {
5582   return current_objc_message_selector;
5583 }
5584
5585 /* Construct an expression for sending a message.
5586    MESS has the object to send to in TREE_PURPOSE
5587    and the argument list (including selector) in TREE_VALUE.
5588
5589    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
5590    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
5591
5592 tree
5593 build_message_expr (tree mess)
5594 {
5595   tree receiver = TREE_PURPOSE (mess);
5596   tree sel_name;
5597   tree args = TREE_VALUE (mess);
5598   tree method_params = NULL_TREE;
5599
5600   if (TREE_CODE (receiver) == ERROR_MARK)
5601     return error_mark_node;
5602
5603   /* Obtain the full selector name.  */
5604   if (TREE_CODE (args) == IDENTIFIER_NODE)
5605     /* A unary selector.  */
5606     sel_name = args;
5607   else if (TREE_CODE (args) == TREE_LIST)
5608     sel_name = build_keyword_selector (args);
5609   else
5610     abort ();
5611
5612   /* Build the parameter list to give to the method.  */
5613   if (TREE_CODE (args) == TREE_LIST)
5614     {
5615       tree chain = args, prev = NULL_TREE;
5616
5617       /* We have a keyword selector--check for comma expressions.  */
5618       while (chain)
5619         {
5620           tree element = TREE_VALUE (chain);
5621
5622           /* We have a comma expression, must collapse...  */
5623           if (TREE_CODE (element) == TREE_LIST)
5624             {
5625               if (prev)
5626                 TREE_CHAIN (prev) = element;
5627               else
5628                 args = element;
5629             }
5630           prev = chain;
5631           chain = TREE_CHAIN (chain);
5632         }
5633       method_params = args;
5634     }
5635
5636 #ifdef OBJCPLUS
5637   if (processing_template_decl)
5638     /* Must wait until template instantiation time.  */
5639     return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
5640                          method_params);
5641 #endif
5642
5643   return finish_message_expr (receiver, sel_name, method_params);
5644 }
5645
5646 /* Look up method SEL_NAME that would be suitable for receiver
5647    of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
5648    nonzero), and report on any duplicates.  */
5649
5650 static tree
5651 lookup_method_in_hash_lists (tree sel_name, int is_class)
5652 {
5653   hash method_prototype = NULL;
5654
5655   if (!is_class)
5656     method_prototype = hash_lookup (nst_method_hash_list,
5657                                     sel_name);
5658                                         
5659   if (!method_prototype)
5660     {
5661       method_prototype = hash_lookup (cls_method_hash_list,
5662                                       sel_name);
5663       is_class = 1;
5664     }
5665
5666   return check_duplicates (method_prototype, 1, is_class);
5667 }
5668
5669 /* The 'finish_message_expr' routine is called from within
5670    'build_message_expr' for non-template functions.  In the case of
5671    C++ template functions, it is called from 'build_expr_from_tree'
5672    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
5673
5674 tree
5675 finish_message_expr (tree receiver, tree sel_name, tree method_params)
5676 {
5677   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
5678   tree selector, retval, class_tree;
5679   int self, super, have_cast;
5680
5681   /* Extract the receiver of the message, as well as its type
5682      (where the latter may take the form of a cast or be inferred
5683      from the implementation context).  */
5684   rtype = receiver;
5685   while (TREE_CODE (rtype) == COMPOUND_EXPR
5686               || TREE_CODE (rtype) == MODIFY_EXPR
5687               || TREE_CODE (rtype) == NOP_EXPR
5688               || TREE_CODE (rtype) == COMPONENT_REF)
5689     rtype = TREE_OPERAND (rtype, 0);
5690   self = (rtype == self_decl);
5691   super = (rtype == UOBJC_SUPER_decl);
5692   rtype = TREE_TYPE (receiver);
5693   have_cast = (TREE_CODE (receiver) == NOP_EXPR
5694                || (TREE_CODE (receiver) == COMPOUND_EXPR
5695                    && !IS_SUPER (rtype)));
5696
5697   /* If the receiver is a class object, retrieve the corresponding
5698      @interface, if one exists. */
5699   class_tree = receiver_is_class_object (receiver, self, super);
5700
5701   /* Now determine the receiver type (if an explicit cast has not been
5702      provided).  */
5703   if (!have_cast)
5704     {
5705       if (class_tree)
5706         rtype = lookup_interface (class_tree);
5707       /* Handle `self' and `super'.  */
5708       else if (super)
5709         {
5710           if (!CLASS_SUPER_NAME (implementation_template))
5711             {
5712               error ("no super class declared in @interface for `%s'",
5713                      IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5714               return error_mark_node;
5715             }
5716           rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5717         }
5718       else if (self)
5719         rtype = lookup_interface (CLASS_NAME (implementation_template));
5720     }
5721
5722   /* If receiver is of type `id' or `Class' (or if the @interface for a
5723      class is not visible), we shall be satisfied with the existence of
5724      any instance or class method. */
5725   if (!rtype || IS_ID (rtype)
5726         || TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
5727     {
5728       if (!rtype)
5729         rtype = xref_tag (RECORD_TYPE, class_tree);
5730       else if (IS_ID (rtype))
5731         {
5732           rprotos = TYPE_PROTOCOL_LIST (rtype);
5733           rtype = NULL_TREE;
5734         }
5735       else
5736         class_tree = TYPE_NAME (rtype) = get_identifier ("Class");
5737
5738       if (rprotos)
5739         method_prototype
5740           = lookup_method_in_protocol_list (rprotos, sel_name,
5741                                             class_tree != NULL_TREE);
5742       if (!method_prototype && !rprotos)
5743         method_prototype
5744           = lookup_method_in_hash_lists (sel_name,
5745                                          class_tree != NULL_TREE);
5746     }
5747   else
5748     {
5749       tree orig_rtype = rtype, saved_rtype;
5750
5751       if (TREE_CODE (rtype) == POINTER_TYPE)
5752         rtype = TREE_TYPE (rtype);
5753       /* Traverse typedef aliases */
5754       while (TREE_CODE (rtype) == RECORD_TYPE && TYPE_NAME (rtype)
5755              && TREE_CODE (TYPE_NAME (rtype)) == TYPE_DECL
5756              && DECL_ORIGINAL_TYPE (TYPE_NAME (rtype)))
5757         rtype = DECL_ORIGINAL_TYPE (TYPE_NAME (rtype));
5758       saved_rtype = rtype;
5759       if (TYPED_OBJECT (rtype))
5760         {
5761           rprotos = TYPE_PROTOCOL_LIST (rtype);
5762           rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
5763         }
5764       /* If we could not find an @interface declaration, we must have
5765          only seen a @class declaration; so, we cannot say anything
5766          more intelligent about which methods the receiver will
5767          understand. */
5768       if (!rtype)
5769         rtype = saved_rtype;
5770       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
5771           || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
5772         {
5773           /* We have a valid ObjC class name.  Look up the method name
5774              in the published @interface for the class (and its
5775              superclasses). */
5776           method_prototype
5777             = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
5778
5779           /* If the method was not found in the @interface, it may still
5780              exist locally as part of the @implementation.  */
5781           if (!method_prototype && objc_implementation_context
5782              && CLASS_NAME (objc_implementation_context)
5783                 == OBJC_TYPE_NAME (rtype))                      
5784             method_prototype
5785               = lookup_method
5786                 ((class_tree
5787                   ? CLASS_CLS_METHODS (objc_implementation_context)
5788                   : CLASS_NST_METHODS (objc_implementation_context)),
5789                   sel_name);
5790
5791           /* If we haven't found a candidate method by now, try looking for
5792              it in the protocol list.  */
5793           if (!method_prototype && rprotos)
5794             method_prototype
5795               = lookup_method_in_protocol_list (rprotos, sel_name,
5796                                                 class_tree != NULL_TREE);
5797         }
5798       else
5799         {
5800           warning ("invalid receiver type `%s'",
5801                    gen_declaration (orig_rtype, errbuf));
5802           rtype = rprotos = NULL_TREE;
5803         }
5804     }   
5805
5806   if (!method_prototype)
5807     {
5808       static bool warn_missing_methods = false;
5809
5810       if (rtype)
5811         warning ("`%s' may not respond to `%c%s'",
5812                  IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
5813                  (class_tree ? '+' : '-'),
5814                  IDENTIFIER_POINTER (sel_name));
5815       if (rprotos)
5816         warning ("`%c%s' not implemented by protocol(s)",
5817                  (class_tree ? '+' : '-'),
5818                  IDENTIFIER_POINTER (sel_name));
5819       if (!warn_missing_methods)
5820         {
5821           warning ("(Messages without a matching method signature");
5822           warning ("will be assumed to return `id' and accept");
5823           warning ("`...' as arguments.)");
5824           warn_missing_methods = true;
5825         }
5826     }
5827
5828   /* Save the selector name for printing error messages.  */
5829   current_objc_message_selector = sel_name;
5830
5831   /* Build the parameters list for looking up the method.
5832      These are the object itself and the selector.  */
5833
5834   if (flag_typed_selectors)
5835     selector = build_typed_selector_reference (sel_name, method_prototype);
5836   else
5837     selector = build_selector_reference (sel_name);
5838
5839   retval = build_objc_method_call (super, method_prototype,
5840                                    receiver,
5841                                    selector, method_params);
5842
5843   current_objc_message_selector = 0;
5844
5845   return retval;
5846 }
5847 \f
5848 /* Build a tree expression to send OBJECT the operation SELECTOR,
5849    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5850    assuming the method has prototype METHOD_PROTOTYPE.
5851    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5852    Use METHOD_PARAMS as list of args to pass to the method.
5853    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
5854
5855 static tree
5856 build_objc_method_call (int super_flag, tree method_prototype,
5857                         tree lookup_object, tree selector,
5858                         tree method_params)
5859 {
5860   tree sender = (super_flag ? umsg_super_decl :
5861                  (!flag_next_runtime || flag_nil_receivers
5862                   ? umsg_decl
5863                   : umsg_nonnil_decl));
5864   tree rcv_p = (super_flag ? objc_super_type : objc_id_type);
5865
5866   /* If a prototype for the method to be called exists, then cast
5867      the sender's return type and arguments to match that of the method.
5868      Otherwise, leave sender as is.  */
5869   tree ret_type
5870     = (method_prototype
5871        ? groktypename (TREE_TYPE (method_prototype))
5872        : objc_id_type);
5873   tree sender_cast
5874     = build_pointer_type
5875       (build_function_type
5876        (ret_type,
5877         get_arg_type_list
5878         (method_prototype, METHOD_REF, super_flag)));
5879   tree method, t;
5880
5881   lookup_object = build_c_cast (rcv_p, lookup_object);
5882     
5883   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
5884   lookup_object = save_expr (lookup_object);
5885
5886   if (flag_next_runtime)
5887     {
5888       /* If we are returning a struct in memory, and the address
5889          of that memory location is passed as a hidden first
5890          argument, then change which messenger entry point this
5891          expr will call.  NB: Note that sender_cast remains
5892          unchanged (it already has a struct return type).  */
5893       if (!targetm.calls.struct_value_rtx (0, 0)
5894           && (TREE_CODE (ret_type) == RECORD_TYPE
5895               || TREE_CODE (ret_type) == UNION_TYPE)
5896           && targetm.calls.return_in_memory (ret_type, 0))
5897         sender = (super_flag ? umsg_super_stret_decl :
5898                 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
5899
5900       method_params = tree_cons (NULL_TREE, lookup_object,
5901                                  tree_cons (NULL_TREE, selector,
5902                                             method_params));
5903       method = build_fold_addr_expr (sender);
5904     }
5905   else
5906     {
5907       /* This is the portable (GNU) way.  */
5908       tree object;
5909
5910       /* First, call the lookup function to get a pointer to the method,
5911          then cast the pointer, then call it with the method arguments.  */
5912       
5913       object = (super_flag ? self_decl : lookup_object);
5914
5915       t = tree_cons (NULL_TREE, selector, NULL_TREE);
5916       t = tree_cons (NULL_TREE, lookup_object, t);
5917       method = build_function_call (sender, t);
5918
5919       /* Pass the object to the method.  */
5920       method_params = tree_cons (NULL_TREE, object,
5921                                  tree_cons (NULL_TREE, selector,
5922                                             method_params));
5923     }
5924
5925   /* ??? Selector is not at this point something we can use inside
5926      the compiler itself.  Set it to garbage for the nonce.  */
5927   t = build (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
5928   return build_function_call (t, method_params);
5929 }
5930 \f
5931 static void
5932 build_protocol_reference (tree p)
5933 {
5934   tree decl, ident, ptype;
5935
5936   /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5937
5938   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5939   ptype
5940     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5941                                                       objc_protocol_template),
5942                                      NULL_TREE));
5943
5944   if (identifier_global_value (ident))
5945     decl = identifier_global_value (ident); /* Set by pushdecl.  */
5946   else
5947     {
5948       decl = build_decl (VAR_DECL, ident, ptype);
5949       DECL_EXTERNAL (decl) = 1;
5950       TREE_PUBLIC (decl) = 0;
5951       TREE_USED (decl) = 1;
5952       DECL_ARTIFICIAL (decl) = 1;
5953
5954       make_decl_rtl (decl, 0);
5955       pushdecl_top_level (decl);
5956    }
5957
5958   PROTOCOL_FORWARD_DECL (p) = decl;
5959 }
5960
5961 /* This function is called by the parser when (and only when) a
5962    @protocol() expression is found, in order to compile it.  */
5963 tree
5964 build_protocol_expr (tree protoname)
5965 {
5966   tree expr;
5967   tree p = lookup_protocol (protoname);
5968
5969   if (!p)
5970     {
5971       error ("cannot find protocol declaration for `%s'",
5972              IDENTIFIER_POINTER (protoname));
5973       return error_mark_node;
5974     }
5975
5976   if (!PROTOCOL_FORWARD_DECL (p))
5977     build_protocol_reference (p);
5978
5979   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5980
5981   /* ??? Ideally we'd build the reference with objc_protocol_type directly,
5982      if we have it, rather than converting it here.  */
5983   expr = convert (objc_protocol_type, expr);
5984
5985   /* The @protocol() expression is being compiled into a pointer to a
5986      statically allocated instance of the Protocol class.  To become
5987      usable at runtime, the 'isa' pointer of the instance need to be
5988      fixed up at runtime by the runtime library, to point to the
5989      actual 'Protocol' class.  */
5990
5991   /* For the GNU runtime, put the static Protocol instance in the list
5992      of statically allocated instances, so that we make sure that its
5993      'isa' pointer is fixed up at runtime by the GNU runtime library
5994      to point to the Protocol class (at runtime, when loading the
5995      module, the GNU runtime library loops on the statically allocated
5996      instances (as found in the defs field in objc_symtab) and fixups
5997      all the 'isa' pointers of those objects).  */
5998   if (! flag_next_runtime)
5999     {
6000       /* This type is a struct containing the fields of a Protocol
6001         object.  (Cfr. objc_protocol_type instead is the type of a pointer
6002         to such a struct).  */
6003       tree protocol_struct_type = xref_tag
6004        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
6005       tree *chain;
6006
6007       /* Look for the list of Protocol statically allocated instances
6008         to fixup at runtime.  Create a new list to hold Protocol
6009         statically allocated instances, if the list is not found.  At
6010         present there is only another list, holding NSConstantString
6011         static instances to be fixed up at runtime.  */
6012       for (chain = &objc_static_instances;
6013            *chain && TREE_VALUE (*chain) != protocol_struct_type;
6014            chain = &TREE_CHAIN (*chain));
6015       if (!*chain)
6016         {
6017          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6018          add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6019                           class_names);
6020        }
6021
6022       /* Add this statically allocated instance to the Protocol list.  */
6023       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6024                                          PROTOCOL_FORWARD_DECL (p),
6025                                          TREE_PURPOSE (*chain));
6026     }
6027
6028
6029   return expr;
6030 }
6031
6032 /* This function is called by the parser when a @selector() expression
6033    is found, in order to compile it.  It is only called by the parser
6034    and only to compile a @selector().  */
6035 tree
6036 build_selector_expr (tree selnamelist)
6037 {
6038   tree selname;
6039
6040   /* Obtain the full selector name.  */
6041   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6042     /* A unary selector.  */
6043     selname = selnamelist;
6044   else if (TREE_CODE (selnamelist) == TREE_LIST)
6045     selname = build_keyword_selector (selnamelist);
6046   else
6047     abort ();
6048
6049   /* If we are required to check @selector() expressions as they
6050      are found, check that the selector has been declared.  */
6051   if (warn_undeclared_selector)
6052     {
6053       /* Look the selector up in the list of all known class and
6054          instance methods (up to this line) to check that the selector
6055          exists.  */
6056       hash hsh;
6057
6058       /* First try with instance methods.  */
6059       hsh = hash_lookup (nst_method_hash_list, selname);
6060
6061       /* If not found, try with class methods.  */
6062       if (!hsh)
6063         {
6064           hsh = hash_lookup (cls_method_hash_list, selname);
6065         }
6066
6067       /* If still not found, print out a warning.  */
6068       if (!hsh)
6069         {
6070           warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
6071         }
6072     }
6073
6074
6075   if (flag_typed_selectors)
6076     return build_typed_selector_reference (selname, 0);
6077   else
6078     return build_selector_reference (selname);
6079 }
6080
6081 tree
6082 build_encode_expr (tree type)
6083 {
6084   tree result;
6085   const char *string;
6086
6087   encode_type (type, obstack_object_size (&util_obstack),
6088                OBJC_ENCODE_INLINE_DEFS);
6089   obstack_1grow (&util_obstack, 0);    /* null terminate string */
6090   string = obstack_finish (&util_obstack);
6091
6092   /* Synthesize a string that represents the encoded struct/union.  */
6093   result = my_build_string (strlen (string) + 1, string);
6094   obstack_free (&util_obstack, util_firstobj);
6095   return result;
6096 }
6097
6098 tree
6099 build_ivar_reference (tree id)
6100 {
6101   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6102     {
6103       /* Historically, a class method that produced objects (factory
6104          method) would assign `self' to the instance that it
6105          allocated.  This would effectively turn the class method into
6106          an instance method.  Following this assignment, the instance
6107          variables could be accessed.  That practice, while safe,
6108          violates the simple rule that a class method should not refer
6109          to an instance variable.  It's better to catch the cases
6110          where this is done unknowingly than to support the above
6111          paradigm.  */
6112       warning ("instance variable `%s' accessed in class method",
6113                IDENTIFIER_POINTER (id));
6114       TREE_TYPE (self_decl) = objc_instance_type; /* cast */
6115     }
6116
6117   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
6118 }
6119 \f
6120 /* Compute a hash value for a given method SEL_NAME.  */
6121
6122 static size_t
6123 hash_func (tree sel_name)
6124 {
6125   const unsigned char *s
6126     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6127   size_t h = 0;
6128
6129   while (*s)
6130     h = h * 67 + *s++ - 113;
6131   return h;
6132 }
6133
6134 static void
6135 hash_init (void)
6136 {
6137   nst_method_hash_list
6138     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6139   cls_method_hash_list
6140     = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6141 }
6142
6143 /* WARNING!!!!  hash_enter is called with a method, and will peek
6144    inside to find its selector!  But hash_lookup is given a selector
6145    directly, and looks for the selector that's inside the found
6146    entry's key (method) for comparison.  */
6147
6148 static void
6149 hash_enter (hash *hashlist, tree method)
6150 {
6151   hash obj;
6152   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6153
6154   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6155   obj->list = 0;
6156   obj->next = hashlist[slot];
6157   obj->key = method;
6158
6159   hashlist[slot] = obj;         /* append to front */
6160 }
6161
6162 static hash
6163 hash_lookup (hash *hashlist, tree sel_name)
6164 {
6165   hash target;
6166
6167   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6168
6169   while (target)
6170     {
6171       if (sel_name == METHOD_SEL_NAME (target->key))
6172         return target;
6173
6174       target = target->next;
6175     }
6176   return 0;
6177 }
6178
6179 static void
6180 hash_add_attr (hash entry, tree value)
6181 {
6182   attr obj;
6183
6184   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6185   obj->next = entry->list;
6186   obj->value = value;
6187
6188   entry->list = obj;            /* append to front */
6189 }
6190 \f
6191 static tree
6192 lookup_method (tree mchain, tree method)
6193 {
6194   tree key;
6195
6196   if (TREE_CODE (method) == IDENTIFIER_NODE)
6197     key = method;
6198   else
6199     key = METHOD_SEL_NAME (method);
6200
6201   while (mchain)
6202     {
6203       if (METHOD_SEL_NAME (mchain) == key)
6204         return mchain;
6205
6206       mchain = TREE_CHAIN (mchain);
6207     }
6208   return NULL_TREE;
6209 }
6210
6211 static tree
6212 lookup_method_static (tree interface, tree ident, int is_class)
6213 {
6214   tree meth = NULL_TREE, root_inter = NULL_TREE;
6215   tree inter = interface;
6216
6217   while (inter)
6218     {
6219       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6220       tree category = inter;
6221
6222       /* First, look up the method in the class itself.  */
6223       if ((meth = lookup_method (chain, ident)))
6224         return meth;
6225
6226       /* Failing that, look for the method in each category of the class.  */
6227       while ((category = CLASS_CATEGORY_LIST (category)))
6228         {
6229           chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6230
6231           /* Check directly in each category.  */
6232           if ((meth = lookup_method (chain, ident)))
6233             return meth;
6234
6235           /* Failing that, check in each category's protocols.  */
6236           if (CLASS_PROTOCOL_LIST (category))
6237             {
6238               if ((meth = (lookup_method_in_protocol_list
6239                            (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6240                 return meth;
6241             }
6242         }
6243
6244       /* If not found in categories, check in protocols of the main class.  */
6245       if (CLASS_PROTOCOL_LIST (inter))
6246         {
6247           if ((meth = (lookup_method_in_protocol_list
6248                        (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6249             return meth;
6250         }
6251
6252       /* Failing that, climb up the inheritance hierarchy.  */
6253       root_inter = inter;
6254       inter = lookup_interface (CLASS_SUPER_NAME (inter));
6255     }
6256   while (inter);
6257
6258   /* If no class (factory) method was found, check if an _instance_
6259      method of the same name exists in the root class.  This is what
6260      the Objective-C runtime will do.  If an instance method was not
6261      found, return 0.  */
6262   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6263 }
6264
6265 /* Add the method to the hash list if it doesn't contain an identical
6266    method already. */
6267 static void
6268 add_method_to_hash_list (hash *hash_list, tree method)
6269 {
6270   hash hsh;
6271
6272   if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6273     {
6274       /* Install on a global chain.  */
6275       hash_enter (hash_list, method);
6276     }
6277   else
6278     {
6279       /* Check types against those; if different, add to a list.  */
6280       attr loop;
6281       int already_there = comp_proto_with_proto (method, hsh->key);
6282       for (loop = hsh->list; !already_there && loop; loop = loop->next)
6283         already_there |= comp_proto_with_proto (method, loop->value);
6284       if (!already_there)
6285         hash_add_attr (hsh, method);
6286     }
6287 }
6288
6289 tree
6290 objc_add_method (tree class, tree method, int is_class)
6291 {
6292   tree mth;
6293
6294   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
6295     {
6296       /* put method on list in reverse order */
6297       if (is_class)
6298         {
6299           TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6300           CLASS_CLS_METHODS (class) = method;
6301         }
6302       else
6303         {
6304           TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6305           CLASS_NST_METHODS (class) = method;
6306         }
6307     }
6308   else
6309     {
6310       /* When processing an @interface for a class or category, give hard
6311          errors on methods with identical selectors but differing argument
6312          and/or return types. We do not do this for @implementations, because
6313          C/C++ will do it for us (i.e., there will be duplicate function
6314          definition errors).  */
6315       if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6316            || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6317           && !comp_proto_with_proto (method, mth))
6318         error ("duplicate declaration of method `%c%s'",
6319                 is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6320     }
6321
6322   if (is_class)
6323     add_method_to_hash_list (cls_method_hash_list, method);
6324   else
6325     {
6326       add_method_to_hash_list (nst_method_hash_list, method);
6327
6328       /* Instance methods in root classes (and categories thereof)
6329          may acts as class methods as a last resort. */
6330       if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6331           || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6332         class = lookup_interface (CLASS_NAME (class));
6333
6334       if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
6335           && !CLASS_SUPER_NAME (class))
6336         add_method_to_hash_list (cls_method_hash_list, method);
6337     }
6338
6339   return method;
6340 }
6341
6342 static tree
6343 add_class (tree class)
6344 {
6345   /* Put interfaces on list in reverse order.  */
6346   TREE_CHAIN (class) = interface_chain;
6347   interface_chain = class;
6348   return interface_chain;
6349 }
6350
6351 static void
6352 add_category (tree class, tree category)
6353 {
6354   /* Put categories on list in reverse order.  */
6355   tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
6356
6357   if (cat)
6358     {
6359       warning ("duplicate interface declaration for category `%s(%s)'",
6360                IDENTIFIER_POINTER (CLASS_NAME (class)),
6361                IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
6362     }
6363   else
6364     {
6365       CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
6366       CLASS_CATEGORY_LIST (class) = category;
6367     }
6368 }
6369
6370 /* Called after parsing each instance variable declaration. Necessary to
6371    preserve typedefs and implement public/private...
6372
6373    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
6374
6375 tree
6376 add_instance_variable (tree class, int public, tree declarator,
6377                        tree declspecs, tree width)
6378 {
6379   tree field_decl = grokfield (declarator, declspecs, width);
6380   tree field_type = TREE_TYPE (field_decl);
6381   const char *ivar_name = DECL_NAME (field_decl)
6382                           ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
6383                           : "<unnamed>";
6384   tree raw_decl;
6385
6386 #ifdef OBJCPLUS
6387   if (TREE_CODE (field_type) == REFERENCE_TYPE)
6388     {
6389       error ("illegal reference type specified for instance variable `%s'",
6390              ivar_name);
6391       /* Return class as is without adding this ivar.  */
6392       return class;
6393     }
6394 #endif
6395
6396   if (field_type == error_mark_node || !TYPE_SIZE (field_type)
6397       || TYPE_SIZE (field_type) == error_mark_node
6398       /* 'type[0]' is allowed, but 'type[]' is not! */
6399 #ifdef OBJCPLUS
6400       || (TYPE_SIZE (field_type) == bitsize_zero_node
6401           && !TREE_OPERAND (declarator, 1))
6402 #endif
6403       )
6404     {
6405       error ("instance variable `%s' has unknown size", ivar_name);
6406       /* Return class as is without adding this ivar.  */
6407       return class;
6408     }
6409
6410 #ifdef OBJCPLUS
6411   /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
6412      cannot be ivars; ditto for classes with vtables. */
6413   if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
6414       || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
6415     {
6416       const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
6417       if(TYPE_POLYMORPHIC_P (field_type)) {
6418         /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
6419         error ("type `%s' has virtual member functions", type_name);
6420         error ("illegal aggregate type `%s' specified for instance variable `%s'",
6421                type_name, ivar_name);
6422         /* Return class as is without adding this ivar.  */
6423         return class;
6424       }
6425       /* user-defined constructors and destructors are not known to Obj-C and
6426          hence will not be called.  This may or may not be a problem. */
6427       if (TYPE_NEEDS_CONSTRUCTING (field_type))
6428         warning ("type `%s' has a user-defined constructor", type_name);
6429       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
6430         warning ("type `%s' has a user-defined destructor", type_name);
6431       warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
6432     }
6433 #endif
6434
6435   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
6436   switch (public)
6437     {
6438     case 0:
6439       TREE_PUBLIC (field_decl) = 0;
6440       TREE_PRIVATE (field_decl) = 0;
6441       TREE_PROTECTED (field_decl) = 1;
6442       break;
6443
6444     case 1:
6445       TREE_PUBLIC (field_decl) = 1;
6446       TREE_PRIVATE (field_decl) = 0;
6447       TREE_PROTECTED (field_decl) = 0;
6448       break;
6449
6450     case 2:
6451       TREE_PUBLIC (field_decl) = 0;
6452       TREE_PRIVATE (field_decl) = 1;
6453       TREE_PROTECTED (field_decl) = 0;
6454       break;
6455
6456     }
6457
6458   raw_decl = build_tree_list (declspecs, build_tree_list (declarator, width));
6459   CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), raw_decl);
6460   CLASS_IVARS (class) = chainon (CLASS_IVARS (class), field_decl);
6461   return class;
6462 }
6463 \f
6464 tree
6465 is_ivar (tree decl_chain, tree ident)
6466 {
6467   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
6468     if (DECL_NAME (decl_chain) == ident)
6469       return decl_chain;
6470   return NULL_TREE;
6471 }
6472
6473 /* True if the ivar is private and we are not in its implementation.  */
6474
6475 int
6476 is_private (tree decl)
6477 {
6478   return (TREE_PRIVATE (decl)
6479           && ! is_ivar (CLASS_IVARS (implementation_template),
6480                         DECL_NAME (decl)));
6481 }
6482
6483 /* We have an instance variable reference;, check to see if it is public.  */
6484
6485 int
6486 objc_is_public (tree expr, tree identifier)
6487 {
6488   tree basetype = TREE_TYPE (expr);
6489   enum tree_code code = TREE_CODE (basetype);
6490   tree decl;
6491
6492   if (code == RECORD_TYPE)
6493     {
6494       if (TREE_STATIC_TEMPLATE (basetype))
6495         {
6496           if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6497             {
6498               error ("cannot find interface declaration for `%s'",
6499                      IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6500               return 0;
6501             }
6502
6503           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6504             {
6505               if (TREE_PUBLIC (decl))
6506                 return 1;
6507
6508               /* Important difference between the Stepstone translator:
6509                  all instance variables should be public within the context
6510                  of the implementation.  */
6511               if (objc_implementation_context
6512                   && (((TREE_CODE (objc_implementation_context)
6513                         == CLASS_IMPLEMENTATION_TYPE)
6514                        || (TREE_CODE (objc_implementation_context)
6515                            == CATEGORY_IMPLEMENTATION_TYPE))
6516                       && (CLASS_NAME (objc_implementation_context)
6517                           == OBJC_TYPE_NAME (basetype))))
6518                 {
6519                   int private = is_private (decl);
6520
6521                   if (private)
6522                     error ("instance variable `%s' is declared private",
6523                            IDENTIFIER_POINTER (DECL_NAME (decl)));
6524                   return !private;
6525                 }
6526
6527               /* The 2.95.2 compiler sometimes allowed C functions to access
6528                  non-@public ivars.  We will let this slide for now...  */
6529               if (!objc_method_context)
6530               {
6531                 warning ("instance variable `%s' is %s; "
6532                          "this will be a hard error in the future",
6533                          IDENTIFIER_POINTER (identifier),
6534                          TREE_PRIVATE (decl) ? "@private" : "@protected");
6535                 return 1;
6536               }
6537                 
6538               error ("instance variable `%s' is declared %s",
6539                      IDENTIFIER_POINTER (identifier),
6540                      TREE_PRIVATE (decl) ? "private" : "protected");
6541               return 0;
6542             }
6543         }
6544
6545       else if (objc_implementation_context && (basetype == objc_object_reference))
6546         {
6547           TREE_TYPE (expr) = uprivate_record;
6548           warning ("static access to object of type `id'");
6549         }
6550     }
6551
6552   return 1;
6553 }
6554 \f
6555 /* Make sure all entries in CHAIN are also in LIST.  */
6556
6557 static int
6558 check_methods (tree chain, tree list, int mtype)
6559 {
6560   int first = 1;
6561
6562   while (chain)
6563     {
6564       if (!lookup_method (list, chain))
6565         {
6566           if (first)
6567             {
6568               if (TREE_CODE (objc_implementation_context)
6569                   == CLASS_IMPLEMENTATION_TYPE)
6570                 warning ("incomplete implementation of class `%s'",
6571                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6572               else if (TREE_CODE (objc_implementation_context)
6573                        == CATEGORY_IMPLEMENTATION_TYPE)
6574                 warning ("incomplete implementation of category `%s'",
6575                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6576               first = 0;
6577             }
6578
6579           warning ("method definition for `%c%s' not found",
6580                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6581         }
6582
6583       chain = TREE_CHAIN (chain);
6584     }
6585
6586     return first;
6587 }
6588
6589 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
6590
6591 static int
6592 conforms_to_protocol (tree class, tree protocol)
6593 {
6594    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6595      {
6596        tree p = CLASS_PROTOCOL_LIST (class);
6597        while (p && TREE_VALUE (p) != protocol)
6598          p = TREE_CHAIN (p);
6599
6600        if (!p)
6601          {
6602            tree super = (CLASS_SUPER_NAME (class)
6603                          ? lookup_interface (CLASS_SUPER_NAME (class))
6604                          : NULL_TREE);
6605            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6606            if (!tmp)
6607              return 0;
6608          }
6609      }
6610
6611    return 1;
6612 }
6613
6614 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6615    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
6616
6617 static int
6618 check_methods_accessible (tree chain, tree context, int mtype)
6619 {
6620   int first = 1;
6621   tree list;
6622   tree base_context = context;
6623
6624   while (chain)
6625     {
6626       context = base_context;
6627       while (context)
6628         {
6629           if (mtype == '+')
6630             list = CLASS_CLS_METHODS (context);
6631           else
6632             list = CLASS_NST_METHODS (context);
6633
6634           if (lookup_method (list, chain))
6635               break;
6636
6637           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6638                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6639             context = (CLASS_SUPER_NAME (context)
6640                        ? lookup_interface (CLASS_SUPER_NAME (context))
6641                        : NULL_TREE);
6642
6643           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6644                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6645             context = (CLASS_NAME (context)
6646                        ? lookup_interface (CLASS_NAME (context))
6647                        : NULL_TREE);
6648           else
6649             abort ();
6650         }
6651
6652       if (context == NULL_TREE)
6653         {
6654           if (first)
6655             {
6656               if (TREE_CODE (objc_implementation_context)
6657                   == CLASS_IMPLEMENTATION_TYPE)
6658                 warning ("incomplete implementation of class `%s'",
6659                          IDENTIFIER_POINTER
6660                            (CLASS_NAME (objc_implementation_context)));
6661               else if (TREE_CODE (objc_implementation_context)
6662                        == CATEGORY_IMPLEMENTATION_TYPE)
6663                 warning ("incomplete implementation of category `%s'",
6664                          IDENTIFIER_POINTER
6665                            (CLASS_SUPER_NAME (objc_implementation_context)));
6666               first = 0;
6667             }
6668           warning ("method definition for `%c%s' not found",
6669                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6670         }
6671
6672       chain = TREE_CHAIN (chain); /* next method...  */
6673     }
6674   return first;
6675 }
6676
6677 /* Check whether the current interface (accessible via
6678    'objc_implementation_context') actually implements protocol P, along
6679    with any protocols that P inherits.  */
6680
6681 static void
6682 check_protocol (tree p, const char *type, const char *name)
6683 {
6684   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6685     {
6686       int f1, f2;
6687
6688       /* Ensure that all protocols have bodies!  */
6689       if (warn_protocol)
6690         {
6691           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6692                               CLASS_CLS_METHODS (objc_implementation_context),
6693                               '+');
6694           f2 = check_methods (PROTOCOL_NST_METHODS (p),
6695                               CLASS_NST_METHODS (objc_implementation_context),
6696                               '-');
6697         }
6698       else
6699         {
6700           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6701                                          objc_implementation_context,
6702                                          '+');
6703           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6704                                          objc_implementation_context,
6705                                          '-');
6706         }
6707
6708       if (!f1 || !f2)
6709         warning ("%s `%s' does not fully implement the `%s' protocol",
6710                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6711     }
6712
6713   /* Check protocols recursively.  */
6714   if (PROTOCOL_LIST (p))
6715     {
6716       tree subs = PROTOCOL_LIST (p);
6717       tree super_class =
6718         lookup_interface (CLASS_SUPER_NAME (implementation_template));
6719
6720       while (subs)
6721         {
6722           tree sub = TREE_VALUE (subs);
6723
6724           /* If the superclass does not conform to the protocols
6725              inherited by P, then we must!  */
6726           if (!super_class || !conforms_to_protocol (super_class, sub))
6727             check_protocol (sub, type, name);
6728           subs = TREE_CHAIN (subs);
6729         }
6730     }
6731 }
6732
6733 /* Check whether the current interface (accessible via
6734    'objc_implementation_context') actually implements the protocols listed
6735    in PROTO_LIST.  */
6736
6737 static void
6738 check_protocols (tree proto_list, const char *type, const char *name)
6739 {
6740   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6741     {
6742       tree p = TREE_VALUE (proto_list);
6743
6744       check_protocol (p, type, name);
6745     }
6746 }
6747 \f
6748 /* Make sure that the class CLASS_NAME is defined
6749    CODE says which kind of thing CLASS_NAME ought to be.
6750    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6751    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
6752
6753 tree
6754 start_class (enum tree_code code, tree class_name, tree super_name,
6755              tree protocol_list)
6756 {
6757   tree class, decl;
6758
6759 #ifdef OBJCPLUS
6760   if (current_namespace != global_namespace) {
6761     error ("Objective-C declarations may only appear in global scope");
6762   }
6763 #endif /* OBJCPLUS */
6764
6765   if (objc_implementation_context)
6766     {
6767       warning ("`@end' missing in implementation context");
6768       finish_class (objc_implementation_context);
6769       objc_ivar_chain = NULL_TREE;
6770       objc_implementation_context = NULL_TREE;
6771     }
6772
6773   class = make_node (code);
6774   TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
6775
6776   CLASS_NAME (class) = class_name;
6777   CLASS_SUPER_NAME (class) = super_name;
6778   CLASS_CLS_METHODS (class) = NULL_TREE;
6779
6780   if (! is_class_name (class_name)
6781       && (decl = lookup_name (class_name)))
6782     {
6783       error ("`%s' redeclared as different kind of symbol",
6784              IDENTIFIER_POINTER (class_name));
6785       error ("%Jprevious declaration of '%D'",
6786              decl, decl);
6787     }
6788
6789   if (code == CLASS_IMPLEMENTATION_TYPE)
6790     {
6791       {
6792         tree chain;
6793
6794         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6795            if (TREE_VALUE (chain) == class_name)
6796              {
6797                error ("reimplementation of class `%s'",
6798                       IDENTIFIER_POINTER (class_name));
6799                return error_mark_node;
6800              }
6801         implemented_classes = tree_cons (NULL_TREE, class_name,
6802                                          implemented_classes);
6803       }
6804
6805       /* Reset for multiple classes per file.  */
6806       method_slot = 0;
6807
6808       objc_implementation_context = class;
6809
6810       /* Lookup the interface for this implementation.  */
6811
6812       if (!(implementation_template = lookup_interface (class_name)))
6813         {
6814           warning ("cannot find interface declaration for `%s'",
6815                    IDENTIFIER_POINTER (class_name));
6816           add_class (implementation_template = objc_implementation_context);
6817         }
6818
6819       /* If a super class has been specified in the implementation,
6820          insure it conforms to the one specified in the interface.  */
6821
6822       if (super_name
6823           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6824         {
6825           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6826           const char *const name =
6827             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6828           error ("conflicting super class name `%s'",
6829                  IDENTIFIER_POINTER (super_name));
6830           error ("previous declaration of `%s'", name);
6831         }
6832
6833       else if (! super_name)
6834         {
6835           CLASS_SUPER_NAME (objc_implementation_context)
6836             = CLASS_SUPER_NAME (implementation_template);
6837         }
6838     }
6839
6840   else if (code == CLASS_INTERFACE_TYPE)
6841     {
6842       if (lookup_interface (class_name))
6843 #ifdef OBJCPLUS
6844         error ("duplicate interface declaration for class `%s'",
6845 #else
6846         warning ("duplicate interface declaration for class `%s'",
6847 #endif  
6848         IDENTIFIER_POINTER (class_name));
6849       else
6850         add_class (class);
6851
6852       if (protocol_list)
6853         CLASS_PROTOCOL_LIST (class)
6854           = lookup_and_install_protocols (protocol_list);
6855     }
6856
6857   else if (code == CATEGORY_INTERFACE_TYPE)
6858     {
6859       tree class_category_is_assoc_with;
6860
6861       /* For a category, class_name is really the name of the class that
6862          the following set of methods will be associated with. We must
6863          find the interface so that can derive the objects template.  */
6864
6865       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6866         {
6867           error ("cannot find interface declaration for `%s'",
6868                  IDENTIFIER_POINTER (class_name));
6869           exit (FATAL_EXIT_CODE);
6870         }
6871       else
6872         add_category (class_category_is_assoc_with, class);
6873
6874       if (protocol_list)
6875         CLASS_PROTOCOL_LIST (class)
6876           = lookup_and_install_protocols (protocol_list);
6877     }
6878
6879   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6880     {
6881       /* Reset for multiple classes per file.  */
6882       method_slot = 0;
6883
6884       objc_implementation_context = class;
6885
6886       /* For a category, class_name is really the name of the class that
6887          the following set of methods will be associated with.  We must
6888          find the interface so that can derive the objects template.  */
6889
6890       if (!(implementation_template = lookup_interface (class_name)))
6891         {
6892           error ("cannot find interface declaration for `%s'",
6893                  IDENTIFIER_POINTER (class_name));
6894           exit (FATAL_EXIT_CODE);
6895         }
6896     }
6897   return class;
6898 }
6899
6900 tree
6901 continue_class (tree class)
6902 {
6903   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6904       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6905     {
6906       struct imp_entry *imp_entry;
6907       tree ivar_context;
6908
6909       /* Check consistency of the instance variables.  */
6910
6911       if (CLASS_IVARS (class))
6912         check_ivars (implementation_template, class);
6913
6914       /* code generation */
6915
6916       ivar_context = build_private_template (implementation_template);
6917
6918       if (!objc_class_template)
6919         build_class_template ();
6920
6921       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6922
6923       imp_entry->next = imp_list;
6924       imp_entry->imp_context = class;
6925       imp_entry->imp_template = implementation_template;
6926
6927       synth_forward_declarations ();
6928       imp_entry->class_decl = UOBJC_CLASS_decl;
6929       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6930
6931       /* Append to front and increment count.  */
6932       imp_list = imp_entry;
6933       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6934         imp_count++;
6935       else
6936         cat_count++;
6937
6938       return ivar_context;
6939     }
6940
6941   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6942     {
6943       if (!CLASS_STATIC_TEMPLATE (class))
6944         {
6945           tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6946           finish_struct (record, get_class_ivars (class, 0), NULL_TREE);
6947           CLASS_STATIC_TEMPLATE (class) = record;
6948
6949           /* Mark this record as a class template for static typing.  */
6950           TREE_STATIC_TEMPLATE (record) = 1;
6951         }
6952
6953       return NULL_TREE;
6954     }
6955
6956   else
6957     return error_mark_node;
6958 }
6959
6960 /* This is called once we see the "@end" in an interface/implementation.  */
6961
6962 void
6963 finish_class (tree class)
6964 {
6965   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6966     {
6967       /* All code generation is done in finish_objc.  */
6968
6969       if (implementation_template != objc_implementation_context)
6970         {
6971           /* Ensure that all method listed in the interface contain bodies.  */
6972           check_methods (CLASS_CLS_METHODS (implementation_template),
6973                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6974           check_methods (CLASS_NST_METHODS (implementation_template),
6975                          CLASS_NST_METHODS (objc_implementation_context), '-');
6976
6977           if (CLASS_PROTOCOL_LIST (implementation_template))
6978             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6979                              "class",
6980                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6981         }
6982     }
6983
6984   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6985     {
6986       tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6987
6988       if (category)
6989         {
6990           /* Ensure all method listed in the interface contain bodies.  */
6991           check_methods (CLASS_CLS_METHODS (category),
6992                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6993           check_methods (CLASS_NST_METHODS (category),
6994                          CLASS_NST_METHODS (objc_implementation_context), '-');
6995
6996           if (CLASS_PROTOCOL_LIST (category))
6997             check_protocols (CLASS_PROTOCOL_LIST (category),
6998                              "category",
6999                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7000         }
7001     }
7002
7003   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
7004     {
7005       tree decl_specs;
7006       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
7007       char *string = (char *) alloca (strlen (class_name) + 3);
7008
7009       /* extern struct objc_object *_<my_name>; */
7010
7011       sprintf (string, "_%s", class_name);
7012
7013       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
7014       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
7015       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
7016                    decl_specs);
7017     }
7018 }
7019
7020 static tree
7021 add_protocol (tree protocol)
7022 {
7023   /* Put protocol on list in reverse order.  */
7024   TREE_CHAIN (protocol) = protocol_chain;
7025   protocol_chain = protocol;
7026   return protocol_chain;
7027 }
7028
7029 static tree
7030 lookup_protocol (tree ident)
7031 {
7032   tree chain;
7033
7034   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7035     if (ident == PROTOCOL_NAME (chain))
7036       return chain;
7037
7038   return NULL_TREE;
7039 }
7040
7041 /* This function forward declares the protocols named by NAMES.  If
7042    they are already declared or defined, the function has no effect.  */
7043
7044 void
7045 objc_declare_protocols (tree names)
7046 {
7047   tree list;
7048
7049 #ifdef OBJCPLUS
7050   if (current_namespace != global_namespace) {
7051     error ("Objective-C declarations may only appear in global scope");
7052   }
7053 #endif /* OBJCPLUS */
7054
7055   for (list = names; list; list = TREE_CHAIN (list))
7056     {
7057       tree name = TREE_VALUE (list);
7058
7059       if (lookup_protocol (name) == NULL_TREE)
7060         {
7061           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7062
7063           TYPE_LANG_SLOT_1 (protocol)
7064             = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7065           PROTOCOL_NAME (protocol) = name;
7066           PROTOCOL_LIST (protocol) = NULL_TREE;
7067           add_protocol (protocol);
7068           PROTOCOL_DEFINED (protocol) = 0;
7069           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7070         }
7071     }
7072 }
7073
7074 tree
7075 start_protocol (enum tree_code code, tree name, tree list)
7076 {
7077   tree protocol;
7078
7079 #ifdef OBJCPLUS
7080   if (current_namespace != global_namespace) {
7081     error ("Objective-C declarations may only appear in global scope");
7082   }
7083 #endif /* OBJCPLUS */
7084
7085   /* This is as good a place as any.  Need to invoke
7086      push_tag_toplevel.  */
7087   if (!objc_protocol_template)
7088     objc_protocol_template = build_protocol_template ();
7089
7090   protocol = lookup_protocol (name);
7091
7092   if (!protocol)
7093     {
7094       protocol = make_node (code);
7095       TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7096
7097       PROTOCOL_NAME (protocol) = name;
7098       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7099       add_protocol (protocol);
7100       PROTOCOL_DEFINED (protocol) = 1;
7101       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7102
7103       check_protocol_recursively (protocol, list);
7104     }
7105   else if (! PROTOCOL_DEFINED (protocol))
7106     {
7107       PROTOCOL_DEFINED (protocol) = 1;
7108       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7109
7110       check_protocol_recursively (protocol, list);
7111     }
7112   else
7113     {
7114       warning ("duplicate declaration for protocol `%s'",
7115                IDENTIFIER_POINTER (name));
7116     }
7117   return protocol;
7118 }
7119
7120 void
7121 finish_protocol (tree protocol ATTRIBUTE_UNUSED)
7122 {
7123 }
7124
7125 \f
7126 /* "Encode" a data type into a string, which grows in util_obstack.
7127    ??? What is the FORMAT?  Someone please document this!  */
7128
7129 static void
7130 encode_type_qualifiers (tree declspecs)
7131 {
7132   tree spec;
7133
7134   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7135     {
7136       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
7137         obstack_1grow (&util_obstack, 'r');
7138       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7139         obstack_1grow (&util_obstack, 'n');
7140       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7141         obstack_1grow (&util_obstack, 'N');
7142       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7143         obstack_1grow (&util_obstack, 'o');
7144       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7145         obstack_1grow (&util_obstack, 'O');
7146       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7147         obstack_1grow (&util_obstack, 'R');
7148       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7149         obstack_1grow (&util_obstack, 'V');
7150     }
7151 }
7152
7153 /* Encode a pointer type.  */
7154
7155 static void
7156 encode_pointer (tree type, int curtype, int format)
7157 {
7158   tree pointer_to = TREE_TYPE (type);
7159
7160   if (TREE_CODE (pointer_to) == RECORD_TYPE)
7161     {
7162       if (OBJC_TYPE_NAME (pointer_to)
7163           && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7164         {
7165           const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7166
7167           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7168             {
7169               obstack_1grow (&util_obstack, '@');
7170               return;
7171             }
7172           else if (TREE_STATIC_TEMPLATE (pointer_to))
7173             {
7174               if (generating_instance_variables)
7175                 {
7176                   obstack_1grow (&util_obstack, '@');
7177                   obstack_1grow (&util_obstack, '"');
7178                   obstack_grow (&util_obstack, name, strlen (name));
7179                   obstack_1grow (&util_obstack, '"');
7180                   return;
7181                 }
7182               else
7183                 {
7184                   obstack_1grow (&util_obstack, '@');
7185                   return;
7186                 }
7187             }
7188           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7189             {
7190               obstack_1grow (&util_obstack, '#');
7191               return;
7192             }
7193           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7194             {
7195               obstack_1grow (&util_obstack, ':');
7196               return;
7197             }
7198         }
7199     }
7200   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7201            && TYPE_MODE (pointer_to) == QImode)
7202     {
7203       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7204                   ? OBJC_TYPE_NAME (pointer_to)
7205                   : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7206
7207       if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7208         {
7209           obstack_1grow (&util_obstack, '*');
7210           return;
7211         }
7212     }
7213
7214   /* We have a type that does not get special treatment.  */
7215
7216   /* NeXT extension */
7217   obstack_1grow (&util_obstack, '^');
7218   encode_type (pointer_to, curtype, format);
7219 }
7220
7221 static void
7222 encode_array (tree type, int curtype, int format)
7223 {
7224   tree an_int_cst = TYPE_SIZE (type);
7225   tree array_of = TREE_TYPE (type);
7226   char buffer[40];
7227
7228   /* An incomplete array is treated like a pointer.  */
7229   if (an_int_cst == NULL)
7230     {
7231       encode_pointer (type, curtype, format);
7232       return;
7233     }
7234
7235   sprintf (buffer, "[%ld",
7236            (long) (TREE_INT_CST_LOW (an_int_cst)
7237                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7238
7239   obstack_grow (&util_obstack, buffer, strlen (buffer));
7240   encode_type (array_of, curtype, format);
7241   obstack_1grow (&util_obstack, ']');
7242   return;
7243 }
7244 \f
7245 static void
7246 encode_aggregate_within (tree type, int curtype, int format, int left,
7247                          int right)
7248 {
7249   tree name;
7250   /* NB: aggregates that are pointed to have slightly different encoding
7251      rules in that you never encode the names of instance variables.  */
7252   int pointed_to
7253    = (obstack_object_size (&util_obstack) > 0
7254       && *(obstack_next_free (&util_obstack) - 1) == '^');
7255   int inline_contents
7256    = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7257       && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7258
7259   /* Traverse struct aliases; it is important to get the
7260      original struct and its tag name (if any).  */
7261   type = TYPE_MAIN_VARIANT (type);
7262   name = OBJC_TYPE_NAME (type);
7263   /* Open parenth/bracket.  */                          
7264   obstack_1grow (&util_obstack, left);
7265
7266   /* Encode the struct/union tag name, or '?' if a tag was
7267      not provided.  Typedef aliases do not qualify.  */
7268   if (name && TREE_CODE (name) == IDENTIFIER_NODE
7269 #ifdef OBJCPLUS
7270       /* Did this struct have a tag?  */
7271       && !TYPE_WAS_ANONYMOUS (type)
7272 #endif
7273       )
7274     obstack_grow (&util_obstack,
7275                   IDENTIFIER_POINTER (name),
7276                   strlen (IDENTIFIER_POINTER (name)));
7277   else
7278     obstack_1grow (&util_obstack, '?');
7279
7280   /* Encode the types (and possibly names) of the inner fields,
7281      if required.  */
7282   if (inline_contents)
7283     {
7284       tree fields = TYPE_FIELDS (type);
7285
7286       obstack_1grow (&util_obstack, '=');
7287       for (; fields; fields = TREE_CHAIN (fields))
7288         {
7289 #ifdef OBJCPLUS
7290           /* C++ static members, and things that are not fields at all,
7291              should not appear in the encoding.  */
7292           if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7293             continue;
7294 #endif
7295           if (generating_instance_variables && !pointed_to)
7296             {
7297               tree fname = DECL_NAME (fields);
7298
7299               obstack_1grow (&util_obstack, '"');
7300               if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7301                 obstack_grow (&util_obstack,
7302                               IDENTIFIER_POINTER (fname),
7303                               strlen (IDENTIFIER_POINTER (fname)));
7304               obstack_1grow (&util_obstack, '"');
7305             }
7306           encode_field_decl (fields, curtype, format);
7307         }
7308     }
7309   /* Close parenth/bracket.  */                         
7310   obstack_1grow (&util_obstack, right);
7311 }
7312
7313 static void
7314 encode_aggregate (tree type, int curtype, int format)
7315 {
7316   enum tree_code code = TREE_CODE (type);
7317
7318   switch (code)
7319     {
7320     case RECORD_TYPE:
7321       {
7322         encode_aggregate_within (type, curtype, format, '{', '}');
7323         break;
7324       }
7325     case UNION_TYPE:
7326       {
7327         encode_aggregate_within (type, curtype, format, '(', ')');
7328         break;
7329       }
7330
7331     case ENUMERAL_TYPE:
7332       obstack_1grow (&util_obstack, 'i');
7333       break;
7334
7335     default:
7336       break;
7337     }
7338 }
7339
7340 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7341    field type.  */
7342
7343 static void
7344 encode_next_bitfield (int width)
7345 {
7346   char buffer[40];
7347   sprintf (buffer, "b%d", width);
7348   obstack_grow (&util_obstack, buffer, strlen (buffer));
7349 }
7350 \f
7351 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
7352 static void
7353 encode_type (tree type, int curtype, int format)
7354 {
7355   enum tree_code code = TREE_CODE (type);
7356   char c;
7357
7358   if (code == INTEGER_TYPE)
7359     {
7360       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7361         {
7362         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
7363         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
7364         case 32: 
7365           if (type == long_unsigned_type_node
7366               || type == long_integer_type_node)
7367                  c = TYPE_UNSIGNED (type) ? 'L' : 'l';
7368           else
7369                  c = TYPE_UNSIGNED (type) ? 'I' : 'i';
7370           break;
7371         case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
7372         default: abort ();
7373         }
7374       obstack_1grow (&util_obstack, c);
7375     }
7376
7377   else if (code == REAL_TYPE)
7378     {
7379       /* Floating point types.  */
7380       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7381         {
7382         case 32:  c = 'f'; break;
7383         case 64:
7384         case 128: c = 'd'; break;
7385         default: abort ();
7386         }
7387       obstack_1grow (&util_obstack, c);
7388     }
7389
7390   else if (code == VOID_TYPE)
7391     obstack_1grow (&util_obstack, 'v');
7392
7393   else if (code == BOOLEAN_TYPE)
7394     obstack_1grow (&util_obstack, 'B');
7395
7396   else if (code == ARRAY_TYPE)
7397     encode_array (type, curtype, format);
7398
7399   else if (code == POINTER_TYPE)
7400     encode_pointer (type, curtype, format);
7401
7402   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7403     encode_aggregate (type, curtype, format);
7404
7405   else if (code == FUNCTION_TYPE) /* '?' */
7406     obstack_1grow (&util_obstack, '?');
7407 }
7408
7409 static void
7410 encode_gnu_bitfield (int position, tree type, int size)
7411 {
7412   enum tree_code code = TREE_CODE (type);
7413   char buffer[40];
7414   char charType = '?';
7415
7416   if (code == INTEGER_TYPE)
7417     {
7418       if (integer_zerop (TYPE_MIN_VALUE (type)))
7419         {
7420           /* Unsigned integer types.  */
7421
7422           if (TYPE_MODE (type) == QImode)
7423             charType = 'C';
7424           else if (TYPE_MODE (type) == HImode)
7425             charType = 'S';
7426           else if (TYPE_MODE (type) == SImode)
7427             {
7428               if (type == long_unsigned_type_node)
7429                 charType = 'L';
7430               else
7431                 charType = 'I';
7432             }
7433           else if (TYPE_MODE (type) == DImode)
7434             charType = 'Q';
7435         }
7436
7437       else
7438         /* Signed integer types.  */
7439         {
7440           if (TYPE_MODE (type) == QImode)
7441             charType = 'c';
7442           else if (TYPE_MODE (type) == HImode)
7443             charType = 's';
7444           else if (TYPE_MODE (type) == SImode)
7445             {
7446               if (type == long_integer_type_node)
7447                 charType = 'l';
7448               else
7449                 charType = 'i';
7450             }
7451
7452           else if (TYPE_MODE (type) == DImode)
7453             charType = 'q';
7454         }
7455     }
7456   else if (code == ENUMERAL_TYPE)
7457     charType = 'i';
7458   else
7459     abort ();
7460
7461   sprintf (buffer, "b%d%c%d", position, charType, size);
7462   obstack_grow (&util_obstack, buffer, strlen (buffer));
7463 }
7464
7465 static void
7466 encode_field_decl (tree field_decl, int curtype, int format)
7467 {
7468   tree type;
7469
7470 #ifdef OBJCPLUS
7471   /* C++ static members, and things that are not fields at all,
7472      should not appear in the encoding.  */
7473   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7474     return;
7475 #endif
7476
7477   type = TREE_TYPE (field_decl);
7478
7479   /* Generate the bitfield typing information, if needed.  Note the difference
7480      between GNU and NeXT runtimes.  */
7481   if (DECL_BIT_FIELD_TYPE (field_decl))
7482     {
7483       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7484
7485       if (flag_next_runtime)
7486         encode_next_bitfield (size);
7487       else
7488         encode_gnu_bitfield (int_bit_position (field_decl),
7489                                   DECL_BIT_FIELD_TYPE (field_decl), size);
7490     }
7491   else
7492     encode_type (TREE_TYPE (field_decl), curtype, format);
7493 }
7494
7495 static tree
7496 objc_expr_last (tree complex_expr)
7497 {
7498   tree next;
7499
7500   if (complex_expr)
7501     while ((next = TREE_OPERAND (complex_expr, 0)))
7502       complex_expr = next;
7503
7504   return complex_expr;
7505 }
7506
7507 static void
7508 synth_self_and_ucmd_args (void)
7509 {
7510   tree decl_specs;
7511
7512   if (objc_method_context
7513       && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7514     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7515   else
7516     /* Really a `struct objc_class *'. However, we allow people to
7517        assign to self, which changes its type midstream.  */
7518     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7519
7520   push_parm_decl (build_tree_list
7521                   (build_tree_list (decl_specs,
7522                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
7523                    unused_list));
7524
7525   decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (objc_selector_type));
7526   push_parm_decl (build_tree_list
7527                   (build_tree_list (decl_specs,
7528                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7529                    unused_list));
7530 }
7531
7532 /* Transform a method definition into a function definition as follows:
7533    - synthesize the first two arguments, "self" and "_cmd".  */
7534
7535 void
7536 start_method_def (tree method)
7537 {
7538   /* Required to implement _msgSuper.  */
7539   objc_method_context = method;
7540   UOBJC_SUPER_decl = NULL_TREE;
7541
7542   /* Must be called BEFORE start_function.  */
7543   push_scope ();
7544   declare_parm_level ();
7545
7546   /* Generate prototype declarations for arguments..."new-style".  */
7547   synth_self_and_ucmd_args ();
7548
7549   /* Generate argument declarations if a keyword_decl.  */
7550   if (METHOD_SEL_ARGS (method))
7551     {
7552       tree arglist = METHOD_SEL_ARGS (method);
7553       do
7554         {
7555           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7556           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7557
7558           if (arg_decl)
7559             {
7560               tree last_expr = objc_expr_last (arg_decl);
7561
7562               /* Unite the abstract decl with its name.  */
7563               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7564               push_parm_decl (build_tree_list
7565                               (build_tree_list (arg_spec, arg_decl),
7566                                NULL_TREE));
7567
7568 #ifndef OBJCPLUS        
7569               /* Unhook: restore the abstract declarator.  */
7570               TREE_OPERAND (last_expr, 0) = NULL_TREE;
7571 #endif  
7572             }
7573
7574           else
7575             push_parm_decl (build_tree_list
7576                             (build_tree_list (arg_spec,
7577                                               KEYWORD_ARG_NAME (arglist)),
7578                              NULL_TREE));
7579
7580           arglist = TREE_CHAIN (arglist);
7581         }
7582       while (arglist);
7583     }
7584
7585   if (METHOD_ADD_ARGS (method) != NULL_TREE
7586       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7587     {
7588       /* We have a variable length selector - in "prototype" format.  */
7589       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7590       while (akey)
7591         {
7592           /* This must be done prior to calling pushdecl.  pushdecl is
7593              going to change our chain on us.  */
7594           tree nextkey = TREE_CHAIN (akey);
7595           pushdecl (akey);
7596           akey = nextkey;
7597         }
7598     }
7599 }
7600
7601 static void
7602 warn_with_method (const char *message, int mtype, tree method)
7603 {
7604   /* Add a readable method name to the warning.  */
7605   warning ("%J%s `%c%s'", method,
7606            message, mtype, gen_method_decl (method, errbuf));
7607 }
7608
7609 /* Return 1 if METHOD is consistent with PROTO.  */
7610
7611 static int
7612 comp_method_with_proto (tree method, tree proto)
7613 {
7614   /* Create a function template node at most once.  */
7615   if (!function1_template)
7616     function1_template = make_node (FUNCTION_TYPE);
7617
7618   /* Install argument types - normally set by build_function_type.  */
7619   TYPE_ARG_TYPES (function1_template)
7620     = get_arg_type_list (proto, METHOD_DEF, 0);
7621
7622   /* install return type */
7623   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7624
7625   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
7626 }
7627
7628 /* Return 1 if TYPE1 is equivalent to TYPE2.  */
7629
7630 static int
7631 objc_types_are_equivalent (tree type1, tree type2)
7632 {
7633   if (type1 == type2)
7634     return 1;
7635   if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7636     return 0;
7637   type1 = TYPE_PROTOCOL_LIST (type1);
7638   type2 = TYPE_PROTOCOL_LIST (type2);
7639   if (list_length (type1) == list_length (type2))
7640     {
7641       for (; type2; type2 = TREE_CHAIN (type2))
7642         if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7643           return 0;
7644       return 1;
7645     }
7646   return 0;
7647 }
7648
7649 /* Return 1 if PROTO1 is equivalent to PROTO2.  */
7650
7651 static int
7652 comp_proto_with_proto (tree proto1, tree proto2)
7653 {
7654   tree type1, type2;
7655
7656   /* The following test is needed in case there are hashing
7657      collisions.  */
7658   if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7659     return 0;
7660
7661   /* Compare return types.  */
7662   type1 = groktypename (TREE_TYPE (proto1));
7663   type2 = groktypename (TREE_TYPE (proto2));
7664
7665   if (!objc_types_are_equivalent (type1, type2))
7666     return 0;
7667
7668   /* Compare argument types.  */
7669   for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7670        type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7671        type1 && type2;
7672        type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7673     {
7674       if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7675         return 0;
7676     }
7677
7678   return (!type1 && !type2);
7679 }
7680
7681 /* - Generate an identifier for the function. the format is "_n_cls",
7682      where 1 <= n <= nMethods, and cls is the name the implementation we
7683      are processing.
7684    - Install the return type from the method declaration.
7685    - If we have a prototype, check for type consistency.  */
7686
7687 static void
7688 really_start_method (tree method, tree parmlist)
7689 {
7690   tree sc_spec, ret_spec, ret_decl, decl_specs;
7691   tree method_decl, method_id;
7692   const char *sel_name, *class_name, *cat_name;
7693   char *buf;
7694
7695   /* Synth the storage class & assemble the return type.  */
7696   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7697   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7698   decl_specs = chainon (sc_spec, ret_spec);
7699
7700   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7701   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7702   cat_name = ((TREE_CODE (objc_implementation_context)
7703                == CLASS_IMPLEMENTATION_TYPE)
7704               ? NULL
7705               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7706   method_slot++;
7707
7708   /* Make sure this is big enough for any plausible method label.  */
7709   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7710                          + (cat_name ? strlen (cat_name) : 0));
7711
7712   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7713                          class_name, cat_name, sel_name, method_slot);
7714
7715   method_id = get_identifier (buf);
7716
7717 #ifdef OBJCPLUS
7718   /* Objective-C methods cannot be overloaded, so we don't need
7719      the type encoding appended.  It looks bad anyway... */
7720   push_lang_context (lang_name_c);
7721 #endif
7722
7723   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7724
7725   /* Check the declarator portion of the return type for the method.  */
7726   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7727     {
7728       /* Unite the complex decl (specified in the abstract decl) with the
7729          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7730       tree save_expr = objc_expr_last (ret_decl);
7731
7732       TREE_OPERAND (save_expr, 0) = method_decl;
7733       method_decl = ret_decl;
7734
7735       /* Fool the parser into thinking it is starting a function.  */
7736       start_function (decl_specs, method_decl, NULL_TREE);
7737
7738       /* Unhook: this has the effect of restoring the abstract declarator.  */
7739       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7740     }
7741
7742   else
7743     {
7744       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7745
7746       /* Fool the parser into thinking it is starting a function.  */
7747       start_function (decl_specs, method_decl, NULL_TREE);
7748
7749       /* Unhook: this has the effect of restoring the abstract declarator.  */
7750       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7751     }
7752
7753 #ifdef OBJCPLUS
7754   /* set self_decl from the first argument...this global is used by
7755    * build_ivar_reference().build_indirect_ref().
7756    */
7757   self_decl = DECL_ARGUMENTS (current_function_decl);
7758
7759   /* snaroff (3/28/96): when compiling with -Wall, this suppresses
7760    * the following: warning:unused parameter `struct objc_selector * _cmd'
7761    */
7762   TREE_USED (self_decl) = 1;
7763   TREE_USED (TREE_CHAIN (self_decl)) = 1;
7764   /* Ditto for the underlying (static) C function.  */
7765   TREE_USED (current_function_decl) = 1;
7766   pop_lang_context ();
7767 #endif
7768
7769   METHOD_DEFINITION (method) = current_function_decl;
7770
7771   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7772
7773   if (implementation_template != objc_implementation_context)
7774     {
7775       tree proto
7776         = lookup_method_static (implementation_template,
7777                                 METHOD_SEL_NAME (method),
7778                                 TREE_CODE (method) == CLASS_METHOD_DECL);
7779
7780       if (proto)
7781         {
7782           if (!comp_method_with_proto (method, proto))
7783             {
7784               char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7785
7786               warn_with_method ("conflicting types for", type, method);
7787               warn_with_method ("previous declaration of", type, proto);
7788             }
7789         }
7790       else
7791         {
7792           /* We have a method @implementation even though we did not
7793              see a corresponding @interface declaration (which is allowed
7794              by Objective-C rules).  Go ahead and place the method in
7795              the @interface anyway, so that message dispatch lookups
7796              will see it.  */
7797           tree interface = implementation_template;
7798
7799           if (TREE_CODE (objc_implementation_context)
7800               == CATEGORY_IMPLEMENTATION_TYPE)
7801             interface = lookup_category
7802                         (interface,
7803                          CLASS_SUPER_NAME (objc_implementation_context));
7804
7805           if (interface)
7806             objc_add_method (interface, copy_node (method),
7807                              TREE_CODE (method) == CLASS_METHOD_DECL);
7808         }
7809     }
7810 }
7811
7812 /* The following routine is always called...this "architecture" is to
7813    accommodate "old-style" variable length selectors.
7814
7815    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7816
7817 void
7818 continue_method_def (void)
7819 {
7820   tree parmlist;
7821
7822   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7823     /* We have a `, ...' immediately following the selector.  */
7824     parmlist = get_parm_info (/*ellipsis=*/true);
7825   else
7826     parmlist = get_parm_info (/*ellipsis=*/false);
7827
7828 #ifndef OBJCPLUS
7829   /* Set self_decl from the first argument...this global is used by
7830      build_ivar_reference calling build_indirect_ref.  */
7831   self_decl = TREE_PURPOSE (parmlist);
7832 #endif /* !OBJCPLUS */
7833
7834   pop_scope ();
7835   really_start_method (objc_method_context, parmlist);
7836   store_parm_decls ();
7837 }
7838
7839 static void *UOBJC_SUPER_scope = 0;
7840
7841 /* _n_Method (id self, SEL sel, ...)
7842      {
7843        struct objc_super _S;
7844        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7845      }  */
7846
7847 tree
7848 get_super_receiver (void)
7849 {
7850   if (objc_method_context)
7851     {
7852       tree super_expr, super_expr_list;
7853
7854       if (!UOBJC_SUPER_decl)
7855       {
7856         UOBJC_SUPER_decl = start_decl (get_identifier (TAG_SUPER),
7857                                        build_tree_list (NULL_TREE,
7858                                        objc_super_template),
7859                                        0, NULL_TREE);
7860         
7861         finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7862
7863         /* This prevents `unused variable' warnings when compiling with -Wall.  */
7864         TREE_USED (UOBJC_SUPER_decl) = 1;
7865         DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7866
7867         UOBJC_SUPER_scope = get_current_scope ();
7868       }
7869
7870       /* Set receiver to self.  */
7871       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7872       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7873       super_expr_list = super_expr;
7874
7875       /* Set class to begin searching.  */
7876 #ifdef OBJCPLUS
7877       super_expr = build_component_ref (UOBJC_SUPER_decl,
7878                                         get_identifier ("super_class"));
7879 #else
7880       super_expr = build_component_ref (UOBJC_SUPER_decl,
7881                                         get_identifier ("class"));
7882 #endif
7883
7884       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7885         {
7886           /* [_cls, __cls]Super are "pre-built" in
7887              synth_forward_declarations.  */
7888
7889           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7890                                           ((TREE_CODE (objc_method_context)
7891                                             == INSTANCE_METHOD_DECL)
7892                                            ? ucls_super_ref
7893                                            : uucls_super_ref));
7894         }
7895
7896       else
7897         /* We have a category.  */
7898         {
7899           tree super_name = CLASS_SUPER_NAME (implementation_template);
7900           tree super_class;
7901
7902           /* Barf if super used in a category of Object.  */
7903           if (!super_name)
7904             {
7905               error ("no super class declared in interface for `%s'",
7906                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7907               return error_mark_node;
7908             }
7909
7910           if (flag_next_runtime && !flag_zero_link)
7911             {
7912               super_class = get_class_reference (super_name);
7913               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7914                 /* If we are in a class method, we must retrieve the
7915                    _metaclass_ for the current class, pointed at by
7916                    the class's "isa" pointer.  The following assumes that
7917                    "isa" is the first ivar in a class (which it must be).  */
7918                 super_class
7919                   = build_indirect_ref
7920                     (build_c_cast (build_pointer_type (objc_class_type),
7921                                    super_class), "unary *");
7922             }
7923           else
7924             {
7925               add_class_reference (super_name);
7926               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7927                              ? objc_get_class_decl : objc_get_meta_class_decl);
7928               assemble_external (super_class);
7929               super_class
7930                 = build_function_call
7931                   (super_class,
7932                    build_tree_list
7933                    (NULL_TREE,
7934                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7935                                      IDENTIFIER_POINTER (super_name))));
7936             }
7937
7938           super_expr
7939             = build_modify_expr (super_expr, NOP_EXPR,
7940                                  build_c_cast (TREE_TYPE (super_expr),
7941                                                super_class));
7942         }
7943
7944       super_expr_list = build_compound_expr (super_expr_list, super_expr);
7945
7946       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7947       super_expr_list = build_compound_expr (super_expr_list, super_expr);
7948
7949       return super_expr_list;
7950     }
7951   else
7952     {
7953       error ("[super ...] must appear in a method context");
7954       return error_mark_node;
7955     }
7956 }
7957
7958 /* When exiting a scope, sever links to a 'super' declaration (if any)
7959    therein contained.  */
7960
7961 void
7962 objc_clear_super_receiver (void)
7963 {
7964   if (objc_method_context
7965       && UOBJC_SUPER_scope == get_current_scope ()) {
7966     UOBJC_SUPER_decl = 0;
7967     UOBJC_SUPER_scope = 0;
7968   }
7969 }
7970
7971 static void
7972 objc_expand_function_end (void)
7973 {
7974   /* This routine may also get called for C functions, including those
7975      nested within ObjC methods.  In such cases, method encoding is
7976      meaningless.  */
7977   if (objc_method_context == NULL_TREE
7978       || DECL_INITIAL (objc_method_context) != current_function_decl)
7979     return;
7980
7981   METHOD_ENCODING (objc_method_context)
7982     = encode_method_prototype (objc_method_context);
7983 }
7984
7985 void
7986 finish_method_def (void)
7987 {
7988   lang_expand_function_end = objc_expand_function_end;
7989   /* We cannot validly inline ObjC methods, at least not without a language
7990      extension to declare that a method need not be dynamically
7991      dispatched, so suppress all thoughts of doing so.  */
7992   DECL_INLINE (current_function_decl) = 0;
7993   DECL_UNINLINABLE (current_function_decl) = 1;
7994
7995   finish_function ();
7996   lang_expand_function_end = NULL;
7997
7998   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7999      since the optimizer may find "may be used before set" errors.  */
8000   objc_method_context = NULL_TREE;
8001 }
8002
8003 #if 0
8004 int
8005 lang_report_error_function (tree decl)
8006 {
8007   if (objc_method_context)
8008     {
8009       fprintf (stderr, "In method `%s'\n",
8010                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8011       return 1;
8012     }
8013
8014   else
8015     return 0;
8016 }
8017 #endif
8018
8019 static int
8020 is_complex_decl (tree type)
8021 {
8022   return (TREE_CODE (type) == ARRAY_TYPE
8023           || TREE_CODE (type) == FUNCTION_TYPE
8024           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
8025 }
8026
8027 \f
8028 /* Code to convert a decl node into text for a declaration in C.  */
8029
8030 static char tmpbuf[256];
8031
8032 static void
8033 adorn_decl (tree decl, char *str)
8034 {
8035   enum tree_code code = TREE_CODE (decl);
8036
8037   if (code == ARRAY_REF)
8038     {
8039       tree an_int_cst = TREE_OPERAND (decl, 1);
8040
8041       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
8042         sprintf (str + strlen (str), "[%ld]",
8043                  (long) TREE_INT_CST_LOW (an_int_cst));
8044       else
8045         strcat (str, "[]");
8046     }
8047
8048   else if (code == ARRAY_TYPE)
8049     {
8050       tree an_int_cst = TYPE_SIZE (decl);
8051       tree array_of = TREE_TYPE (decl);
8052
8053       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
8054         sprintf (str + strlen (str), "[%ld]",
8055                  (long) (TREE_INT_CST_LOW (an_int_cst)
8056                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
8057       else
8058         strcat (str, "[]");
8059     }
8060
8061   else if (code == CALL_EXPR)
8062     {
8063       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
8064
8065       strcat (str, "(");
8066       while (chain)
8067         {
8068           gen_declaration_1 (chain, str);
8069           chain = TREE_CHAIN (chain);
8070           if (chain)
8071             strcat (str, ", ");
8072         }
8073       strcat (str, ")");
8074     }
8075
8076   else if (code == FUNCTION_TYPE)
8077     {
8078       tree chain  = TYPE_ARG_TYPES (decl);
8079
8080       strcat (str, "(");
8081       while (chain && TREE_VALUE (chain) != void_type_node)
8082         {
8083           gen_declaration_1 (TREE_VALUE (chain), str);
8084           chain = TREE_CHAIN (chain);
8085           if (chain && TREE_VALUE (chain) != void_type_node)
8086             strcat (str, ", ");
8087         }
8088       strcat (str, ")");
8089     }
8090
8091   else if (code == INDIRECT_REF)
8092     {
8093       strcpy (tmpbuf, "*");
8094       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
8095         {
8096           tree chain;
8097
8098           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
8099                chain;
8100                chain = TREE_CHAIN (chain))
8101             {
8102               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
8103                 {
8104                   strcat (tmpbuf, " ");
8105                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
8106                 }
8107             }
8108           if (str[0])
8109             strcat (tmpbuf, " ");
8110         }
8111       strcat (tmpbuf, str);
8112       strcpy (str, tmpbuf);
8113     }
8114
8115   else if (code == POINTER_TYPE)
8116     {
8117       strcpy (tmpbuf, "*");
8118       if (TYPE_READONLY (decl) || TYPE_VOLATILE (decl))
8119         {
8120           if (TYPE_READONLY (decl))
8121             strcat (tmpbuf, " const");
8122           if (TYPE_VOLATILE (decl))
8123             strcat (tmpbuf, " volatile");
8124           if (str[0])
8125             strcat (tmpbuf, " ");
8126         }
8127       strcat (tmpbuf, str);
8128       strcpy (str, tmpbuf);
8129     }
8130 }
8131
8132 static char *
8133 gen_declarator (tree decl, char *buf, const char *name)
8134 {
8135   if (decl)
8136     {
8137       enum tree_code code = TREE_CODE (decl);
8138       char *str;
8139       tree op;
8140       int wrap = 0;
8141
8142       switch (code)
8143         {
8144         case ARRAY_REF:
8145         case INDIRECT_REF:
8146         case CALL_EXPR:
8147           op = TREE_OPERAND (decl, 0);
8148
8149           /* We have a pointer to a function or array...(*)(), (*)[] */
8150           if ((code == ARRAY_REF || code == CALL_EXPR)
8151               && op && TREE_CODE (op) == INDIRECT_REF)
8152             wrap = 1;
8153
8154           str = gen_declarator (op, buf, name);
8155
8156           if (wrap)
8157             {
8158               strcpy (tmpbuf, "(");
8159               strcat (tmpbuf, str);
8160               strcat (tmpbuf, ")");
8161               strcpy (str, tmpbuf);
8162             }
8163
8164           adorn_decl (decl, str);
8165           break;
8166
8167         case ARRAY_TYPE:
8168         case FUNCTION_TYPE:
8169         case POINTER_TYPE:
8170           strcpy (buf, name);
8171           str = buf;
8172
8173           /* This clause is done iteratively rather than recursively.  */
8174           do
8175             {
8176               op = (is_complex_decl (TREE_TYPE (decl))
8177                     ? TREE_TYPE (decl) : NULL_TREE);
8178
8179               adorn_decl (decl, str);
8180
8181               /* We have a pointer to a function or array...(*)(), (*)[] */
8182               if (code == POINTER_TYPE
8183                   && op && (TREE_CODE (op) == FUNCTION_TYPE
8184                             || TREE_CODE (op) == ARRAY_TYPE))
8185                 {
8186                   strcpy (tmpbuf, "(");
8187                   strcat (tmpbuf, str);
8188                   strcat (tmpbuf, ")");
8189                   strcpy (str, tmpbuf);
8190                 }
8191
8192               decl = (is_complex_decl (TREE_TYPE (decl))
8193                       ? TREE_TYPE (decl) : NULL_TREE);
8194             }
8195
8196           while (decl && (code = TREE_CODE (decl)))
8197             ;
8198
8199           break;
8200
8201         case IDENTIFIER_NODE:
8202           /* Will only happen if we are processing a "raw" expr-decl.  */
8203           strcpy (buf, IDENTIFIER_POINTER (decl));
8204           return buf;
8205
8206         default:
8207           abort ();
8208         }
8209
8210       return str;
8211     }
8212
8213   else
8214     /* We have an abstract declarator or a _DECL node.  */
8215     {
8216       strcpy (buf, name);
8217       return buf;
8218     }
8219 }
8220
8221 static void
8222 gen_declspecs (tree declspecs, char *buf, int raw)
8223 {
8224   if (raw)
8225     {
8226       tree chain;
8227
8228       for (chain = nreverse (copy_list (declspecs));
8229            chain; chain = TREE_CHAIN (chain))
8230         {
8231           tree aspec = TREE_VALUE (chain);
8232
8233           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
8234             strcat (buf, IDENTIFIER_POINTER (aspec));
8235           else if (TREE_CODE (aspec) == RECORD_TYPE)
8236             {
8237               if (OBJC_TYPE_NAME (aspec))
8238                 {
8239                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8240
8241                   if (! TREE_STATIC_TEMPLATE (aspec))
8242                     strcat (buf, "struct ");
8243                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8244
8245                   /* NEW!!! */
8246                   if (protocol_list)
8247                     {
8248                       tree chain = protocol_list;
8249
8250                       strcat (buf, " <");
8251                       while (chain)
8252                         {
8253                           strcat (buf,
8254                                   IDENTIFIER_POINTER
8255                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
8256                           chain = TREE_CHAIN (chain);
8257                           if (chain)
8258                             strcat (buf, ", ");
8259                         }
8260                       strcat (buf, ">");
8261                     }
8262                 }
8263
8264               else
8265                 strcat (buf, "untagged struct");
8266             }
8267
8268           else if (TREE_CODE (aspec) == UNION_TYPE)
8269             {
8270               if (OBJC_TYPE_NAME (aspec))
8271                 {
8272                   if (! TREE_STATIC_TEMPLATE (aspec))
8273                     strcat (buf, "union ");
8274                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8275                 }
8276               else
8277                 strcat (buf, "untagged union");
8278             }
8279
8280           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
8281             {
8282               if (OBJC_TYPE_NAME (aspec))
8283                 {
8284                   if (! TREE_STATIC_TEMPLATE (aspec))
8285                     strcat (buf, "enum ");
8286                   strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8287                 }
8288               else
8289                 strcat (buf, "untagged enum");
8290             }
8291
8292           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
8293             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
8294
8295           else if (IS_ID (aspec))
8296             {
8297               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8298
8299               strcat (buf, "id");
8300               if (protocol_list)
8301                 {
8302                   tree chain = protocol_list;
8303
8304                   strcat (buf, " <");
8305                   while (chain)
8306                     {
8307                       strcat (buf,
8308                               IDENTIFIER_POINTER
8309                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8310                       chain = TREE_CHAIN (chain);
8311                       if (chain)
8312                         strcat (buf, ", ");
8313                     }
8314                   strcat (buf, ">");
8315                 }
8316             }
8317           if (TREE_CHAIN (chain))
8318             strcat (buf, " ");
8319         }
8320     }
8321   else
8322     {
8323       /* Type qualifiers.  */
8324       if (TYPE_READONLY (declspecs))
8325         strcat (buf, "const ");
8326       if (TYPE_VOLATILE (declspecs))
8327         strcat (buf, "volatile ");
8328
8329       switch (TREE_CODE (declspecs))
8330         {
8331           /* Type specifiers.  */
8332
8333         case INTEGER_TYPE:
8334           declspecs = TYPE_MAIN_VARIANT (declspecs);
8335
8336           /* Signed integer types.  */
8337
8338           if (declspecs == short_integer_type_node)
8339             strcat (buf, "short int ");
8340           else if (declspecs == integer_type_node)
8341             strcat (buf, "int ");
8342           else if (declspecs == long_integer_type_node)
8343             strcat (buf, "long int ");
8344           else if (declspecs == long_long_integer_type_node)
8345             strcat (buf, "long long int ");
8346           else if (declspecs == signed_char_type_node
8347                    || declspecs == char_type_node)
8348             strcat (buf, "char ");
8349
8350           /* Unsigned integer types.  */
8351
8352           else if (declspecs == short_unsigned_type_node)
8353             strcat (buf, "unsigned short ");
8354           else if (declspecs == unsigned_type_node)
8355             strcat (buf, "unsigned int ");
8356           else if (declspecs == long_unsigned_type_node)
8357             strcat (buf, "unsigned long ");
8358           else if (declspecs == long_long_unsigned_type_node)
8359             strcat (buf, "unsigned long long ");
8360           else if (declspecs == unsigned_char_type_node)
8361             strcat (buf, "unsigned char ");
8362           break;
8363
8364         case REAL_TYPE:
8365           declspecs = TYPE_MAIN_VARIANT (declspecs);
8366
8367           if (declspecs == float_type_node)
8368             strcat (buf, "float ");
8369           else if (declspecs == double_type_node)
8370             strcat (buf, "double ");
8371           else if (declspecs == long_double_type_node)
8372             strcat (buf, "long double ");
8373           break;
8374
8375         case RECORD_TYPE:
8376           if (OBJC_TYPE_NAME (declspecs)
8377               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8378             {
8379               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8380
8381               if (! TREE_STATIC_TEMPLATE (declspecs))
8382                 strcat (buf, "struct ");
8383               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8384
8385               if (protocol_list)
8386                 {
8387                   tree chain = protocol_list;
8388
8389                   strcat (buf, " <");
8390                   while (chain)
8391                     {
8392                       strcat (buf,
8393                               IDENTIFIER_POINTER
8394                               (PROTOCOL_NAME (TREE_VALUE (chain))));
8395                       chain = TREE_CHAIN (chain);
8396                       if (chain)
8397                         strcat (buf, ", ");
8398                     }
8399                   strcat (buf, ">");
8400                 }
8401             }
8402
8403           else
8404             strcat (buf, "untagged struct");
8405
8406           strcat (buf, " ");
8407           break;
8408
8409         case UNION_TYPE:
8410           if (OBJC_TYPE_NAME (declspecs)
8411               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8412             {
8413               strcat (buf, "union ");
8414               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8415               strcat (buf, " ");
8416             }
8417
8418           else
8419             strcat (buf, "untagged union ");
8420           break;
8421
8422         case ENUMERAL_TYPE:
8423           if (OBJC_TYPE_NAME (declspecs)
8424               && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8425             {
8426               strcat (buf, "enum ");
8427               strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8428               strcat (buf, " ");
8429             }
8430
8431           else
8432             strcat (buf, "untagged enum ");
8433           break;
8434
8435         case VOID_TYPE:
8436           strcat (buf, "void ");
8437           break;
8438
8439         case POINTER_TYPE:
8440           {
8441             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8442
8443             strcat (buf, "id");
8444             if (protocol_list)
8445               {
8446                 tree chain = protocol_list;
8447
8448                 strcat (buf, " <");
8449                 while (chain)
8450                   {
8451                     strcat (buf,
8452                             IDENTIFIER_POINTER
8453                             (PROTOCOL_NAME (TREE_VALUE (chain))));
8454                     chain = TREE_CHAIN (chain);
8455                     if (chain)
8456                       strcat (buf, ", ");
8457                   }
8458
8459                 strcat (buf, ">");
8460               }
8461           }
8462           break;
8463
8464         default:
8465           break;
8466         }
8467     }
8468 }
8469
8470 /* Given a tree node, produce a printable description of it in the given
8471    buffer, overwriting the buffer.  */
8472
8473 static char *
8474 gen_declaration (tree atype_or_adecl, char *buf)
8475 {
8476   buf[0] = '\0';
8477   gen_declaration_1 (atype_or_adecl, buf);
8478   return buf;
8479 }
8480
8481 /* Given a tree node, append a printable description to the end of the
8482    given buffer.  */
8483
8484 static void
8485 gen_declaration_1 (tree atype_or_adecl, char *buf)
8486 {
8487   char declbuf[256];
8488
8489   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
8490     {
8491       tree declspecs;   /* "identifier_node", "record_type" */
8492       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
8493       tree width = NULL_TREE;   /* for bitfields */
8494
8495       /* We have a "raw", abstract declarator (typename).  */
8496       declarator = TREE_VALUE (atype_or_adecl);
8497       /* In the case of raw ivars, the declarator itself is a list,
8498          and contains bitfield widths.  */
8499       if (declarator && TREE_CODE (declarator) == TREE_LIST)
8500         {
8501           width = TREE_VALUE (declarator);
8502           declarator = TREE_PURPOSE (declarator);
8503         }
8504       declspecs  = TREE_PURPOSE (atype_or_adecl);
8505
8506       gen_declspecs (declspecs, buf, 1);
8507       if (declarator)
8508         {
8509           strcat (buf, " ");
8510           strcat (buf, gen_declarator (declarator, declbuf, ""));
8511         }
8512       if (width)
8513         sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED, 
8514                  TREE_INT_CST_LOW (width));
8515     }
8516
8517   else
8518     {
8519       tree atype;
8520       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
8521       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
8522
8523       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8524           || TREE_CODE (atype_or_adecl) == PARM_DECL
8525           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8526         atype = TREE_TYPE (atype_or_adecl);
8527       else
8528         /* Assume we have a *_type node.  */
8529         atype = atype_or_adecl;
8530
8531       if (is_complex_decl (atype))
8532         {
8533           tree chain;
8534
8535           /* Get the declaration specifier; it is at the end of the list.  */
8536           declarator = chain = atype;
8537           do
8538             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8539           while (is_complex_decl (chain));
8540           declspecs = chain;
8541         }
8542
8543       else
8544         {
8545           declspecs = atype;
8546           declarator = NULL_TREE;
8547         }
8548
8549       gen_declspecs (declspecs, buf, 0);
8550
8551       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8552           || TREE_CODE (atype_or_adecl) == PARM_DECL
8553           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8554         {
8555           const char *const decl_name =
8556             (DECL_NAME (atype_or_adecl)
8557              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8558
8559           if (declarator)
8560             {
8561               strcat (buf, " ");
8562               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8563             }
8564
8565           else if (decl_name[0])
8566             {
8567               strcat (buf, " ");
8568               strcat (buf, decl_name);
8569             }
8570         }
8571       else if (declarator)
8572         {
8573           strcat (buf, " ");
8574           strcat (buf, gen_declarator (declarator, declbuf, ""));
8575         }
8576     }
8577 }
8578
8579 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8580
8581 /* Given a method tree, put a printable description into the given
8582    buffer (overwriting) and return a pointer to the buffer.  */
8583
8584 static char *
8585 gen_method_decl (tree method, char *buf)
8586 {
8587   tree chain;
8588
8589   buf[0] = '\0';
8590   if (RAW_TYPESPEC (method) != objc_object_reference)
8591     {
8592       strcat (buf, "(");
8593       gen_declaration_1 (TREE_TYPE (method), buf);
8594       strcat (buf, ")");
8595     }
8596
8597   chain = METHOD_SEL_ARGS (method);
8598   if (chain)
8599     {
8600       /* We have a chain of keyword_decls.  */
8601       do
8602         {
8603           if (KEYWORD_KEY_NAME (chain))
8604             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8605
8606           strcat (buf, ":");
8607           if (RAW_TYPESPEC (chain) != objc_object_reference)
8608             {
8609               strcat (buf, "(");
8610               gen_declaration_1 (TREE_TYPE (chain), buf);
8611               strcat (buf, ")");
8612             }
8613
8614           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8615           if ((chain = TREE_CHAIN (chain)))
8616             strcat (buf, " ");
8617         }
8618       while (chain);
8619
8620       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8621         strcat (buf, ", ...");
8622       else if (METHOD_ADD_ARGS (method))
8623         {
8624           /* We have a tree list node as generate by get_parm_info.  */
8625           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8626
8627           /* Know we have a chain of parm_decls.  */
8628           while (chain)
8629             {
8630               strcat (buf, ", ");
8631               gen_declaration_1 (chain, buf);
8632               chain = TREE_CHAIN (chain);
8633             }
8634         }
8635     }
8636
8637   else
8638     /* We have a unary selector.  */
8639     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8640
8641   return buf;
8642 }
8643 \f
8644 /* Debug info.  */
8645
8646
8647 /* Dump an @interface declaration of the supplied class CHAIN to the
8648    supplied file FP.  Used to implement the -gen-decls option (which
8649    prints out an @interface declaration of all classes compiled in
8650    this run); potentially useful for debugging the compiler too.  */
8651 static void
8652 dump_interface (FILE *fp, tree chain)
8653 {
8654   /* FIXME: A heap overflow here whenever a method (or ivar)
8655      declaration is so long that it doesn't fit in the buffer.  The
8656      code and all the related functions should be rewritten to avoid
8657      using fixed size buffers.  */
8658   char *buf = (char *) xmalloc (1024 * 10);
8659   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8660   tree ivar_decls = CLASS_RAW_IVARS (chain);
8661   tree nst_methods = CLASS_NST_METHODS (chain);
8662   tree cls_methods = CLASS_CLS_METHODS (chain);
8663
8664   fprintf (fp, "\n@interface %s", my_name);
8665
8666   /* CLASS_SUPER_NAME is used to store the superclass name for
8667      classes, and the category name for categories.  */
8668   if (CLASS_SUPER_NAME (chain))
8669     {
8670       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8671
8672       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8673           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8674         {
8675           fprintf (fp, " (%s)\n", name);
8676         }
8677       else
8678         {
8679           fprintf (fp, " : %s\n", name);
8680         }
8681     }
8682   else
8683     fprintf (fp, "\n");
8684
8685   /* FIXME - the following doesn't seem to work at the moment.  */
8686   if (ivar_decls)
8687     {
8688       fprintf (fp, "{\n");
8689       do
8690         {
8691           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8692           ivar_decls = TREE_CHAIN (ivar_decls);
8693         }
8694       while (ivar_decls);
8695       fprintf (fp, "}\n");
8696     }
8697
8698   while (nst_methods)
8699     {
8700       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8701       nst_methods = TREE_CHAIN (nst_methods);
8702     }
8703
8704   while (cls_methods)
8705     {
8706       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8707       cls_methods = TREE_CHAIN (cls_methods);
8708     }
8709
8710   fprintf (fp, "@end\n");
8711 }
8712
8713 /* Demangle function for Objective-C */
8714 static const char *
8715 objc_demangle (const char *mangled)
8716 {
8717   char *demangled, *cp;
8718
8719   if (mangled[0] == '_' &&
8720       (mangled[1] == 'i' || mangled[1] == 'c') &&
8721       mangled[2] == '_')
8722     {
8723       cp = demangled = xmalloc(strlen(mangled) + 2);
8724       if (mangled[1] == 'i')
8725         *cp++ = '-';            /* for instance method */
8726       else
8727         *cp++ = '+';            /* for class method */
8728       *cp++ = '[';              /* opening left brace */
8729       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8730       while (*cp && *cp == '_')
8731         cp++;                   /* skip any initial underbars in class name */
8732       cp = strchr(cp, '_');     /* find first non-initial underbar */
8733       if (cp == NULL)
8734         {
8735           free(demangled);      /* not mangled name */
8736           return mangled;
8737         }
8738       if (cp[1] == '_')  /* easy case: no category name */
8739         {
8740           *cp++ = ' ';            /* replace two '_' with one ' ' */
8741           strcpy(cp, mangled + (cp - demangled) + 2);
8742         }
8743       else
8744         {
8745           *cp++ = '(';            /* less easy case: category name */
8746           cp = strchr(cp, '_');
8747           if (cp == 0)
8748             {
8749               free(demangled);    /* not mangled name */
8750               return mangled;
8751             }
8752           *cp++ = ')';
8753           *cp++ = ' ';            /* overwriting 1st char of method name... */
8754           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8755         }
8756       while (*cp && *cp == '_')
8757         cp++;                   /* skip any initial underbars in method name */
8758       for (; *cp; cp++)
8759         if (*cp == '_')
8760           *cp = ':';            /* replace remaining '_' with ':' */
8761       *cp++ = ']';              /* closing right brace */
8762       *cp++ = 0;                /* string terminator */
8763       return demangled;
8764     }
8765   else
8766     return mangled;             /* not an objc mangled name */
8767 }
8768
8769 const char *
8770 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8771 {
8772   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8773 }
8774
8775 static void
8776 init_objc (void)
8777 {
8778   gcc_obstack_init (&util_obstack);
8779   util_firstobj = (char *) obstack_finish (&util_obstack);
8780
8781   errbuf = (char *) xmalloc (BUFSIZE);
8782   hash_init ();
8783   synth_module_prologue ();
8784 }
8785 \f
8786 static void
8787 finish_objc (void)
8788 {
8789   struct imp_entry *impent;
8790   tree chain;
8791   /* The internally generated initializers appear to have missing braces.
8792      Don't warn about this.  */
8793   int save_warn_missing_braces = warn_missing_braces;
8794   warn_missing_braces = 0;
8795
8796   /* A missing @end may not be detected by the parser.  */
8797   if (objc_implementation_context)
8798     {
8799       warning ("`@end' missing in implementation context");
8800       finish_class (objc_implementation_context);
8801       objc_ivar_chain = NULL_TREE;
8802       objc_implementation_context = NULL_TREE;
8803     }
8804
8805   /* Process the static instances here because initialization of objc_symtab
8806      depends on them.  */
8807   if (objc_static_instances)
8808     generate_static_references ();
8809
8810   if (imp_list || class_names_chain
8811       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8812     generate_objc_symtab_decl ();
8813
8814   for (impent = imp_list; impent; impent = impent->next)
8815     {
8816       objc_implementation_context = impent->imp_context;
8817       implementation_template = impent->imp_template;
8818
8819       UOBJC_CLASS_decl = impent->class_decl;
8820       UOBJC_METACLASS_decl = impent->meta_decl;
8821
8822       /* Dump the @interface of each class as we compile it, if the
8823          -gen-decls option is in use.  TODO: Dump the classes in the
8824          order they were found, rather than in reverse order as we
8825          are doing now.  */
8826       if (flag_gen_declaration)
8827         {
8828           dump_interface (gen_declaration_file, objc_implementation_context);
8829         }
8830
8831       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8832         {
8833           /* all of the following reference the string pool...  */
8834           generate_ivar_lists ();
8835           generate_dispatch_tables ();
8836           generate_shared_structures ();
8837         }
8838       else
8839         {
8840           generate_dispatch_tables ();
8841           generate_category (objc_implementation_context);
8842         }
8843     }
8844
8845   /* If we are using an array of selectors, we must always
8846      finish up the array decl even if no selectors were used.  */
8847   if (! flag_next_runtime || sel_ref_chain)
8848     build_selector_translation_table ();
8849
8850   if (protocol_chain)
8851     generate_protocols ();
8852
8853   if (flag_replace_objc_classes && imp_list)
8854     generate_objc_image_info ();
8855
8856   if (objc_implementation_context || class_names_chain || objc_static_instances
8857       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8858     {
8859       /* Arrange for ObjC data structures to be initialized at run time.  */
8860       rtx init_sym = build_module_descriptor ();
8861       if (init_sym && targetm.have_ctors_dtors)
8862         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8863     }
8864
8865   /* Dump the class references.  This forces the appropriate classes
8866      to be linked into the executable image, preserving unix archive
8867      semantics.  This can be removed when we move to a more dynamically
8868      linked environment.  */
8869
8870   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8871     {
8872       handle_class_ref (chain);
8873       if (TREE_PURPOSE (chain))
8874         generate_classref_translation_entry (chain);
8875     }
8876
8877   for (impent = imp_list; impent; impent = impent->next)
8878     handle_impent (impent);
8879
8880   /* Dump the string table last.  */
8881
8882   generate_strings ();
8883
8884   if (warn_selector)
8885     {
8886       int slot;
8887       hash hsh;
8888
8889       /* Run through the selector hash tables and print a warning for any
8890          selector which has multiple methods.  */
8891
8892       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8893         {
8894           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8895             check_duplicates (hsh, 0, 1);
8896           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8897             check_duplicates (hsh, 0, 1);
8898         }
8899     }
8900
8901   warn_missing_braces = save_warn_missing_braces;
8902 }
8903 \f
8904 /* Subroutines of finish_objc.  */
8905
8906 static void
8907 generate_classref_translation_entry (tree chain)
8908 {
8909   tree expr, name, decl_specs, decl, sc_spec;
8910   tree type;
8911
8912   type = TREE_TYPE (TREE_PURPOSE (chain));
8913
8914   expr = add_objc_string (TREE_VALUE (chain), class_names);
8915   expr = build_c_cast (type, expr); /* cast! */
8916
8917   name = DECL_NAME (TREE_PURPOSE (chain));
8918
8919   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8920
8921   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8922   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8923
8924   /* The decl that is returned from start_decl is the one that we
8925      forward declared in build_class_reference.  */
8926   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8927   DECL_CONTEXT (decl) = NULL_TREE;
8928   finish_decl (decl, expr, NULL_TREE);
8929   return;
8930 }
8931
8932 static void
8933 handle_class_ref (tree chain)
8934 {
8935   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8936   char *string = (char *) alloca (strlen (name) + 30);
8937   tree decl;
8938   tree exp;
8939
8940   sprintf (string, "%sobjc_class_name_%s",
8941            (flag_next_runtime ? "." : "__"), name);
8942
8943 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8944   if (flag_next_runtime)
8945     {
8946       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8947       return;
8948     }
8949 #endif
8950
8951   /* Make a decl for this name, so we can use its address in a tree.  */
8952   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8953   DECL_EXTERNAL (decl) = 1;
8954   TREE_PUBLIC (decl) = 1;
8955
8956   pushdecl (decl);
8957   rest_of_decl_compilation (decl, 0, 0, 0);
8958
8959   /* Make a decl for the address.  */
8960   sprintf (string, "%sobjc_class_ref_%s",
8961            (flag_next_runtime ? "." : "__"), name);
8962   exp = build1 (ADDR_EXPR, string_type_node, decl);
8963   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8964   DECL_INITIAL (decl) = exp;
8965   TREE_STATIC (decl) = 1;
8966   TREE_USED (decl) = 1;
8967
8968   pushdecl (decl);
8969   rest_of_decl_compilation (decl, 0, 0, 0);
8970 }
8971
8972 static void
8973 handle_impent (struct imp_entry *impent)
8974 {
8975   char *string;
8976
8977   objc_implementation_context = impent->imp_context;
8978   implementation_template = impent->imp_template;
8979
8980   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8981     {
8982       const char *const class_name =
8983         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8984
8985       string = (char *) alloca (strlen (class_name) + 30);
8986
8987       sprintf (string, "%sobjc_class_name_%s",
8988                (flag_next_runtime ? "." : "__"), class_name);
8989     }
8990   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8991     {
8992       const char *const class_name =
8993         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8994       const char *const class_super_name =
8995         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8996
8997       string = (char *) alloca (strlen (class_name)
8998                                 + strlen (class_super_name) + 30);
8999
9000       /* Do the same for categories.  Even though no references to
9001          these symbols are generated automatically by the compiler, it
9002          gives you a handle to pull them into an archive by hand.  */
9003       sprintf (string, "*%sobjc_category_name_%s_%s",
9004                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
9005     }
9006   else
9007     return;
9008
9009 #ifdef ASM_DECLARE_CLASS_REFERENCE
9010   if (flag_next_runtime)
9011     {
9012       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9013       return;
9014     }
9015   else
9016 #endif
9017     {
9018       tree decl, init;
9019
9020       init = build_int_2 (0, 0);
9021       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
9022       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9023       TREE_PUBLIC (decl) = 1;
9024       TREE_READONLY (decl) = 1;
9025       TREE_USED (decl) = 1;
9026       TREE_CONSTANT (decl) = 1;
9027       DECL_CONTEXT (decl) = 0;
9028       DECL_ARTIFICIAL (decl) = 1;
9029       DECL_INITIAL (decl) = init;
9030       assemble_variable (decl, 1, 0, 0);
9031     }
9032 }
9033 \f
9034 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
9035    later requires that ObjC translation units participating in F&C be
9036    specially marked.  The following routine accomplishes this.  */
9037
9038 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9039
9040 static void
9041 generate_objc_image_info (void)
9042 {
9043   tree sc_spec, decl, initlist;
9044
9045   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
9046   decl
9047    = start_decl (get_identifier ("_OBJC_IMAGE_INFO"),
9048                  tree_cons (NULL_TREE,
9049                             build_array_type
9050                             (integer_type_node,
9051                              build_index_type (build_int_2 (1, 0))),
9052                             sc_spec),
9053                  1,
9054                  NULL_TREE);
9055
9056   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
9057   initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
9058   initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
9059
9060   TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
9061   TREE_CONSTANT (initlist) = TREE_STATIC (initlist) = 1;
9062   finish_decl (decl, initlist, NULL_TREE);
9063 }
9064
9065 /* Look up ID as an instance variable.  */
9066
9067 tree
9068 lookup_objc_ivar (tree id)
9069 {
9070   tree decl;
9071
9072   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
9073     /* We have a message to super.  */
9074     return get_super_receiver ();
9075   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
9076     {
9077       if (is_private (decl))
9078         return 0;
9079       else
9080         return build_ivar_reference (id);
9081     }
9082   else
9083     return 0;
9084 }
9085
9086 #include "gt-objc-objc-act.h"
9087 #include "gtype-objc.h"