OSDN Git Service

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