OSDN Git Service

(init_module_descriptor):
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2    Copyright (C) 1992 Free Software Foundation, Inc.
3    Author: Steve Naroff.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22  *      Purpose: This module implements the Objective-C 4.0 language.
23  *
24  *      compatibility issues (with the Stepstone translator):
25  *
26  *      - does not recognize the following 3.3 constructs.
27  *        @requires, @classes, @messages, = (...)
28  *      - methods with variable arguments must conform to ANSI standard.
29  *      - tagged structure definitions that appear in BOTH the interface
30  *        and implementation are not allowed.
31  *      - public/private: all instance variables are public within the
32  *        context of the implementation...I consider this to be a bug in
33  *        the translator.
34  *      - statically allocated objects are not supported. the user will
35  *        receive an error if this service is requested.
36  *
37  *      code generation `options':
38  *
39  *      - OBJC_INT_SELECTORS, OBJC_SELECTORS_WITHOUT_LABELS, NEXT_OBJC_RUNTIME
40  */
41
42 #include <stdio.h>
43 #include "config.h"
44 #include "tree.h"
45 #include "c-tree.h"
46 #include "c-lex.h"
47 #include "flags.h"
48 #include "objc-actions.h"
49 #include "input.h"
50
51 /* The GNU run time requires the selectors in a vector
52    so it can store the operation numbers in them.  */
53 #ifndef NEXT_OBJC_RUNTIME
54 #define OBJC_SELECTORS_WITHOUT_LABELS
55 #endif
56 \f
57 /* Define the special tree codes that we use.  */
58
59 /* Table indexed by tree code giving a string containing a character
60    classifying the tree code.  Possibilities are
61    t, d, s, c, r, <, 1 and 2.  See objc-tree.def for details.  */
62
63 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
64
65 char *objc_tree_code_type[] = {
66   "x",
67 #include "objc-tree.def"
68 };
69 #undef DEFTREECODE
70
71 /* Table indexed by tree code giving number of expression
72    operands beyond the fixed part of the node structure.
73    Not used for types or decls.  */
74
75 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
76
77 int objc_tree_code_length[] = {
78   0,
79 #include "objc-tree.def"
80 };
81 #undef DEFTREECODE
82
83 /* Names of tree components.
84    Used for printing out the tree and error messages.  */
85 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
86
87 char *objc_tree_code_name[] = {
88   "@@dummy",
89 #include "objc-tree.def"
90 };
91 #undef DEFTREECODE
92 \f
93 /* Set up for use of obstacks.  */
94
95 #include "obstack.h"
96
97 #define obstack_chunk_alloc xmalloc
98 #define obstack_chunk_free free
99
100 /* This obstack is used to accumulate the encoding of a data type.  */
101 static struct obstack util_obstack;
102 /* This points to the beginning of obstack contents,
103    so we can free the whole contents.  */
104 char *util_firstobj;
105
106 /* for encode_method_def */
107 #include "rtl.h"
108
109 #define OBJC_VERSION    2
110
111 #define NULLT   (tree) 0
112
113 #define OBJC_ENCODE_INLINE_DEFS         0
114 #define OBJC_ENCODE_DONT_INLINE_DEFS    1
115
116 /*** Private Interface (procedures) ***/
117
118 /* code generation */
119
120 static void synth_module_prologue ();
121 static char *build_module_descriptor ();
122 static tree init_module_descriptor ();
123 static void build_module_entry ();
124 static tree build_objc_method_call ();
125 static void build_message_selector_pool ();
126 static void build_selector_translation_table ();
127 static tree build_ivar_chain ();
128
129 static tree build_ivar_template ();
130 static tree build_method_template ();
131 static tree build_private_template ();
132 static void build_class_template ();
133 static void build_category_template ();
134 static tree build_super_template ();
135
136 static void synth_forward_declarations ();
137 static void generate_ivar_lists ();
138 static void generate_dispatch_tables ();
139 static void generate_shared_structures ();
140
141 static tree build_msg_pool_reference ();
142 static tree init_selector ();
143 static tree build_keword_selector ();
144 static tree synth_id_with_class_suffix ();
145
146 /* misc. bookkeeping */
147
148 typedef struct hashedEntry      *hash;
149 typedef struct hashedAttribute  *attr;
150
151 struct hashedAttribute {
152         attr    next;
153         tree    value;
154 };
155 struct hashedEntry {
156         attr    list;
157         hash    next;
158         tree    key;
159 };
160 static void hash_init ();
161 static void hash_enter ();
162 static hash hash_lookup ();
163 static void hash_add_attr ();
164 static tree lookup_method ();
165 static tree lookup_instance_method_static ();
166 static tree lookup_class_method_static ();
167 static tree add_class ();
168 static int  add_selector_reference ();
169 static void add_class_reference ();
170 static int  add_objc_string ();
171
172 /* type encoding */
173
174 static void encode_aggregate ();
175 static void encode_bitfield ();
176 static void encode_type ();
177 static void encode_field_decl ();
178
179 static void really_start_method ();
180 static int  comp_method_with_proto ();
181 static int  comp_proto_with_proto ();
182 static tree get_arg_type_list ();
183 static tree expr_last ();
184
185 /* utilities for debugging and error diagnostics: */
186
187 static void warn_with_method ();
188 static void error_with_method ();
189 static void error_with_ivar ();
190 static char *gen_method_decl ();
191 static char *gen_declaration ();
192 static char *gen_declarator ();
193 static int is_complex_decl ();
194 static void adorn_decl ();
195 static void dump_interfaces ();
196
197 /*** Private Interface (data) ***/
198
199 /* reserved tag definitions: */
200
201 #define TYPE_ID                 "id"
202 #define TAG_OBJECT              "objc_object"
203 #define TAG_CLASS               "objc_class"
204 #define TAG_SUPER               "objc_super"
205 #define TAG_SELECTOR            "objc_selector"
206
207 #define _TAG_CLASS              "_objc_class"
208 #define _TAG_IVAR               "_objc_ivar"
209 #define _TAG_IVAR_LIST          "_objc_ivar_list"
210 #define _TAG_METHOD             "_objc_method"
211 #define _TAG_METHOD_LIST        "_objc_method_list"
212 #define _TAG_CATEGORY           "_objc_category"
213 #define _TAG_MODULE             "_objc_module"
214 #define _TAG_SYMTAB             "_objc_symtab"
215 #define _TAG_SUPER              "_objc_super"
216
217 /* set by `continue_class ()' and checked by `is_public ()' */
218
219 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC(record_type))
220 #define TYPED_OBJECT(type) \
221        (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
222
223 /* some commonly used instances of "identifier_node". */
224
225 static tree self_id, _cmd_id;
226
227 static tree self_decl, _msg_decl, _msgSuper_decl;
228 static tree objc_getClass_decl, objc_getMetaClass_decl;
229
230 static tree super_type, selector_type, id_type, class_type;
231 static tree instance_type;
232
233 static tree interface_chain = NULLT;
234
235 /* chains to manage selectors that are referenced and defined in the module */
236
237 static tree cls_ref_chain = NULLT;      /* classes referenced */
238 static tree sel_ref_chain = NULLT;      /* selectors referenced */
239 static tree sel_refdef_chain = NULLT;   /* selectors references & defined */
240 static int  max_selector_index;         /* total # of selector referenced */
241
242 /* hash tables to manage the global pool of method prototypes */
243
244 static hash *nst_method_hash_list = 0;
245 static hash *cls_method_hash_list = 0;
246
247 /* the following are used when compiling a class implementation.
248  *
249  * implementation_template will normally be an anInterface, however if
250  * none exists this will be equal to implementation_context...it is
251  * set in start_class.
252  */
253
254 /* backend data declarations */
255
256 static tree _OBJC_SYMBOLS_decl;
257 static tree     _OBJC_INSTANCE_VARIABLES_decl, _OBJC_CLASS_VARIABLES_decl;
258 static tree     _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl;
259 static tree     _OBJC_CLASS_decl, _OBJC_METACLASS_decl;
260 #ifdef OBJC_SELECTORS_WITHOUT_LABELS
261 static tree     _OBJC_SELECTOR_REFERENCES_decl;
262 #endif
263 static tree _OBJC_MODULES_decl;
264 static tree _OBJC_STRINGS_decl;
265
266 static tree implementation_context = NULLT,
267             implementation_template = NULLT;
268
269 struct imp_entry {
270   struct imp_entry *next;
271   tree imp_context;
272   tree imp_template;
273   tree class_decl;              /* _OBJC_CLASS_<my_name>; */
274   tree meta_decl;               /* _OBJC_METACLASS_<my_name>; */
275 };
276 static struct imp_entry *imp_list = 0;
277 static int imp_count = 0;       /* `@implementation' */
278 static int cat_count = 0;       /* `@category' */
279
280 static tree objc_class_template, objc_category_template, _PRIVATE_record;
281 static tree _clsSuper_ref, __clsSuper_ref;
282
283 static tree objc_method_template, objc_ivar_template;
284 static tree objc_symtab_template, objc_module_template;
285 static tree objc_super_template, objc_object_reference;
286
287 static tree objc_object_id, objc_class_id;
288 static tree _OBJC_SUPER_decl;
289
290 static tree method_context = NULLT;
291 static int  method_slot = 0;    /* used by start_method_def */
292
293 #define BUFSIZE         512
294
295 static char *errbuf;    /* a buffer for error diagnostics */
296
297 extern char *strcpy (), *strcat ();
298
299 extern tree groktypename_in_parm_context ();
300
301 extern struct obstack permanent_obstack, *current_obstack,  *rtl_obstack;
302
303 /* data imported from toplev.c  */
304
305 extern char *dump_base_name;
306 \f
307 /* Open and close the file for outputting class declarations, if requested.  */
308
309 int flag_gen_declaration = 0;
310
311 FILE *gen_declaration_file;
312
313 /* Warn if multiple methods are seen for the same selector, but with
314    different argument types. */
315
316 int warn_selector = 0;
317
318 void
319 lang_init ()
320 {
321   /* the beginning of the file is a new line; check for # */
322   /* With luck, we discover the real source file's name from that
323      and put it in input_filename.  */
324   ungetc (check_newline (), finput);
325
326   /* If gen_declaration desired, open the output file.  */
327   if (flag_gen_declaration)
328     {
329       int dump_base_name_length = strlen (dump_base_name);
330       register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
331       strcpy (dumpname, dump_base_name);
332       strcat (dumpname, ".decl");
333       gen_declaration_file = fopen (dumpname, "w");
334       if (gen_declaration_file == 0)
335         pfatal_with_name (dumpname);
336     }
337
338   if (doing_objc_thang)
339     init_objc ();
340 }
341
342 void
343 objc_finish ()
344 {
345   if (doing_objc_thang)
346     finish_objc ();             /* Objective-C finalization */
347
348   if (gen_declaration_file)
349     fclose (gen_declaration_file);
350 }
351
352 void
353 lang_finish ()
354 {
355 }
356
357 int
358 lang_decode_option (p)
359      char *p;
360 {
361   if (!strcmp (p, "-lang-objc"))
362     doing_objc_thang = 1;
363   else if (!strcmp (p, "-gen-decls"))
364     flag_gen_declaration = 1;
365   else if (!strcmp (p, "-Wselector"))
366     warn_selector = 1;
367   else if (!strcmp (p, "-Wno-selector"))
368     warn_selector = 0;
369   else
370     return c_decode_option (p);
371
372   return 1;
373 }
374 \f
375 static tree
376 define_decl (declarator, declspecs)
377      tree declarator;
378      tree declspecs;
379 {
380   tree decl = start_decl (declarator, declspecs, 0);
381   finish_decl (decl, NULLT, NULLT);
382   return decl;
383 }
384
385 /*
386  * rules for statically typed objects...called from `c-typeck.comptypes'.
387  *
388  * an assignment of the form `a' = `b' is permitted if:
389  *
390  *   - `a' is of type "id".
391  *   - `a' and `b' are the same class type.
392  *   - `a' and `b' are of class types A and B such that B is a descendant
393  *     of A.
394  */
395
396 int
397 maybe_objc_comptypes (lhs, rhs)
398      tree lhs, rhs;
399 {
400   if (doing_objc_thang)
401     return objc_comptypes (lhs, rhs);
402   return 0;
403 }
404
405 int
406 objc_comptypes (lhs, rhs)
407      tree lhs;
408      tree rhs;
409 {
410   /* `id' = `<class> *', `<class> *' = `id' */
411
412   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
413       || (TYPED_OBJECT (lhs) && TYPE_NAME (rhs) == objc_object_id))
414     return 1;
415
416   /* `id' = `Class', `Class' = `id' */
417
418
419   else if ((TYPE_NAME (lhs) == objc_object_id &&
420             TYPE_NAME (rhs) == objc_class_id) ||
421            (TYPE_NAME (lhs) == objc_class_id &&
422             TYPE_NAME (rhs) == objc_object_id))
423     return 1;
424
425   /* `<class> *' = `<class> *' */
426
427   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
428     {
429       tree lname = TYPE_NAME (lhs), rname = TYPE_NAME (rhs);
430
431       if (lname == rname)
432         return 1;
433       else
434         {
435           /* if the left hand side is a super class of the right hand side,
436              allow it...
437              */
438           tree rinter = lookup_interface (rname);
439
440           while (rinter)
441             {
442               if (lname == CLASS_SUPER_NAME (rinter))
443                 return 1;
444
445               rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
446             }
447
448           return 0;
449         }
450     }
451   else
452     return 0;
453 }
454
455 /* Called from c-decl.c before all calls to rest_of_decl_compilation.  */
456
457 void
458 maybe_objc_check_decl (decl)
459      tree decl;
460 {
461   if (doing_objc_thang)
462     objc_check_decl (decl);
463 }
464
465 void
466 objc_check_decl (decl)
467      tree decl;
468 {
469   tree type = TREE_TYPE (decl);
470   static int alreadyWarned = 0;
471
472   if (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
473     {
474       if (!alreadyWarned)
475         {
476           error ("GNU compiler does not support statically allocated objects");
477           alreadyWarned = 1;
478         }
479       error_with_decl (decl, "`%s' cannot be statically allocated");
480     }
481 }
482
483 /* implement static typing. at this point, we know we have an interface... */
484
485 tree
486 get_static_reference (interface)
487      tree interface;
488 {
489   return xref_tag (RECORD_TYPE, CLASS_NAME (interface));
490 }
491
492 /* Create and push a decl for a built-in external variable or field NAME.
493    CODE says which.
494    TYPE is its data type.  */
495
496 static tree
497 create_builtin_decl (code, type, name)
498      enum tree_code code;
499      tree type;
500      char *name;
501 {
502   tree decl = build_decl (code, get_identifier (name), type);
503   if (code == VAR_DECL)
504     {
505       TREE_STATIC (decl) = 1;
506       make_decl_rtl (decl, 0, 1);
507       pushdecl (decl);
508     }
509   return decl;
510 }
511
512 /*
513  *      purpose: "play" parser, creating/installing representations
514  *               of the declarations that are required by Objective-C.
515  *
516  *      model:
517  *
518  *              type_spec--------->sc_spec
519  *              (tree_list)        (tree_list)
520  *                  |                  |
521  *                  |                  |
522  *              identifier_node    identifier_node
523  */
524 static void
525 synth_module_prologue ()
526 {
527   tree expr_decl, temp_type;
528
529   /* defined in `objc.h' */
530   objc_object_id = get_identifier (TAG_OBJECT);
531
532   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
533
534   id_type = build_pointer_type (objc_object_reference);
535
536   objc_class_id = get_identifier (TAG_CLASS);
537   
538   class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
539
540   /* Declare type of selector-objects that represent an operation name.  */
541
542 #ifdef OBJC_INT_SELECTORS
543   /* `unsigned int' */
544   selector_type = unsigned_type_node;
545 #else
546   /* `struct objc_selector *' */
547   selector_type
548     = build_pointer_type (xref_tag (RECORD_TYPE,
549                                     get_identifier (TAG_SELECTOR)));
550 #endif /* not OBJC_INT_SELECTORS */
551
552   /* struct objc_object *objc_msgSend (id, SEL, ...); */
553
554   temp_type
555     = build_function_type (id_type,
556                            tree_cons (NULL_TREE, id_type,
557                                       tree_cons (NULLT, selector_type, NULLT)));
558
559   _msg_decl = builtin_function ("objc_msgSend", temp_type, NOT_BUILT_IN, 0);
560
561   /* struct objc_object *objc_msgSendSuper (void *, SEL, ...); */
562
563   temp_type
564     = build_function_type (id_type,
565                            tree_cons (NULL_TREE, ptr_type_node,
566                                       tree_cons (NULLT, selector_type, NULLT)));
567
568   _msgSuper_decl = builtin_function ("objc_msgSendSuper",
569                                      temp_type, NOT_BUILT_IN, 0);
570
571   /* id objc_getClass (); */
572   
573   temp_type = build_function_type (id_type, NULLT);
574
575   objc_getClass_decl
576     = builtin_function ("objc_getClass", temp_type, NOT_BUILT_IN, 0);
577
578   /* id objc_getMetaClass (); */
579
580   objc_getMetaClass_decl
581     = builtin_function ("objc_getMetaClass", temp_type, NOT_BUILT_IN, 0);
582
583   /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
584
585 #ifdef OBJC_SELECTORS_WITHOUT_LABELS
586   _OBJC_SELECTOR_REFERENCES_decl
587     = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
588                            "_OBJC_SELECTOR_REFERENCES");
589 #endif
590 }
591
592 /*
593  * custom "build_string ()" which sets TREE_TYPE!
594  */
595 static tree
596 my_build_string (len, str)
597      int len;
598      char *str;
599 {
600   int wide_flag = 0;
601   tree aString = build_string (len, str);
602   /*
603    *  some code from "combine_strings ()", which is local to c-parse.y.
604    */
605   if (TREE_TYPE (aString) == int_array_type_node)
606     wide_flag = 1;
607
608   TREE_TYPE (aString) =
609     build_array_type (wide_flag ? integer_type_node : char_type_node,
610                       build_index_type (build_int_2 (len - 1, 0)));
611
612   TREE_CONSTANT (aString) = 1;  /* puts string in the ".text" segment */
613   TREE_STATIC (aString) = 1;
614
615   return aString;
616 }
617 \f
618 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
619
620 /* Predefine the following data type:
621
622         struct _objc_symtab {
623                 long sel_ref_cnt;
624                 SEL *refs;
625                 short cls_def_cnt;
626                 short cat_def_cnt;
627                 void *defs[cls_def_cnt + cat_def_cnt];
628         }; */
629
630 static void
631 build_objc_symtab_template ()
632 {
633   tree field_decl, field_decl_chain, index;
634
635   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
636
637   /* long sel_ref_cnt; */
638
639   field_decl = create_builtin_decl (FIELD_DECL,
640                                     long_integer_type_node,
641                                     "sel_ref_cnt");
642   field_decl_chain = field_decl;
643
644   /* SEL *refs; */
645
646   field_decl = create_builtin_decl (FIELD_DECL,
647                                     build_pointer_type (selector_type),
648                                     "refs");
649   chainon (field_decl_chain, field_decl);
650
651   /* short cls_def_cnt; */
652
653   field_decl = create_builtin_decl (FIELD_DECL,
654                                     short_integer_type_node,
655                                     "cls_def_cnt");
656   chainon (field_decl_chain, field_decl);
657
658   /* short cat_def_cnt; */
659
660   field_decl = create_builtin_decl (FIELD_DECL,
661                                     short_integer_type_node,
662                                     "cat_def_cnt");
663   chainon (field_decl_chain, field_decl);
664
665   /* void *defs[cls_def_cnt + cat_def_cnt]; */
666
667   index = build_index_type (build_int_2 (imp_count + cat_count - 1, 0));
668   field_decl = create_builtin_decl (FIELD_DECL,
669                                     build_array_type (ptr_type_node, index),
670                                     "defs");
671   chainon (field_decl_chain, field_decl);
672
673   finish_struct (objc_symtab_template, field_decl_chain);
674 }
675
676 /* Create the initial value for the `defs' field of _objc_symtab.
677    This is a CONSTRUCTOR.  */
678
679 static tree
680 init_def_list ()
681 {
682   tree expr, initlist = NULLT;
683   struct imp_entry *impent;
684
685   if (imp_count)
686     for (impent = imp_list; impent; impent = impent->next)
687       {
688         if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
689           {
690             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
691             initlist = tree_cons (NULLT, expr, initlist);
692           }
693       }
694
695   if (cat_count)
696     for (impent = imp_list; impent; impent = impent->next)
697       {
698         if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
699           {
700             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
701             initlist = tree_cons (NULLT, expr, initlist);
702           }
703       }
704   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
705 }
706
707 /* Construct the initial value for all of _objc_symtab.  */
708
709 static tree
710 init_objc_symtab ()
711 {
712   tree initlist;
713
714   /* sel_ref_cnt = { ..., 5, ... } */
715
716   if (sel_ref_chain)
717     initlist = build_tree_list (NULLT, build_int_2 (max_selector_index, 0));
718   else
719     initlist = build_tree_list (NULLT, build_int_2 (0, 0));
720
721   /* refs = { ..., _OBJC_SELECTOR_REFERENCES, ... } */
722
723 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
724   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
725 #else
726   if (sel_ref_chain)
727     initlist = tree_cons (NULLT, _OBJC_SELECTOR_REFERENCES_decl, initlist);
728   else
729     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
730 #endif
731
732   /* cls_def_cnt = { ..., 5, ... } */
733
734   initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
735
736   /* cat_def_cnt = { ..., 5, ... } */
737
738   initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
739
740   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
741
742   if (imp_count || cat_count)
743     initlist = tree_cons (NULLT, init_def_list (), initlist);
744
745   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
746 }
747
748 /* Push forward-declarations of all the categories
749    so that init_def_list can use them in a CONSTRUCTOR.  */
750
751 static void
752 forward_declare_categories ()
753 {
754   struct imp_entry *impent;
755   tree sav = implementation_context;
756   for (impent = imp_list; impent; impent = impent->next)
757     {
758       if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
759         {
760           /* Set an invisible arg to synth_id_with_class_suffix.  */
761           implementation_context = impent->imp_context;
762           impent->class_decl
763             = create_builtin_decl (VAR_DECL, objc_category_template,
764                                    IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY")));
765         }
766     }
767   implementation_context = sav;
768 }
769
770 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
771    and initialized appropriately.  */
772
773 static void
774 generate_objc_symtab_decl ()
775 {
776   tree sc_spec;
777
778   if (!objc_category_template)
779     build_category_template ();
780
781   /* forward declare categories */
782   if (cat_count)
783     forward_declare_categories ();
784
785   if (!objc_symtab_template)
786     build_objc_symtab_template ();
787
788   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
789
790   _OBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
791                                    tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
792
793   finish_decl (_OBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
794 }
795 \f
796 /*
797  *      tree_node------->tree_node----->...
798  *          |                |
799  *          | (value)        | (value)
800  *          |                |
801  *        expr             expr
802  */
803 static tree
804 init_module_descriptor ()
805 {
806   tree initlist, expr;
807
808   /* version = { 1, ... } */
809
810   expr = build_int_2 (OBJC_VERSION, 0);
811   initlist = build_tree_list (NULLT, expr);
812
813   /* size = { ..., sizeof (struct objc_module), ... } */
814
815   expr = size_in_bytes (objc_module_template);
816   initlist = tree_cons (NULLT, expr, initlist);
817
818   /* name = { ..., "foo.m", ... } */
819
820   expr = build_msg_pool_reference (
821                                    add_objc_string (get_identifier (input_filename)));
822   initlist = tree_cons (NULLT, expr, initlist);
823
824   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
825
826   if (_OBJC_SYMBOLS_decl)
827     expr = build_unary_op (ADDR_EXPR, _OBJC_SYMBOLS_decl, 0);
828   else
829     expr = build_int_2 (0, 0);
830   initlist = tree_cons (NULLT, expr, initlist);
831
832   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
833 }
834
835 /* Write out the data structures to describe Objective C classes defined.
836    If appropriate, compile and output a setup function to initialize them.
837    Return a string which is the name of a function to call to initialize
838    the Objective C data structures for this file (and perhaps for other files
839    also).  */
840
841 static char *
842 build_module_descriptor ()
843 {
844   tree decl_specs, field_decl, field_decl_chain;
845
846   objc_module_template = start_struct (RECORD_TYPE, get_identifier (_TAG_MODULE));
847
848   /* long version; */
849
850   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
851   field_decl = get_identifier ("version");
852   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
853   field_decl_chain = field_decl;
854
855   /* long  size; */
856
857   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
858   field_decl = get_identifier ("size");
859   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
860   chainon (field_decl_chain, field_decl);
861
862   /* char  *name; */
863
864   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
865   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
866   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
867   chainon (field_decl_chain, field_decl);
868
869   /* struct objc_symtab *symtab; */
870
871   decl_specs = get_identifier (_TAG_SYMTAB);
872   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
873   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
874   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
875   chainon (field_decl_chain, field_decl);
876
877   finish_struct (objc_module_template, field_decl_chain);
878
879   /* create an instance of "objc_module" */
880
881   decl_specs = tree_cons (NULLT, objc_module_template,
882                           build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
883
884   _OBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
885                                    decl_specs, 1);
886
887   finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT);
888
889   /* Mark the decl to avoid "defined but not used" warning. */
890   DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1;
891
892   /* Generate a constructor call for the module descriptor. 
893      This code was generated by reading the grammar rules
894      of c-parse.y;  Therefore, it may not be the most efficient
895      way of generating the requisite code. */
896 #ifndef NEXT_OBJC_RUNTIME
897   {
898     tree parms, function_decl, decelerator, void_list_node;
899     tree function_type;
900     char *buf;
901     char *global_object_name = 0;
902     tree t;
903
904     /* Use a global object (which is already required to be unique over
905        the program) rather than the file name (which imposes extra
906        constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
907
908     /* Find the name of some global object defined in this file.  */
909     for (t = getdecls (); t; t = TREE_CHAIN (t))
910       if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
911         {
912           global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
913           break;
914         }
915
916     /* If none, use the name of the file.  */
917     if (!global_object_name)
918       {
919         char *p, *q;
920         global_object_name
921           = (char *) alloca (strlen (main_input_filename) + 1);
922
923         p = main_input_filename;
924         q = global_object_name;
925
926         /* Replace any weird characters in the file name.  */
927         for (; *p; p++)
928           if (! ((*p >= '0' && *p <= '9')
929                  || (*p >= 'A' && *p <= 'Z')
930                  || (*p >= 'a' && *p <= 'z')))
931             *q++ = '_';
932           else
933             *q++ = *p;
934         *q = 0;
935       }
936
937     /* Make the constructor name from the name we have found.  */
938     buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
939                             + strlen (global_object_name));
940     sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
941
942     /* Declare void __objc_execClass (void*); */
943
944     void_list_node = build_tree_list (NULL_TREE, void_type_node);
945     function_type
946       = build_function_type (void_type_node,  
947                              tree_cons (NULL_TREE, ptr_type_node,  
948                                         void_list_node));
949     function_decl = build_decl (FUNCTION_DECL,  
950                                 get_identifier ("__objc_execClass"),  
951                                 function_type);
952     DECL_EXTERNAL (function_decl) = 1;
953     TREE_PUBLIC (function_decl) = 1;
954     pushdecl (function_decl);
955     rest_of_decl_compilation (function_decl, 0, 0, 0);
956
957     parms
958       = build_tree_list (NULLT,
959                          build_unary_op (ADDR_EXPR, _OBJC_MODULES_decl, 0));
960     decelerator = build_function_call (function_decl, parms);
961
962     /* void __objc_file_init () {objc_execClass(&L_OBJC_MODULES);}  */
963
964     start_function (void_list_node,
965                     build_parse_node (CALL_EXPR, get_identifier (buf),
966                                       /* This has the format of the output
967                                          of get_parm_info.  */
968                                       tree_cons (NULL_TREE, NULL_TREE,
969                                                  void_list_node),
970                                       NULL_TREE),
971                     0, 0);
972 #if 0 /* This should be turned back on later
973          for the systems where collect is not needed.  */
974     /* Make these functions nonglobal
975        so each file can use the same name.  */
976     TREE_PUBLIC (current_function_decl) = 0;
977 #endif
978     TREE_USED (current_function_decl) = 1;
979     store_parm_decls ();
980
981     assemble_external (function_decl);
982     c_expand_expr_stmt (decelerator);
983
984     finish_function (0);
985
986     /* Return the name of the constructor function.  */
987     return buf;
988   }
989 #else /* NEXT_OBJC_RUNTIME */
990   return 0;
991 #endif /* NEXT_OBJC_RUNTIME */
992 }
993
994 /* extern const char _OBJC_STRINGS[]; */
995
996 static void
997 generate_forward_declaration_to_string_table ()
998 {
999   tree sc_spec, decl_specs, expr_decl;
1000
1001   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
1002   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1003
1004   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1005
1006   _OBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1007 }
1008
1009 /* static char _OBJC_STRINGS[] = "..."; */
1010
1011 static void
1012 build_message_selector_pool ()
1013 {
1014   tree sc_spec, decl_specs, expr_decl;
1015   tree chain, string_expr;
1016   int goolengthtmp = 0, msg_pool_size = 0;
1017   char *string_goo;
1018
1019   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1020   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1021
1022   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1023
1024   _OBJC_STRINGS_decl = start_decl (expr_decl, decl_specs, 1);
1025
1026   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1027     msg_pool_size += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1028
1029   msg_pool_size++;
1030
1031   string_goo = (char *)xmalloc (msg_pool_size);
1032   bzero (string_goo, msg_pool_size);
1033
1034   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1035     {
1036       strcpy (string_goo + goolengthtmp, IDENTIFIER_POINTER (TREE_VALUE (chain)));
1037       goolengthtmp += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1038     }
1039
1040   string_expr = my_build_string (msg_pool_size, string_goo);
1041
1042   finish_decl (_OBJC_STRINGS_decl, string_expr, NULLT);
1043 }
1044
1045 /*
1046  * synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
1047  *
1048  * the cast stops the compiler from issuing the following message:
1049  *
1050  * grok.m: warning: initialization of non-const * pointer from const *
1051  * grok.m: warning: initialization between incompatible pointer types
1052  */
1053 static tree
1054 build_msg_pool_reference (offset)
1055      int offset;
1056 {
1057   tree expr = build_int_2 (offset, 0);
1058   tree cast;
1059
1060   expr = build_array_ref (_OBJC_STRINGS_decl, expr);
1061   expr = build_unary_op (ADDR_EXPR, expr, 0);
1062
1063   cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
1064                           build1 (INDIRECT_REF, NULLT, NULLT));
1065   TREE_TYPE (expr) = groktypename (cast);
1066   return expr;
1067 }
1068
1069 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1070 static tree
1071 build_selector_reference (idx)
1072       int idx;
1073 {
1074   tree ref, decl, name, ident;
1075   char buf[256];
1076   struct obstack *save_current_obstack = current_obstack;
1077   struct obstack *save_rtl_obstack = rtl_obstack;
1078
1079   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1080
1081   /* new stuff */
1082   rtl_obstack = current_obstack = &permanent_obstack;
1083   ident = get_identifier (buf);
1084
1085   if (IDENTIFIER_GLOBAL_VALUE (ident))
1086     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* set by pushdecl() */
1087   else 
1088     {
1089       decl = build_decl (VAR_DECL, ident, selector_type);
1090       DECL_EXTERNAL (decl) = 1;
1091       TREE_PUBLIC (decl) = 1;
1092       TREE_USED (decl) = 1;
1093   
1094       make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
1095       pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
1096     }
1097   current_obstack = save_current_obstack;
1098   rtl_obstack = save_rtl_obstack;
1099
1100   return decl;
1101 }
1102 #endif
1103
1104 static tree
1105 init_selector (offset)
1106      int offset;
1107 {
1108   tree expr = build_msg_pool_reference (offset);
1109   TREE_TYPE (expr) = selector_type; /* cast */
1110   return expr;
1111 }
1112
1113 static void
1114 build_selector_translation_table ()
1115 {
1116   tree sc_spec, decl_specs, expr_decl;
1117   tree chain, initlist = NULLT;
1118   int offset = 0;
1119 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1120   tree decl, var_decl;
1121   int idx = 0;
1122   char buf[256];
1123 #else
1124   /* The corresponding pop_obstacks is in finish_decl,
1125      called at the end of this function.  */
1126   push_obstacks_nochange ();
1127 #endif
1128
1129   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1130     {
1131       tree expr;
1132
1133 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1134       sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1135       sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
1136
1137       /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
1138       decl_specs = tree_cons (NULLT, selector_type, sc_spec);
1139       var_decl = get_identifier (buf);
1140
1141       /* the `decl' that is returned from start_decl is the one that we
1142         * forward declared in `build_selector_reference()'
1143         */
1144       decl = start_decl (var_decl, decl_specs, 1); 
1145 #endif
1146
1147       expr = init_selector (offset);
1148
1149       /* add one for the '\0' character */
1150       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1151
1152 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1153       finish_decl (decl, expr, NULLT);
1154       idx++;
1155 #else
1156       initlist = tree_cons (NULLT, expr, initlist);
1157 #endif
1158     }
1159
1160 #ifdef OBJC_SELECTORS_WITHOUT_LABELS
1161   /* Cause the variable and its initial value to be actually output.  */
1162   DECL_EXTERNAL (_OBJC_SELECTOR_REFERENCES_decl) = 0;
1163   TREE_STATIC (_OBJC_SELECTOR_REFERENCES_decl) = 1;
1164   /* NULL terminate the list and fix the decl for output. */
1165   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1166   DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1;
1167   initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1168   finish_decl (_OBJC_SELECTOR_REFERENCES_decl, initlist, NULLT);
1169 #endif
1170 }
1171
1172 static void
1173 add_class_reference (ident)
1174      tree ident;
1175 {
1176   tree chain;
1177
1178   if (chain = cls_ref_chain)
1179     {
1180       tree tail;
1181       do
1182         {
1183           if (ident == TREE_VALUE (chain))
1184             return;
1185
1186           tail = chain;
1187           chain = TREE_CHAIN (chain);
1188         }
1189       while (chain);
1190
1191       /* append to the end of the list */
1192       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1193     }
1194   else
1195     cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1196 }
1197
1198 /*
1199  * sel_ref_chain is a list whose "value" fields will be instances of
1200  * identifier_node that represent the selector.
1201  */
1202 static int
1203 add_selector_reference (ident)
1204      tree ident;
1205 {
1206   tree chain;
1207   int index = 0;
1208
1209   /* this adds it to sel_refdef_chain, the global pool of selectors */
1210   add_objc_string (ident);
1211
1212   if (chain = sel_ref_chain)
1213     {
1214       tree tail;
1215       do
1216         {
1217           if (ident == TREE_VALUE (chain))
1218             return index;
1219
1220           index++;
1221           tail = chain;
1222           chain = TREE_CHAIN (chain);
1223         }
1224       while (chain);
1225
1226       /* append to the end of the list */
1227       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1228     }
1229   else
1230     sel_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1231
1232   max_selector_index++;
1233   return index;
1234 }
1235
1236 /*
1237  * sel_refdef_chain is a list whose "value" fields will be instances of
1238  * identifier_node that represent the selector. It returns the offset of
1239  * the selector from the beginning of the _OBJC_STRINGS pool. This offset
1240  * is typically used by "init_selector ()" during code generation.
1241  */
1242 static int
1243 add_objc_string (ident)
1244      tree ident;
1245 {
1246   tree chain;
1247   int offset = 0;
1248
1249   if (chain = sel_refdef_chain)
1250     {
1251       tree tail;
1252       do
1253         {
1254           if (ident == TREE_VALUE (chain))
1255             return offset;
1256
1257           /* add one for the '\0' character */
1258           offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1259           tail = chain;
1260           chain = TREE_CHAIN (chain);
1261         }
1262       while (chain);
1263
1264       /* append to the end of the list */
1265       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1266     }
1267   else
1268     sel_refdef_chain = perm_tree_cons (NULLT, ident, NULLT);
1269
1270   return offset;
1271 }
1272
1273 tree
1274 lookup_interface (ident)
1275      tree ident;
1276 {
1277   tree chain;
1278
1279   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
1280     {
1281       if (ident == CLASS_NAME (chain))
1282         return chain;
1283     }
1284   return NULLT;
1285 }
1286
1287 static tree
1288 objc_copy_list (list, head)
1289      tree list;
1290      tree *head;
1291 {
1292   tree newlist = NULL_TREE, tail = NULL_TREE;
1293
1294   while (list)
1295     {
1296       tail = copy_node (list);
1297
1298       /* the following statement fixes a bug when inheriting instance
1299          variables that are declared to be bitfields. finish_struct () expects
1300          to find the width of the bitfield in DECL_INITIAL (), which it
1301          nulls out after processing the decl of the super class...rather
1302          than change the way finish_struct () works (which is risky),
1303          I create the situation it expects...s.naroff (7/23/89).
1304          */
1305       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
1306         DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
1307
1308       newlist = chainon (newlist, tail);
1309       list = TREE_CHAIN (list);
1310     }
1311   *head = newlist;
1312   return tail;
1313 }
1314
1315 /* used by:
1316  * build_private_template (), get_class_ivars (), and get_static_reference ().
1317  */
1318 static tree
1319 build_ivar_chain (interface)
1320      tree interface;
1321 {
1322   tree my_name, super_name, ivar_chain;
1323
1324   my_name = CLASS_NAME (interface);
1325   super_name = CLASS_SUPER_NAME (interface);
1326
1327   /* "leaf" ivars never get copied...there is no reason to. */
1328   ivar_chain = CLASS_IVARS (interface);
1329
1330   while (super_name)
1331     {
1332       tree op1;
1333       tree super_interface = lookup_interface (super_name);
1334
1335       if (!super_interface)
1336         {
1337           /* fatal did not work with 2 args...should fix */
1338           error ("Cannot find interface declaration for `%s', superclass of `%s'",
1339                  IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name));
1340           exit (34);
1341         }
1342       if (super_interface == interface)
1343         {
1344           fatal ("Circular inheritance in interface declaration for `%s'",
1345                  IDENTIFIER_POINTER (super_name));
1346         }
1347       interface = super_interface;
1348       my_name = CLASS_NAME (interface);
1349       super_name = CLASS_SUPER_NAME (interface);
1350
1351       op1 = CLASS_IVARS (interface);
1352       if (op1)
1353         {
1354           tree head, tail = objc_copy_list (op1, &head);
1355
1356           /* prepend super class ivars...make a copy of the list, we
1357            * do not want to alter the original.
1358            */
1359           TREE_CHAIN (tail) = ivar_chain;
1360           ivar_chain = head;
1361         }
1362     }
1363   return ivar_chain;
1364 }
1365
1366 /*
1367  *  struct <classname> {
1368  *    struct objc_class *isa;
1369  *    ...
1370  *  };
1371  */
1372 static tree
1373 build_private_template (class)
1374      tree class;
1375 {
1376   tree ivar_context;
1377
1378   if (CLASS_STATIC_TEMPLATE (class))
1379     {
1380       _PRIVATE_record = CLASS_STATIC_TEMPLATE (class);
1381       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
1382     }
1383   else
1384     {
1385       _PRIVATE_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
1386
1387       ivar_context = build_ivar_chain (class);
1388
1389       finish_struct (_PRIVATE_record, ivar_context);
1390
1391       CLASS_STATIC_TEMPLATE (class) = _PRIVATE_record;
1392
1393       /* mark this record as class template - for class type checking */
1394       TREE_STATIC_TEMPLATE (_PRIVATE_record) = 1;
1395     }
1396   instance_type = groktypename (
1397                                 build_tree_list (build_tree_list (NULLT, _PRIVATE_record),
1398                                                  build1 (INDIRECT_REF, NULLT, NULLT)));
1399   return ivar_context;
1400 }
1401
1402 /*
1403  *  struct objc_category {
1404  *    char *category_name;
1405  *    char *class_name;
1406  *    struct objc_method_list *instance_methods;
1407  *    struct objc_method_list *class_methods;
1408  *  };
1409  */
1410 static void
1411 build_category_template ()
1412 {
1413   tree decl_specs, field_decl, field_decl_chain;
1414
1415   objc_category_template = start_struct (RECORD_TYPE,
1416                                          get_identifier (_TAG_CATEGORY));
1417   /* char *category_name; */
1418
1419   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1420   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
1421   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1422   field_decl_chain = field_decl;
1423
1424   /* char *class_name; */
1425
1426   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1427   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
1428   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1429   chainon (field_decl_chain, field_decl);
1430
1431   /* struct objc_method_list *instance_methods; */
1432
1433   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1434                                                  get_identifier (_TAG_METHOD_LIST)));
1435   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
1436   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1437   chainon (field_decl_chain, field_decl);
1438
1439   /* struct objc_method_list *class_methods; */
1440
1441   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1442                                                  get_identifier (_TAG_METHOD_LIST)));
1443   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
1444   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1445   chainon (field_decl_chain, field_decl);
1446
1447   finish_struct (objc_category_template, field_decl_chain);
1448 }
1449
1450 /*
1451  *  struct objc_class {
1452  *    struct objc_class *isa;
1453  *    struct objc_class *super_class;
1454  *    char *name;
1455  *    long version;
1456  *    long info;
1457  *    long instance_size;
1458  *    struct objc_ivar_list *ivars;
1459  *    struct objc_method_list *methods;
1460  *    struct objc_cache *cache;
1461  *  };
1462  */
1463 static void
1464 build_class_template ()
1465 {
1466   tree decl_specs, field_decl, field_decl_chain;
1467
1468   objc_class_template = start_struct (RECORD_TYPE, get_identifier (_TAG_CLASS));
1469
1470   /* struct objc_class *isa; */
1471
1472   decl_specs = build_tree_list (NULLT, objc_class_template);
1473   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
1474   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1475   field_decl_chain = field_decl;
1476
1477   /* struct objc_class *super_class; */
1478
1479   decl_specs = build_tree_list (NULLT, objc_class_template);
1480   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
1481   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1482   chainon (field_decl_chain, field_decl);
1483
1484   /* char *name; */
1485
1486   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1487   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
1488   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1489   chainon (field_decl_chain, field_decl);
1490
1491   /* long version; */
1492
1493   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1494   field_decl = get_identifier ("version");
1495   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1496   chainon (field_decl_chain, field_decl);
1497
1498   /* long info; */
1499
1500   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1501   field_decl = get_identifier ("info");
1502   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1503   chainon (field_decl_chain, field_decl);
1504
1505   /* long instance_size; */
1506
1507   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1508   field_decl = get_identifier ("instance_size");
1509   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1510   chainon (field_decl_chain, field_decl);
1511
1512   /* struct objc_ivar_list *ivars; */
1513
1514   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1515                                                  get_identifier (_TAG_IVAR_LIST)));
1516   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
1517   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1518   chainon (field_decl_chain, field_decl);
1519
1520   /* struct objc_method_list *methods; */
1521
1522   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1523                                                  get_identifier (_TAG_METHOD_LIST)));
1524   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
1525   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1526   chainon (field_decl_chain, field_decl);
1527
1528   /* struct objc_cache *cache; */
1529
1530   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1531                                                  get_identifier ("objc_cache")));
1532   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
1533   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1534   chainon (field_decl_chain, field_decl);
1535
1536   finish_struct (objc_class_template, field_decl_chain);
1537 }
1538
1539 /*
1540  * generate appropriate forward declarations for an implementation
1541  */
1542 static void
1543 synth_forward_declarations ()
1544 {
1545   tree sc_spec, decl_specs, factory_id, anId;
1546
1547   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
1548
1549   anId = synth_id_with_class_suffix ("_OBJC_CLASS");
1550
1551   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
1552   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
1553   _OBJC_CLASS_decl = define_decl (anId, decl_specs);
1554
1555   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
1556
1557   anId = synth_id_with_class_suffix ("_OBJC_METACLASS");
1558
1559   _OBJC_METACLASS_decl = define_decl (anId, decl_specs);
1560
1561   /* pre-build the following entities - for speed/convenience. */
1562
1563   anId = get_identifier ("super_class");
1564   _clsSuper_ref = build_component_ref (_OBJC_CLASS_decl, anId);
1565   __clsSuper_ref = build_component_ref (_OBJC_METACLASS_decl, anId);
1566 }
1567
1568 static void
1569 error_with_ivar (message, decl, rawdecl)
1570      char *message;
1571      tree decl;
1572      tree rawdecl;
1573 {
1574   count_error (0);
1575   fprintf (stderr, "%s:%d: ",
1576            DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1577   bzero (errbuf, BUFSIZE);
1578   fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
1579 }
1580
1581 #define USERTYPE(t)     (TREE_CODE (t) == RECORD_TYPE || \
1582                          TREE_CODE (t) == UNION_TYPE ||  \
1583                          TREE_CODE (t) == ENUMERAL_TYPE)
1584
1585 static void
1586 check_ivars (inter, imp)
1587      tree inter;
1588      tree imp;
1589 {
1590   tree intdecls = CLASS_IVARS (inter);
1591   tree impdecls = CLASS_IVARS (imp);
1592   tree rawintdecls = CLASS_RAW_IVARS (inter);
1593   tree rawimpdecls = CLASS_RAW_IVARS (imp);
1594
1595   while (1)
1596     {
1597       tree t1, t2;
1598
1599       if (intdecls == 0 && impdecls == 0)
1600         break;
1601       if (intdecls == 0 || impdecls == 0)
1602         {
1603           error ("inconsistent instance variable specification");
1604           break;
1605         }
1606       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
1607
1608       if (!comptypes (t1, t2))
1609         {
1610           if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
1611             {
1612               error_with_ivar ("conflicting instance variable type",
1613                                impdecls, rawimpdecls);
1614               error_with_ivar ("previous declaration of",
1615                                intdecls, rawintdecls);
1616             }
1617           else                  /* both the type and the name don't match */
1618             {
1619               error ("inconsistent instance variable specification");
1620               break;
1621             }
1622         }
1623       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
1624         {
1625           error_with_ivar ("conflicting instance variable name",
1626                            impdecls, rawimpdecls);
1627           error_with_ivar ("previous declaration of",
1628                            intdecls, rawintdecls);
1629         }
1630       intdecls = TREE_CHAIN (intdecls);
1631       impdecls = TREE_CHAIN (impdecls);
1632       rawintdecls = TREE_CHAIN (rawintdecls);
1633       rawimpdecls = TREE_CHAIN (rawimpdecls);
1634     }
1635 }
1636
1637 /* Set super_type to the data type node for struct objc_super *,
1638    first defining struct objc_super itself.
1639    This needs to be done just once per compilation.  */
1640
1641 static tree
1642 build_super_template ()
1643 {
1644   tree record, decl_specs, field_decl, field_decl_chain;
1645
1646   record = start_struct (RECORD_TYPE, get_identifier (_TAG_SUPER));
1647
1648   /* struct objc_object *self; */
1649
1650   decl_specs = build_tree_list (NULLT, objc_object_reference);
1651   field_decl = get_identifier ("self");
1652   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
1653   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1654   field_decl_chain = field_decl;
1655
1656   /* struct objc_class *class; */
1657
1658   decl_specs = get_identifier (_TAG_CLASS);
1659   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
1660   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
1661
1662   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1663   chainon (field_decl_chain, field_decl);
1664
1665   finish_struct (record, field_decl_chain);
1666
1667   /* `struct objc_super *' */
1668   super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
1669                                               build1 (INDIRECT_REF, NULLT, NULLT)));
1670   return record;
1671 }
1672
1673 /*
1674  *      struct objc_ivar {
1675  *              char *ivar_name;
1676  *              char *ivar_type;
1677  *              int ivar_offset;
1678  *      };
1679  */
1680 static tree
1681 build_ivar_template ()
1682 {
1683   tree objc_ivar_id, objc_ivar_record;
1684   tree decl_specs, field_decl, field_decl_chain;
1685
1686   objc_ivar_id = get_identifier (_TAG_IVAR);
1687   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
1688
1689   /* char *ivar_name; */
1690
1691   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1692   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
1693
1694   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1695   field_decl_chain = field_decl;
1696
1697   /* char *ivar_type; */
1698
1699   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1700   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
1701
1702   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1703   chainon (field_decl_chain, field_decl);
1704
1705   /* int ivar_offset; */
1706
1707   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1708   field_decl = get_identifier ("ivar_offset");
1709
1710   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1711   chainon (field_decl_chain, field_decl);
1712
1713   finish_struct (objc_ivar_record, field_decl_chain);
1714
1715   return objc_ivar_record;
1716 }
1717
1718 /*
1719  *      struct {
1720  *              int ivar_count;
1721  *              struct objc_ivar ivar_list[ivar_count];
1722  *      };
1723  */
1724 static tree
1725 build_ivar_list_template (list_type, size)
1726      tree list_type;
1727      int size;
1728 {
1729   tree objc_ivar_list_id, objc_ivar_list_record;
1730   tree decl_specs, field_decl, field_decl_chain;
1731
1732   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1733
1734   /* int ivar_count; */
1735
1736   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1737   field_decl = get_identifier ("ivar_count");
1738
1739   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1740   field_decl_chain = field_decl;
1741
1742   /* struct objc_ivar ivar_list[]; */
1743
1744   decl_specs = build_tree_list (NULLT, list_type);
1745   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
1746                          build_int_2 (size, 0));
1747
1748   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1749   chainon (field_decl_chain, field_decl);
1750
1751   finish_struct (objc_ivar_list_record, field_decl_chain);
1752
1753   return objc_ivar_list_record;
1754 }
1755
1756 /*
1757  *      struct {
1758  *              int method_next;
1759  *              int method_count;
1760  *              struct objc_method method_list[method_count];
1761  *      };
1762  */
1763 static tree
1764 build_method_list_template (list_type, size)
1765      tree list_type;
1766      int size;
1767 {
1768   tree objc_ivar_list_id, objc_ivar_list_record;
1769   tree decl_specs, field_decl, field_decl_chain;
1770
1771   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1772
1773   /* int method_next; */
1774
1775   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1776   field_decl = get_identifier ("method_next");
1777
1778   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1779   field_decl_chain = field_decl;
1780
1781   /* int method_count; */
1782
1783   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1784   field_decl = get_identifier ("method_count");
1785
1786   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1787   chainon (field_decl_chain, field_decl);
1788
1789   /* struct objc_method method_list[]; */
1790
1791   decl_specs = build_tree_list (NULLT, list_type);
1792   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
1793                          build_int_2 (size, 0));
1794
1795   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1796   chainon (field_decl_chain, field_decl);
1797
1798   finish_struct (objc_ivar_list_record, field_decl_chain);
1799
1800   return objc_ivar_list_record;
1801 }
1802
1803 static tree
1804 build_ivar_list_initializer (field_decl, size)
1805      tree field_decl;
1806      int *size;
1807 {
1808   tree initlist = NULLT;
1809
1810   do
1811     {
1812       int offset;
1813
1814     /* set name */
1815     if (DECL_NAME (field_decl))
1816       {
1817         offset = add_objc_string (DECL_NAME (field_decl));
1818         initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1819       }
1820     else
1821       {
1822         /* unnamed bit-field ivar (yuck). */
1823         initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1824       }
1825
1826       /* set type */
1827       encode_field_decl (field_decl, OBJC_ENCODE_DONT_INLINE_DEFS);
1828       offset = add_objc_string (get_identifier (obstack_finish (&util_obstack)));
1829       obstack_free (&util_obstack, util_firstobj);
1830
1831       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1832
1833       /* set offset */
1834       initlist = tree_cons (NULLT,
1835                             build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) / BITS_PER_UNIT, 0),
1836                             
1837                             initlist);
1838       (*size)++;
1839       field_decl = TREE_CHAIN (field_decl);
1840     }
1841   while (field_decl);
1842
1843   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1844 }
1845
1846 static tree
1847 generate_ivars_list (type, name, size, list)
1848      tree type;
1849      char *name;
1850      int size;
1851      tree list;
1852 {
1853   tree sc_spec, decl_specs, decl, initlist;
1854
1855   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1856   decl_specs = tree_cons (NULLT, type, sc_spec);
1857
1858   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
1859
1860   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
1861   initlist = tree_cons (NULLT, list, initlist);
1862
1863   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
1864
1865   return decl;
1866 }
1867
1868 static void
1869 generate_ivar_lists ()
1870 {
1871   tree initlist, ivar_list_template, chain;
1872   tree cast, variable_length_type;
1873   int size;
1874
1875   if (!objc_ivar_template)
1876     objc_ivar_template = build_ivar_template ();
1877
1878   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1879                                                             get_identifier (_TAG_IVAR_LIST))), NULLT);
1880   variable_length_type = groktypename (cast);
1881
1882   /* only generate class variables for the root of the inheritance
1883      hierarchy since these will be the same for every class */
1884
1885   if (CLASS_SUPER_NAME (implementation_template) == NULLT
1886       && (chain = TYPE_FIELDS (objc_class_template)))
1887     {
1888       size = 0;
1889       initlist = build_ivar_list_initializer (chain, &size);
1890
1891       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1892
1893       _OBJC_CLASS_VARIABLES_decl =
1894         generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
1895                              size, initlist);
1896       /* cast! */
1897       TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type;
1898     }
1899   else
1900     _OBJC_CLASS_VARIABLES_decl = 0;
1901
1902   chain = CLASS_IVARS (implementation_template);
1903   if (chain)
1904     {
1905       size = 0;
1906       initlist = build_ivar_list_initializer (chain, &size);
1907
1908       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1909
1910       _OBJC_INSTANCE_VARIABLES_decl =
1911         generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
1912                              size, initlist);
1913       /* cast! */
1914       TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
1915     }
1916   else
1917     _OBJC_INSTANCE_VARIABLES_decl = 0;
1918 }
1919
1920 static tree
1921 build_dispatch_table_initializer (entries, size)
1922      tree entries;
1923      int *size;
1924 {
1925   tree initlist = NULLT;
1926
1927   do
1928     {
1929       int offset = add_objc_string (METHOD_SEL_NAME (entries));
1930
1931       initlist = tree_cons (NULLT, init_selector (offset), initlist);
1932
1933       offset = add_objc_string (METHOD_ENCODING (entries));
1934       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1935
1936       initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
1937
1938       (*size)++;
1939       entries = TREE_CHAIN (entries);
1940     }
1941   while (entries);
1942
1943   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1944 }
1945
1946 /*
1947  * To accomplish method prototyping without generating all kinds of
1948  * inane warnings, the definition of the dispatch table entries were
1949  * changed from:
1950  *
1951  *      struct objc_method { SEL _cmd; id (*_imp)(); };
1952  * to:
1953  *      struct objc_method { SEL _cmd; void *_imp; };
1954  */
1955 static tree
1956 build_method_template ()
1957 {
1958   tree _SLT_record;
1959   tree decl_specs, field_decl, field_decl_chain, parms;
1960
1961   _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));
1962
1963 #ifdef OBJC_INT_SELECTORS
1964   /* unsigned int _cmd; */
1965   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
1966   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
1967   field_decl = get_identifier ("_cmd");
1968 #else /* not OBJC_INT_SELECTORS */
1969   /* struct objc_selector *_cmd; */
1970   decl_specs = tree_cons (NULLT,
1971                           xref_tag (RECORD_TYPE,
1972                                     get_identifier (TAG_SELECTOR)),
1973                           NULLT);
1974   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
1975 #endif /* not OBJC_INT_SELECTORS */
1976
1977   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1978   field_decl_chain = field_decl;
1979
1980   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
1981   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
1982   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1983   chainon (field_decl_chain, field_decl);
1984
1985   /* void *_imp; */
1986
1987   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
1988   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
1989   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1990   chainon (field_decl_chain, field_decl);
1991
1992   finish_struct (_SLT_record, field_decl_chain);
1993
1994   return _SLT_record;
1995 }
1996
1997
1998 static tree
1999 generate_dispatch_table (type, name, size, list)
2000      tree type;
2001      char *name;
2002      int size;
2003      tree list;
2004 {
2005   tree sc_spec, decl_specs, decl, initlist;
2006
2007   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2008   decl_specs = tree_cons (NULLT, type, sc_spec);
2009
2010   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
2011
2012   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
2013   initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
2014   initlist = tree_cons (NULLT, list, initlist);
2015
2016   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
2017
2018   return decl;
2019 }
2020
2021 static void
2022 generate_dispatch_tables ()
2023 {
2024   tree initlist, chain, method_list_template;
2025   tree cast, variable_length_type;
2026   int size;
2027
2028   if (!objc_method_template)
2029     objc_method_template = build_method_template ();
2030
2031   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2032                                                             get_identifier (_TAG_METHOD_LIST))), NULLT);
2033   variable_length_type = groktypename (cast);
2034
2035   chain = CLASS_CLS_METHODS (implementation_context);
2036   if (chain)
2037     {
2038       size = 0;
2039       initlist = build_dispatch_table_initializer (chain, &size);
2040
2041       method_list_template = build_method_list_template (objc_method_template,
2042                                                          size);
2043       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2044         _OBJC_CLASS_METHODS_decl = 
2045             generate_dispatch_table (method_list_template,
2046                                      "_OBJC_CLASS_METHODS", 
2047                                      size, initlist);
2048       else
2049         /* we have a category */
2050         _OBJC_CLASS_METHODS_decl = 
2051             generate_dispatch_table (method_list_template,
2052                                      "_OBJC_CATEGORY_CLASS_METHODS", 
2053                                      size, initlist);
2054       /* cast! */
2055       TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type;
2056     }
2057   else
2058     _OBJC_CLASS_METHODS_decl = 0;
2059
2060   chain = CLASS_NST_METHODS (implementation_context);
2061   if (chain)
2062     {
2063       size = 0;
2064       initlist = build_dispatch_table_initializer (chain, &size);
2065
2066       method_list_template = build_method_list_template (objc_method_template,
2067                                                          size);
2068       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2069         _OBJC_INSTANCE_METHODS_decl = 
2070             generate_dispatch_table (method_list_template,
2071                                      "_OBJC_INSTANCE_METHODS", 
2072                                      size, initlist);
2073       else
2074         /* we have a category */
2075         _OBJC_INSTANCE_METHODS_decl = 
2076             generate_dispatch_table (method_list_template,
2077                                      "_OBJC_CATEGORY_INSTANCE_METHODS", 
2078                                      size, initlist);
2079       /* cast! */
2080       TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type;
2081     }
2082   else
2083     _OBJC_INSTANCE_METHODS_decl = 0;
2084 }
2085
2086 static tree
2087 build_category_initializer (cat_name, class_name,
2088                             instance_methods, class_methods)
2089      tree cat_name;
2090      tree class_name;
2091      tree instance_methods;
2092      tree class_methods;
2093 {
2094   tree initlist = NULLT, expr;
2095
2096   initlist = tree_cons (NULLT, cat_name, initlist);
2097   initlist = tree_cons (NULLT, class_name, initlist);
2098
2099   if (!instance_methods)
2100     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2101   else
2102     {
2103       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
2104       initlist = tree_cons (NULLT, expr, initlist);
2105     }
2106   if (!class_methods)
2107     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2108   else
2109     {
2110       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
2111       initlist = tree_cons (NULLT, expr, initlist);
2112     }
2113   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2114 }
2115
2116 /*
2117  *  struct objc_class {
2118  *    struct objc_class *isa;
2119  *    struct objc_class *super_class;
2120  *    char *name;
2121  *    long version;
2122  *    long info;
2123  *    long instance_size;
2124  *    struct objc_ivar_list *ivars;
2125  *    struct objc_method_list *methods;
2126  *    struct objc_cache *cache;
2127  *  };
2128  */
2129 static tree
2130 build_shared_structure_initializer (isa, super, name, size, status,
2131                                     dispatch_table, ivar_list)
2132      tree isa;
2133      tree super;
2134      tree name;
2135      tree size;
2136      int status;
2137      tree dispatch_table;
2138      tree ivar_list;
2139 {
2140   tree initlist = NULLT, expr;
2141
2142   /* isa = */
2143   initlist = tree_cons (NULLT, isa, initlist);
2144
2145   /* super_class = */
2146   initlist = tree_cons (NULLT, super, initlist);
2147
2148   /* name = */
2149   initlist = tree_cons (NULLT, name, initlist);
2150
2151   /* version = */
2152   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2153
2154   /* info = */
2155   initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
2156
2157   /* instance_size = */
2158   initlist = tree_cons (NULLT, size, initlist);
2159
2160   /* objc_ivar_list = */
2161   if (!ivar_list)
2162     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2163   else
2164     {
2165       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
2166       initlist = tree_cons (NULLT, expr, initlist);
2167     }
2168
2169   /* objc_method_list = */
2170   if (!dispatch_table)
2171     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2172   else
2173     {
2174       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
2175       initlist = tree_cons (NULLT, expr, initlist);
2176     }
2177
2178   /* method_cache = */
2179   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2180
2181   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2182 }
2183
2184 /*
2185  * static struct objc_category _OBJC_CATEGORY_<name> = { ... };
2186  */
2187 static void
2188 generate_category (cat)
2189      tree cat;
2190 {
2191   tree sc_spec, decl_specs, decl;
2192   tree initlist, cat_name_expr, class_name_expr;
2193   int offset;
2194
2195   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2196   decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
2197
2198   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"),
2199                      decl_specs, 1);
2200
2201   offset = add_objc_string (CLASS_SUPER_NAME (cat));
2202   cat_name_expr = build_msg_pool_reference (offset);
2203
2204   offset = add_objc_string (CLASS_NAME (cat));
2205   class_name_expr = build_msg_pool_reference (offset);
2206
2207   initlist = build_category_initializer (
2208                                          cat_name_expr, class_name_expr,
2209                                          _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl);
2210
2211   finish_decl (decl, initlist, NULLT);
2212 }
2213
2214 /*
2215  * static struct objc_class _OBJC_METACLASS_Foo={ ... };
2216  * static struct objc_class _OBJC_CLASS_Foo={ ... };
2217  */
2218 static void
2219 generate_shared_structures ()
2220 {
2221   tree sc_spec, decl_specs, expr_decl, decl;
2222   tree name_expr, super_expr, root_expr;
2223   tree my_root_id = NULLT, my_super_id = NULLT;
2224   tree cast_type, initlist;
2225   int offset;
2226
2227   my_super_id = CLASS_SUPER_NAME (implementation_template);
2228   if (my_super_id)
2229     {
2230       add_class_reference (my_super_id);
2231
2232       /* compute "my_root_id" - this is required for code generation.
2233        * the "isa" for all meta class structures points to the root of
2234        * the inheritance hierarchy (e.g. "__Object")...
2235        */
2236       my_root_id = my_super_id;
2237       do
2238         {
2239           tree my_root_int = lookup_interface (my_root_id);
2240
2241           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2242             my_root_id = CLASS_SUPER_NAME (my_root_int);
2243           else
2244             break;
2245         }
2246       while (1);
2247     }
2248   else                          /* no super class */
2249     {
2250       my_root_id = CLASS_NAME (implementation_template);
2251     }
2252
2253   cast_type = groktypename (build_tree_list (build_tree_list (NULLT,
2254                                                               objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT)));
2255
2256   offset = add_objc_string (CLASS_NAME (implementation_template));
2257   name_expr = build_msg_pool_reference (offset);
2258
2259   /* install class `isa' and `super' pointers at runtime */
2260   if (my_super_id)
2261     {
2262       offset = add_objc_string (my_super_id);
2263       super_expr = build_msg_pool_reference (offset);
2264       TREE_TYPE (super_expr) = cast_type; /* cast! */
2265     }
2266   else
2267     super_expr = build_int_2 (0, 0);
2268
2269   offset = add_objc_string (my_root_id);
2270   root_expr = build_msg_pool_reference (offset);
2271   TREE_TYPE (root_expr) = cast_type; /* cast! */
2272
2273   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2274
2275   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
2276   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
2277
2278   decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1);
2279
2280   initlist = build_shared_structure_initializer (
2281                                                  root_expr, super_expr, name_expr,
2282                                                  build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0),
2283                                                  2 /*CLS_META*/,
2284                                                  _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl);
2285
2286   finish_decl (decl, initlist, NULLT);
2287
2288   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2289
2290   decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1);
2291
2292   initlist = build_shared_structure_initializer (
2293                                                  build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0),
2294                                                  super_expr, name_expr,
2295                                                  build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0),
2296                                                  1 /*CLS_FACTORY*/,
2297                                                  _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl);
2298
2299   finish_decl (decl, initlist, NULLT);
2300 }
2301
2302 static tree
2303 synth_id_with_class_suffix (preamble)
2304      char *preamble;
2305 {
2306   char *string;
2307   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2308     {
2309       string = (char *) alloca (strlen (preamble)
2310                                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2311                                 + 3);
2312       sprintf (string, "%s_%s", preamble,
2313                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
2314     }
2315   else
2316     {
2317       /* we have a category */
2318       string = (char *) alloca (strlen (preamble)
2319                                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2320                                 + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
2321                                 + 3);
2322       sprintf (string, "%s_%s_%s", preamble,
2323                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
2324                IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
2325     }
2326   return get_identifier (string);
2327 }
2328
2329 /*
2330  *   usage:
2331  *              keyworddecl:
2332  *                      selector ':' '(' typename ')' identifier
2333  *
2334  *   purpose:
2335  *              transform an Objective-C keyword argument into
2336  *              the C equivalent parameter declarator.
2337  *
2338  *   in:        key_name, an "identifier_node" (optional).
2339  *              arg_type, a  "tree_list" (optional).
2340  *              arg_name, an "identifier_node".
2341  *
2342  *   note:      it would be really nice to strongly type the preceding
2343  *              arguments in the function prototype; however, then i
2344  *              could not use the "accessor" macros defined in "tree.h".
2345  *
2346  *   out:       an instance of "keyword_decl".
2347  *
2348  */
2349
2350 tree
2351 build_keyword_decl (key_name, arg_type, arg_name)
2352      tree key_name;
2353      tree arg_type;
2354      tree arg_name;
2355 {
2356   tree keyword_decl;
2357
2358   /* if no type is specified, default to "id" */
2359   if (arg_type == NULLT)
2360     arg_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2361                                 build1 (INDIRECT_REF, NULLT, NULLT));
2362
2363   keyword_decl = make_node (KEYWORD_DECL);
2364
2365   TREE_TYPE (keyword_decl) = arg_type;
2366   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
2367   KEYWORD_KEY_NAME (keyword_decl) = key_name;
2368
2369   return keyword_decl;
2370 }
2371
2372 /*
2373  *  given a chain of keyword_decl's, synthesize the full keyword selector.
2374  */
2375 static tree
2376 build_keyword_selector (selector)
2377      tree selector;
2378 {
2379   int len = 0;
2380   tree key_chain, key_name;
2381   char *buf;
2382
2383   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2384     {
2385       if (TREE_CODE (selector) == KEYWORD_DECL)
2386         key_name = KEYWORD_KEY_NAME (key_chain);
2387       else if (TREE_CODE (selector) == TREE_LIST)
2388         key_name = TREE_PURPOSE (key_chain);
2389
2390       if (key_name)
2391         len += IDENTIFIER_LENGTH (key_name) + 1;
2392       else                      /* just a ':' arg */
2393         len++;
2394     }
2395   buf = (char *)alloca (len + 1);
2396   bzero (buf, len + 1);
2397
2398   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2399     {
2400       if (TREE_CODE (selector) == KEYWORD_DECL)
2401         key_name = KEYWORD_KEY_NAME (key_chain);
2402       else if (TREE_CODE (selector) == TREE_LIST)
2403         key_name = TREE_PURPOSE (key_chain);
2404
2405       if (key_name)
2406         strcat (buf, IDENTIFIER_POINTER (key_name));
2407       strcat (buf, ":");
2408     }
2409   return get_identifier (buf);
2410 }
2411
2412 /* used for declarations and definitions */
2413
2414 tree
2415 build_method_decl (code, ret_type, selector, add_args)
2416      enum tree_code code;
2417      tree ret_type;
2418      tree selector;
2419      tree add_args;
2420 {
2421   tree method_decl;
2422
2423   /* if no type is specified, default to "id" */
2424   if (ret_type == NULLT)
2425     ret_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2426                                 build1 (INDIRECT_REF, NULLT, NULLT));
2427
2428   method_decl = make_node (code);
2429   TREE_TYPE (method_decl) = ret_type;
2430
2431   /*
2432    *  if we have a keyword selector, create an identifier_node that
2433    *  represents the full selector name (`:' included)...
2434    */
2435   if (TREE_CODE (selector) == KEYWORD_DECL)
2436     {
2437       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
2438       METHOD_SEL_ARGS (method_decl) = selector;
2439       METHOD_ADD_ARGS (method_decl) = add_args;
2440     }
2441   else
2442     {
2443       METHOD_SEL_NAME (method_decl) = selector;
2444       METHOD_SEL_ARGS (method_decl) = NULLT;
2445       METHOD_ADD_ARGS (method_decl) = NULLT;
2446     }
2447
2448   return method_decl;
2449 }
2450
2451 #define METHOD_DEF 0
2452 #define METHOD_REF 1
2453 /* Used by `build_message_expr' and `comp_method_types'.
2454    Return an argument list for method METH.
2455    CONTEXT is either METHOD_DEF or METHOD_REF,
2456     saying whether we are trying to define a method or call one.
2457    SUPERFLAG says this is for a send to super;
2458     this makes a difference for the NeXT calling sequence
2459     in which the lookup and the method call are done together.  */
2460
2461 static tree
2462 get_arg_type_list (meth, context, superflag)
2463      tree meth;
2464      int context;
2465      int superflag;
2466 {
2467   tree arglist, akey;
2468
2469 #ifdef NEXT_OBJC_RUNTIME
2470   /* receiver type */
2471   if (superflag)
2472     {
2473       arglist = build_tree_list (NULLT, super_type);
2474     }
2475   else
2476 #endif
2477     {
2478       if (context == METHOD_DEF)
2479         arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
2480       else
2481         arglist = build_tree_list (NULLT, id_type);
2482     }
2483
2484   /* selector type - will eventually change to `int' */
2485   chainon (arglist, build_tree_list (NULLT, selector_type));
2486
2487   /* build a list of argument types */
2488   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
2489     {
2490       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
2491       chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
2492     }
2493
2494   if (METHOD_ADD_ARGS (meth) == (tree)1)
2495     /*
2496      * we have a `, ...' immediately following the selector,
2497      * finalize the arglist...simulate get_parm_info (0)
2498      */
2499     ;
2500   else if (METHOD_ADD_ARGS (meth))
2501     {
2502       /* we have a variable length selector */
2503       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
2504       chainon (arglist, add_arg_list);
2505     }
2506   else                          /* finalize the arglist...simulate get_parm_info (1) */
2507     chainon (arglist, build_tree_list (NULLT, void_type_node));
2508
2509   return arglist;
2510 }
2511
2512 static tree
2513 check_duplicates (hsh)
2514      hash hsh;
2515 {
2516   tree meth = NULLT;
2517
2518   if (hsh)
2519     {
2520       meth = hsh->key;
2521
2522       if (hsh->list)
2523         {
2524           /* we have two methods with the same name and different types */
2525           attr loop;
2526           char type;
2527
2528           type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
2529
2530           warning ("multiple declarations for method `%s'",
2531                    IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
2532
2533           warn_with_method ("using", type, meth);
2534           for (loop = hsh->list; loop; loop = loop->next)
2535             warn_with_method ("also found", type, loop->value);
2536         }
2537     }
2538   return meth;
2539 }
2540
2541 static tree
2542 receiver_is_class_object (receiver)
2543       tree receiver;
2544 {
2545   /* the receiver is a function call that returns an id...
2546    * ...check if it is a call to objc_getClass, if so, give it
2547    * special treatment.
2548    */
2549   tree exp = TREE_OPERAND (receiver, 0);
2550
2551   if (exp != 0 && (TREE_CODE (exp) == ADDR_EXPR))
2552     {
2553       exp = TREE_OPERAND (exp, 0);
2554       if (exp != 0
2555           && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_getClass_decl)
2556         {
2557           /* we have a call to objc_getClass! */
2558           tree arg = TREE_OPERAND (receiver, 1);
2559
2560           if (arg != 0
2561               && TREE_CODE (arg) == TREE_LIST
2562               && (arg = TREE_VALUE (arg))
2563               && TREE_CODE (arg) == NOP_EXPR
2564               && (arg = TREE_OPERAND (arg, 0))
2565               && TREE_CODE (arg) == ADDR_EXPR
2566               && (arg = TREE_OPERAND (arg, 0))
2567               && TREE_CODE (arg) == STRING_CST)
2568             /* finally, we have the class name */
2569             return get_identifier (TREE_STRING_POINTER (arg));
2570         }
2571     }
2572   return 0;
2573 }
2574 \f
2575 /* If we are currently building a message expr, this holds
2576    the identifier of the selector of the message.  This is
2577    used when printing warnings about argument mismatches. */
2578
2579 static tree building_objc_message_expr = 0;
2580
2581 tree
2582 maybe_building_objc_message_expr ()
2583 {
2584   return building_objc_message_expr;
2585 }
2586
2587 /* Construct an expression for sending a message.
2588    MESS has the object to send to in TREE_PURPOSE
2589    and the argument list (including selector) in TREE_VALUE.  */
2590
2591 tree
2592 build_message_expr (mess)
2593      tree mess;
2594 {
2595   tree receiver = TREE_PURPOSE (mess);
2596   tree selector, self_object;
2597   tree rtype, sel_name;
2598   tree args = TREE_VALUE (mess);
2599   tree method_params = NULLT;
2600   tree method_prototype = NULLT;
2601   int selTransTbl_index;
2602   tree retval;
2603   int statically_typed = 0, statically_allocated = 0;
2604   tree class_ident = 0;
2605
2606   /* 1 if this is sending to the superclass.  */
2607   int super;
2608
2609   if (!doing_objc_thang)
2610     fatal ("Objective-C text in C source file");
2611
2612   if (TREE_CODE (receiver) == ERROR_MARK)
2613     return error_mark_node;
2614
2615   /* determine receiver type */
2616   rtype = TREE_TYPE (receiver);
2617   super = (TREE_TYPE (receiver) == super_type);
2618
2619   if (! super)
2620     {
2621       if (TREE_STATIC_TEMPLATE (rtype))
2622         statically_allocated = 1;
2623       else if (TREE_CODE (rtype) == POINTER_TYPE
2624                && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
2625         statically_typed = 1;
2626       /* classfix -smn */
2627       else if (TREE_CODE (receiver) == CALL_EXPR && rtype == id_type
2628                && (class_ident = receiver_is_class_object (receiver)))
2629         ;
2630       else if (TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (id_type)
2631                && TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (class_type))
2632         {
2633           bzero (errbuf, BUFSIZE);
2634           warning ("invalid receiver type `%s'", gen_declaration (rtype, errbuf));
2635         }
2636       if (statically_allocated)
2637         receiver = build_unary_op (ADDR_EXPR, receiver, 0);
2638
2639       /* Don't evaluate the receiver twice. */
2640       receiver = save_expr (receiver);
2641       self_object = receiver;
2642     }
2643   else
2644     /* If sending to `super', use current self as the object.  */
2645     self_object = self_decl;
2646
2647   /* Obtain the full selector name.  */
2648
2649   if (TREE_CODE (args) == IDENTIFIER_NODE)
2650     /* a unary selector */
2651     sel_name = args;
2652   else if (TREE_CODE (args) == TREE_LIST)
2653     sel_name = build_keyword_selector (args);
2654
2655   selTransTbl_index = add_selector_reference (sel_name);
2656
2657   /* Build the parameters list for looking up the method.
2658      These are the object itself and the selector.  */
2659   
2660 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
2661   selector = build_selector_reference (selTransTbl_index);
2662 #else
2663   selector = build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
2664                               build_int_2 (selTransTbl_index, 0));
2665 #endif
2666
2667   /* Build the parameter list to give to the method.  */
2668
2669   method_params = NULLT;
2670   if (TREE_CODE (args) == TREE_LIST)
2671     {
2672       tree chain = args, prev = NULLT;
2673
2674       /* We have a keyword selector--check for comma expressions.  */
2675       while (chain)
2676         {
2677           tree element = TREE_VALUE (chain);
2678
2679           /* We have a comma expression, must collapse...  */
2680           if (TREE_CODE (element) == TREE_LIST)
2681             {
2682               if (prev)
2683                 TREE_CHAIN (prev) = element;
2684               else
2685                 args = element;
2686             }
2687           prev = chain;
2688           chain = TREE_CHAIN (chain);
2689         }
2690       method_params = args;
2691     }
2692
2693   /* Determine operation return type.  */
2694
2695   if (super_type != 0
2696       && TYPE_MAIN_VARIANT (rtype) == TYPE_MAIN_VARIANT (super_type))
2697     {
2698       tree iface;
2699
2700       if (CLASS_SUPER_NAME (implementation_template))
2701         {
2702           iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
2703     
2704           if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
2705             method_prototype = lookup_instance_method_static (iface, sel_name);
2706           else
2707             method_prototype = lookup_class_method_static (iface, sel_name);
2708     
2709           if (iface && !method_prototype)
2710             warning ("`%s' does not respond to `%s'",
2711                      IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
2712                      IDENTIFIER_POINTER (sel_name));
2713         }
2714       else
2715         {
2716           error ("no super class declared in interface for `%s'",
2717                  IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
2718           return error_mark_node;
2719         }
2720
2721     }
2722   else if (statically_allocated)
2723     {
2724       tree iface = lookup_interface (TYPE_NAME (rtype));
2725
2726       if (iface && !(method_prototype = lookup_instance_method_static (iface, sel_name)))
2727         warning ("`%s' does not respond to `%s'",
2728                  IDENTIFIER_POINTER (TYPE_NAME (rtype)),
2729                  IDENTIFIER_POINTER (sel_name));
2730     }
2731   else if (statically_typed)
2732     {
2733       tree ctype = TREE_TYPE (rtype);
2734
2735       /* `self' is now statically_typed...all methods should be visible
2736        * within the context of the implementation...
2737        */
2738       if (implementation_context
2739           && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
2740         {
2741           method_prototype = lookup_instance_method_static (implementation_template, sel_name);
2742
2743           if (!method_prototype && implementation_template != implementation_context)
2744             /* the method is not published in the interface...check locally */
2745             method_prototype = lookup_method (CLASS_NST_METHODS (implementation_context),
2746                                   sel_name);
2747         }
2748       else
2749         {
2750           tree iface;
2751
2752           if (iface = lookup_interface (TYPE_NAME (ctype)))
2753             method_prototype = lookup_instance_method_static (iface, sel_name);
2754         }
2755
2756       if (!method_prototype)
2757         warning ("`%s' does not respond to `%s'",
2758                  IDENTIFIER_POINTER (TYPE_NAME (ctype)),
2759                  IDENTIFIER_POINTER (sel_name));
2760     }
2761   else if (class_ident)
2762     {
2763       if (implementation_context
2764           && CLASS_NAME (implementation_context) == class_ident)
2765         {
2766           method_prototype
2767             = lookup_class_method_static (implementation_template, sel_name);
2768     
2769           if (!method_prototype
2770               && implementation_template != implementation_context)
2771             /* the method is not published in the interface...check locally */
2772             method_prototype
2773               = lookup_method (CLASS_CLS_METHODS (implementation_context),
2774                                sel_name);
2775         }
2776       else
2777         {
2778           tree iface;
2779     
2780           if (iface = lookup_interface (class_ident))
2781             method_prototype = lookup_class_method_static (iface, sel_name);
2782         }
2783   
2784       if (!method_prototype)
2785         {
2786           warning ("cannot find class (factory) method.");
2787           warning ("return type for `%s' defaults to id",
2788                    IDENTIFIER_POINTER (sel_name));
2789         }
2790     }
2791   else
2792     {
2793       hash hsh;
2794
2795       /* we think we have an instance...loophole: extern id Object; */
2796       hsh = hash_lookup (nst_method_hash_list, sel_name);
2797       if (!hsh)
2798         /* for various loopholes...like sending messages to self in a
2799            factory context... */
2800         hsh = hash_lookup (cls_method_hash_list, sel_name);
2801
2802       method_prototype = check_duplicates (hsh);
2803       if (!method_prototype)
2804         {
2805           warning ("cannot find method.");
2806           warning ("return type for `%s' defaults to id",
2807                    IDENTIFIER_POINTER (sel_name));
2808         }
2809     }
2810
2811   /* Save the selector name for printing error messages.  */
2812   building_objc_message_expr = sel_name;
2813
2814   retval = build_objc_method_call (super, method_prototype,
2815                                    receiver, self_object,
2816                                    selector, method_params);
2817
2818   building_objc_message_expr = 0;
2819
2820   return retval;
2821 }
2822 \f
2823 /* Build a tree expression to send OBJECT the operation SELECTOR,
2824    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
2825    assuming the method has prototype METHOD_PROTOTYPE.
2826    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
2827    Use METHOD_PARAMS as list of args to pass to the method.
2828    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
2829
2830 static tree
2831 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
2832                         selector, method_params)
2833      int super_flag;
2834      tree method_prototype, lookup_object, object, selector, method_params;
2835 {
2836   tree sender = (super_flag ? _msgSuper_decl : _msg_decl);
2837
2838 #ifdef NEXT_OBJC_RUNTIME
2839   if (!method_prototype)
2840     {
2841       method_params = tree_cons (NULLT, lookup_object,
2842                                  tree_cons (NULLT, selector, method_params));
2843       return build_function_call (sender, method_params);
2844     }
2845   else
2846     {
2847       /* This is a real kludge, but it is used only for the Next.
2848          Clobber the data type of SENDER temporarily to accept
2849          all the arguments for this operation, and to return
2850          whatever this operation returns.  */
2851       tree arglist = NULLT;
2852       tree retval;
2853
2854       /* Save the proper contents of SENDER's data type.  */
2855       tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
2856       tree savret = TREE_TYPE (TREE_TYPE (sender));
2857
2858       /* Install this method's argument types.  */
2859       arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
2860       TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
2861
2862       /* Install this method's return type.  */
2863       TREE_TYPE (TREE_TYPE (sender))
2864         = groktypename (TREE_TYPE (method_prototype));
2865
2866       /* Call SENDER with all the parameters.
2867          This will do type checking using the arg types for this method.  */
2868       method_params = tree_cons (NULLT, lookup_object,
2869                                  tree_cons (NULLT, selector, method_params));
2870       retval = build_function_call (sender, method_params);
2871
2872       /* Restore SENDER's return/argument types.  */
2873       TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
2874       TREE_TYPE (TREE_TYPE (sender)) = savret;
2875       return retval;
2876     }
2877 #else /* not NEXT_OBJC_RUNTIME */
2878   /* This is the portable way.
2879      First call the lookup function to get a pointer to the method, 
2880      then cast the pointer, then call it with the method arguments.  */
2881   tree method;
2882
2883   /* Avoid trouble since we may evaluate each of these twice.  */
2884   object = save_expr (object);
2885   selector = save_expr (selector);
2886
2887   method
2888     = build_function_call (sender,
2889                            tree_cons (NULLT, lookup_object,
2890                                       tree_cons (NULLT, selector, NULLT)));
2891
2892   /* If we have a method prototype, construct the data type this method needs,
2893      and cast what we got from SENDER into a pointer to that type.  */
2894   if (method_prototype)
2895     {
2896       tree arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
2897       tree valtype = groktypename (TREE_TYPE (method_prototype));
2898       tree fake_function_type = build_function_type (valtype, arglist);
2899       TREE_TYPE (method) = build_pointer_type (fake_function_type);
2900     }
2901   else
2902     {
2903       TREE_TYPE (method)
2904         = build_pointer_type (build_function_type (ptr_type_node, NULLT));
2905     }
2906   /* Pass the object to the method.  */
2907   return build_function_call (method,
2908                               tree_cons (NULLT, object,
2909                                          tree_cons (NULLT, selector,
2910                                                     method_params)));
2911 #endif /* not NEXT_OBJC_RUNTIME */
2912 }
2913 \f
2914 tree
2915 build_selector_expr (selnamelist)
2916      tree selnamelist;
2917 {
2918   tree selname;
2919   int selTransTbl_index;
2920
2921   if (!doing_objc_thang)
2922     fatal ("Objective-C text in C source file");
2923
2924   /* obtain the full selector name */
2925   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
2926     /* a unary selector */
2927     selname = selnamelist;
2928   else if (TREE_CODE (selnamelist) == TREE_LIST)
2929     selname = build_keyword_selector (selnamelist);
2930
2931   selTransTbl_index = add_selector_reference (selname);
2932
2933 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
2934   return build_selector_reference (selTransTbl_index);
2935 #else
2936   /* synthesize a reference into the selector translation table */
2937   return build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
2938                           build_int_2 (selTransTbl_index, 0));
2939 #endif
2940 }
2941
2942 tree
2943 build_encode_expr (type)
2944      tree type;
2945 {
2946   tree result;
2947   char *string;
2948
2949   if (!doing_objc_thang)
2950     fatal ("Objective-C text in C source file");
2951
2952   encode_type (type, OBJC_ENCODE_INLINE_DEFS);
2953   obstack_1grow (&util_obstack, 0);    /* null terminate string */
2954   string = obstack_finish (&util_obstack);
2955
2956   /* synthesize a string that represents the encoded struct/union */
2957   result = my_build_string (strlen (string) + 1, string);
2958   obstack_free (&util_obstack, util_firstobj);
2959   return result;
2960 }
2961
2962 tree
2963 build_ivar_reference (id)
2964      tree id;
2965 {
2966   if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
2967     TREE_TYPE (self_decl) = instance_type; /* cast */
2968
2969   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
2970 }
2971 \f
2972 #define HASH_ALLOC_LIST_SIZE    170
2973 #define ATTR_ALLOC_LIST_SIZE    170
2974 #define SIZEHASHTABLE           257
2975 #define HASHFUNCTION(key)       ((int)key >> 2)         /* divide by 4 */
2976
2977 static void
2978 hash_init ()
2979 {
2980   nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
2981   cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
2982
2983   if (!nst_method_hash_list || !cls_method_hash_list)
2984     perror ("unable to allocate space in objc-tree.c");
2985   else
2986     {
2987       int i;
2988
2989       for (i = 0; i < SIZEHASHTABLE; i++)
2990         {
2991           nst_method_hash_list[i] = 0;
2992           cls_method_hash_list[i] = 0;
2993         }
2994     }
2995 }
2996
2997 static void
2998 hash_enter (hashlist, method)
2999      hash *hashlist;
3000      tree method;
3001 {
3002   static hash   hash_alloc_list = 0;
3003   static int    hash_alloc_index = 0;
3004   hash obj;
3005   int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
3006
3007   if (!hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
3008     {
3009       hash_alloc_index = 0;
3010       hash_alloc_list = (hash)xmalloc (sizeof (struct hashedEntry) *
3011                                       HASH_ALLOC_LIST_SIZE);
3012       if (!hash_alloc_list)
3013         perror ("unable to allocate in objc-tree.c");
3014     }
3015   obj = &hash_alloc_list[hash_alloc_index++];
3016   obj->list = 0;
3017   obj->next = hashlist[slot];
3018   obj->key = method;
3019
3020   hashlist[slot] = obj;         /* append to front */
3021 }
3022
3023 static hash
3024 hash_lookup (hashlist, sel_name)
3025      hash *hashlist;
3026      tree sel_name;
3027 {
3028   hash target;
3029
3030   target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
3031
3032   while (target)
3033     {
3034       if (sel_name == METHOD_SEL_NAME (target->key))
3035         return target;
3036
3037       target = target->next;
3038     }
3039   return 0;
3040 }
3041
3042 static void
3043 hash_add_attr (entry, value)
3044      hash entry;
3045      tree value;
3046 {
3047   static attr   attr_alloc_list = 0;
3048   static int    attr_alloc_index = 0;
3049   attr obj;
3050
3051   if (!attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
3052     {
3053       attr_alloc_index = 0;
3054       attr_alloc_list = (attr)xmalloc (sizeof (struct hashedAttribute) *
3055                                       ATTR_ALLOC_LIST_SIZE);
3056       if (!attr_alloc_list)
3057         perror ("unable to allocate in objc-tree.c");
3058     }
3059   obj = &attr_alloc_list[attr_alloc_index++];
3060   obj->next = entry->list;
3061   obj->value = value;
3062
3063   entry->list = obj;            /* append to front */
3064 }
3065 \f
3066 static tree
3067 lookup_method (mchain, method)
3068      tree mchain;
3069      tree method;
3070 {
3071   tree key;
3072
3073   if (TREE_CODE (method) == IDENTIFIER_NODE)
3074     key = method;
3075   else
3076     key = METHOD_SEL_NAME (method);
3077
3078   while (mchain)
3079     {
3080       if (METHOD_SEL_NAME (mchain) == key)
3081         return mchain;
3082       mchain = TREE_CHAIN (mchain);
3083     }
3084   return NULLT;
3085 }
3086
3087 static tree
3088 lookup_instance_method_static (interface, ident)
3089      tree interface;
3090      tree ident;
3091 {
3092   tree inter = interface;
3093   tree chain = CLASS_NST_METHODS (inter);
3094   tree meth = NULLT;
3095
3096   do
3097     {
3098       if (meth = lookup_method (chain, ident))
3099         return meth;
3100
3101       if (CLASS_CATEGORY_LIST (inter))
3102         {
3103           tree category = CLASS_CATEGORY_LIST (inter);
3104           chain = CLASS_NST_METHODS (category);
3105     
3106           do 
3107             {
3108               if (meth = lookup_method (chain, ident))
3109                 return meth;
3110       
3111               if (category = CLASS_CATEGORY_LIST (category))
3112                 chain = CLASS_NST_METHODS (category);
3113             }
3114           while (category);
3115         }
3116
3117       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
3118         chain = CLASS_NST_METHODS (inter);
3119     }
3120   while (inter);
3121
3122   return meth;
3123 }
3124
3125 static tree
3126 lookup_class_method_static (interface, ident)
3127      tree interface;
3128      tree ident;
3129 {
3130   tree inter = interface;
3131   tree chain = CLASS_CLS_METHODS (inter);
3132   tree meth = NULLT;
3133
3134   do
3135     {
3136       if (meth = lookup_method (chain, ident))
3137         return meth;
3138
3139       if (CLASS_CATEGORY_LIST (inter))
3140         {
3141           tree category = CLASS_CATEGORY_LIST (inter);
3142           chain = CLASS_CLS_METHODS (category);
3143     
3144           do 
3145             {
3146               if (meth = lookup_method (chain, ident))
3147                 return meth;
3148       
3149               if (category = CLASS_CATEGORY_LIST (category))
3150                 chain = CLASS_CLS_METHODS (category);
3151             }
3152           while (category);
3153         }
3154
3155       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
3156         chain = CLASS_CLS_METHODS (inter);
3157     }
3158   while (inter);
3159
3160   return meth;
3161 }
3162
3163 tree
3164 add_class_method (class, method)
3165      tree class;
3166      tree method;
3167 {
3168   tree mth;
3169   hash hsh;
3170
3171   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
3172     {
3173       /* put method on list in reverse order */
3174       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
3175       CLASS_CLS_METHODS (class) = method;
3176     }
3177   else
3178     {
3179       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3180         error ("duplicate definition of class method `%s'.",
3181                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3182       else
3183         {
3184           /* check types, if different complain */
3185           if (!comp_proto_with_proto (method, mth))
3186             error ("duplicate declaration of class method `%s'.",
3187                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3188         }
3189     }
3190
3191   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
3192     {
3193       /* install on a global chain */
3194       hash_enter (cls_method_hash_list, method);
3195     }
3196   else
3197     {
3198       /* check types, if different add to a list */
3199       if (!comp_proto_with_proto (method, hsh->key))
3200         hash_add_attr (hsh, method);
3201     }
3202   return method;
3203 }
3204 \f
3205 tree
3206 add_instance_method (class, method)
3207      tree class;
3208      tree method;
3209 {
3210   tree mth;
3211   hash hsh;
3212
3213   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
3214     {
3215       /* put method on list in reverse order */
3216       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
3217       CLASS_NST_METHODS (class) = method;
3218     }
3219   else
3220     {
3221       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3222         error ("duplicate definition of instance method `%s'.",
3223                IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3224       else
3225         {
3226           /* check types, if different complain */
3227           if (!comp_proto_with_proto (method, mth))
3228             error ("duplicate declaration of instance method `%s'.",
3229                    IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3230         }
3231     }
3232
3233   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
3234     {
3235       /* install on a global chain */
3236       hash_enter (nst_method_hash_list, method);
3237     }
3238   else
3239     {
3240       /* check types, if different add to a list */
3241       if (!comp_proto_with_proto (method, hsh->key))
3242         hash_add_attr (hsh, method);
3243     }
3244   return method;
3245 }
3246
3247 static tree
3248 add_class (class)
3249      tree class;
3250 {
3251   /* put interfaces on list in reverse order */
3252   TREE_CHAIN (class) = interface_chain;
3253   interface_chain = class;
3254   return interface_chain;
3255 }
3256
3257 static void
3258 add_category (class, category)
3259       tree class;
3260       tree category;
3261 {
3262   /* put categories on list in reverse order */
3263   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
3264   CLASS_CATEGORY_LIST (class) = category;
3265 }
3266
3267 /* called after parsing each instance variable declaration. Necessary to
3268  * preserve typedefs and implement public/private...
3269  */
3270 tree
3271 add_instance_variable (class, public, declarator, declspecs, width)
3272      tree class;
3273      int public;
3274      tree declarator;
3275      tree declspecs;
3276      tree width;
3277 {
3278   tree field_decl, raw_decl;
3279
3280   raw_decl = build_tree_list (declspecs /*purpose*/, declarator/*value*/);
3281
3282   if (CLASS_RAW_IVARS (class))
3283     chainon (CLASS_RAW_IVARS (class), raw_decl);
3284   else
3285     CLASS_RAW_IVARS (class) = raw_decl;
3286
3287   field_decl = grokfield (input_filename, lineno,
3288                           declarator, declspecs, width);
3289
3290   /* overload the public attribute, it is not used for FIELD_DECL's */
3291   if (public)
3292     TREE_PUBLIC (field_decl) = 1;
3293
3294   if (CLASS_IVARS (class))
3295     chainon (CLASS_IVARS (class), field_decl);
3296   else
3297     CLASS_IVARS (class) = field_decl;
3298
3299   return class;
3300 }
3301 \f
3302 tree
3303 is_ivar (decl_chain, ident)
3304      tree decl_chain;
3305      tree ident;
3306 {
3307   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
3308     if (DECL_NAME (decl_chain) == ident)
3309       return decl_chain;
3310   return NULL_TREE;
3311 }
3312
3313 /* we have an instance variable reference, check to see if it is public...*/
3314
3315 int
3316 is_public (expr, identifier)
3317      tree expr;
3318      tree identifier;
3319 {
3320   tree basetype = TREE_TYPE (expr);
3321   enum tree_code code = TREE_CODE (basetype);
3322   tree decl;
3323
3324   if (code == RECORD_TYPE)
3325     {
3326       if (TREE_STATIC_TEMPLATE (basetype))
3327         {
3328           if (decl = is_ivar (TYPE_FIELDS (basetype), identifier))
3329             {
3330               /* important difference between the Stepstone translator:
3331                  
3332                  all instance variables should be public within the context
3333                  of the implementation...
3334                  */
3335               if (implementation_context)
3336                 {
3337                   if ((TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE
3338                        && CLASS_NAME (implementation_context) == TYPE_NAME (basetype))
3339                       || (TREE_CODE (implementation_context) == CATEGORY_TYPE
3340                           && CLASS_NAME (implementation_context) == TYPE_NAME (basetype)))
3341                     return 1;
3342                 }
3343
3344               if (TREE_PUBLIC (decl))
3345                 return 1;
3346
3347               error ("instance variable `%s' is declared private",
3348                      IDENTIFIER_POINTER (identifier));
3349               return 0;
3350             }
3351         }
3352       else if (implementation_context && (basetype == objc_object_reference))
3353         {
3354           TREE_TYPE (expr) = _PRIVATE_record;
3355           if (extra_warnings)
3356             {
3357               warning ("static access to object of type `id'");
3358               warning ("please change to type `%s *'",
3359                        IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
3360             }
3361         }
3362     }
3363   return 1;
3364 }
3365
3366 /* implement @defs (<classname>) within struct bodies. */
3367
3368 tree
3369 get_class_ivars (interface)
3370      tree interface;
3371 {
3372   if (!doing_objc_thang)
3373     fatal ("Objective-C text in C source file");
3374
3375   return build_ivar_chain (interface);
3376 }
3377
3378 tree
3379 get_class_reference (interface)
3380      tree interface;
3381 {
3382   tree params;
3383
3384   add_class_reference (CLASS_NAME (interface));
3385
3386   params = build_tree_list (NULLT,
3387                             my_build_string (IDENTIFIER_LENGTH (CLASS_NAME (interface)) + 1,
3388                                              IDENTIFIER_POINTER (CLASS_NAME (interface))));
3389
3390   return build_function_call (objc_getClass_decl, params);
3391 }
3392 \f
3393 /* make sure all entries in "chain" are also in "list" */
3394
3395 static void
3396 check_methods (chain, list, mtype)
3397      tree chain;
3398      tree list;
3399      int mtype;
3400 {
3401   int first = 1;
3402
3403   while (chain)
3404     {
3405       if (!lookup_method (list, chain))
3406         {
3407           if (first)
3408             {
3409               if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
3410                 warning ("incomplete implementation of class `%s'",
3411                          IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
3412               else if (TREE_CODE (implementation_context) == CATEGORY_TYPE)
3413                 warning ("incomplete implementation of category `%s'",
3414                          IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
3415               first = 0;
3416             }
3417           warning ("method definition for `%c%s' not found",
3418                    mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
3419         }
3420       chain = TREE_CHAIN (chain);
3421     }
3422 }
3423 \f
3424 /* Make sure that the class CLASS_NAME is defined
3425    CODE says which kind of thing CLASS_NAME ought to be.
3426    It can be INTERFACE_TYPE, IMPLEMENTATION_TYPE, PROTOCOL_TYPE
3427    or CATEGORY_TYPE.
3428
3429    If CODE is INTERFACE_TYPE, we also do a push_obstacks_nochange
3430    whose matching pop is in continue_class.  */
3431
3432 tree
3433 start_class (code, class_name, super_name)
3434      enum tree_code code;
3435      tree class_name;
3436      tree super_name;
3437 {
3438   tree class;
3439
3440   if (code == INTERFACE_TYPE)
3441     {
3442       push_obstacks_nochange ();
3443       end_temporary_allocation ();
3444     }
3445
3446   if (!doing_objc_thang)
3447     fatal ("Objective-C text in C source file");
3448
3449   class = make_node (code);
3450
3451   CLASS_NAME (class) = class_name;
3452   CLASS_SUPER_NAME (class) = super_name;
3453   CLASS_CLS_METHODS (class) = NULL_TREE;
3454
3455   if (code == IMPLEMENTATION_TYPE)
3456     {
3457       /* pre-build the following entities - for speed/convenience. */
3458       if (!self_id)
3459         self_id = get_identifier ("self");
3460       if (!_cmd_id)
3461         _cmd_id = get_identifier ("_cmd");
3462
3463       if (!objc_super_template)
3464         objc_super_template = build_super_template ();
3465
3466       method_slot = 0;          /* reset for multiple classes per file */
3467
3468       implementation_context = class;
3469
3470       /* lookup the interface for this implementation. */
3471
3472       if (!(implementation_template = lookup_interface (class_name)))
3473         {
3474           warning ("Cannot find interface declaration for `%s'",
3475                    IDENTIFIER_POINTER (class_name));
3476           add_class (implementation_template = implementation_context);
3477         }
3478
3479       /* if a super class has been specified in the implementation,
3480          insure it conforms to the one specified in the interface */
3481
3482       if (super_name
3483           && (super_name != CLASS_SUPER_NAME (implementation_template)))
3484         {
3485           error ("conflicting super class name `%s'",
3486                  IDENTIFIER_POINTER (super_name));
3487           error ("previous declaration of `%s'",
3488                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
3489         }
3490     }
3491   else if (code == INTERFACE_TYPE)
3492     {
3493       if (lookup_interface (class_name))
3494         warning ("duplicate interface declaration for class `%s'",
3495                  IDENTIFIER_POINTER (class_name));
3496       else
3497         add_class (class);
3498     }
3499   else if (code == PROTOCOL_TYPE)
3500     {
3501       tree class_category_is_assoc_with;
3502
3503       /* for a category, class_name is really the name of the class that
3504          the following set of methods will be associated with...we must
3505          find the interface so that can derive the objects template */
3506
3507       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
3508         {
3509           error ("Cannot find interface declaration for `%s'",
3510                  IDENTIFIER_POINTER (class_name));
3511           exit (1);
3512         }
3513       else
3514         add_category (class_category_is_assoc_with, class);
3515     }
3516   else if (code == CATEGORY_TYPE)
3517     {
3518       /* pre-build the following entities - for speed/convenience. */
3519       if (!self_id)
3520         self_id = get_identifier ("self");
3521       if (!_cmd_id)
3522         _cmd_id = get_identifier ("_cmd");
3523
3524       if (!objc_super_template)
3525         objc_super_template = build_super_template ();
3526
3527       method_slot = 0;          /* reset for multiple classes per file */
3528
3529       implementation_context = class;
3530
3531       /* for a category, class_name is really the name of the class that
3532          the following set of methods will be associated with...we must
3533          find the interface so that can derive the objects template */
3534
3535       if (!(implementation_template = lookup_interface (class_name)))
3536         {
3537           error ("Cannot find interface declaration for `%s'",
3538                  IDENTIFIER_POINTER (class_name));
3539           exit (1);
3540         }
3541     }
3542   return class;
3543 }
3544
3545 tree
3546 continue_class (class)
3547      tree class;
3548 {
3549   if (TREE_CODE (class) == IMPLEMENTATION_TYPE
3550       || TREE_CODE (class) == CATEGORY_TYPE)
3551     {
3552       struct imp_entry *impEntry;
3553       tree ivar_context;
3554
3555       /* check consistency of the instance variables. */
3556
3557       if (CLASS_IVARS (class))
3558         check_ivars (implementation_template, class);
3559
3560       /* code generation */
3561
3562       ivar_context = build_private_template (implementation_template);
3563
3564       if (!objc_class_template)
3565         build_class_template ();
3566
3567       if (!(impEntry = (struct imp_entry *)xmalloc (sizeof (struct imp_entry))))
3568         perror ("unable to allocate in objc-tree.c");
3569
3570       impEntry->next = imp_list;
3571       impEntry->imp_context = class;
3572       impEntry->imp_template = implementation_template;
3573
3574       synth_forward_declarations ();
3575       impEntry->class_decl = _OBJC_CLASS_decl;
3576       impEntry->meta_decl = _OBJC_METACLASS_decl;
3577
3578       /* append to front and increment count */
3579       imp_list = impEntry;
3580       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3581         imp_count++;
3582       else
3583         cat_count++;
3584
3585       return ivar_context;
3586     }
3587   else if (TREE_CODE (class) == INTERFACE_TYPE)
3588     {
3589       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
3590
3591       if (!TYPE_FIELDS (record))
3592         {
3593           finish_struct (record, build_ivar_chain (class));
3594           CLASS_STATIC_TEMPLATE (class) = record;
3595
3596           /* mark this record as a class template - for static typing */
3597           TREE_STATIC_TEMPLATE (record) = 1;
3598         }
3599       return NULLT;
3600     }
3601   else
3602     return error_mark_node;
3603 }
3604
3605 /*
3606  * this is called once we see the "@end" in an interface/implementation.
3607  */
3608 void
3609 finish_class (class)
3610      tree class;
3611 {
3612   if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3613     {
3614       /* all code generation is done in finish_objc */
3615
3616       if (implementation_template != implementation_context)
3617         {
3618           /* ensure that all method listed in the interface contain bodies! */
3619           check_methods (CLASS_CLS_METHODS (implementation_template),
3620                          CLASS_CLS_METHODS (implementation_context), '+');
3621           check_methods (CLASS_NST_METHODS (implementation_template),
3622                          CLASS_NST_METHODS (implementation_context), '-');
3623         }
3624     }
3625   else if (TREE_CODE (class) == CATEGORY_TYPE)
3626     {
3627       tree category = CLASS_CATEGORY_LIST (implementation_template);
3628   
3629       /* find the category interface from the class it is associated with */
3630       while (category)
3631         {
3632           if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
3633             break;
3634           category = CLASS_CATEGORY_LIST (category);
3635         }
3636   
3637       if (category)
3638         {
3639           /* ensure that all method listed in the interface contain bodies! */
3640           check_methods (CLASS_CLS_METHODS (category),
3641                          CLASS_CLS_METHODS (implementation_context), '+');
3642           check_methods (CLASS_NST_METHODS (category),
3643                          CLASS_NST_METHODS (implementation_context), '-');
3644         }
3645     } 
3646   else if (TREE_CODE (class) == INTERFACE_TYPE)
3647     {
3648       tree decl_specs;
3649       char *string = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (class))) + 3);
3650
3651       /* extern struct objc_object *_<my_name>; */
3652
3653       sprintf (string, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
3654
3655       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
3656       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
3657       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
3658                    decl_specs);
3659     }
3660 }
3661 \f
3662 /* "Encode" a data type into a string, whichg rows  in util_obstack.
3663    ??? What is the FORMAT?  Someone please document this!  */
3664
3665 /* Encode a pointer type.  */
3666
3667 static void
3668 encode_pointer (type, format)
3669      tree type;
3670      int format;
3671 {
3672   tree pointer_to = TREE_TYPE (type);
3673
3674   if (TREE_CODE (pointer_to) == RECORD_TYPE)
3675     {
3676       if (TYPE_NAME (pointer_to)
3677           && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
3678         {
3679           char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
3680
3681           if ((strcmp (name, TAG_OBJECT) == 0) /* '@' */
3682               || TREE_STATIC_TEMPLATE (pointer_to))
3683             {
3684               obstack_1grow (&util_obstack, '@');
3685               return;
3686             }
3687           else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
3688             {
3689               obstack_1grow (&util_obstack, '#');
3690               return;
3691             }
3692 #ifndef OBJC_INT_SELECTORS
3693           else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
3694             {
3695               obstack_1grow (&util_obstack, ':');
3696               return;
3697             }
3698 #endif /* OBJC_INT_SELECTORS */
3699         }
3700     }
3701   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
3702            && TYPE_MODE (pointer_to) == QImode)
3703     {
3704       obstack_1grow (&util_obstack, '*');
3705       return;
3706     }
3707
3708   /* we have a type that does not get special treatment... */
3709
3710   /* NeXT extension */
3711   obstack_1grow (&util_obstack, '^');
3712   encode_type (pointer_to, format);
3713 }
3714
3715 static void
3716 encode_array (type, format)
3717      tree type;
3718      int format;
3719 {
3720   tree anIntCst = TYPE_SIZE (type);
3721   tree array_of = TREE_TYPE (type);
3722   char buffer[40];
3723
3724   /* An incomplete array is treated like a pointer.  */
3725   if (anIntCst == NULL)
3726     {
3727       /* split for obvious reasons.  North-Keys 30 Mar 1991 */
3728       encode_pointer (type, format);
3729       return;
3730     }
3731   
3732   sprintf (buffer, "[%d",
3733            TREE_INT_CST_LOW (anIntCst)
3734            / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
3735   obstack_grow (&util_obstack, buffer, strlen (buffer));
3736   encode_type (array_of, format);
3737   obstack_1grow (&util_obstack, ']');
3738   return;
3739 }
3740 \f
3741 static void
3742 encode_aggregate (type, format)
3743      tree type;
3744      int format;
3745 {
3746   enum tree_code code = TREE_CODE (type);
3747
3748   switch (code)
3749     {
3750     case RECORD_TYPE:
3751       {
3752         int have_pointer = 0;
3753
3754         if (obstack_object_size (&util_obstack) > 0     
3755             && *(obstack_next_free (&util_obstack)-1) == '^')
3756           have_pointer = 1;
3757
3758         obstack_1grow (&util_obstack, '{');
3759         if (TYPE_NAME (type))
3760           {
3761             if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3762               {
3763                 obstack_grow (&util_obstack,
3764                               IDENTIFIER_POINTER (TYPE_NAME (type)),
3765                               strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3766               }
3767             else /* we have an untagged structure or a typedef */
3768               {
3769                 obstack_1grow (&util_obstack, '?');
3770               }
3771           }
3772         
3773         if (have_pointer
3774             || format == OBJC_ENCODE_DONT_INLINE_DEFS)
3775           {
3776             /* we have a pointer
3777                or we don't want the details.  */
3778             obstack_1grow (&util_obstack, '}');
3779           }
3780         else
3781           {
3782             tree fields = TYPE_FIELDS (type);
3783             obstack_1grow (&util_obstack, '=');
3784             for ( ; fields; fields = TREE_CHAIN (fields))
3785               encode_field_decl (fields, format);
3786             obstack_1grow (&util_obstack, '}');
3787           }
3788         break;
3789       }
3790
3791     case UNION_TYPE:
3792       {
3793         int have_pointer = 0;
3794
3795         if (obstack_object_size (&util_obstack) > 0     
3796             && *(obstack_next_free (&util_obstack)-1) == '^')
3797           have_pointer = 1;
3798
3799         obstack_1grow (&util_obstack, '(');
3800         if (have_pointer && TYPE_NAME (type))
3801           {
3802             if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3803               {
3804                 obstack_grow (&util_obstack,
3805                               IDENTIFIER_POINTER (TYPE_NAME (type)),
3806                               strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3807               }
3808             else /* we have an untagged structure or a typedef */
3809               {
3810                 obstack_1grow (&util_obstack, '?');
3811               }
3812           }
3813         
3814         if (have_pointer
3815             || format == OBJC_ENCODE_DONT_INLINE_DEFS)
3816           {
3817             /* we have a pointer
3818                or we don't want the details.  */
3819             obstack_1grow (&util_obstack, ')');
3820           }
3821         else
3822           {
3823             tree fields = TYPE_FIELDS (type);
3824             for ( ; fields; fields = TREE_CHAIN (fields))
3825               encode_field_decl (fields, format);
3826             obstack_1grow (&util_obstack, ')');
3827           }
3828         break;
3829       }
3830
3831
3832     case ENUMERAL_TYPE:
3833       obstack_1grow (&util_obstack, 'i');
3834       break;
3835     }
3836 }
3837
3838 /*
3839  *  support bitfields, the current version of Objective-C does not support
3840  *  them. the string will consist of one or more "b:n"'s where n is an
3841  *  integer describing the width of the bitfield. Currently, classes in
3842  *  the kit implement a method "-(char *)describeBitfieldStruct:" that
3843  *  simulates this...if they do not implement this method, the archiver
3844  *  assumes the bitfield is 16 bits wide (padded if necessary) and packed
3845  *  according to the GNU compiler. After looking at the "kit", it appears
3846  *  that all classes currently rely on this default behavior, rather than
3847  *  hand generating this string (which is tedious).
3848  */
3849 static void
3850 encode_bitfield (width, format)
3851      int width;
3852      int format;
3853 {
3854   char buffer[40];
3855   sprintf (buffer, "b%d", width);
3856   obstack_grow (&util_obstack, buffer, strlen (buffer));
3857 }
3858 \f
3859 /*
3860  *      format will be:
3861  *
3862  *      OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
3863  */
3864 static void
3865 encode_type (type, format)
3866      tree type;
3867      int format;
3868 {
3869   enum tree_code code = TREE_CODE (type);
3870
3871   if (code == INTEGER_TYPE)
3872     {
3873       if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0)
3874         {
3875           /* unsigned integer types */
3876
3877           if (TYPE_MODE (type) == QImode) /* 'C' */
3878             obstack_1grow (&util_obstack, 'C');
3879           else if (TYPE_MODE (type) == HImode) /* 'S' */
3880             obstack_1grow (&util_obstack, 'S');
3881           else if (TYPE_MODE (type) == SImode)
3882             {
3883               if (type == long_unsigned_type_node)
3884                 obstack_1grow (&util_obstack, 'L'); /* 'L' */
3885               else
3886                 obstack_1grow (&util_obstack, 'I'); /* 'I' */
3887             }
3888         }
3889       else                      /* signed integer types */
3890         {
3891           if (TYPE_MODE (type) == QImode) /* 'c' */
3892             obstack_1grow (&util_obstack, 'c');
3893           else if (TYPE_MODE (type) == HImode) /* 's' */
3894             obstack_1grow (&util_obstack, 's');
3895           else if (TYPE_MODE (type) == SImode) /* 'i' */
3896             {
3897               if (type == long_integer_type_node)
3898                 obstack_1grow (&util_obstack, 'l'); /* 'l' */
3899               else
3900                 obstack_1grow (&util_obstack, 'i'); /* 'i' */
3901             }
3902         }
3903     }
3904   else if (code == REAL_TYPE)
3905     {
3906       /* floating point types */
3907
3908       if (TYPE_MODE (type) == SFmode) /* 'f' */
3909         obstack_1grow (&util_obstack, 'f');
3910       else if (TYPE_MODE (type) == DFmode
3911                || TYPE_MODE (type) == TFmode) /* 'd' */
3912         obstack_1grow (&util_obstack, 'd');
3913     }
3914
3915   else if (code == VOID_TYPE)   /* 'v' */
3916     obstack_1grow (&util_obstack, 'v');
3917
3918   else if (code == ARRAY_TYPE)
3919     encode_array (type, format);
3920
3921   else if (code == POINTER_TYPE)
3922     encode_pointer (type, format);
3923
3924   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
3925     encode_aggregate (type, format);
3926
3927   else if (code == FUNCTION_TYPE) /* '?' */
3928     obstack_1grow (&util_obstack, '?');
3929 }
3930
3931 static void
3932 encode_field_decl (field_decl, format)
3933      tree field_decl;
3934      int format;
3935 {
3936   if (DECL_BIT_FIELD (field_decl))
3937     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
3938   else
3939     encode_type (TREE_TYPE (field_decl), format);
3940 }
3941
3942 static tree
3943 expr_last (complex_expr)
3944      tree complex_expr;
3945 {
3946   tree next;
3947
3948   if (complex_expr)
3949     while (next = TREE_OPERAND (complex_expr, 0))
3950       complex_expr = next;
3951   return complex_expr;
3952 }
3953 \f
3954 /* The selector of the current method,
3955    or NULL if we aren't compiling a method.  */
3956
3957 tree
3958 maybe_objc_method_name (decl)
3959       tree decl;
3960 {
3961   if (method_context)
3962     return METHOD_SEL_NAME (method_context);
3963   else
3964     return 0;
3965 }
3966
3967 /*
3968  *  Transform a method definition into a function definition as follows:
3969  *
3970  *  - synthesize the first two arguments, "self" and "_cmd".
3971  */
3972
3973 void
3974 start_method_def (method)
3975      tree method;
3976 {
3977   tree decl_specs;
3978
3979   /* required to implement _msgSuper () */
3980   method_context = method;
3981   _OBJC_SUPER_decl = NULLT;
3982
3983   pushlevel (0);                /* must be called BEFORE "start_function ()" */
3984
3985   /* generate prototype declarations for arguments..."new-style" */
3986
3987   if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
3988     decl_specs = build_tree_list (NULLT, _PRIVATE_record);
3989   else
3990     /* really a `struct objc_class *'...however we allow people to
3991        assign to self...which changes its type midstream.
3992        */
3993     decl_specs = build_tree_list (NULLT, objc_object_reference);
3994
3995   push_parm_decl (build_tree_list (decl_specs,
3996                                    build1 (INDIRECT_REF, NULLT, self_id)));
3997
3998 #ifdef OBJC_INT_SELECTORS
3999   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
4000   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
4001   push_parm_decl (build_tree_list (decl_specs, _cmd_id));
4002 #else /* not OBJC_INT_SELECTORS */
4003   decl_specs = build_tree_list (NULLT,
4004                                 xref_tag (RECORD_TYPE,
4005                                           get_identifier (TAG_SELECTOR)));
4006   push_parm_decl (build_tree_list (decl_specs, 
4007                                    build1 (INDIRECT_REF, NULLT, _cmd_id)));
4008 #endif /* not OBJC_INT_SELECTORS */
4009
4010   /* generate argument declarations if a keyword_decl */
4011   if (METHOD_SEL_ARGS (method))
4012     {
4013       tree arglist = METHOD_SEL_ARGS (method);
4014       do
4015         {
4016           tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
4017           tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
4018
4019           if (arg_decl)
4020             {
4021               tree last_expr = expr_last (arg_decl);
4022
4023               /* unite the abstract decl with its name */
4024               TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
4025               push_parm_decl (build_tree_list (arg_spec, arg_decl));
4026               /* unhook...restore the abstract declarator */
4027               TREE_OPERAND (last_expr, 0) = NULLT;
4028             }
4029           else
4030             push_parm_decl (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)));
4031
4032           arglist = TREE_CHAIN (arglist);
4033         }
4034       while (arglist);
4035     }
4036
4037   if (METHOD_ADD_ARGS (method) > (tree)1)
4038     {
4039       /* we have a variable length selector - in "prototype" format */
4040       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
4041       while (akey)
4042         {
4043           /* this must be done prior to calling pushdecl (). pushdecl () is
4044            * going to change our chain on us...
4045            */
4046           tree nextkey = TREE_CHAIN (akey);
4047           pushdecl (akey);
4048           akey = nextkey;
4049         }
4050     }
4051 }
4052
4053 static void
4054 error_with_method (message, mtype, method)
4055      char *message;
4056      char mtype;
4057      tree method;
4058 {
4059   count_error (0);
4060   fprintf (stderr, "%s:%d: ",
4061            DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4062   bzero (errbuf, BUFSIZE);
4063   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4064 }
4065
4066 static void
4067 warn_with_method (message, mtype, method)
4068      char *message;
4069      char mtype;
4070      tree method;
4071 {
4072   count_error (1);
4073   fprintf (stderr, "%s:%d: ",
4074            DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4075   bzero (errbuf, BUFSIZE);
4076   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4077 }
4078
4079 /* return 1 if `method' is consistent with `proto' */
4080
4081 static int
4082 comp_method_with_proto (method, proto)
4083      tree method, proto;
4084 {
4085   static tree function_type = 0;
4086
4087   /* create a function_type node once */
4088   if (!function_type)
4089     {
4090       struct obstack *ambient_obstack = current_obstack;
4091       
4092       current_obstack = &permanent_obstack;
4093       function_type = make_node (FUNCTION_TYPE);
4094       current_obstack = ambient_obstack;
4095     }
4096
4097   /* install argument types - normally set by "build_function_type ()". */
4098   TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
4099
4100   /* install return type */
4101   TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
4102
4103   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
4104 }
4105
4106 /* return 1 if `proto1' is consistent with `proto2' */
4107
4108 static int
4109 comp_proto_with_proto (proto1, proto2)
4110      tree proto1, proto2;
4111 {
4112   static tree function_type1 = 0, function_type2 = 0;
4113
4114   /* create a couple function_type node's once */
4115   if (!function_type1)
4116     {
4117       struct obstack *ambient_obstack = current_obstack;
4118       
4119       current_obstack = &permanent_obstack;
4120       function_type1 = make_node (FUNCTION_TYPE);
4121       function_type2 = make_node (FUNCTION_TYPE);
4122       current_obstack = ambient_obstack;
4123     }
4124
4125   /* install argument types - normally set by "build_function_type ()". */
4126   TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
4127   TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
4128
4129   /* install return type */
4130   TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
4131   TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
4132
4133   return comptypes (function_type1, function_type2);
4134 }
4135
4136 /*
4137  *  - generate an identifier for the function. the format is "_n_cls",
4138  *    where 1 <= n <= nMethods, and cls is the name the implementation we
4139  *    are processing.
4140  *  - install the return type from the method declaration.
4141  *  - if we have a prototype, check for type consistency.
4142  */
4143 static void
4144 really_start_method (method, parmlist)
4145      tree method, parmlist;
4146 {
4147   tree sc_spec, ret_spec, ret_decl, decl_specs;
4148   tree method_decl, method_id;
4149   char *buf;
4150
4151   /* synth the storage class & assemble the return type */
4152   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
4153   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
4154   decl_specs = chainon (sc_spec, ret_spec);
4155
4156   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4157     {
4158       /* Make sure this is big enough for any plausible method label.  */
4159       buf = (char *) alloca (50
4160                              + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4161                              + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
4162 #ifdef OBJC_GEN_METHOD_LABEL
4163       OBJC_GEN_METHOD_LABEL (buf,
4164                              TREE_CODE (method) == INSTANCE_METHOD_DECL,
4165                              IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4166                              NULL,
4167                              IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4168 #else
4169       sprintf (buf, "_%d_%s", ++method_slot,
4170                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
4171 #endif
4172     }
4173   else                          /* we have a category */
4174     {
4175       /* Make sure this is big enough for any plausible method label.  */
4176       buf = (char *) alloca (50
4177                              + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4178                              + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
4179                              + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
4180 #ifdef OBJC_GEN_METHOD_LABEL
4181       OBJC_GEN_METHOD_LABEL (buf,
4182                              TREE_CODE (method) == INSTANCE_METHOD_DECL,
4183                              IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4184                              IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)),
4185                              IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4186 #else
4187       sprintf (buf, "_%d_%s_%s", ++method_slot,
4188                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4189                IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
4190 #endif
4191     }
4192
4193   method_id = get_identifier (buf);
4194
4195   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
4196
4197   /* check the declarator portion of the return type for the method */
4198   if (ret_decl = TREE_VALUE (TREE_TYPE (method)))
4199     {
4200       /*
4201        * unite the complex decl (specified in the abstract decl) with the
4202        * function decl just synthesized...(int *), (int (*)()), (int (*)[]).
4203        */
4204       tree save_expr = expr_last (ret_decl);
4205
4206       TREE_OPERAND (save_expr, 0) = method_decl;
4207       method_decl = ret_decl;
4208       /* fool the parser into thinking it is starting a function */
4209       start_function (decl_specs, method_decl, 0);
4210       /* unhook...this has the effect of restoring the abstract declarator */
4211       TREE_OPERAND (save_expr, 0) = NULLT;
4212     }
4213   else
4214     {
4215       TREE_VALUE (TREE_TYPE (method)) = method_decl;
4216       /* fool the parser into thinking it is starting a function */
4217       start_function (decl_specs, method_decl, 0);
4218       /* unhook...this has the effect of restoring the abstract declarator */
4219       TREE_VALUE (TREE_TYPE (method)) = NULLT;
4220     }
4221
4222   METHOD_DEFINITION (method) = current_function_decl;
4223
4224   /* check consistency...start_function (), pushdecl (), duplicate_decls (). */
4225
4226   if (implementation_template != implementation_context)
4227     {
4228       tree chain, proto;
4229
4230       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4231         chain = CLASS_NST_METHODS (implementation_template);
4232       else
4233         chain = CLASS_CLS_METHODS (implementation_template);
4234
4235       if (proto = lookup_method (chain, METHOD_SEL_NAME (method)))
4236         {
4237           if (!comp_method_with_proto (method, proto))
4238             {
4239               fprintf (stderr, "%s: In method `%s'\n", input_filename,
4240                        IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4241               if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4242                 {
4243                   error_with_method ("conflicting types for", '-', method);
4244                   error_with_method ("previous declaration of", '-', proto);
4245                 }
4246               else
4247                 {
4248                   error_with_method ("conflicting types for", '+', method);
4249                   error_with_method ("previous declaration of", '+', proto);
4250                 }
4251             }
4252         }
4253     }
4254 }
4255
4256 /*
4257  * the following routine is always called...this "architecture" is to
4258  * accommodate "old-style" variable length selectors.
4259  *
4260  *      - a:a b:b // prototype  ; id c; id d; // old-style
4261  */
4262 void
4263 continue_method_def ()
4264 {
4265   tree parmlist;
4266
4267   if (METHOD_ADD_ARGS (method_context) == (tree)1)
4268     /*
4269      * we have a `, ...' immediately following the selector.
4270      */
4271     parmlist = get_parm_info (0);
4272   else
4273     parmlist = get_parm_info (1); /* place a `void_at_end' */
4274
4275   /* set self_decl from the first argument...this global is used by
4276    * build_ivar_reference ().build_indirect_ref ().
4277    */
4278   self_decl = TREE_PURPOSE (parmlist);
4279
4280   poplevel (0, 0, 0);           /* must be called BEFORE "start_function ()" */
4281
4282   really_start_method (method_context, parmlist);
4283
4284   store_parm_decls ();          /* must be called AFTER "start_function ()" */
4285 }
4286
4287 void
4288 add_objc_decls ()
4289 {
4290   if (!_OBJC_SUPER_decl)
4291     _OBJC_SUPER_decl = start_decl (get_identifier (_TAG_SUPER),
4292                                    build_tree_list (NULLT, objc_super_template), 0);
4293
4294   /* this prevents `unused variable' warnings when compiling with `-Wall' */
4295   DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1;
4296 }
4297
4298 /*
4299  *      _n_Method (id self, SEL sel, ...)
4300  *      {
4301  *              struct objc_super _S;
4302  *
4303  *              _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
4304  *      }
4305  */
4306 tree
4307 get_super_receiver ()
4308 {
4309   if (method_context)
4310     {
4311       tree super_expr, super_expr_list;
4312
4313       /* set receiver to self */
4314       super_expr = build_component_ref (_OBJC_SUPER_decl, self_id);
4315       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
4316       super_expr_list = build_tree_list (NULLT, super_expr);
4317
4318       /* set class to begin searching */
4319       super_expr = build_component_ref (_OBJC_SUPER_decl, get_identifier ("class"));
4320
4321       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4322         {
4323           /* [_cls, __cls]Super are "pre-built" in synth_foward_declarations () */
4324
4325           if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4326             super_expr = build_modify_expr (super_expr, NOP_EXPR, _clsSuper_ref);
4327           else
4328             super_expr = build_modify_expr (super_expr, NOP_EXPR, __clsSuper_ref);
4329         }
4330       else                      /* we have a category... */
4331         {
4332           tree params, super_name = CLASS_SUPER_NAME (implementation_template);
4333           tree funcCall;
4334
4335           if (!super_name)  /* Barf if super used in a category of Object. */
4336             {
4337               error("no super class declared in interface for `%s'",
4338                     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4339               return error_mark_node;
4340             }
4341
4342           add_class_reference (super_name);
4343
4344           params = build_tree_list (NULLT,
4345                                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
4346                                                      IDENTIFIER_POINTER (super_name)));
4347
4348           if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4349             funcCall = build_function_call (objc_getClass_decl, params);
4350           else
4351             funcCall = build_function_call (objc_getMetaClass_decl, params);
4352
4353           /* cast! */
4354           TREE_TYPE (funcCall) = TREE_TYPE (_clsSuper_ref);
4355           super_expr = build_modify_expr (super_expr, NOP_EXPR, funcCall);
4356         }
4357       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4358
4359       super_expr = build_unary_op (ADDR_EXPR, _OBJC_SUPER_decl, 0);
4360       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4361
4362       return build_compound_expr (super_expr_list);
4363     }
4364   else
4365     {
4366       error ("[super ...] must appear in a method context");
4367       return error_mark_node;
4368     }
4369 }
4370
4371 static tree
4372 encode_method_def (func_decl)
4373       tree func_decl;
4374 {
4375   tree parms;
4376   int stack_size = 0;
4377   char buffer[40];
4378   tree result;
4379
4380   /* return type */
4381   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
4382                OBJC_ENCODE_DONT_INLINE_DEFS);
4383   /* stack size */
4384   for (parms = DECL_ARGUMENTS (func_decl); parms;
4385        parms = TREE_CHAIN (parms))
4386     stack_size += TREE_INT_CST_LOW (TYPE_SIZE (DECL_ARG_TYPE (parms)))
4387                   / BITS_PER_UNIT;
4388
4389   sprintf (buffer, "%d", stack_size);
4390   obstack_grow (&util_obstack, buffer, strlen (buffer));
4391
4392   /* argument types */
4393   for (parms = DECL_ARGUMENTS (func_decl); parms;
4394        parms = TREE_CHAIN (parms))
4395     {
4396       int offset_in_bytes;
4397   
4398       /* type */ 
4399       encode_type (TREE_TYPE (parms), OBJC_ENCODE_DONT_INLINE_DEFS);
4400   
4401       /* compute offset */
4402       if (GET_CODE (DECL_INCOMING_RTL (parms)) == MEM)
4403         {
4404           rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
4405           
4406           /* ??? Here we assume that the parm address is indexed
4407               off the frame pointer or arg pointer.
4408               If that is not true, we produce meaningless results,
4409               but do not crash.  */
4410           if (GET_CODE (addr) == PLUS
4411               && GET_CODE (XEXP (addr, 1)) == CONST_INT)
4412             offset_in_bytes = INTVAL (XEXP (addr, 1));
4413           else
4414             offset_in_bytes = 0;
4415           
4416           /* This is the case where the parm is passed as an int or double
4417               and it is converted to a char, short or float and stored back
4418               in the parmlist.  In this case, describe the parm
4419               with the variable's declared type, and adjust the address
4420               if the least significant bytes (which we are using) are not
4421               the first ones.  */
4422 #if BYTES_BIG_ENDIAN
4423           if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
4424             offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
4425                                 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
4426 #endif
4427         }
4428       else
4429         offset_in_bytes = 0;
4430       
4431       /* The "+ 4" is a total hack to account for the return pc and
4432          saved fp on the 68k.  We should redefine this format! */
4433       sprintf (buffer, "%d", offset_in_bytes + 8);
4434       obstack_grow (&util_obstack, buffer, strlen (buffer));
4435     }
4436
4437   result = get_identifier (obstack_finish (&util_obstack));
4438   obstack_free (&util_obstack, util_firstobj);
4439   return result;
4440 }
4441
4442 void
4443 finish_method_def ()
4444 {
4445   METHOD_ENCODING (method_context) =
4446     encode_method_def (current_function_decl);
4447
4448   finish_function (0);
4449
4450   /* this must be done AFTER finish_function, since the optimizer may
4451      find "may be used before set" errors.  */
4452   method_context = NULLT;       /* required to implement _msgSuper () */
4453 }
4454
4455 int
4456 lang_report_error_function (decl)
4457       tree decl;
4458 {
4459   if (method_context)
4460     {
4461       fprintf (stderr, "In method `%s'\n",
4462                IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
4463       return 1;
4464     }
4465   else
4466     return 0;
4467 }
4468
4469 static int
4470 is_complex_decl (type)
4471      tree type;
4472 {
4473   return (TREE_CODE (type) == ARRAY_TYPE
4474           || TREE_CODE (type) == FUNCTION_TYPE
4475           || TREE_CODE (type) == POINTER_TYPE);
4476 }
4477
4478 \f
4479 /* Code to convert a decl node into text for a declaration in C.  */
4480
4481 static char tmpbuf[256];
4482
4483 static void
4484 adorn_decl (decl, str)
4485      tree decl;
4486      char *str;
4487 {
4488   enum tree_code code = TREE_CODE (decl);
4489
4490   if (code == ARRAY_REF)
4491     {
4492       tree anIntCst = TREE_OPERAND (decl, 1);
4493
4494       sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (anIntCst));
4495     }
4496   else if (code == ARRAY_TYPE)
4497     {
4498       tree anIntCst = TYPE_SIZE (decl);
4499       tree array_of = TREE_TYPE (decl);
4500
4501       sprintf (str + strlen (str), "[%d]",
4502                TREE_INT_CST_LOW (anIntCst)/TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
4503     }
4504   else if (code == CALL_EXPR)
4505     strcat (str, "()");
4506   else if (code == FUNCTION_TYPE)
4507     {
4508       tree chain  = TYPE_ARG_TYPES (decl); /* a list of types */
4509       strcat (str, "(");
4510       while (chain && TREE_VALUE (chain) != void_type_node)
4511         {
4512           gen_declaration (TREE_VALUE (chain), str);
4513           chain = TREE_CHAIN (chain);
4514           if (chain && TREE_VALUE (chain) != void_type_node)
4515             strcat (str, ",");
4516         }
4517       strcat (str, ")");
4518     }
4519   else
4520     {
4521       strcpy (tmpbuf, "*"); strcat (tmpbuf, str);
4522       strcpy (str, tmpbuf);
4523     }
4524 }
4525
4526 static char *
4527 gen_declarator (decl, buf, name)
4528      tree decl;
4529      char *buf;
4530      char *name;
4531 {
4532   if (decl)
4533     {
4534       enum tree_code code = TREE_CODE (decl);
4535       char *str;
4536       tree op;
4537       int wrap = 0;
4538
4539       switch (code)
4540         {
4541         case ARRAY_REF: case INDIRECT_REF: case CALL_EXPR:
4542           {
4543             op = TREE_OPERAND (decl, 0);
4544
4545             /* we have a pointer to a function or array...(*)(), (*)[] */
4546             if ((code == ARRAY_REF || code == CALL_EXPR) &&
4547                 (op && TREE_CODE (op) == INDIRECT_REF))
4548               wrap = 1;
4549
4550             str = gen_declarator (op, buf, name);
4551
4552             if (wrap)
4553               {
4554                 strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4555                 strcpy (str, tmpbuf);
4556               }
4557
4558             adorn_decl (decl, str);
4559             break;
4560           }
4561         case ARRAY_TYPE: case FUNCTION_TYPE: case POINTER_TYPE:
4562           {
4563             str = strcpy (buf, name);
4564
4565             /* this clause is done iteratively...rather than recursively */
4566             do
4567               {
4568                 op = is_complex_decl (TREE_TYPE (decl))
4569                   ? TREE_TYPE (decl)
4570                     : NULLT;
4571
4572                 adorn_decl (decl, str);
4573
4574                 /* we have a pointer to a function or array...(*)(), (*)[] */
4575                 if ((code == POINTER_TYPE) &&
4576                     (op && (TREE_CODE (op) == FUNCTION_TYPE
4577                             || TREE_CODE (op) == ARRAY_TYPE)))
4578                   {
4579                     strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4580                     strcpy (str, tmpbuf);
4581                   }
4582
4583                 decl = is_complex_decl (TREE_TYPE (decl))
4584                   ? TREE_TYPE (decl)
4585                     : NULLT;
4586               }
4587             while (decl && (code = TREE_CODE (decl)));
4588
4589             break;
4590           }
4591         case IDENTIFIER_NODE:
4592           /* will only happen if we are processing a "raw" expr-decl. */
4593           return strcpy (buf, IDENTIFIER_POINTER (decl));
4594         }
4595
4596       return str;
4597     }
4598   else                          /* we have an abstract declarator or a _DECL node */
4599     {
4600       return strcpy (buf, name);
4601     }
4602 }
4603
4604 static void
4605 gen_declspecs (declspecs, buf, raw)
4606      tree declspecs;
4607      char *buf;
4608      int raw;
4609 {
4610   if (raw)
4611     {
4612       tree chain;
4613
4614       for (chain = declspecs; chain; chain = TREE_CHAIN (chain))
4615         {
4616           tree aspec = TREE_VALUE (chain);
4617
4618           if (TREE_CODE (aspec) == IDENTIFIER_NODE)
4619             strcat (buf, IDENTIFIER_POINTER (aspec));
4620           else if (TREE_CODE (aspec) == RECORD_TYPE)
4621             {
4622               if (TYPE_NAME (aspec))
4623                 {
4624                   if (!TREE_STATIC_TEMPLATE (aspec))
4625                     strcat (buf, "struct ");
4626                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4627                 }
4628               else
4629                 strcat (buf, "untagged struct");
4630             }
4631           else if (TREE_CODE (aspec) == UNION_TYPE)
4632             {
4633               if (TYPE_NAME (aspec))
4634                 {
4635                   if (!TREE_STATIC_TEMPLATE (aspec))
4636                     strcat (buf, "union ");
4637                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4638                 }
4639               else
4640                 strcat (buf, "untagged union");
4641             }
4642           else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
4643             {
4644               if (TYPE_NAME (aspec))
4645                 {
4646                   if (!TREE_STATIC_TEMPLATE (aspec))
4647                     strcat (buf, "enum ");
4648                   strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4649                 }
4650               else
4651                 strcat (buf, "untagged enum");
4652             }
4653           strcat (buf, " ");
4654         }
4655     }
4656   else
4657     switch (TREE_CODE (declspecs))
4658       {
4659         /* type specifiers */
4660
4661       case INTEGER_TYPE:        /* signed integer types */
4662
4663         if (declspecs == short_integer_type_node) /* 's' */
4664           strcat (buf, "short int ");
4665         else if (declspecs == integer_type_node) /* 'i' */
4666           strcat (buf, "int ");
4667         else if (declspecs == long_integer_type_node) /* 'l' */
4668           strcat (buf, "long int ");
4669         else if (declspecs == signed_char_type_node || /* 'c' */
4670                  declspecs == char_type_node)
4671           strcat (buf, "char ");
4672
4673         /* unsigned integer types */
4674
4675         else if (declspecs == short_unsigned_type_node) /* 'S' */
4676           strcat (buf, "unsigned short ");
4677         else if (declspecs == unsigned_type_node) /* 'I' */
4678           strcat (buf, "unsigned int ");
4679         else if (declspecs == long_unsigned_type_node) /* 'L' */
4680           strcat (buf, "unsigned long ");
4681         else if (declspecs == unsigned_char_type_node) /* 'C' */
4682           strcat (buf, "unsigned char ");
4683         break;
4684
4685       case REAL_TYPE:           /* floating point types */
4686
4687         if (declspecs == float_type_node) /* 'f' */
4688           strcat (buf, "float ");
4689         else if (declspecs == double_type_node) /* 'd' */
4690           strcat (buf, "double ");
4691         else if (declspecs == long_double_type_node) /* 'd' */
4692           strcat (buf, "long double ");
4693         break;
4694
4695       case RECORD_TYPE:
4696         if (!TREE_STATIC_TEMPLATE (declspecs))
4697           strcat (buf, "struct ");
4698         if (TYPE_NAME (declspecs) &&
4699             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4700           {
4701             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4702             strcat (buf, " ");
4703           }
4704         break;
4705       case UNION_TYPE:
4706         strcat (buf, "union ");
4707         if (TYPE_NAME (declspecs) &&
4708             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4709           {
4710             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4711             strcat (buf, " ");
4712           }
4713         break;
4714       case ENUMERAL_TYPE:
4715         strcat (buf, "enum ");
4716         if (TYPE_NAME (declspecs) &&
4717             (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4718           {
4719             strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4720             strcat (buf, " ");
4721           }
4722         break;
4723       case VOID_TYPE:
4724         strcat (buf, "void ");
4725       }
4726 }
4727
4728 static char *
4729 gen_declaration (atype_or_adecl, buf)
4730      tree atype_or_adecl;
4731      char *buf;
4732 {
4733   char declbuf[256];
4734
4735   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
4736     {
4737       tree declspecs;           /* "identifier_node", "record_type" */
4738       tree declarator;          /* "array_ref", "indirect_ref", "call_expr"... */
4739
4740       /* we have a "raw", abstract declarator (typename) */
4741       declarator = TREE_VALUE (atype_or_adecl);
4742       declspecs  = TREE_PURPOSE (atype_or_adecl);
4743
4744       gen_declspecs (declspecs, buf, 1);
4745       strcat (buf, gen_declarator (declarator, declbuf, ""));
4746     }
4747   else
4748     {
4749       tree atype;
4750       tree declspecs;           /* "integer_type", "real_type", "record_type"... */
4751       tree declarator;          /* "array_type", "function_type", "pointer_type". */
4752
4753       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4754           || TREE_CODE (atype_or_adecl) == PARM_DECL
4755           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4756         atype = TREE_TYPE (atype_or_adecl);
4757       else
4758         atype = atype_or_adecl; /* assume we have a *_type node */
4759
4760       if (is_complex_decl (atype))
4761         {
4762           tree chain;
4763
4764           /* get the declaration specifier...it is at the end of the list */
4765           declarator = chain = atype;
4766           do
4767             chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
4768           while (is_complex_decl (chain));
4769           declspecs = chain;
4770         }
4771       else
4772         {
4773           declspecs = atype;
4774           declarator = NULLT;
4775         }
4776
4777       gen_declspecs (declspecs, buf, 0);
4778
4779       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4780           || TREE_CODE (atype_or_adecl) == PARM_DECL
4781           || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4782         {
4783           if (declarator)
4784             {
4785               strcat (buf, gen_declarator (declarator, declbuf,
4786                                            IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))));
4787             }
4788           else
4789             strcat (buf, IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)));
4790         }
4791       else
4792         {
4793           strcat (buf, gen_declarator (declarator, declbuf, ""));
4794         }
4795     }
4796   return buf;
4797 }
4798
4799 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
4800
4801 static char *
4802 gen_method_decl (method, buf)
4803      tree method;
4804      char *buf;
4805 {
4806   tree chain;
4807
4808   if (RAW_TYPESPEC (method) != objc_object_reference)
4809     {
4810       strcpy (buf, "(");
4811       gen_declaration (TREE_TYPE (method), buf);
4812       strcat (buf, ")");
4813     }
4814
4815   chain = METHOD_SEL_ARGS (method);
4816   if (chain)
4817     {                           /* we have a chain of keyword_decls */
4818       do
4819         {
4820           if (KEYWORD_KEY_NAME (chain))
4821             strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
4822
4823           strcat (buf, ":");
4824           if (RAW_TYPESPEC (chain) != objc_object_reference)
4825             {
4826               strcat (buf, "(");
4827               gen_declaration (TREE_TYPE (chain), buf);
4828               strcat (buf, ")");
4829             }
4830           strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
4831           if (chain = TREE_CHAIN (chain))
4832             strcat (buf, " ");
4833         }
4834       while (chain);
4835
4836       if (METHOD_ADD_ARGS (method) == (tree)1)
4837         strcat (buf, ", ...");
4838       else if (METHOD_ADD_ARGS (method))
4839         {                       /* we have a tree list node as generate by `get_parm_info ()' */
4840           chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
4841           /* know we have a chain of parm_decls */
4842           while (chain)
4843             {
4844               strcat (buf, ", ");
4845               gen_declaration (chain, buf);
4846               chain = TREE_CHAIN (chain);
4847             }
4848         }
4849     }
4850   else                          /* we have a unary selector */
4851     {
4852       strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4853     }
4854
4855   return buf;
4856 }
4857
4858 void
4859 gen_prototype (fp, decl)
4860      FILE *fp;
4861      tree decl;
4862 {
4863   /* we have a function definition - generate prototype */
4864   bzero (errbuf, BUFSIZE);
4865   gen_declaration (decl, errbuf);
4866   fprintf (fp, "%s;\n", errbuf);
4867 }
4868 /*
4869  *  debug info...
4870  */
4871 static void
4872 dump_interface (fp, chain)
4873      FILE *fp;
4874      tree chain;
4875 {
4876   char *buf = (char *)xmalloc (256);
4877   char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
4878   tree ivar_decls = CLASS_RAW_IVARS (chain);
4879   tree nst_methods = CLASS_NST_METHODS (chain);
4880   tree cls_methods = CLASS_CLS_METHODS (chain);
4881
4882   fprintf (fp, "\n@interface %s", my_name);
4883
4884   if (CLASS_SUPER_NAME (chain))
4885     {
4886       char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
4887       fprintf (fp, " : %s\n", super_name);
4888     }
4889   else
4890     fprintf (fp, "\n");
4891
4892   if (ivar_decls)
4893     {
4894       fprintf (fp, "{\n");
4895       do
4896         {
4897           bzero (buf, 256);
4898           fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
4899           ivar_decls = TREE_CHAIN (ivar_decls);
4900         }
4901       while (ivar_decls);
4902       fprintf (fp, "}\n");
4903     }
4904
4905   while (nst_methods)
4906     {
4907       bzero (buf, 256);
4908       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
4909       nst_methods = TREE_CHAIN (nst_methods);
4910     }
4911
4912   while (cls_methods)
4913     {
4914       bzero (buf, 256);
4915       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
4916       cls_methods = TREE_CHAIN (cls_methods);
4917     }
4918   fprintf (fp, "\n@end");
4919 }
4920
4921 void
4922 init_objc ()
4923 {
4924   /* Add the special tree codes of Objective C to the tables.  */
4925
4926   gcc_obstack_init (&util_obstack);
4927   util_firstobj = (char *) obstack_finish (&util_obstack);
4928
4929   tree_code_type
4930     = (char **) realloc (tree_code_type,
4931                          sizeof (char *) * LAST_OBJC_TREE_CODE);
4932   tree_code_length
4933     = (int *) realloc (tree_code_length,
4934                        sizeof (int) * LAST_OBJC_TREE_CODE);
4935   tree_code_name
4936     = (char **) realloc (tree_code_name,
4937                          sizeof (char *) * LAST_OBJC_TREE_CODE);
4938   bcopy (objc_tree_code_type,
4939          tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
4940          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4941           * sizeof (char *)));
4942   bcopy (objc_tree_code_length,
4943          tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
4944          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4945           * sizeof (int)));
4946   bcopy (objc_tree_code_name,
4947          tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
4948          (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4949           * sizeof (char *)));
4950
4951   errbuf = (char *)xmalloc (BUFSIZE);
4952   hash_init ();
4953   synth_module_prologue ();
4954 }
4955 \f
4956 void
4957 finish_objc ()
4958 {
4959   struct imp_entry *impent;
4960   tree chain;
4961
4962   generate_forward_declaration_to_string_table ();
4963
4964 #ifdef OBJC_PROLOGUE
4965   OBJC_PROLOGUE;
4966 #endif
4967
4968   if (implementation_context || sel_refdef_chain)
4969     generate_objc_symtab_decl ();
4970
4971   for (impent = imp_list; impent; impent = impent->next)
4972     {
4973       implementation_context = impent->imp_context;
4974       implementation_template = impent->imp_template;
4975
4976       _OBJC_CLASS_decl = impent->class_decl;
4977       _OBJC_METACLASS_decl = impent->meta_decl;
4978
4979       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4980         {
4981           /* all of the following reference the string pool...  */
4982           generate_ivar_lists ();
4983           generate_dispatch_tables ();
4984           generate_shared_structures ();
4985         }
4986       else
4987         {
4988           generate_dispatch_tables ();
4989           generate_category (implementation_context);
4990         }
4991     }
4992
4993   /* If we are using an array of selectors, we must always
4994      finish up the array decl even if no selectors were used.  */
4995 #ifndef OBJC_SELECTORS_WITHOUT_LABELS
4996   if (sel_ref_chain)
4997 #endif
4998     build_selector_translation_table ();
4999
5000   if (implementation_context || sel_refdef_chain)
5001     {
5002       /* Arrange for Objc data structures to be initialized at run time.  */
5003
5004       char *init_name = build_module_descriptor ();
5005       if (init_name)
5006         assemble_constructor (init_name);
5007     }
5008
5009   /* dump the string table last */
5010
5011   if (sel_refdef_chain)
5012     {
5013       build_message_selector_pool ();
5014     }
5015
5016   /* dump the class references...this forces the appropriate classes
5017      to be linked into the executable image, preserving unix archive
5018      semantics...this can be removed when we move to a more dynamically
5019      linked environment
5020      */
5021   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5022     handle_class_ref (chain);
5023
5024   for (impent = imp_list; impent; impent = impent->next)
5025     handle_impent (impent);
5026
5027 #if 0 /* If GAS has such a bug, let's fix it.  */
5028   /*** this fixes a gross bug in the assembler...it `expects' #APP to have
5029    *** a matching #NO_APP, or it crashes (sometimes). app_disable () will
5030    *** insure this is the case. 5/19/89, s.naroff.
5031    ***/
5032   if (cls_ref_chain || imp_list)
5033     app_disable ();
5034 #endif
5035
5036   if (flag_gen_declaration)
5037     {
5038       add_class (implementation_context);
5039       dump_interface (gen_declaration_file, implementation_context);
5040     }
5041   if (warn_selector)
5042     {
5043       int slot;
5044       
5045       /* Run through the selector hash tables and print a warning for any
5046          selector which has multiple methods. */
5047       
5048       for (slot = 0; slot < SIZEHASHTABLE; slot++)
5049         {
5050           hash hsh;
5051           
5052           for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
5053             {
5054               if (hsh->list)
5055                 {
5056                   tree meth = hsh->key;
5057                   char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5058                               ? '-' : '+';
5059                   attr loop;
5060               
5061                   warning ("potential selector conflict for method `%s'",
5062                            IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5063                   warn_with_method ("found", type, meth);
5064                   for (loop = hsh->list; loop; loop = loop->next)
5065                     warn_with_method ("found", type, loop->value);
5066                 }
5067             }
5068         }
5069     
5070       for (slot = 0; slot < SIZEHASHTABLE; slot++)
5071         {
5072           hash hsh;
5073           
5074           for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
5075             {
5076               if (hsh->list)
5077                 {
5078                   tree meth = hsh->key;
5079                   char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5080                               ? '-' : '+';
5081                   attr loop;
5082               
5083                   warning ("potential selector conflict for method `%s'",
5084                            IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5085                   warn_with_method ("found", type, meth);
5086                   for (loop = hsh->list; loop; loop = loop->next)
5087                     warn_with_method ("found", type, loop->value);
5088                 }
5089             }
5090         }
5091     }
5092 }
5093 \f
5094 /* Subroutines of finish_objc.  */
5095
5096 handle_class_ref (chain)
5097      tree chain;
5098 {
5099   tree decl;
5100   char *string
5101     = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30);
5102
5103   sprintf (string, "__objc_class_name_%s",
5104            IDENTIFIER_POINTER (TREE_VALUE (chain)));
5105
5106   /* Make a decl for this name, so we can use its address in a tree.  */
5107   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
5108   DECL_EXTERNAL (decl) = 1;
5109   TREE_PUBLIC (decl) = 1;
5110
5111   pushdecl (decl);
5112   rest_of_decl_compilation (decl, 0, 0, 0);
5113
5114   /* Make following constant read-only (why not)?  */
5115   text_section ();
5116
5117   /* Output a constant to reference this address.  */
5118   output_constant (build1 (ADDR_EXPR, string_type_node, decl),
5119                    int_size_in_bytes (string_type_node));
5120 }
5121
5122 handle_impent (impent)
5123      struct imp_entry *impent;
5124 {
5125   implementation_context = impent->imp_context;
5126   implementation_template = impent->imp_template;
5127
5128   if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
5129     {
5130       char *string
5131         = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30);
5132
5133       sprintf (string, "__objc_class_name_%s",
5134                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
5135       assemble_global (string);
5136       assemble_label (string);
5137     }
5138   else if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
5139     {
5140       char *string
5141         = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)))
5142                            + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)))
5143                            + 30);
5144
5145       /* Do the same for categories.  Even though no references to these
5146           symbols are generated automatically by the compiler, it gives
5147           you a handle to pull them into an archive by hand. */
5148       sprintf (string, "__objc_category_name_%s_%s",
5149                IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
5150                IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
5151       assemble_global (string);
5152       assemble_label (string);
5153     }
5154 }
5155 \f
5156 #ifdef DEBUG
5157
5158 static void
5159 objc_debug (fp)
5160      FILE *fp;
5161 {
5162   char *buf = (char *)xmalloc (256);
5163
5164   {                             /* dump function prototypes */
5165     tree loop = _OBJC_MODULES_decl;
5166
5167     fprintf (fp, "\n\nfunction prototypes:\n");
5168     while (loop)
5169       {
5170         if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
5171           {
5172             /* we have a function definition - generate prototype */
5173             bzero (errbuf, BUFSIZE);
5174             gen_declaration (loop, errbuf);
5175             fprintf (fp, "%s;\n", errbuf);
5176           }
5177         loop = TREE_CHAIN (loop);
5178       }
5179   }
5180   {                             /* dump global chains */
5181     tree loop;
5182     int i, index = 0, offset = 0;
5183     hash hashlist;
5184
5185     for (i = 0; i < SIZEHASHTABLE; i++)
5186       {
5187         if (hashlist = nst_method_hash_list[i])
5188           {
5189             fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
5190             do
5191               {
5192                 bzero (buf, 256);
5193                 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
5194                 hashlist = hashlist->next;
5195               }
5196             while (hashlist);
5197           }
5198       }
5199     for (i = 0; i < SIZEHASHTABLE; i++)
5200       {
5201         if (hashlist = cls_method_hash_list[i])
5202           {
5203             fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
5204             do
5205               {
5206                 bzero (buf, 256);
5207                 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
5208                 hashlist = hashlist->next;
5209               }
5210             while (hashlist);
5211           }
5212       }
5213     fprintf (fp, "\nsel_refdef_chain:\n");
5214     for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
5215       {
5216         fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
5217                  IDENTIFIER_POINTER (TREE_VALUE (loop)));
5218         index++;
5219         /* add one for the '\0' character */
5220         offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
5221       }
5222     fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
5223   }
5224 }
5225 #endif
5226
5227 void
5228 print_lang_statistics ()
5229 {
5230 }