OSDN Git Service

* tree.c (build_constructor): New function.
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3    2001, 2002, 2003 Free Software Foundation, Inc.
4    Contributed by Steve Naroff.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Purpose: This module implements the Objective-C 4.0 language.
24
25    compatibility issues (with the Stepstone translator):
26
27    - does not recognize the following 3.3 constructs.
28      @requires, @classes, @messages, = (...)
29    - methods with variable arguments must conform to ANSI standard.
30    - tagged structure definitions that appear in BOTH the interface
31      and implementation are not allowed.
32    - public/private: all instance variables are public within the
33      context of the implementation...I consider this to be a bug in
34      the translator.
35    - statically allocated objects are not supported. the user will
36      receive an error if this service is requested.
37
38    code generation `options':
39
40    */
41
42 #include "config.h"
43 #include "system.h"
44 #include "coretypes.h"
45 #include "tm.h"
46 #include "tree.h"
47 #include "rtl.h"
48 #include "expr.h"
49 #include "c-tree.h"
50 #include "c-common.h"
51 #include "flags.h"
52 #include "objc-act.h"
53 #include "input.h"
54 #include "except.h"
55 #include "function.h"
56 #include "output.h"
57 #include "toplev.h"
58 #include "ggc.h"
59 #include "varray.h"
60 #include "debug.h"
61 #include "target.h"
62 #include "diagnostic.h"
63 #include "cgraph.h"
64
65 /* This is the default way of generating a method name.  */
66 /* I am not sure it is really correct.
67    Perhaps there's a danger that it will make name conflicts
68    if method names contain underscores. -- rms.  */
69 #ifndef OBJC_GEN_METHOD_LABEL
70 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
71   do {                                      \
72     char *temp;                             \
73     sprintf ((BUF), "_%s_%s_%s_%s",         \
74              ((IS_INST) ? "i" : "c"),       \
75              (CLASS_NAME),                  \
76              ((CAT_NAME)? (CAT_NAME) : ""), \
77              (SEL_NAME));                   \
78     for (temp = (BUF); *temp; temp++)       \
79       if (*temp == ':') *temp = '_';        \
80   } while (0)
81 #endif
82
83 /* These need specifying.  */
84 #ifndef OBJC_FORWARDING_STACK_OFFSET
85 #define OBJC_FORWARDING_STACK_OFFSET 0
86 #endif
87
88 #ifndef OBJC_FORWARDING_MIN_OFFSET
89 #define OBJC_FORWARDING_MIN_OFFSET 0
90 #endif
91 \f
92 \f
93 /* Set up for use of obstacks.  */
94
95 #include "obstack.h"
96
97 /* This obstack is used to accumulate the encoding of a data type.  */
98 static struct obstack util_obstack;
99 /* This points to the beginning of obstack contents,
100    so we can free the whole contents.  */
101 char *util_firstobj;
102
103 /* for encode_method_def */
104 #include "rtl.h"
105
106 /* The version identifies which language generation and runtime
107    the module (file) was compiled for, and is recorded in the
108    module descriptor.  */
109
110 #define OBJC_VERSION    (flag_next_runtime ? 5 : 8)
111 #define PROTOCOL_VERSION 2
112
113 /* (Decide if these can ever be validly changed.) */
114 #define OBJC_ENCODE_INLINE_DEFS         0
115 #define OBJC_ENCODE_DONT_INLINE_DEFS    1
116
117 /*** Private Interface (procedures) ***/
118
119 /* Used by compile_file.  */
120
121 static void init_objc                           PARAMS ((void));
122 static void finish_objc                         PARAMS ((void));
123
124 /* Code generation.  */
125
126 static void synth_module_prologue               PARAMS ((void));
127 static tree objc_build_constructor              PARAMS ((tree, tree));
128 static rtx build_module_descriptor              PARAMS ((void));
129 static tree init_module_descriptor              PARAMS ((tree));
130 static tree build_objc_method_call              PARAMS ((int, tree, tree,
131                                                        tree, tree, tree));
132 static void generate_strings                    PARAMS ((void));
133 static tree get_proto_encoding                  PARAMS ((tree));
134 static void build_selector_translation_table    PARAMS ((void));
135
136 static tree objc_add_static_instance            PARAMS ((tree, tree));
137
138 static tree build_ivar_template                 PARAMS ((void));
139 static tree build_method_template               PARAMS ((void));
140 static tree build_private_template              PARAMS ((tree));
141 static void build_class_template                PARAMS ((void));
142 static void build_selector_template             PARAMS ((void));
143 static void build_category_template             PARAMS ((void));
144 static tree build_super_template                PARAMS ((void));
145 static tree build_category_initializer          PARAMS ((tree, tree, tree,
146                                                        tree, tree, tree));
147 static tree build_protocol_initializer          PARAMS ((tree, tree, tree,
148                                                        tree, tree));
149
150 static void synth_forward_declarations          PARAMS ((void));
151 static void generate_ivar_lists                 PARAMS ((void));
152 static void generate_dispatch_tables            PARAMS ((void));
153 static void generate_shared_structures          PARAMS ((void));
154 static tree generate_protocol_list              PARAMS ((tree));
155 static void generate_forward_declaration_to_string_table PARAMS ((void));
156 static void build_protocol_reference            PARAMS ((tree));
157
158 static tree build_keyword_selector              PARAMS ((tree));
159 static tree synth_id_with_class_suffix          PARAMS ((const char *, tree));
160
161 static void generate_static_references          PARAMS ((void));
162 static int check_methods_accessible             PARAMS ((tree, tree,
163                                                        int));
164 static void encode_aggregate_within             PARAMS ((tree, int, int,
165                                                        int, int));
166 static const char *objc_demangle                PARAMS ((const char *));
167 static void objc_expand_function_end            PARAMS ((void));
168
169 /* Hash tables to manage the global pool of method prototypes.  */
170
171 hash *nst_method_hash_list = 0;
172 hash *cls_method_hash_list = 0;
173
174 static size_t hash_func                         PARAMS ((tree));
175 static void hash_init                           PARAMS ((void));
176 static void hash_enter                          PARAMS ((hash *, tree));
177 static hash hash_lookup                         PARAMS ((hash *, tree));
178 static void hash_add_attr                       PARAMS ((hash, tree));
179 static tree lookup_method                       PARAMS ((tree, tree));
180 static tree lookup_instance_method_static       PARAMS ((tree, tree));
181 static tree lookup_class_method_static          PARAMS ((tree, tree));
182 static tree add_class                           PARAMS ((tree));
183 static void add_category                        PARAMS ((tree, tree));
184
185 enum string_section
186 {
187   class_names,          /* class, category, protocol, module names */
188   meth_var_names,       /* method and variable names */
189   meth_var_types        /* method and variable type descriptors */
190 };
191
192 static tree add_objc_string                     PARAMS ((tree,
193                                                        enum string_section));
194 static tree get_objc_string_decl                PARAMS ((tree,
195                                                        enum string_section));
196 static tree build_objc_string_decl              PARAMS ((enum string_section));
197 static tree build_selector_reference_decl       PARAMS ((void));
198
199 /* Protocol additions.  */
200
201 static tree add_protocol                        PARAMS ((tree));
202 static tree lookup_protocol                     PARAMS ((tree));
203 static void check_protocol_recursively          PARAMS ((tree, tree));
204 static tree lookup_and_install_protocols        PARAMS ((tree));
205
206 /* Type encoding.  */
207
208 static void encode_type_qualifiers              PARAMS ((tree));
209 static void encode_pointer                      PARAMS ((tree, int, int));
210 static void encode_array                        PARAMS ((tree, int, int));
211 static void encode_aggregate                    PARAMS ((tree, int, int));
212 static void encode_bitfield                     PARAMS ((int));
213 static void encode_type                         PARAMS ((tree, int, int));
214 static void encode_field_decl                   PARAMS ((tree, int, int));
215
216 static void really_start_method                 PARAMS ((tree, tree));
217 static int comp_method_with_proto               PARAMS ((tree, tree));
218 static int comp_proto_with_proto                PARAMS ((tree, tree));
219 static tree get_arg_type_list                   PARAMS ((tree, int, int));
220 static tree 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   lineno = 0;
445
446   /* If gen_declaration desired, open the output file.  */
447   if (flag_gen_declaration)
448     {
449       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
450       gen_declaration_file = fopen (dumpname, "w");
451       if (gen_declaration_file == 0)
452         fatal_io_error ("can't open %s", dumpname);
453       free (dumpname);
454     }
455
456   if (flag_next_runtime)
457     {
458       TAG_GETCLASS = "objc_getClass";
459       TAG_GETMETACLASS = "objc_getMetaClass";
460       TAG_MSGSEND = "objc_msgSend";
461       TAG_MSGSENDSUPER = "objc_msgSendSuper";
462       TAG_EXECCLASS = "__objc_execClass";
463       default_constant_string_class_name = "NSConstantString";
464     }
465   else
466     {
467       TAG_GETCLASS = "objc_get_class";
468       TAG_GETMETACLASS = "objc_get_meta_class";
469       TAG_MSGSEND = "objc_msg_lookup";
470       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
471       TAG_EXECCLASS = "__objc_exec_class";
472       default_constant_string_class_name = "NXConstantString";
473       flag_typed_selectors = 1;
474     }
475
476   objc_ellipsis_node = make_node (ERROR_MARK);
477
478   init_objc ();
479
480   if (print_struct_values)
481     generate_struct_by_value_array ();
482
483   return 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
1701     = grokfield (input_filename, lineno, 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
1709     = grokfield (input_filename, lineno, 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
1717     = grokfield (input_filename, lineno, 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
1726     = grokfield (input_filename, lineno, 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 = lineno;
2053             if (flag_next_runtime && TREE_PURPOSE (chain))
2054               lineno = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
2055             warning ("creating selector for non existant method %s",
2056                      IDENTIFIER_POINTER (TREE_VALUE (chain)));
2057             lineno = 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
2569     = grokfield (input_filename, lineno, 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
2578     = grokfield (input_filename, lineno, 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
2588     = grokfield (input_filename, lineno, 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
2600     = grokfield (input_filename, lineno, 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
2612     = grokfield (input_filename, lineno, 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
2676   field_decl
2677     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2678   field_decl_chain = field_decl;
2679
2680   /* struct objc_method method_list[]; */
2681
2682   decl_specs = build_tree_list (NULL_TREE, list_type);
2683   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2684                          build_int_2 (size, 0));
2685
2686   field_decl
2687     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2688   chainon (field_decl_chain, field_decl);
2689
2690   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2691
2692   return objc_ivar_list_record;
2693 }
2694
2695 static tree
2696 build_method_prototype_template ()
2697 {
2698   tree proto_record;
2699   tree decl_specs, field_decl, field_decl_chain;
2700
2701   proto_record
2702     = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2703
2704   /* struct objc_selector *_cmd; */
2705   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2706                           get_identifier (TAG_SELECTOR)), NULL_TREE);
2707   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2708
2709   field_decl
2710     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2711   field_decl_chain = field_decl;
2712
2713   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2714   field_decl
2715     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2716   field_decl
2717     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2718   chainon (field_decl_chain, field_decl);
2719
2720   finish_struct (proto_record, field_decl_chain, NULL_TREE);
2721
2722   return proto_record;
2723 }
2724
2725 /* True if last call to forwarding_offset yielded a register offset.  */
2726 static int offset_is_register;
2727
2728 static int
2729 forwarding_offset (parm)
2730       tree parm;
2731 {
2732   int offset_in_bytes;
2733
2734   if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2735     {
2736       rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2737
2738       /* ??? Here we assume that the parm address is indexed
2739           off the frame pointer or arg pointer.
2740           If that is not true, we produce meaningless results,
2741           but do not crash.  */
2742       if (GET_CODE (addr) == PLUS
2743           && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2744         offset_in_bytes = INTVAL (XEXP (addr, 1));
2745       else
2746         offset_in_bytes = 0;
2747
2748       offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2749       offset_is_register = 0;
2750     }
2751   else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2752     {
2753       int regno = REGNO (DECL_INCOMING_RTL (parm));
2754       offset_in_bytes = apply_args_register_offset (regno);
2755       offset_is_register = 1;
2756     }
2757   else
2758     return 0;
2759
2760   /* This is the case where the parm is passed as an int or double
2761      and it is converted to a char, short or float and stored back
2762      in the parmlist.  In this case, describe the parm
2763      with the variable's declared type, and adjust the address
2764      if the least significant bytes (which we are using) are not
2765      the first ones.  */
2766   if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2767     offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2768                         - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2769
2770   return offset_in_bytes;
2771 }
2772
2773 static tree
2774 encode_method_prototype (method_decl, func_decl)
2775       tree method_decl;
2776       tree func_decl;
2777 {
2778   tree parms;
2779   int stack_size, i;
2780   tree user_args;
2781   HOST_WIDE_INT max_parm_end = 0;
2782   char buf[40];
2783   tree result;
2784
2785   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
2786   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2787
2788   /* C type.  */
2789   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2790                obstack_object_size (&util_obstack),
2791                OBJC_ENCODE_INLINE_DEFS);
2792
2793   /* Stack size.  */
2794   for (parms = DECL_ARGUMENTS (func_decl); parms;
2795        parms = TREE_CHAIN (parms))
2796     {
2797       HOST_WIDE_INT parm_end = (forwarding_offset (parms)
2798                                 + int_size_in_bytes (TREE_TYPE (parms)));
2799
2800       if (!offset_is_register && max_parm_end < parm_end)
2801         max_parm_end = parm_end;
2802     }
2803
2804   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2805
2806   sprintf (buf, "%d", stack_size);
2807   obstack_grow (&util_obstack, buf, strlen (buf));
2808
2809   user_args = METHOD_SEL_ARGS (method_decl);
2810
2811   /* Argument types.  */
2812   for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2813        parms = TREE_CHAIN (parms), i++)
2814     {
2815       /* Process argument qualifiers for user supplied arguments.  */
2816       if (i > 1)
2817         {
2818           encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2819           user_args = TREE_CHAIN (user_args);
2820         }
2821
2822       /* Type.  */
2823       encode_type (TREE_TYPE (parms),
2824                    obstack_object_size (&util_obstack),
2825                    OBJC_ENCODE_INLINE_DEFS);
2826
2827       /* Compute offset.  */
2828       sprintf (buf, "%d", forwarding_offset (parms));
2829
2830       /* Indicate register.  */
2831       if (offset_is_register)
2832         obstack_1grow (&util_obstack, '+');
2833       
2834       obstack_grow (&util_obstack, buf, strlen (buf));
2835     }
2836
2837   obstack_1grow (&util_obstack, '\0');
2838   result = get_identifier (obstack_finish (&util_obstack));
2839   obstack_free (&util_obstack, util_firstobj);
2840   return result;
2841 }
2842
2843 static tree
2844 generate_descriptor_table (type, name, size, list, proto)
2845      tree type;
2846      const char *name;
2847      int size;
2848      tree list;
2849      tree proto;
2850 {
2851   tree sc_spec, decl_specs, decl, initlist;
2852
2853   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2854   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2855
2856   decl = start_decl (synth_id_with_class_suffix (name, proto),
2857                      decl_specs, 1, NULL_TREE);
2858   DECL_CONTEXT (decl) = NULL_TREE;
2859
2860   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2861   initlist = tree_cons (NULL_TREE, list, initlist);
2862
2863   finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
2864                NULL_TREE);
2865
2866   return decl;
2867 }
2868
2869 static void
2870 generate_method_descriptors (protocol)
2871      tree protocol;
2872 {
2873   tree initlist, chain, method_list_template;
2874   tree cast, variable_length_type;
2875   int size;
2876
2877   if (!objc_method_prototype_template)
2878     objc_method_prototype_template = build_method_prototype_template ();
2879
2880   cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2881                                 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2882                           NULL_TREE);
2883   variable_length_type = groktypename (cast);
2884
2885   chain = PROTOCOL_CLS_METHODS (protocol);
2886   if (chain)
2887     {
2888       size = list_length (chain);
2889
2890       method_list_template
2891         = build_method_prototype_list_template (objc_method_prototype_template,
2892                                                 size);
2893
2894       initlist 
2895         = build_descriptor_table_initializer (objc_method_prototype_template,
2896                                               chain);
2897
2898       UOBJC_CLASS_METHODS_decl
2899         = generate_descriptor_table (method_list_template,
2900                                      "_OBJC_PROTOCOL_CLASS_METHODS",
2901                                      size, initlist, protocol);
2902       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2903     }
2904   else
2905     UOBJC_CLASS_METHODS_decl = 0;
2906
2907   chain = PROTOCOL_NST_METHODS (protocol);
2908   if (chain)
2909     {
2910       size = list_length (chain);
2911
2912       method_list_template
2913         = build_method_prototype_list_template (objc_method_prototype_template,
2914                                                 size);
2915       initlist
2916         = build_descriptor_table_initializer (objc_method_prototype_template,
2917                                               chain);
2918
2919       UOBJC_INSTANCE_METHODS_decl
2920         = generate_descriptor_table (method_list_template,
2921                                      "_OBJC_PROTOCOL_INSTANCE_METHODS",
2922                                      size, initlist, protocol);
2923       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
2924     }
2925   else
2926     UOBJC_INSTANCE_METHODS_decl = 0;
2927 }
2928
2929 /* Generate a temporary FUNCTION_DECL node to be used in
2930    hack_method_prototype below.  */
2931
2932 static GTY(()) int build_tmp_function_decl_xxx;
2933 static tree
2934 build_tmp_function_decl ()
2935 {
2936   tree decl_specs, expr_decl, parms;
2937   char buffer[80];
2938
2939   /* struct objc_object *objc_xxx (id, SEL, ...); */
2940   pushlevel (0);
2941   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2942   push_parm_decl (build_tree_list
2943                   (build_tree_list (decl_specs,
2944                                     build1 (INDIRECT_REF, NULL_TREE,
2945                                             NULL_TREE)),
2946                    NULL_TREE));
2947
2948   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2949                                           get_identifier (TAG_SELECTOR)));
2950   expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
2951
2952   push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
2953                                    NULL_TREE));
2954   parms = get_parm_info (0);
2955   poplevel (0, 0, 0);
2956
2957   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2958   sprintf (buffer, "__objc_tmp_%x", build_tmp_function_decl_xxx++);
2959   expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
2960   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
2961
2962   return define_decl (expr_decl, decl_specs);
2963 }
2964
2965 /* Generate the prototypes for protocol methods.  This is used to
2966    generate method encodings for these.
2967
2968    NST_METHODS is the method to generate a _DECL node for TMP_DECL is
2969    a decl node to be used.  This is also where the return value is
2970    given.  */
2971
2972 static void
2973 hack_method_prototype (nst_methods, tmp_decl)
2974      tree nst_methods;
2975      tree tmp_decl;
2976 {
2977   tree parms;
2978   tree parm;
2979
2980   /* Hack to avoid problem with static typing of self arg.  */
2981   TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
2982   start_method_def (nst_methods);
2983   TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
2984
2985   if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node)
2986     parms = get_parm_info (0); /* we have a `, ...' */
2987   else
2988     parms = get_parm_info (1); /* place a `void_at_end' */
2989
2990   poplevel (0, 0, 0);   /* Must be called BEFORE start_function.  */
2991
2992   /* Usually called from store_parm_decls -> init_function_start.  */
2993
2994   DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
2995
2996   if (current_function_decl)
2997     abort ();
2998   current_function_decl = tmp_decl;
2999
3000   {
3001     /* Code taken from start_function.  */
3002     tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3003     /* Promote the value to int before returning it.  */
3004     if (TREE_CODE (restype) == INTEGER_TYPE
3005         && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3006       restype = integer_type_node;
3007     DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3008   }
3009
3010   for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3011     DECL_CONTEXT (parm) = tmp_decl;
3012
3013   init_function_start (tmp_decl, "objc-act", 0);
3014
3015   /* Typically called from expand_function_start for function definitions.  */
3016   assign_parms (tmp_decl);
3017
3018   /* install return type */
3019   TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3020
3021   current_function_decl = NULL;
3022 }
3023
3024 static void
3025 generate_protocol_references (plist)
3026      tree plist;
3027 {
3028   tree lproto;
3029
3030   /* Forward declare protocols referenced.  */
3031   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3032     {
3033       tree proto = TREE_VALUE (lproto);
3034
3035       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3036           && PROTOCOL_NAME (proto))
3037         {
3038           if (! PROTOCOL_FORWARD_DECL (proto))
3039             build_protocol_reference (proto);
3040
3041           if (PROTOCOL_LIST (proto))
3042             generate_protocol_references (PROTOCOL_LIST (proto));
3043         }
3044     }
3045 }
3046
3047 /* For each protocol which was referenced either from a @protocol()
3048    expression, or because a class/category implements it (then a
3049    pointer to the protocol is stored in the struct describing the
3050    class/category), we create a statically allocated instance of the
3051    Protocol class.  The code is written in such a way as to generate
3052    as few Protocol objects as possible; we generate a unique Protocol
3053    instance for each protocol, and we don't generate a Protocol
3054    instance if the protocol is never referenced (either from a
3055    @protocol() or from a class/category implementation).  These
3056    statically allocated objects can be referred to via the static
3057    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3058    
3059    The statically allocated Protocol objects that we generate here
3060    need to be fixed up at runtime in order to be used: the 'isa'
3061   pointer of the objects need to be set up to point to the 'Protocol'
3062    class, as known at runtime.
3063
3064    The NeXT runtime fixes up all protocols at program startup time,
3065    before main() is entered.  It uses a low-level trick to look up all
3066    those symbols, then loops on them and fixes them up.
3067
3068    The GNU runtime as well fixes up all protocols before user code
3069    from the module is executed; it requires pointers to those symbols
3070    to be put in the objc_symtab (which is then passed as argument to
3071    the function __objc_exec_class() which the compiler sets up to be
3072    executed automatically when the module is loaded); setup of those
3073    Protocol objects happen in two ways in the GNU runtime: all
3074    Protocol objects referred to by a class or category implementation
3075    are fixed up when the class/category is loaded; all Protocol
3076    objects referred to by a @protocol() expression are added by the
3077    compiler to the list of statically allocated instances to fixup
3078    (the same list holding the statically allocated constant string
3079    objects).  Because, as explained above, the compiler generates as
3080    few Protocol objects as possible, some Protocol object might end up
3081    being referenced multiple times when compiled with the GNU runtime,
3082    and end up being fixed up multiple times at runtime inizialization.
3083    But that doesn't hurt, it's just a little inefficient.  */
3084 static void
3085 generate_protocols ()
3086 {
3087   tree p, tmp_decl, encoding;
3088   tree sc_spec, decl_specs, decl;
3089   tree initlist, protocol_name_expr, refs_decl, refs_expr;
3090   tree cast_type2;
3091
3092   tmp_decl = build_tmp_function_decl ();
3093
3094   if (! objc_protocol_template)
3095     objc_protocol_template = build_protocol_template ();
3096
3097   /* If a protocol was directly referenced, pull in indirect references.  */
3098   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3099     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3100       generate_protocol_references (PROTOCOL_LIST (p));
3101
3102   for (p = protocol_chain; p; p = TREE_CHAIN (p))
3103     {
3104       tree nst_methods = PROTOCOL_NST_METHODS (p);
3105       tree cls_methods = PROTOCOL_CLS_METHODS (p);
3106
3107       /* If protocol wasn't referenced, don't generate any code.  */
3108       if (! PROTOCOL_FORWARD_DECL (p))
3109         continue;
3110
3111       /* Make sure we link in the Protocol class.  */
3112       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3113
3114       while (nst_methods)
3115         {
3116           if (! METHOD_ENCODING (nst_methods))
3117             {
3118               hack_method_prototype (nst_methods, tmp_decl);
3119               encoding = encode_method_prototype (nst_methods, tmp_decl);
3120               METHOD_ENCODING (nst_methods) = encoding;
3121             }
3122           nst_methods = TREE_CHAIN (nst_methods);
3123         }
3124
3125       while (cls_methods)
3126         {
3127           if (! METHOD_ENCODING (cls_methods))
3128             {
3129               hack_method_prototype (cls_methods, tmp_decl);
3130               encoding = encode_method_prototype (cls_methods, tmp_decl);
3131               METHOD_ENCODING (cls_methods) = encoding;
3132             }
3133
3134           cls_methods = TREE_CHAIN (cls_methods);
3135         }
3136       generate_method_descriptors (p);
3137
3138       if (PROTOCOL_LIST (p))
3139         refs_decl = generate_protocol_list (p);
3140       else
3141         refs_decl = 0;
3142
3143       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3144
3145       sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3146                            NULL_TREE);
3147       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3148
3149       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3150                          decl_specs, 1, NULL_TREE);
3151
3152       DECL_CONTEXT (decl) = NULL_TREE;
3153
3154       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3155
3156       if (refs_decl)
3157         {
3158           cast_type2
3159             = groktypename
3160                 (build_tree_list (build_tree_list (NULL_TREE,
3161                                                    objc_protocol_template),
3162                                   build1 (INDIRECT_REF, NULL_TREE,
3163                                           build1 (INDIRECT_REF, NULL_TREE,
3164                                                   NULL_TREE))));
3165
3166           refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3167           TREE_TYPE (refs_expr) = cast_type2;
3168         }
3169       else
3170         refs_expr = build_int_2 (0, 0);
3171
3172       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3173          by generate_method_descriptors, which is called above.  */
3174       initlist = build_protocol_initializer (TREE_TYPE (decl),
3175                                              protocol_name_expr, refs_expr,
3176                                              UOBJC_INSTANCE_METHODS_decl,
3177                                              UOBJC_CLASS_METHODS_decl);
3178       finish_decl (decl, initlist, NULL_TREE);
3179
3180       /* Mark the decl as used to avoid "defined but not used" warning.  */
3181       TREE_USED (decl) = 1;
3182     }
3183 }
3184
3185 static tree
3186 build_protocol_initializer (type, protocol_name, protocol_list,
3187                             instance_methods, class_methods)
3188      tree type;
3189      tree protocol_name;
3190      tree protocol_list;
3191      tree instance_methods;
3192      tree class_methods;
3193 {
3194   tree initlist = NULL_TREE, expr;
3195   tree cast_type;
3196
3197   cast_type = groktypename
3198     (build_tree_list
3199      (build_tree_list (NULL_TREE,
3200                        xref_tag (RECORD_TYPE,
3201                                  get_identifier (UTAG_CLASS))),
3202       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3203
3204   /* Filling the "isa" in with one allows the runtime system to
3205      detect that the version change...should remove before final release.  */
3206
3207   expr = build_int_2 (PROTOCOL_VERSION, 0);
3208   TREE_TYPE (expr) = cast_type;
3209   initlist = tree_cons (NULL_TREE, expr, initlist);
3210   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3211   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3212
3213   if (!instance_methods)
3214     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3215   else
3216     {
3217       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3218       initlist = tree_cons (NULL_TREE, expr, initlist);
3219     }
3220
3221   if (!class_methods)
3222     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3223   else
3224     {
3225       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3226       initlist = tree_cons (NULL_TREE, expr, initlist);
3227     }
3228
3229   return objc_build_constructor (type, nreverse (initlist));
3230 }
3231 \f
3232 /* struct objc_category {
3233      char *category_name;
3234      char *class_name;
3235      struct objc_method_list *instance_methods;
3236      struct objc_method_list *class_methods;
3237      struct objc_protocol_list *protocols;
3238    };   */
3239
3240 static void
3241 build_category_template ()
3242 {
3243   tree decl_specs, field_decl, field_decl_chain;
3244
3245   objc_category_template = start_struct (RECORD_TYPE,
3246                                          get_identifier (UTAG_CATEGORY));
3247   /* char *category_name; */
3248
3249   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3250   field_decl
3251     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3252   field_decl
3253     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3254   field_decl_chain = field_decl;
3255
3256   /* char *class_name; */
3257
3258   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3259   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3260   field_decl
3261     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3262   chainon (field_decl_chain, field_decl);
3263
3264   /* struct objc_method_list *instance_methods; */
3265
3266   decl_specs = build_tree_list (NULL_TREE,
3267                                 xref_tag (RECORD_TYPE,
3268                                           get_identifier (UTAG_METHOD_LIST)));
3269   field_decl
3270     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3271   field_decl
3272     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3273   chainon (field_decl_chain, field_decl);
3274
3275   /* struct objc_method_list *class_methods; */
3276
3277   decl_specs = build_tree_list (NULL_TREE,
3278                                 xref_tag (RECORD_TYPE,
3279                                           get_identifier (UTAG_METHOD_LIST)));
3280   field_decl
3281     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3282   field_decl
3283     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3284   chainon (field_decl_chain, field_decl);
3285
3286   /* struct objc_protocol **protocol_list; */
3287
3288   decl_specs = build_tree_list (NULL_TREE,
3289                                 xref_tag (RECORD_TYPE,
3290                                           get_identifier (UTAG_PROTOCOL)));
3291   field_decl
3292     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3293   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3294   field_decl
3295     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3296   chainon (field_decl_chain, field_decl);
3297
3298   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3299 }
3300
3301 /* struct objc_selector {
3302      void *sel_id;
3303      char *sel_type;
3304    }; */
3305
3306 static void
3307 build_selector_template ()
3308 {
3309
3310   tree decl_specs, field_decl, field_decl_chain;
3311
3312   objc_selector_template 
3313     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3314
3315   /* void *sel_id; */
3316
3317   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3318   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3319   field_decl
3320     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3321   field_decl_chain = field_decl;
3322
3323   /* char *sel_type; */
3324
3325   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3326   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3327   field_decl
3328     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3329   chainon (field_decl_chain, field_decl);
3330
3331   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3332 }
3333
3334 /* struct objc_class {
3335      struct objc_class *isa;
3336      struct objc_class *super_class;
3337      char *name;
3338      long version;
3339      long info;
3340      long instance_size;
3341      struct objc_ivar_list *ivars;
3342      struct objc_method_list *methods;
3343      if (flag_next_runtime)
3344        struct objc_cache *cache;
3345      else {
3346        struct sarray *dtable;
3347        struct objc_class *subclass_list;
3348        struct objc_class *sibling_class;
3349      }
3350      struct objc_protocol_list *protocols;
3351      void *gc_object_type;
3352    };  */
3353
3354 static void
3355 build_class_template ()
3356 {
3357   tree decl_specs, field_decl, field_decl_chain;
3358
3359   objc_class_template
3360     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3361
3362   /* struct objc_class *isa; */
3363
3364   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3365   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3366   field_decl
3367     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3368   field_decl_chain = field_decl;
3369
3370   /* struct objc_class *super_class; */
3371
3372   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3373   field_decl
3374     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3375   field_decl
3376     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3377   chainon (field_decl_chain, field_decl);
3378
3379   /* char *name; */
3380
3381   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3382   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3383   field_decl
3384     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3385   chainon (field_decl_chain, field_decl);
3386
3387   /* long version; */
3388
3389   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3390   field_decl = get_identifier ("version");
3391   field_decl
3392     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3393   chainon (field_decl_chain, field_decl);
3394
3395   /* long info; */
3396
3397   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3398   field_decl = get_identifier ("info");
3399   field_decl
3400     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3401   chainon (field_decl_chain, field_decl);
3402
3403   /* long instance_size; */
3404
3405   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3406   field_decl = get_identifier ("instance_size");
3407   field_decl
3408     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3409   chainon (field_decl_chain, field_decl);
3410
3411   /* struct objc_ivar_list *ivars; */
3412
3413   decl_specs = build_tree_list (NULL_TREE,
3414                                 xref_tag (RECORD_TYPE,
3415                                           get_identifier (UTAG_IVAR_LIST)));
3416   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3417   field_decl
3418     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3419   chainon (field_decl_chain, field_decl);
3420
3421   /* struct objc_method_list *methods; */
3422
3423   decl_specs = build_tree_list (NULL_TREE,
3424                                 xref_tag (RECORD_TYPE,
3425                                           get_identifier (UTAG_METHOD_LIST)));
3426   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3427   field_decl
3428     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3429   chainon (field_decl_chain, field_decl);
3430
3431   if (flag_next_runtime)
3432     {
3433       /* struct objc_cache *cache; */
3434
3435       decl_specs = build_tree_list (NULL_TREE,
3436                                     xref_tag (RECORD_TYPE,
3437                                               get_identifier ("objc_cache")));
3438       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3439       field_decl = grokfield (input_filename, lineno, field_decl,
3440                               decl_specs, NULL_TREE);
3441       chainon (field_decl_chain, field_decl);
3442     }
3443   else
3444     {
3445       /* struct sarray *dtable; */
3446
3447       decl_specs = build_tree_list (NULL_TREE,
3448                                     xref_tag (RECORD_TYPE,
3449                                               get_identifier ("sarray")));
3450       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3451       field_decl = grokfield (input_filename, lineno, field_decl,
3452                               decl_specs, NULL_TREE);
3453       chainon (field_decl_chain, field_decl);
3454
3455       /* struct objc_class *subclass_list; */
3456
3457       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3458       field_decl
3459         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3460       field_decl = grokfield (input_filename, lineno, field_decl,
3461                               decl_specs, NULL_TREE);
3462       chainon (field_decl_chain, field_decl);
3463
3464       /* struct objc_class *sibling_class; */
3465
3466       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3467       field_decl
3468         = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3469       field_decl = grokfield (input_filename, lineno, field_decl,
3470                               decl_specs, NULL_TREE);
3471       chainon (field_decl_chain, field_decl);
3472     }
3473
3474   /* struct objc_protocol **protocol_list; */
3475
3476   decl_specs = build_tree_list (NULL_TREE, 
3477                                 xref_tag (RECORD_TYPE,
3478                                           get_identifier (UTAG_PROTOCOL)));
3479   field_decl
3480     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3481   field_decl
3482     = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3483   field_decl = grokfield (input_filename, lineno, field_decl,
3484                           decl_specs, NULL_TREE);
3485   chainon (field_decl_chain, field_decl);
3486
3487   /* void *sel_id; */
3488
3489   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3490   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3491   field_decl
3492     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3493   chainon (field_decl_chain, field_decl);
3494
3495   /* void *gc_object_type; */
3496
3497   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3498   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3499   field_decl
3500     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3501   chainon (field_decl_chain, field_decl);
3502
3503   finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3504 }
3505
3506 /* Generate appropriate forward declarations for an implementation.  */
3507
3508 static void
3509 synth_forward_declarations ()
3510 {
3511   tree sc_spec, decl_specs, an_id;
3512
3513   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3514
3515   an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
3516
3517   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3518   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3519   UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3520   TREE_USED (UOBJC_CLASS_decl) = 1;
3521   DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3522
3523   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3524
3525   an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3526                                       objc_implementation_context);
3527
3528   UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3529   TREE_USED (UOBJC_METACLASS_decl) = 1;
3530   DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3531
3532   /* Pre-build the following entities - for speed/convenience.  */
3533
3534   an_id = get_identifier ("super_class");
3535   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3536   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3537 }
3538
3539 static void
3540 error_with_ivar (message, decl, rawdecl)
3541      const char *message;
3542      tree decl;
3543      tree rawdecl;
3544 {
3545   diagnostic_count_diagnostic (global_dc, DK_ERROR);
3546
3547   diagnostic_report_current_function (global_dc);
3548
3549   error_with_file_and_line (DECL_SOURCE_FILE (decl),
3550                             DECL_SOURCE_LINE (decl),
3551                             "%s `%s'",
3552                             message, gen_declaration (rawdecl, errbuf));
3553
3554 }
3555
3556 static void
3557 check_ivars (inter, imp)
3558      tree inter;
3559      tree imp;
3560 {
3561   tree intdecls = CLASS_IVARS (inter);
3562   tree impdecls = CLASS_IVARS (imp);
3563   tree rawintdecls = CLASS_RAW_IVARS (inter);
3564   tree rawimpdecls = CLASS_RAW_IVARS (imp);
3565
3566   while (1)
3567     {
3568       tree t1, t2;
3569
3570       if (intdecls == 0 && impdecls == 0)
3571         break;
3572       if (intdecls == 0 || impdecls == 0)
3573         {
3574           error ("inconsistent instance variable specification");
3575           break;
3576         }
3577
3578       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3579
3580       if (!comptypes (t1, t2))
3581         {
3582           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3583             {
3584               error_with_ivar ("conflicting instance variable type",
3585                                impdecls, rawimpdecls);
3586               error_with_ivar ("previous declaration of",
3587                                intdecls, rawintdecls);
3588             }
3589           else                  /* both the type and the name don't match */
3590             {
3591               error ("inconsistent instance variable specification");
3592               break;
3593             }
3594         }
3595
3596       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3597         {
3598           error_with_ivar ("conflicting instance variable name",
3599                            impdecls, rawimpdecls);
3600           error_with_ivar ("previous declaration of",
3601                            intdecls, rawintdecls);
3602         }
3603
3604       intdecls = TREE_CHAIN (intdecls);
3605       impdecls = TREE_CHAIN (impdecls);
3606       rawintdecls = TREE_CHAIN (rawintdecls);
3607       rawimpdecls = TREE_CHAIN (rawimpdecls);
3608     }
3609 }
3610
3611 /* Set super_type to the data type node for struct objc_super *,
3612    first defining struct objc_super itself.
3613    This needs to be done just once per compilation.  */
3614
3615 static tree
3616 build_super_template ()
3617 {
3618   tree record, decl_specs, field_decl, field_decl_chain;
3619
3620   record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3621
3622   /* struct objc_object *self; */
3623
3624   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3625   field_decl = get_identifier ("self");
3626   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3627   field_decl = grokfield (input_filename, lineno,
3628                           field_decl, decl_specs, NULL_TREE);
3629   field_decl_chain = field_decl;
3630
3631   /* struct objc_class *class; */
3632
3633   decl_specs = get_identifier (UTAG_CLASS);
3634   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3635   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3636
3637   field_decl = grokfield (input_filename, lineno,
3638                           field_decl, decl_specs, NULL_TREE);
3639   chainon (field_decl_chain, field_decl);
3640
3641   finish_struct (record, field_decl_chain, NULL_TREE);
3642
3643   /* `struct objc_super *' */
3644   super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3645                                                                record),
3646                                               build1 (INDIRECT_REF,
3647                                                       NULL_TREE, NULL_TREE)));
3648   return record;
3649 }
3650
3651 /* struct objc_ivar {
3652      char *ivar_name;
3653      char *ivar_type;
3654      int ivar_offset;
3655    };  */
3656
3657 static tree
3658 build_ivar_template ()
3659 {
3660   tree objc_ivar_id, objc_ivar_record;
3661   tree decl_specs, field_decl, field_decl_chain;
3662
3663   objc_ivar_id = get_identifier (UTAG_IVAR);
3664   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3665
3666   /* char *ivar_name; */
3667
3668   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3669   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3670
3671   field_decl = grokfield (input_filename, lineno, field_decl,
3672                           decl_specs, NULL_TREE);
3673   field_decl_chain = field_decl;
3674
3675   /* char *ivar_type; */
3676
3677   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3678   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3679
3680   field_decl = grokfield (input_filename, lineno, field_decl,
3681                           decl_specs, NULL_TREE);
3682   chainon (field_decl_chain, field_decl);
3683
3684   /* int ivar_offset; */
3685
3686   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3687   field_decl = get_identifier ("ivar_offset");
3688
3689   field_decl = grokfield (input_filename, lineno, field_decl,
3690                           decl_specs, NULL_TREE);
3691   chainon (field_decl_chain, field_decl);
3692
3693   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3694
3695   return objc_ivar_record;
3696 }
3697
3698 /* struct {
3699      int ivar_count;
3700      struct objc_ivar ivar_list[ivar_count];
3701    };  */
3702
3703 static tree
3704 build_ivar_list_template (list_type, size)
3705      tree list_type;
3706      int size;
3707 {
3708   tree objc_ivar_list_record;
3709   tree decl_specs, field_decl, field_decl_chain;
3710
3711   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3712
3713   /* int ivar_count; */
3714
3715   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3716   field_decl = get_identifier ("ivar_count");
3717
3718   field_decl = grokfield (input_filename, lineno, field_decl,
3719                           decl_specs, NULL_TREE);
3720   field_decl_chain = field_decl;
3721
3722   /* struct objc_ivar ivar_list[]; */
3723
3724   decl_specs = build_tree_list (NULL_TREE, list_type);
3725   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3726                          build_int_2 (size, 0));
3727
3728   field_decl = grokfield (input_filename, lineno,
3729                           field_decl, decl_specs, NULL_TREE);
3730   chainon (field_decl_chain, field_decl);
3731
3732   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3733
3734   return objc_ivar_list_record;
3735 }
3736
3737 /* struct {
3738      int method_next;
3739      int method_count;
3740      struct objc_method method_list[method_count];
3741    };  */
3742
3743 static tree
3744 build_method_list_template (list_type, size)
3745      tree list_type;
3746      int size;
3747 {
3748   tree objc_ivar_list_record;
3749   tree decl_specs, field_decl, field_decl_chain;
3750
3751   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3752
3753   /* int method_next; */
3754
3755   decl_specs
3756     = build_tree_list
3757       (NULL_TREE, 
3758        xref_tag (RECORD_TYPE,
3759                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3760   field_decl
3761     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3762   field_decl = grokfield (input_filename, lineno, field_decl,
3763                           decl_specs, NULL_TREE);
3764   field_decl_chain = field_decl;
3765
3766   /* int method_count; */
3767
3768   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3769   field_decl = get_identifier ("method_count");
3770
3771   field_decl = grokfield (input_filename, lineno,
3772                           field_decl, decl_specs, NULL_TREE);
3773   chainon (field_decl_chain, field_decl);
3774
3775   /* struct objc_method method_list[]; */
3776
3777   decl_specs = build_tree_list (NULL_TREE, list_type);
3778   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3779                          build_int_2 (size, 0));
3780
3781   field_decl = grokfield (input_filename, lineno,
3782                           field_decl, decl_specs, NULL_TREE);
3783   chainon (field_decl_chain, field_decl);
3784
3785   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3786
3787   return objc_ivar_list_record;
3788 }
3789
3790 static tree
3791 build_ivar_list_initializer (type, field_decl)
3792      tree type;
3793      tree field_decl;
3794 {
3795   tree initlist = NULL_TREE;
3796
3797   do
3798     {
3799       tree ivar = NULL_TREE;
3800
3801       /* Set name.  */
3802       if (DECL_NAME (field_decl))
3803         ivar = tree_cons (NULL_TREE,
3804                           add_objc_string (DECL_NAME (field_decl),
3805                                            meth_var_names),
3806                           ivar);
3807       else
3808         /* Unnamed bit-field ivar (yuck).  */
3809         ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3810
3811       /* Set type.  */
3812       encode_field_decl (field_decl,
3813                          obstack_object_size (&util_obstack),
3814                          OBJC_ENCODE_DONT_INLINE_DEFS);
3815
3816       /* Null terminate string.  */
3817       obstack_1grow (&util_obstack, 0);
3818       ivar
3819         = tree_cons
3820           (NULL_TREE,
3821            add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3822                             meth_var_types),
3823            ivar);
3824       obstack_free (&util_obstack, util_firstobj);
3825
3826       /* Set offset.  */
3827       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
3828       initlist = tree_cons (NULL_TREE, 
3829                             objc_build_constructor (type, nreverse (ivar)),
3830                             initlist);
3831
3832       field_decl = TREE_CHAIN (field_decl);
3833     }
3834   while (field_decl);
3835
3836   return objc_build_constructor (build_array_type (type, 0),
3837                                  nreverse (initlist));
3838 }
3839
3840 static tree
3841 generate_ivars_list (type, name, size, list)
3842      tree type;
3843      const char *name;
3844      int size;
3845      tree list;
3846 {
3847   tree sc_spec, decl_specs, decl, initlist;
3848
3849   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3850   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3851
3852   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
3853                      decl_specs, 1, NULL_TREE);
3854
3855   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3856   initlist = tree_cons (NULL_TREE, list, initlist);
3857
3858   finish_decl (decl,
3859                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3860                NULL_TREE);
3861
3862   return decl;
3863 }
3864
3865 static void
3866 generate_ivar_lists ()
3867 {
3868   tree initlist, ivar_list_template, chain;
3869   tree cast, variable_length_type;
3870   int size;
3871
3872   generating_instance_variables = 1;
3873
3874   if (!objc_ivar_template)
3875     objc_ivar_template = build_ivar_template ();
3876
3877   cast
3878     = build_tree_list
3879       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3880                                          get_identifier (UTAG_IVAR_LIST))),
3881        NULL_TREE);
3882   variable_length_type = groktypename (cast);
3883
3884   /* Only generate class variables for the root of the inheritance
3885      hierarchy since these will be the same for every class.  */
3886
3887   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3888       && (chain = TYPE_FIELDS (objc_class_template)))
3889     {
3890       size = list_length (chain);
3891
3892       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3893       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3894
3895       UOBJC_CLASS_VARIABLES_decl
3896         = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3897                                size, initlist);
3898       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3899     }
3900   else
3901     UOBJC_CLASS_VARIABLES_decl = 0;
3902
3903   chain = CLASS_IVARS (implementation_template);
3904   if (chain)
3905     {
3906       size = list_length (chain);
3907       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3908       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3909
3910       UOBJC_INSTANCE_VARIABLES_decl
3911         = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3912                                size, initlist);
3913       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3914     }
3915   else
3916     UOBJC_INSTANCE_VARIABLES_decl = 0;
3917
3918   generating_instance_variables = 0;
3919 }
3920
3921 static tree
3922 build_dispatch_table_initializer (type, entries)
3923      tree type;
3924      tree entries;
3925 {
3926   tree initlist = NULL_TREE;
3927
3928   do
3929     {
3930       tree elemlist = NULL_TREE;
3931
3932       elemlist = tree_cons (NULL_TREE,
3933                             build_selector (METHOD_SEL_NAME (entries)),
3934                             NULL_TREE);
3935
3936       /* Generate the method encoding if we don't have one already.  */
3937       if (! METHOD_ENCODING (entries))
3938         METHOD_ENCODING (entries) =
3939           encode_method_def (METHOD_DEFINITION (entries));
3940
3941       elemlist = tree_cons (NULL_TREE,
3942                             add_objc_string (METHOD_ENCODING (entries),
3943                                              meth_var_types),
3944                             elemlist);
3945
3946       elemlist = tree_cons (NULL_TREE, 
3947                             build_unary_op (ADDR_EXPR,
3948                                             METHOD_DEFINITION (entries), 1),
3949                             elemlist);
3950
3951       initlist = tree_cons (NULL_TREE, 
3952                             objc_build_constructor (type, nreverse (elemlist)),
3953                             initlist);
3954
3955       entries = TREE_CHAIN (entries);
3956     }
3957   while (entries);
3958
3959   return objc_build_constructor (build_array_type (type, 0),
3960                                  nreverse (initlist));
3961 }
3962
3963 /* To accomplish method prototyping without generating all kinds of
3964    inane warnings, the definition of the dispatch table entries were
3965    changed from:
3966
3967         struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3968    to:
3969         struct objc_method { SEL _cmd; ...; void *_imp; };  */
3970
3971 static tree
3972 build_method_template ()
3973 {
3974   tree _SLT_record;
3975   tree decl_specs, field_decl, field_decl_chain;
3976
3977   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3978
3979   /* struct objc_selector *_cmd; */
3980   decl_specs = tree_cons (NULL_TREE,
3981                           xref_tag (RECORD_TYPE,
3982                                     get_identifier (TAG_SELECTOR)),
3983                           NULL_TREE);
3984   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3985
3986   field_decl = grokfield (input_filename, lineno, field_decl,
3987                           decl_specs, NULL_TREE);
3988   field_decl_chain = field_decl;
3989
3990   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3991   field_decl = build1 (INDIRECT_REF, NULL_TREE,
3992                        get_identifier ("method_types"));
3993   field_decl = grokfield (input_filename, lineno, field_decl,
3994                           decl_specs, NULL_TREE);
3995   chainon (field_decl_chain, field_decl);
3996
3997   /* void *_imp; */
3998
3999   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4000   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4001   field_decl = grokfield (input_filename, lineno, field_decl,
4002                           decl_specs, NULL_TREE);
4003   chainon (field_decl_chain, field_decl);
4004
4005   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4006
4007   return _SLT_record;
4008 }
4009
4010
4011 static tree
4012 generate_dispatch_table (type, name, size, list)
4013      tree type;
4014      const char *name;
4015      int size;
4016      tree list;
4017 {
4018   tree sc_spec, decl_specs, decl, initlist;
4019
4020   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4021   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4022
4023   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4024                      decl_specs, 1, NULL_TREE);
4025
4026   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4027   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4028   initlist = tree_cons (NULL_TREE, list, initlist);
4029
4030   finish_decl (decl,
4031                objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4032                NULL_TREE);
4033
4034   return decl;
4035 }
4036
4037 static void
4038 mark_referenced_methods ()
4039 {
4040   struct imp_entry *impent;
4041   tree chain;
4042
4043   for (impent = imp_list; impent; impent = impent->next)
4044     {
4045       chain = CLASS_CLS_METHODS (impent->imp_context);
4046       while (chain)
4047         {
4048           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1);
4049           chain = TREE_CHAIN (chain);
4050         }
4051       chain = CLASS_NST_METHODS (impent->imp_context);
4052       while (chain)
4053         {
4054           cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1);
4055           chain = TREE_CHAIN (chain);
4056         }
4057     }
4058 }
4059
4060 static void
4061 generate_dispatch_tables ()
4062 {
4063   tree initlist, chain, method_list_template;
4064   tree cast, variable_length_type;
4065   int size;
4066
4067   if (!objc_method_template)
4068     objc_method_template = build_method_template ();
4069
4070   cast
4071     = build_tree_list
4072       (build_tree_list (NULL_TREE,
4073                         xref_tag (RECORD_TYPE,
4074                                   get_identifier (UTAG_METHOD_LIST))),
4075        NULL_TREE);
4076
4077   variable_length_type = groktypename (cast);
4078
4079   chain = CLASS_CLS_METHODS (objc_implementation_context);
4080   if (chain)
4081     {
4082       size = list_length (chain);
4083
4084       method_list_template
4085         = build_method_list_template (objc_method_template, size);
4086       initlist
4087         = build_dispatch_table_initializer (objc_method_template, chain);
4088
4089       UOBJC_CLASS_METHODS_decl
4090         = generate_dispatch_table (method_list_template,
4091                                    ((TREE_CODE (objc_implementation_context)
4092                                      == CLASS_IMPLEMENTATION_TYPE)
4093                                     ? "_OBJC_CLASS_METHODS"
4094                                     : "_OBJC_CATEGORY_CLASS_METHODS"),
4095                                    size, initlist);
4096       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4097     }
4098   else
4099     UOBJC_CLASS_METHODS_decl = 0;
4100
4101   chain = CLASS_NST_METHODS (objc_implementation_context);
4102   if (chain)
4103     {
4104       size = list_length (chain);
4105
4106       method_list_template
4107         = build_method_list_template (objc_method_template, size);
4108       initlist
4109         = build_dispatch_table_initializer (objc_method_template, chain);
4110
4111       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4112         UOBJC_INSTANCE_METHODS_decl
4113           = generate_dispatch_table (method_list_template,
4114                                      "_OBJC_INSTANCE_METHODS",
4115                                      size, initlist);
4116       else
4117         /* We have a category.  */
4118         UOBJC_INSTANCE_METHODS_decl
4119           = generate_dispatch_table (method_list_template,
4120                                      "_OBJC_CATEGORY_INSTANCE_METHODS",
4121                                      size, initlist);
4122       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4123     }
4124   else
4125     UOBJC_INSTANCE_METHODS_decl = 0;
4126 }
4127
4128 static tree
4129 generate_protocol_list (i_or_p)
4130      tree i_or_p;
4131 {
4132   tree initlist, decl_specs, sc_spec;
4133   tree refs_decl, expr_decl, lproto, e, plist;
4134   tree cast_type;
4135   int size = 0;
4136
4137   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4138       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4139     plist = CLASS_PROTOCOL_LIST (i_or_p);
4140   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4141     plist = PROTOCOL_LIST (i_or_p);
4142   else
4143     abort ();
4144
4145   cast_type = groktypename
4146     (build_tree_list
4147      (build_tree_list (NULL_TREE,
4148                        xref_tag (RECORD_TYPE,
4149                                  get_identifier (UTAG_PROTOCOL))),
4150       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4151
4152   /* Compute size.  */
4153   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4154     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4155         && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4156       size++;
4157
4158   /* Build initializer.  */
4159   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4160
4161   e = build_int_2 (size, 0);
4162   TREE_TYPE (e) = cast_type;
4163   initlist = tree_cons (NULL_TREE, e, initlist);
4164
4165   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4166     {
4167       tree pval = TREE_VALUE (lproto);
4168
4169       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4170           && PROTOCOL_FORWARD_DECL (pval))
4171         {
4172           e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4173           initlist = tree_cons (NULL_TREE, e, initlist);
4174         }
4175     }
4176
4177   /* static struct objc_protocol *refs[n]; */
4178
4179   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4180   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4181                                            get_identifier (UTAG_PROTOCOL)),
4182                           sc_spec);
4183
4184   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4185     expr_decl = build_nt (ARRAY_REF,
4186                           synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4187                                                       i_or_p),
4188                           build_int_2 (size + 2, 0));
4189   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4190     expr_decl = build_nt (ARRAY_REF,
4191                           synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4192                                                       i_or_p),
4193                           build_int_2 (size + 2, 0));
4194   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4195     expr_decl
4196       = build_nt (ARRAY_REF,
4197                   synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4198                                               i_or_p),
4199                   build_int_2 (size + 2, 0));
4200   else
4201     abort ();
4202
4203   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4204
4205   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4206   DECL_CONTEXT (refs_decl) = NULL_TREE;
4207
4208   finish_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4209                                                   nreverse (initlist)),
4210                NULL_TREE);
4211
4212   return refs_decl;
4213 }
4214
4215 static tree
4216 build_category_initializer (type, cat_name, class_name,
4217                             instance_methods, class_methods, protocol_list)
4218      tree type;
4219      tree cat_name;
4220      tree class_name;
4221      tree instance_methods;
4222      tree class_methods;
4223      tree protocol_list;
4224 {
4225   tree initlist = NULL_TREE, expr;
4226
4227   initlist = tree_cons (NULL_TREE, cat_name, initlist);
4228   initlist = tree_cons (NULL_TREE, class_name, initlist);
4229
4230   if (!instance_methods)
4231     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4232   else
4233     {
4234       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4235       initlist = tree_cons (NULL_TREE, expr, initlist);
4236     }
4237   if (!class_methods)
4238     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4239   else
4240     {
4241       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4242       initlist = tree_cons (NULL_TREE, expr, initlist);
4243     }
4244
4245   /* protocol_list = */
4246   if (!protocol_list)
4247      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4248   else
4249      {
4250        tree cast_type2 = groktypename
4251          (build_tree_list
4252           (build_tree_list (NULL_TREE,
4253                             xref_tag (RECORD_TYPE,
4254                                       get_identifier (UTAG_PROTOCOL))),
4255            build1 (INDIRECT_REF, NULL_TREE,
4256                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4257
4258         expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4259         TREE_TYPE (expr) = cast_type2;
4260         initlist = tree_cons (NULL_TREE, expr, initlist);
4261      }
4262
4263   return objc_build_constructor (type, nreverse (initlist));
4264 }
4265
4266 /* struct objc_class {
4267      struct objc_class *isa;
4268      struct objc_class *super_class;
4269      char *name;
4270      long version;
4271      long info;
4272      long instance_size;
4273      struct objc_ivar_list *ivars;
4274      struct objc_method_list *methods;
4275      if (flag_next_runtime)
4276        struct objc_cache *cache;
4277      else {
4278        struct sarray *dtable;
4279        struct objc_class *subclass_list;
4280        struct objc_class *sibling_class;
4281      }
4282      struct objc_protocol_list *protocols;
4283      void *gc_object_type;
4284    };  */
4285
4286 static tree
4287 build_shared_structure_initializer (type, isa, super, name, size, status,
4288                                     dispatch_table, ivar_list, protocol_list)
4289      tree type;
4290      tree isa;
4291      tree super;
4292      tree name;
4293      tree size;
4294      int status;
4295      tree dispatch_table;
4296      tree ivar_list;
4297      tree protocol_list;
4298 {
4299   tree initlist = NULL_TREE, expr;
4300
4301   /* isa = */
4302   initlist = tree_cons (NULL_TREE, isa, initlist);
4303
4304   /* super_class = */
4305   initlist = tree_cons (NULL_TREE, super, initlist);
4306
4307   /* name = */
4308   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4309
4310   /* version = */
4311   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4312
4313   /* info = */
4314   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4315
4316   /* instance_size = */
4317   initlist = tree_cons (NULL_TREE, size, initlist);
4318
4319   /* objc_ivar_list = */
4320   if (!ivar_list)
4321     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4322   else
4323     {
4324       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4325       initlist = tree_cons (NULL_TREE, expr, initlist);
4326     }
4327
4328   /* objc_method_list = */
4329   if (!dispatch_table)
4330     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4331   else
4332     {
4333       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4334       initlist = tree_cons (NULL_TREE, expr, initlist);
4335     }
4336
4337   if (flag_next_runtime)
4338     /* method_cache = */
4339     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4340   else
4341     {
4342       /* dtable = */
4343       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4344
4345       /* subclass_list = */
4346       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4347
4348       /* sibling_class = */
4349       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4350     }
4351
4352   /* protocol_list = */
4353   if (! protocol_list)
4354     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4355   else
4356      {
4357        tree cast_type2
4358          = groktypename
4359          (build_tree_list
4360           (build_tree_list (NULL_TREE,
4361                             xref_tag (RECORD_TYPE,
4362                                       get_identifier (UTAG_PROTOCOL))),
4363            build1 (INDIRECT_REF, NULL_TREE,
4364                    build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4365
4366      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4367      TREE_TYPE (expr) = cast_type2;
4368      initlist = tree_cons (NULL_TREE, expr, initlist);
4369      }
4370
4371   /* gc_object_type = NULL */
4372   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4373
4374   return objc_build_constructor (type, nreverse (initlist));
4375 }
4376
4377 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
4378
4379 static void
4380 generate_category (cat)
4381      tree cat;
4382 {
4383   tree sc_spec, decl_specs, decl;
4384   tree initlist, cat_name_expr, class_name_expr;
4385   tree protocol_decl, category;
4386
4387   add_class_reference (CLASS_NAME (cat));
4388   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4389
4390   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4391
4392   category = CLASS_CATEGORY_LIST (implementation_template);
4393
4394   /* find the category interface from the class it is associated with */
4395   while (category)
4396     {
4397       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4398         break;
4399       category = CLASS_CATEGORY_LIST (category);
4400     }
4401
4402   if (category && CLASS_PROTOCOL_LIST (category))
4403     {
4404       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4405       protocol_decl = generate_protocol_list (category);
4406     }
4407   else
4408     protocol_decl = 0;
4409
4410   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4411   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4412
4413   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4414                                                  objc_implementation_context),
4415                      decl_specs, 1, NULL_TREE);
4416
4417   initlist = build_category_initializer (TREE_TYPE (decl),
4418                                          cat_name_expr, class_name_expr,
4419                                          UOBJC_INSTANCE_METHODS_decl,
4420                                          UOBJC_CLASS_METHODS_decl,
4421                                          protocol_decl);
4422
4423   TREE_USED (decl) = 1;
4424   finish_decl (decl, initlist, NULL_TREE);
4425 }
4426
4427 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4428    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
4429
4430 static void
4431 generate_shared_structures ()
4432 {
4433   tree sc_spec, decl_specs, decl;
4434   tree name_expr, super_expr, root_expr;
4435   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4436   tree cast_type, initlist, protocol_decl;
4437
4438   my_super_id = CLASS_SUPER_NAME (implementation_template);
4439   if (my_super_id)
4440     {
4441       add_class_reference (my_super_id);
4442
4443       /* Compute "my_root_id" - this is required for code generation.
4444          the "isa" for all meta class structures points to the root of
4445          the inheritance hierarchy (e.g. "__Object")...  */
4446       my_root_id = my_super_id;
4447       do
4448         {
4449           tree my_root_int = lookup_interface (my_root_id);
4450
4451           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4452             my_root_id = CLASS_SUPER_NAME (my_root_int);
4453           else
4454             break;
4455         }
4456       while (1);
4457     }
4458   else
4459     /* No super class.  */
4460     my_root_id = CLASS_NAME (implementation_template);
4461
4462   cast_type
4463     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4464                                                       objc_class_template),
4465                                      build1 (INDIRECT_REF,
4466                                              NULL_TREE, NULL_TREE)));
4467
4468   name_expr = add_objc_string (CLASS_NAME (implementation_template),
4469                                class_names);
4470
4471   /* Install class `isa' and `super' pointers at runtime.  */
4472   if (my_super_id)
4473     {
4474       super_expr = add_objc_string (my_super_id, class_names);
4475       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4476     }
4477   else
4478     super_expr = build_int_2 (0, 0);
4479
4480   root_expr = add_objc_string (my_root_id, class_names);
4481   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4482
4483   if (CLASS_PROTOCOL_LIST (implementation_template))
4484     {
4485       generate_protocol_references
4486         (CLASS_PROTOCOL_LIST (implementation_template));
4487       protocol_decl = generate_protocol_list (implementation_template);
4488     }
4489   else
4490     protocol_decl = 0;
4491
4492   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4493
4494   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4495   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4496
4497   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4498                      NULL_TREE);
4499
4500   initlist
4501     = build_shared_structure_initializer
4502       (TREE_TYPE (decl),
4503        root_expr, super_expr, name_expr,
4504        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
4505        2 /*CLS_META*/,
4506        UOBJC_CLASS_METHODS_decl,
4507        UOBJC_CLASS_VARIABLES_decl,
4508        protocol_decl);
4509
4510   finish_decl (decl, initlist, NULL_TREE);
4511
4512   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4513
4514   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4515                      NULL_TREE);
4516
4517   initlist
4518     = build_shared_structure_initializer
4519       (TREE_TYPE (decl),
4520        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4521        super_expr, name_expr,
4522        convert (integer_type_node,
4523                 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
4524                                 (implementation_template))),
4525        1 /*CLS_FACTORY*/,
4526        UOBJC_INSTANCE_METHODS_decl,
4527        UOBJC_INSTANCE_VARIABLES_decl,
4528        protocol_decl);
4529
4530   finish_decl (decl, initlist, NULL_TREE);
4531 }
4532
4533 static tree
4534 synth_id_with_class_suffix (preamble, ctxt)
4535      const char *preamble;
4536      tree ctxt;
4537 {
4538   char *string;
4539   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4540       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4541     {
4542       const char *const class_name
4543         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4544       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4545       sprintf (string, "%s_%s", preamble,
4546                IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4547     }
4548   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4549            || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4550     {
4551       /* We have a category.  */
4552       const char *const class_name
4553         = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4554       const char *const class_super_name
4555         = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
4556       string = (char *) alloca (strlen (preamble)
4557                                 + strlen (class_name)
4558                                 + strlen (class_super_name)
4559                                 + 3);
4560       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4561     }
4562   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4563     {
4564       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4565       string
4566         = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4567       sprintf (string, "%s_%s", preamble, protocol_name);
4568     }
4569   else
4570     abort ();
4571   
4572   return get_identifier (string);
4573 }
4574
4575 static int
4576 is_objc_type_qualifier (node)
4577      tree node;
4578 {
4579   return (TREE_CODE (node) == IDENTIFIER_NODE
4580           && (node == ridpointers [(int) RID_CONST]
4581               || node == ridpointers [(int) RID_VOLATILE]
4582               || node == ridpointers [(int) RID_IN]
4583               || node == ridpointers [(int) RID_OUT]
4584               || node == ridpointers [(int) RID_INOUT]
4585               || node == ridpointers [(int) RID_BYCOPY]
4586               || node == ridpointers [(int) RID_BYREF]
4587               || node == ridpointers [(int) RID_ONEWAY]));
4588 }
4589
4590 /* If type is empty or only type qualifiers are present, add default
4591    type of id (otherwise grokdeclarator will default to int).  */
4592
4593 static tree
4594 adjust_type_for_id_default (type)
4595      tree type;
4596 {
4597   tree declspecs, chain;
4598
4599   if (!type)
4600     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4601                             build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4602
4603   declspecs = TREE_PURPOSE (type);
4604
4605   /* Determine if a typespec is present.  */
4606   for (chain = declspecs;
4607        chain;
4608        chain = TREE_CHAIN (chain))
4609     {
4610       if (TYPED_OBJECT (TREE_VALUE (chain))
4611           && !(TREE_VALUE (type) 
4612                && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
4613         error ("can not use an object as parameter to a method\n");
4614       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4615         return type;
4616     }
4617
4618   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4619                                      declspecs),
4620                           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4621 }
4622
4623 /*   Usage:
4624                 keyworddecl:
4625                         selector ':' '(' typename ')' identifier
4626   
4627      Purpose:
4628                 Transform an Objective-C keyword argument into
4629                 the C equivalent parameter declarator.
4630   
4631      In:        key_name, an "identifier_node" (optional).
4632                 arg_type, a  "tree_list" (optional).
4633                 arg_name, an "identifier_node".
4634   
4635      Note:      It would be really nice to strongly type the preceding
4636                 arguments in the function prototype; however, then I
4637                 could not use the "accessor" macros defined in "tree.h".
4638   
4639      Out:       an instance of "keyword_decl".  */
4640
4641 tree
4642 build_keyword_decl (key_name, arg_type, arg_name)
4643      tree key_name;
4644      tree arg_type;
4645      tree arg_name;
4646 {
4647   tree keyword_decl;
4648
4649   /* If no type is specified, default to "id".  */
4650   arg_type = adjust_type_for_id_default (arg_type);
4651
4652   keyword_decl = make_node (KEYWORD_DECL);
4653
4654   TREE_TYPE (keyword_decl) = arg_type;
4655   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4656   KEYWORD_KEY_NAME (keyword_decl) = key_name;
4657
4658   return keyword_decl;
4659 }
4660
4661 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
4662
4663 static tree
4664 build_keyword_selector (selector)
4665      tree selector;
4666 {
4667   int len = 0;
4668   tree key_chain, key_name;
4669   char *buf;
4670
4671   /* Scan the selector to see how much space we'll need.  */
4672   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4673     {
4674       if (TREE_CODE (selector) == KEYWORD_DECL)
4675         key_name = KEYWORD_KEY_NAME (key_chain);
4676       else if (TREE_CODE (selector) == TREE_LIST)
4677         key_name = TREE_PURPOSE (key_chain);
4678       else
4679         abort ();
4680
4681       if (key_name)
4682         len += IDENTIFIER_LENGTH (key_name) + 1;
4683       else
4684         /* Just a ':' arg.  */
4685         len++;
4686     }
4687
4688   buf = (char *) alloca (len + 1);
4689   /* Start the buffer out as an empty string.  */
4690   buf[0] = '\0';
4691
4692   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4693     {
4694       if (TREE_CODE (selector) == KEYWORD_DECL)
4695         key_name = KEYWORD_KEY_NAME (key_chain);
4696       else if (TREE_CODE (selector) == TREE_LIST)
4697         key_name = TREE_PURPOSE (key_chain);
4698       else
4699         abort ();
4700
4701       if (key_name)
4702         strcat (buf, IDENTIFIER_POINTER (key_name));
4703       strcat (buf, ":");
4704     }
4705
4706   return get_identifier (buf);
4707 }
4708
4709 /* Used for declarations and definitions.  */
4710
4711 tree
4712 build_method_decl (code, ret_type, selector, add_args)
4713      enum tree_code code;
4714      tree ret_type;
4715      tree selector;
4716      tree add_args;
4717 {
4718   tree method_decl;
4719
4720   /* If no type is specified, default to "id".  */
4721   ret_type = adjust_type_for_id_default (ret_type);
4722
4723   method_decl = make_node (code);
4724   TREE_TYPE (method_decl) = ret_type;
4725
4726   /* If we have a keyword selector, create an identifier_node that
4727      represents the full selector name (`:' included)...  */
4728   if (TREE_CODE (selector) == KEYWORD_DECL)
4729     {
4730       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4731       METHOD_SEL_ARGS (method_decl) = selector;
4732       METHOD_ADD_ARGS (method_decl) = add_args;
4733     }
4734   else
4735     {
4736       METHOD_SEL_NAME (method_decl) = selector;
4737       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4738       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4739     }
4740
4741   return method_decl;
4742 }
4743
4744 #define METHOD_DEF 0
4745 #define METHOD_REF 1
4746
4747 /* Used by `build_objc_method_call' and `comp_method_types'.  Return
4748    an argument list for method METH.  CONTEXT is either METHOD_DEF or
4749    METHOD_REF, saying whether we are trying to define a method or call
4750    one.  SUPERFLAG says this is for a send to super; this makes a
4751    difference for the NeXT calling sequence in which the lookup and
4752    the method call are done together.  */
4753
4754 static tree
4755 get_arg_type_list (meth, context, superflag)
4756      tree meth;
4757      int context;
4758      int superflag;
4759 {
4760   tree arglist, akey;
4761
4762   /* Receiver type.  */
4763   if (flag_next_runtime && superflag)
4764     arglist = build_tree_list (NULL_TREE, super_type);
4765   else if (context == METHOD_DEF)
4766     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4767   else
4768     arglist = build_tree_list (NULL_TREE, id_type);
4769
4770   /* Selector type - will eventually change to `int'.  */
4771   chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4772
4773   /* Build a list of argument types.  */
4774   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4775     {
4776       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4777       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4778     }
4779
4780   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
4781     /* We have a `, ...' immediately following the selector,
4782        finalize the arglist...simulate get_parm_info (0).  */
4783     ;
4784   else if (METHOD_ADD_ARGS (meth))
4785     {
4786       /* we have a variable length selector */
4787       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4788       chainon (arglist, add_arg_list);
4789     }
4790   else
4791     /* finalize the arglist...simulate get_parm_info (1) */
4792     chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4793
4794   return arglist;
4795 }
4796
4797 static tree
4798 check_duplicates (hsh)
4799      hash hsh;
4800 {
4801   tree meth = NULL_TREE;
4802
4803   if (hsh)
4804     {
4805       meth = hsh->key;
4806
4807       if (hsh->list)
4808         {
4809           /* We have two methods with the same name and different types.  */
4810           attr loop;
4811           char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4812
4813           warning ("multiple declarations for method `%s'",
4814                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4815
4816           warn_with_method ("using", type, meth);
4817           for (loop = hsh->list; loop; loop = loop->next)
4818             warn_with_method ("also found", type, loop->value);
4819         }
4820     }
4821   return meth;
4822 }
4823
4824 /* If RECEIVER is a class reference, return the identifier node for
4825    the referenced class.  RECEIVER is created by get_class_reference,
4826    so we check the exact form created depending on which runtimes are
4827    used.  */
4828
4829 static tree
4830 receiver_is_class_object (receiver)
4831       tree receiver;
4832 {
4833   tree chain, exp, arg;
4834
4835   /* The receiver is 'self' in the context of a class method.  */
4836   if (objc_method_context
4837       && receiver == self_decl
4838       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
4839     {
4840       return CLASS_NAME (objc_implementation_context);
4841     }
4842   
4843   if (flag_next_runtime)
4844     {
4845       /* The receiver is a variable created by
4846          build_class_reference_decl.  */
4847       if (TREE_CODE (receiver) == VAR_DECL
4848           && TREE_TYPE (receiver) == objc_class_type)
4849         /* Look up the identifier.  */
4850         for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4851           if (TREE_PURPOSE (chain) == receiver)
4852             return TREE_VALUE (chain);
4853     }
4854   else
4855     {
4856       /* The receiver is a function call that returns an id.  Check if
4857          it is a call to objc_getClass, if so, pick up the class name.  */
4858       if (TREE_CODE (receiver) == CALL_EXPR 
4859           && (exp = TREE_OPERAND (receiver, 0))
4860           && TREE_CODE (exp) == ADDR_EXPR
4861           && (exp = TREE_OPERAND (exp, 0))
4862           && TREE_CODE (exp) == FUNCTION_DECL
4863           && exp == objc_get_class_decl
4864           /* We have a call to objc_getClass!  */
4865           && (arg = TREE_OPERAND (receiver, 1))
4866           && TREE_CODE (arg) == TREE_LIST
4867           && (arg = TREE_VALUE (arg)))
4868         {
4869           STRIP_NOPS (arg);
4870           if (TREE_CODE (arg) == ADDR_EXPR
4871               && (arg = TREE_OPERAND (arg, 0))
4872               && TREE_CODE (arg) == STRING_CST)
4873             /* Finally, we have the class name.  */
4874             return get_identifier (TREE_STRING_POINTER (arg));
4875         }
4876     }
4877   return 0;
4878 }
4879 \f
4880 /* If we are currently building a message expr, this holds
4881    the identifier of the selector of the message.  This is
4882    used when printing warnings about argument mismatches.  */
4883
4884 static tree current_objc_message_selector = 0;
4885
4886 tree
4887 objc_message_selector ()
4888 {
4889   return current_objc_message_selector;
4890 }
4891
4892 /* Construct an expression for sending a message.
4893    MESS has the object to send to in TREE_PURPOSE
4894    and the argument list (including selector) in TREE_VALUE.
4895
4896    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4897    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
4898
4899 tree
4900 build_message_expr (mess)
4901      tree mess;
4902 {
4903   tree receiver = TREE_PURPOSE (mess);
4904   tree sel_name;
4905   tree args = TREE_VALUE (mess);
4906   tree method_params = NULL_TREE;
4907
4908   if (TREE_CODE (receiver) == ERROR_MARK)
4909     return error_mark_node;
4910
4911   /* Obtain the full selector name.  */
4912   if (TREE_CODE (args) == IDENTIFIER_NODE)
4913     /* A unary selector.  */
4914     sel_name = args;
4915   else if (TREE_CODE (args) == TREE_LIST)
4916     sel_name = build_keyword_selector (args);
4917   else
4918     abort ();
4919
4920   /* Build the parameter list to give to the method.  */
4921   if (TREE_CODE (args) == TREE_LIST)
4922     {
4923       tree chain = args, prev = NULL_TREE;
4924
4925       /* We have a keyword selector--check for comma expressions.  */
4926       while (chain)
4927         {
4928           tree element = TREE_VALUE (chain);
4929
4930           /* We have a comma expression, must collapse...  */
4931           if (TREE_CODE (element) == TREE_LIST)
4932             {
4933               if (prev)
4934                 TREE_CHAIN (prev) = element;
4935               else
4936                 args = element;
4937             }
4938           prev = chain;
4939           chain = TREE_CHAIN (chain);
4940         }
4941       method_params = args;
4942     }
4943
4944   return finish_message_expr (receiver, sel_name, method_params);
4945 }
4946
4947 /* The 'finish_message_expr' routine is called from within
4948    'build_message_expr' for non-template functions.  In the case of
4949    C++ template functions, it is called from 'build_expr_from_tree'
4950    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
4951    
4952 tree
4953 finish_message_expr (receiver, sel_name, method_params)
4954      tree receiver, sel_name, method_params; 
4955 {      
4956   tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
4957   tree selector, self_object, retval;
4958   int statically_typed = 0, statically_allocated = 0;
4959   
4960   /* Determine receiver type.  */
4961   tree rtype = TREE_TYPE (receiver);
4962   int super = IS_SUPER (rtype);
4963
4964   if (! super)
4965     {
4966       if (TREE_STATIC_TEMPLATE (rtype))
4967         statically_allocated = 1;
4968       else if (TREE_CODE (rtype) == POINTER_TYPE
4969                && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4970         statically_typed = 1;
4971       else if ((flag_next_runtime
4972                 || (IS_ID (rtype)))
4973                && (class_ident = receiver_is_class_object (receiver)))
4974         ;
4975       else if (! IS_ID (rtype)
4976                /* Allow any type that matches objc_class_type.  */
4977                && ! comptypes (rtype, objc_class_type))
4978         {
4979           warning ("invalid receiver type `%s'",
4980                    gen_declaration (rtype, errbuf));
4981         }
4982       if (statically_allocated)
4983         receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4984
4985       /* Don't evaluate the receiver twice.  */
4986       receiver = save_expr (receiver);
4987       self_object = receiver;
4988     }
4989   else
4990     /* If sending to `super', use current self as the object.  */
4991     self_object = self_decl;
4992
4993   /* Determine operation return type.  */
4994
4995   if (super)
4996     {
4997       tree iface;
4998
4999       if (CLASS_SUPER_NAME (implementation_template))
5000         {
5001           iface
5002             = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5003
5004           if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
5005             method_prototype = lookup_instance_method_static (iface, sel_name);
5006           else
5007             method_prototype = lookup_class_method_static (iface, sel_name);
5008
5009           if (iface && !method_prototype)
5010             warning ("`%s' does not respond to `%s'",
5011                      IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
5012                      IDENTIFIER_POINTER (sel_name));
5013         }
5014       else
5015         {
5016           error ("no super class declared in interface for `%s'",
5017                  IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5018           return error_mark_node;
5019         }
5020
5021     }
5022   else if (statically_allocated)
5023     {
5024       tree ctype = TREE_TYPE (rtype);
5025       tree iface = lookup_interface (TYPE_NAME (rtype));
5026
5027       if (iface)
5028         method_prototype = lookup_instance_method_static (iface, sel_name);
5029
5030       if (! method_prototype && ctype && TYPE_PROTOCOL_LIST (ctype))
5031         method_prototype
5032           = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5033                                             sel_name, 0);
5034
5035       if (!method_prototype)
5036         warning ("`%s' does not respond to `%s'",
5037                  IDENTIFIER_POINTER (TYPE_NAME (rtype)),
5038                  IDENTIFIER_POINTER (sel_name));
5039     }
5040   else if (statically_typed)
5041     {
5042       tree ctype = TREE_TYPE (rtype);
5043
5044       /* `self' is now statically_typed.  All methods should be visible
5045          within the context of the implementation.  */
5046       if (objc_implementation_context
5047           && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
5048         {
5049           method_prototype
5050             = lookup_instance_method_static (implementation_template,
5051                                              sel_name);
5052
5053           if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5054             method_prototype
5055               = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5056                                                 sel_name, 0);
5057
5058           if (! method_prototype
5059               && implementation_template != objc_implementation_context)
5060             /* The method is not published in the interface.  Check
5061                locally.  */
5062             method_prototype
5063               = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
5064                                sel_name);
5065         }
5066       else
5067         {
5068           tree iface;
5069
5070           if ((iface = lookup_interface (TYPE_NAME (ctype))))
5071             method_prototype = lookup_instance_method_static (iface, sel_name);
5072
5073           if (! method_prototype)
5074             {
5075               tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5076               if (protocol_list)
5077                 method_prototype
5078                   = lookup_method_in_protocol_list (protocol_list,
5079                                                     sel_name, 0);
5080             }
5081         }
5082
5083       if (!method_prototype)
5084         warning ("`%s' does not respond to `%s'",
5085                  IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5086                  IDENTIFIER_POINTER (sel_name));
5087     }
5088   else if (class_ident)
5089     {
5090       if (objc_implementation_context
5091           && CLASS_NAME (objc_implementation_context) == class_ident)
5092         {
5093           method_prototype
5094             = lookup_class_method_static (implementation_template, sel_name);
5095
5096           if (!method_prototype
5097               && implementation_template != objc_implementation_context)
5098             /* The method is not published in the interface. Check
5099                locally.  */
5100             method_prototype
5101               = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
5102                                sel_name);
5103         }
5104       else
5105         {
5106           tree iface;
5107
5108           if ((iface = lookup_interface (class_ident)))
5109             method_prototype = lookup_class_method_static (iface, sel_name);
5110         }
5111
5112       if (!method_prototype)
5113         {
5114           warning ("cannot find class (factory) method");
5115           warning ("return type for `%s' defaults to id",
5116                    IDENTIFIER_POINTER (sel_name));
5117         }
5118     }
5119   else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5120     {
5121       /* An anonymous object that has been qualified with a protocol.  */
5122
5123       tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5124
5125       method_prototype = lookup_method_in_protocol_list (protocol_list,
5126                                                          sel_name, 0);
5127
5128       if (!method_prototype)
5129         {
5130           hash hsh;
5131
5132           warning ("method `%s' not implemented by protocol",
5133                    IDENTIFIER_POINTER (sel_name));
5134
5135           /* Try and find the method signature in the global pools.  */
5136
5137           if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5138             hsh = hash_lookup (cls_method_hash_list, sel_name);
5139
5140           if (!(method_prototype = check_duplicates (hsh)))
5141             warning ("return type defaults to id");
5142         }
5143     }
5144   else
5145     {
5146       hash hsh;
5147
5148       /* We think we have an instance...loophole: extern id Object; */
5149       hsh = hash_lookup (nst_method_hash_list, sel_name);
5150       
5151       if (!hsh)
5152         /* For various loopholes */     
5153         hsh = hash_lookup (cls_method_hash_list, sel_name);
5154
5155       method_prototype = check_duplicates (hsh);
5156       if (!method_prototype)
5157         {
5158           warning ("cannot find method");
5159           warning ("return type for `%s' defaults to id",
5160                    IDENTIFIER_POINTER (sel_name));
5161         }
5162     }
5163
5164   /* Save the selector name for printing error messages.  */
5165   current_objc_message_selector = sel_name;
5166
5167   /* Build the parameters list for looking up the method.
5168      These are the object itself and the selector.  */
5169
5170   if (flag_typed_selectors)
5171     selector = build_typed_selector_reference (sel_name, method_prototype);
5172   else
5173     selector = build_selector_reference (sel_name);
5174
5175   retval = build_objc_method_call (super, method_prototype,
5176                                    receiver, self_object,
5177                                    selector, method_params);
5178
5179   current_objc_message_selector = 0;
5180
5181   return retval;
5182 }
5183 \f
5184 /* Build a tree expression to send OBJECT the operation SELECTOR,
5185    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5186    assuming the method has prototype METHOD_PROTOTYPE.
5187    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5188    Use METHOD_PARAMS as list of args to pass to the method.
5189    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
5190
5191 static tree
5192 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5193                         selector, method_params)
5194      int super_flag;
5195      tree method_prototype, lookup_object, object, selector, method_params;
5196 {
5197   tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5198   tree rcv_p = (super_flag
5199                 ? build_pointer_type (xref_tag (RECORD_TYPE,
5200                                                 get_identifier (TAG_SUPER)))
5201                 : id_type);
5202
5203   if (flag_next_runtime)
5204     {
5205       if (! method_prototype)
5206         {
5207           method_params = tree_cons (NULL_TREE, lookup_object,
5208                                      tree_cons (NULL_TREE, selector,
5209                                                 method_params));
5210           assemble_external (sender);
5211           return build_function_call (sender, method_params);
5212         }
5213       else
5214         {
5215           /* This is a real kludge, but it is used only for the Next.
5216              Clobber the data type of SENDER temporarily to accept
5217              all the arguments for this operation, and to return
5218              whatever this operation returns.  */
5219           tree arglist = NULL_TREE, retval, savarg, savret;
5220           tree ret_type = groktypename (TREE_TYPE (method_prototype));
5221
5222           /* Save the proper contents of SENDER's data type.  */
5223           savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5224           savret = TREE_TYPE (TREE_TYPE (sender));
5225
5226           /* Install this method's argument types.  */
5227           arglist = get_arg_type_list (method_prototype, METHOD_REF,
5228                                        super_flag);
5229           TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5230
5231           /* Install this method's return type.  */
5232           TREE_TYPE (TREE_TYPE (sender)) = ret_type;
5233
5234           /* Call SENDER with all the parameters.  This will do type
5235              checking using the arg types for this method.  */
5236           method_params = tree_cons (NULL_TREE, lookup_object,
5237                                      tree_cons (NULL_TREE, selector,
5238                                                 method_params));
5239           assemble_external (sender);
5240           retval = build_function_call (sender, method_params);
5241
5242           /* Restore SENDER's return/argument types.  */
5243           TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5244           TREE_TYPE (TREE_TYPE (sender)) = savret;
5245           return retval;
5246         }
5247     }
5248   else
5249     {
5250       /* This is the portable way.
5251          First call the lookup function to get a pointer to the method,
5252          then cast the pointer, then call it with the method arguments.  */
5253       tree method;
5254
5255       /* Avoid trouble since we may evaluate each of these twice.  */
5256       object = save_expr (object);
5257       selector = save_expr (selector);
5258
5259       lookup_object = build_c_cast (rcv_p, lookup_object);
5260
5261       assemble_external (sender);
5262       method
5263         = build_function_call (sender,
5264                                tree_cons (NULL_TREE, lookup_object,
5265                                           tree_cons (NULL_TREE, selector,
5266                                                      NULL_TREE)));
5267
5268       /* If we have a method prototype, construct the data type this
5269          method needs, and cast what we got from SENDER into a pointer
5270          to that type.  */
5271       if (method_prototype)
5272         {
5273           tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5274                                             super_flag);
5275           tree valtype = groktypename (TREE_TYPE (method_prototype));
5276           tree fake_function_type = build_function_type (valtype, arglist);
5277           TREE_TYPE (method) = build_pointer_type (fake_function_type);
5278         }
5279       else
5280         TREE_TYPE (method)
5281           = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5282
5283       /* Pass the object to the method.  */
5284       assemble_external (method);
5285       return build_function_call (method,
5286                                   tree_cons (NULL_TREE, object,
5287                                              tree_cons (NULL_TREE, selector,
5288                                                         method_params)));
5289     }
5290 }
5291 \f
5292 static void
5293 build_protocol_reference (p)
5294      tree p;
5295 {
5296   tree decl, ident, ptype;
5297
5298   /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5299
5300   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5301   ptype
5302     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5303                                                       objc_protocol_template),
5304                                      NULL_TREE));
5305
5306   if (identifier_global_value (ident))
5307     decl = identifier_global_value (ident); /* Set by pushdecl.  */
5308   else
5309     {
5310       decl = build_decl (VAR_DECL, ident, ptype);
5311       DECL_EXTERNAL (decl) = 1;
5312       TREE_PUBLIC (decl) = 1;
5313       TREE_USED (decl) = 1;
5314       DECL_ARTIFICIAL (decl) = 1;
5315
5316       make_decl_rtl (decl, 0);
5317       pushdecl_top_level (decl);
5318    }
5319
5320   PROTOCOL_FORWARD_DECL (p) = decl;
5321 }
5322
5323 /* This function is called by the parser when (and only when) a
5324    @protocol() expression is found, in order to compile it.  */
5325 tree
5326 build_protocol_expr (protoname)
5327      tree protoname;
5328 {
5329   tree expr;
5330   tree p = lookup_protocol (protoname);
5331
5332   if (!p)
5333     {
5334       error ("cannot find protocol declaration for `%s'",
5335              IDENTIFIER_POINTER (protoname));
5336       return error_mark_node;
5337     }
5338
5339   if (!PROTOCOL_FORWARD_DECL (p))
5340     build_protocol_reference (p);
5341
5342   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5343
5344   TREE_TYPE (expr) = protocol_type;
5345
5346   /* The @protocol() expression is being compiled into a pointer to a
5347      statically allocated instance of the Protocol class.  To become
5348      usable at runtime, the 'isa' pointer of the instance need to be
5349      fixed up at runtime by the runtime library, to point to the
5350      actual 'Protocol' class.  */
5351
5352   /* For the GNU runtime, put the static Protocol instance in the list
5353      of statically allocated instances, so that we make sure that its
5354      'isa' pointer is fixed up at runtime by the GNU runtime library
5355      to point to the Protocol class (at runtime, when loading the
5356      module, the GNU runtime library loops on the statically allocated
5357      instances (as found in the defs field in objc_symtab) and fixups
5358      all the 'isa' pointers of those objects).  */
5359   if (! flag_next_runtime)
5360     {
5361       /* This type is a struct containing the fields of a Protocol
5362         object.  (Cfr. protocol_type instead is the type of a pointer
5363         to such a struct).  */
5364       tree protocol_struct_type = xref_tag 
5365        (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
5366       tree *chain;
5367       
5368       /* Look for the list of Protocol statically allocated instances
5369         to fixup at runtime.  Create a new list to hold Protocol
5370         statically allocated instances, if the list is not found.  At
5371         present there is only another list, holding NSConstantString
5372         static instances to be fixed up at runtime.  */
5373       for (chain = &objc_static_instances;
5374            *chain && TREE_VALUE (*chain) != protocol_struct_type;
5375            chain = &TREE_CHAIN (*chain));
5376       if (!*chain)
5377         {
5378          *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
5379          add_objc_string (TYPE_NAME (protocol_struct_type),
5380                           class_names);
5381        }
5382       
5383       /* Add this statically allocated instance to the Protocol list.  */
5384       TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, 
5385                                          PROTOCOL_FORWARD_DECL (p),
5386                                          TREE_PURPOSE (*chain));
5387     }
5388   
5389
5390   return expr;
5391 }
5392
5393 /* This function is called by the parser when a @selector() expression
5394    is found, in order to compile it.  It is only called by the parser
5395    and only to compile a @selector().  */
5396 tree
5397 build_selector_expr (selnamelist)
5398      tree selnamelist;
5399 {
5400   tree selname;
5401
5402   /* Obtain the full selector name.  */
5403   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5404     /* A unary selector.  */
5405     selname = selnamelist;
5406   else if (TREE_CODE (selnamelist) == TREE_LIST)
5407     selname = build_keyword_selector (selnamelist);
5408   else
5409     abort ();
5410
5411   /* If we are required to check @selector() expressions as they
5412      are found, check that the selector has been declared.  */
5413   if (warn_undeclared_selector)
5414     {
5415       /* Look the selector up in the list of all known class and
5416          instance methods (up to this line) to check that the selector
5417          exists.  */
5418       hash hsh;
5419
5420       /* First try with instance methods.  */
5421       hsh = hash_lookup (nst_method_hash_list, selname);
5422       
5423       /* If not found, try with class methods.  */
5424       if (!hsh)
5425         {
5426           hsh = hash_lookup (cls_method_hash_list, selname);
5427         }
5428       
5429       /* If still not found, print out a warning.  */
5430       if (!hsh)
5431         {
5432           warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
5433         }
5434     }
5435   
5436
5437   if (flag_typed_selectors)
5438     return build_typed_selector_reference (selname, 0);
5439   else
5440     return build_selector_reference (selname);
5441 }
5442
5443 tree
5444 build_encode_expr (type)
5445      tree type;
5446 {
5447   tree result;
5448   const char *string;
5449
5450   encode_type (type, obstack_object_size (&util_obstack),
5451                OBJC_ENCODE_INLINE_DEFS);
5452   obstack_1grow (&util_obstack, 0);    /* null terminate string */
5453   string = obstack_finish (&util_obstack);
5454
5455   /* Synthesize a string that represents the encoded struct/union.  */
5456   result = my_build_string (strlen (string) + 1, string);
5457   obstack_free (&util_obstack, util_firstobj);
5458   return result;
5459 }
5460
5461 tree
5462 build_ivar_reference (id)
5463      tree id;
5464 {
5465   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
5466     {
5467       /* Historically, a class method that produced objects (factory
5468          method) would assign `self' to the instance that it
5469          allocated.  This would effectively turn the class method into
5470          an instance method.  Following this assignment, the instance
5471          variables could be accessed.  That practice, while safe,
5472          violates the simple rule that a class method should not refer
5473          to an instance variable.  It's better to catch the cases
5474          where this is done unknowingly than to support the above
5475          paradigm.  */
5476       warning ("instance variable `%s' accessed in class method",
5477                IDENTIFIER_POINTER (id));
5478       TREE_TYPE (self_decl) = instance_type; /* cast */
5479     }
5480
5481   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5482 }
5483 \f
5484 /* Compute a hash value for a given method SEL_NAME.  */
5485
5486 static size_t
5487 hash_func (sel_name)
5488      tree sel_name;
5489 {
5490   const unsigned char *s 
5491     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
5492   size_t h = 0;
5493   
5494   while (*s)
5495     h = h * 67 + *s++ - 113;
5496   return h;  
5497 }
5498      
5499 static void
5500 hash_init ()
5501 {
5502   nst_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5503   cls_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
5504 }
5505
5506 /* WARNING!!!!  hash_enter is called with a method, and will peek
5507    inside to find its selector!  But hash_lookup is given a selector
5508    directly, and looks for the selector that's inside the found
5509    entry's key (method) for comparison.  */
5510
5511 static void
5512 hash_enter (hashlist, method)
5513      hash *hashlist;
5514      tree method;
5515 {
5516   hash obj;
5517   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5518
5519   obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
5520   obj->list = 0;
5521   obj->next = hashlist[slot];
5522   obj->key = method;
5523
5524   hashlist[slot] = obj;         /* append to front */
5525 }
5526
5527 static hash
5528 hash_lookup (hashlist, sel_name)
5529      hash *hashlist;
5530      tree sel_name;
5531 {
5532   hash target;
5533
5534   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
5535
5536   while (target)
5537     {
5538       if (sel_name == METHOD_SEL_NAME (target->key))
5539         return target;
5540
5541       target = target->next;
5542     }
5543   return 0;
5544 }
5545
5546 static void
5547 hash_add_attr (entry, value)
5548      hash entry;
5549      tree value;
5550 {
5551   attr obj;
5552
5553   obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
5554   obj->next = entry->list;
5555   obj->value = value;
5556
5557   entry->list = obj;            /* append to front */
5558 }
5559 \f
5560 static tree
5561 lookup_method (mchain, method)
5562      tree mchain;
5563      tree method;
5564 {
5565   tree key;
5566
5567   if (TREE_CODE (method) == IDENTIFIER_NODE)
5568     key = method;
5569   else
5570     key = METHOD_SEL_NAME (method);
5571
5572   while (mchain)
5573     {
5574       if (METHOD_SEL_NAME (mchain) == key)
5575         return mchain;
5576
5577       mchain = TREE_CHAIN (mchain);
5578     }
5579   return NULL_TREE;
5580 }
5581
5582 static tree
5583 lookup_instance_method_static (interface, ident)
5584      tree interface;
5585      tree ident;
5586 {
5587   tree inter = interface;
5588   tree chain = CLASS_NST_METHODS (inter);
5589   tree meth = NULL_TREE;
5590
5591   do
5592     {
5593       if ((meth = lookup_method (chain, ident)))
5594         return meth;
5595
5596       if (CLASS_CATEGORY_LIST (inter))
5597         {
5598           tree category = CLASS_CATEGORY_LIST (inter);
5599           chain = CLASS_NST_METHODS (category);
5600
5601           do
5602             {
5603               if ((meth = lookup_method (chain, ident)))
5604                 return meth;
5605
5606               /* Check for instance methods in protocols in categories.  */
5607               if (CLASS_PROTOCOL_LIST (category))
5608                 {
5609                   if ((meth = (lookup_method_in_protocol_list
5610                                (CLASS_PROTOCOL_LIST (category), ident, 0))))
5611                     return meth;
5612                 }
5613
5614               if ((category = CLASS_CATEGORY_LIST (category)))
5615                 chain = CLASS_NST_METHODS (category);
5616             }
5617           while (category);
5618         }
5619
5620       if (CLASS_PROTOCOL_LIST (inter))
5621         {
5622           if ((meth = (lookup_method_in_protocol_list
5623                        (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5624             return meth;
5625         }
5626
5627       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5628         chain = CLASS_NST_METHODS (inter);
5629     }
5630   while (inter);
5631
5632   return meth;
5633 }
5634
5635 static tree
5636 lookup_class_method_static (interface, ident)
5637      tree interface;
5638      tree ident;
5639 {
5640   tree inter = interface;
5641   tree chain = CLASS_CLS_METHODS (inter);
5642   tree meth = NULL_TREE;
5643   tree root_inter = NULL_TREE;
5644
5645   do
5646     {
5647       if ((meth = lookup_method (chain, ident)))
5648         return meth;
5649
5650       if (CLASS_CATEGORY_LIST (inter))
5651         {
5652           tree category = CLASS_CATEGORY_LIST (inter);
5653           chain = CLASS_CLS_METHODS (category);
5654
5655           do
5656             {
5657               if ((meth = lookup_method (chain, ident)))
5658                 return meth;
5659
5660               /* Check for class methods in protocols in categories.  */
5661               if (CLASS_PROTOCOL_LIST (category))
5662                 {
5663                   if ((meth = (lookup_method_in_protocol_list
5664                                (CLASS_PROTOCOL_LIST (category), ident, 1))))
5665                     return meth;
5666                 }
5667
5668               if ((category = CLASS_CATEGORY_LIST (category)))
5669                 chain = CLASS_CLS_METHODS (category);
5670             }
5671           while (category);
5672         }
5673
5674       /* Check for class methods in protocols.  */
5675       if (CLASS_PROTOCOL_LIST (inter))
5676         {
5677           if ((meth = (lookup_method_in_protocol_list
5678                        (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5679             return meth;
5680         }
5681
5682       root_inter = inter;
5683       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5684         chain = CLASS_CLS_METHODS (inter);
5685     }
5686   while (inter);
5687
5688   /* If no class (factory) method was found, check if an _instance_
5689      method of the same name exists in the root class.  This is what
5690      the Objective-C runtime will do.  */
5691   return lookup_instance_method_static (root_inter, ident);
5692 }
5693
5694 tree
5695 add_class_method (class, method)
5696      tree class;
5697      tree method;
5698 {
5699   tree mth;
5700   hash hsh;
5701
5702   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5703     {
5704       /* put method on list in reverse order */
5705       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5706       CLASS_CLS_METHODS (class) = method;
5707     }
5708   else
5709     {
5710       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5711         error ("duplicate definition of class method `%s'",
5712                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5713       else
5714         {
5715           /* Check types; if different, complain.  */
5716           if (!comp_proto_with_proto (method, mth))
5717             error ("duplicate declaration of class method `%s'",
5718                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5719         }
5720     }
5721
5722   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5723     {
5724       /* Install on a global chain.  */
5725       hash_enter (cls_method_hash_list, method);
5726     }
5727   else
5728     {
5729       /* Check types; if different, add to a list.  */
5730       if (!comp_proto_with_proto (method, hsh->key))
5731         hash_add_attr (hsh, method);
5732     }
5733   return method;
5734 }
5735 \f
5736 tree
5737 add_instance_method (class, method)
5738      tree class;
5739      tree method;
5740 {
5741   tree mth;
5742   hash hsh;
5743
5744   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5745     {
5746       /* Put method on list in reverse order.  */
5747       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5748       CLASS_NST_METHODS (class) = method;
5749     }
5750   else
5751     {
5752       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5753         error ("duplicate definition of instance method `%s'",
5754                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5755       else
5756         {
5757           /* Check types; if different, complain.  */
5758           if (!comp_proto_with_proto (method, mth))
5759             error ("duplicate declaration of instance method `%s'",
5760                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5761         }
5762     }
5763
5764   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5765     {
5766       /* Install on a global chain.  */
5767       hash_enter (nst_method_hash_list, method);
5768     }
5769   else
5770     {
5771       /* Check types; if different, add to a list.  */
5772       if (!comp_proto_with_proto (method, hsh->key))
5773         hash_add_attr (hsh, method);
5774     }
5775   return method;
5776 }
5777
5778 static tree
5779 add_class (class)
5780      tree class;
5781 {
5782   /* Put interfaces on list in reverse order.  */
5783   TREE_CHAIN (class) = interface_chain;
5784   interface_chain = class;
5785   return interface_chain;
5786 }
5787
5788 static void
5789 add_category (class, category)
5790       tree class;
5791       tree category;
5792 {
5793   /* Put categories on list in reverse order.  */
5794   tree cat = CLASS_CATEGORY_LIST (class);
5795
5796   while (cat)
5797     {
5798       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5799         warning ("duplicate interface declaration for category `%s(%s)'",
5800                  IDENTIFIER_POINTER (CLASS_NAME (class)),
5801                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5802       cat = CLASS_CATEGORY_LIST (cat);
5803     }
5804
5805   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5806   CLASS_CATEGORY_LIST (class) = category;
5807 }
5808
5809 /* Called after parsing each instance variable declaration. Necessary to
5810    preserve typedefs and implement public/private...
5811
5812    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
5813
5814 tree
5815 add_instance_variable (class, public, declarator, declspecs, width)
5816      tree class;
5817      int public;
5818      tree declarator;
5819      tree declspecs;
5820      tree width;
5821 {
5822   tree field_decl, raw_decl;
5823
5824   raw_decl = build_tree_list (declspecs, declarator);
5825
5826   if (CLASS_RAW_IVARS (class))
5827     chainon (CLASS_RAW_IVARS (class), raw_decl);
5828   else
5829     CLASS_RAW_IVARS (class) = raw_decl;
5830
5831   field_decl = grokfield (input_filename, lineno,
5832                           declarator, declspecs, width);
5833
5834   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
5835   switch (public)
5836     {
5837     case 0:
5838       TREE_PUBLIC (field_decl) = 0;
5839       TREE_PRIVATE (field_decl) = 0;
5840       TREE_PROTECTED (field_decl) = 1;
5841       break;
5842
5843     case 1:
5844       TREE_PUBLIC (field_decl) = 1;
5845       TREE_PRIVATE (field_decl) = 0;
5846       TREE_PROTECTED (field_decl) = 0;
5847       break;
5848
5849     case 2:
5850       TREE_PUBLIC (field_decl) = 0;
5851       TREE_PRIVATE (field_decl) = 1;
5852       TREE_PROTECTED (field_decl) = 0;
5853       break;
5854
5855     }
5856
5857   if (CLASS_IVARS (class))
5858     chainon (CLASS_IVARS (class), field_decl);
5859   else
5860     CLASS_IVARS (class) = field_decl;
5861
5862   return class;
5863 }
5864 \f
5865 tree
5866 is_ivar (decl_chain, ident)
5867      tree decl_chain;
5868      tree ident;
5869 {
5870   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5871     if (DECL_NAME (decl_chain) == ident)
5872       return decl_chain;
5873   return NULL_TREE;
5874 }
5875
5876 /* True if the ivar is private and we are not in its implementation.  */
5877
5878 int
5879 is_private (decl)
5880      tree decl;
5881 {
5882   if (TREE_PRIVATE (decl)
5883       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5884     {
5885       error ("instance variable `%s' is declared private",
5886              IDENTIFIER_POINTER (DECL_NAME (decl)));
5887       return 1;
5888     }
5889   else
5890     return 0;
5891 }
5892
5893 /* We have an instance variable reference;, check to see if it is public.  */
5894
5895 int
5896 is_public (expr, identifier)
5897      tree expr;
5898      tree identifier;
5899 {
5900   tree basetype = TREE_TYPE (expr);
5901   enum tree_code code = TREE_CODE (basetype);
5902   tree decl;
5903
5904   if (code == RECORD_TYPE)
5905     {
5906       if (TREE_STATIC_TEMPLATE (basetype))
5907         {
5908           if (!lookup_interface (TYPE_NAME (basetype)))
5909             {
5910               error ("cannot find interface declaration for `%s'",
5911                      IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5912               return 0;
5913             }
5914
5915           if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5916             {
5917               if (TREE_PUBLIC (decl))
5918                 return 1;
5919
5920               /* Important difference between the Stepstone translator:
5921                  all instance variables should be public within the context
5922                  of the implementation.  */
5923               if (objc_implementation_context
5924                   && (((TREE_CODE (objc_implementation_context)
5925                         == CLASS_IMPLEMENTATION_TYPE)
5926                        || (TREE_CODE (objc_implementation_context)
5927                            == CATEGORY_IMPLEMENTATION_TYPE))
5928                       && (CLASS_NAME (objc_implementation_context)
5929                           == TYPE_NAME (basetype))))
5930                 return ! is_private (decl);
5931
5932               error ("instance variable `%s' is declared %s",
5933                      IDENTIFIER_POINTER (identifier),
5934                      TREE_PRIVATE (decl) ? "private" : "protected");
5935               return 0;
5936             }
5937         }
5938
5939       else if (objc_implementation_context && (basetype == objc_object_reference))
5940         {
5941           TREE_TYPE (expr) = uprivate_record;
5942           warning ("static access to object of type `id'");
5943         }
5944     }
5945
5946   return 1;
5947 }
5948 \f
5949 /* Make sure all entries in CHAIN are also in LIST.  */
5950
5951 static int
5952 check_methods (chain, list, mtype)
5953      tree chain;
5954      tree list;
5955      int mtype;
5956 {
5957   int first = 1;
5958
5959   while (chain)
5960     {
5961       if (!lookup_method (list, chain))
5962         {
5963           if (first)
5964             {
5965               if (TREE_CODE (objc_implementation_context)
5966                   == CLASS_IMPLEMENTATION_TYPE)
5967                 warning ("incomplete implementation of class `%s'",
5968                          IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
5969               else if (TREE_CODE (objc_implementation_context)
5970                        == CATEGORY_IMPLEMENTATION_TYPE)
5971                 warning ("incomplete implementation of category `%s'",
5972                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
5973               first = 0;
5974             }
5975
5976           warning ("method definition for `%c%s' not found",
5977                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5978         }
5979
5980       chain = TREE_CHAIN (chain);
5981     }
5982
5983     return first;
5984 }
5985
5986 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
5987
5988 static int
5989 conforms_to_protocol (class, protocol)
5990      tree class;
5991      tree protocol;
5992 {
5993    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
5994      {
5995        tree p = CLASS_PROTOCOL_LIST (class);
5996        while (p && TREE_VALUE (p) != protocol)
5997          p = TREE_CHAIN (p);
5998
5999        if (!p)
6000          {
6001            tree super = (CLASS_SUPER_NAME (class)
6002                          ? lookup_interface (CLASS_SUPER_NAME (class))
6003                          : NULL_TREE);
6004            int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6005            if (!tmp)
6006              return 0;
6007          }
6008      }
6009
6010    return 1;
6011 }
6012
6013 /* Make sure all methods in CHAIN are accessible as MTYPE methods in 
6014    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
6015
6016 static int
6017 check_methods_accessible (chain, context, mtype)
6018      tree chain;
6019      tree context;
6020      int mtype;
6021 {
6022   int first = 1;
6023   tree list;
6024   tree base_context = context;
6025
6026   while (chain)
6027     {
6028       context = base_context;
6029       while (context)
6030         {
6031           if (mtype == '+')
6032             list = CLASS_CLS_METHODS (context);
6033           else
6034             list = CLASS_NST_METHODS (context);
6035
6036           if (lookup_method (list, chain))
6037               break; 
6038
6039           else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6040                    || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6041             context = (CLASS_SUPER_NAME (context) 
6042                        ? lookup_interface (CLASS_SUPER_NAME (context))
6043                        : NULL_TREE);
6044
6045           else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6046                    || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6047             context = (CLASS_NAME (context) 
6048                        ? lookup_interface (CLASS_NAME (context))
6049                        : NULL_TREE);
6050           else
6051             abort ();
6052         }
6053
6054       if (context == NULL_TREE)
6055         {
6056           if (first)
6057             {
6058               if (TREE_CODE (objc_implementation_context)
6059                   == CLASS_IMPLEMENTATION_TYPE)
6060                 warning ("incomplete implementation of class `%s'",
6061                          IDENTIFIER_POINTER
6062                            (CLASS_NAME (objc_implementation_context)));
6063               else if (TREE_CODE (objc_implementation_context)
6064                        == CATEGORY_IMPLEMENTATION_TYPE)
6065                 warning ("incomplete implementation of category `%s'",
6066                          IDENTIFIER_POINTER
6067                            (CLASS_SUPER_NAME (objc_implementation_context)));
6068               first = 0;
6069             }
6070           warning ("method definition for `%c%s' not found",
6071                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6072         }
6073
6074       chain = TREE_CHAIN (chain); /* next method...  */
6075     }
6076   return first;
6077 }
6078
6079 /* Check whether the current interface (accessible via
6080    'objc_implementation_context') actually implements protocol P, along
6081    with any protocols that P inherits.  */
6082    
6083 static void
6084 check_protocol (p, type, name)
6085      tree p;
6086      const char *type;
6087      const char *name;
6088 {
6089   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6090     {
6091       int f1, f2;
6092
6093       /* Ensure that all protocols have bodies!  */
6094       if (warn_protocol)
6095         {
6096           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6097                               CLASS_CLS_METHODS (objc_implementation_context),
6098                               '+');
6099           f2 = check_methods (PROTOCOL_NST_METHODS (p),
6100                               CLASS_NST_METHODS (objc_implementation_context),
6101                               '-');
6102         }
6103       else
6104         {
6105           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6106                                          objc_implementation_context,
6107                                          '+');
6108           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6109                                          objc_implementation_context,
6110                                          '-');
6111         }
6112
6113       if (!f1 || !f2)
6114         warning ("%s `%s' does not fully implement the `%s' protocol",
6115                  type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6116     }
6117     
6118   /* Check protocols recursively.  */
6119   if (PROTOCOL_LIST (p))
6120     {
6121       tree subs = PROTOCOL_LIST (p);
6122       tree super_class =
6123         lookup_interface (CLASS_SUPER_NAME (implementation_template));
6124
6125       while (subs) 
6126         {
6127           tree sub = TREE_VALUE (subs);
6128
6129           /* If the superclass does not conform to the protocols
6130              inherited by P, then we must!  */
6131           if (!super_class || !conforms_to_protocol (super_class, sub))
6132             check_protocol (sub, type, name);
6133           subs = TREE_CHAIN (subs);
6134         }
6135     }
6136 }
6137         
6138 /* Check whether the current interface (accessible via
6139    'objc_implementation_context') actually implements the protocols listed
6140    in PROTO_LIST.  */
6141    
6142 static void
6143 check_protocols (proto_list, type, name)
6144      tree proto_list;
6145      const char *type;
6146      const char *name;
6147 {
6148   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6149     {
6150       tree p = TREE_VALUE (proto_list);
6151
6152       check_protocol (p, type, name);
6153     }
6154 }
6155 \f
6156 /* Make sure that the class CLASS_NAME is defined
6157    CODE says which kind of thing CLASS_NAME ought to be.
6158    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6159    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
6160
6161 tree
6162 start_class (code, class_name, super_name, protocol_list)
6163      enum tree_code code;
6164      tree class_name;
6165      tree super_name;
6166      tree protocol_list;
6167 {
6168   tree class, decl;
6169
6170   if (objc_implementation_context)
6171     {
6172       warning ("`@end' missing in implementation context");
6173       finish_class (objc_implementation_context);
6174       objc_ivar_chain = NULL_TREE;
6175       objc_implementation_context = NULL_TREE;
6176     }
6177
6178   class = make_node (code);
6179   TYPE_BINFO (class) = make_tree_vec (BINFO_ELTS);
6180
6181   CLASS_NAME (class) = class_name;
6182   CLASS_SUPER_NAME (class) = super_name;
6183   CLASS_CLS_METHODS (class) = NULL_TREE;
6184
6185   if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6186     {
6187       error ("`%s' redeclared as different kind of symbol",
6188              IDENTIFIER_POINTER (class_name));
6189       error_with_decl (decl, "previous declaration of `%s'");
6190     }
6191
6192   if (code == CLASS_IMPLEMENTATION_TYPE)
6193     {
6194       {
6195         tree chain;
6196
6197         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6198            if (TREE_VALUE (chain) == class_name)
6199              {
6200                error ("reimplementation of class `%s'",
6201                       IDENTIFIER_POINTER (class_name));
6202                return error_mark_node;
6203              }
6204         implemented_classes = tree_cons (NULL_TREE, class_name,
6205                                          implemented_classes);
6206       }
6207
6208       /* Pre-build the following entities - for speed/convenience.  */
6209       if (!self_id)
6210           self_id = get_identifier ("self");
6211       if (!ucmd_id)
6212         ucmd_id = get_identifier ("_cmd");
6213       if (!unused_list)
6214         unused_list
6215           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6216       if (!objc_super_template)
6217         objc_super_template = build_super_template ();
6218
6219       /* Reset for multiple classes per file.  */
6220       method_slot = 0;
6221
6222       objc_implementation_context = class;
6223
6224       /* Lookup the interface for this implementation.  */
6225
6226       if (!(implementation_template = lookup_interface (class_name)))
6227         {
6228           warning ("cannot find interface declaration for `%s'",
6229                    IDENTIFIER_POINTER (class_name));
6230           add_class (implementation_template = objc_implementation_context);
6231         }
6232
6233       /* If a super class has been specified in the implementation,
6234          insure it conforms to the one specified in the interface.  */
6235
6236       if (super_name
6237           && (super_name != CLASS_SUPER_NAME (implementation_template)))
6238         {
6239           tree previous_name = CLASS_SUPER_NAME (implementation_template);
6240           const char *const name =
6241             previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6242           error ("conflicting super class name `%s'",
6243                  IDENTIFIER_POINTER (super_name));
6244           error ("previous declaration of `%s'", name);
6245         }
6246
6247       else if (! super_name)
6248         {
6249           CLASS_SUPER_NAME (objc_implementation_context) 
6250             = CLASS_SUPER_NAME (implementation_template);
6251         }
6252     }
6253
6254   else if (code == CLASS_INTERFACE_TYPE)
6255     {
6256       if (lookup_interface (class_name))
6257         warning ("duplicate interface declaration for class `%s'",
6258                  IDENTIFIER_POINTER (class_name));
6259       else
6260         add_class (class);
6261
6262       if (protocol_list)
6263         CLASS_PROTOCOL_LIST (class)
6264           = lookup_and_install_protocols (protocol_list);
6265     }
6266
6267   else if (code == CATEGORY_INTERFACE_TYPE)
6268     {
6269       tree class_category_is_assoc_with;
6270
6271       /* For a category, class_name is really the name of the class that
6272          the following set of methods will be associated with. We must
6273          find the interface so that can derive the objects template.  */
6274
6275       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6276         {
6277           error ("cannot find interface declaration for `%s'",
6278                  IDENTIFIER_POINTER (class_name));
6279           exit (FATAL_EXIT_CODE);
6280         }
6281       else
6282         add_category (class_category_is_assoc_with, class);
6283
6284       if (protocol_list)
6285         CLASS_PROTOCOL_LIST (class)
6286           = lookup_and_install_protocols (protocol_list);
6287     }
6288
6289   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6290     {
6291       /* Pre-build the following entities for speed/convenience.  */
6292       if (!self_id)
6293         self_id = get_identifier ("self");
6294       if (!ucmd_id)
6295         ucmd_id = get_identifier ("_cmd");
6296       if (!unused_list)
6297         unused_list
6298           = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6299       if (!objc_super_template)
6300         objc_super_template = build_super_template ();
6301
6302       /* Reset for multiple classes per file.  */
6303       method_slot = 0;
6304
6305       objc_implementation_context = class;
6306
6307       /* For a category, class_name is really the name of the class that
6308          the following set of methods will be associated with.  We must
6309          find the interface so that can derive the objects template.  */
6310
6311       if (!(implementation_template = lookup_interface (class_name)))
6312         {
6313           error ("cannot find interface declaration for `%s'",
6314                  IDENTIFIER_POINTER (class_name));
6315           exit (FATAL_EXIT_CODE);
6316         }
6317     }
6318   return class;
6319 }
6320
6321 tree
6322 continue_class (class)
6323      tree class;
6324 {
6325   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6326       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6327     {
6328       struct imp_entry *imp_entry;
6329       tree ivar_context;
6330
6331       /* Check consistency of the instance variables.  */
6332
6333       if (CLASS_IVARS (class))
6334         check_ivars (implementation_template, class);
6335
6336       /* code generation */
6337
6338       ivar_context = build_private_template (implementation_template);
6339
6340       if (!objc_class_template)
6341         build_class_template ();
6342
6343       imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6344
6345       imp_entry->next = imp_list;
6346       imp_entry->imp_context = class;
6347       imp_entry->imp_template = implementation_template;
6348
6349       synth_forward_declarations ();
6350       imp_entry->class_decl = UOBJC_CLASS_decl;
6351       imp_entry->meta_decl = UOBJC_METACLASS_decl;
6352
6353       /* Append to front and increment count.  */
6354       imp_list = imp_entry;
6355       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6356         imp_count++;
6357       else
6358         cat_count++;
6359
6360       return ivar_context;
6361     }
6362
6363   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6364     {
6365       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6366
6367       if (!TYPE_FIELDS (record))
6368         {
6369           finish_struct (record, get_class_ivars (class), NULL_TREE);
6370           CLASS_STATIC_TEMPLATE (class) = record;
6371
6372           /* Mark this record as a class template for static typing.  */
6373           TREE_STATIC_TEMPLATE (record) = 1;
6374         }
6375
6376       return NULL_TREE;
6377     }
6378
6379   else
6380     return error_mark_node;
6381 }
6382
6383 /* This is called once we see the "@end" in an interface/implementation.  */
6384
6385 void
6386 finish_class (class)
6387      tree class;
6388 {
6389   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6390     {
6391       /* All code generation is done in finish_objc.  */
6392
6393       if (implementation_template != objc_implementation_context)
6394         {
6395           /* Ensure that all method listed in the interface contain bodies.  */
6396           check_methods (CLASS_CLS_METHODS (implementation_template),
6397                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6398           check_methods (CLASS_NST_METHODS (implementation_template),
6399                          CLASS_NST_METHODS (objc_implementation_context), '-');
6400
6401           if (CLASS_PROTOCOL_LIST (implementation_template))
6402             check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6403                              "class",
6404                              IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6405         }
6406     }
6407
6408   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6409     {
6410       tree category = CLASS_CATEGORY_LIST (implementation_template);
6411
6412       /* Find the category interface from the class it is associated with.  */
6413       while (category)
6414         {
6415           if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6416             break;
6417           category = CLASS_CATEGORY_LIST (category);
6418         }
6419
6420       if (category)
6421         {
6422           /* Ensure all method listed in the interface contain bodies.  */
6423           check_methods (CLASS_CLS_METHODS (category),
6424                          CLASS_CLS_METHODS (objc_implementation_context), '+');
6425           check_methods (CLASS_NST_METHODS (category),
6426                          CLASS_NST_METHODS (objc_implementation_context), '-');
6427
6428           if (CLASS_PROTOCOL_LIST (category))
6429             check_protocols (CLASS_PROTOCOL_LIST (category),
6430                              "category",
6431                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6432         }
6433     }
6434
6435   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6436     {
6437       tree decl_specs;
6438       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6439       char *string = (char *) alloca (strlen (class_name) + 3);
6440
6441       /* extern struct objc_object *_<my_name>; */
6442
6443       sprintf (string, "_%s", class_name);
6444
6445       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6446       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6447       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6448                    decl_specs);
6449     }
6450 }
6451
6452 static tree
6453 add_protocol (protocol)
6454      tree protocol;
6455 {
6456   /* Put protocol on list in reverse order.  */
6457   TREE_CHAIN (protocol) = protocol_chain;
6458   protocol_chain = protocol;
6459   return protocol_chain;
6460 }
6461
6462 static tree
6463 lookup_protocol (ident)
6464      tree ident;
6465 {
6466   tree chain;
6467
6468   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6469     if (ident == PROTOCOL_NAME (chain))
6470       return chain;
6471
6472   return NULL_TREE;
6473 }
6474
6475 /* This function forward declares the protocols named by NAMES.  If
6476    they are already declared or defined, the function has no effect.  */
6477
6478 void
6479 objc_declare_protocols (names)
6480      tree names;
6481 {
6482   tree list;
6483
6484   for (list = names; list; list = TREE_CHAIN (list))
6485     {
6486       tree name = TREE_VALUE (list);
6487
6488       if (lookup_protocol (name) == NULL_TREE)
6489         {
6490           tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6491
6492           TYPE_BINFO (protocol) = make_tree_vec (2);
6493           PROTOCOL_NAME (protocol) = name;
6494           PROTOCOL_LIST (protocol) = NULL_TREE;
6495           add_protocol (protocol);
6496           PROTOCOL_DEFINED (protocol) = 0;
6497           PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6498         }
6499     }
6500 }
6501
6502 tree
6503 start_protocol (code, name, list)
6504      enum tree_code code;
6505      tree name;
6506      tree list;
6507 {
6508   tree protocol;
6509
6510   /* This is as good a place as any.  Need to invoke
6511      push_tag_toplevel.  */
6512   if (!objc_protocol_template)
6513     objc_protocol_template = build_protocol_template ();
6514
6515   protocol = lookup_protocol (name);
6516
6517   if (!protocol)
6518     {
6519       protocol = make_node (code);
6520       TYPE_BINFO (protocol) = make_tree_vec (2);
6521
6522       PROTOCOL_NAME (protocol) = name;
6523       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6524       add_protocol (protocol);
6525       PROTOCOL_DEFINED (protocol) = 1;
6526       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6527
6528       check_protocol_recursively (protocol, list);
6529     }
6530   else if (! PROTOCOL_DEFINED (protocol))
6531     {
6532       PROTOCOL_DEFINED (protocol) = 1;
6533       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6534
6535       check_protocol_recursively (protocol, list);
6536     }
6537   else
6538     {
6539       warning ("duplicate declaration for protocol `%s'",
6540                IDENTIFIER_POINTER (name));
6541     }
6542   return protocol;
6543 }
6544
6545 void
6546 finish_protocol (protocol)
6547      tree protocol ATTRIBUTE_UNUSED;
6548 {
6549 }
6550
6551 \f
6552 /* "Encode" a data type into a string, which grows in util_obstack.
6553    ??? What is the FORMAT?  Someone please document this!  */
6554
6555 static void
6556 encode_type_qualifiers (declspecs)
6557      tree declspecs;
6558 {
6559   tree spec;
6560
6561   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6562     {
6563       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6564         obstack_1grow (&util_obstack, 'r');
6565       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6566         obstack_1grow (&util_obstack, 'n');
6567       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6568         obstack_1grow (&util_obstack, 'N');
6569       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6570         obstack_1grow (&util_obstack, 'o');
6571       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6572         obstack_1grow (&util_obstack, 'O');
6573       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6574         obstack_1grow (&util_obstack, 'R');
6575       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6576         obstack_1grow (&util_obstack, 'V');
6577     }
6578 }
6579
6580 /* Encode a pointer type.  */
6581
6582 static void
6583 encode_pointer (type, curtype, format)
6584      tree type;
6585      int curtype;
6586      int format;
6587 {
6588   tree pointer_to = TREE_TYPE (type);
6589
6590   if (TREE_CODE (pointer_to) == RECORD_TYPE)
6591     {
6592       if (TYPE_NAME (pointer_to)
6593           && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6594         {
6595           const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6596
6597           if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6598             {
6599               obstack_1grow (&util_obstack, '@');
6600               return;
6601             }
6602           else if (TREE_STATIC_TEMPLATE (pointer_to))
6603             {
6604               if (generating_instance_variables)
6605                 {
6606                   obstack_1grow (&util_obstack, '@');
6607                   obstack_1grow (&util_obstack, '"');
6608                   obstack_grow (&util_obstack, name, strlen (name));
6609                   obstack_1grow (&util_obstack, '"');
6610                   return;
6611                 }
6612               else
6613                 {
6614                   obstack_1grow (&util_obstack, '@');
6615                   return;
6616                 }
6617             }
6618           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6619             {
6620               obstack_1grow (&util_obstack, '#');
6621               return;
6622             }
6623           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6624             {
6625               obstack_1grow (&util_obstack, ':');
6626               return;
6627             }
6628         }
6629     }
6630   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6631            && TYPE_MODE (pointer_to) == QImode)
6632     {
6633       obstack_1grow (&util_obstack, '*');
6634       return;
6635     }
6636
6637   /* We have a type that does not get special treatment.  */
6638
6639   /* NeXT extension */
6640   obstack_1grow (&util_obstack, '^');
6641   encode_type (pointer_to, curtype, format);
6642 }
6643
6644 static void
6645 encode_array (type, curtype, format)
6646      tree type;
6647      int curtype;
6648      int format;
6649 {
6650   tree an_int_cst = TYPE_SIZE (type);
6651   tree array_of = TREE_TYPE (type);
6652   char buffer[40];
6653
6654   /* An incomplete array is treated like a pointer.  */
6655   if (an_int_cst == NULL)
6656     {
6657       encode_pointer (type, curtype, format);
6658       return;
6659     }
6660
6661   sprintf (buffer, "[%ld",
6662            (long) (TREE_INT_CST_LOW (an_int_cst)
6663                    / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6664
6665   obstack_grow (&util_obstack, buffer, strlen (buffer));
6666   encode_type (array_of, curtype, format);
6667   obstack_1grow (&util_obstack, ']');
6668   return;
6669 }
6670 \f
6671 static void
6672 encode_aggregate_within (type, curtype, format, left, right)
6673      tree type;
6674      int curtype;
6675      int format;
6676      int left;
6677      int right;
6678 {
6679   /* The RECORD_TYPE may in fact be a typedef!  For purposes
6680      of encoding, we need the real underlying enchilada.  */
6681   if (TYPE_MAIN_VARIANT (type))
6682     type = TYPE_MAIN_VARIANT (type);
6683
6684   if (obstack_object_size (&util_obstack) > 0
6685       && *(obstack_next_free (&util_obstack) - 1) == '^')
6686     {
6687       tree name = TYPE_NAME (type);
6688
6689       /* we have a reference; this is a NeXT extension.  */
6690
6691       if (obstack_object_size (&util_obstack) - curtype == 1
6692           && format == OBJC_ENCODE_INLINE_DEFS)
6693         {
6694           /* Output format of struct for first level only.  */
6695           tree fields = TYPE_FIELDS (type);
6696
6697           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6698             {
6699               obstack_1grow (&util_obstack, left);
6700               obstack_grow (&util_obstack,
6701                             IDENTIFIER_POINTER (name),
6702                             strlen (IDENTIFIER_POINTER (name)));
6703               obstack_1grow (&util_obstack, '=');
6704             }
6705           else
6706             {
6707               obstack_1grow (&util_obstack, left);
6708               obstack_grow (&util_obstack, "?=", 2);
6709             }
6710
6711           for ( ; fields; fields = TREE_CHAIN (fields))
6712               encode_field_decl (fields, curtype, format);
6713
6714           obstack_1grow (&util_obstack, right);
6715         }
6716
6717       else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6718         {
6719           obstack_1grow (&util_obstack, left);
6720           obstack_grow (&util_obstack,
6721                         IDENTIFIER_POINTER (name),
6722                         strlen (IDENTIFIER_POINTER (name)));
6723           obstack_1grow (&util_obstack, right);
6724         }
6725
6726       else
6727         {
6728           /* We have an untagged structure or a typedef.  */
6729           obstack_1grow (&util_obstack, left);
6730           obstack_1grow (&util_obstack, '?');
6731           obstack_1grow (&util_obstack, right);
6732         }
6733     }
6734
6735   else
6736     {
6737       tree name = TYPE_NAME (type);
6738       tree fields = TYPE_FIELDS (type);
6739
6740       if (format == OBJC_ENCODE_INLINE_DEFS
6741           || generating_instance_variables)
6742         {
6743           obstack_1grow (&util_obstack, left);
6744           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6745               obstack_grow (&util_obstack,
6746                           IDENTIFIER_POINTER (name),
6747                           strlen (IDENTIFIER_POINTER (name)));
6748           else
6749               obstack_1grow (&util_obstack, '?');
6750
6751           obstack_1grow (&util_obstack, '=');
6752
6753           for (; fields; fields = TREE_CHAIN (fields))
6754             {
6755               if (generating_instance_variables)
6756                 {
6757                   tree fname = DECL_NAME (fields);
6758
6759                   obstack_1grow (&util_obstack, '"');
6760                   if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6761                     {
6762                       obstack_grow (&util_obstack,
6763                                     IDENTIFIER_POINTER (fname),
6764                                     strlen (IDENTIFIER_POINTER (fname)));
6765                     }
6766
6767                   obstack_1grow (&util_obstack, '"');
6768                 }
6769
6770               encode_field_decl (fields, curtype, format);
6771             }
6772
6773           obstack_1grow (&util_obstack, right);
6774         }
6775
6776       else
6777         {
6778           obstack_1grow (&util_obstack, left);
6779           if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6780               obstack_grow (&util_obstack,
6781                             IDENTIFIER_POINTER (name),
6782                             strlen (IDENTIFIER_POINTER (name)));
6783           else
6784               /* We have an untagged structure or a typedef.  */
6785               obstack_1grow (&util_obstack, '?');
6786
6787           obstack_1grow (&util_obstack, right);
6788         }
6789     }
6790 }
6791
6792 static void
6793 encode_aggregate (type, curtype, format)
6794      tree type;
6795      int curtype;
6796      int format;
6797 {
6798   enum tree_code code = TREE_CODE (type);
6799
6800   switch (code)
6801     {
6802     case RECORD_TYPE:
6803       {
6804         encode_aggregate_within(type, curtype, format, '{', '}');
6805         break;
6806       }
6807     case UNION_TYPE:
6808       {
6809         encode_aggregate_within(type, curtype, format, '(', ')');
6810         break;
6811       }
6812
6813     case ENUMERAL_TYPE:
6814       obstack_1grow (&util_obstack, 'i');
6815       break;
6816
6817     default:
6818       break;
6819     }
6820 }
6821
6822 /* Support bitfields.  The current version of Objective-C does not support
6823    them.  The string will consist of one or more "b:n"'s where n is an
6824    integer describing the width of the bitfield. Currently, classes in
6825    the kit implement a method "-(char *)describeBitfieldStruct:" that
6826    simulates this. If they do not implement this method, the archiver
6827    assumes the bitfield is 16 bits wide (padded if necessary) and packed
6828    according to the GNU compiler. After looking at the "kit", it appears
6829    that all classes currently rely on this default behavior, rather than
6830    hand generating this string (which is tedious).  */
6831
6832 static void
6833 encode_bitfield (width)
6834      int width;
6835 {
6836   char buffer[40];
6837   sprintf (buffer, "b%d", width);
6838   obstack_grow (&util_obstack, buffer, strlen (buffer));
6839 }
6840 \f
6841 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
6842
6843 static void
6844 encode_type (type, curtype, format)
6845      tree type;
6846      int curtype;
6847      int format;
6848 {
6849   enum tree_code code = TREE_CODE (type);
6850
6851   if (code == INTEGER_TYPE)
6852     {
6853       if (integer_zerop (TYPE_MIN_VALUE (type)))
6854         {
6855           /* Unsigned integer types.  */
6856
6857           if (TYPE_MODE (type) == QImode)
6858             obstack_1grow (&util_obstack, 'C');
6859           else if (TYPE_MODE (type) == HImode)
6860             obstack_1grow (&util_obstack, 'S');
6861           else if (TYPE_MODE (type) == SImode)
6862             {
6863               if (type == long_unsigned_type_node)
6864                 obstack_1grow (&util_obstack, 'L');
6865               else
6866                 obstack_1grow (&util_obstack, 'I');
6867             }
6868           else if (TYPE_MODE (type) == DImode)
6869             obstack_1grow (&util_obstack, 'Q');
6870         }
6871
6872       else
6873         /* Signed integer types.  */
6874         {
6875           if (TYPE_MODE (type) == QImode)
6876             obstack_1grow (&util_obstack, 'c');
6877           else if (TYPE_MODE (type) == HImode)
6878             obstack_1grow (&util_obstack, 's');
6879           else if (TYPE_MODE (type) == SImode)
6880             {
6881               if (type == long_integer_type_node)
6882                 obstack_1grow (&util_obstack, 'l');
6883               else
6884                 obstack_1grow (&util_obstack, 'i');
6885             }
6886
6887           else if (TYPE_MODE (type) == DImode)
6888             obstack_1grow (&util_obstack, 'q');
6889         }
6890     }
6891
6892   else if (code == REAL_TYPE)
6893     {
6894       /* Floating point types.  */
6895
6896       if (TYPE_MODE (type) == SFmode)
6897         obstack_1grow (&util_obstack, 'f');
6898       else if (TYPE_MODE (type) == DFmode
6899                || TYPE_MODE (type) == TFmode)
6900         obstack_1grow (&util_obstack, 'd');
6901     }
6902
6903   else if (code == VOID_TYPE)
6904     obstack_1grow (&util_obstack, 'v');
6905
6906   else if (code == ARRAY_TYPE)
6907     encode_array (type, curtype, format);
6908
6909   else if (code == POINTER_TYPE)
6910     encode_pointer (type, curtype, format);
6911
6912   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6913     encode_aggregate (type, curtype, format);
6914
6915   else if (code == FUNCTION_TYPE) /* '?' */
6916     obstack_1grow (&util_obstack, '?');
6917 }
6918
6919 static void
6920 encode_complete_bitfield (position, type, size)
6921      int position;
6922      tree type;
6923      int size;
6924 {
6925   enum tree_code code = TREE_CODE (type);
6926   char buffer[40];
6927   char charType = '?';
6928
6929   if (code == INTEGER_TYPE)
6930     {
6931       if (integer_zerop (TYPE_MIN_VALUE (type)))
6932         {
6933           /* Unsigned integer types.  */
6934
6935           if (TYPE_MODE (type) == QImode)
6936             charType = 'C';
6937           else if (TYPE_MODE (type) == HImode)
6938             charType = 'S';
6939           else if (TYPE_MODE (type) == SImode)
6940             {
6941               if (type == long_unsigned_type_node)
6942                 charType = 'L';
6943               else
6944                 charType = 'I';
6945             }
6946           else if (TYPE_MODE (type) == DImode)
6947             charType = 'Q';
6948         }
6949
6950       else
6951         /* Signed integer types.  */
6952         {
6953           if (TYPE_MODE (type) == QImode)
6954             charType = 'c';
6955           else if (TYPE_MODE (type) == HImode)
6956             charType = 's';
6957           else if (TYPE_MODE (type) == SImode)
6958             {
6959               if (type == long_integer_type_node)
6960                 charType = 'l';
6961               else
6962                 charType = 'i';
6963             }
6964
6965           else if (TYPE_MODE (type) == DImode)
6966             charType = 'q';
6967         }
6968     }
6969   else if (code == ENUMERAL_TYPE)
6970     charType = 'i';
6971   else
6972     abort ();
6973
6974   sprintf (buffer, "b%d%c%d", position, charType, size);
6975   obstack_grow (&util_obstack, buffer, strlen (buffer));
6976 }
6977
6978 static void
6979 encode_field_decl (field_decl, curtype, format)
6980      tree field_decl;
6981      int curtype;
6982      int format;
6983 {
6984   tree type;
6985
6986   type = TREE_TYPE (field_decl);
6987
6988   /* If this field is obviously a bitfield, or is a bitfield that has been
6989      clobbered to look like a ordinary integer mode, go ahead and generate
6990      the bitfield typing information.  */
6991   if (flag_next_runtime)
6992     {
6993       if (DECL_BIT_FIELD_TYPE (field_decl))
6994         encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6995       else
6996         encode_type (TREE_TYPE (field_decl), curtype, format);
6997     }
6998   else
6999     {
7000       if (DECL_BIT_FIELD_TYPE (field_decl))
7001         encode_complete_bitfield (int_bit_position (field_decl),
7002                                   DECL_BIT_FIELD_TYPE (field_decl),
7003                                   tree_low_cst (DECL_SIZE (field_decl), 1));
7004       else
7005         encode_type (TREE_TYPE (field_decl), curtype, format);
7006     }
7007 }
7008
7009 static tree
7010 expr_last (complex_expr)
7011      tree complex_expr;
7012 {
7013   tree next;
7014
7015   if (complex_expr)
7016     while ((next = TREE_OPERAND (complex_expr, 0)))
7017       complex_expr = next;
7018
7019   return complex_expr;
7020 }
7021 \f
7022 /* Transform a method definition into a function definition as follows:
7023    - synthesize the first two arguments, "self" and "_cmd".  */
7024
7025 void
7026 start_method_def (method)
7027      tree method;
7028 {
7029   tree decl_specs;
7030
7031   /* Required to implement _msgSuper.  */
7032   objc_method_context = method;
7033   UOBJC_SUPER_decl = NULL_TREE;
7034
7035   /* Must be called BEFORE start_function.  */
7036   pushlevel (0);
7037
7038   /* Generate prototype declarations for arguments..."new-style".  */
7039
7040   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7041     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7042   else
7043     /* Really a `struct objc_class *'. However, we allow people to
7044        assign to self, which changes its type midstream.  */
7045     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7046
7047   push_parm_decl (build_tree_list
7048                   (build_tree_list (decl_specs,
7049                                     build1 (INDIRECT_REF, NULL_TREE, self_id)),
7050                    unused_list));
7051
7052   decl_specs = build_tree_list (NULL_TREE,
7053                                 xref_tag (RECORD_TYPE,
7054                                           get_identifier (TAG_SELECTOR)));
7055   push_parm_decl (build_tree_list
7056                   (build_tree_list (decl_specs,
7057                                     build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7058                    unused_list));
7059
7060   /* Generate argument declarations if a keyword_decl.  */
7061   if (METHOD_SEL_ARGS (method))
7062     {
7063       tree arglist = METHOD_SEL_ARGS (method);
7064       do
7065         {
7066           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7067           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7068
7069           if (arg_decl)
7070             {
7071               tree last_expr = expr_last (arg_decl);
7072
7073               /* Unite the abstract decl with its name.  */
7074               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7075               push_parm_decl (build_tree_list
7076                               (build_tree_list (arg_spec, arg_decl),
7077                                NULL_TREE));
7078
7079               /* Unhook: restore the abstract declarator.  */
7080               TREE_OPERAND (last_expr, 0) = NULL_TREE;
7081             }
7082
7083           else
7084             push_parm_decl (build_tree_list
7085                             (build_tree_list (arg_spec,
7086                                               KEYWORD_ARG_NAME (arglist)),
7087                              NULL_TREE));
7088
7089           arglist = TREE_CHAIN (arglist);
7090         }
7091       while (arglist);
7092     }
7093
7094   if (METHOD_ADD_ARGS (method) != NULL_TREE
7095       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7096     {
7097       /* We have a variable length selector - in "prototype" format.  */
7098       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7099       while (akey)
7100         {
7101           /* This must be done prior to calling pushdecl.  pushdecl is
7102              going to change our chain on us.  */
7103           tree nextkey = TREE_CHAIN (akey);
7104           pushdecl (akey);
7105           akey = nextkey;
7106         }
7107     }
7108 }
7109
7110 static void
7111 warn_with_method (message, mtype, method)
7112      const char *message;
7113      int mtype;
7114      tree method;
7115 {
7116   if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
7117     return;
7118
7119   diagnostic_report_current_function (global_dc);
7120
7121   /* Add a readable method name to the warning.  */
7122   warning_with_file_and_line (DECL_SOURCE_FILE (method),
7123                               DECL_SOURCE_LINE (method),
7124                               "%s `%c%s'",
7125                               message, mtype,
7126                               gen_method_decl (method, errbuf));
7127 }
7128
7129 /* Return 1 if METHOD is consistent with PROTO.  */
7130
7131 static int
7132 comp_method_with_proto (method, proto)
7133      tree method, proto;
7134 {
7135   /* Create a function template node at most once.  */
7136   if (!function1_template)
7137     function1_template = make_node (FUNCTION_TYPE);
7138
7139   /* Install argument types - normally set by build_function_type.  */
7140   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7141
7142   /* install return type */
7143   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7144
7145   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
7146 }
7147
7148 /* Return 1 if PROTO1 is consistent with PROTO2.  */
7149
7150 static int
7151 comp_proto_with_proto (proto0, proto1)
7152      tree proto0, proto1;
7153 {
7154   /* Create a couple of function_template nodes at most once.  */
7155   if (!function1_template)
7156     function1_template = make_node (FUNCTION_TYPE);
7157   if (!function2_template)
7158     function2_template = make_node (FUNCTION_TYPE);
7159
7160   /* Install argument types; normally set by build_function_type.  */
7161   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
7162   TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
7163
7164   /* Install return type.  */
7165   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
7166   TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
7167
7168   return comptypes (function1_template, function2_template);
7169 }
7170
7171 /* - Generate an identifier for the function. the format is "_n_cls",
7172      where 1 <= n <= nMethods, and cls is the name the implementation we
7173      are processing.
7174    - Install the return type from the method declaration.
7175    - If we have a prototype, check for type consistency.  */
7176
7177 static void
7178 really_start_method (method, parmlist)
7179      tree method, parmlist;
7180 {
7181   tree sc_spec, ret_spec, ret_decl, decl_specs;
7182   tree method_decl, method_id;
7183   const char *sel_name, *class_name, *cat_name;
7184   char *buf;
7185
7186   /* Synth the storage class & assemble the return type.  */
7187   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7188   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7189   decl_specs = chainon (sc_spec, ret_spec);
7190
7191   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7192   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7193   cat_name = ((TREE_CODE (objc_implementation_context)
7194                == CLASS_IMPLEMENTATION_TYPE)
7195               ? NULL
7196               : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7197   method_slot++;
7198
7199   /* Make sure this is big enough for any plausible method label.  */
7200   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7201                          + (cat_name ? strlen (cat_name) : 0));
7202
7203   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7204                          class_name, cat_name, sel_name, method_slot);
7205
7206   method_id = get_identifier (buf);
7207
7208   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7209
7210   /* Check the declarator portion of the return type for the method.  */
7211   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7212     {
7213       /* Unite the complex decl (specified in the abstract decl) with the
7214          function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
7215       tree save_expr = expr_last (ret_decl);
7216
7217       TREE_OPERAND (save_expr, 0) = method_decl;
7218       method_decl = ret_decl;
7219
7220       /* Fool the parser into thinking it is starting a function.  */
7221       start_function (decl_specs, method_decl, NULL_TREE);
7222
7223       /* Unhook: this has the effect of restoring the abstract declarator.  */
7224       TREE_OPERAND (save_expr, 0) = NULL_TREE;
7225     }
7226
7227   else
7228     {
7229       TREE_VALUE (TREE_TYPE (method)) = method_decl;
7230
7231       /* Fool the parser into thinking it is starting a function.  */
7232       start_function (decl_specs, method_decl, NULL_TREE);
7233
7234       /* Unhook: this has the effect of restoring the abstract declarator.  */
7235       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7236     }
7237
7238   METHOD_DEFINITION (method) = current_function_decl;
7239
7240   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
7241
7242   if (implementation_template != objc_implementation_context)
7243     {
7244       tree proto;
7245
7246       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7247         proto = lookup_instance_method_static (implementation_template,
7248                                                METHOD_SEL_NAME (method));
7249       else
7250         proto = lookup_class_method_static (implementation_template,
7251                                             METHOD_SEL_NAME (method));
7252
7253       if (proto && ! comp_method_with_proto (method, proto))
7254         {
7255           char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7256
7257           warn_with_method ("conflicting types for", type, method);
7258           warn_with_method ("previous declaration of", type, proto);
7259         }
7260     }
7261 }
7262
7263 /* The following routine is always called...this "architecture" is to
7264    accommodate "old-style" variable length selectors.
7265  
7266    - a:a b:b // prototype  ; id c; id d; // old-style.  */
7267
7268 void
7269 continue_method_def ()
7270 {
7271   tree parmlist;
7272
7273   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7274     /* We have a `, ...' immediately following the selector.  */
7275     parmlist = get_parm_info (0);
7276   else
7277     parmlist = get_parm_info (1); /* place a `void_at_end' */
7278
7279   /* Set self_decl from the first argument...this global is used by
7280      build_ivar_reference calling build_indirect_ref.  */
7281   self_decl = TREE_PURPOSE (parmlist);
7282
7283   poplevel (0, 0, 0);
7284   really_start_method (objc_method_context, parmlist);
7285   store_parm_decls ();
7286 }
7287
7288 /* Called by the parser, from the `pushlevel' production.  */
7289
7290 void
7291 add_objc_decls ()
7292 {
7293   if (!UOBJC_SUPER_decl)
7294     {
7295       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7296                                      build_tree_list (NULL_TREE,
7297                                                       objc_super_template),
7298                                      0, NULL_TREE);
7299
7300       finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7301
7302       /* This prevents `unused variable' warnings when compiling with -Wall.  */
7303       TREE_USED (UOBJC_SUPER_decl) = 1;
7304       DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7305     }
7306 }
7307
7308 /* _n_Method (id self, SEL sel, ...)
7309      {
7310        struct objc_super _S;
7311        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7312      }  */
7313
7314 tree
7315 get_super_receiver ()
7316 {
7317   if (objc_method_context)
7318     {
7319       tree super_expr, super_expr_list;
7320
7321       /* Set receiver to self.  */
7322       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7323       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7324       super_expr_list = build_tree_list (NULL_TREE, super_expr);
7325
7326       /* Set class to begin searching.  */
7327       super_expr = build_component_ref (UOBJC_SUPER_decl,
7328                                         get_identifier ("class"));
7329
7330       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7331         {
7332           /* [_cls, __cls]Super are "pre-built" in
7333              synth_forward_declarations.  */
7334
7335           super_expr = build_modify_expr (super_expr, NOP_EXPR,
7336                                           ((TREE_CODE (objc_method_context)
7337                                             == INSTANCE_METHOD_DECL)
7338                                            ? ucls_super_ref
7339                                            : uucls_super_ref));
7340         }
7341
7342       else
7343         /* We have a category.  */
7344         {
7345           tree super_name = CLASS_SUPER_NAME (implementation_template);
7346           tree super_class;
7347
7348           /* Barf if super used in a category of Object.  */
7349           if (!super_name)
7350             {
7351               error ("no super class declared in interface for `%s'",
7352                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7353               return error_mark_node;
7354             }
7355
7356           if (flag_next_runtime)
7357             {
7358               super_class = get_class_reference (super_name);
7359               if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7360                 /* Cast the super class to 'id', since the user may not have
7361                    included <objc/objc-class.h>, leaving 'struct objc_class'
7362                    an incomplete type.  */
7363                 super_class
7364                   = build_component_ref (build_indirect_ref 
7365                                          (build_c_cast (id_type, super_class), "->"),
7366                                           get_identifier ("isa"));
7367             }
7368           else
7369             {
7370               add_class_reference (super_name);
7371               super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7372                              ? objc_get_class_decl : objc_get_meta_class_decl);
7373               assemble_external (super_class);
7374               super_class
7375                 = build_function_call
7376                   (super_class,
7377                    build_tree_list
7378                    (NULL_TREE,
7379                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7380                                      IDENTIFIER_POINTER (super_name))));
7381             }
7382
7383           TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7384           super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7385         }
7386
7387       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7388
7389       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7390       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7391
7392       return build_compound_expr (super_expr_list);
7393     }
7394   else
7395     {
7396       error ("[super ...] must appear in a method context");
7397       return error_mark_node;
7398     }
7399 }
7400
7401 static tree
7402 encode_method_def (func_decl)
7403       tree func_decl;
7404 {
7405   tree parms;
7406   int stack_size;
7407   HOST_WIDE_INT max_parm_end = 0;
7408   char buffer[40];
7409   tree result;
7410
7411   /* Return type.  */
7412   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7413                obstack_object_size (&util_obstack),
7414                OBJC_ENCODE_INLINE_DEFS);
7415
7416   /* Stack size.  */
7417   for (parms = DECL_ARGUMENTS (func_decl); parms;
7418        parms = TREE_CHAIN (parms))
7419     {
7420       HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7421                                 + int_size_in_bytes (TREE_TYPE (parms)));
7422
7423       if (! offset_is_register && parm_end > max_parm_end)
7424         max_parm_end = parm_end;
7425     }
7426
7427   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7428
7429   sprintf (buffer, "%d", stack_size);
7430   obstack_grow (&util_obstack, buffer, strlen (buffer));
7431
7432   /* Argument types.  */
7433   for (parms = DECL_ARGUMENTS (func_decl); parms;
7434        parms = TREE_CHAIN (parms))
7435     {
7436       /* Type.  */
7437       encode_type (TREE_TYPE (parms),
7438                    obstack_object_size (&util_obstack),
7439                    OBJC_ENCODE_INLINE_DEFS);
7440
7441       /* Compute offset.  */
7442       sprintf (buffer, "%d", forwarding_offset (parms));
7443
7444       /* Indicate register.  */
7445       if (offset_is_register)
7446         obstack_1grow (&util_obstack, '+');
7447
7448       obstack_grow (&util_obstack, buffer, strlen (buffer));
7449     }
7450
7451   /* Null terminate string.  */
7452   obstack_1grow (&util_obstack, 0);
7453   result = get_identifier (obstack_finish (&util_obstack));
7454   obstack_free (&util_obstack, util_firstobj);
7455   return result;
7456 }
7457
7458 static void
7459 objc_expand_function_end ()
7460 {
7461   METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
7462 }
7463
7464 void
7465 finish_method_def ()
7466 {
7467   lang_expand_function_end = objc_expand_function_end;
7468   finish_function (0, 1);
7469   lang_expand_function_end = NULL;
7470
7471   /* Required to implement _msgSuper. This must be done AFTER finish_function,
7472      since the optimizer may find "may be used before set" errors.  */
7473   objc_method_context = NULL_TREE;
7474 }
7475
7476 #if 0
7477 int
7478 lang_report_error_function (decl)
7479       tree decl;
7480 {
7481   if (objc_method_context)
7482     {
7483       fprintf (stderr, "In method `%s'\n",
7484                IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7485       return 1;
7486     }
7487
7488   else
7489     return 0;
7490 }
7491 #endif
7492
7493 static int
7494 is_complex_decl (type)
7495      tree type;
7496 {
7497   return (TREE_CODE (type) == ARRAY_TYPE
7498           || TREE_CODE (type) == FUNCTION_TYPE
7499           || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7500 }
7501
7502 \f
7503 /* Code to convert a decl node into text for a declaration in C.  */
7504
7505 static char tmpbuf[256];
7506
7507 static void
7508 adorn_decl (decl, str)
7509      tree decl;
7510      char *str;
7511 {
7512   enum tree_code code = TREE_CODE (decl);
7513
7514   if (code == ARRAY_REF)
7515     {
7516       tree an_int_cst = TREE_OPERAND (decl, 1);
7517
7518       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7519         sprintf (str + strlen (str), "[%ld]",
7520                  (long) TREE_INT_CST_LOW (an_int_cst));
7521       else
7522         strcat (str, "[]");
7523     }
7524
7525   else if (code == ARRAY_TYPE)
7526     {
7527       tree an_int_cst = TYPE_SIZE (decl);
7528       tree array_of = TREE_TYPE (decl);
7529
7530       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7531         sprintf (str + strlen (str), "[%ld]",
7532                  (long) (TREE_INT_CST_LOW (an_int_cst)
7533                          / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7534       else
7535         strcat (str, "[]");
7536     }
7537
7538   else if (code == CALL_EXPR)
7539     {
7540       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7541
7542       strcat (str, "(");
7543       while (chain)
7544         {
7545           gen_declaration_1 (chain, str);
7546           chain = TREE_CHAIN (chain);
7547           if (chain)
7548             strcat (str, ", ");
7549         }
7550       strcat (str, ")");
7551     }
7552
7553   else if (code == FUNCTION_TYPE)
7554     {
7555       tree chain  = TYPE_ARG_TYPES (decl);
7556
7557       strcat (str, "(");
7558       while (chain && TREE_VALUE (chain) != void_type_node)
7559         {
7560           gen_declaration_1 (TREE_VALUE (chain), str);
7561           chain = TREE_CHAIN (chain);
7562           if (chain && TREE_VALUE (chain) != void_type_node)
7563             strcat (str, ", ");
7564         }
7565       strcat (str, ")");
7566     }
7567
7568   else if (code == INDIRECT_REF)
7569     {
7570       strcpy (tmpbuf, "*");
7571       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7572         {
7573           tree chain;
7574
7575           for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7576                chain;
7577                chain = TREE_CHAIN (chain))
7578             {
7579               if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7580                 {
7581                   strcat (tmpbuf, " ");
7582                   strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7583                 }
7584             }
7585           if (str[0])
7586             strcat (tmpbuf, " ");
7587         }
7588       strcat (tmpbuf, str);
7589       strcpy (str, tmpbuf);
7590     }
7591
7592   else if (code == POINTER_TYPE)
7593     {
7594       strcpy (tmpbuf, "*");
7595       if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7596         {
7597           if (TREE_READONLY (decl))
7598             strcat (tmpbuf, " const");
7599           if (TYPE_VOLATILE (decl))
7600             strcat (tmpbuf, " volatile");
7601           if (str[0])
7602             strcat (tmpbuf, " ");
7603         }
7604       strcat (tmpbuf, str);
7605       strcpy (str, tmpbuf);
7606     }
7607 }
7608
7609 static char *
7610 gen_declarator (decl, buf, name)
7611      tree decl;
7612      char *buf;
7613      const char *name;
7614 {
7615   if (decl)
7616     {
7617       enum tree_code code = TREE_CODE (decl);
7618       char *str;
7619       tree op;
7620       int wrap = 0;
7621
7622       switch (code)
7623         {
7624         case ARRAY_REF:
7625         case INDIRECT_REF:
7626         case CALL_EXPR:
7627           op = TREE_OPERAND (decl, 0);
7628
7629           /* We have a pointer to a function or array...(*)(), (*)[] */
7630           if ((code == ARRAY_REF || code == CALL_EXPR)
7631               && op && TREE_CODE (op) == INDIRECT_REF)
7632             wrap = 1;
7633
7634           str = gen_declarator (op, buf, name);
7635
7636           if (wrap)
7637             {
7638               strcpy (tmpbuf, "(");
7639               strcat (tmpbuf, str);
7640               strcat (tmpbuf, ")");
7641               strcpy (str, tmpbuf);
7642             }
7643
7644           adorn_decl (decl, str);
7645           break;
7646
7647         case ARRAY_TYPE:
7648         case FUNCTION_TYPE:
7649         case POINTER_TYPE:
7650           strcpy (buf, name);
7651           str = buf;
7652
7653           /* This clause is done iteratively rather than recursively.  */
7654           do
7655             {
7656               op = (is_complex_decl (TREE_TYPE (decl))
7657                     ? TREE_TYPE (decl) : NULL_TREE);
7658
7659               adorn_decl (decl, str);
7660
7661               /* We have a pointer to a function or array...(*)(), (*)[] */
7662               if (code == POINTER_TYPE
7663                   && op && (TREE_CODE (op) == FUNCTION_TYPE
7664                             || TREE_CODE (op) == ARRAY_TYPE))
7665                 {
7666                   strcpy (tmpbuf, "(");
7667                   strcat (tmpbuf, str);
7668                   strcat (tmpbuf, ")");
7669                   strcpy (str, tmpbuf);
7670                 }
7671
7672               decl = (is_complex_decl (TREE_TYPE (decl))
7673                       ? TREE_TYPE (decl) : NULL_TREE);
7674             }
7675
7676           while (decl && (code = TREE_CODE (decl)))
7677             ;
7678
7679           break;
7680
7681         case IDENTIFIER_NODE:
7682           /* Will only happen if we are processing a "raw" expr-decl.  */
7683           strcpy (buf, IDENTIFIER_POINTER (decl));
7684           return buf;
7685
7686         default:
7687           abort ();
7688         }
7689
7690       return str;
7691     }
7692
7693   else
7694     /* We have an abstract declarator or a _DECL node.  */
7695     {
7696       strcpy (buf, name);
7697       return buf;
7698     }
7699 }
7700
7701 static void
7702 gen_declspecs (declspecs, buf, raw)
7703      tree declspecs;
7704      char *buf;
7705      int raw;
7706 {
7707   if (raw)
7708     {
7709       tree chain;
7710
7711       for (chain = nreverse (copy_list (declspecs));
7712            chain; chain = TREE_CHAIN (chain))
7713         {
7714           tree aspec = TREE_VALUE (chain);
7715
7716           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7717             strcat (buf, IDENTIFIER_POINTER (aspec));
7718           else if (TREE_CODE (aspec) == RECORD_TYPE)
7719             {
7720               if (TYPE_NAME (aspec))
7721                 {
7722                   tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7723
7724                   if (! TREE_STATIC_TEMPLATE (aspec))
7725                     strcat (buf, "struct ");
7726                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7727
7728                   /* NEW!!! */
7729                   if (protocol_list)
7730                     {
7731                       tree chain = protocol_list;
7732
7733                       strcat (buf, " <");
7734                       while (chain)
7735                         {
7736                           strcat (buf,
7737                                   IDENTIFIER_POINTER
7738                                   (PROTOCOL_NAME (TREE_VALUE (chain))));
7739                           chain = TREE_CHAIN (chain);
7740                           if (chain)
7741                             strcat (buf, ", ");
7742                         }
7743                       strcat (buf, ">");
7744                     }
7745                 }
7746
7747               else
7748                 strcat (buf, "untagged struct");
7749             }
7750
7751           else if (TREE_CODE (aspec) == UNION_TYPE)
7752             {
7753               if (TYPE_NAME (aspec))
7754                 {
7755                   if (! TREE_STATIC_TEMPLATE (aspec))
7756                     strcat (buf, "union ");
7757                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7758                 }
7759               else
7760                 strcat (buf, "untagged union");
7761             }
7762
7763           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7764             {
7765               if (TYPE_NAME (aspec))
7766                 {
7767                   if (! TREE_STATIC_TEMPLATE (aspec))
7768                     strcat (buf, "enum ");
7769                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7770                 }
7771               else
7772                 strcat (buf, "untagged enum");
7773             }
7774
7775           else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7776             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7777
7778           else if (IS_ID (aspec))
7779             {
7780               tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7781
7782               strcat (buf, "id");
7783               if (protocol_list)
7784                 {
7785                   tree chain = protocol_list;
7786
7787                   strcat (buf, " <");
7788                   while (chain)
7789                     {
7790                       strcat (buf,
7791                               IDENTIFIER_POINTER
7792                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7793                       chain = TREE_CHAIN (chain);
7794                       if (chain)
7795                         strcat (buf, ", ");
7796                     }
7797                   strcat (buf, ">");
7798                 }
7799             }
7800           if (TREE_CHAIN (chain))
7801             strcat (buf, " ");
7802         }
7803     }
7804   else
7805     {
7806       /* Type qualifiers.  */
7807       if (TREE_READONLY (declspecs))
7808         strcat (buf, "const ");
7809       if (TYPE_VOLATILE (declspecs))
7810         strcat (buf, "volatile ");
7811
7812       switch (TREE_CODE (declspecs))
7813         {
7814           /* Type specifiers.  */
7815
7816         case INTEGER_TYPE:
7817           declspecs = TYPE_MAIN_VARIANT (declspecs);
7818
7819           /* Signed integer types.  */
7820
7821           if (declspecs == short_integer_type_node)
7822             strcat (buf, "short int ");
7823           else if (declspecs == integer_type_node)
7824             strcat (buf, "int ");
7825           else if (declspecs == long_integer_type_node)
7826             strcat (buf, "long int ");
7827           else if (declspecs == long_long_integer_type_node)
7828             strcat (buf, "long long int ");
7829           else if (declspecs == signed_char_type_node
7830                    || declspecs == char_type_node)
7831             strcat (buf, "char ");
7832
7833           /* Unsigned integer types.  */
7834
7835           else if (declspecs == short_unsigned_type_node)
7836             strcat (buf, "unsigned short ");
7837           else if (declspecs == unsigned_type_node)
7838             strcat (buf, "unsigned int ");
7839           else if (declspecs == long_unsigned_type_node)
7840             strcat (buf, "unsigned long ");
7841           else if (declspecs == long_long_unsigned_type_node)
7842             strcat (buf, "unsigned long long ");
7843           else if (declspecs == unsigned_char_type_node)
7844             strcat (buf, "unsigned char ");
7845           break;
7846
7847         case REAL_TYPE:
7848           declspecs = TYPE_MAIN_VARIANT (declspecs);
7849
7850           if (declspecs == float_type_node)
7851             strcat (buf, "float ");
7852           else if (declspecs == double_type_node)
7853             strcat (buf, "double ");
7854           else if (declspecs == long_double_type_node)
7855             strcat (buf, "long double ");
7856           break;
7857
7858         case RECORD_TYPE:
7859           if (TYPE_NAME (declspecs)
7860               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7861             {
7862               tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7863
7864               if (! TREE_STATIC_TEMPLATE (declspecs))
7865                 strcat (buf, "struct ");
7866               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7867
7868               if (protocol_list)
7869                 {
7870                   tree chain = protocol_list;
7871
7872                   strcat (buf, " <");
7873                   while (chain)
7874                     {
7875                       strcat (buf,
7876                               IDENTIFIER_POINTER
7877                               (PROTOCOL_NAME (TREE_VALUE (chain))));
7878                       chain = TREE_CHAIN (chain);
7879                       if (chain)
7880                         strcat (buf, ", ");
7881                     }
7882                   strcat (buf, ">");
7883                 }
7884             }
7885
7886           else
7887             strcat (buf, "untagged struct");
7888
7889           strcat (buf, " ");
7890           break;
7891
7892         case UNION_TYPE:
7893           if (TYPE_NAME (declspecs)
7894               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7895             {
7896               strcat (buf, "union ");
7897               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7898               strcat (buf, " ");
7899             }
7900
7901           else
7902             strcat (buf, "untagged union ");
7903           break;
7904
7905         case ENUMERAL_TYPE:
7906           if (TYPE_NAME (declspecs)
7907               && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7908             {
7909               strcat (buf, "enum ");
7910               strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7911               strcat (buf, " ");
7912             }
7913
7914           else
7915             strcat (buf, "untagged enum ");
7916           break;
7917
7918         case VOID_TYPE:
7919           strcat (buf, "void ");
7920           break;
7921
7922         case POINTER_TYPE:
7923           {
7924             tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7925
7926             strcat (buf, "id");
7927             if (protocol_list)
7928               {
7929                 tree chain = protocol_list;
7930
7931                 strcat (buf, " <");
7932                 while (chain)
7933                   {
7934                     strcat (buf,
7935                             IDENTIFIER_POINTER
7936                             (PROTOCOL_NAME (TREE_VALUE (chain))));
7937                     chain = TREE_CHAIN (chain);
7938                     if (chain)
7939                       strcat (buf, ", ");
7940                   }
7941
7942                 strcat (buf, ">");
7943               }
7944           }
7945           break;
7946           
7947         default:
7948           break;
7949         }
7950     }
7951 }
7952
7953 /* Given a tree node, produce a printable description of it in the given
7954    buffer, overwriting the buffer.  */
7955
7956 static char *
7957 gen_declaration (atype_or_adecl, buf)
7958      tree atype_or_adecl;
7959      char *buf;
7960 {
7961   buf[0] = '\0';
7962   gen_declaration_1 (atype_or_adecl, buf);
7963   return buf;
7964 }
7965
7966 /* Given a tree node, append a printable description to the end of the
7967    given buffer.  */
7968
7969 static void
7970 gen_declaration_1 (atype_or_adecl, buf)
7971      tree atype_or_adecl;
7972      char *buf;
7973 {
7974   char declbuf[256];
7975
7976   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7977     {
7978       tree declspecs;   /* "identifier_node", "record_type" */
7979       tree declarator;  /* "array_ref", "indirect_ref", "call_expr"...  */
7980
7981       /* We have a "raw", abstract declarator (typename).  */
7982       declarator = TREE_VALUE (atype_or_adecl);
7983       declspecs  = TREE_PURPOSE (atype_or_adecl);
7984
7985       gen_declspecs (declspecs, buf, 1);
7986       if (declarator)
7987         {
7988           strcat (buf, " ");
7989           strcat (buf, gen_declarator (declarator, declbuf, ""));
7990         }
7991     }
7992
7993   else
7994     {
7995       tree atype;
7996       tree declspecs;   /* "integer_type", "real_type", "record_type"...  */
7997       tree declarator;  /* "array_type", "function_type", "pointer_type".  */
7998
7999       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8000           || TREE_CODE (atype_or_adecl) == PARM_DECL
8001           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8002         atype = TREE_TYPE (atype_or_adecl);
8003       else
8004         /* Assume we have a *_type node.  */
8005         atype = atype_or_adecl;
8006
8007       if (is_complex_decl (atype))
8008         {
8009           tree chain;
8010
8011           /* Get the declaration specifier; it is at the end of the list.  */
8012           declarator = chain = atype;
8013           do
8014             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8015           while (is_complex_decl (chain));
8016           declspecs = chain;
8017         }
8018
8019       else
8020         {
8021           declspecs = atype;
8022           declarator = NULL_TREE;
8023         }
8024
8025       gen_declspecs (declspecs, buf, 0);
8026
8027       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8028           || TREE_CODE (atype_or_adecl) == PARM_DECL
8029           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8030         {
8031           const char *const decl_name =
8032             (DECL_NAME (atype_or_adecl)
8033              ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8034
8035           if (declarator)
8036             {
8037               strcat (buf, " ");
8038               strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8039             }
8040
8041           else if (decl_name[0])
8042             {
8043               strcat (buf, " ");
8044               strcat (buf, decl_name);
8045             }
8046         }
8047       else if (declarator)
8048         {
8049           strcat (buf, " ");
8050           strcat (buf, gen_declarator (declarator, declbuf, ""));
8051         }
8052     }
8053 }
8054
8055 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8056
8057 /* Given a method tree, put a printable description into the given
8058    buffer (overwriting) and return a pointer to the buffer.  */
8059
8060 static char *
8061 gen_method_decl (method, buf)
8062      tree method;
8063      char *buf;
8064 {
8065   tree chain;
8066
8067   buf[0] = '\0';
8068   if (RAW_TYPESPEC (method) != objc_object_reference)
8069     {
8070       strcat (buf, "(");
8071       gen_declaration_1 (TREE_TYPE (method), buf);
8072       strcat (buf, ")");
8073     }
8074
8075   chain = METHOD_SEL_ARGS (method);
8076   if (chain)
8077     {
8078       /* We have a chain of keyword_decls.  */
8079       do
8080         {
8081           if (KEYWORD_KEY_NAME (chain))
8082             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8083
8084           strcat (buf, ":");
8085           if (RAW_TYPESPEC (chain) != objc_object_reference)
8086             {
8087               strcat (buf, "(");
8088               gen_declaration_1 (TREE_TYPE (chain), buf);
8089               strcat (buf, ")");
8090             }
8091
8092           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8093           if ((chain = TREE_CHAIN (chain)))
8094             strcat (buf, " ");
8095         }
8096       while (chain);
8097
8098       if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8099         strcat (buf, ", ...");
8100       else if (METHOD_ADD_ARGS (method))
8101         {
8102           /* We have a tree list node as generate by get_parm_info.  */
8103           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8104
8105           /* Know we have a chain of parm_decls.  */
8106           while (chain)
8107             {
8108               strcat (buf, ", ");
8109               gen_declaration_1 (chain, buf);
8110               chain = TREE_CHAIN (chain);
8111             }
8112         }
8113     }
8114
8115   else
8116     /* We have a unary selector.  */
8117     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8118
8119   return buf;
8120 }
8121 \f
8122 /* Debug info.  */
8123
8124
8125 /* Dump an @interface declaration of the supplied class CHAIN to the
8126    supplied file FP.  Used to implement the -gen-decls option (which
8127    prints out an @interface declaration of all classes compiled in
8128    this run); potentially useful for debugging the compiler too.  */
8129 static void
8130 dump_interface (fp, chain)
8131      FILE *fp;
8132      tree chain;
8133 {
8134   /* FIXME: A heap overflow here whenever a method (or ivar)
8135      declaration is so long that it doesn't fit in the buffer.  The
8136      code and all the related functions should be rewritten to avoid
8137      using fixed size buffers.  */
8138   char *buf = (char *) xmalloc (1024 * 10);
8139   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8140   tree ivar_decls = CLASS_RAW_IVARS (chain);
8141   tree nst_methods = CLASS_NST_METHODS (chain);
8142   tree cls_methods = CLASS_CLS_METHODS (chain);
8143
8144   fprintf (fp, "\n@interface %s", my_name);
8145
8146   /* CLASS_SUPER_NAME is used to store the superclass name for 
8147      classes, and the category name for categories.  */
8148   if (CLASS_SUPER_NAME (chain))
8149     {
8150       const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8151       
8152       if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE 
8153           || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8154         {
8155           fprintf (fp, " (%s)\n", name);
8156         }
8157       else
8158         {
8159           fprintf (fp, " : %s\n", name);
8160         }
8161     }
8162   else
8163     fprintf (fp, "\n");
8164
8165   /* FIXME - the following doesn't seem to work at the moment.  */
8166   if (ivar_decls)
8167     {
8168       fprintf (fp, "{\n");
8169       do
8170         {
8171           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8172           ivar_decls = TREE_CHAIN (ivar_decls);
8173         }
8174       while (ivar_decls);
8175       fprintf (fp, "}\n");
8176     }
8177
8178   while (nst_methods)
8179     {
8180       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8181       nst_methods = TREE_CHAIN (nst_methods);
8182     }
8183
8184   while (cls_methods)
8185     {
8186       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8187       cls_methods = TREE_CHAIN (cls_methods);
8188     }
8189
8190   fprintf (fp, "@end\n");
8191 }
8192
8193 /* Demangle function for Objective-C */
8194 static const char *
8195 objc_demangle (mangled)
8196      const char *mangled;
8197 {
8198   char *demangled, *cp;
8199
8200   if (mangled[0] == '_' &&
8201       (mangled[1] == 'i' || mangled[1] == 'c') &&
8202       mangled[2] == '_')
8203     {
8204       cp = demangled = xmalloc(strlen(mangled) + 2);
8205       if (mangled[1] == 'i')
8206         *cp++ = '-';            /* for instance method */
8207       else
8208         *cp++ = '+';            /* for class method */
8209       *cp++ = '[';              /* opening left brace */
8210       strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
8211       while (*cp && *cp == '_')
8212         cp++;                   /* skip any initial underbars in class name */
8213       cp = strchr(cp, '_');     /* find first non-initial underbar */
8214       if (cp == NULL)
8215         {
8216           free(demangled);      /* not mangled name */
8217           return mangled;
8218         }
8219       if (cp[1] == '_')  /* easy case: no category name */
8220         {
8221           *cp++ = ' ';            /* replace two '_' with one ' ' */
8222           strcpy(cp, mangled + (cp - demangled) + 2);
8223         }
8224       else
8225         {
8226           *cp++ = '(';            /* less easy case: category name */
8227           cp = strchr(cp, '_');
8228           if (cp == 0)
8229             {
8230               free(demangled);    /* not mangled name */
8231               return mangled;
8232             }
8233           *cp++ = ')';
8234           *cp++ = ' ';            /* overwriting 1st char of method name... */
8235           strcpy(cp, mangled + (cp - demangled)); /* get it back */
8236         }
8237       while (*cp && *cp == '_')
8238         cp++;                   /* skip any initial underbars in method name */
8239       for (; *cp; cp++)
8240         if (*cp == '_')
8241           *cp = ':';            /* replace remaining '_' with ':' */
8242       *cp++ = ']';              /* closing right brace */
8243       *cp++ = 0;                /* string terminator */
8244       return demangled;
8245     }
8246   else
8247     return mangled;             /* not an objc mangled name */
8248 }
8249
8250 const char *
8251 objc_printable_name (decl, kind)
8252      tree decl;
8253      int kind ATTRIBUTE_UNUSED;
8254 {
8255   return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8256 }
8257
8258 static void
8259 init_objc ()
8260 {
8261   gcc_obstack_init (&util_obstack);
8262   util_firstobj = (char *) obstack_finish (&util_obstack);
8263
8264   errbuf = (char *) xmalloc (BUFSIZE);
8265   hash_init ();
8266   synth_module_prologue ();
8267 }
8268 \f
8269 static void
8270 finish_objc ()
8271 {
8272   struct imp_entry *impent;
8273   tree chain;
8274   /* The internally generated initializers appear to have missing braces.
8275      Don't warn about this.  */
8276   int save_warn_missing_braces = warn_missing_braces;
8277   warn_missing_braces = 0;
8278
8279   /* A missing @end may not be detected by the parser.  */
8280   if (objc_implementation_context)
8281     {
8282       warning ("`@end' missing in implementation context");
8283       finish_class (objc_implementation_context);
8284       objc_ivar_chain = NULL_TREE;
8285       objc_implementation_context = NULL_TREE;
8286     }
8287
8288   generate_forward_declaration_to_string_table ();
8289
8290 #ifdef OBJC_PROLOGUE
8291   OBJC_PROLOGUE;
8292 #endif
8293
8294   /* Process the static instances here because initialization of objc_symtab
8295      depends on them.  */
8296   if (objc_static_instances)
8297     generate_static_references ();
8298
8299   if (imp_list || class_names_chain
8300       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8301     generate_objc_symtab_decl ();
8302
8303   for (impent = imp_list; impent; impent = impent->next)
8304     {
8305       objc_implementation_context = impent->imp_context;
8306       implementation_template = impent->imp_template;
8307
8308       UOBJC_CLASS_decl = impent->class_decl;
8309       UOBJC_METACLASS_decl = impent->meta_decl;
8310       
8311       /* Dump the @interface of each class as we compile it, if the
8312          -gen-decls option is in use.  TODO: Dump the classes in the
8313          order they were found, rather than in reverse order as we
8314          are doing now.  */
8315       if (flag_gen_declaration)
8316         {
8317           dump_interface (gen_declaration_file, objc_implementation_context);
8318         }
8319       
8320       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8321         {
8322           /* all of the following reference the string pool...  */
8323           generate_ivar_lists ();
8324           generate_dispatch_tables ();
8325           generate_shared_structures ();
8326         }
8327       else
8328         {
8329           generate_dispatch_tables ();
8330           generate_category (objc_implementation_context);
8331         }
8332     }
8333
8334   /* If we are using an array of selectors, we must always
8335      finish up the array decl even if no selectors were used.  */
8336   if (! flag_next_runtime || sel_ref_chain)
8337     build_selector_translation_table ();
8338
8339   if (protocol_chain)
8340     generate_protocols ();
8341
8342   if (objc_implementation_context || class_names_chain || objc_static_instances
8343       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8344     {
8345       /* Arrange for ObjC data structures to be initialized at run time.  */
8346       rtx init_sym = build_module_descriptor ();
8347       if (init_sym && targetm.have_ctors_dtors)
8348         (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8349     }
8350
8351   /* Dump the class references.  This forces the appropriate classes
8352      to be linked into the executable image, preserving unix archive
8353      semantics.  This can be removed when we move to a more dynamically
8354      linked environment.  */
8355
8356   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8357     {
8358       handle_class_ref (chain);
8359       if (TREE_PURPOSE (chain))
8360         generate_classref_translation_entry (chain);
8361     }
8362
8363   for (impent = imp_list; impent; impent = impent->next)
8364     handle_impent (impent);
8365
8366   /* Dump the string table last.  */
8367
8368   generate_strings ();
8369
8370   if (warn_selector)
8371     {
8372       int slot;
8373       hash hsh;
8374
8375       /* Run through the selector hash tables and print a warning for any
8376          selector which has multiple methods.  */
8377
8378       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8379         for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8380           if (hsh->list)
8381             {
8382               tree meth = hsh->key;
8383               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8384                            ? '-' : '+');
8385               attr loop;
8386
8387               warning ("potential selector conflict for method `%s'",
8388                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8389               warn_with_method ("found", type, meth);
8390               for (loop = hsh->list; loop; loop = loop->next)
8391                 warn_with_method ("found", type, loop->value);
8392             }
8393
8394       for (slot = 0; slot < SIZEHASHTABLE; slot++)
8395         for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8396           if (hsh->list)
8397             {
8398               tree meth = hsh->key;
8399               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8400                            ? '-' : '+');
8401               attr loop;
8402
8403               warning ("potential selector conflict for method `%s'",
8404                        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8405               warn_with_method ("found", type, meth);
8406               for (loop = hsh->list; loop; loop = loop->next)
8407                 warn_with_method ("found", type, loop->value);
8408             }
8409     }
8410
8411   warn_missing_braces = save_warn_missing_braces;
8412 }
8413 \f
8414 /* Subroutines of finish_objc.  */
8415
8416 static void
8417 generate_classref_translation_entry (chain)
8418      tree chain;
8419 {
8420   tree expr, name, decl_specs, decl, sc_spec;
8421   tree type;
8422
8423   type = TREE_TYPE (TREE_PURPOSE (chain));
8424
8425   expr = add_objc_string (TREE_VALUE (chain), class_names);
8426   expr = build_c_cast (type, expr); /* cast! */
8427
8428   name = DECL_NAME (TREE_PURPOSE (chain));
8429
8430   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8431
8432   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8433   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8434
8435   /* The decl that is returned from start_decl is the one that we
8436      forward declared in build_class_reference.  */
8437   decl = start_decl (name, decl_specs, 1, NULL_TREE);
8438   DECL_CONTEXT (decl) = NULL_TREE;
8439   finish_decl (decl, expr, NULL_TREE);
8440   return;
8441 }
8442
8443 static void
8444 handle_class_ref (chain)
8445      tree chain;
8446 {
8447   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8448   char *string = (char *) alloca (strlen (name) + 30);
8449   tree decl;
8450   tree exp;
8451
8452   sprintf (string, "%sobjc_class_name_%s",
8453            (flag_next_runtime ? "." : "__"), name);
8454
8455 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8456   if (flag_next_runtime)
8457     {
8458       ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8459       return;
8460     }
8461 #endif
8462
8463   /* Make a decl for this name, so we can use its address in a tree.  */
8464   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8465   DECL_EXTERNAL (decl) = 1;
8466   TREE_PUBLIC (decl) = 1;
8467
8468   pushdecl (decl);
8469   rest_of_decl_compilation (decl, 0, 0, 0);
8470
8471   /* Make a decl for the address.  */
8472   sprintf (string, "%sobjc_class_ref_%s",
8473            (flag_next_runtime ? "." : "__"), name);
8474   exp = build1 (ADDR_EXPR, string_type_node, decl);
8475   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8476   DECL_INITIAL (decl) = exp;
8477   TREE_STATIC (decl) = 1;
8478   TREE_USED (decl) = 1;
8479
8480   pushdecl (decl);
8481   rest_of_decl_compilation (decl, 0, 0, 0);
8482 }
8483
8484 static void
8485 handle_impent (impent)
8486      struct imp_entry *impent;
8487 {
8488   char *string;
8489
8490   objc_implementation_context = impent->imp_context;
8491   implementation_template = impent->imp_template;
8492
8493   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8494     {
8495       const char *const class_name =
8496         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8497
8498       string = (char *) alloca (strlen (class_name) + 30);
8499
8500       sprintf (string, "%sobjc_class_name_%s",
8501                (flag_next_runtime ? "." : "__"), class_name);
8502     }
8503   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8504     {
8505       const char *const class_name =
8506         IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8507       const char *const class_super_name =
8508         IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8509
8510       string = (char *) alloca (strlen (class_name)
8511                                 + strlen (class_super_name) + 30);
8512
8513       /* Do the same for categories.  Even though no references to
8514          these symbols are generated automatically by the compiler, it
8515          gives you a handle to pull them into an archive by hand.  */
8516       sprintf (string, "*%sobjc_category_name_%s_%s",
8517                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8518     }
8519   else
8520     return;
8521
8522 #ifdef ASM_DECLARE_CLASS_REFERENCE
8523   if (flag_next_runtime)
8524     {
8525       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8526       return;
8527     }
8528   else
8529 #endif
8530     {
8531       tree decl, init;
8532
8533       init = build_int_2 (0, 0);
8534       TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
8535       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
8536       TREE_PUBLIC (decl) = 1;
8537       TREE_READONLY (decl) = 1;
8538       TREE_USED (decl) = 1;
8539       TREE_CONSTANT (decl) = 1;
8540       DECL_CONTEXT (decl) = 0;
8541       DECL_ARTIFICIAL (decl) = 1;
8542       DECL_INITIAL (decl) = init;
8543       assemble_variable (decl, 1, 0, 0);
8544     }
8545 }
8546 \f
8547 /* Look up ID as an instance variable.  */
8548 tree
8549 lookup_objc_ivar (id)
8550      tree id;
8551 {
8552   tree decl;
8553
8554   if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8555     /* We have a message to super.  */
8556     return get_super_receiver ();
8557   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8558     {
8559       if (is_private (decl))
8560         return error_mark_node;
8561       else
8562         return build_ivar_reference (id);
8563     }
8564   else
8565     return 0;
8566 }
8567
8568 #include "gt-objc-objc-act.h"
8569 #include "gtype-objc.h"