OSDN Git Service

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