OSDN Git Service

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