OSDN Git Service

2002-08-19 Ziemowit Laski <zlaski@apple.com>
[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 tree
5109 build_selector_expr (selnamelist)
5110      tree selnamelist;
5111 {
5112   tree selname;
5113
5114   /* Obtain the full selector name.  */
5115   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5116     /* A unary selector.  */
5117     selname = selnamelist;
5118   else if (TREE_CODE (selnamelist) == TREE_LIST)
5119     selname = build_keyword_selector (selnamelist);
5120   else
5121     abort ();
5122
5123   if (flag_typed_selectors)
5124     return build_typed_selector_reference (selname, 0);
5125   else
5126     return build_selector_reference (selname);
5127 }
5128
5129 tree
5130 build_encode_expr (type)
5131      tree type;
5132 {
5133   tree result;
5134   const char *string;
5135
5136   encode_type (type, obstack_object_size (&util_obstack),
5137                OBJC_ENCODE_INLINE_DEFS);
5138   obstack_1grow (&util_obstack, 0);    /* null terminate string */
5139   string = obstack_finish (&util_obstack);
5140
5141   /* Synthesize a string that represents the encoded struct/union.  */
5142   result = my_build_string (strlen (string) + 1, string);
5143   obstack_free (&util_obstack, util_firstobj);
5144   return result;
5145 }
5146
5147 tree
5148 build_ivar_reference (id)
5149      tree id;
5150 {
5151   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
5152     {
5153       /* Historically, a class method that produced objects (factory
5154          method) would assign `self' to the instance that it
5155          allocated.  This would effectively turn the class method into
5156          an instance method.  Following this assignment, the instance
5157          variables could be accessed.  That practice, while safe,
5158          violates the simple rule that a class method should not refer
5159          to an instance variable.  It's better to catch the cases
5160          where this is done unknowingly than to support the above
5161          paradigm.  */
5162       warning ("instance variable `%s' accessed in class method",
5163                IDENTIFIER_POINTER (id));
5164       TREE_TYPE (self_decl) = instance_type; /* cast */
5165     }
5166
5167   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5168 }
5169 \f
5170 /* Compute a hash value for a given method SEL_NAME.  */
5171
5172 static size_t
5173 hash_func (sel_name)
5174      tree sel_name;
5175 {
5176   const unsigned char *s 
5177     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
5178   size_t h = 0;
5179   
5180   while (*s)
5181     h = h * 67 + *s++ - 113;
5182   return h;  
5183 }
5184      
5185 static void
5186 hash_init ()
5187 {
5188   nst_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5189   cls_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5190 }
5191
5192 /* WARNING!!!!  hash_enter is called with a method, and will peek
5193    inside to find its selector!  But hash_lookup is given a selector
5194    directly, and looks for the selector that's inside the found
5195    entry's key (method) for comparison.  */
5196
5197 static void
5198 hash_enter (hashlist, method)
5199      hash *hashlist;
5200      tree method;
5201 {
5202   hash obj;
5203   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5204
5205   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
5206   obj->list = 0;
5207   obj->next = hashlist[slot];
5208   obj->key = method;
5209
5210   hashlist[slot] = obj;         /* append to front */
5211 }
5212
5213 static hash
5214 hash_lookup (hashlist, sel_name)
5215      hash *hashlist;
5216      tree sel_name;
5217 {
5218   hash target;
5219
5220   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
5221
5222   while (target)
5223     {
5224       if (sel_name == METHOD_SEL_NAME (target->key))
5225         return target;
5226
5227       target = target->next;
5228     }
5229   return 0;
5230 }
5231
5232 static void
5233 hash_add_attr (entry, value)
5234      hash entry;
5235      tree value;
5236 {
5237   attr obj;
5238
5239   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
5240   obj->next = entry->list;
5241   obj->value = value;
5242
5243   entry->list = obj;            /* append to front */
5244 }
5245 \f
5246 static tree
5247 lookup_method (mchain, method)
5248      tree mchain;
5249      tree method;
5250 {
5251   tree key;
5252
5253   if (TREE_CODE (method) == IDENTIFIER_NODE)
5254     key = method;
5255   else
5256     key = METHOD_SEL_NAME (method);
5257
5258   while (mchain)
5259     {
5260       if (METHOD_SEL_NAME (mchain) == key)
5261         return mchain;
5262       mchain = TREE_CHAIN (mchain);
5263     }
5264   return NULL_TREE;
5265 }
5266
5267 static tree
5268 lookup_instance_method_static (interface, ident)
5269      tree interface;
5270      tree ident;
5271 {
5272   tree inter = interface;
5273   tree chain = CLASS_NST_METHODS (inter);
5274   tree meth = NULL_TREE;
5275
5276   do
5277     {
5278       if ((meth = lookup_method (chain, ident)))
5279         return meth;
5280
5281       if (CLASS_CATEGORY_LIST (inter))
5282         {
5283           tree category = CLASS_CATEGORY_LIST (inter);
5284           chain = CLASS_NST_METHODS (category);
5285
5286           do
5287             {
5288               if ((meth = lookup_method (chain, ident)))
5289                 return meth;
5290
5291               /* Check for instance methods in protocols in categories.  */
5292               if (CLASS_PROTOCOL_LIST (category))
5293                 {
5294                   if ((meth = (lookup_method_in_protocol_list
5295                                (CLASS_PROTOCOL_LIST (category), ident, 0))))
5296                     return meth;
5297                 }
5298
5299               if ((category = CLASS_CATEGORY_LIST (category)))
5300                 chain = CLASS_NST_METHODS (category);
5301             }
5302           while (category);
5303         }
5304
5305       if (CLASS_PROTOCOL_LIST (inter))
5306         {
5307           if ((meth = (lookup_method_in_protocol_list
5308                        (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5309             return meth;
5310         }
5311
5312       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5313         chain = CLASS_NST_METHODS (inter);
5314     }
5315   while (inter);
5316
5317   return meth;
5318 }
5319
5320 static tree
5321 lookup_class_method_static (interface, ident)
5322      tree interface;
5323      tree ident;
5324 {
5325   tree inter = interface;
5326   tree chain = CLASS_CLS_METHODS (inter);
5327   tree meth = NULL_TREE;
5328   tree root_inter = NULL_TREE;
5329
5330   do
5331     {
5332       if ((meth = lookup_method (chain, ident)))
5333         return meth;
5334
5335       if (CLASS_CATEGORY_LIST (inter))
5336         {
5337           tree category = CLASS_CATEGORY_LIST (inter);
5338           chain = CLASS_CLS_METHODS (category);
5339
5340           do
5341             {
5342               if ((meth = lookup_method (chain, ident)))
5343                 return meth;
5344
5345               /* Check for class methods in protocols in categories.  */
5346               if (CLASS_PROTOCOL_LIST (category))
5347                 {
5348                   if ((meth = (lookup_method_in_protocol_list
5349                                (CLASS_PROTOCOL_LIST (category), ident, 1))))
5350                     return meth;
5351                 }
5352
5353               if ((category = CLASS_CATEGORY_LIST (category)))
5354                 chain = CLASS_CLS_METHODS (category);
5355             }
5356           while (category);
5357         }
5358
5359       /* Check for class methods in protocols.  */
5360       if (CLASS_PROTOCOL_LIST (inter))
5361         {
5362           if ((meth = (lookup_method_in_protocol_list
5363                        (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5364             return meth;
5365         }
5366
5367       root_inter = inter;
5368       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5369         chain = CLASS_CLS_METHODS (inter);
5370     }
5371   while (inter);
5372
5373   /* If no class (factory) method was found, check if an _instance_
5374      method of the same name exists in the root class.  This is what
5375      the Objective-C runtime will do.  */
5376   return lookup_instance_method_static (root_inter, ident);
5377 }
5378
5379 tree
5380 add_class_method (class, method)
5381      tree class;
5382      tree method;
5383 {
5384   tree mth;
5385   hash hsh;
5386
5387   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5388     {
5389       /* put method on list in reverse order */
5390       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5391       CLASS_CLS_METHODS (class) = method;
5392     }
5393   else
5394     {
5395       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5396         error ("duplicate definition of class method `%s'",
5397                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5398       else
5399         {
5400           /* Check types; if different, complain.  */
5401           if (!comp_proto_with_proto (method, mth))
5402             error ("duplicate declaration of class method `%s'",
5403                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5404         }
5405     }
5406
5407   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5408     {
5409       /* Install on a global chain.  */
5410       hash_enter (cls_method_hash_list, method);
5411     }
5412   else
5413     {
5414       /* Check types; if different, add to a list.  */
5415       if (!comp_proto_with_proto (method, hsh->key))
5416         hash_add_attr (hsh, method);
5417     }
5418   return method;
5419 }
5420 \f
5421 tree
5422 add_instance_method (class, method)
5423      tree class;
5424      tree method;
5425 {
5426   tree mth;
5427   hash hsh;
5428
5429   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5430     {
5431       /* Put method on list in reverse order.  */
5432       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5433       CLASS_NST_METHODS (class) = method;
5434     }
5435   else
5436     {
5437       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5438         error ("duplicate definition of instance method `%s'",
5439                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5440       else
5441         {
5442           /* Check types; if different, complain.  */
5443           if (!comp_proto_with_proto (method, mth))
5444             error ("duplicate declaration of instance method `%s'",
5445                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5446         }
5447     }
5448
5449   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5450     {
5451       /* Install on a global chain.  */
5452       hash_enter (nst_method_hash_list, method);
5453     }
5454   else
5455     {
5456       /* Check types; if different, add to a list.  */
5457       if (!comp_proto_with_proto (method, hsh->key))
5458         hash_add_attr (hsh, method);
5459     }
5460   return method;
5461 }
5462
5463 static tree
5464 add_class (class)
5465      tree class;
5466 {
5467   /* Put interfaces on list in reverse order.  */
5468   TREE_CHAIN (class) = interface_chain;
5469   interface_chain = class;
5470   return interface_chain;
5471 }
5472
5473 static void
5474 add_category (class, category)
5475       tree class;
5476       tree category;
5477 {
5478   /* Put categories on list in reverse order.  */
5479   tree cat = CLASS_CATEGORY_LIST (class);
5480
5481   while (cat)
5482     {
5483       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5484         warning ("duplicate interface declaration for category `%s(%s)'",
5485                  IDENTIFIER_POINTER (CLASS_NAME (class)),
5486                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5487       cat = CLASS_CATEGORY_LIST (cat);
5488     }
5489
5490   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5491   CLASS_CATEGORY_LIST (class) = category;
5492 }
5493
5494 /* Called after parsing each instance variable declaration. Necessary to
5495    preserve typedefs and implement public/private...
5496
5497    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
5498
5499 tree
5500 add_instance_variable (class, public, declarator, declspecs, width)
5501      tree class;
5502      int public;
5503      tree declarator;
5504      tree declspecs;
5505      tree width;
5506 {
5507   tree field_decl, raw_decl;
5508
5509   raw_decl = build_tree_list (declspecs, declarator);
5510
5511   if (CLASS_RAW_IVARS (class))
5512     chainon (CLASS_RAW_IVARS (class), raw_decl);
5513   else
5514     CLASS_RAW_IVARS (class) = raw_decl;
5515
5516   field_decl = grokfield (input_filename, lineno,
5517                           declarator, declspecs, width);
5518
5519   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
5520   switch (public)
5521     {
5522     case 0:
5523       TREE_PUBLIC (field_decl) = 0;
5524       TREE_PRIVATE (field_decl) = 0;
5525       TREE_PROTECTED (field_decl) = 1;
5526       break;
5527
5528     case 1:
5529       TREE_PUBLIC (field_decl) = 1;
5530       TREE_PRIVATE (field_decl) = 0;
5531       TREE_PROTECTED (field_decl) = 0;
5532       break;
5533
5534     case 2:
5535       TREE_PUBLIC (field_decl) = 0;
5536       TREE_PRIVATE (field_decl) = 1;
5537       TREE_PROTECTED (field_decl) = 0;
5538       break;
5539
5540     }
5541
5542   if (CLASS_IVARS (class))
5543     chainon (CLASS_IVARS (class), field_decl);
5544   else
5545     CLASS_IVARS (class) = field_decl;
5546
5547   return class;
5548 }
5549 \f
5550 tree
5551 is_ivar (decl_chain, ident)
5552      tree decl_chain;
5553      tree ident;
5554 {
5555   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5556     if (DECL_NAME (decl_chain) == ident)
5557       return decl_chain;
5558   return NULL_TREE;
5559 }
5560
5561 /* True if the ivar is private and we are not in its implementation.  */
5562
5563 int
5564 is_private (decl)
5565      tree decl;
5566 {
5567   if (TREE_PRIVATE (decl)
5568       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5569     {
5570       error ("instance variable `%s' is declared private",
5571              IDENTIFIER_POINTER (DECL_NAME (decl)));
5572       return 1;
5573     }
5574   else
5575     return 0;
5576 }
5577
5578 /* We have an instance variable reference;, check to see if it is public.  */
5579
5580 int
5581 is_public (expr, identifier)
5582      tree expr;
5583      tree identifier;
5584 {
5585   tree basetype = TREE_TYPE (expr);
5586   enum tree_code code = TREE_CODE (basetype);
5587   tree decl;
5588
5589   if (code == RECORD_TYPE)
5590     {
5591       if (TREE_STATIC_TEMPLATE (basetype))
5592         {
5593           if (!lookup_interface (TYPE_NAME (basetype)))
5594             {
5595               error ("cannot find interface declaration for `%s'",
5596                      IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5597               return 0;
5598             }
5599
5600           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5601             {
5602               if (TREE_PUBLIC (decl))
5603                 return 1;
5604
5605               /* Important difference between the Stepstone translator:
5606                  all instance variables should be public within the context
5607                  of the implementation.  */
5608               if (objc_implementation_context
5609                   && (((TREE_CODE (objc_implementation_context)
5610                         == CLASS_IMPLEMENTATION_TYPE)
5611                        || (TREE_CODE (objc_implementation_context)
5612                            == CATEGORY_IMPLEMENTATION_TYPE))
5613                       && (CLASS_NAME (objc_implementation_context)
5614                           == TYPE_NAME (basetype))))
5615                 return ! is_private (decl);
5616
5617               error ("instance variable `%s' is declared %s",
5618                      IDENTIFIER_POINTER (identifier),
5619                      TREE_PRIVATE (decl) ? "private" : "protected");
5620               return 0;
5621             }
5622         }
5623
5624       else if (objc_implementation_context && (basetype == objc_object_reference))
5625         {
5626           TREE_TYPE (expr) = uprivate_record;
5627           warning ("static access to object of type `id'");
5628         }
5629     }
5630
5631   return 1;
5632 }
5633 \f
5634 /* Make sure all entries in CHAIN are also in LIST.  */
5635
5636 static int
5637 check_methods (chain, list, mtype)
5638      tree chain;
5639      tree list;
5640      int mtype;
5641 {
5642   int first = 1;
5643
5644   while (chain)
5645     {
5646       if (!lookup_method (list, chain))
5647         {
5648           if (first)
5649             {
5650               if (TREE_CODE (objc_implementation_context)
5651                   == CLASS_IMPLEMENTATION_TYPE)
5652                 warning ("incomplete implementation of class `%s'",
5653                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
5654               else if (TREE_CODE (objc_implementation_context)
5655                        == CATEGORY_IMPLEMENTATION_TYPE)
5656                 warning ("incomplete implementation of category `%s'",
5657                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
5658               first = 0;
5659             }
5660
5661           warning ("method definition for `%c%s' not found",
5662                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5663         }
5664
5665       chain = TREE_CHAIN (chain);
5666     }
5667
5668     return first;
5669 }
5670
5671 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
5672
5673 static int
5674 conforms_to_protocol (class, protocol)
5675      tree class;
5676      tree protocol;
5677 {
5678    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
5679      {
5680        tree p = CLASS_PROTOCOL_LIST (class);
5681        while (p && TREE_VALUE (p) != protocol)
5682          p = TREE_CHAIN (p);
5683
5684        if (!p)
5685          {
5686            tree super = (CLASS_SUPER_NAME (class)
5687                          ? lookup_interface (CLASS_SUPER_NAME (class))
5688                          : NULL_TREE);
5689            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5690            if (!tmp)
5691              return 0;
5692          }
5693      }
5694
5695    return 1;
5696 }
5697
5698 /* Make sure all methods in CHAIN are accessible as MTYPE methods in 
5699    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
5700
5701 static int
5702 check_methods_accessible (chain, context, mtype)
5703      tree chain;
5704      tree context;
5705      int mtype;
5706 {
5707   int first = 1;
5708   tree list;
5709   tree base_context = context;
5710
5711   while (chain)
5712     {
5713       context = base_context;
5714       while (context)
5715         {
5716           if (mtype == '+')
5717             list = CLASS_CLS_METHODS (context);
5718           else
5719             list = CLASS_NST_METHODS (context);
5720
5721           if (lookup_method (list, chain))
5722               break; 
5723
5724           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5725                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5726             context = (CLASS_SUPER_NAME (context) 
5727                        ? lookup_interface (CLASS_SUPER_NAME (context))
5728                        : NULL_TREE);
5729
5730           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5731                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5732             context = (CLASS_NAME (context) 
5733                        ? lookup_interface (CLASS_NAME (context))
5734                        : NULL_TREE);
5735           else
5736             abort ();
5737         }
5738
5739       if (context == NULL_TREE)
5740         {
5741           if (first)
5742             {
5743               if (TREE_CODE (objc_implementation_context)
5744                   == CLASS_IMPLEMENTATION_TYPE)
5745                 warning ("incomplete implementation of class `%s'",
5746                          IDENTIFIER_POINTER
5747                            (CLASS_NAME (objc_implementation_context)));
5748               else if (TREE_CODE (objc_implementation_context)
5749                        == CATEGORY_IMPLEMENTATION_TYPE)
5750                 warning ("incomplete implementation of category `%s'",
5751                          IDENTIFIER_POINTER
5752                            (CLASS_SUPER_NAME (objc_implementation_context)));
5753               first = 0;
5754             }
5755           warning ("method definition for `%c%s' not found",
5756                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5757         }
5758
5759       chain = TREE_CHAIN (chain); /* next method...  */
5760     }
5761   return first;
5762 }
5763
5764 /* Check whether the current interface (accessible via
5765    'objc_implementation_context') actually implements protocol P, along
5766    with any protocols that P inherits.  */
5767    
5768 static void
5769 check_protocol (p, type, name)
5770      tree p;
5771      const char *type;
5772      const char *name;
5773 {
5774   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
5775     {
5776       int f1, f2;
5777
5778       /* Ensure that all protocols have bodies!  */
5779       if (warn_protocol)
5780         {
5781           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
5782                               CLASS_CLS_METHODS (objc_implementation_context),
5783                               '+');
5784           f2 = check_methods (PROTOCOL_NST_METHODS (p),
5785                               CLASS_NST_METHODS (objc_implementation_context),
5786                               '-');
5787         }
5788       else
5789         {
5790           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
5791                                          objc_implementation_context,
5792                                          '+');
5793           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
5794                                          objc_implementation_context,
5795                                          '-');
5796         }
5797
5798       if (!f1 || !f2)
5799         warning ("%s `%s' does not fully implement the `%s' protocol",
5800                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
5801     }
5802     
5803   /* Check protocols recursively.  */
5804   if (PROTOCOL_LIST (p))
5805     {
5806       tree subs = PROTOCOL_LIST (p);
5807       tree super_class =
5808         lookup_interface (CLASS_SUPER_NAME (implementation_template));
5809
5810       while (subs) 
5811         {
5812           tree sub = TREE_VALUE (subs);
5813
5814           /* If the superclass does not conform to the protocols
5815              inherited by P, then we must!  */
5816           if (!super_class || !conforms_to_protocol (super_class, sub))
5817             check_protocol (sub, type, name);
5818           subs = TREE_CHAIN (subs);
5819         }
5820     }
5821 }
5822         
5823 /* Check whether the current interface (accessible via
5824    'objc_implementation_context') actually implements the protocols listed
5825    in PROTO_LIST.  */
5826    
5827 static void
5828 check_protocols (proto_list, type, name)
5829      tree proto_list;
5830      const char *type;
5831      const char *name;
5832 {
5833   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
5834     {
5835       tree p = TREE_VALUE (proto_list);
5836
5837       check_protocol (p, type, name);
5838     }
5839 }
5840 \f
5841 /* Make sure that the class CLASS_NAME is defined
5842    CODE says which kind of thing CLASS_NAME ought to be.
5843    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
5844    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
5845
5846 tree
5847 start_class (code, class_name, super_name, protocol_list)
5848      enum tree_code code;
5849      tree class_name;
5850      tree super_name;
5851      tree protocol_list;
5852 {
5853   tree class, decl;
5854
5855   if (objc_implementation_context)
5856     {
5857       warning ("`@end' missing in implementation context");
5858       finish_class (objc_implementation_context);
5859       objc_ivar_chain = NULL_TREE;
5860       objc_implementation_context = NULL_TREE;
5861     }
5862
5863   class = make_node (code);
5864   TYPE_BINFO (class) = make_tree_vec (6);
5865
5866   CLASS_NAME (class) = class_name;
5867   CLASS_SUPER_NAME (class) = super_name;
5868   CLASS_CLS_METHODS (class) = NULL_TREE;
5869
5870   if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
5871     {
5872       error ("`%s' redeclared as different kind of symbol",
5873              IDENTIFIER_POINTER (class_name));
5874       error_with_decl (decl, "previous declaration of `%s'");
5875     }
5876
5877   if (code == CLASS_IMPLEMENTATION_TYPE)
5878     {
5879       {
5880         tree chain;
5881
5882         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
5883            if (TREE_VALUE (chain) == class_name)
5884              {
5885                error ("reimplementation of class `%s'",
5886                       IDENTIFIER_POINTER (class_name));
5887                return error_mark_node;
5888              }
5889         implemented_classes = tree_cons (NULL_TREE, class_name,
5890                                          implemented_classes);
5891       }
5892
5893       /* Pre-build the following entities - for speed/convenience.  */
5894       if (!self_id)
5895           self_id = get_identifier ("self");
5896       if (!ucmd_id)
5897         ucmd_id = get_identifier ("_cmd");
5898       if (!unused_list)
5899         unused_list
5900           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
5901       if (!objc_super_template)
5902         objc_super_template = build_super_template ();
5903
5904       /* Reset for multiple classes per file.  */
5905       method_slot = 0;
5906
5907       objc_implementation_context = class;
5908
5909       /* Lookup the interface for this implementation.  */
5910
5911       if (!(implementation_template = lookup_interface (class_name)))
5912         {
5913           warning ("cannot find interface declaration for `%s'",
5914                    IDENTIFIER_POINTER (class_name));
5915           add_class (implementation_template = objc_implementation_context);
5916         }
5917
5918       /* If a super class has been specified in the implementation,
5919          insure it conforms to the one specified in the interface.  */
5920
5921       if (super_name
5922           && (super_name != CLASS_SUPER_NAME (implementation_template)))
5923         {
5924           tree previous_name = CLASS_SUPER_NAME (implementation_template);
5925           const char *const name =
5926             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
5927           error ("conflicting super class name `%s'",
5928                  IDENTIFIER_POINTER (super_name));
5929           error ("previous declaration of `%s'", name);
5930         }
5931
5932       else if (! super_name)
5933         {
5934           CLASS_SUPER_NAME (objc_implementation_context) 
5935             = CLASS_SUPER_NAME (implementation_template);
5936         }
5937     }
5938
5939   else if (code == CLASS_INTERFACE_TYPE)
5940     {
5941       if (lookup_interface (class_name))
5942         warning ("duplicate interface declaration for class `%s'",
5943                  IDENTIFIER_POINTER (class_name));
5944       else
5945         add_class (class);
5946
5947       if (protocol_list)
5948         CLASS_PROTOCOL_LIST (class)
5949           = lookup_and_install_protocols (protocol_list);
5950     }
5951
5952   else if (code == CATEGORY_INTERFACE_TYPE)
5953     {
5954       tree class_category_is_assoc_with;
5955
5956       /* For a category, class_name is really the name of the class that
5957          the following set of methods will be associated with. We must
5958          find the interface so that can derive the objects template.  */
5959
5960       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
5961         {
5962           error ("cannot find interface declaration for `%s'",
5963                  IDENTIFIER_POINTER (class_name));
5964           exit (FATAL_EXIT_CODE);
5965         }
5966       else
5967         add_category (class_category_is_assoc_with, class);
5968
5969       if (protocol_list)
5970         CLASS_PROTOCOL_LIST (class)
5971           = lookup_and_install_protocols (protocol_list);
5972     }
5973
5974   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
5975     {
5976       /* Pre-build the following entities for speed/convenience.  */
5977       if (!self_id)
5978         self_id = get_identifier ("self");
5979       if (!ucmd_id)
5980         ucmd_id = get_identifier ("_cmd");
5981       if (!unused_list)
5982         unused_list
5983           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
5984       if (!objc_super_template)
5985         objc_super_template = build_super_template ();
5986
5987       /* Reset for multiple classes per file.  */
5988       method_slot = 0;
5989
5990       objc_implementation_context = class;
5991
5992       /* For a category, class_name is really the name of the class that
5993          the following set of methods will be associated with.  We must
5994          find the interface so that can derive the objects template.  */
5995
5996       if (!(implementation_template = lookup_interface (class_name)))
5997         {
5998           error ("cannot find interface declaration for `%s'",
5999                  IDENTIFIER_POINTER (class_name));
6000           exit (FATAL_EXIT_CODE);
6001         }
6002     }
6003   return class;
6004 }
6005
6006 tree
6007 continue_class (class)
6008      tree class;
6009 {
6010   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6011       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6012     {
6013       struct imp_entry *imp_entry;
6014       tree ivar_context;
6015
6016       /* Check consistency of the instance variables.  */
6017
6018       if (CLASS_IVARS (class))
6019         check_ivars (implementation_template, class);
6020
6021       /* code generation */
6022
6023       ivar_context = build_private_template (implementation_template);
6024
6025       if (!objc_class_template)
6026         build_class_template ();
6027
6028       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6029
6030       imp_entry->next = imp_list;
6031       imp_entry->imp_context = class;
6032       imp_entry->imp_template = implementation_template;
6033
6034       synth_forward_declarations ();
6035       imp_entry->class_decl = UOBJC_CLASS_decl;
6036       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6037
6038       /* Append to front and increment count.  */
6039       imp_list = imp_entry;
6040       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6041         imp_count++;
6042       else
6043         cat_count++;
6044
6045       return ivar_context;
6046     }
6047
6048   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6049     {
6050       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6051
6052       if (!TYPE_FIELDS (record))
6053         {
6054           finish_struct (record, get_class_ivars (class), NULL_TREE);
6055           CLASS_STATIC_TEMPLATE (class) = record;
6056
6057           /* Mark this record as a class template for static typing.  */
6058           TREE_STATIC_TEMPLATE (record) = 1;
6059         }
6060
6061       return NULL_TREE;
6062     }
6063
6064   else
6065     return error_mark_node;
6066 }
6067
6068 /* This is called once we see the "@end" in an interface/implementation.  */
6069
6070 void
6071 finish_class (class)
6072      tree class;
6073 {
6074   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6075     {
6076       /* All code generation is done in finish_objc.  */
6077
6078       if (implementation_template != objc_implementation_context)
6079         {
6080           /* Ensure that all method listed in the interface contain bodies.  */
6081           check_methods (CLASS_CLS_METHODS (implementation_template),
6082                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6083           check_methods (CLASS_NST_METHODS (implementation_template),
6084                          CLASS_NST_METHODS (objc_implementation_context), '-');
6085
6086           if (CLASS_PROTOCOL_LIST (implementation_template))
6087             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6088                              "class",
6089                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6090         }
6091     }
6092
6093   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6094     {
6095       tree category = CLASS_CATEGORY_LIST (implementation_template);
6096
6097       /* Find the category interface from the class it is associated with.  */
6098       while (category)
6099         {
6100           if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6101             break;
6102           category = CLASS_CATEGORY_LIST (category);
6103         }
6104
6105       if (category)
6106         {
6107           /* Ensure all method listed in the interface contain bodies.  */
6108           check_methods (CLASS_CLS_METHODS (category),
6109                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6110           check_methods (CLASS_NST_METHODS (category),
6111                          CLASS_NST_METHODS (objc_implementation_context), '-');
6112
6113           if (CLASS_PROTOCOL_LIST (category))
6114             check_protocols (CLASS_PROTOCOL_LIST (category),
6115                              "category",
6116                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6117         }
6118     }
6119
6120   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6121     {
6122       tree decl_specs;
6123       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6124       char *string = (char *) alloca (strlen (class_name) + 3);
6125
6126       /* extern struct objc_object *_<my_name>; */
6127
6128       sprintf (string, "_%s", class_name);
6129
6130       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6131       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6132       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6133                    decl_specs);
6134     }
6135 }
6136
6137 static tree
6138 add_protocol (protocol)
6139      tree protocol;
6140 {
6141   /* Put protocol on list in reverse order.  */
6142   TREE_CHAIN (protocol) = protocol_chain;
6143   protocol_chain = protocol;
6144   return protocol_chain;
6145 }
6146
6147 static tree
6148 lookup_protocol (ident)
6149      tree ident;
6150 {
6151   tree chain;
6152
6153   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6154     if (ident == PROTOCOL_NAME (chain))
6155       return chain;
6156
6157   return NULL_TREE;
6158 }
6159
6160 /* This function forward declares the protocols named by NAMES.  If
6161    they are already declared or defined, the function has no effect.  */
6162
6163 void
6164 objc_declare_protocols (names)
6165      tree names;
6166 {
6167   tree list;
6168
6169   for (list = names; list; list = TREE_CHAIN (list))
6170     {
6171       tree name = TREE_VALUE (list);
6172
6173       if (lookup_protocol (name) == NULL_TREE)
6174         {
6175           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6176
6177           TYPE_BINFO (protocol) = make_tree_vec (2);
6178           PROTOCOL_NAME (protocol) = name;
6179           PROTOCOL_LIST (protocol) = NULL_TREE;
6180           add_protocol (protocol);
6181           PROTOCOL_DEFINED (protocol) = 0;
6182           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6183         }
6184     }
6185 }
6186
6187 tree
6188 start_protocol (code, name, list)
6189      enum tree_code code;
6190      tree name;
6191      tree list;
6192 {
6193   tree protocol;
6194
6195   /* This is as good a place as any.  Need to invoke
6196      push_tag_toplevel.  */
6197   if (!objc_protocol_template)
6198     objc_protocol_template = build_protocol_template ();
6199
6200   protocol = lookup_protocol (name);
6201
6202   if (!protocol)
6203     {
6204       protocol = make_node (code);
6205       TYPE_BINFO (protocol) = make_tree_vec (2);
6206
6207       PROTOCOL_NAME (protocol) = name;
6208       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6209       add_protocol (protocol);
6210       PROTOCOL_DEFINED (protocol) = 1;
6211       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6212
6213       check_protocol_recursively (protocol, list);
6214     }
6215   else if (! PROTOCOL_DEFINED (protocol))
6216     {
6217       PROTOCOL_DEFINED (protocol) = 1;
6218       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6219
6220       check_protocol_recursively (protocol, list);
6221     }
6222   else
6223     {
6224       warning ("duplicate declaration for protocol `%s'",
6225                IDENTIFIER_POINTER (name));
6226     }
6227   return protocol;
6228 }
6229
6230 void
6231 finish_protocol (protocol)
6232      tree protocol ATTRIBUTE_UNUSED;
6233 {
6234 }
6235
6236 \f
6237 /* "Encode" a data type into a string, which grows in util_obstack.
6238    ??? What is the FORMAT?  Someone please document this!  */
6239
6240 static void
6241 encode_type_qualifiers (declspecs)
6242      tree declspecs;
6243 {
6244   tree spec;
6245
6246   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6247     {
6248       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6249         obstack_1grow (&util_obstack, 'r');
6250       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6251         obstack_1grow (&util_obstack, 'n');
6252       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6253         obstack_1grow (&util_obstack, 'N');
6254       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6255         obstack_1grow (&util_obstack, 'o');
6256       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6257         obstack_1grow (&util_obstack, 'O');
6258       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6259         obstack_1grow (&util_obstack, 'R');
6260       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6261         obstack_1grow (&util_obstack, 'V');
6262     }
6263 }
6264
6265 /* Encode a pointer type.  */
6266
6267 static void
6268 encode_pointer (type, curtype, format)
6269      tree type;
6270      int curtype;
6271      int format;
6272 {
6273   tree pointer_to = TREE_TYPE (type);
6274
6275   if (TREE_CODE (pointer_to) == RECORD_TYPE)
6276     {
6277       if (TYPE_NAME (pointer_to)
6278           && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6279         {
6280           const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6281
6282           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6283             {
6284               obstack_1grow (&util_obstack, '@');
6285               return;
6286             }
6287           else if (TREE_STATIC_TEMPLATE (pointer_to))
6288             {
6289               if (generating_instance_variables)
6290                 {
6291                   obstack_1grow (&util_obstack, '@');
6292                   obstack_1grow (&util_obstack, '"');
6293                   obstack_grow (&util_obstack, name, strlen (name));
6294                   obstack_1grow (&util_obstack, '"');
6295                   return;
6296                 }
6297               else
6298                 {
6299                   obstack_1grow (&util_obstack, '@');
6300                   return;
6301                 }
6302             }
6303           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6304             {
6305               obstack_1grow (&util_obstack, '#');
6306               return;
6307             }
6308           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6309             {
6310               obstack_1grow (&util_obstack, ':');
6311               return;
6312             }
6313         }
6314     }
6315   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6316            && TYPE_MODE (pointer_to) == QImode)
6317     {
6318       obstack_1grow (&util_obstack, '*');
6319       return;
6320     }
6321
6322   /* We have a type that does not get special treatment.  */
6323
6324   /* NeXT extension */
6325   obstack_1grow (&util_obstack, '^');
6326   encode_type (pointer_to, curtype, format);
6327 }
6328
6329 static void
6330 encode_array (type, curtype, format)
6331      tree type;
6332      int curtype;
6333      int format;
6334 {
6335   tree an_int_cst = TYPE_SIZE (type);
6336   tree array_of = TREE_TYPE (type);
6337   char buffer[40];
6338
6339   /* An incomplete array is treated like a pointer.  */
6340   if (an_int_cst == NULL)
6341     {
6342       encode_pointer (type, curtype, format);
6343       return;
6344     }
6345
6346   sprintf (buffer, "[%ld",
6347            (long) (TREE_INT_CST_LOW (an_int_cst)
6348                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6349
6350   obstack_grow (&util_obstack, buffer, strlen (buffer));
6351   encode_type (array_of, curtype, format);
6352   obstack_1grow (&util_obstack, ']');
6353   return;
6354 }
6355 \f
6356 static void
6357 encode_aggregate_within (type, curtype, format, left, right)
6358      tree type;
6359      int curtype;
6360      int format;
6361      int left;
6362      int right;
6363 {
6364   /* The RECORD_TYPE may in fact be a typedef!  For purposes
6365      of encoding, we need the real underlying enchilada.  */
6366   if (TYPE_MAIN_VARIANT (type))
6367     type = TYPE_MAIN_VARIANT (type);
6368
6369   if (obstack_object_size (&util_obstack) > 0
6370       && *(obstack_next_free (&util_obstack) - 1) == '^')
6371     {
6372       tree name = TYPE_NAME (type);
6373
6374       /* we have a reference; this is a NeXT extension.  */
6375
6376       if (obstack_object_size (&util_obstack) - curtype == 1
6377           && format == OBJC_ENCODE_INLINE_DEFS)
6378         {
6379           /* Output format of struct for first level only.  */
6380           tree fields = TYPE_FIELDS (type);
6381
6382           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6383             {
6384               obstack_1grow (&util_obstack, left);
6385               obstack_grow (&util_obstack,
6386                             IDENTIFIER_POINTER (name),
6387                             strlen (IDENTIFIER_POINTER (name)));
6388               obstack_1grow (&util_obstack, '=');
6389             }
6390           else
6391             {
6392               obstack_1grow (&util_obstack, left);
6393               obstack_grow (&util_obstack, "?=", 2);
6394             }
6395
6396           for ( ; fields; fields = TREE_CHAIN (fields))
6397               encode_field_decl (fields, curtype, format);
6398
6399           obstack_1grow (&util_obstack, right);
6400         }
6401
6402       else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6403         {
6404           obstack_1grow (&util_obstack, left);
6405           obstack_grow (&util_obstack,
6406                         IDENTIFIER_POINTER (name),
6407                         strlen (IDENTIFIER_POINTER (name)));
6408           obstack_1grow (&util_obstack, right);
6409         }
6410
6411       else
6412         {
6413           /* We have an untagged structure or a typedef.  */
6414           obstack_1grow (&util_obstack, left);
6415           obstack_1grow (&util_obstack, '?');
6416           obstack_1grow (&util_obstack, right);
6417         }
6418     }
6419
6420   else
6421     {
6422       tree name = TYPE_NAME (type);
6423       tree fields = TYPE_FIELDS (type);
6424
6425       if (format == OBJC_ENCODE_INLINE_DEFS
6426           || generating_instance_variables)
6427         {
6428           obstack_1grow (&util_obstack, left);
6429           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6430               obstack_grow (&util_obstack,
6431                           IDENTIFIER_POINTER (name),
6432                           strlen (IDENTIFIER_POINTER (name)));
6433           else
6434               obstack_1grow (&util_obstack, '?');
6435
6436           obstack_1grow (&util_obstack, '=');
6437
6438           for (; fields; fields = TREE_CHAIN (fields))
6439             {
6440               if (generating_instance_variables)
6441                 {
6442                   tree fname = DECL_NAME (fields);
6443
6444                   obstack_1grow (&util_obstack, '"');
6445                   if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6446                     {
6447                       obstack_grow (&util_obstack,
6448                                     IDENTIFIER_POINTER (fname),
6449                                     strlen (IDENTIFIER_POINTER (fname)));
6450                     }
6451
6452                   obstack_1grow (&util_obstack, '"');
6453                 }
6454
6455               encode_field_decl (fields, curtype, format);
6456             }
6457
6458           obstack_1grow (&util_obstack, right);
6459         }
6460
6461       else
6462         {
6463           obstack_1grow (&util_obstack, left);
6464           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6465               obstack_grow (&util_obstack,
6466                             IDENTIFIER_POINTER (name),
6467                             strlen (IDENTIFIER_POINTER (name)));
6468           else
6469               /* We have an untagged structure or a typedef.  */
6470               obstack_1grow (&util_obstack, '?');
6471
6472           obstack_1grow (&util_obstack, right);
6473         }
6474     }
6475 }
6476
6477 static void
6478 encode_aggregate (type, curtype, format)
6479      tree type;
6480      int curtype;
6481      int format;
6482 {
6483   enum tree_code code = TREE_CODE (type);
6484
6485   switch (code)
6486     {
6487     case RECORD_TYPE:
6488       {
6489         encode_aggregate_within(type, curtype, format, '{', '}');
6490         break;
6491       }
6492     case UNION_TYPE:
6493       {
6494         encode_aggregate_within(type, curtype, format, '(', ')');
6495         break;
6496       }
6497
6498     case ENUMERAL_TYPE:
6499       obstack_1grow (&util_obstack, 'i');
6500       break;
6501
6502     default:
6503       break;
6504     }
6505 }
6506
6507 /* Support bitfields.  The current version of Objective-C does not support
6508    them.  The string will consist of one or more "b:n"'s where n is an
6509    integer describing the width of the bitfield. Currently, classes in
6510    the kit implement a method "-(char *)describeBitfieldStruct:" that
6511    simulates this. If they do not implement this method, the archiver
6512    assumes the bitfield is 16 bits wide (padded if necessary) and packed
6513    according to the GNU compiler. After looking at the "kit", it appears
6514    that all classes currently rely on this default behavior, rather than
6515    hand generating this string (which is tedious).  */
6516
6517 static void
6518 encode_bitfield (width)
6519      int width;
6520 {
6521   char buffer[40];
6522   sprintf (buffer, "b%d", width);
6523   obstack_grow (&util_obstack, buffer, strlen (buffer));
6524 }
6525 \f
6526 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
6527
6528 static void
6529 encode_type (type, curtype, format)
6530      tree type;
6531      int curtype;
6532      int format;
6533 {
6534   enum tree_code code = TREE_CODE (type);
6535
6536   if (code == INTEGER_TYPE)
6537     {
6538       if (integer_zerop (TYPE_MIN_VALUE (type)))
6539         {
6540           /* Unsigned integer types.  */
6541
6542           if (TYPE_MODE (type) == QImode)
6543             obstack_1grow (&util_obstack, 'C');
6544           else if (TYPE_MODE (type) == HImode)
6545             obstack_1grow (&util_obstack, 'S');
6546           else if (TYPE_MODE (type) == SImode)
6547             {
6548               if (type == long_unsigned_type_node)
6549                 obstack_1grow (&util_obstack, 'L');
6550               else
6551                 obstack_1grow (&util_obstack, 'I');
6552             }
6553           else if (TYPE_MODE (type) == DImode)
6554             obstack_1grow (&util_obstack, 'Q');
6555         }
6556
6557       else
6558         /* Signed integer types.  */
6559         {
6560           if (TYPE_MODE (type) == QImode)
6561             obstack_1grow (&util_obstack, 'c');
6562           else if (TYPE_MODE (type) == HImode)
6563             obstack_1grow (&util_obstack, 's');
6564           else if (TYPE_MODE (type) == SImode)
6565             {
6566               if (type == long_integer_type_node)
6567                 obstack_1grow (&util_obstack, 'l');
6568               else
6569                 obstack_1grow (&util_obstack, 'i');
6570             }
6571
6572           else if (TYPE_MODE (type) == DImode)
6573             obstack_1grow (&util_obstack, 'q');
6574         }
6575     }
6576
6577   else if (code == REAL_TYPE)
6578     {
6579       /* Floating point types.  */
6580
6581       if (TYPE_MODE (type) == SFmode)
6582         obstack_1grow (&util_obstack, 'f');
6583       else if (TYPE_MODE (type) == DFmode
6584                || TYPE_MODE (type) == TFmode)
6585         obstack_1grow (&util_obstack, 'd');
6586     }
6587
6588   else if (code == VOID_TYPE)
6589     obstack_1grow (&util_obstack, 'v');
6590
6591   else if (code == ARRAY_TYPE)
6592     encode_array (type, curtype, format);
6593
6594   else if (code == POINTER_TYPE)
6595     encode_pointer (type, curtype, format);
6596
6597   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6598     encode_aggregate (type, curtype, format);
6599
6600   else if (code == FUNCTION_TYPE) /* '?' */
6601     obstack_1grow (&util_obstack, '?');
6602 }
6603
6604 static void
6605 encode_complete_bitfield (position, type, size)
6606      int position;
6607      tree type;
6608      int size;
6609 {
6610   enum tree_code code = TREE_CODE (type);
6611   char buffer[40];
6612   char charType = '?';
6613
6614   if (code == INTEGER_TYPE)
6615     {
6616       if (integer_zerop (TYPE_MIN_VALUE (type)))
6617         {
6618           /* Unsigned integer types.  */
6619
6620           if (TYPE_MODE (type) == QImode)
6621             charType = 'C';
6622           else if (TYPE_MODE (type) == HImode)
6623             charType = 'S';
6624           else if (TYPE_MODE (type) == SImode)
6625             {
6626               if (type == long_unsigned_type_node)
6627                 charType = 'L';
6628               else
6629                 charType = 'I';
6630             }
6631           else if (TYPE_MODE (type) == DImode)
6632             charType = 'Q';
6633         }
6634
6635       else
6636         /* Signed integer types.  */
6637         {
6638           if (TYPE_MODE (type) == QImode)
6639             charType = 'c';
6640           else if (TYPE_MODE (type) == HImode)
6641             charType = 's';
6642           else if (TYPE_MODE (type) == SImode)
6643             {
6644               if (type == long_integer_type_node)
6645                 charType = 'l';
6646               else
6647                 charType = 'i';
6648             }
6649
6650           else if (TYPE_MODE (type) == DImode)
6651             charType = 'q';
6652         }
6653     }
6654   else if (code == ENUMERAL_TYPE)
6655     charType = 'i';
6656   else
6657     abort ();
6658
6659   sprintf (buffer, "b%d%c%d", position, charType, size);
6660   obstack_grow (&util_obstack, buffer, strlen (buffer));
6661 }
6662
6663 static void
6664 encode_field_decl (field_decl, curtype, format)
6665      tree field_decl;
6666      int curtype;
6667      int format;
6668 {
6669   tree type;
6670
6671   type = TREE_TYPE (field_decl);
6672
6673   /* If this field is obviously a bitfield, or is a bitfield that has been
6674      clobbered to look like a ordinary integer mode, go ahead and generate
6675      the bitfield typing information.  */
6676   if (flag_next_runtime)
6677     {
6678       if (DECL_BIT_FIELD_TYPE (field_decl))
6679         encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6680       else
6681         encode_type (TREE_TYPE (field_decl), curtype, format);
6682     }
6683   else
6684     {
6685       if (DECL_BIT_FIELD_TYPE (field_decl))
6686         encode_complete_bitfield (int_bit_position (field_decl),
6687                                   DECL_BIT_FIELD_TYPE (field_decl),
6688                                   tree_low_cst (DECL_SIZE (field_decl), 1));
6689       else
6690         encode_type (TREE_TYPE (field_decl), curtype, format);
6691     }
6692 }
6693
6694 static tree
6695 expr_last (complex_expr)
6696      tree complex_expr;
6697 {
6698   tree next;
6699
6700   if (complex_expr)
6701     while ((next = TREE_OPERAND (complex_expr, 0)))
6702       complex_expr = next;
6703
6704   return complex_expr;
6705 }
6706 \f
6707 /* Transform a method definition into a function definition as follows:
6708    - synthesize the first two arguments, "self" and "_cmd".  */
6709
6710 void
6711 start_method_def (method)
6712      tree method;
6713 {
6714   tree decl_specs;
6715
6716   /* Required to implement _msgSuper.  */
6717   objc_method_context = method;
6718   UOBJC_SUPER_decl = NULL_TREE;
6719
6720   /* Must be called BEFORE start_function.  */
6721   pushlevel (0);
6722
6723   /* Generate prototype declarations for arguments..."new-style".  */
6724
6725   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
6726     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6727   else
6728     /* Really a `struct objc_class *'. However, we allow people to
6729        assign to self, which changes its type midstream.  */
6730     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6731
6732   push_parm_decl (build_tree_list
6733                   (build_tree_list (decl_specs,
6734                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
6735                    unused_list));
6736
6737   decl_specs = build_tree_list (NULL_TREE,
6738                                 xref_tag (RECORD_TYPE,
6739                                           get_identifier (TAG_SELECTOR)));
6740   push_parm_decl (build_tree_list
6741                   (build_tree_list (decl_specs,
6742                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6743                    unused_list));
6744
6745   /* Generate argument declarations if a keyword_decl.  */
6746   if (METHOD_SEL_ARGS (method))
6747     {
6748       tree arglist = METHOD_SEL_ARGS (method);
6749       do
6750         {
6751           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6752           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6753
6754           if (arg_decl)
6755             {
6756               tree last_expr = expr_last (arg_decl);
6757
6758               /* Unite the abstract decl with its name.  */
6759               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6760               push_parm_decl (build_tree_list
6761                               (build_tree_list (arg_spec, arg_decl),
6762                                NULL_TREE));
6763
6764               /* Unhook: restore the abstract declarator.  */
6765               TREE_OPERAND (last_expr, 0) = NULL_TREE;
6766             }
6767
6768           else
6769             push_parm_decl (build_tree_list
6770                             (build_tree_list (arg_spec,
6771                                               KEYWORD_ARG_NAME (arglist)),
6772                              NULL_TREE));
6773
6774           arglist = TREE_CHAIN (arglist);
6775         }
6776       while (arglist);
6777     }
6778
6779   if (METHOD_ADD_ARGS (method) != NULL_TREE
6780       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
6781     {
6782       /* We have a variable length selector - in "prototype" format.  */
6783       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6784       while (akey)
6785         {
6786           /* This must be done prior to calling pushdecl.  pushdecl is
6787              going to change our chain on us.  */
6788           tree nextkey = TREE_CHAIN (akey);
6789           pushdecl (akey);
6790           akey = nextkey;
6791         }
6792     }
6793 }
6794
6795 static void
6796 warn_with_method (message, mtype, method)
6797      const char *message;
6798      int mtype;
6799      tree method;
6800 {
6801   if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
6802     return;
6803
6804   diagnostic_report_current_function (global_dc);
6805
6806   /* Add a readable method name to the warning.  */
6807   warning_with_file_and_line (DECL_SOURCE_FILE (method),
6808                               DECL_SOURCE_LINE (method),
6809                               "%s `%c%s'",
6810                               message, mtype,
6811                               gen_method_decl (method, errbuf));
6812 }
6813
6814 /* Return 1 if METHOD is consistent with PROTO.  */
6815
6816 static int
6817 comp_method_with_proto (method, proto)
6818      tree method, proto;
6819 {
6820   /* Create a function template node at most once.  */
6821   if (!function1_template)
6822     function1_template = make_node (FUNCTION_TYPE);
6823
6824   /* Install argument types - normally set by build_function_type.  */
6825   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
6826
6827   /* install return type */
6828   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
6829
6830   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
6831 }
6832
6833 /* Return 1 if PROTO1 is consistent with PROTO2.  */
6834
6835 static int
6836 comp_proto_with_proto (proto0, proto1)
6837      tree proto0, proto1;
6838 {
6839   /* Create a couple of function_template nodes at most once.  */
6840   if (!function1_template)
6841     function1_template = make_node (FUNCTION_TYPE);
6842   if (!function2_template)
6843     function2_template = make_node (FUNCTION_TYPE);
6844
6845   /* Install argument types; normally set by build_function_type.  */
6846   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
6847   TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
6848
6849   /* Install return type.  */
6850   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
6851   TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
6852
6853   return comptypes (function1_template, function2_template);
6854 }
6855
6856 /* - Generate an identifier for the function. the format is "_n_cls",
6857      where 1 <= n <= nMethods, and cls is the name the implementation we
6858      are processing.
6859    - Install the return type from the method declaration.
6860    - If we have a prototype, check for type consistency.  */
6861
6862 static void
6863 really_start_method (method, parmlist)
6864      tree method, parmlist;
6865 {
6866   tree sc_spec, ret_spec, ret_decl, decl_specs;
6867   tree method_decl, method_id;
6868   const char *sel_name, *class_name, *cat_name;
6869   char *buf;
6870
6871   /* Synth the storage class & assemble the return type.  */
6872   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
6873   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
6874   decl_specs = chainon (sc_spec, ret_spec);
6875
6876   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
6877   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
6878   cat_name = ((TREE_CODE (objc_implementation_context)
6879                == CLASS_IMPLEMENTATION_TYPE)
6880               ? NULL
6881               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6882   method_slot++;
6883
6884   /* Make sure this is big enough for any plausible method label.  */
6885   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
6886                          + (cat_name ? strlen (cat_name) : 0));
6887
6888   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
6889                          class_name, cat_name, sel_name, method_slot);
6890
6891   method_id = get_identifier (buf);
6892
6893   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
6894
6895   /* Check the declarator portion of the return type for the method.  */
6896   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
6897     {
6898       /* Unite the complex decl (specified in the abstract decl) with the
6899          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
6900       tree save_expr = expr_last (ret_decl);
6901
6902       TREE_OPERAND (save_expr, 0) = method_decl;
6903       method_decl = ret_decl;
6904
6905       /* Fool the parser into thinking it is starting a function.  */
6906       start_function (decl_specs, method_decl, NULL_TREE);
6907
6908       /* Unhook: this has the effect of restoring the abstract declarator.  */
6909       TREE_OPERAND (save_expr, 0) = NULL_TREE;
6910     }
6911
6912   else
6913     {
6914       TREE_VALUE (TREE_TYPE (method)) = method_decl;
6915
6916       /* Fool the parser into thinking it is starting a function.  */
6917       start_function (decl_specs, method_decl, NULL_TREE);
6918
6919       /* Unhook: this has the effect of restoring the abstract declarator.  */
6920       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
6921     }
6922
6923   METHOD_DEFINITION (method) = current_function_decl;
6924
6925   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
6926
6927   if (implementation_template != objc_implementation_context)
6928     {
6929       tree proto;
6930
6931       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
6932         proto = lookup_instance_method_static (implementation_template,
6933                                                METHOD_SEL_NAME (method));
6934       else
6935         proto = lookup_class_method_static (implementation_template,
6936                                             METHOD_SEL_NAME (method));
6937
6938       if (proto && ! comp_method_with_proto (method, proto))
6939         {
6940           char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
6941
6942           warn_with_method ("conflicting types for", type, method);
6943           warn_with_method ("previous declaration of", type, proto);
6944         }
6945     }
6946 }
6947
6948 /* The following routine is always called...this "architecture" is to
6949    accommodate "old-style" variable length selectors.
6950  
6951    - a:a b:b // prototype  ; id c; id d; // old-style.  */
6952
6953 void
6954 continue_method_def ()
6955 {
6956   tree parmlist;
6957
6958   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
6959     /* We have a `, ...' immediately following the selector.  */
6960     parmlist = get_parm_info (0);
6961   else
6962     parmlist = get_parm_info (1); /* place a `void_at_end' */
6963
6964   /* Set self_decl from the first argument...this global is used by
6965      build_ivar_reference calling build_indirect_ref.  */
6966   self_decl = TREE_PURPOSE (parmlist);
6967
6968   poplevel (0, 0, 0);
6969   really_start_method (objc_method_context, parmlist);
6970   store_parm_decls ();
6971 }
6972
6973 /* Called by the parser, from the `pushlevel' production.  */
6974
6975 void
6976 add_objc_decls ()
6977 {
6978   if (!UOBJC_SUPER_decl)
6979     {
6980       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
6981                                      build_tree_list (NULL_TREE,
6982                                                       objc_super_template),
6983                                      0, NULL_TREE);
6984
6985       finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
6986
6987       /* This prevents `unused variable' warnings when compiling with -Wall.  */
6988       TREE_USED (UOBJC_SUPER_decl) = 1;
6989       DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
6990     }
6991 }
6992
6993 /* _n_Method (id self, SEL sel, ...)
6994      {
6995        struct objc_super _S;
6996        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
6997      }  */
6998
6999 tree
7000 get_super_receiver ()
7001 {
7002   if (objc_method_context)
7003     {
7004       tree super_expr, super_expr_list;
7005
7006       /* Set receiver to self.  */
7007       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7008       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7009       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7010
7011       /* Set class to begin searching.  */
7012       super_expr = build_component_ref (UOBJC_SUPER_decl,
7013                                         get_identifier ("class"));
7014
7015       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7016         {
7017           /* [_cls, __cls]Super are "pre-built" in
7018              synth_forward_declarations.  */
7019
7020           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7021                                           ((TREE_CODE (objc_method_context)
7022                                             == INSTANCE_METHOD_DECL)
7023                                            ? ucls_super_ref
7024                                            : uucls_super_ref));
7025         }
7026
7027       else
7028         /* We have a category.  */
7029         {
7030           tree super_name = CLASS_SUPER_NAME (implementation_template);
7031           tree super_class;
7032
7033           /* Barf if super used in a category of Object.  */
7034           if (!super_name)
7035             {
7036               error ("no super class declared in interface for `%s'",
7037                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7038               return error_mark_node;
7039             }
7040
7041           if (flag_next_runtime)
7042             {
7043               super_class = get_class_reference (super_name);
7044               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7045                 super_class
7046                   = build_component_ref (build_indirect_ref (super_class, "->"),
7047                                          get_identifier ("isa"));
7048             }
7049           else
7050             {
7051               add_class_reference (super_name);
7052               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7053                              ? objc_get_class_decl : objc_get_meta_class_decl);
7054               assemble_external (super_class);
7055               super_class
7056                 = build_function_call
7057                   (super_class,
7058                    build_tree_list
7059                    (NULL_TREE,
7060                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7061                                      IDENTIFIER_POINTER (super_name))));
7062             }
7063
7064           TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7065           super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7066         }
7067
7068       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7069
7070       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7071       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7072
7073       return build_compound_expr (super_expr_list);
7074     }
7075   else
7076     {
7077       error ("[super ...] must appear in a method context");
7078       return error_mark_node;
7079     }
7080 }
7081
7082 static tree
7083 encode_method_def (func_decl)
7084       tree func_decl;
7085 {
7086   tree parms;
7087   int stack_size;
7088   HOST_WIDE_INT max_parm_end = 0;
7089   char buffer[40];
7090   tree result;
7091
7092   /* Return type.  */
7093   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7094                obstack_object_size (&util_obstack),
7095                OBJC_ENCODE_INLINE_DEFS);
7096
7097   /* Stack size.  */
7098   for (parms = DECL_ARGUMENTS (func_decl); parms;
7099        parms = TREE_CHAIN (parms))
7100     {
7101       HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7102                                 + int_size_in_bytes (TREE_TYPE (parms)));
7103
7104       if (! offset_is_register && parm_end > max_parm_end)
7105         max_parm_end = parm_end;
7106     }
7107
7108   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7109
7110   sprintf (buffer, "%d", stack_size);
7111   obstack_grow (&util_obstack, buffer, strlen (buffer));
7112
7113   /* Argument types.  */
7114   for (parms = DECL_ARGUMENTS (func_decl); parms;
7115        parms = TREE_CHAIN (parms))
7116     {
7117       /* Type.  */
7118       encode_type (TREE_TYPE (parms),
7119                    obstack_object_size (&util_obstack),
7120                    OBJC_ENCODE_INLINE_DEFS);
7121
7122       /* Compute offset.  */
7123       sprintf (buffer, "%d", forwarding_offset (parms));
7124
7125       /* Indicate register.  */
7126       if (offset_is_register)
7127         obstack_1grow (&util_obstack, '+');
7128
7129       obstack_grow (&util_obstack, buffer, strlen (buffer));
7130     }
7131
7132   /* Null terminate string.  */
7133   obstack_1grow (&util_obstack, 0);
7134   result = get_identifier (obstack_finish (&util_obstack));
7135   obstack_free (&util_obstack, util_firstobj);
7136   return result;
7137 }
7138
7139 static void
7140 objc_expand_function_end ()
7141 {
7142   METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
7143 }
7144
7145 void
7146 finish_method_def ()
7147 {
7148   lang_expand_function_end = objc_expand_function_end;
7149   finish_function (0, 1);
7150   lang_expand_function_end = NULL;
7151
7152   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7153      since the optimizer may find "may be used before set" errors.  */
7154   objc_method_context = NULL_TREE;
7155 }
7156
7157 #if 0
7158 int
7159 lang_report_error_function (decl)
7160       tree decl;
7161 {
7162   if (objc_method_context)
7163     {
7164       fprintf (stderr, "In method `%s'\n",
7165                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7166       return 1;
7167     }
7168
7169   else
7170     return 0;
7171 }
7172 #endif
7173
7174 static int
7175 is_complex_decl (type)
7176      tree type;
7177 {
7178   return (TREE_CODE (type) == ARRAY_TYPE
7179           || TREE_CODE (type) == FUNCTION_TYPE
7180           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7181 }
7182
7183 \f
7184 /* Code to convert a decl node into text for a declaration in C.  */
7185
7186 static char tmpbuf[256];
7187
7188 static void
7189 adorn_decl (decl, str)
7190      tree decl;
7191      char *str;
7192 {
7193   enum tree_code code = TREE_CODE (decl);
7194
7195   if (code == ARRAY_REF)
7196     {
7197       tree an_int_cst = TREE_OPERAND (decl, 1);
7198
7199       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7200         sprintf (str + strlen (str), "[%ld]",
7201                  (long) TREE_INT_CST_LOW (an_int_cst));
7202       else
7203         strcat (str, "[]");
7204     }
7205
7206   else if (code == ARRAY_TYPE)
7207     {
7208       tree an_int_cst = TYPE_SIZE (decl);
7209       tree array_of = TREE_TYPE (decl);
7210
7211       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7212         sprintf (str + strlen (str), "[%ld]",
7213                  (long) (TREE_INT_CST_LOW (an_int_cst)
7214                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7215       else
7216         strcat (str, "[]");
7217     }
7218
7219   else if (code == CALL_EXPR)
7220     {
7221       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7222
7223       strcat (str, "(");
7224       while (chain)
7225         {
7226           gen_declaration_1 (chain, str);
7227           chain = TREE_CHAIN (chain);
7228           if (chain)
7229             strcat (str, ", ");
7230         }
7231       strcat (str, ")");
7232     }
7233
7234   else if (code == FUNCTION_TYPE)
7235     {
7236       tree chain  = TYPE_ARG_TYPES (decl);
7237
7238       strcat (str, "(");
7239       while (chain && TREE_VALUE (chain) != void_type_node)
7240         {
7241           gen_declaration_1 (TREE_VALUE (chain), str);
7242           chain = TREE_CHAIN (chain);
7243           if (chain && TREE_VALUE (chain) != void_type_node)
7244             strcat (str, ", ");
7245         }
7246       strcat (str, ")");
7247     }
7248
7249   else if (code == INDIRECT_REF)
7250     {
7251       strcpy (tmpbuf, "*");
7252       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7253         {
7254           tree chain;
7255
7256           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7257                chain;
7258                chain = TREE_CHAIN (chain))
7259             {
7260               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7261                 {
7262                   strcat (tmpbuf, " ");
7263                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7264                 }
7265             }
7266           if (str[0])
7267             strcat (tmpbuf, " ");
7268         }
7269       strcat (tmpbuf, str);
7270       strcpy (str, tmpbuf);
7271     }
7272
7273   else if (code == POINTER_TYPE)
7274     {
7275       strcpy (tmpbuf, "*");
7276       if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7277         {
7278           if (TREE_READONLY (decl))
7279             strcat (tmpbuf, " const");
7280           if (TYPE_VOLATILE (decl))
7281             strcat (tmpbuf, " volatile");
7282           if (str[0])
7283             strcat (tmpbuf, " ");
7284         }
7285       strcat (tmpbuf, str);
7286       strcpy (str, tmpbuf);
7287     }
7288 }
7289
7290 static char *
7291 gen_declarator (decl, buf, name)
7292      tree decl;
7293      char *buf;
7294      const char *name;
7295 {
7296   if (decl)
7297     {
7298       enum tree_code code = TREE_CODE (decl);
7299       char *str;
7300       tree op;
7301       int wrap = 0;
7302
7303       switch (code)
7304         {
7305         case ARRAY_REF:
7306         case INDIRECT_REF:
7307         case CALL_EXPR:
7308           op = TREE_OPERAND (decl, 0);
7309
7310           /* We have a pointer to a function or array...(*)(), (*)[] */
7311           if ((code == ARRAY_REF || code == CALL_EXPR)
7312               && op && TREE_CODE (op) == INDIRECT_REF)
7313             wrap = 1;
7314
7315           str = gen_declarator (op, buf, name);
7316
7317           if (wrap)
7318             {
7319               strcpy (tmpbuf, "(");
7320               strcat (tmpbuf, str);
7321               strcat (tmpbuf, ")");
7322               strcpy (str, tmpbuf);
7323             }
7324
7325           adorn_decl (decl, str);
7326           break;
7327
7328         case ARRAY_TYPE:
7329         case FUNCTION_TYPE:
7330         case POINTER_TYPE:
7331           strcpy (buf, name);
7332           str = buf;
7333
7334           /* This clause is done iteratively rather than recursively.  */
7335           do
7336             {
7337               op = (is_complex_decl (TREE_TYPE (decl))
7338                     ? TREE_TYPE (decl) : NULL_TREE);
7339
7340               adorn_decl (decl, str);
7341
7342               /* We have a pointer to a function or array...(*)(), (*)[] */
7343               if (code == POINTER_TYPE
7344                   && op && (TREE_CODE (op) == FUNCTION_TYPE
7345                             || TREE_CODE (op) == ARRAY_TYPE))
7346                 {
7347                   strcpy (tmpbuf, "(");
7348                   strcat (tmpbuf, str);
7349                   strcat (tmpbuf, ")");
7350                   strcpy (str, tmpbuf);
7351                 }
7352
7353               decl = (is_complex_decl (TREE_TYPE (decl))
7354                       ? TREE_TYPE (decl) : NULL_TREE);
7355             }
7356
7357           while (decl && (code = TREE_CODE (decl)))
7358             ;
7359
7360           break;
7361
7362         case IDENTIFIER_NODE:
7363           /* Will only happen if we are processing a "raw" expr-decl.  */
7364           strcpy (buf, IDENTIFIER_POINTER (decl));
7365           return buf;
7366
7367         default:
7368           abort ();
7369         }
7370
7371       return str;
7372     }
7373
7374   else
7375     /* We have an abstract declarator or a _DECL node.  */
7376     {
7377       strcpy (buf, name);
7378       return buf;
7379     }
7380 }
7381
7382 static void
7383 gen_declspecs (declspecs, buf, raw)
7384      tree declspecs;
7385      char *buf;
7386      int raw;
7387 {
7388   if (raw)
7389     {
7390       tree chain;
7391
7392       for (chain = nreverse (copy_list (declspecs));
7393            chain; chain = TREE_CHAIN (chain))
7394         {
7395           tree aspec = TREE_VALUE (chain);
7396
7397           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7398             strcat (buf, IDENTIFIER_POINTER (aspec));
7399           else if (TREE_CODE (aspec) == RECORD_TYPE)
7400             {
7401               if (TYPE_NAME (aspec))
7402                 {
7403                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7404
7405                   if (! TREE_STATIC_TEMPLATE (aspec))
7406                     strcat (buf, "struct ");
7407                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7408
7409                   /* NEW!!! */
7410                   if (protocol_list)
7411                     {
7412                       tree chain = protocol_list;
7413
7414                       strcat (buf, " <");
7415                       while (chain)
7416                         {
7417                           strcat (buf,
7418                                   IDENTIFIER_POINTER
7419                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
7420                           chain = TREE_CHAIN (chain);
7421                           if (chain)
7422                             strcat (buf, ", ");
7423                         }
7424                       strcat (buf, ">");
7425                     }
7426                 }
7427
7428               else
7429                 strcat (buf, "untagged struct");
7430             }
7431
7432           else if (TREE_CODE (aspec) == UNION_TYPE)
7433             {
7434               if (TYPE_NAME (aspec))
7435                 {
7436                   if (! TREE_STATIC_TEMPLATE (aspec))
7437                     strcat (buf, "union ");
7438                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7439                 }
7440               else
7441                 strcat (buf, "untagged union");
7442             }
7443
7444           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7445             {
7446               if (TYPE_NAME (aspec))
7447                 {
7448                   if (! TREE_STATIC_TEMPLATE (aspec))
7449                     strcat (buf, "enum ");
7450                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7451                 }
7452               else
7453                 strcat (buf, "untagged enum");
7454             }
7455
7456           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7457             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7458
7459           else if (IS_ID (aspec))
7460             {
7461               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7462
7463               strcat (buf, "id");
7464               if (protocol_list)
7465                 {
7466                   tree chain = protocol_list;
7467
7468                   strcat (buf, " <");
7469                   while (chain)
7470                     {
7471                       strcat (buf,
7472                               IDENTIFIER_POINTER
7473                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7474                       chain = TREE_CHAIN (chain);
7475                       if (chain)
7476                         strcat (buf, ", ");
7477                     }
7478                   strcat (buf, ">");
7479                 }
7480             }
7481           if (TREE_CHAIN (chain))
7482             strcat (buf, " ");
7483         }
7484     }
7485   else
7486     {
7487       /* Type qualifiers.  */
7488       if (TREE_READONLY (declspecs))
7489         strcat (buf, "const ");
7490       if (TYPE_VOLATILE (declspecs))
7491         strcat (buf, "volatile ");
7492
7493       switch (TREE_CODE (declspecs))
7494         {
7495           /* Type specifiers.  */
7496
7497         case INTEGER_TYPE:
7498           declspecs = TYPE_MAIN_VARIANT (declspecs);
7499
7500           /* Signed integer types.  */
7501
7502           if (declspecs == short_integer_type_node)
7503             strcat (buf, "short int ");
7504           else if (declspecs == integer_type_node)
7505             strcat (buf, "int ");
7506           else if (declspecs == long_integer_type_node)
7507             strcat (buf, "long int ");
7508           else if (declspecs == long_long_integer_type_node)
7509             strcat (buf, "long long int ");
7510           else if (declspecs == signed_char_type_node
7511                    || declspecs == char_type_node)
7512             strcat (buf, "char ");
7513
7514           /* Unsigned integer types.  */
7515
7516           else if (declspecs == short_unsigned_type_node)
7517             strcat (buf, "unsigned short ");
7518           else if (declspecs == unsigned_type_node)
7519             strcat (buf, "unsigned int ");
7520           else if (declspecs == long_unsigned_type_node)
7521             strcat (buf, "unsigned long ");
7522           else if (declspecs == long_long_unsigned_type_node)
7523             strcat (buf, "unsigned long long ");
7524           else if (declspecs == unsigned_char_type_node)
7525             strcat (buf, "unsigned char ");
7526           break;
7527
7528         case REAL_TYPE:
7529           declspecs = TYPE_MAIN_VARIANT (declspecs);
7530
7531           if (declspecs == float_type_node)
7532             strcat (buf, "float ");
7533           else if (declspecs == double_type_node)
7534             strcat (buf, "double ");
7535           else if (declspecs == long_double_type_node)
7536             strcat (buf, "long double ");
7537           break;
7538
7539         case RECORD_TYPE:
7540           if (TYPE_NAME (declspecs)
7541               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7542             {
7543               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7544
7545               if (! TREE_STATIC_TEMPLATE (declspecs))
7546                 strcat (buf, "struct ");
7547               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7548
7549               if (protocol_list)
7550                 {
7551                   tree chain = protocol_list;
7552
7553                   strcat (buf, " <");
7554                   while (chain)
7555                     {
7556                       strcat (buf,
7557                               IDENTIFIER_POINTER
7558                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7559                       chain = TREE_CHAIN (chain);
7560                       if (chain)
7561                         strcat (buf, ", ");
7562                     }
7563                   strcat (buf, ">");
7564                 }
7565             }
7566
7567           else
7568             strcat (buf, "untagged struct");
7569
7570           strcat (buf, " ");
7571           break;
7572
7573         case UNION_TYPE:
7574           if (TYPE_NAME (declspecs)
7575               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7576             {
7577               strcat (buf, "union ");
7578               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7579               strcat (buf, " ");
7580             }
7581
7582           else
7583             strcat (buf, "untagged union ");
7584           break;
7585
7586         case ENUMERAL_TYPE:
7587           if (TYPE_NAME (declspecs)
7588               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7589             {
7590               strcat (buf, "enum ");
7591               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7592               strcat (buf, " ");
7593             }
7594
7595           else
7596             strcat (buf, "untagged enum ");
7597           break;
7598
7599         case VOID_TYPE:
7600           strcat (buf, "void ");
7601           break;
7602
7603         case POINTER_TYPE:
7604           {
7605             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7606
7607             strcat (buf, "id");
7608             if (protocol_list)
7609               {
7610                 tree chain = protocol_list;
7611
7612                 strcat (buf, " <");
7613                 while (chain)
7614                   {
7615                     strcat (buf,
7616                             IDENTIFIER_POINTER
7617                             (PROTOCOL_NAME (TREE_VALUE (chain))));
7618                     chain = TREE_CHAIN (chain);
7619                     if (chain)
7620                       strcat (buf, ", ");
7621                   }
7622
7623                 strcat (buf, ">");
7624               }
7625           }
7626           break;
7627           
7628         default:
7629           break;
7630         }
7631     }
7632 }
7633
7634 /* Given a tree node, produce a printable description of it in the given
7635    buffer, overwriting the buffer.  */
7636
7637 static char *
7638 gen_declaration (atype_or_adecl, buf)
7639      tree atype_or_adecl;
7640      char *buf;
7641 {
7642   buf[0] = '\0';
7643   gen_declaration_1 (atype_or_adecl, buf);
7644   return buf;
7645 }
7646
7647 /* Given a tree node, append a printable description to the end of the
7648    given buffer.  */
7649
7650 static void
7651 gen_declaration_1 (atype_or_adecl, buf)
7652      tree atype_or_adecl;
7653      char *buf;
7654 {
7655   char declbuf[256];
7656
7657   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7658     {
7659       tree declspecs;   /* "identifier_node", "record_type" */
7660       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
7661
7662       /* We have a "raw", abstract declarator (typename).  */
7663       declarator = TREE_VALUE (atype_or_adecl);
7664       declspecs  = TREE_PURPOSE (atype_or_adecl);
7665
7666       gen_declspecs (declspecs, buf, 1);
7667       if (declarator)
7668         {
7669           strcat (buf, " ");
7670           strcat (buf, gen_declarator (declarator, declbuf, ""));
7671         }
7672     }
7673
7674   else
7675     {
7676       tree atype;
7677       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
7678       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
7679
7680       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7681           || TREE_CODE (atype_or_adecl) == PARM_DECL
7682           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7683         atype = TREE_TYPE (atype_or_adecl);
7684       else
7685         /* Assume we have a *_type node.  */
7686         atype = atype_or_adecl;
7687
7688       if (is_complex_decl (atype))
7689         {
7690           tree chain;
7691
7692           /* Get the declaration specifier; it is at the end of the list.  */
7693           declarator = chain = atype;
7694           do
7695             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7696           while (is_complex_decl (chain));
7697           declspecs = chain;
7698         }
7699
7700       else
7701         {
7702           declspecs = atype;
7703           declarator = NULL_TREE;
7704         }
7705
7706       gen_declspecs (declspecs, buf, 0);
7707
7708       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7709           || TREE_CODE (atype_or_adecl) == PARM_DECL
7710           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7711         {
7712           const char *const decl_name =
7713             (DECL_NAME (atype_or_adecl)
7714              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
7715
7716           if (declarator)
7717             {
7718               strcat (buf, " ");
7719               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7720             }
7721
7722           else if (decl_name[0])
7723             {
7724               strcat (buf, " ");
7725               strcat (buf, decl_name);
7726             }
7727         }
7728       else if (declarator)
7729         {
7730           strcat (buf, " ");
7731           strcat (buf, gen_declarator (declarator, declbuf, ""));
7732         }
7733     }
7734 }
7735
7736 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7737
7738 /* Given a method tree, put a printable description into the given
7739    buffer (overwriting) and return a pointer to the buffer.  */
7740
7741 static char *
7742 gen_method_decl (method, buf)
7743      tree method;
7744      char *buf;
7745 {
7746   tree chain;
7747
7748   buf[0] = '\0';
7749   if (RAW_TYPESPEC (method) != objc_object_reference)
7750     {
7751       strcat (buf, "(");
7752       gen_declaration_1 (TREE_TYPE (method), buf);
7753       strcat (buf, ")");
7754     }
7755
7756   chain = METHOD_SEL_ARGS (method);
7757   if (chain)
7758     {
7759       /* We have a chain of keyword_decls.  */
7760       do
7761         {
7762           if (KEYWORD_KEY_NAME (chain))
7763             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7764
7765           strcat (buf, ":");
7766           if (RAW_TYPESPEC (chain) != objc_object_reference)
7767             {
7768               strcat (buf, "(");
7769               gen_declaration_1 (TREE_TYPE (chain), buf);
7770               strcat (buf, ")");
7771             }
7772
7773           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7774           if ((chain = TREE_CHAIN (chain)))
7775             strcat (buf, " ");
7776         }
7777       while (chain);
7778
7779       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
7780         strcat (buf, ", ...");
7781       else if (METHOD_ADD_ARGS (method))
7782         {
7783           /* We have a tree list node as generate by get_parm_info.  */
7784           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7785
7786           /* Know we have a chain of parm_decls.  */
7787           while (chain)
7788             {
7789               strcat (buf, ", ");
7790               gen_declaration_1 (chain, buf);
7791               chain = TREE_CHAIN (chain);
7792             }
7793         }
7794     }
7795
7796   else
7797     /* We have a unary selector.  */
7798     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7799
7800   return buf;
7801 }
7802 \f
7803 /* Debug info.  */
7804
7805 static void
7806 dump_interface (fp, chain)
7807      FILE *fp;
7808      tree chain;
7809 {
7810   char *buf = (char *) xmalloc (256);
7811   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7812   tree ivar_decls = CLASS_RAW_IVARS (chain);
7813   tree nst_methods = CLASS_NST_METHODS (chain);
7814   tree cls_methods = CLASS_CLS_METHODS (chain);
7815
7816   fprintf (fp, "\n@interface %s", my_name);
7817
7818   if (CLASS_SUPER_NAME (chain))
7819     {
7820       const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7821       fprintf (fp, " : %s\n", super_name);
7822     }
7823   else
7824     fprintf (fp, "\n");
7825
7826   if (ivar_decls)
7827     {
7828       fprintf (fp, "{\n");
7829       do
7830         {
7831           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7832           ivar_decls = TREE_CHAIN (ivar_decls);
7833         }
7834       while (ivar_decls);
7835       fprintf (fp, "}\n");
7836     }
7837
7838   while (nst_methods)
7839     {
7840       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7841       nst_methods = TREE_CHAIN (nst_methods);
7842     }
7843
7844   while (cls_methods)
7845     {
7846       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7847       cls_methods = TREE_CHAIN (cls_methods);
7848     }
7849   fprintf (fp, "\n@end");
7850 }
7851
7852 /* Demangle function for Objective-C */
7853 static const char *
7854 objc_demangle (mangled)
7855      const char *mangled;
7856 {
7857   char *demangled, *cp;
7858
7859   if (mangled[0] == '_' &&
7860       (mangled[1] == 'i' || mangled[1] == 'c') &&
7861       mangled[2] == '_')
7862     {
7863       cp = demangled = xmalloc(strlen(mangled) + 2);
7864       if (mangled[1] == 'i')
7865         *cp++ = '-';            /* for instance method */
7866       else
7867         *cp++ = '+';            /* for class method */
7868       *cp++ = '[';              /* opening left brace */
7869       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
7870       while (*cp && *cp == '_')
7871         cp++;                   /* skip any initial underbars in class name */
7872       cp = strchr(cp, '_');     /* find first non-initial underbar */
7873       if (cp == NULL)
7874         {
7875           free(demangled);      /* not mangled name */
7876           return mangled;
7877         }
7878       if (cp[1] == '_')  /* easy case: no category name */
7879         {
7880           *cp++ = ' ';            /* replace two '_' with one ' ' */
7881           strcpy(cp, mangled + (cp - demangled) + 2);
7882         }
7883       else
7884         {
7885           *cp++ = '(';            /* less easy case: category name */
7886           cp = strchr(cp, '_');
7887           if (cp == 0)
7888             {
7889               free(demangled);    /* not mangled name */
7890               return mangled;
7891             }
7892           *cp++ = ')';
7893           *cp++ = ' ';            /* overwriting 1st char of method name... */
7894           strcpy(cp, mangled + (cp - demangled)); /* get it back */
7895         }
7896       while (*cp && *cp == '_')
7897         cp++;                   /* skip any initial underbars in method name */
7898       for (; *cp; cp++)
7899         if (*cp == '_')
7900           *cp = ':';            /* replace remaining '_' with ':' */
7901       *cp++ = ']';              /* closing right brace */
7902       *cp++ = 0;                /* string terminator */
7903       return demangled;
7904     }
7905   else
7906     return mangled;             /* not an objc mangled name */
7907 }
7908
7909 const char *
7910 objc_printable_name (decl, kind)
7911      tree decl;
7912      int kind ATTRIBUTE_UNUSED;
7913 {
7914   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
7915 }
7916
7917 static void
7918 init_objc ()
7919 {
7920   gcc_obstack_init (&util_obstack);
7921   util_firstobj = (char *) obstack_finish (&util_obstack);
7922
7923   errbuf = (char *) xmalloc (BUFSIZE);
7924   hash_init ();
7925   synth_module_prologue ();
7926 }
7927 \f
7928 static void
7929 finish_objc ()
7930 {
7931   struct imp_entry *impent;
7932   tree chain;
7933   /* The internally generated initializers appear to have missing braces.
7934      Don't warn about this.  */
7935   int save_warn_missing_braces = warn_missing_braces;
7936   warn_missing_braces = 0;
7937
7938   /* A missing @end may not be detected by the parser.  */
7939   if (objc_implementation_context)
7940     {
7941       warning ("`@end' missing in implementation context");
7942       finish_class (objc_implementation_context);
7943       objc_ivar_chain = NULL_TREE;
7944       objc_implementation_context = NULL_TREE;
7945     }
7946
7947   generate_forward_declaration_to_string_table ();
7948
7949 #ifdef OBJC_PROLOGUE
7950   OBJC_PROLOGUE;
7951 #endif
7952
7953   /* Process the static instances here because initialization of objc_symtab
7954      depends on them.  */
7955   if (objc_static_instances)
7956     generate_static_references ();
7957
7958   if (imp_list || class_names_chain
7959       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7960     generate_objc_symtab_decl ();
7961
7962   for (impent = imp_list; impent; impent = impent->next)
7963     {
7964       objc_implementation_context = impent->imp_context;
7965       implementation_template = impent->imp_template;
7966
7967       UOBJC_CLASS_decl = impent->class_decl;
7968       UOBJC_METACLASS_decl = impent->meta_decl;
7969
7970       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7971         {
7972           /* all of the following reference the string pool...  */
7973           generate_ivar_lists ();
7974           generate_dispatch_tables ();
7975           generate_shared_structures ();
7976         }
7977       else
7978         {
7979           generate_dispatch_tables ();
7980           generate_category (objc_implementation_context);
7981         }
7982     }
7983
7984   /* If we are using an array of selectors, we must always
7985      finish up the array decl even if no selectors were used.  */
7986   if (! flag_next_runtime || sel_ref_chain)
7987     build_selector_translation_table ();
7988
7989   if (protocol_chain)
7990     generate_protocols ();
7991
7992   if (objc_implementation_context || class_names_chain || objc_static_instances
7993       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7994     {
7995       /* Arrange for ObjC data structures to be initialized at run time.  */
7996       rtx init_sym = build_module_descriptor ();
7997       if (init_sym && targetm.have_ctors_dtors)
7998         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
7999     }
8000
8001   /* Dump the class references.  This forces the appropriate classes
8002      to be linked into the executable image, preserving unix archive
8003      semantics.  This can be removed when we move to a more dynamically
8004      linked environment.  */
8005
8006   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8007     {
8008       handle_class_ref (chain);
8009       if (TREE_PURPOSE (chain))
8010         generate_classref_translation_entry (chain);
8011     }
8012
8013   for (impent = imp_list; impent; impent = impent->next)
8014     handle_impent (impent);
8015
8016   /* Dump the string table last.  */
8017
8018   generate_strings ();
8019
8020   if (flag_gen_declaration)
8021     {
8022       add_class (objc_implementation_context);
8023       dump_interface (gen_declaration_file, objc_implementation_context);
8024     }
8025
8026   if (warn_selector)
8027     {
8028       int slot;
8029       hash hsh;
8030
8031       /* Run through the selector hash tables and print a warning for any
8032          selector which has multiple methods.  */
8033
8034       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8035         for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8036           if (hsh->list)
8037             {
8038               tree meth = hsh->key;
8039               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8040                            ? '-' : '+');
8041               attr loop;
8042
8043               warning ("potential selector conflict for method `%s'",
8044                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8045               warn_with_method ("found", type, meth);
8046               for (loop = hsh->list; loop; loop = loop->next)
8047                 warn_with_method ("found", type, loop->value);
8048             }
8049
8050       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8051         for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8052           if (hsh->list)
8053             {
8054               tree meth = hsh->key;
8055               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8056                            ? '-' : '+');
8057               attr loop;
8058
8059               warning ("potential selector conflict for method `%s'",
8060                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8061               warn_with_method ("found", type, meth);
8062               for (loop = hsh->list; loop; loop = loop->next)
8063                 warn_with_method ("found", type, loop->value);
8064             }
8065     }
8066
8067   warn_missing_braces = save_warn_missing_braces;
8068 }
8069 \f
8070 /* Subroutines of finish_objc.  */
8071
8072 static void
8073 generate_classref_translation_entry (chain)
8074      tree chain;
8075 {
8076   tree expr, name, decl_specs, decl, sc_spec;
8077   tree type;
8078
8079   type = TREE_TYPE (TREE_PURPOSE (chain));
8080
8081   expr = add_objc_string (TREE_VALUE (chain), class_names);
8082   expr = build_c_cast (type, expr); /* cast! */
8083
8084   name = DECL_NAME (TREE_PURPOSE (chain));
8085
8086   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8087
8088   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8089   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8090
8091   /* The decl that is returned from start_decl is the one that we
8092      forward declared in build_class_reference.  */
8093   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8094   DECL_CONTEXT (decl) = NULL_TREE;
8095   finish_decl (decl, expr, NULL_TREE);
8096   return;
8097 }
8098
8099 static void
8100 handle_class_ref (chain)
8101      tree chain;
8102 {
8103   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8104   char *string = (char *) alloca (strlen (name) + 30);
8105   tree decl;
8106   tree exp;
8107
8108   sprintf (string, "%sobjc_class_name_%s",
8109            (flag_next_runtime ? "." : "__"), name);
8110
8111 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8112   if (flag_next_runtime)
8113     {
8114       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8115       return;
8116     }
8117 #endif
8118
8119   /* Make a decl for this name, so we can use its address in a tree.  */
8120   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8121   DECL_EXTERNAL (decl) = 1;
8122   TREE_PUBLIC (decl) = 1;
8123
8124   pushdecl (decl);
8125   rest_of_decl_compilation (decl, 0, 0, 0);
8126
8127   /* Make a decl for the address.  */
8128   sprintf (string, "%sobjc_class_ref_%s",
8129            (flag_next_runtime ? "." : "__"), name);
8130   exp = build1 (ADDR_EXPR, string_type_node, decl);
8131   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8132   DECL_INITIAL (decl) = exp;
8133   TREE_STATIC (decl) = 1;
8134   TREE_USED (decl) = 1;
8135
8136   pushdecl (decl);
8137   rest_of_decl_compilation (decl, 0, 0, 0);
8138 }
8139
8140 static void
8141 handle_impent (impent)
8142      struct imp_entry *impent;
8143 {
8144   char *string;
8145
8146   objc_implementation_context = impent->imp_context;
8147   implementation_template = impent->imp_template;
8148
8149   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8150     {
8151       const char *const class_name =
8152         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8153
8154       string = (char *) alloca (strlen (class_name) + 30);
8155
8156       sprintf (string, "%sobjc_class_name_%s",
8157                (flag_next_runtime ? "." : "__"), class_name);
8158     }
8159   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8160     {
8161       const char *const class_name =
8162         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8163       const char *const class_super_name =
8164         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8165
8166       string = (char *) alloca (strlen (class_name)
8167                                 + strlen (class_super_name) + 30);
8168
8169       /* Do the same for categories.  Even though no references to
8170          these symbols are generated automatically by the compiler, it
8171          gives you a handle to pull them into an archive by hand.  */
8172       sprintf (string, "*%sobjc_category_name_%s_%s",
8173                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8174     }
8175   else
8176     return;
8177
8178 #ifdef ASM_DECLARE_CLASS_REFERENCE
8179   if (flag_next_runtime)
8180     {
8181       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8182       return;
8183     }
8184   else
8185 #endif
8186     {
8187       tree decl, init;
8188
8189       init = build_int_2 (0, 0);
8190       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
8191       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
8192       TREE_PUBLIC (decl) = 1;
8193       TREE_READONLY (decl) = 1;
8194       TREE_USED (decl) = 1;
8195       TREE_CONSTANT (decl) = 1;
8196       DECL_CONTEXT (decl) = 0;
8197       DECL_ARTIFICIAL (decl) = 1;
8198       DECL_INITIAL (decl) = init;
8199       assemble_variable (decl, 1, 0, 0);
8200     }
8201 }
8202 \f
8203 /* Look up ID as an instance variable.  */
8204 tree
8205 lookup_objc_ivar (id)
8206      tree id;
8207 {
8208   tree decl;
8209
8210   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8211     /* We have a message to super.  */
8212     return get_super_receiver ();
8213   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8214     {
8215       if (is_private (decl))
8216         return error_mark_node;
8217       else
8218         return build_ivar_reference (id);
8219     }
8220   else
8221     return 0;
8222 }
8223
8224 #include "gtype-objc.h"