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