OSDN Git Service

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