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