OSDN Git Service

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