OSDN Git Service

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