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