OSDN Git Service

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