OSDN Git Service

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