OSDN Git Service

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