OSDN Git Service

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