OSDN Git Service

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