OSDN Git Service

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