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