OSDN Git Service

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