OSDN Git Service

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