OSDN Git Service

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