OSDN Git Service

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