OSDN Git Service

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