OSDN Git Service

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