OSDN Git Service

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