OSDN Git Service

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