OSDN Git Service

Compile ObjC @protocols into list of ObjC statically allocated instances,
[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_CHAIN (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, prototype)
1982      tree ident, prototype;
1983 {
1984   tree *chain = &sel_ref_chain;
1985   tree expr;
1986   int index = 0;
1987
1988   while (*chain)
1989     {
1990       if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
1991         goto return_at_index;
1992
1993       index++;
1994       chain = &TREE_CHAIN (*chain);
1995     }
1996
1997   *chain = tree_cons (prototype, 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 /* For each protocol which was referenced either from a @protocol()
2871    expression, or because a class/category implements it (then a
2872    pointer to the protocol is stored in the struct describing the
2873    class/category), we create a statically allocated instance of the
2874    Protocol class.  The code is written in such a way as to generate
2875    as few Protocol objects as possible; we generate a unique Protocol
2876    instance for each protocol, and we don't generate a Protocol
2877    instance if the protocol is never referenced (either from a
2878    @protocol() or from a class/category implementation).  These
2879    statically allocated objects can be referred to via the static
2880    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
2881    
2882    The statically allocated Protocol objects that we generate here
2883    need to be fixed up at runtime in order to be used: the 'isa'
2884   pointer of the objects need to be set up to point to the 'Protocol'
2885    class, as known at runtime.
2886
2887    The NeXT runtime fixes up all protocols at program startup time,
2888    before main() is entered.  It uses a low-level trick to look up all
2889    those symbols, then loops on them and fixes them up.
2890
2891    The GNU runtime as well fixes up all protocols before user code
2892    from the module is executed; it requires pointers to those symbols
2893    to be put in the objc_symtab (which is then passed as argument to
2894    the function __objc_exec_class() which the compiler sets up to be
2895    executed automatically when the module is loaded); setup of those
2896    Protocol objects happen in two ways in the GNU runtime: all
2897    Protocol objects referred to by a class or category implementation
2898    are fixed up when the class/category is loaded; all Protocol
2899    objects referred to by a @protocol() expression are added by the
2900    compiler to the list of statically allocated instances to fixup
2901    (the same list holding the statically allocated constant string
2902    objects).  Because, as explained above, the compiler generates as
2903    few Protocol objects as possible, some Protocol object might end up
2904    being referenced multiple times when compiled with the GNU runtime,
2905    and end up being fixed up multiple times at runtime inizialization.
2906    But that doesn't hurt, it's just a little inefficient.  */
2907 static void
2908 generate_protocols ()
2909 {
2910   tree p, tmp_decl, encoding;
2911   tree sc_spec, decl_specs, decl;
2912   tree initlist, protocol_name_expr, refs_decl, refs_expr;
2913   tree cast_type2;
2914
2915   tmp_decl = build_tmp_function_decl ();
2916
2917   if (! objc_protocol_template)
2918     objc_protocol_template = build_protocol_template ();
2919
2920   /* If a protocol was directly referenced, pull in indirect references.  */
2921   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2922     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2923       generate_protocol_references (PROTOCOL_LIST (p));
2924
2925   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2926     {
2927       tree nst_methods = PROTOCOL_NST_METHODS (p);
2928       tree cls_methods = PROTOCOL_CLS_METHODS (p);
2929
2930       /* If protocol wasn't referenced, don't generate any code.  */
2931       if (! PROTOCOL_FORWARD_DECL (p))
2932         continue;
2933
2934       /* Make sure we link in the Protocol class.  */
2935       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2936
2937       while (nst_methods)
2938         {
2939           if (! METHOD_ENCODING (nst_methods))
2940             {
2941               hack_method_prototype (nst_methods, tmp_decl);
2942               encoding = encode_method_prototype (nst_methods, tmp_decl);
2943               METHOD_ENCODING (nst_methods) = encoding;
2944             }
2945           nst_methods = TREE_CHAIN (nst_methods);
2946         }
2947
2948       while (cls_methods)
2949         {
2950           if (! METHOD_ENCODING (cls_methods))
2951             {
2952               hack_method_prototype (cls_methods, tmp_decl);
2953               encoding = encode_method_prototype (cls_methods, tmp_decl);
2954               METHOD_ENCODING (cls_methods) = encoding;
2955             }
2956
2957           cls_methods = TREE_CHAIN (cls_methods);
2958         }
2959       generate_method_descriptors (p);
2960
2961       if (PROTOCOL_LIST (p))
2962         refs_decl = generate_protocol_list (p);
2963       else
2964         refs_decl = 0;
2965
2966       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
2967
2968       sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
2969                            NULL_TREE);
2970       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
2971
2972       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
2973                          decl_specs, 1, NULL_TREE);
2974
2975       DECL_CONTEXT (decl) = NULL_TREE;
2976
2977       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2978
2979       if (refs_decl)
2980         {
2981           cast_type2
2982             = groktypename
2983                 (build_tree_list (build_tree_list (NULL_TREE,
2984                                                    objc_protocol_template),
2985                                   build1 (INDIRECT_REF, NULL_TREE,
2986                                           build1 (INDIRECT_REF, NULL_TREE,
2987                                                   NULL_TREE))));
2988
2989           refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
2990           TREE_TYPE (refs_expr) = cast_type2;
2991         }
2992       else
2993         refs_expr = build_int_2 (0, 0);
2994
2995       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
2996          by generate_method_descriptors, which is called above.  */
2997       initlist = build_protocol_initializer (TREE_TYPE (decl),
2998                                              protocol_name_expr, refs_expr,
2999                                              UOBJC_INSTANCE_METHODS_decl,
3000                                              UOBJC_CLASS_METHODS_decl);
3001       finish_decl (decl, initlist, NULL_TREE);
3002
3003       /* Mark the decl as used to avoid "defined but not used" warning.  */
3004       TREE_USED (decl) = 1;
3005     }
3006 }
3007
3008 static tree
3009 build_protocol_initializer (type, protocol_name, protocol_list,
3010                             instance_methods, class_methods)
3011      tree type;
3012      tree protocol_name;
3013      tree protocol_list;
3014      tree instance_methods;
3015      tree class_methods;
3016 {
3017   tree initlist = NULL_TREE, expr;
3018   tree cast_type;
3019
3020   cast_type = groktypename
3021     (build_tree_list
3022      (build_tree_list (NULL_TREE,
3023                        xref_tag (RECORD_TYPE,
3024                                  get_identifier (UTAG_CLASS))),
3025       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3026
3027   /* Filling the "isa" in with one allows the runtime system to
3028      detect that the version change...should remove before final release.  */
3029
3030   expr = build_int_2 (PROTOCOL_VERSION, 0);
3031   TREE_TYPE (expr) = cast_type;
3032   initlist = tree_cons (NULL_TREE, expr, initlist);
3033   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3034   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3035
3036   if (!instance_methods)
3037     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3038   else
3039     {
3040       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3041       initlist = tree_cons (NULL_TREE, expr, initlist);
3042     }
3043
3044   if (!class_methods)
3045     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3046   else
3047     {
3048       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3049       initlist = tree_cons (NULL_TREE, expr, initlist);
3050     }
3051
3052   return build_constructor (type, nreverse (initlist));
3053 }
3054 \f
3055 /* struct objc_category {
3056      char *category_name;
3057      char *class_name;
3058      struct objc_method_list *instance_methods;
3059      struct objc_method_list *class_methods;
3060      struct objc_protocol_list *protocols;
3061    };   */
3062
3063 static void
3064 build_category_template ()
3065 {
3066   tree decl_specs, field_decl, field_decl_chain;
3067
3068   objc_category_template = start_struct (RECORD_TYPE,
3069                                          get_identifier (UTAG_CATEGORY));
3070   /* char *category_name; */
3071
3072   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3073   field_decl
3074     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3075   field_decl
3076     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3077   field_decl_chain = field_decl;
3078
3079   /* char *class_name; */
3080
3081   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3082   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3083   field_decl
3084     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3085   chainon (field_decl_chain, field_decl);
3086
3087   /* struct objc_method_list *instance_methods; */
3088
3089   decl_specs = build_tree_list (NULL_TREE,
3090                                 xref_tag (RECORD_TYPE,
3091                                           get_identifier (UTAG_METHOD_LIST)));
3092   field_decl
3093     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3094   field_decl
3095     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3096   chainon (field_decl_chain, field_decl);
3097
3098   /* struct objc_method_list *class_methods; */
3099
3100   decl_specs = build_tree_list (NULL_TREE,
3101                                 xref_tag (RECORD_TYPE,
3102                                           get_identifier (UTAG_METHOD_LIST)));
3103   field_decl
3104     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3105   field_decl
3106     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3107   chainon (field_decl_chain, field_decl);
3108
3109   /* struct objc_protocol **protocol_list; */
3110
3111   decl_specs = build_tree_list (NULL_TREE,
3112                                 xref_tag (RECORD_TYPE,
3113                                           get_identifier (UTAG_PROTOCOL)));
3114   field_decl
3115     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3116   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3117   field_decl
3118     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3119   chainon (field_decl_chain, field_decl);
3120
3121   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3122 }
3123
3124 /* struct objc_selector {
3125      void *sel_id;
3126      char *sel_type;
3127    }; */
3128
3129 static void
3130 build_selector_template ()
3131 {
3132
3133   tree decl_specs, field_decl, field_decl_chain;
3134
3135   objc_selector_template 
3136     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3137
3138   /* void *sel_id; */
3139
3140   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3141   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3142   field_decl
3143     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3144   field_decl_chain = field_decl;
3145
3146   /* char *sel_type; */
3147
3148   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3149   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3150   field_decl
3151     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3152   chainon (field_decl_chain, field_decl);
3153
3154   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3155 }
3156
3157 /* struct objc_class {
3158      struct objc_class *isa;
3159      struct objc_class *super_class;
3160      char *name;
3161      long version;
3162      long info;
3163      long instance_size;
3164      struct objc_ivar_list *ivars;
3165      struct objc_method_list *methods;
3166      if (flag_next_runtime)
3167        struct objc_cache *cache;
3168      else {
3169        struct sarray *dtable;
3170        struct objc_class *subclass_list;
3171        struct objc_class *sibling_class;
3172      }
3173      struct objc_protocol_list *protocols;
3174      void *gc_object_type;
3175    };  */
3176
3177 static void
3178 build_class_template ()
3179 {
3180   tree decl_specs, field_decl, field_decl_chain;
3181
3182   objc_class_template
3183     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3184
3185   /* struct objc_class *isa; */
3186
3187   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3188   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3189   field_decl
3190     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3191   field_decl_chain = field_decl;
3192
3193   /* struct objc_class *super_class; */
3194
3195   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3196   field_decl
3197     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3198   field_decl
3199     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3200   chainon (field_decl_chain, field_decl);
3201
3202   /* char *name; */
3203
3204   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3205   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3206   field_decl
3207     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3208   chainon (field_decl_chain, field_decl);
3209
3210   /* long version; */
3211
3212   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3213   field_decl = get_identifier ("version");
3214   field_decl
3215     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3216   chainon (field_decl_chain, field_decl);
3217
3218   /* long info; */
3219
3220   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3221   field_decl = get_identifier ("info");
3222   field_decl
3223     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3224   chainon (field_decl_chain, field_decl);
3225
3226   /* long instance_size; */
3227
3228   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3229   field_decl = get_identifier ("instance_size");
3230   field_decl
3231     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3232   chainon (field_decl_chain, field_decl);
3233
3234   /* struct objc_ivar_list *ivars; */
3235
3236   decl_specs = build_tree_list (NULL_TREE,
3237                                 xref_tag (RECORD_TYPE,
3238                                           get_identifier (UTAG_IVAR_LIST)));
3239   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3240   field_decl
3241     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3242   chainon (field_decl_chain, field_decl);
3243
3244   /* struct objc_method_list *methods; */
3245
3246   decl_specs = build_tree_list (NULL_TREE,
3247                                 xref_tag (RECORD_TYPE,
3248                                           get_identifier (UTAG_METHOD_LIST)));
3249   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3250   field_decl
3251     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3252   chainon (field_decl_chain, field_decl);
3253
3254   if (flag_next_runtime)
3255     {
3256       /* struct objc_cache *cache; */
3257
3258       decl_specs = build_tree_list (NULL_TREE,
3259                                     xref_tag (RECORD_TYPE,
3260                                               get_identifier ("objc_cache")));
3261       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3262       field_decl = grokfield (input_filename, lineno, field_decl,
3263                               decl_specs, NULL_TREE);
3264       chainon (field_decl_chain, field_decl);
3265     }
3266   else
3267     {
3268       /* struct sarray *dtable; */
3269
3270       decl_specs = build_tree_list (NULL_TREE,
3271                                     xref_tag (RECORD_TYPE,
3272                                               get_identifier ("sarray")));
3273       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3274       field_decl = grokfield (input_filename, lineno, field_decl,
3275                               decl_specs, NULL_TREE);
3276       chainon (field_decl_chain, field_decl);
3277
3278       /* struct objc_class *subclass_list; */
3279
3280       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3281       field_decl
3282         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3283       field_decl = grokfield (input_filename, lineno, field_decl,
3284                               decl_specs, NULL_TREE);
3285       chainon (field_decl_chain, field_decl);
3286
3287       /* struct objc_class *sibling_class; */
3288
3289       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3290       field_decl
3291         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3292       field_decl = grokfield (input_filename, lineno, field_decl,
3293                               decl_specs, NULL_TREE);
3294       chainon (field_decl_chain, field_decl);
3295     }
3296
3297   /* struct objc_protocol **protocol_list; */
3298
3299   decl_specs = build_tree_list (NULL_TREE, 
3300                                 xref_tag (RECORD_TYPE,
3301                                           get_identifier (UTAG_PROTOCOL)));
3302   field_decl
3303     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3304   field_decl
3305     = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3306   field_decl = grokfield (input_filename, lineno, field_decl,
3307                           decl_specs, NULL_TREE);
3308   chainon (field_decl_chain, field_decl);
3309
3310   /* void *sel_id; */
3311
3312   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3313   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3314   field_decl
3315     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3316   chainon (field_decl_chain, field_decl);
3317
3318   /* void *gc_object_type; */
3319
3320   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3321   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3322   field_decl
3323     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3324   chainon (field_decl_chain, field_decl);
3325
3326   finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3327 }
3328
3329 /* Generate appropriate forward declarations for an implementation.  */
3330
3331 static void
3332 synth_forward_declarations ()
3333 {
3334   tree sc_spec, decl_specs, an_id;
3335
3336   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3337
3338   an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
3339
3340   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3341   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3342   UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3343   TREE_USED (UOBJC_CLASS_decl) = 1;
3344   DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3345
3346   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3347
3348   an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3349                                       objc_implementation_context);
3350
3351   UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3352   TREE_USED (UOBJC_METACLASS_decl) = 1;
3353   DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3354
3355   /* Pre-build the following entities - for speed/convenience.  */
3356
3357   an_id = get_identifier ("super_class");
3358   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3359   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3360 }
3361
3362 static void
3363 error_with_ivar (message, decl, rawdecl)
3364      const char *message;
3365      tree decl;
3366      tree rawdecl;
3367 {
3368   diagnostic_count_diagnostic (global_dc, DK_ERROR);
3369
3370   diagnostic_report_current_function (global_dc);
3371
3372   error_with_file_and_line (DECL_SOURCE_FILE (decl),
3373                             DECL_SOURCE_LINE (decl),
3374                             "%s `%s'",
3375                             message, gen_declaration (rawdecl, errbuf));
3376
3377 }
3378
3379 static void
3380 check_ivars (inter, imp)
3381      tree inter;
3382      tree imp;
3383 {
3384   tree intdecls = CLASS_IVARS (inter);
3385   tree impdecls = CLASS_IVARS (imp);
3386   tree rawintdecls = CLASS_RAW_IVARS (inter);
3387   tree rawimpdecls = CLASS_RAW_IVARS (imp);
3388
3389   while (1)
3390     {
3391       tree t1, t2;
3392
3393       if (intdecls == 0 && impdecls == 0)
3394         break;
3395       if (intdecls == 0 || impdecls == 0)
3396         {
3397           error ("inconsistent instance variable specification");
3398           break;
3399         }
3400
3401       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3402
3403       if (!comptypes (t1, t2))
3404         {
3405           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3406             {
3407               error_with_ivar ("conflicting instance variable type",
3408                                impdecls, rawimpdecls);
3409               error_with_ivar ("previous declaration of",
3410                                intdecls, rawintdecls);
3411             }
3412           else                  /* both the type and the name don't match */
3413             {
3414               error ("inconsistent instance variable specification");
3415               break;
3416             }
3417         }
3418
3419       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3420         {
3421           error_with_ivar ("conflicting instance variable name",
3422                            impdecls, rawimpdecls);
3423           error_with_ivar ("previous declaration of",
3424                            intdecls, rawintdecls);
3425         }
3426
3427       intdecls = TREE_CHAIN (intdecls);
3428       impdecls = TREE_CHAIN (impdecls);
3429       rawintdecls = TREE_CHAIN (rawintdecls);
3430       rawimpdecls = TREE_CHAIN (rawimpdecls);
3431     }
3432 }
3433
3434 /* Set super_type to the data type node for struct objc_super *,
3435    first defining struct objc_super itself.
3436    This needs to be done just once per compilation.  */
3437
3438 static tree
3439 build_super_template ()
3440 {
3441   tree record, decl_specs, field_decl, field_decl_chain;
3442
3443   record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3444
3445   /* struct objc_object *self; */
3446
3447   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3448   field_decl = get_identifier ("self");
3449   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3450   field_decl = grokfield (input_filename, lineno,
3451                           field_decl, decl_specs, NULL_TREE);
3452   field_decl_chain = field_decl;
3453
3454   /* struct objc_class *class; */
3455
3456   decl_specs = get_identifier (UTAG_CLASS);
3457   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3458   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3459
3460   field_decl = grokfield (input_filename, lineno,
3461                           field_decl, decl_specs, NULL_TREE);
3462   chainon (field_decl_chain, field_decl);
3463
3464   finish_struct (record, field_decl_chain, NULL_TREE);
3465
3466   /* `struct objc_super *' */
3467   super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3468                                                                record),
3469                                               build1 (INDIRECT_REF,
3470                                                       NULL_TREE, NULL_TREE)));
3471   return record;
3472 }
3473
3474 /* struct objc_ivar {
3475      char *ivar_name;
3476      char *ivar_type;
3477      int ivar_offset;
3478    };  */
3479
3480 static tree
3481 build_ivar_template ()
3482 {
3483   tree objc_ivar_id, objc_ivar_record;
3484   tree decl_specs, field_decl, field_decl_chain;
3485
3486   objc_ivar_id = get_identifier (UTAG_IVAR);
3487   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3488
3489   /* char *ivar_name; */
3490
3491   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3492   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3493
3494   field_decl = grokfield (input_filename, lineno, field_decl,
3495                           decl_specs, NULL_TREE);
3496   field_decl_chain = field_decl;
3497
3498   /* char *ivar_type; */
3499
3500   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3501   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3502
3503   field_decl = grokfield (input_filename, lineno, field_decl,
3504                           decl_specs, NULL_TREE);
3505   chainon (field_decl_chain, field_decl);
3506
3507   /* int ivar_offset; */
3508
3509   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3510   field_decl = get_identifier ("ivar_offset");
3511
3512   field_decl = grokfield (input_filename, lineno, field_decl,
3513                           decl_specs, NULL_TREE);
3514   chainon (field_decl_chain, field_decl);
3515
3516   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3517
3518   return objc_ivar_record;
3519 }
3520
3521 /* struct {
3522      int ivar_count;
3523      struct objc_ivar ivar_list[ivar_count];
3524    };  */
3525
3526 static tree
3527 build_ivar_list_template (list_type, size)
3528      tree list_type;
3529      int size;
3530 {
3531   tree objc_ivar_list_record;
3532   tree decl_specs, field_decl, field_decl_chain;
3533
3534   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3535
3536   /* int ivar_count; */
3537
3538   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3539   field_decl = get_identifier ("ivar_count");
3540
3541   field_decl = grokfield (input_filename, lineno, field_decl,
3542                           decl_specs, NULL_TREE);
3543   field_decl_chain = field_decl;
3544
3545   /* struct objc_ivar ivar_list[]; */
3546
3547   decl_specs = build_tree_list (NULL_TREE, list_type);
3548   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3549                          build_int_2 (size, 0));
3550
3551   field_decl = grokfield (input_filename, lineno,
3552                           field_decl, decl_specs, NULL_TREE);
3553   chainon (field_decl_chain, field_decl);
3554
3555   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3556
3557   return objc_ivar_list_record;
3558 }
3559
3560 /* struct {
3561      int method_next;
3562      int method_count;
3563      struct objc_method method_list[method_count];
3564    };  */
3565
3566 static tree
3567 build_method_list_template (list_type, size)
3568      tree list_type;
3569      int size;
3570 {
3571   tree objc_ivar_list_record;
3572   tree decl_specs, field_decl, field_decl_chain;
3573
3574   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3575
3576   /* int method_next; */
3577
3578   decl_specs
3579     = build_tree_list
3580       (NULL_TREE, 
3581        xref_tag (RECORD_TYPE,
3582                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3583   field_decl
3584     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3585   field_decl = grokfield (input_filename, lineno, field_decl,
3586                           decl_specs, NULL_TREE);
3587   field_decl_chain = field_decl;
3588
3589   /* int method_count; */
3590
3591   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3592   field_decl = get_identifier ("method_count");
3593
3594   field_decl = grokfield (input_filename, lineno,
3595                           field_decl, decl_specs, NULL_TREE);
3596   chainon (field_decl_chain, field_decl);
3597
3598   /* struct objc_method method_list[]; */
3599
3600   decl_specs = build_tree_list (NULL_TREE, list_type);
3601   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3602                          build_int_2 (size, 0));
3603
3604   field_decl = grokfield (input_filename, lineno,
3605                           field_decl, decl_specs, NULL_TREE);
3606   chainon (field_decl_chain, field_decl);
3607
3608   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3609
3610   return objc_ivar_list_record;
3611 }
3612
3613 static tree
3614 build_ivar_list_initializer (type, field_decl)
3615      tree type;
3616      tree field_decl;
3617 {
3618   tree initlist = NULL_TREE;
3619
3620   do
3621     {
3622       tree ivar = NULL_TREE;
3623
3624       /* Set name.  */
3625       if (DECL_NAME (field_decl))
3626         ivar = tree_cons (NULL_TREE,
3627                           add_objc_string (DECL_NAME (field_decl),
3628                                            meth_var_names),
3629                           ivar);
3630       else
3631         /* Unnamed bit-field ivar (yuck).  */
3632         ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3633
3634       /* Set type.  */
3635       encode_field_decl (field_decl,
3636                          obstack_object_size (&util_obstack),
3637                          OBJC_ENCODE_DONT_INLINE_DEFS);
3638
3639       /* Null terminate string.  */
3640       obstack_1grow (&util_obstack, 0);
3641       ivar
3642         = tree_cons
3643           (NULL_TREE,
3644            add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3645                             meth_var_types),
3646            ivar);
3647       obstack_free (&util_obstack, util_firstobj);
3648
3649       /* Set offset.  */
3650       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
3651       initlist = tree_cons (NULL_TREE, 
3652                             build_constructor (type, nreverse (ivar)),
3653                             initlist);
3654
3655       field_decl = TREE_CHAIN (field_decl);
3656     }
3657   while (field_decl);
3658
3659   return build_constructor (build_array_type (type, 0), nreverse (initlist));
3660 }
3661
3662 static tree
3663 generate_ivars_list (type, name, size, list)
3664      tree type;
3665      const char *name;
3666      int size;
3667      tree list;
3668 {
3669   tree sc_spec, decl_specs, decl, initlist;
3670
3671   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3672   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3673
3674   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
3675                      decl_specs, 1, NULL_TREE);
3676
3677   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3678   initlist = tree_cons (NULL_TREE, list, initlist);
3679
3680   finish_decl (decl,
3681                build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3682                NULL_TREE);
3683
3684   return decl;
3685 }
3686
3687 static void
3688 generate_ivar_lists ()
3689 {
3690   tree initlist, ivar_list_template, chain;
3691   tree cast, variable_length_type;
3692   int size;
3693
3694   generating_instance_variables = 1;
3695
3696   if (!objc_ivar_template)
3697     objc_ivar_template = build_ivar_template ();
3698
3699   cast
3700     = build_tree_list
3701       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3702                                          get_identifier (UTAG_IVAR_LIST))),
3703        NULL_TREE);
3704   variable_length_type = groktypename (cast);
3705
3706   /* Only generate class variables for the root of the inheritance
3707      hierarchy since these will be the same for every class.  */
3708
3709   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3710       && (chain = TYPE_FIELDS (objc_class_template)))
3711     {
3712       size = list_length (chain);
3713
3714       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3715       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3716
3717       UOBJC_CLASS_VARIABLES_decl
3718         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3719                                size, initlist);
3720       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3721     }
3722   else
3723     UOBJC_CLASS_VARIABLES_decl = 0;
3724
3725   chain = CLASS_IVARS (implementation_template);
3726   if (chain)
3727     {
3728       size = list_length (chain);
3729       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3730       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3731
3732       UOBJC_INSTANCE_VARIABLES_decl
3733         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3734                                size, initlist);
3735       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3736     }
3737   else
3738     UOBJC_INSTANCE_VARIABLES_decl = 0;
3739
3740   generating_instance_variables = 0;
3741 }
3742
3743 static tree
3744 build_dispatch_table_initializer (type, entries)
3745      tree type;
3746      tree entries;
3747 {
3748   tree initlist = NULL_TREE;
3749
3750   do
3751     {
3752       tree elemlist = NULL_TREE;
3753
3754       elemlist = tree_cons (NULL_TREE,
3755                             build_selector (METHOD_SEL_NAME (entries)),
3756                             NULL_TREE);
3757
3758       /* Generate the method encoding if we don't have one already.  */
3759       if (! METHOD_ENCODING (entries))
3760         METHOD_ENCODING (entries) =
3761           encode_method_def (METHOD_DEFINITION (entries));
3762
3763       elemlist = tree_cons (NULL_TREE,
3764                             add_objc_string (METHOD_ENCODING (entries),
3765                                              meth_var_types),
3766                             elemlist);
3767
3768       elemlist = tree_cons (NULL_TREE, 
3769                             build_unary_op (ADDR_EXPR,
3770                                             METHOD_DEFINITION (entries), 1),
3771                             elemlist);
3772
3773       initlist = tree_cons (NULL_TREE, 
3774                             build_constructor (type, nreverse (elemlist)),
3775                             initlist);
3776
3777       entries = TREE_CHAIN (entries);
3778     }
3779   while (entries);
3780
3781   return build_constructor (build_array_type (type, 0), nreverse (initlist));
3782 }
3783
3784 /* To accomplish method prototyping without generating all kinds of
3785    inane warnings, the definition of the dispatch table entries were
3786    changed from:
3787
3788         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3789    to:
3790         struct objc_method { SEL _cmd; ...; void *_imp; };  */
3791
3792 static tree
3793 build_method_template ()
3794 {
3795   tree _SLT_record;
3796   tree decl_specs, field_decl, field_decl_chain;
3797
3798   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3799
3800   /* struct objc_selector *_cmd; */
3801   decl_specs = tree_cons (NULL_TREE,
3802                           xref_tag (RECORD_TYPE,
3803                                     get_identifier (TAG_SELECTOR)),
3804                           NULL_TREE);
3805   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3806
3807   field_decl = grokfield (input_filename, lineno, field_decl,
3808                           decl_specs, NULL_TREE);
3809   field_decl_chain = field_decl;
3810
3811   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3812   field_decl = build1 (INDIRECT_REF, NULL_TREE,
3813                        get_identifier ("method_types"));
3814   field_decl = grokfield (input_filename, lineno, field_decl,
3815                           decl_specs, NULL_TREE);
3816   chainon (field_decl_chain, field_decl);
3817
3818   /* void *_imp; */
3819
3820   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
3821   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
3822   field_decl = grokfield (input_filename, lineno, field_decl,
3823                           decl_specs, NULL_TREE);
3824   chainon (field_decl_chain, field_decl);
3825
3826   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
3827
3828   return _SLT_record;
3829 }
3830
3831
3832 static tree
3833 generate_dispatch_table (type, name, size, list)
3834      tree type;
3835      const char *name;
3836      int size;
3837      tree list;
3838 {
3839   tree sc_spec, decl_specs, decl, initlist;
3840
3841   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3842   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3843
3844   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
3845                      decl_specs, 1, NULL_TREE);
3846
3847   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
3848   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
3849   initlist = tree_cons (NULL_TREE, list, initlist);
3850
3851   finish_decl (decl,
3852                build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3853                NULL_TREE);
3854
3855   return decl;
3856 }
3857
3858 static void
3859 generate_dispatch_tables ()
3860 {
3861   tree initlist, chain, method_list_template;
3862   tree cast, variable_length_type;
3863   int size;
3864
3865   if (!objc_method_template)
3866     objc_method_template = build_method_template ();
3867
3868   cast
3869     = build_tree_list
3870       (build_tree_list (NULL_TREE,
3871                         xref_tag (RECORD_TYPE,
3872                                   get_identifier (UTAG_METHOD_LIST))),
3873        NULL_TREE);
3874
3875   variable_length_type = groktypename (cast);
3876
3877   chain = CLASS_CLS_METHODS (objc_implementation_context);
3878   if (chain)
3879     {
3880       size = list_length (chain);
3881
3882       method_list_template
3883         = build_method_list_template (objc_method_template, size);
3884       initlist
3885         = build_dispatch_table_initializer (objc_method_template, chain);
3886
3887       UOBJC_CLASS_METHODS_decl
3888         = generate_dispatch_table (method_list_template,
3889                                    ((TREE_CODE (objc_implementation_context)
3890                                      == CLASS_IMPLEMENTATION_TYPE)
3891                                     ? "_OBJC_CLASS_METHODS"
3892                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
3893                                    size, initlist);
3894       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3895     }
3896   else
3897     UOBJC_CLASS_METHODS_decl = 0;
3898
3899   chain = CLASS_NST_METHODS (objc_implementation_context);
3900   if (chain)
3901     {
3902       size = list_length (chain);
3903
3904       method_list_template
3905         = build_method_list_template (objc_method_template, size);
3906       initlist
3907         = build_dispatch_table_initializer (objc_method_template, chain);
3908
3909       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
3910         UOBJC_INSTANCE_METHODS_decl
3911           = generate_dispatch_table (method_list_template,
3912                                      "_OBJC_INSTANCE_METHODS",
3913                                      size, initlist);
3914       else
3915         /* We have a category.  */
3916         UOBJC_INSTANCE_METHODS_decl
3917           = generate_dispatch_table (method_list_template,
3918                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
3919                                      size, initlist);
3920       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3921     }
3922   else
3923     UOBJC_INSTANCE_METHODS_decl = 0;
3924 }
3925
3926 static tree
3927 generate_protocol_list (i_or_p)
3928      tree i_or_p;
3929 {
3930   tree initlist, decl_specs, sc_spec;
3931   tree refs_decl, expr_decl, lproto, e, plist;
3932   tree cast_type;
3933   int size = 0;
3934
3935   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
3936       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
3937     plist = CLASS_PROTOCOL_LIST (i_or_p);
3938   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
3939     plist = PROTOCOL_LIST (i_or_p);
3940   else
3941     abort ();
3942
3943   cast_type = groktypename
3944     (build_tree_list
3945      (build_tree_list (NULL_TREE,
3946                        xref_tag (RECORD_TYPE,
3947                                  get_identifier (UTAG_PROTOCOL))),
3948       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3949
3950   /* Compute size.  */
3951   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3952     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
3953         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
3954       size++;
3955
3956   /* Build initializer.  */
3957   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
3958
3959   e = build_int_2 (size, 0);
3960   TREE_TYPE (e) = cast_type;
3961   initlist = tree_cons (NULL_TREE, e, initlist);
3962
3963   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3964     {
3965       tree pval = TREE_VALUE (lproto);
3966
3967       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
3968           && PROTOCOL_FORWARD_DECL (pval))
3969         {
3970           e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
3971           initlist = tree_cons (NULL_TREE, e, initlist);
3972         }
3973     }
3974
3975   /* static struct objc_protocol *refs[n]; */
3976
3977   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3978   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
3979                                            get_identifier (UTAG_PROTOCOL)),
3980                           sc_spec);
3981
3982   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
3983     expr_decl = build_nt (ARRAY_REF,
3984                           synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
3985                                                       i_or_p),
3986                           build_int_2 (size + 2, 0));
3987   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
3988     expr_decl = build_nt (ARRAY_REF,
3989                           synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
3990                                                       i_or_p),
3991                           build_int_2 (size + 2, 0));
3992   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
3993     expr_decl
3994       = build_nt (ARRAY_REF,
3995                   synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
3996                                               i_or_p),
3997                   build_int_2 (size + 2, 0));
3998   else
3999     abort ();
4000
4001   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4002
4003   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4004   DECL_CONTEXT (refs_decl) = NULL_TREE;
4005
4006   finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4007                                              nreverse (initlist)),
4008                NULL_TREE);
4009
4010   return refs_decl;
4011 }
4012
4013 static tree
4014 build_category_initializer (type, cat_name, class_name,
4015                             instance_methods, class_methods, protocol_list)
4016      tree type;
4017      tree cat_name;
4018      tree class_name;
4019      tree instance_methods;
4020      tree class_methods;
4021      tree protocol_list;
4022 {
4023   tree initlist = NULL_TREE, expr;
4024
4025   initlist = tree_cons (NULL_TREE, cat_name, initlist);
4026   initlist = tree_cons (NULL_TREE, class_name, initlist);
4027
4028   if (!instance_methods)
4029     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4030   else
4031     {
4032       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4033       initlist = tree_cons (NULL_TREE, expr, initlist);
4034     }
4035   if (!class_methods)
4036     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4037   else
4038     {
4039       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4040       initlist = tree_cons (NULL_TREE, expr, initlist);
4041     }
4042
4043   /* protocol_list = */
4044   if (!protocol_list)
4045      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4046   else
4047      {
4048        tree cast_type2 = groktypename
4049          (build_tree_list
4050           (build_tree_list (NULL_TREE,
4051                             xref_tag (RECORD_TYPE,
4052                                       get_identifier (UTAG_PROTOCOL))),
4053            build1 (INDIRECT_REF, NULL_TREE,
4054                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4055
4056         expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4057         TREE_TYPE (expr) = cast_type2;
4058         initlist = tree_cons (NULL_TREE, expr, initlist);
4059      }
4060
4061   return build_constructor (type, nreverse (initlist));
4062 }
4063
4064 /* struct objc_class {
4065      struct objc_class *isa;
4066      struct objc_class *super_class;
4067      char *name;
4068      long version;
4069      long info;
4070      long instance_size;
4071      struct objc_ivar_list *ivars;
4072      struct objc_method_list *methods;
4073      if (flag_next_runtime)
4074        struct objc_cache *cache;
4075      else {
4076        struct sarray *dtable;
4077        struct objc_class *subclass_list;
4078        struct objc_class *sibling_class;
4079      }
4080      struct objc_protocol_list *protocols;
4081      void *gc_object_type;
4082    };  */
4083
4084 static tree
4085 build_shared_structure_initializer (type, isa, super, name, size, status,
4086                                     dispatch_table, ivar_list, protocol_list)
4087      tree type;
4088      tree isa;
4089      tree super;
4090      tree name;
4091      tree size;
4092      int status;
4093      tree dispatch_table;
4094      tree ivar_list;
4095      tree protocol_list;
4096 {
4097   tree initlist = NULL_TREE, expr;
4098
4099   /* isa = */
4100   initlist = tree_cons (NULL_TREE, isa, initlist);
4101
4102   /* super_class = */
4103   initlist = tree_cons (NULL_TREE, super, initlist);
4104
4105   /* name = */
4106   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4107
4108   /* version = */
4109   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4110
4111   /* info = */
4112   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4113
4114   /* instance_size = */
4115   initlist = tree_cons (NULL_TREE, size, initlist);
4116
4117   /* objc_ivar_list = */
4118   if (!ivar_list)
4119     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4120   else
4121     {
4122       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4123       initlist = tree_cons (NULL_TREE, expr, initlist);
4124     }
4125
4126   /* objc_method_list = */
4127   if (!dispatch_table)
4128     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4129   else
4130     {
4131       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4132       initlist = tree_cons (NULL_TREE, expr, initlist);
4133     }
4134
4135   if (flag_next_runtime)
4136     /* method_cache = */
4137     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4138   else
4139     {
4140       /* dtable = */
4141       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4142
4143       /* subclass_list = */
4144       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4145
4146       /* sibling_class = */
4147       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4148     }
4149
4150   /* protocol_list = */
4151   if (! protocol_list)
4152     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4153   else
4154      {
4155        tree cast_type2
4156          = groktypename
4157          (build_tree_list
4158           (build_tree_list (NULL_TREE,
4159                             xref_tag (RECORD_TYPE,
4160                                       get_identifier (UTAG_PROTOCOL))),
4161            build1 (INDIRECT_REF, NULL_TREE,
4162                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4163
4164      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4165      TREE_TYPE (expr) = cast_type2;
4166      initlist = tree_cons (NULL_TREE, expr, initlist);
4167      }
4168
4169   /* gc_object_type = NULL */
4170   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4171
4172   return build_constructor (type, nreverse (initlist));
4173 }
4174
4175 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
4176
4177 static void
4178 generate_category (cat)
4179      tree cat;
4180 {
4181   tree sc_spec, decl_specs, decl;
4182   tree initlist, cat_name_expr, class_name_expr;
4183   tree protocol_decl, category;
4184
4185   add_class_reference (CLASS_NAME (cat));
4186   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4187
4188   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4189
4190   category = CLASS_CATEGORY_LIST (implementation_template);
4191
4192   /* find the category interface from the class it is associated with */
4193   while (category)
4194     {
4195       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4196         break;
4197       category = CLASS_CATEGORY_LIST (category);
4198     }
4199
4200   if (category && CLASS_PROTOCOL_LIST (category))
4201     {
4202       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4203       protocol_decl = generate_protocol_list (category);
4204     }
4205   else
4206     protocol_decl = 0;
4207
4208   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4209   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4210
4211   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4212                                                  objc_implementation_context),
4213                      decl_specs, 1, NULL_TREE);
4214
4215   initlist = build_category_initializer (TREE_TYPE (decl),
4216                                          cat_name_expr, class_name_expr,
4217                                          UOBJC_INSTANCE_METHODS_decl,
4218                                          UOBJC_CLASS_METHODS_decl,
4219                                          protocol_decl);
4220
4221   TREE_USED (decl) = 1;
4222   finish_decl (decl, initlist, NULL_TREE);
4223 }
4224
4225 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4226    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
4227
4228 static void
4229 generate_shared_structures ()
4230 {
4231   tree sc_spec, decl_specs, decl;
4232   tree name_expr, super_expr, root_expr;
4233   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4234   tree cast_type, initlist, protocol_decl;
4235
4236   my_super_id = CLASS_SUPER_NAME (implementation_template);
4237   if (my_super_id)
4238     {
4239       add_class_reference (my_super_id);
4240
4241       /* Compute "my_root_id" - this is required for code generation.
4242          the "isa" for all meta class structures points to the root of
4243          the inheritance hierarchy (e.g. "__Object")...  */
4244       my_root_id = my_super_id;
4245       do
4246         {
4247           tree my_root_int = lookup_interface (my_root_id);
4248
4249           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4250             my_root_id = CLASS_SUPER_NAME (my_root_int);
4251           else
4252             break;
4253         }
4254       while (1);
4255     }
4256   else
4257     /* No super class.  */
4258     my_root_id = CLASS_NAME (implementation_template);
4259
4260   cast_type
4261     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4262                                                       objc_class_template),
4263                                      build1 (INDIRECT_REF,
4264                                              NULL_TREE, NULL_TREE)));
4265
4266   name_expr = add_objc_string (CLASS_NAME (implementation_template),
4267                                class_names);
4268
4269   /* Install class `isa' and `super' pointers at runtime.  */
4270   if (my_super_id)
4271     {
4272       super_expr = add_objc_string (my_super_id, class_names);
4273       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4274     }
4275   else
4276     super_expr = build_int_2 (0, 0);
4277
4278   root_expr = add_objc_string (my_root_id, class_names);
4279   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4280
4281   if (CLASS_PROTOCOL_LIST (implementation_template))
4282     {
4283       generate_protocol_references
4284         (CLASS_PROTOCOL_LIST (implementation_template));
4285       protocol_decl = generate_protocol_list (implementation_template);
4286     }
4287   else
4288     protocol_decl = 0;
4289
4290   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4291
4292   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4293   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4294
4295   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4296                      NULL_TREE);
4297
4298   initlist
4299     = build_shared_structure_initializer
4300       (TREE_TYPE (decl),
4301        root_expr, super_expr, name_expr,
4302        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
4303        2 /*CLS_META*/,
4304        UOBJC_CLASS_METHODS_decl,
4305        UOBJC_CLASS_VARIABLES_decl,
4306        protocol_decl);
4307
4308   finish_decl (decl, initlist, NULL_TREE);
4309
4310   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4311
4312   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4313                      NULL_TREE);
4314
4315   initlist
4316     = build_shared_structure_initializer
4317       (TREE_TYPE (decl),
4318        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4319        super_expr, name_expr,
4320        convert (integer_type_node,
4321                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
4322                                 (implementation_template))),
4323        1 /*CLS_FACTORY*/,
4324        UOBJC_INSTANCE_METHODS_decl,
4325        UOBJC_INSTANCE_VARIABLES_decl,
4326        protocol_decl);
4327
4328   finish_decl (decl, initlist, NULL_TREE);
4329 }
4330
4331 static tree
4332 synth_id_with_class_suffix (preamble, ctxt)
4333      const char *preamble;
4334      tree ctxt;
4335 {
4336   char *string;
4337   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4338       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4339     {
4340       const char *const class_name
4341         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4342       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4343       sprintf (string, "%s_%s", preamble,
4344                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4345     }
4346   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4347            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4348     {
4349       /* We have a category.  */
4350       const char *const class_name
4351         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4352       const char *const class_super_name
4353         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
4354       string = (char *) alloca (strlen (preamble)
4355                                 + strlen (class_name)
4356                                 + strlen (class_super_name)
4357                                 + 3);
4358       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4359     }
4360   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4361     {
4362       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4363       string
4364         = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4365       sprintf (string, "%s_%s", preamble, protocol_name);
4366     }
4367   else
4368     abort ();
4369   
4370   return get_identifier (string);
4371 }
4372
4373 static int
4374 is_objc_type_qualifier (node)
4375      tree node;
4376 {
4377   return (TREE_CODE (node) == IDENTIFIER_NODE
4378           && (node == ridpointers [(int) RID_CONST]
4379               || node == ridpointers [(int) RID_VOLATILE]
4380               || node == ridpointers [(int) RID_IN]
4381               || node == ridpointers [(int) RID_OUT]
4382               || node == ridpointers [(int) RID_INOUT]
4383               || node == ridpointers [(int) RID_BYCOPY]
4384               || node == ridpointers [(int) RID_BYREF]
4385               || node == ridpointers [(int) RID_ONEWAY]));
4386 }
4387
4388 /* If type is empty or only type qualifiers are present, add default
4389    type of id (otherwise grokdeclarator will default to int).  */
4390
4391 static tree
4392 adjust_type_for_id_default (type)
4393      tree type;
4394 {
4395   tree declspecs, chain;
4396
4397   if (!type)
4398     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4399                             build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4400
4401   declspecs = TREE_PURPOSE (type);
4402
4403   /* Determine if a typespec is present.  */
4404   for (chain = declspecs;
4405        chain;
4406        chain = TREE_CHAIN (chain))
4407     {
4408       if (TYPED_OBJECT (TREE_VALUE (chain))
4409           && !(TREE_VALUE (type) 
4410                && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
4411         error ("can not use an object as parameter to a method\n");
4412       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4413         return type;
4414     }
4415
4416   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4417                                      declspecs),
4418                           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4419 }
4420
4421 /*   Usage:
4422                 keyworddecl:
4423                         selector ':' '(' typename ')' identifier
4424   
4425      Purpose:
4426                 Transform an Objective-C keyword argument into
4427                 the C equivalent parameter declarator.
4428   
4429      In:        key_name, an "identifier_node" (optional).
4430                 arg_type, a  "tree_list" (optional).
4431                 arg_name, an "identifier_node".
4432   
4433      Note:      It would be really nice to strongly type the preceding
4434                 arguments in the function prototype; however, then I
4435                 could not use the "accessor" macros defined in "tree.h".
4436   
4437      Out:       an instance of "keyword_decl".  */
4438
4439 tree
4440 build_keyword_decl (key_name, arg_type, arg_name)
4441      tree key_name;
4442      tree arg_type;
4443      tree arg_name;
4444 {
4445   tree keyword_decl;
4446
4447   /* If no type is specified, default to "id".  */
4448   arg_type = adjust_type_for_id_default (arg_type);
4449
4450   keyword_decl = make_node (KEYWORD_DECL);
4451
4452   TREE_TYPE (keyword_decl) = arg_type;
4453   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4454   KEYWORD_KEY_NAME (keyword_decl) = key_name;
4455
4456   return keyword_decl;
4457 }
4458
4459 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
4460
4461 static tree
4462 build_keyword_selector (selector)
4463      tree selector;
4464 {
4465   int len = 0;
4466   tree key_chain, key_name;
4467   char *buf;
4468
4469   /* Scan the selector to see how much space we'll need.  */
4470   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4471     {
4472       if (TREE_CODE (selector) == KEYWORD_DECL)
4473         key_name = KEYWORD_KEY_NAME (key_chain);
4474       else if (TREE_CODE (selector) == TREE_LIST)
4475         key_name = TREE_PURPOSE (key_chain);
4476       else
4477         abort ();
4478
4479       if (key_name)
4480         len += IDENTIFIER_LENGTH (key_name) + 1;
4481       else
4482         /* Just a ':' arg.  */
4483         len++;
4484     }
4485
4486   buf = (char *) alloca (len + 1);
4487   /* Start the buffer out as an empty string.  */
4488   buf[0] = '\0';
4489
4490   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4491     {
4492       if (TREE_CODE (selector) == KEYWORD_DECL)
4493         key_name = KEYWORD_KEY_NAME (key_chain);
4494       else if (TREE_CODE (selector) == TREE_LIST)
4495         key_name = TREE_PURPOSE (key_chain);
4496       else
4497         abort ();
4498
4499       if (key_name)
4500         strcat (buf, IDENTIFIER_POINTER (key_name));
4501       strcat (buf, ":");
4502     }
4503
4504   return get_identifier (buf);
4505 }
4506
4507 /* Used for declarations and definitions.  */
4508
4509 tree
4510 build_method_decl (code, ret_type, selector, add_args)
4511      enum tree_code code;
4512      tree ret_type;
4513      tree selector;
4514      tree add_args;
4515 {
4516   tree method_decl;
4517
4518   /* If no type is specified, default to "id".  */
4519   ret_type = adjust_type_for_id_default (ret_type);
4520
4521   method_decl = make_node (code);
4522   TREE_TYPE (method_decl) = ret_type;
4523
4524   /* If we have a keyword selector, create an identifier_node that
4525      represents the full selector name (`:' included)...  */
4526   if (TREE_CODE (selector) == KEYWORD_DECL)
4527     {
4528       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4529       METHOD_SEL_ARGS (method_decl) = selector;
4530       METHOD_ADD_ARGS (method_decl) = add_args;
4531     }
4532   else
4533     {
4534       METHOD_SEL_NAME (method_decl) = selector;
4535       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4536       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4537     }
4538
4539   return method_decl;
4540 }
4541
4542 #define METHOD_DEF 0
4543 #define METHOD_REF 1
4544
4545 /* Used by `build_objc_method_call' and `comp_method_types'.  Return
4546    an argument list for method METH.  CONTEXT is either METHOD_DEF or
4547    METHOD_REF, saying whether we are trying to define a method or call
4548    one.  SUPERFLAG says this is for a send to super; this makes a
4549    difference for the NeXT calling sequence in which the lookup and
4550    the method call are done together.  */
4551
4552 static tree
4553 get_arg_type_list (meth, context, superflag)
4554      tree meth;
4555      int context;
4556      int superflag;
4557 {
4558   tree arglist, akey;
4559
4560   /* Receiver type.  */
4561   if (flag_next_runtime && superflag)
4562     arglist = build_tree_list (NULL_TREE, super_type);
4563   else if (context == METHOD_DEF)
4564     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4565   else
4566     arglist = build_tree_list (NULL_TREE, id_type);
4567
4568   /* Selector type - will eventually change to `int'.  */
4569   chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4570
4571   /* Build a list of argument types.  */
4572   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4573     {
4574       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4575       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4576     }
4577
4578   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
4579     /* We have a `, ...' immediately following the selector,
4580        finalize the arglist...simulate get_parm_info (0).  */
4581     ;
4582   else if (METHOD_ADD_ARGS (meth))
4583     {
4584       /* we have a variable length selector */
4585       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4586       chainon (arglist, add_arg_list);
4587     }
4588   else
4589     /* finalize the arglist...simulate get_parm_info (1) */
4590     chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4591
4592   return arglist;
4593 }
4594
4595 static tree
4596 check_duplicates (hsh)
4597      hash hsh;
4598 {
4599   tree meth = NULL_TREE;
4600
4601   if (hsh)
4602     {
4603       meth = hsh->key;
4604
4605       if (hsh->list)
4606         {
4607           /* We have two methods with the same name and different types.  */
4608           attr loop;
4609           char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4610
4611           warning ("multiple declarations for method `%s'",
4612                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4613
4614           warn_with_method ("using", type, meth);
4615           for (loop = hsh->list; loop; loop = loop->next)
4616             warn_with_method ("also found", type, loop->value);
4617         }
4618     }
4619   return meth;
4620 }
4621
4622 /* If RECEIVER is a class reference, return the identifier node for
4623    the referenced class.  RECEIVER is created by get_class_reference,
4624    so we check the exact form created depending on which runtimes are
4625    used.  */
4626
4627 static tree
4628 receiver_is_class_object (receiver)
4629       tree receiver;
4630 {
4631   tree chain, exp, arg;
4632
4633   /* The receiver is 'self' in the context of a class method.  */
4634   if (objc_method_context
4635       && receiver == self_decl
4636       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
4637     {
4638       return CLASS_NAME (objc_implementation_context);
4639     }
4640   
4641   if (flag_next_runtime)
4642     {
4643       /* The receiver is a variable created by
4644          build_class_reference_decl.  */
4645       if (TREE_CODE (receiver) == VAR_DECL
4646           && TREE_TYPE (receiver) == objc_class_type)
4647         /* Look up the identifier.  */
4648         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4649           if (TREE_PURPOSE (chain) == receiver)
4650             return TREE_VALUE (chain);
4651     }
4652   else
4653     {
4654       /* The receiver is a function call that returns an id.  Check if
4655          it is a call to objc_getClass, if so, pick up the class name.  */
4656       if (TREE_CODE (receiver) == CALL_EXPR 
4657           && (exp = TREE_OPERAND (receiver, 0))
4658           && TREE_CODE (exp) == ADDR_EXPR
4659           && (exp = TREE_OPERAND (exp, 0))
4660           && TREE_CODE (exp) == FUNCTION_DECL
4661           && exp == objc_get_class_decl
4662           /* We have a call to objc_getClass!  */
4663           && (arg = TREE_OPERAND (receiver, 1))
4664           && TREE_CODE (arg) == TREE_LIST
4665           && (arg = TREE_VALUE (arg)))
4666         {
4667           STRIP_NOPS (arg);
4668           if (TREE_CODE (arg) == ADDR_EXPR
4669               && (arg = TREE_OPERAND (arg, 0))
4670               && TREE_CODE (arg) == STRING_CST)
4671             /* Finally, we have the class name.  */
4672             return get_identifier (TREE_STRING_POINTER (arg));
4673         }
4674     }
4675   return 0;
4676 }
4677 \f
4678 /* If we are currently building a message expr, this holds
4679    the identifier of the selector of the message.  This is
4680    used when printing warnings about argument mismatches.  */
4681
4682 static tree current_objc_message_selector = 0;
4683
4684 tree
4685 objc_message_selector ()
4686 {
4687   return current_objc_message_selector;
4688 }
4689
4690 /* Construct an expression for sending a message.
4691    MESS has the object to send to in TREE_PURPOSE
4692    and the argument list (including selector) in TREE_VALUE.
4693
4694    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4695    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
4696
4697 tree
4698 build_message_expr (mess)
4699      tree mess;
4700 {
4701   tree receiver = TREE_PURPOSE (mess);
4702   tree sel_name;
4703   tree args = TREE_VALUE (mess);
4704   tree method_params = NULL_TREE;
4705
4706   if (TREE_CODE (receiver) == ERROR_MARK)
4707     return error_mark_node;
4708
4709   /* Obtain the full selector name.  */
4710   if (TREE_CODE (args) == IDENTIFIER_NODE)
4711     /* A unary selector.  */
4712     sel_name = args;
4713   else if (TREE_CODE (args) == TREE_LIST)
4714     sel_name = build_keyword_selector (args);
4715   else
4716     abort ();
4717
4718   /* Build the parameter list to give to the method.  */
4719   if (TREE_CODE (args) == TREE_LIST)
4720     {
4721       tree chain = args, prev = NULL_TREE;
4722
4723       /* We have a keyword selector--check for comma expressions.  */
4724       while (chain)
4725         {
4726           tree element = TREE_VALUE (chain);
4727
4728           /* We have a comma expression, must collapse...  */
4729           if (TREE_CODE (element) == TREE_LIST)
4730             {
4731               if (prev)
4732                 TREE_CHAIN (prev) = element;
4733               else
4734                 args = element;
4735             }
4736           prev = chain;
4737           chain = TREE_CHAIN (chain);
4738         }
4739       method_params = args;
4740     }
4741
4742   return finish_message_expr (receiver, sel_name, method_params);
4743 }
4744
4745 /* The 'finish_message_expr' routine is called from within
4746    'build_message_expr' for non-template functions.  In the case of
4747    C++ template functions, it is called from 'build_expr_from_tree'
4748    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
4749    
4750 tree
4751 finish_message_expr (receiver, sel_name, method_params)
4752      tree receiver, sel_name, method_params; 
4753 {      
4754   tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
4755   tree selector, self_object, retval;
4756   int statically_typed = 0, statically_allocated = 0;
4757   
4758   /* Determine receiver type.  */
4759   tree rtype = TREE_TYPE (receiver);
4760   int super = IS_SUPER (rtype);
4761
4762   if (! super)
4763     {
4764       if (TREE_STATIC_TEMPLATE (rtype))
4765         statically_allocated = 1;
4766       else if (TREE_CODE (rtype) == POINTER_TYPE
4767                && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4768         statically_typed = 1;
4769       else if ((flag_next_runtime
4770                 || (IS_ID (rtype)))
4771                && (class_ident = receiver_is_class_object (receiver)))
4772         ;
4773       else if (! IS_ID (rtype)
4774                /* Allow any type that matches objc_class_type.  */
4775                && ! comptypes (rtype, objc_class_type))
4776         {
4777           warning ("invalid receiver type `%s'",
4778                    gen_declaration (rtype, errbuf));
4779         }
4780       if (statically_allocated)
4781         receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4782
4783       /* Don't evaluate the receiver twice.  */
4784       receiver = save_expr (receiver);
4785       self_object = receiver;
4786     }
4787   else
4788     /* If sending to `super', use current self as the object.  */
4789     self_object = self_decl;
4790
4791   /* Determine operation return type.  */
4792
4793   if (super)
4794     {
4795       tree iface;
4796
4797       if (CLASS_SUPER_NAME (implementation_template))
4798         {
4799           iface
4800             = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4801
4802           if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
4803             method_prototype = lookup_instance_method_static (iface, sel_name);
4804           else
4805             method_prototype = lookup_class_method_static (iface, sel_name);
4806
4807           if (iface && !method_prototype)
4808             warning ("`%s' does not respond to `%s'",
4809                      IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4810                      IDENTIFIER_POINTER (sel_name));
4811         }
4812       else
4813         {
4814           error ("no super class declared in interface for `%s'",
4815                  IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4816           return error_mark_node;
4817         }
4818
4819     }
4820   else if (statically_allocated)
4821     {
4822       tree ctype = TREE_TYPE (rtype);
4823       tree iface = lookup_interface (TYPE_NAME (rtype));
4824
4825       if (iface)
4826         method_prototype = lookup_instance_method_static (iface, sel_name);
4827
4828       if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4829         method_prototype
4830           = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4831                                             sel_name, 0);
4832
4833       if (!method_prototype)
4834         warning ("`%s' does not respond to `%s'",
4835                  IDENTIFIER_POINTER (TYPE_NAME (rtype)),
4836                  IDENTIFIER_POINTER (sel_name));
4837     }
4838   else if (statically_typed)
4839     {
4840       tree ctype = TREE_TYPE (rtype);
4841
4842       /* `self' is now statically_typed.  All methods should be visible
4843          within the context of the implementation.  */
4844       if (objc_implementation_context
4845           && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
4846         {
4847           method_prototype
4848             = lookup_instance_method_static (implementation_template,
4849                                              sel_name);
4850
4851           if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4852             method_prototype
4853               = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4854                                                 sel_name, 0);
4855
4856           if (! method_prototype
4857               && implementation_template != objc_implementation_context)
4858             /* The method is not published in the interface.  Check
4859                locally.  */
4860             method_prototype
4861               = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
4862                                sel_name);
4863         }
4864       else
4865         {
4866           tree iface;
4867
4868           if ((iface = lookup_interface (TYPE_NAME (ctype))))
4869             method_prototype = lookup_instance_method_static (iface, sel_name);
4870
4871           if (! method_prototype)
4872             {
4873               tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
4874               if (protocol_list)
4875                 method_prototype
4876                   = lookup_method_in_protocol_list (protocol_list,
4877                                                     sel_name, 0);
4878             }
4879         }
4880
4881       if (!method_prototype)
4882         warning ("`%s' does not respond to `%s'",
4883                  IDENTIFIER_POINTER (TYPE_NAME (ctype)),
4884                  IDENTIFIER_POINTER (sel_name));
4885     }
4886   else if (class_ident)
4887     {
4888       if (objc_implementation_context
4889           && CLASS_NAME (objc_implementation_context) == class_ident)
4890         {
4891           method_prototype
4892             = lookup_class_method_static (implementation_template, sel_name);
4893
4894           if (!method_prototype
4895               && implementation_template != objc_implementation_context)
4896             /* The method is not published in the interface. Check
4897                locally.  */
4898             method_prototype
4899               = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
4900                                sel_name);
4901         }
4902       else
4903         {
4904           tree iface;
4905
4906           if ((iface = lookup_interface (class_ident)))
4907             method_prototype = lookup_class_method_static (iface, sel_name);
4908         }
4909
4910       if (!method_prototype)
4911         {
4912           warning ("cannot find class (factory) method");
4913           warning ("return type for `%s' defaults to id",
4914                    IDENTIFIER_POINTER (sel_name));
4915         }
4916     }
4917   else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
4918     {
4919       /* An anonymous object that has been qualified with a protocol.  */
4920
4921       tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
4922
4923       method_prototype = lookup_method_in_protocol_list (protocol_list,
4924                                                          sel_name, 0);
4925
4926       if (!method_prototype)
4927         {
4928           hash hsh;
4929
4930           warning ("method `%s' not implemented by protocol",
4931                    IDENTIFIER_POINTER (sel_name));
4932
4933           /* Try and find the method signature in the global pools.  */
4934
4935           if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
4936             hsh = hash_lookup (cls_method_hash_list, sel_name);
4937
4938           if (!(method_prototype = check_duplicates (hsh)))
4939             warning ("return type defaults to id");
4940         }
4941     }
4942   else
4943     {
4944       hash hsh;
4945
4946       /* We think we have an instance...loophole: extern id Object; */
4947       hsh = hash_lookup (nst_method_hash_list, sel_name);
4948       
4949       if (!hsh)
4950         /* For various loopholes */     
4951         hsh = hash_lookup (cls_method_hash_list, sel_name);
4952
4953       method_prototype = check_duplicates (hsh);
4954       if (!method_prototype)
4955         {
4956           warning ("cannot find method");
4957           warning ("return type for `%s' defaults to id",
4958                    IDENTIFIER_POINTER (sel_name));
4959         }
4960     }
4961
4962   /* Save the selector name for printing error messages.  */
4963   current_objc_message_selector = sel_name;
4964
4965   /* Build the parameters list for looking up the method.
4966      These are the object itself and the selector.  */
4967
4968   if (flag_typed_selectors)
4969     selector = build_typed_selector_reference (sel_name, method_prototype);
4970   else
4971     selector = build_selector_reference (sel_name);
4972
4973   retval = build_objc_method_call (super, method_prototype,
4974                                    receiver, self_object,
4975                                    selector, method_params);
4976
4977   current_objc_message_selector = 0;
4978
4979   return retval;
4980 }
4981 \f
4982 /* Build a tree expression to send OBJECT the operation SELECTOR,
4983    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
4984    assuming the method has prototype METHOD_PROTOTYPE.
4985    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
4986    Use METHOD_PARAMS as list of args to pass to the method.
4987    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
4988
4989 static tree
4990 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
4991                         selector, method_params)
4992      int super_flag;
4993      tree method_prototype, lookup_object, object, selector, method_params;
4994 {
4995   tree sender = (super_flag ? umsg_super_decl : umsg_decl);
4996   tree rcv_p = (super_flag
4997                 ? build_pointer_type (xref_tag (RECORD_TYPE,
4998                                                 get_identifier (TAG_SUPER)))
4999                 : id_type);
5000
5001   if (flag_next_runtime)
5002     {
5003       if (! method_prototype)
5004         {
5005           method_params = tree_cons (NULL_TREE, lookup_object,
5006                                      tree_cons (NULL_TREE, selector,
5007                                                 method_params));
5008           assemble_external (sender);
5009           return build_function_call (sender, method_params);
5010         }
5011       else
5012         {
5013           /* This is a real kludge, but it is used only for the Next.
5014              Clobber the data type of SENDER temporarily to accept
5015              all the arguments for this operation, and to return
5016              whatever this operation returns.  */
5017           tree arglist = NULL_TREE, retval, savarg, savret;
5018           tree ret_type = groktypename (TREE_TYPE (method_prototype));
5019
5020           /* Save the proper contents of SENDER's data type.  */
5021           savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5022           savret = TREE_TYPE (TREE_TYPE (sender));
5023
5024           /* Install this method's argument types.  */
5025           arglist = get_arg_type_list (method_prototype, METHOD_REF,
5026                                        super_flag);
5027           TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5028
5029           /* Install this method's return type.  */
5030           TREE_TYPE (TREE_TYPE (sender)) = ret_type;
5031
5032           /* Call SENDER with all the parameters.  This will do type
5033              checking using the arg types for this method.  */
5034           method_params = tree_cons (NULL_TREE, lookup_object,
5035                                      tree_cons (NULL_TREE, selector,
5036                                                 method_params));
5037           assemble_external (sender);
5038           retval = build_function_call (sender, method_params);
5039
5040           /* Restore SENDER's return/argument types.  */
5041           TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5042           TREE_TYPE (TREE_TYPE (sender)) = savret;
5043           return retval;
5044         }
5045     }
5046   else
5047     {
5048       /* This is the portable way.
5049          First call the lookup function to get a pointer to the method,
5050          then cast the pointer, then call it with the method arguments.  */
5051       tree method;
5052
5053       /* Avoid trouble since we may evaluate each of these twice.  */
5054       object = save_expr (object);
5055       selector = save_expr (selector);
5056
5057       lookup_object = build_c_cast (rcv_p, lookup_object);
5058
5059       assemble_external (sender);
5060       method
5061         = build_function_call (sender,
5062                                tree_cons (NULL_TREE, lookup_object,
5063                                           tree_cons (NULL_TREE, selector,
5064                                                      NULL_TREE)));
5065
5066       /* If we have a method prototype, construct the data type this
5067          method needs, and cast what we got from SENDER into a pointer
5068          to that type.  */
5069       if (method_prototype)
5070         {
5071           tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5072                                             super_flag);
5073           tree valtype = groktypename (TREE_TYPE (method_prototype));
5074           tree fake_function_type = build_function_type (valtype, arglist);
5075           TREE_TYPE (method) = build_pointer_type (fake_function_type);
5076         }
5077       else
5078         TREE_TYPE (method)
5079           = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5080
5081       /* Pass the object to the method.  */
5082       assemble_external (method);
5083       return build_function_call (method,
5084                                   tree_cons (NULL_TREE, object,
5085                                              tree_cons (NULL_TREE, selector,
5086                                                         method_params)));
5087     }
5088 }
5089 \f
5090 static void
5091 build_protocol_reference (p)
5092      tree p;
5093 {
5094   tree decl, ident, ptype;
5095
5096   /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5097
5098   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5099   ptype
5100     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5101                                                       objc_protocol_template),
5102                                      NULL_TREE));
5103
5104   if (IDENTIFIER_GLOBAL_VALUE (ident))
5105     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl.  */
5106   else
5107     {
5108       decl = build_decl (VAR_DECL, ident, ptype);
5109       DECL_EXTERNAL (decl) = 1;
5110       TREE_PUBLIC (decl) = 1;
5111       TREE_USED (decl) = 1;
5112       DECL_ARTIFICIAL (decl) = 1;
5113
5114       make_decl_rtl (decl, 0);
5115       pushdecl_top_level (decl);
5116    }
5117
5118   PROTOCOL_FORWARD_DECL (p) = decl;
5119 }
5120
5121 /* This function is called by the parser when (and only when) a
5122    @protocol() expression is found, in order to compile it.  */
5123 tree
5124 build_protocol_expr (protoname)
5125      tree protoname;
5126 {
5127   tree expr;
5128   tree p = lookup_protocol (protoname);
5129
5130   if (!p)
5131     {
5132       error ("cannot find protocol declaration for `%s'",
5133              IDENTIFIER_POINTER (protoname));
5134       return error_mark_node;
5135     }
5136
5137   if (!PROTOCOL_FORWARD_DECL (p))
5138     build_protocol_reference (p);
5139
5140   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5141
5142   TREE_TYPE (expr) = protocol_type;
5143
5144   /* The @protocol() expression is being compiled into a pointer to a
5145      statically allocated instance of the Protocol class.  To become
5146      usable at runtime, the 'isa' pointer of the instance need to be
5147      fixed up at runtime by the runtime library, to point to the
5148      actual 'Protocol' class.  */
5149
5150   /* For the GNU runtime, put the static Protocol instance in the list
5151      of statically allocated instances, so that we make sure that its
5152      'isa' pointer is fixed up at runtime by the GNU runtime library
5153      to point to the Protocol class (at runtime, when loading the
5154      module, the GNU runtime library loops on the statically allocated
5155      instances (as found in the defs field in objc_symtab) and fixups
5156      all the 'isa' pointers of those objects).  */
5157   if (! flag_next_runtime)
5158     {
5159       /* This type is a struct containing the fields of a Protocol
5160         object.  (Cfr. protocol_type instead is the type of a pointer
5161         to such a struct).  */
5162       tree protocol_struct_type = xref_tag 
5163        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
5164       tree *chain;
5165       
5166       /* Look for the list of Protocol statically allocated instances
5167         to fixup at runtime.  Create a new list to hold Protocol
5168         statically allocated instances, if the list is not found.  At
5169         present there is only another list, holding NSConstantString
5170         static instances to be fixed up at runtime.  */
5171       for (chain = &objc_static_instances;
5172            *chain && TREE_VALUE (*chain) != protocol_struct_type;
5173            chain = &TREE_CHAIN (*chain));
5174       if (!*chain)
5175         {
5176          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
5177          add_objc_string (TYPE_NAME (protocol_struct_type),
5178                           class_names);
5179        }
5180       
5181       /* Add this statically allocated instance to the Protocol list.  */
5182       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, 
5183                                          PROTOCOL_FORWARD_DECL (p),
5184                                          TREE_PURPOSE (*chain));
5185     }
5186   
5187
5188   return expr;
5189 }
5190
5191 /* This function is called by the parser when a @selector() expression
5192    is found, in order to compile it.  It is only called by the parser
5193    and only to compile a @selector().  */
5194 tree
5195 build_selector_expr (selnamelist)
5196      tree selnamelist;
5197 {
5198   tree selname;
5199
5200   /* Obtain the full selector name.  */
5201   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5202     /* A unary selector.  */
5203     selname = selnamelist;
5204   else if (TREE_CODE (selnamelist) == TREE_LIST)
5205     selname = build_keyword_selector (selnamelist);
5206   else
5207     abort ();
5208
5209   /* If we are required to check @selector() expressions as they
5210      are found, check that the selector has been declared.  */
5211   if (warn_undeclared_selector)
5212     {
5213       /* Look the selector up in the list of all known class and
5214          instance methods (up to this line) to check that the selector
5215          exists.  */
5216       hash hsh;
5217
5218       /* First try with instance methods.  */
5219       hsh = hash_lookup (nst_method_hash_list, selname);
5220       
5221       /* If not found, try with class methods.  */
5222       if (!hsh)
5223         {
5224           hsh = hash_lookup (cls_method_hash_list, selname);
5225         }
5226       
5227       /* If still not found, print out a warning.  */
5228       if (!hsh)
5229         {
5230           warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
5231         }
5232     }
5233   
5234
5235   if (flag_typed_selectors)
5236     return build_typed_selector_reference (selname, 0);
5237   else
5238     return build_selector_reference (selname);
5239 }
5240
5241 tree
5242 build_encode_expr (type)
5243      tree type;
5244 {
5245   tree result;
5246   const char *string;
5247
5248   encode_type (type, obstack_object_size (&util_obstack),
5249                OBJC_ENCODE_INLINE_DEFS);
5250   obstack_1grow (&util_obstack, 0);    /* null terminate string */
5251   string = obstack_finish (&util_obstack);
5252
5253   /* Synthesize a string that represents the encoded struct/union.  */
5254   result = my_build_string (strlen (string) + 1, string);
5255   obstack_free (&util_obstack, util_firstobj);
5256   return result;
5257 }
5258
5259 tree
5260 build_ivar_reference (id)
5261      tree id;
5262 {
5263   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
5264     {
5265       /* Historically, a class method that produced objects (factory
5266          method) would assign `self' to the instance that it
5267          allocated.  This would effectively turn the class method into
5268          an instance method.  Following this assignment, the instance
5269          variables could be accessed.  That practice, while safe,
5270          violates the simple rule that a class method should not refer
5271          to an instance variable.  It's better to catch the cases
5272          where this is done unknowingly than to support the above
5273          paradigm.  */
5274       warning ("instance variable `%s' accessed in class method",
5275                IDENTIFIER_POINTER (id));
5276       TREE_TYPE (self_decl) = instance_type; /* cast */
5277     }
5278
5279   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5280 }
5281 \f
5282 /* Compute a hash value for a given method SEL_NAME.  */
5283
5284 static size_t
5285 hash_func (sel_name)
5286      tree sel_name;
5287 {
5288   const unsigned char *s 
5289     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
5290   size_t h = 0;
5291   
5292   while (*s)
5293     h = h * 67 + *s++ - 113;
5294   return h;  
5295 }
5296      
5297 static void
5298 hash_init ()
5299 {
5300   nst_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5301   cls_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5302 }
5303
5304 /* WARNING!!!!  hash_enter is called with a method, and will peek
5305    inside to find its selector!  But hash_lookup is given a selector
5306    directly, and looks for the selector that's inside the found
5307    entry's key (method) for comparison.  */
5308
5309 static void
5310 hash_enter (hashlist, method)
5311      hash *hashlist;
5312      tree method;
5313 {
5314   hash obj;
5315   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5316
5317   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
5318   obj->list = 0;
5319   obj->next = hashlist[slot];
5320   obj->key = method;
5321
5322   hashlist[slot] = obj;         /* append to front */
5323 }
5324
5325 static hash
5326 hash_lookup (hashlist, sel_name)
5327      hash *hashlist;
5328      tree sel_name;
5329 {
5330   hash target;
5331
5332   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
5333
5334   while (target)
5335     {
5336       if (sel_name == METHOD_SEL_NAME (target->key))
5337         return target;
5338
5339       target = target->next;
5340     }
5341   return 0;
5342 }
5343
5344 static void
5345 hash_add_attr (entry, value)
5346      hash entry;
5347      tree value;
5348 {
5349   attr obj;
5350
5351   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
5352   obj->next = entry->list;
5353   obj->value = value;
5354
5355   entry->list = obj;            /* append to front */
5356 }
5357 \f
5358 static tree
5359 lookup_method (mchain, method)
5360      tree mchain;
5361      tree method;
5362 {
5363   tree key;
5364
5365   if (TREE_CODE (method) == IDENTIFIER_NODE)
5366     key = method;
5367   else
5368     key = METHOD_SEL_NAME (method);
5369
5370   while (mchain)
5371     {
5372       if (METHOD_SEL_NAME (mchain) == key)
5373         return mchain;
5374
5375       mchain = TREE_CHAIN (mchain);
5376     }
5377   return NULL_TREE;
5378 }
5379
5380 static tree
5381 lookup_instance_method_static (interface, ident)
5382      tree interface;
5383      tree ident;
5384 {
5385   tree inter = interface;
5386   tree chain = CLASS_NST_METHODS (inter);
5387   tree meth = NULL_TREE;
5388
5389   do
5390     {
5391       if ((meth = lookup_method (chain, ident)))
5392         return meth;
5393
5394       if (CLASS_CATEGORY_LIST (inter))
5395         {
5396           tree category = CLASS_CATEGORY_LIST (inter);
5397           chain = CLASS_NST_METHODS (category);
5398
5399           do
5400             {
5401               if ((meth = lookup_method (chain, ident)))
5402                 return meth;
5403
5404               /* Check for instance methods in protocols in categories.  */
5405               if (CLASS_PROTOCOL_LIST (category))
5406                 {
5407                   if ((meth = (lookup_method_in_protocol_list
5408                                (CLASS_PROTOCOL_LIST (category), ident, 0))))
5409                     return meth;
5410                 }
5411
5412               if ((category = CLASS_CATEGORY_LIST (category)))
5413                 chain = CLASS_NST_METHODS (category);
5414             }
5415           while (category);
5416         }
5417
5418       if (CLASS_PROTOCOL_LIST (inter))
5419         {
5420           if ((meth = (lookup_method_in_protocol_list
5421                        (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5422             return meth;
5423         }
5424
5425       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5426         chain = CLASS_NST_METHODS (inter);
5427     }
5428   while (inter);
5429
5430   return meth;
5431 }
5432
5433 static tree
5434 lookup_class_method_static (interface, ident)
5435      tree interface;
5436      tree ident;
5437 {
5438   tree inter = interface;
5439   tree chain = CLASS_CLS_METHODS (inter);
5440   tree meth = NULL_TREE;
5441   tree root_inter = NULL_TREE;
5442
5443   do
5444     {
5445       if ((meth = lookup_method (chain, ident)))
5446         return meth;
5447
5448       if (CLASS_CATEGORY_LIST (inter))
5449         {
5450           tree category = CLASS_CATEGORY_LIST (inter);
5451           chain = CLASS_CLS_METHODS (category);
5452
5453           do
5454             {
5455               if ((meth = lookup_method (chain, ident)))
5456                 return meth;
5457
5458               /* Check for class methods in protocols in categories.  */
5459               if (CLASS_PROTOCOL_LIST (category))
5460                 {
5461                   if ((meth = (lookup_method_in_protocol_list
5462                                (CLASS_PROTOCOL_LIST (category), ident, 1))))
5463                     return meth;
5464                 }
5465
5466               if ((category = CLASS_CATEGORY_LIST (category)))
5467                 chain = CLASS_CLS_METHODS (category);
5468             }
5469           while (category);
5470         }
5471
5472       /* Check for class methods in protocols.  */
5473       if (CLASS_PROTOCOL_LIST (inter))
5474         {
5475           if ((meth = (lookup_method_in_protocol_list
5476                        (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5477             return meth;
5478         }
5479
5480       root_inter = inter;
5481       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5482         chain = CLASS_CLS_METHODS (inter);
5483     }
5484   while (inter);
5485
5486   /* If no class (factory) method was found, check if an _instance_
5487      method of the same name exists in the root class.  This is what
5488      the Objective-C runtime will do.  */
5489   return lookup_instance_method_static (root_inter, ident);
5490 }
5491
5492 tree
5493 add_class_method (class, method)
5494      tree class;
5495      tree method;
5496 {
5497   tree mth;
5498   hash hsh;
5499
5500   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5501     {
5502       /* put method on list in reverse order */
5503       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5504       CLASS_CLS_METHODS (class) = method;
5505     }
5506   else
5507     {
5508       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5509         error ("duplicate definition of class method `%s'",
5510                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5511       else
5512         {
5513           /* Check types; if different, complain.  */
5514           if (!comp_proto_with_proto (method, mth))
5515             error ("duplicate declaration of class method `%s'",
5516                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5517         }
5518     }
5519
5520   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5521     {
5522       /* Install on a global chain.  */
5523       hash_enter (cls_method_hash_list, method);
5524     }
5525   else
5526     {
5527       /* Check types; if different, add to a list.  */
5528       if (!comp_proto_with_proto (method, hsh->key))
5529         hash_add_attr (hsh, method);
5530     }
5531   return method;
5532 }
5533 \f
5534 tree
5535 add_instance_method (class, method)
5536      tree class;
5537      tree method;
5538 {
5539   tree mth;
5540   hash hsh;
5541
5542   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5543     {
5544       /* Put method on list in reverse order.  */
5545       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5546       CLASS_NST_METHODS (class) = method;
5547     }
5548   else
5549     {
5550       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5551         error ("duplicate definition of instance method `%s'",
5552                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5553       else
5554         {
5555           /* Check types; if different, complain.  */
5556           if (!comp_proto_with_proto (method, mth))
5557             error ("duplicate declaration of instance method `%s'",
5558                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5559         }
5560     }
5561
5562   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5563     {
5564       /* Install on a global chain.  */
5565       hash_enter (nst_method_hash_list, method);
5566     }
5567   else
5568     {
5569       /* Check types; if different, add to a list.  */
5570       if (!comp_proto_with_proto (method, hsh->key))
5571         hash_add_attr (hsh, method);
5572     }
5573   return method;
5574 }
5575
5576 static tree
5577 add_class (class)
5578      tree class;
5579 {
5580   /* Put interfaces on list in reverse order.  */
5581   TREE_CHAIN (class) = interface_chain;
5582   interface_chain = class;
5583   return interface_chain;
5584 }
5585
5586 static void
5587 add_category (class, category)
5588       tree class;
5589       tree category;
5590 {
5591   /* Put categories on list in reverse order.  */
5592   tree cat = CLASS_CATEGORY_LIST (class);
5593
5594   while (cat)
5595     {
5596       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5597         warning ("duplicate interface declaration for category `%s(%s)'",
5598                  IDENTIFIER_POINTER (CLASS_NAME (class)),
5599                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5600       cat = CLASS_CATEGORY_LIST (cat);
5601     }
5602
5603   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5604   CLASS_CATEGORY_LIST (class) = category;
5605 }
5606
5607 /* Called after parsing each instance variable declaration. Necessary to
5608    preserve typedefs and implement public/private...
5609
5610    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
5611
5612 tree
5613 add_instance_variable (class, public, declarator, declspecs, width)
5614      tree class;
5615      int public;
5616      tree declarator;
5617      tree declspecs;
5618      tree width;
5619 {
5620   tree field_decl, raw_decl;
5621
5622   raw_decl = build_tree_list (declspecs, declarator);
5623
5624   if (CLASS_RAW_IVARS (class))
5625     chainon (CLASS_RAW_IVARS (class), raw_decl);
5626   else
5627     CLASS_RAW_IVARS (class) = raw_decl;
5628
5629   field_decl = grokfield (input_filename, lineno,
5630                           declarator, declspecs, width);
5631
5632   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
5633   switch (public)
5634     {
5635     case 0:
5636       TREE_PUBLIC (field_decl) = 0;
5637       TREE_PRIVATE (field_decl) = 0;
5638       TREE_PROTECTED (field_decl) = 1;
5639       break;
5640
5641     case 1:
5642       TREE_PUBLIC (field_decl) = 1;
5643       TREE_PRIVATE (field_decl) = 0;
5644       TREE_PROTECTED (field_decl) = 0;
5645       break;
5646
5647     case 2:
5648       TREE_PUBLIC (field_decl) = 0;
5649       TREE_PRIVATE (field_decl) = 1;
5650       TREE_PROTECTED (field_decl) = 0;
5651       break;
5652
5653     }
5654
5655   if (CLASS_IVARS (class))
5656     chainon (CLASS_IVARS (class), field_decl);
5657   else
5658     CLASS_IVARS (class) = field_decl;
5659
5660   return class;
5661 }
5662 \f
5663 tree
5664 is_ivar (decl_chain, ident)
5665      tree decl_chain;
5666      tree ident;
5667 {
5668   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5669     if (DECL_NAME (decl_chain) == ident)
5670       return decl_chain;
5671   return NULL_TREE;
5672 }
5673
5674 /* True if the ivar is private and we are not in its implementation.  */
5675
5676 int
5677 is_private (decl)
5678      tree decl;
5679 {
5680   if (TREE_PRIVATE (decl)
5681       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5682     {
5683       error ("instance variable `%s' is declared private",
5684              IDENTIFIER_POINTER (DECL_NAME (decl)));
5685       return 1;
5686     }
5687   else
5688     return 0;
5689 }
5690
5691 /* We have an instance variable reference;, check to see if it is public.  */
5692
5693 int
5694 is_public (expr, identifier)
5695      tree expr;
5696      tree identifier;
5697 {
5698   tree basetype = TREE_TYPE (expr);
5699   enum tree_code code = TREE_CODE (basetype);
5700   tree decl;
5701
5702   if (code == RECORD_TYPE)
5703     {
5704       if (TREE_STATIC_TEMPLATE (basetype))
5705         {
5706           if (!lookup_interface (TYPE_NAME (basetype)))
5707             {
5708               error ("cannot find interface declaration for `%s'",
5709                      IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5710               return 0;
5711             }
5712
5713           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5714             {
5715               if (TREE_PUBLIC (decl))
5716                 return 1;
5717
5718               /* Important difference between the Stepstone translator:
5719                  all instance variables should be public within the context
5720                  of the implementation.  */
5721               if (objc_implementation_context
5722                   && (((TREE_CODE (objc_implementation_context)
5723                         == CLASS_IMPLEMENTATION_TYPE)
5724                        || (TREE_CODE (objc_implementation_context)
5725                            == CATEGORY_IMPLEMENTATION_TYPE))
5726                       && (CLASS_NAME (objc_implementation_context)
5727                           == TYPE_NAME (basetype))))
5728                 return ! is_private (decl);
5729
5730               error ("instance variable `%s' is declared %s",
5731                      IDENTIFIER_POINTER (identifier),
5732                      TREE_PRIVATE (decl) ? "private" : "protected");
5733               return 0;
5734             }
5735         }
5736
5737       else if (objc_implementation_context && (basetype == objc_object_reference))
5738         {
5739           TREE_TYPE (expr) = uprivate_record;
5740           warning ("static access to object of type `id'");
5741         }
5742     }
5743
5744   return 1;
5745 }
5746 \f
5747 /* Make sure all entries in CHAIN are also in LIST.  */
5748
5749 static int
5750 check_methods (chain, list, mtype)
5751      tree chain;
5752      tree list;
5753      int mtype;
5754 {
5755   int first = 1;
5756
5757   while (chain)
5758     {
5759       if (!lookup_method (list, chain))
5760         {
5761           if (first)
5762             {
5763               if (TREE_CODE (objc_implementation_context)
5764                   == CLASS_IMPLEMENTATION_TYPE)
5765                 warning ("incomplete implementation of class `%s'",
5766                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
5767               else if (TREE_CODE (objc_implementation_context)
5768                        == CATEGORY_IMPLEMENTATION_TYPE)
5769                 warning ("incomplete implementation of category `%s'",
5770                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
5771               first = 0;
5772             }
5773
5774           warning ("method definition for `%c%s' not found",
5775                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5776         }
5777
5778       chain = TREE_CHAIN (chain);
5779     }
5780
5781     return first;
5782 }
5783
5784 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
5785
5786 static int
5787 conforms_to_protocol (class, protocol)
5788      tree class;
5789      tree protocol;
5790 {
5791    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
5792      {
5793        tree p = CLASS_PROTOCOL_LIST (class);
5794        while (p && TREE_VALUE (p) != protocol)
5795          p = TREE_CHAIN (p);
5796
5797        if (!p)
5798          {
5799            tree super = (CLASS_SUPER_NAME (class)
5800                          ? lookup_interface (CLASS_SUPER_NAME (class))
5801                          : NULL_TREE);
5802            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5803            if (!tmp)
5804              return 0;
5805          }
5806      }
5807
5808    return 1;
5809 }
5810
5811 /* Make sure all methods in CHAIN are accessible as MTYPE methods in 
5812    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
5813
5814 static int
5815 check_methods_accessible (chain, context, mtype)
5816      tree chain;
5817      tree context;
5818      int mtype;
5819 {
5820   int first = 1;
5821   tree list;
5822   tree base_context = context;
5823
5824   while (chain)
5825     {
5826       context = base_context;
5827       while (context)
5828         {
5829           if (mtype == '+')
5830             list = CLASS_CLS_METHODS (context);
5831           else
5832             list = CLASS_NST_METHODS (context);
5833
5834           if (lookup_method (list, chain))
5835               break; 
5836
5837           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5838                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5839             context = (CLASS_SUPER_NAME (context) 
5840                        ? lookup_interface (CLASS_SUPER_NAME (context))
5841                        : NULL_TREE);
5842
5843           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5844                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5845             context = (CLASS_NAME (context) 
5846                        ? lookup_interface (CLASS_NAME (context))
5847                        : NULL_TREE);
5848           else
5849             abort ();
5850         }
5851
5852       if (context == NULL_TREE)
5853         {
5854           if (first)
5855             {
5856               if (TREE_CODE (objc_implementation_context)
5857                   == CLASS_IMPLEMENTATION_TYPE)
5858                 warning ("incomplete implementation of class `%s'",
5859                          IDENTIFIER_POINTER
5860                            (CLASS_NAME (objc_implementation_context)));
5861               else if (TREE_CODE (objc_implementation_context)
5862                        == CATEGORY_IMPLEMENTATION_TYPE)
5863                 warning ("incomplete implementation of category `%s'",
5864                          IDENTIFIER_POINTER
5865                            (CLASS_SUPER_NAME (objc_implementation_context)));
5866               first = 0;
5867             }
5868           warning ("method definition for `%c%s' not found",
5869                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5870         }
5871
5872       chain = TREE_CHAIN (chain); /* next method...  */
5873     }
5874   return first;
5875 }
5876
5877 /* Check whether the current interface (accessible via
5878    'objc_implementation_context') actually implements protocol P, along
5879    with any protocols that P inherits.  */
5880    
5881 static void
5882 check_protocol (p, type, name)
5883      tree p;
5884      const char *type;
5885      const char *name;
5886 {
5887   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
5888     {
5889       int f1, f2;
5890
5891       /* Ensure that all protocols have bodies!  */
5892       if (warn_protocol)
5893         {
5894           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
5895                               CLASS_CLS_METHODS (objc_implementation_context),
5896                               '+');
5897           f2 = check_methods (PROTOCOL_NST_METHODS (p),
5898                               CLASS_NST_METHODS (objc_implementation_context),
5899                               '-');
5900         }
5901       else
5902         {
5903           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
5904                                          objc_implementation_context,
5905                                          '+');
5906           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
5907                                          objc_implementation_context,
5908                                          '-');
5909         }
5910
5911       if (!f1 || !f2)
5912         warning ("%s `%s' does not fully implement the `%s' protocol",
5913                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
5914     }
5915     
5916   /* Check protocols recursively.  */
5917   if (PROTOCOL_LIST (p))
5918     {
5919       tree subs = PROTOCOL_LIST (p);
5920       tree super_class =
5921         lookup_interface (CLASS_SUPER_NAME (implementation_template));
5922
5923       while (subs) 
5924         {
5925           tree sub = TREE_VALUE (subs);
5926
5927           /* If the superclass does not conform to the protocols
5928              inherited by P, then we must!  */
5929           if (!super_class || !conforms_to_protocol (super_class, sub))
5930             check_protocol (sub, type, name);
5931           subs = TREE_CHAIN (subs);
5932         }
5933     }
5934 }
5935         
5936 /* Check whether the current interface (accessible via
5937    'objc_implementation_context') actually implements the protocols listed
5938    in PROTO_LIST.  */
5939    
5940 static void
5941 check_protocols (proto_list, type, name)
5942      tree proto_list;
5943      const char *type;
5944      const char *name;
5945 {
5946   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
5947     {
5948       tree p = TREE_VALUE (proto_list);
5949
5950       check_protocol (p, type, name);
5951     }
5952 }
5953 \f
5954 /* Make sure that the class CLASS_NAME is defined
5955    CODE says which kind of thing CLASS_NAME ought to be.
5956    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
5957    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
5958
5959 tree
5960 start_class (code, class_name, super_name, protocol_list)
5961      enum tree_code code;
5962      tree class_name;
5963      tree super_name;
5964      tree protocol_list;
5965 {
5966   tree class, decl;
5967
5968   if (objc_implementation_context)
5969     {
5970       warning ("`@end' missing in implementation context");
5971       finish_class (objc_implementation_context);
5972       objc_ivar_chain = NULL_TREE;
5973       objc_implementation_context = NULL_TREE;
5974     }
5975
5976   class = make_node (code);
5977   TYPE_BINFO (class) = make_tree_vec (6);
5978
5979   CLASS_NAME (class) = class_name;
5980   CLASS_SUPER_NAME (class) = super_name;
5981   CLASS_CLS_METHODS (class) = NULL_TREE;
5982
5983   if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
5984     {
5985       error ("`%s' redeclared as different kind of symbol",
5986              IDENTIFIER_POINTER (class_name));
5987       error_with_decl (decl, "previous declaration of `%s'");
5988     }
5989
5990   if (code == CLASS_IMPLEMENTATION_TYPE)
5991     {
5992       {
5993         tree chain;
5994
5995         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
5996            if (TREE_VALUE (chain) == class_name)
5997              {
5998                error ("reimplementation of class `%s'",
5999                       IDENTIFIER_POINTER (class_name));
6000                return error_mark_node;
6001              }
6002         implemented_classes = tree_cons (NULL_TREE, class_name,
6003                                          implemented_classes);
6004       }
6005
6006       /* Pre-build the following entities - for speed/convenience.  */
6007       if (!self_id)
6008           self_id = get_identifier ("self");
6009       if (!ucmd_id)
6010         ucmd_id = get_identifier ("_cmd");
6011       if (!unused_list)
6012         unused_list
6013           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6014       if (!objc_super_template)
6015         objc_super_template = build_super_template ();
6016
6017       /* Reset for multiple classes per file.  */
6018       method_slot = 0;
6019
6020       objc_implementation_context = class;
6021
6022       /* Lookup the interface for this implementation.  */
6023
6024       if (!(implementation_template = lookup_interface (class_name)))
6025         {
6026           warning ("cannot find interface declaration for `%s'",
6027                    IDENTIFIER_POINTER (class_name));
6028           add_class (implementation_template = objc_implementation_context);
6029         }
6030
6031       /* If a super class has been specified in the implementation,
6032          insure it conforms to the one specified in the interface.  */
6033
6034       if (super_name
6035           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6036         {
6037           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6038           const char *const name =
6039             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6040           error ("conflicting super class name `%s'",
6041                  IDENTIFIER_POINTER (super_name));
6042           error ("previous declaration of `%s'", name);
6043         }
6044
6045       else if (! super_name)
6046         {
6047           CLASS_SUPER_NAME (objc_implementation_context) 
6048             = CLASS_SUPER_NAME (implementation_template);
6049         }
6050     }
6051
6052   else if (code == CLASS_INTERFACE_TYPE)
6053     {
6054       if (lookup_interface (class_name))
6055         warning ("duplicate interface declaration for class `%s'",
6056                  IDENTIFIER_POINTER (class_name));
6057       else
6058         add_class (class);
6059
6060       if (protocol_list)
6061         CLASS_PROTOCOL_LIST (class)
6062           = lookup_and_install_protocols (protocol_list);
6063     }
6064
6065   else if (code == CATEGORY_INTERFACE_TYPE)
6066     {
6067       tree class_category_is_assoc_with;
6068
6069       /* For a category, class_name is really the name of the class that
6070          the following set of methods will be associated with. We must
6071          find the interface so that can derive the objects template.  */
6072
6073       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6074         {
6075           error ("cannot find interface declaration for `%s'",
6076                  IDENTIFIER_POINTER (class_name));
6077           exit (FATAL_EXIT_CODE);
6078         }
6079       else
6080         add_category (class_category_is_assoc_with, class);
6081
6082       if (protocol_list)
6083         CLASS_PROTOCOL_LIST (class)
6084           = lookup_and_install_protocols (protocol_list);
6085     }
6086
6087   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6088     {
6089       /* Pre-build the following entities for speed/convenience.  */
6090       if (!self_id)
6091         self_id = get_identifier ("self");
6092       if (!ucmd_id)
6093         ucmd_id = get_identifier ("_cmd");
6094       if (!unused_list)
6095         unused_list
6096           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6097       if (!objc_super_template)
6098         objc_super_template = build_super_template ();
6099
6100       /* Reset for multiple classes per file.  */
6101       method_slot = 0;
6102
6103       objc_implementation_context = class;
6104
6105       /* For a category, class_name is really the name of the class that
6106          the following set of methods will be associated with.  We must
6107          find the interface so that can derive the objects template.  */
6108
6109       if (!(implementation_template = lookup_interface (class_name)))
6110         {
6111           error ("cannot find interface declaration for `%s'",
6112                  IDENTIFIER_POINTER (class_name));
6113           exit (FATAL_EXIT_CODE);
6114         }
6115     }
6116   return class;
6117 }
6118
6119 tree
6120 continue_class (class)
6121      tree class;
6122 {
6123   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6124       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6125     {
6126       struct imp_entry *imp_entry;
6127       tree ivar_context;
6128
6129       /* Check consistency of the instance variables.  */
6130
6131       if (CLASS_IVARS (class))
6132         check_ivars (implementation_template, class);
6133
6134       /* code generation */
6135
6136       ivar_context = build_private_template (implementation_template);
6137
6138       if (!objc_class_template)
6139         build_class_template ();
6140
6141       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6142
6143       imp_entry->next = imp_list;
6144       imp_entry->imp_context = class;
6145       imp_entry->imp_template = implementation_template;
6146
6147       synth_forward_declarations ();
6148       imp_entry->class_decl = UOBJC_CLASS_decl;
6149       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6150
6151       /* Append to front and increment count.  */
6152       imp_list = imp_entry;
6153       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6154         imp_count++;
6155       else
6156         cat_count++;
6157
6158       return ivar_context;
6159     }
6160
6161   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6162     {
6163       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6164
6165       if (!TYPE_FIELDS (record))
6166         {
6167           finish_struct (record, get_class_ivars (class), NULL_TREE);
6168           CLASS_STATIC_TEMPLATE (class) = record;
6169
6170           /* Mark this record as a class template for static typing.  */
6171           TREE_STATIC_TEMPLATE (record) = 1;
6172         }
6173
6174       return NULL_TREE;
6175     }
6176
6177   else
6178     return error_mark_node;
6179 }
6180
6181 /* This is called once we see the "@end" in an interface/implementation.  */
6182
6183 void
6184 finish_class (class)
6185      tree class;
6186 {
6187   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6188     {
6189       /* All code generation is done in finish_objc.  */
6190
6191       if (implementation_template != objc_implementation_context)
6192         {
6193           /* Ensure that all method listed in the interface contain bodies.  */
6194           check_methods (CLASS_CLS_METHODS (implementation_template),
6195                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6196           check_methods (CLASS_NST_METHODS (implementation_template),
6197                          CLASS_NST_METHODS (objc_implementation_context), '-');
6198
6199           if (CLASS_PROTOCOL_LIST (implementation_template))
6200             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6201                              "class",
6202                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6203         }
6204     }
6205
6206   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6207     {
6208       tree category = CLASS_CATEGORY_LIST (implementation_template);
6209
6210       /* Find the category interface from the class it is associated with.  */
6211       while (category)
6212         {
6213           if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6214             break;
6215           category = CLASS_CATEGORY_LIST (category);
6216         }
6217
6218       if (category)
6219         {
6220           /* Ensure all method listed in the interface contain bodies.  */
6221           check_methods (CLASS_CLS_METHODS (category),
6222                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6223           check_methods (CLASS_NST_METHODS (category),
6224                          CLASS_NST_METHODS (objc_implementation_context), '-');
6225
6226           if (CLASS_PROTOCOL_LIST (category))
6227             check_protocols (CLASS_PROTOCOL_LIST (category),
6228                              "category",
6229                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6230         }
6231     }
6232
6233   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6234     {
6235       tree decl_specs;
6236       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6237       char *string = (char *) alloca (strlen (class_name) + 3);
6238
6239       /* extern struct objc_object *_<my_name>; */
6240
6241       sprintf (string, "_%s", class_name);
6242
6243       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6244       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6245       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6246                    decl_specs);
6247     }
6248 }
6249
6250 static tree
6251 add_protocol (protocol)
6252      tree protocol;
6253 {
6254   /* Put protocol on list in reverse order.  */
6255   TREE_CHAIN (protocol) = protocol_chain;
6256   protocol_chain = protocol;
6257   return protocol_chain;
6258 }
6259
6260 static tree
6261 lookup_protocol (ident)
6262      tree ident;
6263 {
6264   tree chain;
6265
6266   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6267     if (ident == PROTOCOL_NAME (chain))
6268       return chain;
6269
6270   return NULL_TREE;
6271 }
6272
6273 /* This function forward declares the protocols named by NAMES.  If
6274    they are already declared or defined, the function has no effect.  */
6275
6276 void
6277 objc_declare_protocols (names)
6278      tree names;
6279 {
6280   tree list;
6281
6282   for (list = names; list; list = TREE_CHAIN (list))
6283     {
6284       tree name = TREE_VALUE (list);
6285
6286       if (lookup_protocol (name) == NULL_TREE)
6287         {
6288           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6289
6290           TYPE_BINFO (protocol) = make_tree_vec (2);
6291           PROTOCOL_NAME (protocol) = name;
6292           PROTOCOL_LIST (protocol) = NULL_TREE;
6293           add_protocol (protocol);
6294           PROTOCOL_DEFINED (protocol) = 0;
6295           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6296         }
6297     }
6298 }
6299
6300 tree
6301 start_protocol (code, name, list)
6302      enum tree_code code;
6303      tree name;
6304      tree list;
6305 {
6306   tree protocol;
6307
6308   /* This is as good a place as any.  Need to invoke
6309      push_tag_toplevel.  */
6310   if (!objc_protocol_template)
6311     objc_protocol_template = build_protocol_template ();
6312
6313   protocol = lookup_protocol (name);
6314
6315   if (!protocol)
6316     {
6317       protocol = make_node (code);
6318       TYPE_BINFO (protocol) = make_tree_vec (2);
6319
6320       PROTOCOL_NAME (protocol) = name;
6321       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6322       add_protocol (protocol);
6323       PROTOCOL_DEFINED (protocol) = 1;
6324       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6325
6326       check_protocol_recursively (protocol, list);
6327     }
6328   else if (! PROTOCOL_DEFINED (protocol))
6329     {
6330       PROTOCOL_DEFINED (protocol) = 1;
6331       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6332
6333       check_protocol_recursively (protocol, list);
6334     }
6335   else
6336     {
6337       warning ("duplicate declaration for protocol `%s'",
6338                IDENTIFIER_POINTER (name));
6339     }
6340   return protocol;
6341 }
6342
6343 void
6344 finish_protocol (protocol)
6345      tree protocol ATTRIBUTE_UNUSED;
6346 {
6347 }
6348
6349 \f
6350 /* "Encode" a data type into a string, which grows in util_obstack.
6351    ??? What is the FORMAT?  Someone please document this!  */
6352
6353 static void
6354 encode_type_qualifiers (declspecs)
6355      tree declspecs;
6356 {
6357   tree spec;
6358
6359   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6360     {
6361       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6362         obstack_1grow (&util_obstack, 'r');
6363       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6364         obstack_1grow (&util_obstack, 'n');
6365       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6366         obstack_1grow (&util_obstack, 'N');
6367       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6368         obstack_1grow (&util_obstack, 'o');
6369       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6370         obstack_1grow (&util_obstack, 'O');
6371       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6372         obstack_1grow (&util_obstack, 'R');
6373       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6374         obstack_1grow (&util_obstack, 'V');
6375     }
6376 }
6377
6378 /* Encode a pointer type.  */
6379
6380 static void
6381 encode_pointer (type, curtype, format)
6382      tree type;
6383      int curtype;
6384      int format;
6385 {
6386   tree pointer_to = TREE_TYPE (type);
6387
6388   if (TREE_CODE (pointer_to) == RECORD_TYPE)
6389     {
6390       if (TYPE_NAME (pointer_to)
6391           && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6392         {
6393           const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6394
6395           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6396             {
6397               obstack_1grow (&util_obstack, '@');
6398               return;
6399             }
6400           else if (TREE_STATIC_TEMPLATE (pointer_to))
6401             {
6402               if (generating_instance_variables)
6403                 {
6404                   obstack_1grow (&util_obstack, '@');
6405                   obstack_1grow (&util_obstack, '"');
6406                   obstack_grow (&util_obstack, name, strlen (name));
6407                   obstack_1grow (&util_obstack, '"');
6408                   return;
6409                 }
6410               else
6411                 {
6412                   obstack_1grow (&util_obstack, '@');
6413                   return;
6414                 }
6415             }
6416           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6417             {
6418               obstack_1grow (&util_obstack, '#');
6419               return;
6420             }
6421           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6422             {
6423               obstack_1grow (&util_obstack, ':');
6424               return;
6425             }
6426         }
6427     }
6428   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6429            && TYPE_MODE (pointer_to) == QImode)
6430     {
6431       obstack_1grow (&util_obstack, '*');
6432       return;
6433     }
6434
6435   /* We have a type that does not get special treatment.  */
6436
6437   /* NeXT extension */
6438   obstack_1grow (&util_obstack, '^');
6439   encode_type (pointer_to, curtype, format);
6440 }
6441
6442 static void
6443 encode_array (type, curtype, format)
6444      tree type;
6445      int curtype;
6446      int format;
6447 {
6448   tree an_int_cst = TYPE_SIZE (type);
6449   tree array_of = TREE_TYPE (type);
6450   char buffer[40];
6451
6452   /* An incomplete array is treated like a pointer.  */
6453   if (an_int_cst == NULL)
6454     {
6455       encode_pointer (type, curtype, format);
6456       return;
6457     }
6458
6459   sprintf (buffer, "[%ld",
6460            (long) (TREE_INT_CST_LOW (an_int_cst)
6461                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6462
6463   obstack_grow (&util_obstack, buffer, strlen (buffer));
6464   encode_type (array_of, curtype, format);
6465   obstack_1grow (&util_obstack, ']');
6466   return;
6467 }
6468 \f
6469 static void
6470 encode_aggregate_within (type, curtype, format, left, right)
6471      tree type;
6472      int curtype;
6473      int format;
6474      int left;
6475      int right;
6476 {
6477   /* The RECORD_TYPE may in fact be a typedef!  For purposes
6478      of encoding, we need the real underlying enchilada.  */
6479   if (TYPE_MAIN_VARIANT (type))
6480     type = TYPE_MAIN_VARIANT (type);
6481
6482   if (obstack_object_size (&util_obstack) > 0
6483       && *(obstack_next_free (&util_obstack) - 1) == '^')
6484     {
6485       tree name = TYPE_NAME (type);
6486
6487       /* we have a reference; this is a NeXT extension.  */
6488
6489       if (obstack_object_size (&util_obstack) - curtype == 1
6490           && format == OBJC_ENCODE_INLINE_DEFS)
6491         {
6492           /* Output format of struct for first level only.  */
6493           tree fields = TYPE_FIELDS (type);
6494
6495           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6496             {
6497               obstack_1grow (&util_obstack, left);
6498               obstack_grow (&util_obstack,
6499                             IDENTIFIER_POINTER (name),
6500                             strlen (IDENTIFIER_POINTER (name)));
6501               obstack_1grow (&util_obstack, '=');
6502             }
6503           else
6504             {
6505               obstack_1grow (&util_obstack, left);
6506               obstack_grow (&util_obstack, "?=", 2);
6507             }
6508
6509           for ( ; fields; fields = TREE_CHAIN (fields))
6510               encode_field_decl (fields, curtype, format);
6511
6512           obstack_1grow (&util_obstack, right);
6513         }
6514
6515       else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6516         {
6517           obstack_1grow (&util_obstack, left);
6518           obstack_grow (&util_obstack,
6519                         IDENTIFIER_POINTER (name),
6520                         strlen (IDENTIFIER_POINTER (name)));
6521           obstack_1grow (&util_obstack, right);
6522         }
6523
6524       else
6525         {
6526           /* We have an untagged structure or a typedef.  */
6527           obstack_1grow (&util_obstack, left);
6528           obstack_1grow (&util_obstack, '?');
6529           obstack_1grow (&util_obstack, right);
6530         }
6531     }
6532
6533   else
6534     {
6535       tree name = TYPE_NAME (type);
6536       tree fields = TYPE_FIELDS (type);
6537
6538       if (format == OBJC_ENCODE_INLINE_DEFS
6539           || generating_instance_variables)
6540         {
6541           obstack_1grow (&util_obstack, left);
6542           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6543               obstack_grow (&util_obstack,
6544                           IDENTIFIER_POINTER (name),
6545                           strlen (IDENTIFIER_POINTER (name)));
6546           else
6547               obstack_1grow (&util_obstack, '?');
6548
6549           obstack_1grow (&util_obstack, '=');
6550
6551           for (; fields; fields = TREE_CHAIN (fields))
6552             {
6553               if (generating_instance_variables)
6554                 {
6555                   tree fname = DECL_NAME (fields);
6556
6557                   obstack_1grow (&util_obstack, '"');
6558                   if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6559                     {
6560                       obstack_grow (&util_obstack,
6561                                     IDENTIFIER_POINTER (fname),
6562                                     strlen (IDENTIFIER_POINTER (fname)));
6563                     }
6564
6565                   obstack_1grow (&util_obstack, '"');
6566                 }
6567
6568               encode_field_decl (fields, curtype, format);
6569             }
6570
6571           obstack_1grow (&util_obstack, right);
6572         }
6573
6574       else
6575         {
6576           obstack_1grow (&util_obstack, left);
6577           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6578               obstack_grow (&util_obstack,
6579                             IDENTIFIER_POINTER (name),
6580                             strlen (IDENTIFIER_POINTER (name)));
6581           else
6582               /* We have an untagged structure or a typedef.  */
6583               obstack_1grow (&util_obstack, '?');
6584
6585           obstack_1grow (&util_obstack, right);
6586         }
6587     }
6588 }
6589
6590 static void
6591 encode_aggregate (type, curtype, format)
6592      tree type;
6593      int curtype;
6594      int format;
6595 {
6596   enum tree_code code = TREE_CODE (type);
6597
6598   switch (code)
6599     {
6600     case RECORD_TYPE:
6601       {
6602         encode_aggregate_within(type, curtype, format, '{', '}');
6603         break;
6604       }
6605     case UNION_TYPE:
6606       {
6607         encode_aggregate_within(type, curtype, format, '(', ')');
6608         break;
6609       }
6610
6611     case ENUMERAL_TYPE:
6612       obstack_1grow (&util_obstack, 'i');
6613       break;
6614
6615     default:
6616       break;
6617     }
6618 }
6619
6620 /* Support bitfields.  The current version of Objective-C does not support
6621    them.  The string will consist of one or more "b:n"'s where n is an
6622    integer describing the width of the bitfield. Currently, classes in
6623    the kit implement a method "-(char *)describeBitfieldStruct:" that
6624    simulates this. If they do not implement this method, the archiver
6625    assumes the bitfield is 16 bits wide (padded if necessary) and packed
6626    according to the GNU compiler. After looking at the "kit", it appears
6627    that all classes currently rely on this default behavior, rather than
6628    hand generating this string (which is tedious).  */
6629
6630 static void
6631 encode_bitfield (width)
6632      int width;
6633 {
6634   char buffer[40];
6635   sprintf (buffer, "b%d", width);
6636   obstack_grow (&util_obstack, buffer, strlen (buffer));
6637 }
6638 \f
6639 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
6640
6641 static void
6642 encode_type (type, curtype, format)
6643      tree type;
6644      int curtype;
6645      int format;
6646 {
6647   enum tree_code code = TREE_CODE (type);
6648
6649   if (code == INTEGER_TYPE)
6650     {
6651       if (integer_zerop (TYPE_MIN_VALUE (type)))
6652         {
6653           /* Unsigned integer types.  */
6654
6655           if (TYPE_MODE (type) == QImode)
6656             obstack_1grow (&util_obstack, 'C');
6657           else if (TYPE_MODE (type) == HImode)
6658             obstack_1grow (&util_obstack, 'S');
6659           else if (TYPE_MODE (type) == SImode)
6660             {
6661               if (type == long_unsigned_type_node)
6662                 obstack_1grow (&util_obstack, 'L');
6663               else
6664                 obstack_1grow (&util_obstack, 'I');
6665             }
6666           else if (TYPE_MODE (type) == DImode)
6667             obstack_1grow (&util_obstack, 'Q');
6668         }
6669
6670       else
6671         /* Signed integer types.  */
6672         {
6673           if (TYPE_MODE (type) == QImode)
6674             obstack_1grow (&util_obstack, 'c');
6675           else if (TYPE_MODE (type) == HImode)
6676             obstack_1grow (&util_obstack, 's');
6677           else if (TYPE_MODE (type) == SImode)
6678             {
6679               if (type == long_integer_type_node)
6680                 obstack_1grow (&util_obstack, 'l');
6681               else
6682                 obstack_1grow (&util_obstack, 'i');
6683             }
6684
6685           else if (TYPE_MODE (type) == DImode)
6686             obstack_1grow (&util_obstack, 'q');
6687         }
6688     }
6689
6690   else if (code == REAL_TYPE)
6691     {
6692       /* Floating point types.  */
6693
6694       if (TYPE_MODE (type) == SFmode)
6695         obstack_1grow (&util_obstack, 'f');
6696       else if (TYPE_MODE (type) == DFmode
6697                || TYPE_MODE (type) == TFmode)
6698         obstack_1grow (&util_obstack, 'd');
6699     }
6700
6701   else if (code == VOID_TYPE)
6702     obstack_1grow (&util_obstack, 'v');
6703
6704   else if (code == ARRAY_TYPE)
6705     encode_array (type, curtype, format);
6706
6707   else if (code == POINTER_TYPE)
6708     encode_pointer (type, curtype, format);
6709
6710   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6711     encode_aggregate (type, curtype, format);
6712
6713   else if (code == FUNCTION_TYPE) /* '?' */
6714     obstack_1grow (&util_obstack, '?');
6715 }
6716
6717 static void
6718 encode_complete_bitfield (position, type, size)
6719      int position;
6720      tree type;
6721      int size;
6722 {
6723   enum tree_code code = TREE_CODE (type);
6724   char buffer[40];
6725   char charType = '?';
6726
6727   if (code == INTEGER_TYPE)
6728     {
6729       if (integer_zerop (TYPE_MIN_VALUE (type)))
6730         {
6731           /* Unsigned integer types.  */
6732
6733           if (TYPE_MODE (type) == QImode)
6734             charType = 'C';
6735           else if (TYPE_MODE (type) == HImode)
6736             charType = 'S';
6737           else if (TYPE_MODE (type) == SImode)
6738             {
6739               if (type == long_unsigned_type_node)
6740                 charType = 'L';
6741               else
6742                 charType = 'I';
6743             }
6744           else if (TYPE_MODE (type) == DImode)
6745             charType = 'Q';
6746         }
6747
6748       else
6749         /* Signed integer types.  */
6750         {
6751           if (TYPE_MODE (type) == QImode)
6752             charType = 'c';
6753           else if (TYPE_MODE (type) == HImode)
6754             charType = 's';
6755           else if (TYPE_MODE (type) == SImode)
6756             {
6757               if (type == long_integer_type_node)
6758                 charType = 'l';
6759               else
6760                 charType = 'i';
6761             }
6762
6763           else if (TYPE_MODE (type) == DImode)
6764             charType = 'q';
6765         }
6766     }
6767   else if (code == ENUMERAL_TYPE)
6768     charType = 'i';
6769   else
6770     abort ();
6771
6772   sprintf (buffer, "b%d%c%d", position, charType, size);
6773   obstack_grow (&util_obstack, buffer, strlen (buffer));
6774 }
6775
6776 static void
6777 encode_field_decl (field_decl, curtype, format)
6778      tree field_decl;
6779      int curtype;
6780      int format;
6781 {
6782   tree type;
6783
6784   type = TREE_TYPE (field_decl);
6785
6786   /* If this field is obviously a bitfield, or is a bitfield that has been
6787      clobbered to look like a ordinary integer mode, go ahead and generate
6788      the bitfield typing information.  */
6789   if (flag_next_runtime)
6790     {
6791       if (DECL_BIT_FIELD_TYPE (field_decl))
6792         encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6793       else
6794         encode_type (TREE_TYPE (field_decl), curtype, format);
6795     }
6796   else
6797     {
6798       if (DECL_BIT_FIELD_TYPE (field_decl))
6799         encode_complete_bitfield (int_bit_position (field_decl),
6800                                   DECL_BIT_FIELD_TYPE (field_decl),
6801                                   tree_low_cst (DECL_SIZE (field_decl), 1));
6802       else
6803         encode_type (TREE_TYPE (field_decl), curtype, format);
6804     }
6805 }
6806
6807 static tree
6808 expr_last (complex_expr)
6809      tree complex_expr;
6810 {
6811   tree next;
6812
6813   if (complex_expr)
6814     while ((next = TREE_OPERAND (complex_expr, 0)))
6815       complex_expr = next;
6816
6817   return complex_expr;
6818 }
6819 \f
6820 /* Transform a method definition into a function definition as follows:
6821    - synthesize the first two arguments, "self" and "_cmd".  */
6822
6823 void
6824 start_method_def (method)
6825      tree method;
6826 {
6827   tree decl_specs;
6828
6829   /* Required to implement _msgSuper.  */
6830   objc_method_context = method;
6831   UOBJC_SUPER_decl = NULL_TREE;
6832
6833   /* Must be called BEFORE start_function.  */
6834   pushlevel (0);
6835
6836   /* Generate prototype declarations for arguments..."new-style".  */
6837
6838   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
6839     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6840   else
6841     /* Really a `struct objc_class *'. However, we allow people to
6842        assign to self, which changes its type midstream.  */
6843     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6844
6845   push_parm_decl (build_tree_list
6846                   (build_tree_list (decl_specs,
6847                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
6848                    unused_list));
6849
6850   decl_specs = build_tree_list (NULL_TREE,
6851                                 xref_tag (RECORD_TYPE,
6852                                           get_identifier (TAG_SELECTOR)));
6853   push_parm_decl (build_tree_list
6854                   (build_tree_list (decl_specs,
6855                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6856                    unused_list));
6857
6858   /* Generate argument declarations if a keyword_decl.  */
6859   if (METHOD_SEL_ARGS (method))
6860     {
6861       tree arglist = METHOD_SEL_ARGS (method);
6862       do
6863         {
6864           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6865           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6866
6867           if (arg_decl)
6868             {
6869               tree last_expr = expr_last (arg_decl);
6870
6871               /* Unite the abstract decl with its name.  */
6872               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6873               push_parm_decl (build_tree_list
6874                               (build_tree_list (arg_spec, arg_decl),
6875                                NULL_TREE));
6876
6877               /* Unhook: restore the abstract declarator.  */
6878               TREE_OPERAND (last_expr, 0) = NULL_TREE;
6879             }
6880
6881           else
6882             push_parm_decl (build_tree_list
6883                             (build_tree_list (arg_spec,
6884                                               KEYWORD_ARG_NAME (arglist)),
6885                              NULL_TREE));
6886
6887           arglist = TREE_CHAIN (arglist);
6888         }
6889       while (arglist);
6890     }
6891
6892   if (METHOD_ADD_ARGS (method) != NULL_TREE
6893       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
6894     {
6895       /* We have a variable length selector - in "prototype" format.  */
6896       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6897       while (akey)
6898         {
6899           /* This must be done prior to calling pushdecl.  pushdecl is
6900              going to change our chain on us.  */
6901           tree nextkey = TREE_CHAIN (akey);
6902           pushdecl (akey);
6903           akey = nextkey;
6904         }
6905     }
6906 }
6907
6908 static void
6909 warn_with_method (message, mtype, method)
6910      const char *message;
6911      int mtype;
6912      tree method;
6913 {
6914   if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
6915     return;
6916
6917   diagnostic_report_current_function (global_dc);
6918
6919   /* Add a readable method name to the warning.  */
6920   warning_with_file_and_line (DECL_SOURCE_FILE (method),
6921                               DECL_SOURCE_LINE (method),
6922                               "%s `%c%s'",
6923                               message, mtype,
6924                               gen_method_decl (method, errbuf));
6925 }
6926
6927 /* Return 1 if METHOD is consistent with PROTO.  */
6928
6929 static int
6930 comp_method_with_proto (method, proto)
6931      tree method, proto;
6932 {
6933   /* Create a function template node at most once.  */
6934   if (!function1_template)
6935     function1_template = make_node (FUNCTION_TYPE);
6936
6937   /* Install argument types - normally set by build_function_type.  */
6938   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
6939
6940   /* install return type */
6941   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
6942
6943   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
6944 }
6945
6946 /* Return 1 if PROTO1 is consistent with PROTO2.  */
6947
6948 static int
6949 comp_proto_with_proto (proto0, proto1)
6950      tree proto0, proto1;
6951 {
6952   /* Create a couple of function_template nodes at most once.  */
6953   if (!function1_template)
6954     function1_template = make_node (FUNCTION_TYPE);
6955   if (!function2_template)
6956     function2_template = make_node (FUNCTION_TYPE);
6957
6958   /* Install argument types; normally set by build_function_type.  */
6959   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
6960   TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
6961
6962   /* Install return type.  */
6963   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
6964   TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
6965
6966   return comptypes (function1_template, function2_template);
6967 }
6968
6969 /* - Generate an identifier for the function. the format is "_n_cls",
6970      where 1 <= n <= nMethods, and cls is the name the implementation we
6971      are processing.
6972    - Install the return type from the method declaration.
6973    - If we have a prototype, check for type consistency.  */
6974
6975 static void
6976 really_start_method (method, parmlist)
6977      tree method, parmlist;
6978 {
6979   tree sc_spec, ret_spec, ret_decl, decl_specs;
6980   tree method_decl, method_id;
6981   const char *sel_name, *class_name, *cat_name;
6982   char *buf;
6983
6984   /* Synth the storage class & assemble the return type.  */
6985   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
6986   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
6987   decl_specs = chainon (sc_spec, ret_spec);
6988
6989   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
6990   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
6991   cat_name = ((TREE_CODE (objc_implementation_context)
6992                == CLASS_IMPLEMENTATION_TYPE)
6993               ? NULL
6994               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6995   method_slot++;
6996
6997   /* Make sure this is big enough for any plausible method label.  */
6998   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
6999                          + (cat_name ? strlen (cat_name) : 0));
7000
7001   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7002                          class_name, cat_name, sel_name, method_slot);
7003
7004   method_id = get_identifier (buf);
7005
7006   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7007
7008   /* Check the declarator portion of the return type for the method.  */
7009   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7010     {
7011       /* Unite the complex decl (specified in the abstract decl) with the
7012          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7013       tree save_expr = expr_last (ret_decl);
7014
7015       TREE_OPERAND (save_expr, 0) = method_decl;
7016       method_decl = ret_decl;
7017
7018       /* Fool the parser into thinking it is starting a function.  */
7019       start_function (decl_specs, method_decl, NULL_TREE);
7020
7021       /* Unhook: this has the effect of restoring the abstract declarator.  */
7022       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7023     }
7024
7025   else
7026     {
7027       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7028
7029       /* Fool the parser into thinking it is starting a function.  */
7030       start_function (decl_specs, method_decl, NULL_TREE);
7031
7032       /* Unhook: this has the effect of restoring the abstract declarator.  */
7033       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7034     }
7035
7036   METHOD_DEFINITION (method) = current_function_decl;
7037
7038   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7039
7040   if (implementation_template != objc_implementation_context)
7041     {
7042       tree proto;
7043
7044       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7045         proto = lookup_instance_method_static (implementation_template,
7046                                                METHOD_SEL_NAME (method));
7047       else
7048         proto = lookup_class_method_static (implementation_template,
7049                                             METHOD_SEL_NAME (method));
7050
7051       if (proto && ! comp_method_with_proto (method, proto))
7052         {
7053           char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7054
7055           warn_with_method ("conflicting types for", type, method);
7056           warn_with_method ("previous declaration of", type, proto);
7057         }
7058     }
7059 }
7060
7061 /* The following routine is always called...this "architecture" is to
7062    accommodate "old-style" variable length selectors.
7063  
7064    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7065
7066 void
7067 continue_method_def ()
7068 {
7069   tree parmlist;
7070
7071   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7072     /* We have a `, ...' immediately following the selector.  */
7073     parmlist = get_parm_info (0);
7074   else
7075     parmlist = get_parm_info (1); /* place a `void_at_end' */
7076
7077   /* Set self_decl from the first argument...this global is used by
7078      build_ivar_reference calling build_indirect_ref.  */
7079   self_decl = TREE_PURPOSE (parmlist);
7080
7081   poplevel (0, 0, 0);
7082   really_start_method (objc_method_context, parmlist);
7083   store_parm_decls ();
7084 }
7085
7086 /* Called by the parser, from the `pushlevel' production.  */
7087
7088 void
7089 add_objc_decls ()
7090 {
7091   if (!UOBJC_SUPER_decl)
7092     {
7093       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7094                                      build_tree_list (NULL_TREE,
7095                                                       objc_super_template),
7096                                      0, NULL_TREE);
7097
7098       finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7099
7100       /* This prevents `unused variable' warnings when compiling with -Wall.  */
7101       TREE_USED (UOBJC_SUPER_decl) = 1;
7102       DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7103     }
7104 }
7105
7106 /* _n_Method (id self, SEL sel, ...)
7107      {
7108        struct objc_super _S;
7109        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7110      }  */
7111
7112 tree
7113 get_super_receiver ()
7114 {
7115   if (objc_method_context)
7116     {
7117       tree super_expr, super_expr_list;
7118
7119       /* Set receiver to self.  */
7120       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7121       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7122       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7123
7124       /* Set class to begin searching.  */
7125       super_expr = build_component_ref (UOBJC_SUPER_decl,
7126                                         get_identifier ("class"));
7127
7128       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7129         {
7130           /* [_cls, __cls]Super are "pre-built" in
7131              synth_forward_declarations.  */
7132
7133           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7134                                           ((TREE_CODE (objc_method_context)
7135                                             == INSTANCE_METHOD_DECL)
7136                                            ? ucls_super_ref
7137                                            : uucls_super_ref));
7138         }
7139
7140       else
7141         /* We have a category.  */
7142         {
7143           tree super_name = CLASS_SUPER_NAME (implementation_template);
7144           tree super_class;
7145
7146           /* Barf if super used in a category of Object.  */
7147           if (!super_name)
7148             {
7149               error ("no super class declared in interface for `%s'",
7150                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7151               return error_mark_node;
7152             }
7153
7154           if (flag_next_runtime)
7155             {
7156               super_class = get_class_reference (super_name);
7157               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7158                 /* Cast the super class to 'id', since the user may not have
7159                    included <objc/objc-class.h>, leaving 'struct objc_class'
7160                    an incomplete type.  */
7161                 super_class
7162                   = build_component_ref (build_indirect_ref 
7163                                          (build_c_cast (id_type, super_class), "->"),
7164                                           get_identifier ("isa"));
7165             }
7166           else
7167             {
7168               add_class_reference (super_name);
7169               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7170                              ? objc_get_class_decl : objc_get_meta_class_decl);
7171               assemble_external (super_class);
7172               super_class
7173                 = build_function_call
7174                   (super_class,
7175                    build_tree_list
7176                    (NULL_TREE,
7177                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7178                                      IDENTIFIER_POINTER (super_name))));
7179             }
7180
7181           TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7182           super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7183         }
7184
7185       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7186
7187       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7188       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7189
7190       return build_compound_expr (super_expr_list);
7191     }
7192   else
7193     {
7194       error ("[super ...] must appear in a method context");
7195       return error_mark_node;
7196     }
7197 }
7198
7199 static tree
7200 encode_method_def (func_decl)
7201       tree func_decl;
7202 {
7203   tree parms;
7204   int stack_size;
7205   HOST_WIDE_INT max_parm_end = 0;
7206   char buffer[40];
7207   tree result;
7208
7209   /* Return type.  */
7210   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7211                obstack_object_size (&util_obstack),
7212                OBJC_ENCODE_INLINE_DEFS);
7213
7214   /* Stack size.  */
7215   for (parms = DECL_ARGUMENTS (func_decl); parms;
7216        parms = TREE_CHAIN (parms))
7217     {
7218       HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7219                                 + int_size_in_bytes (TREE_TYPE (parms)));
7220
7221       if (! offset_is_register && parm_end > max_parm_end)
7222         max_parm_end = parm_end;
7223     }
7224
7225   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7226
7227   sprintf (buffer, "%d", stack_size);
7228   obstack_grow (&util_obstack, buffer, strlen (buffer));
7229
7230   /* Argument types.  */
7231   for (parms = DECL_ARGUMENTS (func_decl); parms;
7232        parms = TREE_CHAIN (parms))
7233     {
7234       /* Type.  */
7235       encode_type (TREE_TYPE (parms),
7236                    obstack_object_size (&util_obstack),
7237                    OBJC_ENCODE_INLINE_DEFS);
7238
7239       /* Compute offset.  */
7240       sprintf (buffer, "%d", forwarding_offset (parms));
7241
7242       /* Indicate register.  */
7243       if (offset_is_register)
7244         obstack_1grow (&util_obstack, '+');
7245
7246       obstack_grow (&util_obstack, buffer, strlen (buffer));
7247     }
7248
7249   /* Null terminate string.  */
7250   obstack_1grow (&util_obstack, 0);
7251   result = get_identifier (obstack_finish (&util_obstack));
7252   obstack_free (&util_obstack, util_firstobj);
7253   return result;
7254 }
7255
7256 static void
7257 objc_expand_function_end ()
7258 {
7259   METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
7260 }
7261
7262 void
7263 finish_method_def ()
7264 {
7265   lang_expand_function_end = objc_expand_function_end;
7266   finish_function (0, 1);
7267   lang_expand_function_end = NULL;
7268
7269   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7270      since the optimizer may find "may be used before set" errors.  */
7271   objc_method_context = NULL_TREE;
7272 }
7273
7274 #if 0
7275 int
7276 lang_report_error_function (decl)
7277       tree decl;
7278 {
7279   if (objc_method_context)
7280     {
7281       fprintf (stderr, "In method `%s'\n",
7282                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7283       return 1;
7284     }
7285
7286   else
7287     return 0;
7288 }
7289 #endif
7290
7291 static int
7292 is_complex_decl (type)
7293      tree type;
7294 {
7295   return (TREE_CODE (type) == ARRAY_TYPE
7296           || TREE_CODE (type) == FUNCTION_TYPE
7297           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7298 }
7299
7300 \f
7301 /* Code to convert a decl node into text for a declaration in C.  */
7302
7303 static char tmpbuf[256];
7304
7305 static void
7306 adorn_decl (decl, str)
7307      tree decl;
7308      char *str;
7309 {
7310   enum tree_code code = TREE_CODE (decl);
7311
7312   if (code == ARRAY_REF)
7313     {
7314       tree an_int_cst = TREE_OPERAND (decl, 1);
7315
7316       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7317         sprintf (str + strlen (str), "[%ld]",
7318                  (long) TREE_INT_CST_LOW (an_int_cst));
7319       else
7320         strcat (str, "[]");
7321     }
7322
7323   else if (code == ARRAY_TYPE)
7324     {
7325       tree an_int_cst = TYPE_SIZE (decl);
7326       tree array_of = TREE_TYPE (decl);
7327
7328       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7329         sprintf (str + strlen (str), "[%ld]",
7330                  (long) (TREE_INT_CST_LOW (an_int_cst)
7331                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7332       else
7333         strcat (str, "[]");
7334     }
7335
7336   else if (code == CALL_EXPR)
7337     {
7338       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7339
7340       strcat (str, "(");
7341       while (chain)
7342         {
7343           gen_declaration_1 (chain, str);
7344           chain = TREE_CHAIN (chain);
7345           if (chain)
7346             strcat (str, ", ");
7347         }
7348       strcat (str, ")");
7349     }
7350
7351   else if (code == FUNCTION_TYPE)
7352     {
7353       tree chain  = TYPE_ARG_TYPES (decl);
7354
7355       strcat (str, "(");
7356       while (chain && TREE_VALUE (chain) != void_type_node)
7357         {
7358           gen_declaration_1 (TREE_VALUE (chain), str);
7359           chain = TREE_CHAIN (chain);
7360           if (chain && TREE_VALUE (chain) != void_type_node)
7361             strcat (str, ", ");
7362         }
7363       strcat (str, ")");
7364     }
7365
7366   else if (code == INDIRECT_REF)
7367     {
7368       strcpy (tmpbuf, "*");
7369       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7370         {
7371           tree chain;
7372
7373           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7374                chain;
7375                chain = TREE_CHAIN (chain))
7376             {
7377               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7378                 {
7379                   strcat (tmpbuf, " ");
7380                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7381                 }
7382             }
7383           if (str[0])
7384             strcat (tmpbuf, " ");
7385         }
7386       strcat (tmpbuf, str);
7387       strcpy (str, tmpbuf);
7388     }
7389
7390   else if (code == POINTER_TYPE)
7391     {
7392       strcpy (tmpbuf, "*");
7393       if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7394         {
7395           if (TREE_READONLY (decl))
7396             strcat (tmpbuf, " const");
7397           if (TYPE_VOLATILE (decl))
7398             strcat (tmpbuf, " volatile");
7399           if (str[0])
7400             strcat (tmpbuf, " ");
7401         }
7402       strcat (tmpbuf, str);
7403       strcpy (str, tmpbuf);
7404     }
7405 }
7406
7407 static char *
7408 gen_declarator (decl, buf, name)
7409      tree decl;
7410      char *buf;
7411      const char *name;
7412 {
7413   if (decl)
7414     {
7415       enum tree_code code = TREE_CODE (decl);
7416       char *str;
7417       tree op;
7418       int wrap = 0;
7419
7420       switch (code)
7421         {
7422         case ARRAY_REF:
7423         case INDIRECT_REF:
7424         case CALL_EXPR:
7425           op = TREE_OPERAND (decl, 0);
7426
7427           /* We have a pointer to a function or array...(*)(), (*)[] */
7428           if ((code == ARRAY_REF || code == CALL_EXPR)
7429               && op && TREE_CODE (op) == INDIRECT_REF)
7430             wrap = 1;
7431
7432           str = gen_declarator (op, buf, name);
7433
7434           if (wrap)
7435             {
7436               strcpy (tmpbuf, "(");
7437               strcat (tmpbuf, str);
7438               strcat (tmpbuf, ")");
7439               strcpy (str, tmpbuf);
7440             }
7441
7442           adorn_decl (decl, str);
7443           break;
7444
7445         case ARRAY_TYPE:
7446         case FUNCTION_TYPE:
7447         case POINTER_TYPE:
7448           strcpy (buf, name);
7449           str = buf;
7450
7451           /* This clause is done iteratively rather than recursively.  */
7452           do
7453             {
7454               op = (is_complex_decl (TREE_TYPE (decl))
7455                     ? TREE_TYPE (decl) : NULL_TREE);
7456
7457               adorn_decl (decl, str);
7458
7459               /* We have a pointer to a function or array...(*)(), (*)[] */
7460               if (code == POINTER_TYPE
7461                   && op && (TREE_CODE (op) == FUNCTION_TYPE
7462                             || TREE_CODE (op) == ARRAY_TYPE))
7463                 {
7464                   strcpy (tmpbuf, "(");
7465                   strcat (tmpbuf, str);
7466                   strcat (tmpbuf, ")");
7467                   strcpy (str, tmpbuf);
7468                 }
7469
7470               decl = (is_complex_decl (TREE_TYPE (decl))
7471                       ? TREE_TYPE (decl) : NULL_TREE);
7472             }
7473
7474           while (decl && (code = TREE_CODE (decl)))
7475             ;
7476
7477           break;
7478
7479         case IDENTIFIER_NODE:
7480           /* Will only happen if we are processing a "raw" expr-decl.  */
7481           strcpy (buf, IDENTIFIER_POINTER (decl));
7482           return buf;
7483
7484         default:
7485           abort ();
7486         }
7487
7488       return str;
7489     }
7490
7491   else
7492     /* We have an abstract declarator or a _DECL node.  */
7493     {
7494       strcpy (buf, name);
7495       return buf;
7496     }
7497 }
7498
7499 static void
7500 gen_declspecs (declspecs, buf, raw)
7501      tree declspecs;
7502      char *buf;
7503      int raw;
7504 {
7505   if (raw)
7506     {
7507       tree chain;
7508
7509       for (chain = nreverse (copy_list (declspecs));
7510            chain; chain = TREE_CHAIN (chain))
7511         {
7512           tree aspec = TREE_VALUE (chain);
7513
7514           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7515             strcat (buf, IDENTIFIER_POINTER (aspec));
7516           else if (TREE_CODE (aspec) == RECORD_TYPE)
7517             {
7518               if (TYPE_NAME (aspec))
7519                 {
7520                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7521
7522                   if (! TREE_STATIC_TEMPLATE (aspec))
7523                     strcat (buf, "struct ");
7524                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7525
7526                   /* NEW!!! */
7527                   if (protocol_list)
7528                     {
7529                       tree chain = protocol_list;
7530
7531                       strcat (buf, " <");
7532                       while (chain)
7533                         {
7534                           strcat (buf,
7535                                   IDENTIFIER_POINTER
7536                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
7537                           chain = TREE_CHAIN (chain);
7538                           if (chain)
7539                             strcat (buf, ", ");
7540                         }
7541                       strcat (buf, ">");
7542                     }
7543                 }
7544
7545               else
7546                 strcat (buf, "untagged struct");
7547             }
7548
7549           else if (TREE_CODE (aspec) == UNION_TYPE)
7550             {
7551               if (TYPE_NAME (aspec))
7552                 {
7553                   if (! TREE_STATIC_TEMPLATE (aspec))
7554                     strcat (buf, "union ");
7555                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7556                 }
7557               else
7558                 strcat (buf, "untagged union");
7559             }
7560
7561           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7562             {
7563               if (TYPE_NAME (aspec))
7564                 {
7565                   if (! TREE_STATIC_TEMPLATE (aspec))
7566                     strcat (buf, "enum ");
7567                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7568                 }
7569               else
7570                 strcat (buf, "untagged enum");
7571             }
7572
7573           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7574             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7575
7576           else if (IS_ID (aspec))
7577             {
7578               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7579
7580               strcat (buf, "id");
7581               if (protocol_list)
7582                 {
7583                   tree chain = protocol_list;
7584
7585                   strcat (buf, " <");
7586                   while (chain)
7587                     {
7588                       strcat (buf,
7589                               IDENTIFIER_POINTER
7590                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7591                       chain = TREE_CHAIN (chain);
7592                       if (chain)
7593                         strcat (buf, ", ");
7594                     }
7595                   strcat (buf, ">");
7596                 }
7597             }
7598           if (TREE_CHAIN (chain))
7599             strcat (buf, " ");
7600         }
7601     }
7602   else
7603     {
7604       /* Type qualifiers.  */
7605       if (TREE_READONLY (declspecs))
7606         strcat (buf, "const ");
7607       if (TYPE_VOLATILE (declspecs))
7608         strcat (buf, "volatile ");
7609
7610       switch (TREE_CODE (declspecs))
7611         {
7612           /* Type specifiers.  */
7613
7614         case INTEGER_TYPE:
7615           declspecs = TYPE_MAIN_VARIANT (declspecs);
7616
7617           /* Signed integer types.  */
7618
7619           if (declspecs == short_integer_type_node)
7620             strcat (buf, "short int ");
7621           else if (declspecs == integer_type_node)
7622             strcat (buf, "int ");
7623           else if (declspecs == long_integer_type_node)
7624             strcat (buf, "long int ");
7625           else if (declspecs == long_long_integer_type_node)
7626             strcat (buf, "long long int ");
7627           else if (declspecs == signed_char_type_node
7628                    || declspecs == char_type_node)
7629             strcat (buf, "char ");
7630
7631           /* Unsigned integer types.  */
7632
7633           else if (declspecs == short_unsigned_type_node)
7634             strcat (buf, "unsigned short ");
7635           else if (declspecs == unsigned_type_node)
7636             strcat (buf, "unsigned int ");
7637           else if (declspecs == long_unsigned_type_node)
7638             strcat (buf, "unsigned long ");
7639           else if (declspecs == long_long_unsigned_type_node)
7640             strcat (buf, "unsigned long long ");
7641           else if (declspecs == unsigned_char_type_node)
7642             strcat (buf, "unsigned char ");
7643           break;
7644
7645         case REAL_TYPE:
7646           declspecs = TYPE_MAIN_VARIANT (declspecs);
7647
7648           if (declspecs == float_type_node)
7649             strcat (buf, "float ");
7650           else if (declspecs == double_type_node)
7651             strcat (buf, "double ");
7652           else if (declspecs == long_double_type_node)
7653             strcat (buf, "long double ");
7654           break;
7655
7656         case RECORD_TYPE:
7657           if (TYPE_NAME (declspecs)
7658               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7659             {
7660               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7661
7662               if (! TREE_STATIC_TEMPLATE (declspecs))
7663                 strcat (buf, "struct ");
7664               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7665
7666               if (protocol_list)
7667                 {
7668                   tree chain = protocol_list;
7669
7670                   strcat (buf, " <");
7671                   while (chain)
7672                     {
7673                       strcat (buf,
7674                               IDENTIFIER_POINTER
7675                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7676                       chain = TREE_CHAIN (chain);
7677                       if (chain)
7678                         strcat (buf, ", ");
7679                     }
7680                   strcat (buf, ">");
7681                 }
7682             }
7683
7684           else
7685             strcat (buf, "untagged struct");
7686
7687           strcat (buf, " ");
7688           break;
7689
7690         case UNION_TYPE:
7691           if (TYPE_NAME (declspecs)
7692               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7693             {
7694               strcat (buf, "union ");
7695               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7696               strcat (buf, " ");
7697             }
7698
7699           else
7700             strcat (buf, "untagged union ");
7701           break;
7702
7703         case ENUMERAL_TYPE:
7704           if (TYPE_NAME (declspecs)
7705               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7706             {
7707               strcat (buf, "enum ");
7708               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7709               strcat (buf, " ");
7710             }
7711
7712           else
7713             strcat (buf, "untagged enum ");
7714           break;
7715
7716         case VOID_TYPE:
7717           strcat (buf, "void ");
7718           break;
7719
7720         case POINTER_TYPE:
7721           {
7722             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7723
7724             strcat (buf, "id");
7725             if (protocol_list)
7726               {
7727                 tree chain = protocol_list;
7728
7729                 strcat (buf, " <");
7730                 while (chain)
7731                   {
7732                     strcat (buf,
7733                             IDENTIFIER_POINTER
7734                             (PROTOCOL_NAME (TREE_VALUE (chain))));
7735                     chain = TREE_CHAIN (chain);
7736                     if (chain)
7737                       strcat (buf, ", ");
7738                   }
7739
7740                 strcat (buf, ">");
7741               }
7742           }
7743           break;
7744           
7745         default:
7746           break;
7747         }
7748     }
7749 }
7750
7751 /* Given a tree node, produce a printable description of it in the given
7752    buffer, overwriting the buffer.  */
7753
7754 static char *
7755 gen_declaration (atype_or_adecl, buf)
7756      tree atype_or_adecl;
7757      char *buf;
7758 {
7759   buf[0] = '\0';
7760   gen_declaration_1 (atype_or_adecl, buf);
7761   return buf;
7762 }
7763
7764 /* Given a tree node, append a printable description to the end of the
7765    given buffer.  */
7766
7767 static void
7768 gen_declaration_1 (atype_or_adecl, buf)
7769      tree atype_or_adecl;
7770      char *buf;
7771 {
7772   char declbuf[256];
7773
7774   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7775     {
7776       tree declspecs;   /* "identifier_node", "record_type" */
7777       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
7778
7779       /* We have a "raw", abstract declarator (typename).  */
7780       declarator = TREE_VALUE (atype_or_adecl);
7781       declspecs  = TREE_PURPOSE (atype_or_adecl);
7782
7783       gen_declspecs (declspecs, buf, 1);
7784       if (declarator)
7785         {
7786           strcat (buf, " ");
7787           strcat (buf, gen_declarator (declarator, declbuf, ""));
7788         }
7789     }
7790
7791   else
7792     {
7793       tree atype;
7794       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
7795       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
7796
7797       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7798           || TREE_CODE (atype_or_adecl) == PARM_DECL
7799           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7800         atype = TREE_TYPE (atype_or_adecl);
7801       else
7802         /* Assume we have a *_type node.  */
7803         atype = atype_or_adecl;
7804
7805       if (is_complex_decl (atype))
7806         {
7807           tree chain;
7808
7809           /* Get the declaration specifier; it is at the end of the list.  */
7810           declarator = chain = atype;
7811           do
7812             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7813           while (is_complex_decl (chain));
7814           declspecs = chain;
7815         }
7816
7817       else
7818         {
7819           declspecs = atype;
7820           declarator = NULL_TREE;
7821         }
7822
7823       gen_declspecs (declspecs, buf, 0);
7824
7825       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7826           || TREE_CODE (atype_or_adecl) == PARM_DECL
7827           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7828         {
7829           const char *const decl_name =
7830             (DECL_NAME (atype_or_adecl)
7831              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
7832
7833           if (declarator)
7834             {
7835               strcat (buf, " ");
7836               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7837             }
7838
7839           else if (decl_name[0])
7840             {
7841               strcat (buf, " ");
7842               strcat (buf, decl_name);
7843             }
7844         }
7845       else if (declarator)
7846         {
7847           strcat (buf, " ");
7848           strcat (buf, gen_declarator (declarator, declbuf, ""));
7849         }
7850     }
7851 }
7852
7853 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7854
7855 /* Given a method tree, put a printable description into the given
7856    buffer (overwriting) and return a pointer to the buffer.  */
7857
7858 static char *
7859 gen_method_decl (method, buf)
7860      tree method;
7861      char *buf;
7862 {
7863   tree chain;
7864
7865   buf[0] = '\0';
7866   if (RAW_TYPESPEC (method) != objc_object_reference)
7867     {
7868       strcat (buf, "(");
7869       gen_declaration_1 (TREE_TYPE (method), buf);
7870       strcat (buf, ")");
7871     }
7872
7873   chain = METHOD_SEL_ARGS (method);
7874   if (chain)
7875     {
7876       /* We have a chain of keyword_decls.  */
7877       do
7878         {
7879           if (KEYWORD_KEY_NAME (chain))
7880             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7881
7882           strcat (buf, ":");
7883           if (RAW_TYPESPEC (chain) != objc_object_reference)
7884             {
7885               strcat (buf, "(");
7886               gen_declaration_1 (TREE_TYPE (chain), buf);
7887               strcat (buf, ")");
7888             }
7889
7890           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7891           if ((chain = TREE_CHAIN (chain)))
7892             strcat (buf, " ");
7893         }
7894       while (chain);
7895
7896       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
7897         strcat (buf, ", ...");
7898       else if (METHOD_ADD_ARGS (method))
7899         {
7900           /* We have a tree list node as generate by get_parm_info.  */
7901           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7902
7903           /* Know we have a chain of parm_decls.  */
7904           while (chain)
7905             {
7906               strcat (buf, ", ");
7907               gen_declaration_1 (chain, buf);
7908               chain = TREE_CHAIN (chain);
7909             }
7910         }
7911     }
7912
7913   else
7914     /* We have a unary selector.  */
7915     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7916
7917   return buf;
7918 }
7919 \f
7920 /* Debug info.  */
7921
7922
7923 /* Dump an @interface declaration of the supplied class CHAIN to the
7924    supplied file FP.  Used to implement the -gen-decls option (which
7925    prints out an @interface declaration of all classes compiled in
7926    this run); potentially useful for debugging the compiler too.  */
7927 static void
7928 dump_interface (fp, chain)
7929      FILE *fp;
7930      tree chain;
7931 {
7932   /* FIXME: A heap overflow here whenever a method (or ivar)
7933      declaration is so long that it doesn't fit in the buffer.  The
7934      code and all the related functions should be rewritten to avoid
7935      using fixed size buffers.  */
7936   char *buf = (char *) xmalloc (1024 * 10);
7937   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7938   tree ivar_decls = CLASS_RAW_IVARS (chain);
7939   tree nst_methods = CLASS_NST_METHODS (chain);
7940   tree cls_methods = CLASS_CLS_METHODS (chain);
7941
7942   fprintf (fp, "\n@interface %s", my_name);
7943
7944   /* CLASS_SUPER_NAME is used to store the superclass name for 
7945      classes, and the category name for categories.  */
7946   if (CLASS_SUPER_NAME (chain))
7947     {
7948       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7949       
7950       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE 
7951           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
7952         {
7953           fprintf (fp, " (%s)\n", name);
7954         }
7955       else
7956         {
7957           fprintf (fp, " : %s\n", name);
7958         }
7959     }
7960   else
7961     fprintf (fp, "\n");
7962
7963   /* FIXME - the following doesn't seem to work at the moment.  */
7964   if (ivar_decls)
7965     {
7966       fprintf (fp, "{\n");
7967       do
7968         {
7969           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7970           ivar_decls = TREE_CHAIN (ivar_decls);
7971         }
7972       while (ivar_decls);
7973       fprintf (fp, "}\n");
7974     }
7975
7976   while (nst_methods)
7977     {
7978       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7979       nst_methods = TREE_CHAIN (nst_methods);
7980     }
7981
7982   while (cls_methods)
7983     {
7984       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7985       cls_methods = TREE_CHAIN (cls_methods);
7986     }
7987
7988   fprintf (fp, "@end\n");
7989 }
7990
7991 /* Demangle function for Objective-C */
7992 static const char *
7993 objc_demangle (mangled)
7994      const char *mangled;
7995 {
7996   char *demangled, *cp;
7997
7998   if (mangled[0] == '_' &&
7999       (mangled[1] == 'i' || mangled[1] == 'c') &&
8000       mangled[2] == '_')
8001     {
8002       cp = demangled = xmalloc(strlen(mangled) + 2);
8003       if (mangled[1] == 'i')
8004         *cp++ = '-';            /* for instance method */
8005       else
8006         *cp++ = '+';            /* for class method */
8007       *cp++ = '[';              /* opening left brace */
8008       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8009       while (*cp && *cp == '_')
8010         cp++;                   /* skip any initial underbars in class name */
8011       cp = strchr(cp, '_');     /* find first non-initial underbar */
8012       if (cp == NULL)
8013         {
8014           free(demangled);      /* not mangled name */
8015           return mangled;
8016         }
8017       if (cp[1] == '_')  /* easy case: no category name */
8018         {
8019           *cp++ = ' ';            /* replace two '_' with one ' ' */
8020           strcpy(cp, mangled + (cp - demangled) + 2);
8021         }
8022       else
8023         {
8024           *cp++ = '(';            /* less easy case: category name */
8025           cp = strchr(cp, '_');
8026           if (cp == 0)
8027             {
8028               free(demangled);    /* not mangled name */
8029               return mangled;
8030             }
8031           *cp++ = ')';
8032           *cp++ = ' ';            /* overwriting 1st char of method name... */
8033           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8034         }
8035       while (*cp && *cp == '_')
8036         cp++;                   /* skip any initial underbars in method name */
8037       for (; *cp; cp++)
8038         if (*cp == '_')
8039           *cp = ':';            /* replace remaining '_' with ':' */
8040       *cp++ = ']';              /* closing right brace */
8041       *cp++ = 0;                /* string terminator */
8042       return demangled;
8043     }
8044   else
8045     return mangled;             /* not an objc mangled name */
8046 }
8047
8048 const char *
8049 objc_printable_name (decl, kind)
8050      tree decl;
8051      int kind ATTRIBUTE_UNUSED;
8052 {
8053   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8054 }
8055
8056 static void
8057 init_objc ()
8058 {
8059   gcc_obstack_init (&util_obstack);
8060   util_firstobj = (char *) obstack_finish (&util_obstack);
8061
8062   errbuf = (char *) xmalloc (BUFSIZE);
8063   hash_init ();
8064   synth_module_prologue ();
8065 }
8066 \f
8067 static void
8068 finish_objc ()
8069 {
8070   struct imp_entry *impent;
8071   tree chain;
8072   /* The internally generated initializers appear to have missing braces.
8073      Don't warn about this.  */
8074   int save_warn_missing_braces = warn_missing_braces;
8075   warn_missing_braces = 0;
8076
8077   /* A missing @end may not be detected by the parser.  */
8078   if (objc_implementation_context)
8079     {
8080       warning ("`@end' missing in implementation context");
8081       finish_class (objc_implementation_context);
8082       objc_ivar_chain = NULL_TREE;
8083       objc_implementation_context = NULL_TREE;
8084     }
8085
8086   generate_forward_declaration_to_string_table ();
8087
8088 #ifdef OBJC_PROLOGUE
8089   OBJC_PROLOGUE;
8090 #endif
8091
8092   /* Process the static instances here because initialization of objc_symtab
8093      depends on them.  */
8094   if (objc_static_instances)
8095     generate_static_references ();
8096
8097   if (imp_list || class_names_chain
8098       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8099     generate_objc_symtab_decl ();
8100
8101   for (impent = imp_list; impent; impent = impent->next)
8102     {
8103       objc_implementation_context = impent->imp_context;
8104       implementation_template = impent->imp_template;
8105
8106       UOBJC_CLASS_decl = impent->class_decl;
8107       UOBJC_METACLASS_decl = impent->meta_decl;
8108       
8109       /* Dump the @interface of each class as we compile it, if the
8110          -gen-decls option is in use.  TODO: Dump the classes in the
8111          order they were found, rather than in reverse order as we
8112          are doing now.  */
8113       if (flag_gen_declaration)
8114         {
8115           dump_interface (gen_declaration_file, objc_implementation_context);
8116         }
8117       
8118       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8119         {
8120           /* all of the following reference the string pool...  */
8121           generate_ivar_lists ();
8122           generate_dispatch_tables ();
8123           generate_shared_structures ();
8124         }
8125       else
8126         {
8127           generate_dispatch_tables ();
8128           generate_category (objc_implementation_context);
8129         }
8130     }
8131
8132   /* If we are using an array of selectors, we must always
8133      finish up the array decl even if no selectors were used.  */
8134   if (! flag_next_runtime || sel_ref_chain)
8135     build_selector_translation_table ();
8136
8137   if (protocol_chain)
8138     generate_protocols ();
8139
8140   if (objc_implementation_context || class_names_chain || objc_static_instances
8141       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8142     {
8143       /* Arrange for ObjC data structures to be initialized at run time.  */
8144       rtx init_sym = build_module_descriptor ();
8145       if (init_sym && targetm.have_ctors_dtors)
8146         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8147     }
8148
8149   /* Dump the class references.  This forces the appropriate classes
8150      to be linked into the executable image, preserving unix archive
8151      semantics.  This can be removed when we move to a more dynamically
8152      linked environment.  */
8153
8154   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8155     {
8156       handle_class_ref (chain);
8157       if (TREE_PURPOSE (chain))
8158         generate_classref_translation_entry (chain);
8159     }
8160
8161   for (impent = imp_list; impent; impent = impent->next)
8162     handle_impent (impent);
8163
8164   /* Dump the string table last.  */
8165
8166   generate_strings ();
8167
8168   if (warn_selector)
8169     {
8170       int slot;
8171       hash hsh;
8172
8173       /* Run through the selector hash tables and print a warning for any
8174          selector which has multiple methods.  */
8175
8176       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8177         for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8178           if (hsh->list)
8179             {
8180               tree meth = hsh->key;
8181               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8182                            ? '-' : '+');
8183               attr loop;
8184
8185               warning ("potential selector conflict for method `%s'",
8186                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8187               warn_with_method ("found", type, meth);
8188               for (loop = hsh->list; loop; loop = loop->next)
8189                 warn_with_method ("found", type, loop->value);
8190             }
8191
8192       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8193         for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8194           if (hsh->list)
8195             {
8196               tree meth = hsh->key;
8197               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8198                            ? '-' : '+');
8199               attr loop;
8200
8201               warning ("potential selector conflict for method `%s'",
8202                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8203               warn_with_method ("found", type, meth);
8204               for (loop = hsh->list; loop; loop = loop->next)
8205                 warn_with_method ("found", type, loop->value);
8206             }
8207     }
8208
8209   warn_missing_braces = save_warn_missing_braces;
8210 }
8211 \f
8212 /* Subroutines of finish_objc.  */
8213
8214 static void
8215 generate_classref_translation_entry (chain)
8216      tree chain;
8217 {
8218   tree expr, name, decl_specs, decl, sc_spec;
8219   tree type;
8220
8221   type = TREE_TYPE (TREE_PURPOSE (chain));
8222
8223   expr = add_objc_string (TREE_VALUE (chain), class_names);
8224   expr = build_c_cast (type, expr); /* cast! */
8225
8226   name = DECL_NAME (TREE_PURPOSE (chain));
8227
8228   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8229
8230   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8231   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8232
8233   /* The decl that is returned from start_decl is the one that we
8234      forward declared in build_class_reference.  */
8235   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8236   DECL_CONTEXT (decl) = NULL_TREE;
8237   finish_decl (decl, expr, NULL_TREE);
8238   return;
8239 }
8240
8241 static void
8242 handle_class_ref (chain)
8243      tree chain;
8244 {
8245   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8246   char *string = (char *) alloca (strlen (name) + 30);
8247   tree decl;
8248   tree exp;
8249
8250   sprintf (string, "%sobjc_class_name_%s",
8251            (flag_next_runtime ? "." : "__"), name);
8252
8253 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8254   if (flag_next_runtime)
8255     {
8256       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8257       return;
8258     }
8259 #endif
8260
8261   /* Make a decl for this name, so we can use its address in a tree.  */
8262   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8263   DECL_EXTERNAL (decl) = 1;
8264   TREE_PUBLIC (decl) = 1;
8265
8266   pushdecl (decl);
8267   rest_of_decl_compilation (decl, 0, 0, 0);
8268
8269   /* Make a decl for the address.  */
8270   sprintf (string, "%sobjc_class_ref_%s",
8271            (flag_next_runtime ? "." : "__"), name);
8272   exp = build1 (ADDR_EXPR, string_type_node, decl);
8273   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8274   DECL_INITIAL (decl) = exp;
8275   TREE_STATIC (decl) = 1;
8276   TREE_USED (decl) = 1;
8277
8278   pushdecl (decl);
8279   rest_of_decl_compilation (decl, 0, 0, 0);
8280 }
8281
8282 static void
8283 handle_impent (impent)
8284      struct imp_entry *impent;
8285 {
8286   char *string;
8287
8288   objc_implementation_context = impent->imp_context;
8289   implementation_template = impent->imp_template;
8290
8291   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8292     {
8293       const char *const class_name =
8294         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8295
8296       string = (char *) alloca (strlen (class_name) + 30);
8297
8298       sprintf (string, "%sobjc_class_name_%s",
8299                (flag_next_runtime ? "." : "__"), class_name);
8300     }
8301   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8302     {
8303       const char *const class_name =
8304         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8305       const char *const class_super_name =
8306         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8307
8308       string = (char *) alloca (strlen (class_name)
8309                                 + strlen (class_super_name) + 30);
8310
8311       /* Do the same for categories.  Even though no references to
8312          these symbols are generated automatically by the compiler, it
8313          gives you a handle to pull them into an archive by hand.  */
8314       sprintf (string, "*%sobjc_category_name_%s_%s",
8315                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8316     }
8317   else
8318     return;
8319
8320 #ifdef ASM_DECLARE_CLASS_REFERENCE
8321   if (flag_next_runtime)
8322     {
8323       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8324       return;
8325     }
8326   else
8327 #endif
8328     {
8329       tree decl, init;
8330
8331       init = build_int_2 (0, 0);
8332       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
8333       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
8334       TREE_PUBLIC (decl) = 1;
8335       TREE_READONLY (decl) = 1;
8336       TREE_USED (decl) = 1;
8337       TREE_CONSTANT (decl) = 1;
8338       DECL_CONTEXT (decl) = 0;
8339       DECL_ARTIFICIAL (decl) = 1;
8340       DECL_INITIAL (decl) = init;
8341       assemble_variable (decl, 1, 0, 0);
8342     }
8343 }
8344 \f
8345 /* Look up ID as an instance variable.  */
8346 tree
8347 lookup_objc_ivar (id)
8348      tree id;
8349 {
8350   tree decl;
8351
8352   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8353     /* We have a message to super.  */
8354     return get_super_receiver ();
8355   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8356     {
8357       if (is_private (decl))
8358         return error_mark_node;
8359       else
8360         return build_ivar_reference (id);
8361     }
8362   else
8363     return 0;
8364 }
8365
8366 #include "gtype-objc.h"