OSDN Git Service

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