1/* Implement classes and message passing for Objective C.
2   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4   Contributed by Steve Naroff.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to
20the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA.  */
22
23/* Purpose: This module implements the Objective-C 4.0 language.
24
25   compatibility issues (with the Stepstone translator):
26
27   - does not recognize the following 3.3 constructs.
28     @requires, @classes, @messages, = (...)
29   - methods with variable arguments must conform to ANSI standard.
30   - tagged structure definitions that appear in BOTH the interface
31     and implementation are not allowed.
32   - public/private: all instance variables are public within the
33     context of the implementation...I consider this to be a bug in
34     the translator.
35   - statically allocated objects are not supported. the user will
36     receive an error if this service is requested.
37
38   code generation `options':
39
40   */
41
42#include "config.h"
43#include "system.h"
44#include "coretypes.h"
45#include "tm.h"
46#include "tree.h"
47#include "rtl.h"
48#include "tm_p.h"
49#include "expr.h"
50
51#ifdef OBJCPLUS
52#include "cp-tree.h"
53#else
54#include "c-tree.h"
55#endif
56
57#include "c-common.h"
58#include "c-pragma.h"
59#include "flags.h"
60#include "langhooks.h"
61#include "objc-act.h"
62#include "input.h"
63#include "except.h"
64#include "function.h"
65#include "output.h"
66#include "toplev.h"
67#include "ggc.h"
68#include "varray.h"
69#include "debug.h"
70#include "target.h"
71#include "diagnostic.h"
72#include "cgraph.h"
73#include "tree-iterator.h"
74#include "libfuncs.h"
75#include "hashtab.h"
76#include "langhooks-def.h"
77
78#define OBJC_VOID_AT_END	void_list_node
79
80static unsigned int should_call_super_dealloc = 0;
81
82/* When building Objective-C++, we are not linking against the C front-end
83   and so need to replicate the C tree-construction functions in some way.  */
84#ifdef OBJCPLUS
85#define OBJCP_REMAP_FUNCTIONS
86#include "objcp-decl.h"
87#endif  /* OBJCPLUS */
88
89/* This is the default way of generating a method name.  */
90/* I am not sure it is really correct.
91   Perhaps there's a danger that it will make name conflicts
92   if method names contain underscores. -- rms.  */
93#ifndef OBJC_GEN_METHOD_LABEL
94#define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
95  do {					    \
96    char *temp;				    \
97    sprintf ((BUF), "_%s_%s_%s_%s",	    \
98	     ((IS_INST) ? "i" : "c"),	    \
99	     (CLASS_NAME),		    \
100	     ((CAT_NAME)? (CAT_NAME) : ""), \
101	     (SEL_NAME));		    \
102    for (temp = (BUF); *temp; temp++)	    \
103      if (*temp == ':') *temp = '_';	    \
104  } while (0)
105#endif
106
107/* These need specifying.  */
108#ifndef OBJC_FORWARDING_STACK_OFFSET
109#define OBJC_FORWARDING_STACK_OFFSET 0
110#endif
111
112#ifndef OBJC_FORWARDING_MIN_OFFSET
113#define OBJC_FORWARDING_MIN_OFFSET 0
114#endif
115
116/* Set up for use of obstacks.  */
117
118#include "obstack.h"
119
120/* This obstack is used to accumulate the encoding of a data type.  */
121static struct obstack util_obstack;
122
123/* This points to the beginning of obstack contents, so we can free
124   the whole contents.  */
125char *util_firstobj;
126
127/* The version identifies which language generation and runtime
128   the module (file) was compiled for, and is recorded in the
129   module descriptor.  */
130
131#define OBJC_VERSION	(flag_next_runtime ? 6 : 8)
132#define PROTOCOL_VERSION 2
133
134/* (Decide if these can ever be validly changed.) */
135#define OBJC_ENCODE_INLINE_DEFS 	0
136#define OBJC_ENCODE_DONT_INLINE_DEFS	1
137
138/*** Private Interface (procedures) ***/
139
140/* Used by compile_file.  */
141
142static void init_objc (void);
143static void finish_objc (void);
144
145/* Code generation.  */
146
147static tree objc_build_constructor (tree, tree);
148static tree build_objc_method_call (int, tree, tree, tree, tree);
149static tree get_proto_encoding (tree);
150static tree lookup_interface (tree);
151static tree objc_add_static_instance (tree, tree);
152
153static tree start_class (enum tree_code, tree, tree, tree);
154static tree continue_class (tree);
155static void finish_class (tree);
156static void start_method_def (tree);
157#ifdef OBJCPLUS
158static void objc_start_function (tree, tree, tree, tree);
159#else
160static void objc_start_function (tree, tree, tree, struct c_arg_info *);
161#endif
162static tree start_protocol (enum tree_code, tree, tree);
163static tree build_method_decl (enum tree_code, tree, tree, tree, bool);
164static tree objc_add_method (tree, tree, int);
165static tree add_instance_variable (tree, int, tree);
166static tree build_ivar_reference (tree);
167static tree is_ivar (tree, tree);
168
169static void build_objc_exception_stuff (void);
170static void build_next_objc_exception_stuff (void);
171
172/* We only need the following for ObjC; ObjC++ will use C++'s definition
173   of DERIVED_FROM_P.  */
174#ifndef OBJCPLUS
175static bool objc_derived_from_p (tree, tree);
176#define DERIVED_FROM_P(PARENT, CHILD) objc_derived_from_p (PARENT, CHILD)
177#endif
178static void objc_xref_basetypes (tree, tree);
179
180static void build_class_template (void);
181static void build_selector_template (void);
182static void build_category_template (void);
183static void build_super_template (void);
184static tree build_protocol_initializer (tree, tree, tree, tree, tree);
185static tree get_class_ivars (tree, bool);
186static tree generate_protocol_list (tree);
187static void build_protocol_reference (tree);
188
189#ifdef OBJCPLUS
190static void objc_generate_cxx_cdtors (void);
191#endif
192
193static const char *synth_id_with_class_suffix (const char *, tree);
194
195/* Hash tables to manage the global pool of method prototypes.  */
196
197hash *nst_method_hash_list = 0;
198hash *cls_method_hash_list = 0;
199
200static hash hash_lookup (hash *, tree);
201static tree lookup_method (tree, tree);
202static tree lookup_method_static (tree, tree, int);
203
204enum string_section
205{
206  class_names,		/* class, category, protocol, module names */
207  meth_var_names,	/* method and variable names */
208  meth_var_types	/* method and variable type descriptors */
209};
210
211static tree add_objc_string (tree, enum string_section);
212static tree build_objc_string_decl (enum string_section);
213static void build_selector_table_decl (void);
214
215/* Protocol additions.  */
216
217static tree lookup_protocol (tree);
218static tree lookup_and_install_protocols (tree);
219
220/* Type encoding.  */
221
222static void encode_type_qualifiers (tree);
223static void encode_type (tree, int, int);
224static void encode_field_decl (tree, int, int);
225
226#ifdef OBJCPLUS
227static void really_start_method (tree, tree);
228#else
229static void really_start_method (tree, struct c_arg_info *);
230#endif
231static int comp_proto_with_proto (tree, tree, int);
232static void objc_push_parm (tree);
233#ifdef OBJCPLUS
234static tree objc_get_parm_info (int);
235#else
236static struct c_arg_info *objc_get_parm_info (int);
237#endif
238
239/* Utilities for debugging and error diagnostics.  */
240
241static void warn_with_method (const char *, int, tree);
242static char *gen_type_name (tree);
243static char *gen_type_name_0 (tree);
244static char *gen_method_decl (tree);
245static char *gen_declaration (tree);
246
247/* Everything else.  */
248
249static tree create_field_decl (tree, const char *);
250static void add_class_reference (tree);
251static void build_protocol_template (void);
252static tree encode_method_prototype (tree);
253static void generate_classref_translation_entry (tree);
254static void handle_class_ref (tree);
255static void generate_struct_by_value_array (void)
256     ATTRIBUTE_NORETURN;
257static void mark_referenced_methods (void);
258static void generate_objc_image_info (void);
259
260/*** Private Interface (data) ***/
261
262/* Reserved tag definitions.  */
263
264#define OBJECT_TYPEDEF_NAME		"id"
265#define CLASS_TYPEDEF_NAME		"Class"
266
267#define TAG_OBJECT			"objc_object"
268#define TAG_CLASS			"objc_class"
269#define TAG_SUPER			"objc_super"
270#define TAG_SELECTOR			"objc_selector"
271
272#define UTAG_CLASS			"_objc_class"
273#define UTAG_IVAR			"_objc_ivar"
274#define UTAG_IVAR_LIST			"_objc_ivar_list"
275#define UTAG_METHOD			"_objc_method"
276#define UTAG_METHOD_LIST		"_objc_method_list"
277#define UTAG_CATEGORY			"_objc_category"
278#define UTAG_MODULE			"_objc_module"
279#define UTAG_SYMTAB			"_objc_symtab"
280#define UTAG_SUPER			"_objc_super"
281#define UTAG_SELECTOR			"_objc_selector"
282
283#define UTAG_PROTOCOL			"_objc_protocol"
284#define UTAG_METHOD_PROTOTYPE		"_objc_method_prototype"
285#define UTAG_METHOD_PROTOTYPE_LIST	"_objc__method_prototype_list"
286
287/* Note that the string object global name is only needed for the
288   NeXT runtime.  */
289#define STRING_OBJECT_GLOBAL_FORMAT	"_%sClassReference"
290
291#define PROTOCOL_OBJECT_CLASS_NAME	"Protocol"
292
293static const char *TAG_GETCLASS;
294static const char *TAG_GETMETACLASS;
295static const char *TAG_MSGSEND;
296static const char *TAG_MSGSENDSUPER;
297/* The NeXT Objective-C messenger may have two extra entry points, for use
298   when returning a structure. */
299static const char *TAG_MSGSEND_STRET;
300static const char *TAG_MSGSENDSUPER_STRET;
301static const char *default_constant_string_class_name;
302
303/* Runtime metadata flags.  */
304#define CLS_FACTORY			0x0001L
305#define CLS_META			0x0002L
306#define CLS_HAS_CXX_STRUCTORS		0x2000L
307
308#define OBJC_MODIFIER_STATIC		0x00000001
309#define OBJC_MODIFIER_FINAL		0x00000002
310#define OBJC_MODIFIER_PUBLIC		0x00000004
311#define OBJC_MODIFIER_PRIVATE		0x00000008
312#define OBJC_MODIFIER_PROTECTED		0x00000010
313#define OBJC_MODIFIER_NATIVE		0x00000020
314#define OBJC_MODIFIER_SYNCHRONIZED	0x00000040
315#define OBJC_MODIFIER_ABSTRACT		0x00000080
316#define OBJC_MODIFIER_VOLATILE		0x00000100
317#define OBJC_MODIFIER_TRANSIENT		0x00000200
318#define OBJC_MODIFIER_NONE_SPECIFIED	0x80000000
319
320/* NeXT-specific tags.  */
321
322#define TAG_MSGSEND_NONNIL		"objc_msgSendNonNil"
323#define TAG_MSGSEND_NONNIL_STRET	"objc_msgSendNonNil_stret"
324#define TAG_EXCEPTIONEXTRACT		"objc_exception_extract"
325#define TAG_EXCEPTIONTRYENTER		"objc_exception_try_enter"
326#define TAG_EXCEPTIONTRYEXIT		"objc_exception_try_exit"
327#define TAG_EXCEPTIONMATCH		"objc_exception_match"
328#define TAG_EXCEPTIONTHROW		"objc_exception_throw"
329#define TAG_SYNCENTER			"objc_sync_enter"
330#define TAG_SYNCEXIT			"objc_sync_exit"
331#define TAG_SETJMP			"_setjmp"
332#define UTAG_EXCDATA			"_objc_exception_data"
333
334#define TAG_ASSIGNIVAR			"objc_assign_ivar"
335#define TAG_ASSIGNGLOBAL		"objc_assign_global"
336#define TAG_ASSIGNSTRONGCAST		"objc_assign_strongCast"
337
338/* Branch entry points.  All that matters here are the addresses;
339   functions with these names do not really exist in libobjc.  */
340
341#define TAG_MSGSEND_FAST		"objc_msgSend_Fast"
342#define TAG_ASSIGNIVAR_FAST		"objc_assign_ivar_Fast"
343
344#define TAG_CXX_CONSTRUCT		".cxx_construct"
345#define TAG_CXX_DESTRUCT		".cxx_destruct"
346
347/* GNU-specific tags.  */
348
349#define TAG_EXECCLASS			"__objc_exec_class"
350#define TAG_GNUINIT			"__objc_gnu_init"
351
352/* Flags for lookup_method_static().  */
353#define OBJC_LOOKUP_CLASS	1	/* Look for class methods.  */
354#define OBJC_LOOKUP_NO_SUPER	2	/* Do not examine superclasses.  */
355
356/* The OCTI_... enumeration itself is in objc/objc-act.h.  */
357tree objc_global_trees[OCTI_MAX];
358
359static void handle_impent (struct imp_entry *);
360
361struct imp_entry *imp_list = 0;
362int imp_count = 0;	/* `@implementation' */
363int cat_count = 0;	/* `@category' */
364
365enum tree_code objc_inherit_code;
366int objc_public_flag;
367
368/* Use to generate method labels.  */
369static int method_slot = 0;
370
371#define BUFSIZE		1024
372
373static char *errbuf;	/* Buffer for error diagnostics */
374
375/* Data imported from tree.c.  */
376
377extern enum debug_info_type write_symbols;
378
379/* Data imported from toplev.c.  */
380
381extern const char *dump_base_name;
382
383static int flag_typed_selectors;
384
385/* Store all constructed constant strings in a hash table so that
386   they get uniqued properly.  */
387
388struct string_descriptor GTY(())
389{
390  /* The literal argument .  */
391  tree literal;
392
393  /* The resulting constant string.  */
394  tree constructor;
395};
396
397static GTY((param_is (struct string_descriptor))) htab_t string_htab;
398
399/* Store the EH-volatilized types in a hash table, for easy retrieval.  */
400struct volatilized_type GTY(())
401{
402  tree type;
403};
404
405static GTY((param_is (struct volatilized_type))) htab_t volatilized_htab;
406
407FILE *gen_declaration_file;
408
409/* Tells "encode_pointer/encode_aggregate" whether we are generating
410   type descriptors for instance variables (as opposed to methods).
411   Type descriptors for instance variables contain more information
412   than methods (for static typing and embedded structures).  */
413
414static int generating_instance_variables = 0;
415
416/* Some platforms pass small structures through registers versus
417   through an invisible pointer.  Determine at what size structure is
418   the transition point between the two possibilities.  */
419
420static void
421generate_struct_by_value_array (void)
422{
423  tree type;
424  tree field_decl, field_decl_chain;
425  int i, j;
426  int aggregate_in_mem[32];
427  int found = 0;
428
429  /* Presumably no platform passes 32 byte structures in a register.  */
430  for (i = 1; i < 32; i++)
431    {
432      char buffer[5];
433
434      /* Create an unnamed struct that has `i' character components */
435      type = start_struct (RECORD_TYPE, NULL_TREE);
436
437      strcpy (buffer, "c1");
438      field_decl = create_field_decl (char_type_node,
439				      buffer);
440      field_decl_chain = field_decl;
441
442      for (j = 1; j < i; j++)
443	{
444	  sprintf (buffer, "c%d", j + 1);
445	  field_decl = create_field_decl (char_type_node,
446					  buffer);
447	  chainon (field_decl_chain, field_decl);
448	}
449      finish_struct (type, field_decl_chain, NULL_TREE);
450
451      aggregate_in_mem[i] = aggregate_value_p (type, 0);
452      if (!aggregate_in_mem[i])
453	found = 1;
454    }
455
456  /* We found some structures that are returned in registers instead of memory
457     so output the necessary data.  */
458  if (found)
459    {
460      for (i = 31; i >= 0;  i--)
461	if (!aggregate_in_mem[i])
462	  break;
463      printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
464
465      /* The first member of the structure is always 0 because we don't handle
466	 structures with 0 members */
467      printf ("static int struct_forward_array[] = {\n  0");
468
469      for (j = 1; j <= i; j++)
470	printf (", %d", aggregate_in_mem[j]);
471      printf ("\n};\n");
472    }
473
474  exit (0);
475}
476
477bool
478objc_init (void)
479{
480#ifdef OBJCPLUS
481  if (cxx_init () == false)
482#else
483  if (c_objc_common_init () == false)
484#endif
485    return false;
486
487#ifndef USE_MAPPED_LOCATION
488  /* Force the line number back to 0; check_newline will have
489     raised it to 1, which will make the builtin functions appear
490     not to be built in.  */
491  input_line = 0;
492#endif
493
494  /* If gen_declaration desired, open the output file.  */
495  if (flag_gen_declaration)
496    {
497      register char * const dumpname = concat (dump_base_name, ".decl", NULL);
498      gen_declaration_file = fopen (dumpname, "w");
499      if (gen_declaration_file == 0)
500	fatal_error ("can't open %s: %m", dumpname);
501      free (dumpname);
502    }
503
504  if (flag_next_runtime)
505    {
506      TAG_GETCLASS = "objc_getClass";
507      TAG_GETMETACLASS = "objc_getMetaClass";
508      TAG_MSGSEND = "objc_msgSend";
509      TAG_MSGSENDSUPER = "objc_msgSendSuper";
510      TAG_MSGSEND_STRET = "objc_msgSend_stret";
511      TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
512      default_constant_string_class_name = "NSConstantString";
513    }
514  else
515    {
516      TAG_GETCLASS = "objc_get_class";
517      TAG_GETMETACLASS = "objc_get_meta_class";
518      TAG_MSGSEND = "objc_msg_lookup";
519      TAG_MSGSENDSUPER = "objc_msg_lookup_super";
520      /* GNU runtime does not provide special functions to support
521	 structure-returning methods.  */
522      default_constant_string_class_name = "NXConstantString";
523      flag_typed_selectors = 1;
524    }
525
526  init_objc ();
527
528  if (print_struct_values)
529    generate_struct_by_value_array ();
530
531  return true;
532}
533
534void
535objc_finish_file (void)
536{
537  mark_referenced_methods ();
538
539#ifdef OBJCPLUS
540  /* We need to instantiate templates _before_ we emit ObjC metadata;
541     if we do not, some metadata (such as selectors) may go missing.  */
542  at_eof = 1;
543  instantiate_pending_templates (0);
544#endif
545
546  /* Finalize Objective-C runtime data.  No need to generate tables
547     and code if only checking syntax, or if generating a PCH file.  */
548  if (!flag_syntax_only && !pch_file)
549    finish_objc ();
550
551  if (gen_declaration_file)
552    fclose (gen_declaration_file);
553
554#ifdef OBJCPLUS
555  cp_finish_file ();
556#endif
557}
558
559/* Return the first occurrence of a method declaration corresponding
560   to sel_name in rproto_list.  Search rproto_list recursively.
561   If is_class is 0, search for instance methods, otherwise for class
562   methods.  */
563static tree
564lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
565				int is_class)
566{
567   tree rproto, p;
568   tree fnd = 0;
569
570   for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
571     {
572        p = TREE_VALUE (rproto);
573
574	if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
575	  {
576	    if ((fnd = lookup_method (is_class
577				      ? PROTOCOL_CLS_METHODS (p)
578				      : PROTOCOL_NST_METHODS (p), sel_name)))
579	      ;
580	    else if (PROTOCOL_LIST (p))
581	      fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
582						    sel_name, is_class);
583	  }
584	else
585          {
586	    ; /* An identifier...if we could not find a protocol.  */
587          }
588
589	if (fnd)
590	  return fnd;
591     }
592
593   return 0;
594}
595
596static tree
597lookup_protocol_in_reflist (tree rproto_list, tree lproto)
598{
599  tree rproto, p;
600
601  /* Make sure the protocol is supported by the object on the rhs.  */
602  if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
603    {
604      tree fnd = 0;
605      for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
606	{
607	  p = TREE_VALUE (rproto);
608
609	  if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
610	    {
611	      if (lproto == p)
612		fnd = lproto;
613
614	      else if (PROTOCOL_LIST (p))
615		fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
616	    }
617
618	  if (fnd)
619	    return fnd;
620	}
621    }
622  else
623    {
624      ; /* An identifier...if we could not find a protocol.  */
625    }
626
627  return 0;
628}
629
630void
631objc_start_class_interface (tree class, tree super_class, tree protos)
632{
633  objc_interface_context
634    = objc_ivar_context
635    = start_class (CLASS_INTERFACE_TYPE, class, super_class, protos);
636  objc_public_flag = 0;
637}
638
639void
640objc_start_category_interface (tree class, tree categ, tree protos)
641{
642  objc_interface_context
643    = start_class (CATEGORY_INTERFACE_TYPE, class, categ, protos);
644  objc_ivar_chain
645    = continue_class (objc_interface_context);
646}
647
648void
649objc_start_protocol (tree name, tree protos)
650{
651  objc_interface_context
652    = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
653}
654
655void
656objc_continue_interface (void)
657{
658  objc_ivar_chain
659    = continue_class (objc_interface_context);
660}
661
662void
663objc_finish_interface (void)
664{
665  finish_class (objc_interface_context);
666  objc_interface_context = NULL_TREE;
667}
668
669void
670objc_start_class_implementation (tree class, tree super_class)
671{
672  objc_implementation_context
673    = objc_ivar_context
674    = start_class (CLASS_IMPLEMENTATION_TYPE, class, super_class, NULL_TREE);
675  objc_public_flag = 0;
676}
677
678void
679objc_start_category_implementation (tree class, tree categ)
680{
681  objc_implementation_context
682    = start_class (CATEGORY_IMPLEMENTATION_TYPE, class, categ, NULL_TREE);
683  objc_ivar_chain
684    = continue_class (objc_implementation_context);
685}
686
687void
688objc_continue_implementation (void)
689{
690  objc_ivar_chain
691    = continue_class (objc_implementation_context);
692}
693
694void
695objc_finish_implementation (void)
696{
697#ifdef OBJCPLUS
698  if (flag_objc_call_cxx_cdtors)
699    objc_generate_cxx_cdtors ();
700#endif
701
702  if (objc_implementation_context)
703    {
704      finish_class (objc_implementation_context);
705      objc_ivar_chain = NULL_TREE;
706      objc_implementation_context = NULL_TREE;
707    }
708  else
709    warning (0, "%<@end%> must appear in an @implementation context");
710}
711
712void
713objc_set_visibility (int visibility)
714{
715  objc_public_flag = visibility;
716}
717
718void
719objc_set_method_type (enum tree_code type)
720{
721  objc_inherit_code = (type == PLUS_EXPR
722		       ? CLASS_METHOD_DECL
723		       : INSTANCE_METHOD_DECL);
724}
725
726tree
727objc_build_method_signature (tree rettype, tree selector,
728			     tree optparms, bool ellipsis)
729{
730  return build_method_decl (objc_inherit_code, rettype, selector,
731			    optparms, ellipsis);
732}
733
734void
735objc_add_method_declaration (tree decl)
736{
737  if (!objc_interface_context)
738    fatal_error ("method declaration not in @interface context");
739
740  objc_add_method (objc_interface_context,
741		   decl,
742		   objc_inherit_code == CLASS_METHOD_DECL);
743}
744
745void
746objc_start_method_definition (tree decl)
747{
748  if (!objc_implementation_context)
749    fatal_error ("method definition not in @implementation context");
750
751  objc_add_method (objc_implementation_context,
752		   decl,
753		   objc_inherit_code == CLASS_METHOD_DECL);
754  start_method_def (decl);
755}
756
757void
758objc_add_instance_variable (tree decl)
759{
760  (void) add_instance_variable (objc_ivar_context,
761				objc_public_flag,
762				decl);
763}
764
765/* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
766   an '@'.  */
767
768int
769objc_is_reserved_word (tree ident)
770{
771  unsigned char code = C_RID_CODE (ident);
772
773  return (OBJC_IS_AT_KEYWORD (code)
774#ifdef OBJCPLUS
775	  || code == RID_CLASS || code == RID_PUBLIC
776	  || code == RID_PROTECTED || code == RID_PRIVATE
777	  || code == RID_TRY || code == RID_THROW || code == RID_CATCH
778#endif
779	    );
780}
781
782/* Return true if TYPE is 'id'.  */
783
784static bool
785objc_is_object_id (tree type)
786{
787  return OBJC_TYPE_NAME (type) == objc_object_id;
788}
789
790static bool
791objc_is_class_id (tree type)
792{
793  return OBJC_TYPE_NAME (type) == objc_class_id;
794}
795
796/* Construct a C struct with same name as CLASS, a base struct with tag
797   SUPER_NAME (if any), and FIELDS indicated.  */
798
799static tree
800objc_build_struct (tree class, tree fields, tree super_name)
801{
802  tree name = CLASS_NAME (class);
803  tree s = start_struct (RECORD_TYPE, name);
804  tree super = (super_name ? xref_tag (RECORD_TYPE, super_name) : NULL_TREE);
805  tree t, objc_info = NULL_TREE;
806
807  if (super)
808    {
809      /* Prepend a packed variant of the base class into the layout.  This
810	 is necessary to preserve ObjC ABI compatibility.  */
811      tree base = build_decl (FIELD_DECL, NULL_TREE, super);
812      tree field = TYPE_FIELDS (super);
813
814      while (field && TREE_CHAIN (field)
815	     && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
816	field = TREE_CHAIN (field);
817
818      /* For ObjC ABI purposes, the "packed" size of a base class is the
819	 the sum of the offset and the size (in bits) of the last field
820	 in the class.  */
821      DECL_SIZE (base)
822	= (field && TREE_CODE (field) == FIELD_DECL
823	   ? size_binop (PLUS_EXPR,
824			 size_binop (PLUS_EXPR,
825				     size_binop
826				     (MULT_EXPR,
827				      convert (bitsizetype,
828					       DECL_FIELD_OFFSET (field)),
829				      bitsize_int (BITS_PER_UNIT)),
830				     DECL_FIELD_BIT_OFFSET (field)),
831			 DECL_SIZE (field))
832	   : bitsize_zero_node);
833      DECL_SIZE_UNIT (base)
834	= size_binop (FLOOR_DIV_EXPR, convert (sizetype, DECL_SIZE (base)),
835		      size_int (BITS_PER_UNIT));
836      DECL_ARTIFICIAL (base) = 1;
837      DECL_ALIGN (base) = 1;
838      DECL_FIELD_CONTEXT (base) = s;
839#ifdef OBJCPLUS
840      DECL_FIELD_IS_BASE (base) = 1;
841
842      if (fields)
843	TREE_NO_WARNING (fields) = 1;	/* Suppress C++ ABI warnings -- we   */
844#endif					/* are following the ObjC ABI here.  */
845      TREE_CHAIN (base) = fields;
846      fields = base;
847    }
848
849  /* NB: Calling finish_struct() may cause type TYPE_LANG_SPECIFIC fields
850     in all variants of this RECORD_TYPE to be clobbered, but it is therein
851     that we store protocol conformance info (e.g., 'NSObject <MyProtocol>').
852     Hence, we must squirrel away the ObjC-specific information before calling
853     finish_struct(), and then reinstate it afterwards.  */
854
855  for (t = TYPE_NEXT_VARIANT (s); t; t = TYPE_NEXT_VARIANT (t))
856    objc_info
857      = chainon (objc_info,
858		 build_tree_list (NULL_TREE, TYPE_OBJC_INFO (t)));
859
860  /* Point the struct at its related Objective-C class.  */
861  INIT_TYPE_OBJC_INFO (s);
862  TYPE_OBJC_INTERFACE (s) = class;
863
864  s = finish_struct (s, fields, NULL_TREE);
865
866  for (t = TYPE_NEXT_VARIANT (s); t;
867       t = TYPE_NEXT_VARIANT (t), objc_info = TREE_CHAIN (objc_info))
868    {
869      TYPE_OBJC_INFO (t) = TREE_VALUE (objc_info);
870      /* Replace the IDENTIFIER_NODE with an actual @interface.  */
871      TYPE_OBJC_INTERFACE (t) = class;
872    }
873
874  /* Use TYPE_BINFO structures to point at the super class, if any.  */
875  objc_xref_basetypes (s, super);
876
877  /* Mark this struct as a class template.  */
878  CLASS_STATIC_TEMPLATE (class) = s;
879
880  return s;
881}
882
883/* Build a type differing from TYPE only in that TYPE_VOLATILE is set.
884   Unlike tree.c:build_qualified_type(), preserve TYPE_LANG_SPECIFIC in the
885   process.  */
886static tree
887objc_build_volatilized_type (tree type)
888{
889  tree t;
890
891  /* Check if we have not constructed the desired variant already.  */
892  for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
893    {
894      /* The type qualifiers must (obviously) match up.  */
895      if (!TYPE_VOLATILE (t)
896	  || (TYPE_READONLY (t) != TYPE_READONLY (type))
897	  || (TYPE_RESTRICT (t) != TYPE_RESTRICT (type)))
898	continue;
899
900      /* For pointer types, the pointees (and hence their TYPE_LANG_SPECIFIC
901	 info, if any) must match up.  */
902      if (POINTER_TYPE_P (t)
903	  && (TREE_TYPE (t) != TREE_TYPE (type)))
904	continue;
905
906      /* Everything matches up!  */
907      return t;
908    }
909
910  /* Ok, we could not re-use any of the pre-existing variants.  Create
911     a new one.  */
912  t = build_variant_type_copy (type);
913  TYPE_VOLATILE (t) = 1;
914
915  return t;
916}
917
918/* Mark DECL as being 'volatile' for purposes of Darwin
919   _setjmp()/_longjmp() exception handling.  Called from
920   objc_mark_locals_volatile().  */
921void
922objc_volatilize_decl (tree decl)
923{
924  /* Do not mess with variables that are 'static' or (already)
925     'volatile'.  */
926  if (!TREE_THIS_VOLATILE (decl) && !TREE_STATIC (decl)
927      && (TREE_CODE (decl) == VAR_DECL
928	  || TREE_CODE (decl) == PARM_DECL))
929    {
930      tree t = TREE_TYPE (decl);
931      struct volatilized_type key;
932      void **loc;
933
934      t = objc_build_volatilized_type (t);
935      key.type = t;
936      loc = htab_find_slot (volatilized_htab, &key, INSERT);
937
938      if (!*loc)
939	{
940	  *loc = ggc_alloc (sizeof (key));
941	  ((struct volatilized_type *) *loc)->type = t;
942	}
943
944      TREE_TYPE (decl) = t;
945      TREE_THIS_VOLATILE (decl) = 1;
946      TREE_SIDE_EFFECTS (decl) = 1;
947      DECL_REGISTER (decl) = 0;
948#ifndef OBJCPLUS
949      C_DECL_REGISTER (decl) = 0;
950#endif
951    }
952}
953
954/* Check if protocol PROTO is adopted (directly or indirectly) by class CLS
955   (including its categoreis and superclasses) or by object type TYP.
956   Issue a warning if PROTO is not adopted anywhere and WARN is set.  */
957
958static bool
959objc_lookup_protocol (tree proto, tree cls, tree typ, bool warn)
960{
961  bool class_type = (cls != NULL_TREE);
962
963  while (cls)
964    {
965      tree c;
966
967      /* Check protocols adopted by the class and its categories.  */
968      for (c = cls; c; c = CLASS_CATEGORY_LIST (c))
969	{
970	  if (lookup_protocol_in_reflist (CLASS_PROTOCOL_LIST (c), proto))
971	    return true;
972	}
973
974      /* Repeat for superclasses.  */
975      cls = lookup_interface (CLASS_SUPER_NAME (cls));
976    }
977
978  /* Check for any protocols attached directly to the object type.  */
979  if (TYPE_HAS_OBJC_INFO (typ))
980    {
981      if (lookup_protocol_in_reflist (TYPE_OBJC_PROTOCOL_LIST (typ), proto))
982	return true;
983    }
984
985  if (warn)
986    {
987      strcpy (errbuf, class_type ? "class \'" : "type \'");
988      gen_type_name_0 (class_type ? typ : TYPE_POINTER_TO (typ));
989      strcat (errbuf, "\' does not ");
990      /* NB: Types 'id' and 'Class' cannot reasonably be described as
991	 "implementing" a given protocol, since they do not have an
992	 implementation.  */
993      strcat (errbuf, class_type ? "implement" : "conform to");
994      strcat (errbuf, " the \'");
995      strcat (errbuf, IDENTIFIER_POINTER (PROTOCOL_NAME (proto)));
996      strcat (errbuf, "\' protocol");
997      warning (0, errbuf);
998    }
999
1000  return false;
1001}
1002
1003/* Check if class RCLS and instance struct type RTYP conform to at least the
1004   same protocols that LCLS and LTYP conform to.  */
1005
1006static bool
1007objc_compare_protocols (tree lcls, tree ltyp, tree rcls, tree rtyp, bool warn)
1008{
1009  tree p;
1010  bool have_lproto = false;
1011
1012  while (lcls)
1013    {
1014      /* NB: We do _not_ look at categories defined for LCLS; these may or
1015	 may not get loaded in, and therefore it is unreasonable to require
1016	 that RCLS/RTYP must implement any of their protocols.  */
1017      for (p = CLASS_PROTOCOL_LIST (lcls); p; p = TREE_CHAIN (p))
1018	{
1019	  have_lproto = true;
1020
1021	  if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1022	    return warn;
1023	}
1024
1025      /* Repeat for superclasses.  */
1026      lcls = lookup_interface (CLASS_SUPER_NAME (lcls));
1027    }
1028
1029  /* Check for any protocols attached directly to the object type.  */
1030  if (TYPE_HAS_OBJC_INFO (ltyp))
1031    {
1032      for (p = TYPE_OBJC_PROTOCOL_LIST (ltyp); p; p = TREE_CHAIN (p))
1033	{
1034	  have_lproto = true;
1035
1036	  if (!objc_lookup_protocol (TREE_VALUE (p), rcls, rtyp, warn))
1037	    return warn;
1038	}
1039    }
1040
1041  /* NB: If LTYP and LCLS have no protocols to search for, return 'true'
1042     vacuously, _unless_ RTYP is a protocol-qualified 'id'.  We can get
1043     away with simply checking for 'id' or 'Class' (!RCLS), since this
1044     routine will not get called in other cases.  */
1045  return have_lproto || (rcls != NULL_TREE);
1046}
1047
1048/* Determine if it is permissible to assign (if ARGNO is greater than -3)
1049   an instance of RTYP to an instance of LTYP or to compare the two
1050   (if ARGNO is equal to -3), per ObjC type system rules.  Before
1051   returning 'true', this routine may issue warnings related to, e.g.,
1052   protocol conformance.  When returning 'false', the routine must
1053   produce absolutely no warnings; the C or C++ front-end will do so
1054   instead, if needed.  If either LTYP or RTYP is not an Objective-C type,
1055   the routine must return 'false'.
1056
1057   The ARGNO parameter is encoded as follows:
1058     >= 1	Parameter number (CALLEE contains function being called);
1059     0		Return value;
1060     -1		Assignment;
1061     -2		Initialization;
1062     -3		Comparison (LTYP and RTYP may match in either direction).  */
1063
1064bool
1065objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee)
1066{
1067  tree lcls, rcls, lproto, rproto;
1068  bool pointers_compatible;
1069
1070  /* We must be dealing with pointer types */
1071  if (!POINTER_TYPE_P (ltyp) || !POINTER_TYPE_P (rtyp))
1072    return false;
1073
1074  do
1075    {
1076      ltyp = TREE_TYPE (ltyp);  /* Remove indirections.  */
1077      rtyp = TREE_TYPE (rtyp);
1078    }
1079  while (POINTER_TYPE_P (ltyp) && POINTER_TYPE_P (rtyp));
1080
1081  /* Past this point, we are only interested in ObjC class instances,
1082     or 'id' or 'Class'.  */
1083  if (TREE_CODE (ltyp) != RECORD_TYPE || TREE_CODE (rtyp) != RECORD_TYPE)
1084    return false;
1085
1086  if (!objc_is_object_id (ltyp) && !objc_is_class_id (ltyp)
1087      && !TYPE_HAS_OBJC_INFO (ltyp))
1088    return false;
1089
1090  if (!objc_is_object_id (rtyp) && !objc_is_class_id (rtyp)
1091      && !TYPE_HAS_OBJC_INFO (rtyp))
1092    return false;
1093
1094  /* Past this point, we are committed to returning 'true' to the caller.
1095     However, we can still warn about type and/or protocol mismatches.  */
1096
1097  if (TYPE_HAS_OBJC_INFO (ltyp))
1098    {
1099      lcls = TYPE_OBJC_INTERFACE (ltyp);
1100      lproto = TYPE_OBJC_PROTOCOL_LIST (ltyp);
1101    }
1102  else
1103    lcls = lproto = NULL_TREE;
1104
1105  if (TYPE_HAS_OBJC_INFO (rtyp))
1106    {
1107      rcls = TYPE_OBJC_INTERFACE (rtyp);
1108      rproto = TYPE_OBJC_PROTOCOL_LIST (rtyp);
1109    }
1110  else
1111    rcls = rproto = NULL_TREE;
1112
1113  /* If we could not find an @interface declaration, we must have
1114     only seen a @class declaration; for purposes of type comparison,
1115     treat it as a stand-alone (root) class.  */
1116
1117  if (lcls && TREE_CODE (lcls) == IDENTIFIER_NODE)
1118    lcls = NULL_TREE;
1119
1120  if (rcls && TREE_CODE (rcls) == IDENTIFIER_NODE)
1121    rcls = NULL_TREE;
1122
1123  /* If either type is an unqualified 'id', we're done.  */
1124  if ((!lproto && objc_is_object_id (ltyp))
1125      || (!rproto && objc_is_object_id (rtyp)))
1126    return true;
1127
1128  pointers_compatible = (TYPE_MAIN_VARIANT (ltyp) == TYPE_MAIN_VARIANT (rtyp));
1129
1130  /* If the underlying types are the same, and at most one of them has
1131     a protocol list, we do not need to issue any diagnostics.  */
1132  if (pointers_compatible && (!lproto || !rproto))
1133    return true;
1134
1135  /* If exactly one of the types is 'Class', issue a diagnostic; any
1136     exceptions of this rule have already been handled.  */
1137  if (objc_is_class_id (ltyp) ^ objc_is_class_id (rtyp))
1138    pointers_compatible = false;
1139  /* Otherwise, check for inheritance relations.  */
1140  else
1141    {
1142      if (!pointers_compatible)
1143	pointers_compatible
1144	  = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp));
1145
1146      if (!pointers_compatible)
1147	pointers_compatible = DERIVED_FROM_P (ltyp, rtyp);
1148
1149      if (!pointers_compatible && argno == -3)
1150	pointers_compatible = DERIVED_FROM_P (rtyp, ltyp);
1151    }
1152
1153  /* If the pointers match modulo protocols, check for protocol conformance
1154     mismatches.  */
1155  if (pointers_compatible)
1156    {
1157      pointers_compatible = objc_compare_protocols (lcls, ltyp, rcls, rtyp,
1158						    argno != -3);
1159
1160      if (!pointers_compatible && argno == -3)
1161	pointers_compatible = objc_compare_protocols (rcls, rtyp, lcls, ltyp,
1162						      argno != -3);
1163    }
1164
1165  if (!pointers_compatible)
1166    {
1167      /* NB: For the time being, we shall make our warnings look like their
1168	 C counterparts.  In the future, we may wish to make them more
1169	 ObjC-specific.  */
1170      switch (argno)
1171	{
1172	case -3:
1173	  warning (0, "comparison of distinct Objective-C types lacks a cast");
1174	  break;
1175
1176	case -2:
1177	  warning (0, "initialization from distinct Objective-C type");
1178	  break;
1179
1180	case -1:
1181	  warning (0, "assignment from distinct Objective-C type");
1182	  break;
1183
1184	case 0:
1185	  warning (0, "distinct Objective-C type in return");
1186	  break;
1187
1188	default:
1189	  warning (0, "passing argument %d of %qE from distinct "
1190		   "Objective-C type", argno, callee);
1191	  break;
1192	}
1193    }
1194
1195  return true;
1196}
1197
1198/* Check if LTYP and RTYP have the same type qualifiers.  If either type
1199   lives in the volatilized hash table, ignore the 'volatile' bit when
1200   making the comparison.  */
1201
1202bool
1203objc_type_quals_match (tree ltyp, tree rtyp)
1204{
1205  int lquals = TYPE_QUALS (ltyp), rquals = TYPE_QUALS (rtyp);
1206  struct volatilized_type key;
1207
1208  key.type = ltyp;
1209
1210  if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
1211    lquals &= ~TYPE_QUAL_VOLATILE;
1212
1213  key.type = rtyp;
1214
1215  if (htab_find_slot (volatilized_htab, &key, NO_INSERT))
1216    rquals &= ~TYPE_QUAL_VOLATILE;
1217
1218  return (lquals == rquals);
1219}
1220
1221#ifndef OBJCPLUS
1222/* Determine if CHILD is derived from PARENT.  The routine assumes that
1223   both parameters are RECORD_TYPEs, and is non-reflexive.  */
1224
1225static bool
1226objc_derived_from_p (tree parent, tree child)
1227{
1228  parent = TYPE_MAIN_VARIANT (parent);
1229
1230  for (child = TYPE_MAIN_VARIANT (child);
1231       TYPE_BINFO (child) && BINFO_N_BASE_BINFOS (TYPE_BINFO (child));)
1232    {
1233      child = TYPE_MAIN_VARIANT (BINFO_TYPE (BINFO_BASE_BINFO
1234					     (TYPE_BINFO (child),
1235					      0)));
1236
1237      if (child == parent)
1238	return true;
1239    }
1240
1241  return false;
1242}
1243#endif
1244
1245static tree
1246objc_build_component_ref (tree datum, tree component)
1247{
1248  /* If COMPONENT is NULL, the caller is referring to the anonymous
1249     base class field.  */
1250  if (!component)
1251    {
1252      tree base = TYPE_FIELDS (TREE_TYPE (datum));
1253
1254      return build3 (COMPONENT_REF, TREE_TYPE (base), datum, base, NULL_TREE);
1255    }
1256
1257  /* The 'build_component_ref' routine has been removed from the C++
1258     front-end, but 'finish_class_member_access_expr' seems to be
1259     a worthy substitute.  */
1260#ifdef OBJCPLUS
1261  return finish_class_member_access_expr (datum, component, false);
1262#else
1263  return build_component_ref (datum, component);
1264#endif
1265}
1266
1267/* Recursively copy inheritance information rooted at BINFO.  To do this,
1268   we emulate the song and dance performed by cp/tree.c:copy_binfo().  */
1269
1270static tree
1271objc_copy_binfo (tree binfo)
1272{
1273  tree btype = BINFO_TYPE (binfo);
1274  tree binfo2 = make_tree_binfo (BINFO_N_BASE_BINFOS (binfo));
1275  tree base_binfo;
1276  int ix;
1277
1278  BINFO_TYPE (binfo2) = btype;
1279  BINFO_OFFSET (binfo2) = BINFO_OFFSET (binfo);
1280  BINFO_BASE_ACCESSES (binfo2) = BINFO_BASE_ACCESSES (binfo);
1281
1282  /* Recursively copy base binfos of BINFO.  */
1283  for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
1284    {
1285      tree base_binfo2 = objc_copy_binfo (base_binfo);
1286
1287      BINFO_INHERITANCE_CHAIN (base_binfo2) = binfo2;
1288      BINFO_BASE_APPEND (binfo2, base_binfo2);
1289    }
1290
1291  return binfo2;
1292}
1293
1294/* Record superclass information provided in BASETYPE for ObjC class REF.
1295   This is loosely based on cp/decl.c:xref_basetypes().  */
1296
1297static void
1298objc_xref_basetypes (tree ref, tree basetype)
1299{
1300  tree binfo = make_tree_binfo (basetype ? 1 : 0);
1301
1302  TYPE_BINFO (ref) = binfo;
1303  BINFO_OFFSET (binfo) = size_zero_node;
1304  BINFO_TYPE (binfo) = ref;
1305
1306  if (basetype)
1307    {
1308      tree base_binfo = objc_copy_binfo (TYPE_BINFO (basetype));
1309
1310      BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
1311      BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, 1);
1312      BINFO_BASE_APPEND (binfo, base_binfo);
1313      BINFO_BASE_ACCESS_APPEND (binfo, access_public_node);
1314    }
1315}
1316
1317static hashval_t
1318volatilized_hash (const void *ptr)
1319{
1320  tree typ = ((struct volatilized_type *)ptr)->type;
1321
1322  return htab_hash_pointer(typ);
1323}
1324
1325static int
1326volatilized_eq (const void *ptr1, const void *ptr2)
1327{
1328  tree typ1 = ((struct volatilized_type *)ptr1)->type;
1329  tree typ2 = ((struct volatilized_type *)ptr2)->type;
1330
1331  return typ1 == typ2;
1332}
1333
1334/* Called from finish_decl.  */
1335
1336void
1337objc_check_decl (tree decl)
1338{
1339  tree type = TREE_TYPE (decl);
1340
1341  if (TREE_CODE (type) != RECORD_TYPE)
1342    return;
1343  if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
1344    error ("statically allocated instance of Objective-C class %qs",
1345	   IDENTIFIER_POINTER (type));
1346}
1347
1348/* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
1349   either name an Objective-C class, or refer to the special 'id' or 'Class'
1350   types.  If INTERFACE is not a valid ObjC type, just return it unchanged.  */
1351
1352tree
1353objc_get_protocol_qualified_type (tree interface, tree protocols)
1354{
1355  /* If INTERFACE is not provided, default to 'id'.  */
1356  tree type = (interface ? objc_is_id (interface) : objc_object_type);
1357  bool is_ptr = (type != NULL_TREE);
1358
1359  if (!is_ptr)
1360    {
1361      type = objc_is_class_name (interface);
1362
1363      if (type)
1364	type = xref_tag (RECORD_TYPE, type);
1365      else
1366        return interface;
1367    }
1368
1369  if (protocols)
1370    {
1371      type = build_variant_type_copy (type);
1372
1373      /* For pointers (i.e., 'id' or 'Class'), attach the protocol(s)
1374	 to the pointee.  */
1375      if (is_ptr)
1376	{
1377	  TREE_TYPE (type) = build_variant_type_copy (TREE_TYPE (type));
1378	  TYPE_POINTER_TO (TREE_TYPE (type)) = type;
1379	  type = TREE_TYPE (type);
1380	}
1381
1382      /* Look up protocols and install in lang specific list.  */
1383      DUP_TYPE_OBJC_INFO (type, TYPE_MAIN_VARIANT (type));
1384      TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols (protocols);
1385
1386      /* For RECORD_TYPEs, point to the @interface; for 'id' and 'Class',
1387	 return the pointer to the new pointee variant.  */
1388      if (is_ptr)
1389	type = TYPE_POINTER_TO (type);
1390      else
1391	TYPE_OBJC_INTERFACE (type)
1392	  = TYPE_OBJC_INTERFACE (TYPE_MAIN_VARIANT (type));
1393    }
1394
1395  return type;
1396}
1397
1398/* Check for circular dependencies in protocols.  The arguments are
1399   PROTO, the protocol to check, and LIST, a list of protocol it
1400   conforms to.  */
1401
1402static void
1403check_protocol_recursively (tree proto, tree list)
1404{
1405  tree p;
1406
1407  for (p = list; p; p = TREE_CHAIN (p))
1408    {
1409      tree pp = TREE_VALUE (p);
1410
1411      if (TREE_CODE (pp) == IDENTIFIER_NODE)
1412	pp = lookup_protocol (pp);
1413
1414      if (pp == proto)
1415	fatal_error ("protocol %qs has circular dependency",
1416		     IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1417      if (pp)
1418	check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1419    }
1420}
1421
1422/* Look up PROTOCOLS, and return a list of those that are found.
1423   If none are found, return NULL.  */
1424
1425static tree
1426lookup_and_install_protocols (tree protocols)
1427{
1428  tree proto;
1429  tree return_value = NULL_TREE;
1430
1431  for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1432    {
1433      tree ident = TREE_VALUE (proto);
1434      tree p = lookup_protocol (ident);
1435
1436      if (p)
1437	return_value = chainon (return_value,
1438				build_tree_list (NULL_TREE, p));
1439      else if (ident != error_mark_node)
1440	error ("cannot find protocol declaration for %qs",
1441	       IDENTIFIER_POINTER (ident));
1442    }
1443
1444  return return_value;
1445}
1446
1447/* Create a declaration for field NAME of a given TYPE.  */
1448
1449static tree
1450create_field_decl (tree type, const char *name)
1451{
1452  return build_decl (FIELD_DECL, get_identifier (name), type);
1453}
1454
1455/* Create a global, static declaration for variable NAME of a given TYPE.  The
1456   finish_var_decl() routine will need to be called on it afterwards.  */
1457
1458static tree
1459start_var_decl (tree type, const char *name)
1460{
1461  tree var = build_decl (VAR_DECL, get_identifier (name), type);
1462
1463  TREE_STATIC (var) = 1;
1464  DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
1465  DECL_IGNORED_P (var) = 1;
1466  DECL_ARTIFICIAL (var) = 1;
1467  DECL_CONTEXT (var) = NULL_TREE;
1468#ifdef OBJCPLUS
1469  DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
1470#endif
1471
1472  return var;
1473}
1474
1475/* Finish off the variable declaration created by start_var_decl().  */
1476
1477static void
1478finish_var_decl (tree var, tree initializer)
1479{
1480  finish_decl (var, initializer, NULL_TREE);
1481  /* Ensure that the variable actually gets output.  */
1482  mark_decl_referenced (var);
1483  /* Mark the decl to avoid "defined but not used" warning.  */
1484  TREE_USED (var) = 1;
1485}
1486
1487/* Find the decl for the constant string class reference.  This is only
1488   used for the NeXT runtime.  */
1489
1490static tree
1491setup_string_decl (void)
1492{
1493  char *name;
1494  size_t length;
1495
1496  /* %s in format will provide room for terminating null */
1497  length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1498	   + strlen (constant_string_class_name);
1499  name = xmalloc (length);
1500  sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1501	   constant_string_class_name);
1502  constant_string_global_id = get_identifier (name);
1503  string_class_decl = lookup_name (constant_string_global_id);
1504
1505  return string_class_decl;
1506}
1507
1508/* Purpose: "play" parser, creating/installing representations
1509   of the declarations that are required by Objective-C.
1510
1511   Model:
1512
1513	type_spec--------->sc_spec
1514	(tree_list)        (tree_list)
1515	    |                  |
1516	    |                  |
1517	identifier_node    identifier_node  */
1518
1519static void
1520synth_module_prologue (void)
1521{
1522  tree type;
1523  enum debug_info_type save_write_symbols = write_symbols;
1524  const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1525
1526  /* Suppress outputting debug symbols, because
1527     dbxout_init hasn'r been called yet.  */
1528  write_symbols = NO_DEBUG;
1529  debug_hooks = &do_nothing_debug_hooks;
1530
1531#ifdef OBJCPLUS
1532  push_lang_context (lang_name_c); /* extern "C" */
1533#endif
1534
1535  /* The following are also defined in <objc/objc.h> and friends.  */
1536
1537  objc_object_id = get_identifier (TAG_OBJECT);
1538  objc_class_id = get_identifier (TAG_CLASS);
1539
1540  objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1541  objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
1542
1543  objc_object_type = build_pointer_type (objc_object_reference);
1544  objc_class_type = build_pointer_type (objc_class_reference);
1545
1546  objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
1547  objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
1548
1549  /* Declare the 'id' and 'Class' typedefs.  */
1550
1551  type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1552						objc_object_name,
1553						objc_object_type));
1554  DECL_IN_SYSTEM_HEADER (type) = 1;
1555  type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1556						objc_class_name,
1557						objc_class_type));
1558  DECL_IN_SYSTEM_HEADER (type) = 1;
1559
1560  /* Forward-declare '@interface Protocol'.  */
1561
1562  type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1563  objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
1564  objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1565                                type));
1566
1567  /* Declare type of selector-objects that represent an operation name.  */
1568
1569  if (flag_next_runtime)
1570    /* `struct objc_selector *' */
1571    objc_selector_type
1572      = build_pointer_type (xref_tag (RECORD_TYPE,
1573				      get_identifier (TAG_SELECTOR)));
1574  else
1575    /* `const struct objc_selector *' */
1576    objc_selector_type
1577      = build_pointer_type
1578	(build_qualified_type (xref_tag (RECORD_TYPE,
1579					 get_identifier (TAG_SELECTOR)),
1580			       TYPE_QUAL_CONST));
1581
1582  /* Declare receiver type used for dispatching messages to 'super'.  */
1583
1584  /* `struct objc_super *' */
1585  objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1586						  get_identifier (TAG_SUPER)));
1587
1588  /* Declare pointers to method and ivar lists.  */
1589  objc_method_list_ptr = build_pointer_type
1590			 (xref_tag (RECORD_TYPE,
1591				    get_identifier (UTAG_METHOD_LIST)));
1592  objc_method_proto_list_ptr
1593    = build_pointer_type (xref_tag (RECORD_TYPE,
1594				    get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
1595  objc_ivar_list_ptr = build_pointer_type
1596		       (xref_tag (RECORD_TYPE,
1597				  get_identifier (UTAG_IVAR_LIST)));
1598
1599  /* TREE_NOTHROW is cleared for the message-sending functions,
1600     because the function that gets called can throw in Obj-C++, or
1601     could itself call something that can throw even in Obj-C.  */
1602
1603  if (flag_next_runtime)
1604    {
1605      /* NB: In order to call one of the ..._stret (struct-returning)
1606      functions, the function *MUST* first be cast to a signature that
1607      corresponds to the actual ObjC method being invoked.  This is
1608      what is done by the build_objc_method_call() routine below.  */
1609
1610      /* id objc_msgSend (id, SEL, ...); */
1611      /* id objc_msgSendNonNil (id, SEL, ...); */
1612      /* id objc_msgSend_stret (id, SEL, ...); */
1613      /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1614      type
1615	= build_function_type (objc_object_type,
1616			       tree_cons (NULL_TREE, objc_object_type,
1617					  tree_cons (NULL_TREE, objc_selector_type,
1618						     NULL_TREE)));
1619      umsg_decl = builtin_function (TAG_MSGSEND,
1620				    type, 0, NOT_BUILT_IN,
1621				    NULL, NULL_TREE);
1622      umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1623					   type, 0, NOT_BUILT_IN,
1624					   NULL, NULL_TREE);
1625      umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1626					  type, 0, NOT_BUILT_IN,
1627					  NULL, NULL_TREE);
1628      umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1629						 type, 0, NOT_BUILT_IN,
1630						 NULL, NULL_TREE);
1631
1632      /* These can throw, because the function that gets called can throw
1633	 in Obj-C++, or could itself call something that can throw even
1634	 in Obj-C.  */
1635      TREE_NOTHROW (umsg_decl) = 0;
1636      TREE_NOTHROW (umsg_nonnil_decl) = 0;
1637      TREE_NOTHROW (umsg_stret_decl) = 0;
1638      TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
1639
1640      /* id objc_msgSend_Fast (id, SEL, ...)
1641	   __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
1642#ifdef OFFS_MSGSEND_FAST
1643      umsg_fast_decl = builtin_function (TAG_MSGSEND_FAST,
1644					 type, 0, NOT_BUILT_IN,
1645					 NULL, NULL_TREE);
1646      TREE_NOTHROW (umsg_fast_decl) = 0;
1647      DECL_ATTRIBUTES (umsg_fast_decl)
1648	= tree_cons (get_identifier ("hard_coded_address"),
1649		     build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
1650		     NULL_TREE);
1651#else
1652      /* No direct dispatch availible.  */
1653      umsg_fast_decl = umsg_decl;
1654#endif
1655
1656      /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1657      /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1658      type
1659	= build_function_type (objc_object_type,
1660			       tree_cons (NULL_TREE, objc_super_type,
1661					  tree_cons (NULL_TREE, objc_selector_type,
1662						     NULL_TREE)));
1663      umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1664					  type, 0, NOT_BUILT_IN,
1665					  NULL, NULL_TREE);
1666      umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1667						type, 0, NOT_BUILT_IN, 0,
1668						NULL_TREE);
1669      TREE_NOTHROW (umsg_super_decl) = 0;
1670      TREE_NOTHROW (umsg_super_stret_decl) = 0;
1671    }
1672  else
1673    {
1674      /* GNU runtime messenger entry points.  */
1675
1676      /* typedef id (*IMP)(id, SEL, ...); */
1677      tree IMP_type
1678	= build_pointer_type
1679	  (build_function_type (objc_object_type,
1680				tree_cons (NULL_TREE, objc_object_type,
1681					   tree_cons (NULL_TREE, objc_selector_type,
1682						      NULL_TREE))));
1683
1684      /* IMP objc_msg_lookup (id, SEL); */
1685      type
1686        = build_function_type (IMP_type,
1687			       tree_cons (NULL_TREE, objc_object_type,
1688					  tree_cons (NULL_TREE, objc_selector_type,
1689						     OBJC_VOID_AT_END)));
1690      umsg_decl = builtin_function (TAG_MSGSEND,
1691				    type, 0, NOT_BUILT_IN,
1692				    NULL, NULL_TREE);
1693      TREE_NOTHROW (umsg_decl) = 0;
1694
1695      /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1696      type
1697        = build_function_type (IMP_type,
1698			       tree_cons (NULL_TREE, objc_super_type,
1699					  tree_cons (NULL_TREE, objc_selector_type,
1700						     OBJC_VOID_AT_END)));
1701      umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1702					  type, 0, NOT_BUILT_IN,
1703					  NULL, NULL_TREE);
1704      TREE_NOTHROW (umsg_super_decl) = 0;
1705
1706      /* The following GNU runtime entry point is called to initialize
1707	 each module:
1708
1709	 __objc_exec_class (void *); */
1710      type
1711	= build_function_type (void_type_node,
1712			       tree_cons (NULL_TREE, ptr_type_node,
1713					  OBJC_VOID_AT_END));
1714      execclass_decl = builtin_function (TAG_EXECCLASS,
1715					 type, 0, NOT_BUILT_IN,
1716					 NULL, NULL_TREE);
1717    }
1718
1719  /* id objc_getClass (const char *); */
1720
1721  type = build_function_type (objc_object_type,
1722				   tree_cons (NULL_TREE,
1723					      const_string_type_node,
1724					      OBJC_VOID_AT_END));
1725
1726  objc_get_class_decl
1727    = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
1728			NULL, NULL_TREE);
1729
1730  /* id objc_getMetaClass (const char *); */
1731
1732  objc_get_meta_class_decl
1733    = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1734
1735  build_class_template ();
1736  build_super_template ();
1737  build_protocol_template ();
1738  build_category_template ();
1739  build_objc_exception_stuff ();
1740
1741  if (flag_next_runtime)
1742    build_next_objc_exception_stuff ();
1743
1744  /* static SEL _OBJC_SELECTOR_TABLE[]; */
1745
1746  if (! flag_next_runtime)
1747    build_selector_table_decl ();
1748
1749  /* Forward declare constant_string_id and constant_string_type.  */
1750  if (!constant_string_class_name)
1751    constant_string_class_name = default_constant_string_class_name;
1752
1753  constant_string_id = get_identifier (constant_string_class_name);
1754  objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1755
1756  /* Pre-build the following entities - for speed/convenience.  */
1757  self_id = get_identifier ("self");
1758  ucmd_id = get_identifier ("_cmd");
1759
1760#ifdef OBJCPLUS
1761  pop_lang_context ();
1762#endif
1763
1764  write_symbols = save_write_symbols;
1765  debug_hooks = save_hooks;
1766}
1767
1768/* Ensure that the ivar list for NSConstantString/NXConstantString
1769   (or whatever was specified via `-fconstant-string-class')
1770   contains fields at least as large as the following three, so that
1771   the runtime can stomp on them with confidence:
1772
1773   struct STRING_OBJECT_CLASS_NAME
1774   {
1775     Object isa;
1776     char *cString;
1777     unsigned int length;
1778   }; */
1779
1780static int
1781check_string_class_template (void)
1782{
1783  tree field_decl = objc_get_class_ivars (constant_string_id);
1784
1785#define AT_LEAST_AS_LARGE_AS(F, T) \
1786  (F && TREE_CODE (F) == FIELD_DECL \
1787     && (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (F))) \
1788	 >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1789
1790  if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1791    return 0;
1792
1793  field_decl = TREE_CHAIN (field_decl);
1794  if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1795    return 0;
1796
1797  field_decl = TREE_CHAIN (field_decl);
1798  return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1799
1800#undef AT_LEAST_AS_LARGE_AS
1801}
1802
1803/* Avoid calling `check_string_class_template ()' more than once.  */
1804static GTY(()) int string_layout_checked;
1805
1806/* Construct an internal string layout to be used as a template for
1807   creating NSConstantString/NXConstantString instances.  */
1808
1809static tree
1810objc_build_internal_const_str_type (void)
1811{
1812  tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1813  tree fields = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
1814  tree field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
1815
1816  TREE_CHAIN (field) = fields; fields = field;
1817  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1818  TREE_CHAIN (field) = fields; fields = field;
1819  /* NB: The finish_builtin_struct() routine expects FIELD_DECLs in
1820     reverse order!  */
1821  finish_builtin_struct (type, "__builtin_ObjCString",
1822			 fields, NULL_TREE);
1823
1824  return type;
1825}
1826
1827/* Custom build_string which sets TREE_TYPE!  */
1828
1829static tree
1830my_build_string (int len, const char *str)
1831{
1832  return fix_string_type (build_string (len, str));
1833}
1834
1835/* Build a string with contents STR and length LEN and convert it to a
1836   pointer.  */
1837
1838static tree
1839my_build_string_pointer (int len, const char *str)
1840{
1841  tree string = my_build_string (len, str);
1842  tree ptrtype = build_pointer_type (TREE_TYPE (TREE_TYPE (string)));
1843  return build1 (ADDR_EXPR, ptrtype, string);
1844}
1845
1846static hashval_t
1847string_hash (const void *ptr)
1848{
1849  tree str = ((struct string_descriptor *)ptr)->literal;
1850  const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
1851  int i, len = TREE_STRING_LENGTH (str);
1852  hashval_t h = len;
1853
1854  for (i = 0; i < len; i++)
1855    h = ((h * 613) + p[i]);
1856
1857  return h;
1858}
1859
1860static int
1861string_eq (const void *ptr1, const void *ptr2)
1862{
1863  tree str1 = ((struct string_descriptor *)ptr1)->literal;
1864  tree str2 = ((struct string_descriptor *)ptr2)->literal;
1865  int len1 = TREE_STRING_LENGTH (str1);
1866
1867  return (len1 == TREE_STRING_LENGTH (str2)
1868	  && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
1869		      len1));
1870}
1871
1872/* Given a chain of STRING_CST's, build a static instance of
1873   NXConstantString which points at the concatenation of those
1874   strings.  We place the string object in the __string_objects
1875   section of the __OBJC segment.  The Objective-C runtime will
1876   initialize the isa pointers of the string objects to point at the
1877   NXConstantString class object.  */
1878
1879tree
1880objc_build_string_object (tree string)
1881{
1882  tree initlist, constructor, constant_string_class;
1883  int length;
1884  tree fields, addr;
1885  struct string_descriptor *desc, key;
1886  void **loc;
1887
1888  /* Prep the string argument.  */
1889  string = fix_string_type (string);
1890  TREE_SET_CODE (string, STRING_CST);
1891  length = TREE_STRING_LENGTH (string) - 1;
1892
1893  /* Check whether the string class being used actually exists and has the
1894     correct ivar layout.  */
1895  if (!string_layout_checked)
1896    {
1897      string_layout_checked = -1;
1898      constant_string_class = lookup_interface (constant_string_id);
1899      internal_const_str_type = objc_build_internal_const_str_type ();
1900
1901      if (!constant_string_class
1902	  || !(constant_string_type
1903	       = CLASS_STATIC_TEMPLATE (constant_string_class)))
1904	error ("cannot find interface declaration for %qs",
1905	       IDENTIFIER_POINTER (constant_string_id));
1906      /* The NSConstantString/NXConstantString ivar layout is now known.  */
1907      else if (!check_string_class_template ())
1908	error ("interface %qs does not have valid constant string layout",
1909	       IDENTIFIER_POINTER (constant_string_id));
1910      /* For the NeXT runtime, we can generate a literal reference
1911	 to the string class, don't need to run a constructor.  */
1912      else if (flag_next_runtime && !setup_string_decl ())
1913	error ("cannot find reference tag for class %qs",
1914	       IDENTIFIER_POINTER (constant_string_id));
1915      else
1916	{
1917	  string_layout_checked = 1;  /* Success!  */
1918	  add_class_reference (constant_string_id);
1919	}
1920    }
1921
1922  if (string_layout_checked == -1)
1923    return error_mark_node;
1924
1925  /* Perhaps we already constructed a constant string just like this one? */
1926  key.literal = string;
1927  loc = htab_find_slot (string_htab, &key, INSERT);
1928  desc = *loc;
1929
1930  if (!desc)
1931    {
1932      tree var;
1933      *loc = desc = ggc_alloc (sizeof (*desc));
1934      desc->literal = string;
1935
1936      /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
1937      /* NeXT:   (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length })   */
1938      fields = TYPE_FIELDS (internal_const_str_type);
1939      initlist
1940	= build_tree_list (fields,
1941			   flag_next_runtime
1942			   ? build_unary_op (ADDR_EXPR, string_class_decl, 0)
1943			   : build_int_cst (NULL_TREE, 0));
1944      fields = TREE_CHAIN (fields);
1945      initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1),
1946			    initlist);
1947      fields = TREE_CHAIN (fields);
1948      initlist = tree_cons (fields, build_int_cst (NULL_TREE, length),
1949 			    initlist);
1950      constructor = objc_build_constructor (internal_const_str_type,
1951					    nreverse (initlist));
1952      TREE_INVARIANT (constructor) = true;
1953
1954      if (!flag_next_runtime)
1955	constructor
1956	  = objc_add_static_instance (constructor, constant_string_type);
1957      else
1958        {
1959	  var = build_decl (CONST_DECL, NULL, TREE_TYPE (constructor));
1960	  DECL_INITIAL (var) = constructor;
1961	  TREE_STATIC (var) = 1;
1962	  pushdecl_top_level (var);
1963	  constructor = var;
1964	}
1965      desc->constructor = constructor;
1966    }
1967
1968  addr = convert (build_pointer_type (constant_string_type),
1969		  build_unary_op (ADDR_EXPR, desc->constructor, 1));
1970
1971  return addr;
1972}
1973
1974/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1975
1976static GTY(()) int num_static_inst;
1977
1978static tree
1979objc_add_static_instance (tree constructor, tree class_decl)
1980{
1981  tree *chain, decl;
1982  char buf[256];
1983
1984  /* Find the list of static instances for the CLASS_DECL.  Create one if
1985     not found.  */
1986  for (chain = &objc_static_instances;
1987       *chain && TREE_VALUE (*chain) != class_decl;
1988       chain = &TREE_CHAIN (*chain));
1989  if (!*chain)
1990    {
1991      *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1992      add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1993    }
1994
1995  sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1996  decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1997  DECL_COMMON (decl) = 1;
1998  TREE_STATIC (decl) = 1;
1999  DECL_ARTIFICIAL (decl) = 1;
2000  TREE_USED (decl) = 1;
2001  DECL_INITIAL (decl) = constructor;
2002
2003  /* We may be writing something else just now.
2004     Postpone till end of input.  */
2005  DECL_DEFER_OUTPUT (decl) = 1;
2006  pushdecl_top_level (decl);
2007  rest_of_decl_compilation (decl, 1, 0);
2008
2009  /* Add the DECL to the head of this CLASS' list.  */
2010  TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
2011
2012  return decl;
2013}
2014
2015/* Build a static constant CONSTRUCTOR
2016   with type TYPE and elements ELTS.  */
2017
2018static tree
2019objc_build_constructor (tree type, tree elts)
2020{
2021  tree constructor = build_constructor_from_list (type, elts);
2022
2023  TREE_CONSTANT (constructor) = 1;
2024  TREE_STATIC (constructor) = 1;
2025  TREE_READONLY (constructor) = 1;
2026
2027#ifdef OBJCPLUS
2028  /* Adjust for impedance mismatch.  We should figure out how to build
2029     CONSTRUCTORs that consistently please both the C and C++ gods.  */
2030  if (!TREE_PURPOSE (elts))
2031    TREE_TYPE (constructor) = NULL_TREE;
2032  TREE_HAS_CONSTRUCTOR (constructor) = 1;
2033#endif
2034
2035  return constructor;
2036}
2037
2038/* Take care of defining and initializing _OBJC_SYMBOLS.  */
2039
2040/* Predefine the following data type:
2041
2042   struct _objc_symtab
2043   {
2044     long sel_ref_cnt;
2045     SEL *refs;
2046     short cls_def_cnt;
2047     short cat_def_cnt;
2048     void *defs[cls_def_cnt + cat_def_cnt];
2049   }; */
2050
2051static void
2052build_objc_symtab_template (void)
2053{
2054  tree field_decl, field_decl_chain;
2055
2056  objc_symtab_template
2057    = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
2058
2059  /* long sel_ref_cnt; */
2060  field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt");
2061  field_decl_chain = field_decl;
2062
2063  /* SEL *refs; */
2064  field_decl = create_field_decl (build_pointer_type (objc_selector_type),
2065				  "refs");
2066  chainon (field_decl_chain, field_decl);
2067
2068  /* short cls_def_cnt; */
2069  field_decl = create_field_decl (short_integer_type_node, "cls_def_cnt");
2070  chainon (field_decl_chain, field_decl);
2071
2072  /* short cat_def_cnt; */
2073  field_decl = create_field_decl (short_integer_type_node,
2074				  "cat_def_cnt");
2075  chainon (field_decl_chain, field_decl);
2076
2077  if (imp_count || cat_count || !flag_next_runtime)
2078    {
2079      /* void *defs[imp_count + cat_count (+ 1)]; */
2080      /* NB: The index is one less than the size of the array.  */
2081      int index = imp_count + cat_count
2082		+ (flag_next_runtime? -1: 0);
2083      field_decl = create_field_decl
2084		   (build_array_type
2085		    (ptr_type_node,
2086		     build_index_type (build_int_cst (NULL_TREE, index))),
2087		    "defs");
2088      chainon (field_decl_chain, field_decl);
2089    }
2090
2091  finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
2092}
2093
2094/* Create the initial value for the `defs' field of _objc_symtab.
2095   This is a CONSTRUCTOR.  */
2096
2097static tree
2098init_def_list (tree type)
2099{
2100  tree expr, initlist = NULL_TREE;
2101  struct imp_entry *impent;
2102
2103  if (imp_count)
2104    for (impent = imp_list; impent; impent = impent->next)
2105      {
2106	if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2107	  {
2108	    expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
2109	    initlist = tree_cons (NULL_TREE, expr, initlist);
2110	  }
2111      }
2112
2113  if (cat_count)
2114    for (impent = imp_list; impent; impent = impent->next)
2115      {
2116	if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2117	  {
2118	    expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
2119	    initlist = tree_cons (NULL_TREE, expr, initlist);
2120	  }
2121      }
2122
2123  if (!flag_next_runtime)
2124    {
2125      /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
2126      tree expr;
2127
2128      if (static_instances_decl)
2129	expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
2130      else
2131	expr = build_int_cst (NULL_TREE, 0);
2132
2133      initlist = tree_cons (NULL_TREE, expr, initlist);
2134    }
2135
2136  return objc_build_constructor (type, nreverse (initlist));
2137}
2138
2139/* Construct the initial value for all of _objc_symtab.  */
2140
2141static tree
2142init_objc_symtab (tree type)
2143{
2144  tree initlist;
2145
2146  /* sel_ref_cnt = { ..., 5, ... } */
2147
2148  initlist = build_tree_list (NULL_TREE,
2149			      build_int_cst (long_integer_type_node, 0));
2150
2151  /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2152
2153  if (flag_next_runtime || ! sel_ref_chain)
2154    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2155  else
2156    initlist
2157      = tree_cons (NULL_TREE,
2158		   convert (build_pointer_type (objc_selector_type),
2159			    build_unary_op (ADDR_EXPR,
2160					    UOBJC_SELECTOR_TABLE_decl, 1)),
2161		   initlist);
2162
2163  /* cls_def_cnt = { ..., 5, ... } */
2164
2165  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
2166
2167  /* cat_def_cnt = { ..., 5, ... } */
2168
2169  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
2170
2171  /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2172
2173  if (imp_count || cat_count || !flag_next_runtime)
2174    {
2175
2176      tree field = TYPE_FIELDS (type);
2177      field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
2178
2179      initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
2180			    initlist);
2181    }
2182
2183  return objc_build_constructor (type, nreverse (initlist));
2184}
2185
2186/* Generate forward declarations for metadata such as
2187  'OBJC_CLASS_...'.  */
2188
2189static tree
2190build_metadata_decl (const char *name, tree type)
2191{
2192  tree decl;
2193
2194  /* struct TYPE NAME_<name>; */
2195  decl = start_var_decl (type, synth_id_with_class_suffix
2196			       (name,
2197				objc_implementation_context));
2198
2199  return decl;
2200}
2201
2202/* Push forward-declarations of all the categories so that
2203   init_def_list can use them in a CONSTRUCTOR.  */
2204
2205static void
2206forward_declare_categories (void)
2207{
2208  struct imp_entry *impent;
2209  tree sav = objc_implementation_context;
2210
2211  for (impent = imp_list; impent; impent = impent->next)
2212    {
2213      if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2214	{
2215	  /* Set an invisible arg to synth_id_with_class_suffix.  */
2216	  objc_implementation_context = impent->imp_context;
2217	  /* extern struct objc_category _OBJC_CATEGORY_<name>; */
2218	  impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
2219						    objc_category_template);
2220	}
2221    }
2222  objc_implementation_context = sav;
2223}
2224
2225/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2226   and initialized appropriately.  */
2227
2228static void
2229generate_objc_symtab_decl (void)
2230{
2231  /* forward declare categories */
2232  if (cat_count)
2233    forward_declare_categories ();
2234
2235  build_objc_symtab_template ();
2236  UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2237  finish_var_decl (UOBJC_SYMBOLS_decl,
2238		   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2239}
2240
2241static tree
2242init_module_descriptor (tree type)
2243{
2244  tree initlist, expr;
2245
2246  /* version = { 1, ... } */
2247
2248  expr = build_int_cst (long_integer_type_node, OBJC_VERSION);
2249  initlist = build_tree_list (NULL_TREE, expr);
2250
2251  /* size = { ..., sizeof (struct _objc_module), ... } */
2252
2253  expr = convert (long_integer_type_node,
2254		  size_in_bytes (objc_module_template));
2255  initlist = tree_cons (NULL_TREE, expr, initlist);
2256
2257  /* Don't provide any file name for security reasons. */
2258  /* name = { ..., "", ... } */
2259
2260  expr = add_objc_string (get_identifier (""), class_names);
2261  initlist = tree_cons (NULL_TREE, expr, initlist);
2262
2263  /* symtab = { ..., _OBJC_SYMBOLS, ... } */
2264
2265  if (UOBJC_SYMBOLS_decl)
2266    expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
2267  else
2268    expr = build_int_cst (NULL_TREE, 0);
2269  initlist = tree_cons (NULL_TREE, expr, initlist);
2270
2271  return objc_build_constructor (type, nreverse (initlist));
2272}
2273
2274/* Write out the data structures to describe Objective C classes defined.
2275
2276   struct _objc_module { ... } _OBJC_MODULE = { ... };   */
2277
2278static void
2279build_module_descriptor (void)
2280{
2281  tree field_decl, field_decl_chain;
2282
2283#ifdef OBJCPLUS
2284  push_lang_context (lang_name_c); /* extern "C" */
2285#endif
2286
2287  objc_module_template
2288    = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
2289
2290  /* long version; */
2291  field_decl = create_field_decl (long_integer_type_node, "version");
2292  field_decl_chain = field_decl;
2293
2294  /* long size; */
2295  field_decl = create_field_decl (long_integer_type_node, "size");
2296  chainon (field_decl_chain, field_decl);
2297
2298  /* char *name; */
2299  field_decl = create_field_decl (string_type_node, "name");
2300  chainon (field_decl_chain, field_decl);
2301
2302  /* struct _objc_symtab *symtab; */
2303  field_decl
2304    = create_field_decl (build_pointer_type
2305			 (xref_tag (RECORD_TYPE,
2306				    get_identifier (UTAG_SYMTAB))),
2307			 "symtab");
2308  chainon (field_decl_chain, field_decl);
2309
2310  finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
2311
2312  /* Create an instance of "_objc_module".  */
2313  UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
2314  finish_var_decl (UOBJC_MODULES_decl,
2315		   init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
2316
2317#ifdef OBJCPLUS
2318  pop_lang_context ();
2319#endif
2320}
2321
2322/* The GNU runtime requires us to provide a static initializer function
2323   for each module:
2324
2325   static void __objc_gnu_init (void) {
2326     __objc_exec_class (&L_OBJC_MODULES);
2327   }  */
2328
2329static void
2330build_module_initializer_routine (void)
2331{
2332  tree body;
2333
2334#ifdef OBJCPLUS
2335  push_lang_context (lang_name_c); /* extern "C" */
2336#endif
2337
2338  objc_push_parm (build_decl (PARM_DECL, NULL_TREE, void_type_node));
2339  objc_start_function (get_identifier (TAG_GNUINIT),
2340		       build_function_type (void_type_node,
2341					    OBJC_VOID_AT_END),
2342		       NULL_TREE, objc_get_parm_info (0));
2343
2344  body = c_begin_compound_stmt (true);
2345  add_stmt (build_function_call
2346	    (execclass_decl,
2347	     build_tree_list
2348	     (NULL_TREE,
2349	      build_unary_op (ADDR_EXPR,
2350			      UOBJC_MODULES_decl, 0))));
2351  add_stmt (c_end_compound_stmt (body, true));
2352
2353  TREE_PUBLIC (current_function_decl) = 0;
2354
2355#ifndef OBJCPLUS
2356  /* For Objective-C++, we will need to call __objc_gnu_init
2357     from objc_generate_static_init_call() below.  */
2358  DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
2359#endif
2360
2361  GNU_INIT_decl = current_function_decl;
2362  finish_function ();
2363
2364#ifdef OBJCPLUS
2365    pop_lang_context ();
2366#endif
2367}
2368
2369#ifdef OBJCPLUS
2370/* Return 1 if the __objc_gnu_init function has been synthesized and needs
2371   to be called by the module initializer routine.  */
2372
2373int
2374objc_static_init_needed_p (void)
2375{
2376  return (GNU_INIT_decl != NULL_TREE);
2377}
2378
2379/* Generate a call to the __objc_gnu_init initializer function.  */
2380
2381tree
2382objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
2383{
2384  add_stmt (build_stmt (EXPR_STMT,
2385			build_function_call (GNU_INIT_decl, NULL_TREE)));
2386
2387  return ctors;
2388}
2389#endif /* OBJCPLUS */
2390
2391/* Return the DECL of the string IDENT in the SECTION.  */
2392
2393static tree
2394get_objc_string_decl (tree ident, enum string_section section)
2395{
2396  tree chain;
2397
2398  if (section == class_names)
2399    chain = class_names_chain;
2400  else if (section == meth_var_names)
2401    chain = meth_var_names_chain;
2402  else if (section == meth_var_types)
2403    chain = meth_var_types_chain;
2404  else
2405    abort ();
2406
2407  for (; chain != 0; chain = TREE_CHAIN (chain))
2408    if (TREE_VALUE (chain) == ident)
2409      return (TREE_PURPOSE (chain));
2410
2411  abort ();
2412  return NULL_TREE;
2413}
2414
2415/* Output references to all statically allocated objects.  Return the DECL
2416   for the array built.  */
2417
2418static void
2419generate_static_references (void)
2420{
2421  tree decls = NULL_TREE, expr = NULL_TREE;
2422  tree class_name, class, decl, initlist;
2423  tree cl_chain, in_chain, type
2424    = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
2425  int num_inst, num_class;
2426  char buf[256];
2427
2428  if (flag_next_runtime)
2429    abort ();
2430
2431  for (cl_chain = objc_static_instances, num_class = 0;
2432       cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
2433    {
2434      for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
2435	   in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
2436
2437      sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
2438      decl = start_var_decl (type, buf);
2439
2440      /* Output {class_name, ...}.  */
2441      class = TREE_VALUE (cl_chain);
2442      class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
2443      initlist = build_tree_list (NULL_TREE,
2444				  build_unary_op (ADDR_EXPR, class_name, 1));
2445
2446      /* Output {..., instance, ...}.  */
2447      for (in_chain = TREE_PURPOSE (cl_chain);
2448	   in_chain; in_chain = TREE_CHAIN (in_chain))
2449	{
2450	  expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2451	  initlist = tree_cons (NULL_TREE, expr, initlist);
2452	}
2453
2454      /* Output {..., NULL}.  */
2455      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2456
2457      expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2458      finish_var_decl (decl, expr);
2459      decls
2460	= tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2461    }
2462
2463  decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
2464  expr = objc_build_constructor (type, nreverse (decls));
2465  static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
2466  finish_var_decl (static_instances_decl, expr);
2467}
2468
2469static GTY(()) int selector_reference_idx;
2470
2471static tree
2472build_selector_reference_decl (void)
2473{
2474  tree decl;
2475  char buf[256];
2476
2477  sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2478  decl = start_var_decl (objc_selector_type, buf);
2479
2480  return decl;
2481}
2482
2483static void
2484build_selector_table_decl (void)
2485{
2486  tree temp;
2487
2488  if (flag_typed_selectors)
2489    {
2490      build_selector_template ();
2491      temp = build_array_type (objc_selector_template, NULL_TREE);
2492    }
2493  else
2494    temp = build_array_type (objc_selector_type, NULL_TREE);
2495
2496  UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
2497}
2498
2499/* Just a handy wrapper for add_objc_string.  */
2500
2501static tree
2502build_selector (tree ident)
2503{
2504  return convert (objc_selector_type,
2505		  add_objc_string (ident, meth_var_names));
2506}
2507
2508static void
2509build_selector_translation_table (void)
2510{
2511  tree chain, initlist = NULL_TREE;
2512  int offset = 0;
2513  tree decl = NULL_TREE;
2514
2515  for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2516    {
2517      tree expr;
2518
2519      if (warn_selector && objc_implementation_context)
2520      {
2521        tree method_chain;
2522        bool found = false;
2523        for (method_chain = meth_var_names_chain;
2524             method_chain;
2525             method_chain = TREE_CHAIN (method_chain))
2526          {
2527            if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2528              {
2529                found = true;
2530                break;
2531              }
2532          }
2533        if (!found)
2534	  {
2535	    location_t *loc;
2536	    if (flag_next_runtime && TREE_PURPOSE (chain))
2537	      loc = &DECL_SOURCE_LOCATION (TREE_PURPOSE (chain));
2538	    else
2539	      loc = &input_location;
2540	    warning (0, "%Hcreating selector for nonexistent method %qE",
2541		     loc, TREE_VALUE (chain));
2542	  }
2543      }
2544
2545      expr = build_selector (TREE_VALUE (chain));
2546      /* add one for the '\0' character */
2547      offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2548
2549      if (flag_next_runtime)
2550	{
2551	  decl = TREE_PURPOSE (chain);
2552	  finish_var_decl (decl, expr);
2553	}
2554      else
2555	{
2556	  if (flag_typed_selectors)
2557	    {
2558	      tree eltlist = NULL_TREE;
2559	      tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2560	      eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2561	      eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2562	      expr = objc_build_constructor (objc_selector_template,
2563					     nreverse (eltlist));
2564	    }
2565
2566	  initlist = tree_cons (NULL_TREE, expr, initlist);
2567	}
2568    }
2569
2570  if (! flag_next_runtime)
2571    {
2572      /* Cause the selector table (previously forward-declared)
2573	 to be actually output.  */
2574      initlist = tree_cons (NULL_TREE,
2575			    flag_typed_selectors
2576			    ? objc_build_constructor
2577			      (objc_selector_template,
2578			       tree_cons (NULL_TREE,
2579					  build_int_cst (NULL_TREE, 0),
2580					  tree_cons (NULL_TREE,
2581						     build_int_cst (NULL_TREE, 0),
2582						     NULL_TREE)))
2583			    : build_int_cst (NULL_TREE, 0), initlist);
2584      initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2585					 nreverse (initlist));
2586      finish_var_decl (UOBJC_SELECTOR_TABLE_decl, initlist);
2587    }
2588}
2589
2590static tree
2591get_proto_encoding (tree proto)
2592{
2593  tree encoding;
2594  if (proto)
2595    {
2596      if (! METHOD_ENCODING (proto))
2597	{
2598	  encoding = encode_method_prototype (proto);
2599	  METHOD_ENCODING (proto) = encoding;
2600	}
2601      else
2602	encoding = METHOD_ENCODING (proto);
2603
2604      return add_objc_string (encoding, meth_var_types);
2605    }
2606  else
2607    return build_int_cst (NULL_TREE, 0);
2608}
2609
2610/* sel_ref_chain is a list whose "value" fields will be instances of
2611   identifier_node that represent the selector.  */
2612
2613static tree
2614build_typed_selector_reference (tree ident, tree prototype)
2615{
2616  tree *chain = &sel_ref_chain;
2617  tree expr;
2618  int index = 0;
2619
2620  while (*chain)
2621    {
2622      if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2623	goto return_at_index;
2624
2625      index++;
2626      chain = &TREE_CHAIN (*chain);
2627    }
2628
2629  *chain = tree_cons (prototype, ident, NULL_TREE);
2630
2631 return_at_index:
2632  expr = build_unary_op (ADDR_EXPR,
2633			 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2634					  build_int_cst (NULL_TREE, index)),
2635			 1);
2636  return convert (objc_selector_type, expr);
2637}
2638
2639static tree
2640build_selector_reference (tree ident)
2641{
2642  tree *chain = &sel_ref_chain;
2643  tree expr;
2644  int index = 0;
2645
2646  while (*chain)
2647    {
2648      if (TREE_VALUE (*chain) == ident)
2649	return (flag_next_runtime
2650		? TREE_PURPOSE (*chain)
2651		: build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2652				   build_int_cst (NULL_TREE, index)));
2653
2654      index++;
2655      chain = &TREE_CHAIN (*chain);
2656    }
2657
2658  expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
2659
2660  *chain = tree_cons (expr, ident, NULL_TREE);
2661
2662  return (flag_next_runtime
2663	  ? expr
2664	  : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2665			     build_int_cst (NULL_TREE, index)));
2666}
2667
2668static GTY(()) int class_reference_idx;
2669
2670static tree
2671build_class_reference_decl (void)
2672{
2673  tree decl;
2674  char buf[256];
2675
2676  sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2677  decl = start_var_decl (objc_class_type, buf);
2678
2679  return decl;
2680}
2681
2682/* Create a class reference, but don't create a variable to reference
2683   it.  */
2684
2685static void
2686add_class_reference (tree ident)
2687{
2688  tree chain;
2689
2690  if ((chain = cls_ref_chain))
2691    {
2692      tree tail;
2693      do
2694        {
2695	  if (ident == TREE_VALUE (chain))
2696	    return;
2697
2698	  tail = chain;
2699	  chain = TREE_CHAIN (chain);
2700        }
2701      while (chain);
2702
2703      /* Append to the end of the list */
2704      TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2705    }
2706  else
2707    cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2708}
2709
2710/* Get a class reference, creating it if necessary.  Also create the
2711   reference variable.  */
2712
2713tree
2714objc_get_class_reference (tree ident)
2715{
2716  tree orig_ident = (DECL_P (ident)
2717		     ? DECL_NAME (ident)
2718		     : TYPE_P (ident)
2719		     ? OBJC_TYPE_NAME (ident)
2720		     : ident);
2721  bool local_scope = false;
2722
2723#ifdef OBJCPLUS
2724  if (processing_template_decl)
2725    /* Must wait until template instantiation time.  */
2726    return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2727#endif
2728
2729  if (TREE_CODE (ident) == TYPE_DECL)
2730    ident = (DECL_ORIGINAL_TYPE (ident)
2731	     ? DECL_ORIGINAL_TYPE (ident)
2732	     : TREE_TYPE (ident));
2733
2734#ifdef OBJCPLUS
2735  if (TYPE_P (ident) && TYPE_CONTEXT (ident)
2736      && TYPE_CONTEXT (ident) != global_namespace)
2737    local_scope = true;
2738#endif
2739
2740  if (local_scope || !(ident = objc_is_class_name (ident)))
2741    {
2742      error ("%qs is not an Objective-C class name or alias",
2743	     IDENTIFIER_POINTER (orig_ident));
2744      return error_mark_node;
2745    }
2746
2747  if (flag_next_runtime && !flag_zero_link)
2748    {
2749      tree *chain;
2750      tree decl;
2751
2752      for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2753	if (TREE_VALUE (*chain) == ident)
2754	  {
2755	    if (! TREE_PURPOSE (*chain))
2756	      TREE_PURPOSE (*chain) = build_class_reference_decl ();
2757
2758	    return TREE_PURPOSE (*chain);
2759	  }
2760
2761      decl = build_class_reference_decl ();
2762      *chain = tree_cons (decl, ident, NULL_TREE);
2763      return decl;
2764    }
2765  else
2766    {
2767      tree params;
2768
2769      add_class_reference (ident);
2770
2771      params = build_tree_list (NULL_TREE,
2772				my_build_string_pointer
2773				(IDENTIFIER_LENGTH (ident) + 1,
2774				 IDENTIFIER_POINTER (ident)));
2775
2776      assemble_external (objc_get_class_decl);
2777      return build_function_call (objc_get_class_decl, params);
2778    }
2779}
2780
2781/* For each string section we have a chain which maps identifier nodes
2782   to decls for the strings.  */
2783
2784static tree
2785add_objc_string (tree ident, enum string_section section)
2786{
2787  tree *chain, decl, type, string_expr;
2788
2789  if (section == class_names)
2790    chain = &class_names_chain;
2791  else if (section == meth_var_names)
2792    chain = &meth_var_names_chain;
2793  else if (section == meth_var_types)
2794    chain = &meth_var_types_chain;
2795  else
2796    abort ();
2797
2798  while (*chain)
2799    {
2800      if (TREE_VALUE (*chain) == ident)
2801	return convert (string_type_node,
2802			build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1));
2803
2804      chain = &TREE_CHAIN (*chain);
2805    }
2806
2807  decl = build_objc_string_decl (section);
2808
2809  type = build_array_type
2810	 (char_type_node,
2811	  build_index_type
2812	  (build_int_cst (NULL_TREE,
2813			  IDENTIFIER_LENGTH (ident))));
2814  decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2815  string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2816				 IDENTIFIER_POINTER (ident));
2817  finish_var_decl (decl, string_expr);
2818
2819  *chain = tree_cons (decl, ident, NULL_TREE);
2820
2821  return convert (string_type_node, build_unary_op (ADDR_EXPR, decl, 1));
2822}
2823
2824static GTY(()) int class_names_idx;
2825static GTY(()) int meth_var_names_idx;
2826static GTY(()) int meth_var_types_idx;
2827
2828static tree
2829build_objc_string_decl (enum string_section section)
2830{
2831  tree decl, ident;
2832  char buf[256];
2833
2834  if (section == class_names)
2835    sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2836  else if (section == meth_var_names)
2837    sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2838  else if (section == meth_var_types)
2839    sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2840
2841  ident = get_identifier (buf);
2842
2843  decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2844  DECL_EXTERNAL (decl) = 1;
2845  TREE_PUBLIC (decl) = 0;
2846  TREE_USED (decl) = 1;
2847  TREE_CONSTANT (decl) = 1;
2848  DECL_CONTEXT (decl) = 0;
2849  DECL_ARTIFICIAL (decl) = 1;
2850#ifdef OBJCPLUS
2851  DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */
2852#endif
2853
2854  make_decl_rtl (decl);
2855  pushdecl_top_level (decl);
2856
2857  return decl;
2858}
2859
2860
2861void
2862objc_declare_alias (tree alias_ident, tree class_ident)
2863{
2864  tree underlying_class;
2865
2866#ifdef OBJCPLUS
2867  if (current_namespace != global_namespace) {
2868    error ("Objective-C declarations may only appear in global scope");
2869  }
2870#endif /* OBJCPLUS */
2871
2872  if (!(underlying_class = objc_is_class_name (class_ident)))
2873    warning (0, "cannot find class %qs", IDENTIFIER_POINTER (class_ident));
2874  else if (objc_is_class_name (alias_ident))
2875    warning (0, "class %qs already exists", IDENTIFIER_POINTER (alias_ident));
2876  else
2877    {
2878      /* Implement @compatibility_alias as a typedef.  */
2879#ifdef OBJCPLUS
2880      push_lang_context (lang_name_c); /* extern "C" */
2881#endif
2882      lang_hooks.decls.pushdecl (build_decl
2883				 (TYPE_DECL,
2884				  alias_ident,
2885				  xref_tag (RECORD_TYPE, underlying_class)));
2886#ifdef OBJCPLUS
2887      pop_lang_context ();
2888#endif
2889      alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2890    }
2891}
2892
2893void
2894objc_declare_class (tree ident_list)
2895{
2896  tree list;
2897#ifdef OBJCPLUS
2898  if (current_namespace != global_namespace) {
2899    error ("Objective-C declarations may only appear in global scope");
2900  }
2901#endif /* OBJCPLUS */
2902
2903  for (list = ident_list; list; list = TREE_CHAIN (list))
2904    {
2905      tree ident = TREE_VALUE (list);
2906
2907      if (! objc_is_class_name (ident))
2908	{
2909	  tree record = lookup_name (ident), type = record;
2910
2911	  if (record)
2912	    {
2913	      if (TREE_CODE (record) == TYPE_DECL)
2914		type = DECL_ORIGINAL_TYPE (record);
2915
2916	      if (!TYPE_HAS_OBJC_INFO (type)
2917		  || !TYPE_OBJC_INTERFACE (type))
2918		{
2919		  error ("%qs redeclared as different kind of symbol",
2920			 IDENTIFIER_POINTER (ident));
2921		  error ("previous declaration of %q+D",
2922			 record);
2923		}
2924	    }
2925
2926	  record = xref_tag (RECORD_TYPE, ident);
2927	  INIT_TYPE_OBJC_INFO (record);
2928	  TYPE_OBJC_INTERFACE (record) = ident;
2929	  class_chain = tree_cons (NULL_TREE, ident, class_chain);
2930	}
2931    }
2932}
2933
2934tree
2935objc_is_class_name (tree ident)
2936{
2937  tree chain;
2938
2939  if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2940      && identifier_global_value (ident))
2941    ident = identifier_global_value (ident);
2942  while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2943    ident = OBJC_TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2944
2945  if (ident && TREE_CODE (ident) == RECORD_TYPE)
2946    ident = OBJC_TYPE_NAME (ident);
2947#ifdef OBJCPLUS
2948  if (ident && TREE_CODE (ident) == TYPE_DECL)
2949    ident = DECL_NAME (ident);
2950#endif
2951  if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2952    return NULL_TREE;
2953
2954  if (lookup_interface (ident))
2955    return ident;
2956
2957  for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2958    {
2959      if (ident == TREE_VALUE (chain))
2960	return ident;
2961    }
2962
2963  for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2964    {
2965      if (ident == TREE_VALUE (chain))
2966	return TREE_PURPOSE (chain);
2967    }
2968
2969  return 0;
2970}
2971
2972/* Check whether TYPE is either 'id' or 'Class'.  */
2973
2974tree
2975objc_is_id (tree type)
2976{
2977  if (type && TREE_CODE (type) == IDENTIFIER_NODE
2978      && identifier_global_value (type))
2979    type = identifier_global_value (type);
2980
2981  if (type && TREE_CODE (type) == TYPE_DECL)
2982    type = TREE_TYPE (type);
2983
2984  /* NB: This function may be called before the ObjC front-end has
2985     been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL.  */
2986  return (objc_object_type && type
2987	  && (IS_ID (type) || IS_CLASS (type) || IS_SUPER (type))
2988	  ? type
2989	  : NULL_TREE);
2990}
2991
2992/* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
2993   class instance.  This is needed by other parts of the compiler to
2994   handle ObjC types gracefully.  */
2995
2996tree
2997objc_is_object_ptr (tree type)
2998{
2999  tree ret;
3000
3001  type = TYPE_MAIN_VARIANT (type);
3002  if (!POINTER_TYPE_P (type))
3003    return 0;
3004
3005  ret = objc_is_id (type);
3006  if (!ret)
3007    ret = objc_is_class_name (TREE_TYPE (type));
3008
3009  return ret;
3010}
3011
3012static int
3013objc_is_gcable_type (tree type, int or_strong_p)
3014{
3015  tree name;
3016
3017  if (!TYPE_P (type))
3018    return 0;
3019  if (objc_is_id (TYPE_MAIN_VARIANT (type)))
3020    return 1;
3021  if (or_strong_p && lookup_attribute ("objc_gc", TYPE_ATTRIBUTES (type)))
3022    return 1;
3023  if (TREE_CODE (type) != POINTER_TYPE && TREE_CODE (type) != INDIRECT_REF)
3024    return 0;
3025  type = TREE_TYPE (type);
3026  if (TREE_CODE (type) != RECORD_TYPE)
3027    return 0;
3028  name = TYPE_NAME (type);
3029  return (objc_is_class_name (name) != NULL_TREE);
3030}
3031
3032static tree
3033objc_substitute_decl (tree expr, tree oldexpr, tree newexpr)
3034{
3035  if (expr == oldexpr)
3036    return newexpr;
3037
3038  switch (TREE_CODE (expr))
3039    {
3040    case COMPONENT_REF:
3041      return objc_build_component_ref
3042	     (objc_substitute_decl (TREE_OPERAND (expr, 0),
3043				    oldexpr,
3044				    newexpr),
3045	      DECL_NAME (TREE_OPERAND (expr, 1)));
3046    case ARRAY_REF:
3047      return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
3048						    oldexpr,
3049						    newexpr),
3050			      TREE_OPERAND (expr, 1));
3051    case INDIRECT_REF:
3052      return build_indirect_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
3053						       oldexpr,
3054						       newexpr), "->");
3055    default:
3056      return expr;
3057    }
3058}
3059
3060static tree
3061objc_build_ivar_assignment (tree outervar, tree lhs, tree rhs)
3062{
3063  tree func_params;
3064  /* The LHS parameter contains the expression 'outervar->memberspec';
3065     we need to transform it into '&((typeof(outervar) *) 0)->memberspec',
3066     where memberspec may be arbitrarily complex (e.g., 'g->f.d[2].g[3]').
3067  */
3068  tree offs
3069    = objc_substitute_decl
3070      (lhs, outervar, convert (TREE_TYPE (outervar), integer_zero_node));
3071  tree func
3072    = (flag_objc_direct_dispatch
3073       ? objc_assign_ivar_fast_decl
3074       : objc_assign_ivar_decl);
3075
3076  offs = convert (integer_type_node, build_unary_op (ADDR_EXPR, offs, 0));
3077  offs = fold (offs);
3078  func_params = tree_cons (NULL_TREE,
3079	convert (objc_object_type, rhs),
3080	    tree_cons (NULL_TREE, convert (objc_object_type, outervar),
3081		tree_cons (NULL_TREE, offs,
3082		    NULL_TREE)));
3083
3084  assemble_external (func);
3085  return build_function_call (func, func_params);
3086}
3087
3088static tree
3089objc_build_global_assignment (tree lhs, tree rhs)
3090{
3091  tree func_params = tree_cons (NULL_TREE,
3092	convert (objc_object_type, rhs),
3093	    tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3094		      build_unary_op (ADDR_EXPR, lhs, 0)),
3095		    NULL_TREE));
3096
3097  assemble_external (objc_assign_global_decl);
3098  return build_function_call (objc_assign_global_decl, func_params);
3099}
3100
3101static tree
3102objc_build_strong_cast_assignment (tree lhs, tree rhs)
3103{
3104  tree func_params = tree_cons (NULL_TREE,
3105	convert (objc_object_type, rhs),
3106	    tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
3107		      build_unary_op (ADDR_EXPR, lhs, 0)),
3108		    NULL_TREE));
3109
3110  assemble_external (objc_assign_strong_cast_decl);
3111  return build_function_call (objc_assign_strong_cast_decl, func_params);
3112}
3113
3114static int
3115objc_is_gcable_p (tree expr)
3116{
3117  return (TREE_CODE (expr) == COMPONENT_REF
3118	  ? objc_is_gcable_p (TREE_OPERAND (expr, 1))
3119	  : TREE_CODE (expr) == ARRAY_REF
3120	  ? (objc_is_gcable_p (TREE_TYPE (expr))
3121	     || objc_is_gcable_p (TREE_OPERAND (expr, 0)))
3122	  : TREE_CODE (expr) == ARRAY_TYPE
3123	  ? objc_is_gcable_p (TREE_TYPE (expr))
3124	  : TYPE_P (expr)
3125	  ? objc_is_gcable_type (expr, 1)
3126	  : (objc_is_gcable_p (TREE_TYPE (expr))
3127	     || (DECL_P (expr)
3128		 && lookup_attribute ("objc_gc", DECL_ATTRIBUTES (expr)))));
3129}
3130
3131static int
3132objc_is_ivar_reference_p (tree expr)
3133{
3134  return (TREE_CODE (expr) == ARRAY_REF
3135	  ? objc_is_ivar_reference_p (TREE_OPERAND (expr, 0))
3136	  : TREE_CODE (expr) == COMPONENT_REF
3137	  ? TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL
3138	  : 0);
3139}
3140
3141static int
3142objc_is_global_reference_p (tree expr)
3143{
3144  return (TREE_CODE (expr) == INDIRECT_REF || TREE_CODE (expr) == PLUS_EXPR
3145	  ? objc_is_global_reference_p (TREE_OPERAND (expr, 0))
3146	  : DECL_P (expr)
3147	  ? (!DECL_CONTEXT (expr) || TREE_STATIC (expr))
3148	  : 0);
3149}
3150
3151tree
3152objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
3153{
3154  tree result = NULL_TREE, outer;
3155  int strong_cast_p = 0, outer_gc_p = 0, indirect_p = 0;
3156
3157  /* See if we have any lhs casts, and strip them out.  NB: The lvalue casts
3158     will have been transformed to the form '*(type *)&expr'.  */
3159  if (TREE_CODE (lhs) == INDIRECT_REF)
3160    {
3161      outer = TREE_OPERAND (lhs, 0);
3162
3163      while (!strong_cast_p
3164	     && (TREE_CODE (outer) == CONVERT_EXPR
3165		 || TREE_CODE (outer) == NOP_EXPR
3166		 || TREE_CODE (outer) == NON_LVALUE_EXPR))
3167	{
3168	  tree lhstype = TREE_TYPE (outer);
3169
3170	  /* Descend down the cast chain, and record the first objc_gc
3171	     attribute found.  */
3172	  if (POINTER_TYPE_P (lhstype))
3173	    {
3174	      tree attr
3175		= lookup_attribute ("objc_gc",
3176				    TYPE_ATTRIBUTES (TREE_TYPE (lhstype)));
3177
3178	      if (attr)
3179		strong_cast_p = 1;
3180	    }
3181
3182	  outer = TREE_OPERAND (outer, 0);
3183	}
3184    }
3185
3186  /* If we have a __strong cast, it trumps all else.  */
3187  if (strong_cast_p)
3188    {
3189      if (modifycode != NOP_EXPR)
3190        goto invalid_pointer_arithmetic;
3191
3192      if (warn_assign_intercept)
3193	warning (0, "strong-cast assignment has been intercepted");
3194
3195      result = objc_build_strong_cast_assignment (lhs, rhs);
3196
3197      goto exit_point;
3198    }
3199
3200  /* the lhs must be of a suitable type, regardless of its underlying
3201     structure.  */
3202  if (!objc_is_gcable_p (lhs))
3203    goto exit_point;
3204
3205  outer = lhs;
3206
3207  while (outer
3208	 && (TREE_CODE (outer) == COMPONENT_REF
3209	     || TREE_CODE (outer) == ARRAY_REF))
3210    outer = TREE_OPERAND (outer, 0);
3211
3212  if (TREE_CODE (outer) == INDIRECT_REF)
3213    {
3214      outer = TREE_OPERAND (outer, 0);
3215      indirect_p = 1;
3216    }
3217
3218  outer_gc_p = objc_is_gcable_p (outer);
3219
3220  /* Handle ivar assignments. */
3221  if (objc_is_ivar_reference_p (lhs))
3222    {
3223      /* if the struct to the left of the ivar is not an Objective-C object (__strong
3224	 doesn't cut it here), the best we can do here is suggest a cast.  */
3225      if (!objc_is_gcable_type (TREE_TYPE (outer), 0))
3226	{
3227	  /* We may still be able to use the global write barrier... */
3228	  if (!indirect_p && objc_is_global_reference_p (outer))
3229	    goto global_reference;
3230
3231	 suggest_cast:
3232	  if (modifycode == NOP_EXPR)
3233	    {
3234	      if (warn_assign_intercept)
3235		warning (0, "strong-cast may possibly be needed");
3236	    }
3237
3238	  goto exit_point;
3239	}
3240
3241      if (modifycode != NOP_EXPR)
3242        goto invalid_pointer_arithmetic;
3243
3244      if (warn_assign_intercept)
3245	warning (0, "instance variable assignment has been intercepted");
3246
3247      result = objc_build_ivar_assignment (outer, lhs, rhs);
3248
3249      goto exit_point;
3250    }
3251
3252  /* Likewise, intercept assignment to global/static variables if their type is
3253     GC-marked.  */
3254  if (objc_is_global_reference_p (outer))
3255    {
3256      if (indirect_p)
3257	goto suggest_cast;
3258
3259     global_reference:
3260      if (modifycode != NOP_EXPR)
3261	{
3262	 invalid_pointer_arithmetic:
3263	  if (outer_gc_p)
3264	    warning (0, "pointer arithmetic for garbage-collected objects not allowed");
3265
3266	  goto exit_point;
3267	}
3268
3269      if (warn_assign_intercept)
3270	warning (0, "global/static variable assignment has been intercepted");
3271
3272      result = objc_build_global_assignment (lhs, rhs);
3273    }
3274
3275  /* In all other cases, fall back to the normal mechanism.  */
3276 exit_point:
3277  return result;
3278}
3279
3280struct interface_tuple GTY(())
3281{
3282  tree id;
3283  tree class_name;
3284};
3285
3286static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
3287
3288static hashval_t
3289hash_interface (const void *p)
3290{
3291  const struct interface_tuple *d = p;
3292  return IDENTIFIER_HASH_VALUE (d->id);
3293}
3294
3295static int
3296eq_interface (const void *p1, const void *p2)
3297{
3298  const struct interface_tuple *d = p1;
3299  return d->id == p2;
3300}
3301
3302static tree
3303lookup_interface (tree ident)
3304{
3305#ifdef OBJCPLUS
3306  if (ident && TREE_CODE (ident) == TYPE_DECL)
3307    ident = DECL_NAME (ident);
3308#endif
3309
3310  if (ident == NULL_TREE || TREE_CODE (ident) != IDENTIFIER_NODE)
3311    return NULL_TREE;
3312
3313  {
3314    struct interface_tuple **slot;
3315    tree i = NULL_TREE;
3316
3317    if (interface_htab)
3318      {
3319	slot = (struct interface_tuple **)
3320	  htab_find_slot_with_hash (interface_htab, ident,
3321				    IDENTIFIER_HASH_VALUE (ident),
3322				    NO_INSERT);
3323	if (slot && *slot)
3324	  i = (*slot)->class_name;
3325      }
3326    return i;
3327  }
3328}
3329
3330/* Implement @defs (<classname>) within struct bodies.  */
3331
3332tree
3333objc_get_class_ivars (tree class_name)
3334{
3335  tree interface = lookup_interface (class_name);
3336
3337  if (interface)
3338    return get_class_ivars (interface, true);
3339
3340  error ("cannot find interface declaration for %qs",
3341	 IDENTIFIER_POINTER (class_name));
3342
3343  return error_mark_node;
3344}
3345
3346/* Used by: build_private_template, continue_class,
3347   and for @defs constructs.  */
3348
3349static tree
3350get_class_ivars (tree interface, bool inherited)
3351{
3352  tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
3353
3354  /* Both CLASS_RAW_IVARS and CLASS_IVARS contain a list of ivars declared
3355     by the current class (i.e., they do not include super-class ivars).
3356     However, the CLASS_IVARS list will be side-effected by a call to
3357     finish_struct(), which will fill in field offsets.  */
3358  if (!CLASS_IVARS (interface))
3359    CLASS_IVARS (interface) = ivar_chain;
3360
3361  if (!inherited)
3362    return ivar_chain;
3363
3364  while (CLASS_SUPER_NAME (interface))
3365    {
3366      /* Prepend super-class ivars.  */
3367      interface = lookup_interface (CLASS_SUPER_NAME (interface));
3368      ivar_chain = chainon (copy_list (CLASS_RAW_IVARS (interface)),
3369			    ivar_chain);
3370    }
3371
3372  return ivar_chain;
3373}
3374
3375static tree
3376objc_create_temporary_var (tree type)
3377{
3378  tree decl;
3379
3380  decl = build_decl (VAR_DECL, NULL_TREE, type);
3381  TREE_USED (decl) = 1;
3382  DECL_ARTIFICIAL (decl) = 1;
3383  DECL_IGNORED_P (decl) = 1;
3384  DECL_CONTEXT (decl) = current_function_decl;
3385
3386  return decl;
3387}
3388
3389/* Exception handling constructs.  We begin by having the parser do most
3390   of the work and passing us blocks.  What we do next depends on whether
3391   we're doing "native" exception handling or legacy Darwin setjmp exceptions.
3392   We abstract all of this in a handful of appropriately named routines.  */
3393
3394/* Stack of open try blocks.  */
3395
3396struct objc_try_context
3397{
3398  struct objc_try_context *outer;
3399
3400  /* Statements (or statement lists) as processed by the parser.  */
3401  tree try_body;
3402  tree finally_body;
3403
3404  /* Some file position locations.  */
3405  location_t try_locus;
3406  location_t end_try_locus;
3407  location_t end_catch_locus;
3408  location_t finally_locus;
3409  location_t end_finally_locus;
3410
3411  /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
3412     of a TRY_CATCH_EXPR.  Even when doing Darwin setjmp.  */
3413  tree catch_list;
3414
3415  /* The CATCH_EXPR of an open @catch clause.  */
3416  tree current_catch;
3417
3418  /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR.  */
3419  tree caught_decl;
3420  tree stack_decl;
3421  tree rethrow_decl;
3422};
3423
3424static struct objc_try_context *cur_try_context;
3425
3426/* This hook, called via lang_eh_runtime_type, generates a runtime object
3427   that represents TYPE.  For Objective-C, this is just the class name.  */
3428/* ??? Isn't there a class object or some such?  Is it easy to get?  */
3429
3430#ifndef OBJCPLUS
3431static tree
3432objc_eh_runtime_type (tree type)
3433{
3434  return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
3435}
3436#endif
3437
3438/* Initialize exception handling.  */
3439
3440static void
3441objc_init_exceptions (void)
3442{
3443  static bool done = false;
3444  if (done)
3445    return;
3446  done = true;
3447
3448  if (flag_objc_sjlj_exceptions)
3449    {
3450      /* On Darwin, ObjC exceptions require a sufficiently recent
3451	 version of the runtime, so the user must ask for them explicitly.  */
3452      if (!flag_objc_exceptions)
3453	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
3454		 "exception syntax");
3455    }
3456#ifndef OBJCPLUS
3457  else
3458    {
3459      c_eh_initialized_p = true;
3460      eh_personality_libfunc
3461	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
3462			    ? "__gnu_objc_personality_sj0"
3463			    : "__gnu_objc_personality_v0");
3464      default_init_unwind_resume_libfunc ();
3465      using_eh_for_cleanups ();
3466      lang_eh_runtime_type = objc_eh_runtime_type;
3467    }
3468#endif
3469}
3470
3471/* Build an EXC_PTR_EXPR, or the moral equivalent.  In the case of Darwin,
3472   we'll arrange for it to be initialized (and associated with a binding)
3473   later.  */
3474
3475static tree
3476objc_build_exc_ptr (void)
3477{
3478  if (flag_objc_sjlj_exceptions)
3479    {
3480      tree var = cur_try_context->caught_decl;
3481      if (!var)
3482	{
3483	  var = objc_create_temporary_var (objc_object_type);
3484	  cur_try_context->caught_decl = var;
3485	}
3486      return var;
3487    }
3488  else
3489    return build0 (EXC_PTR_EXPR, objc_object_type);
3490}
3491
3492/* Build "objc_exception_try_exit(&_stack)".  */
3493
3494static tree
3495next_sjlj_build_try_exit (void)
3496{
3497  tree t;
3498  t = build_fold_addr_expr (cur_try_context->stack_decl);
3499  t = tree_cons (NULL, t, NULL);
3500  t = build_function_call (objc_exception_try_exit_decl, t);
3501  return t;
3502}
3503
3504/* Build
3505	objc_exception_try_enter (&_stack);
3506	if (_setjmp(&_stack.buf))
3507	  ;
3508	else
3509	  ;
3510   Return the COND_EXPR.  Note that the THEN and ELSE fields are left
3511   empty, ready for the caller to fill them in.  */
3512
3513static tree
3514next_sjlj_build_enter_and_setjmp (void)
3515{
3516  tree t, enter, sj, cond;
3517
3518  t = build_fold_addr_expr (cur_try_context->stack_decl);
3519  t = tree_cons (NULL, t, NULL);
3520  enter = build_function_call (objc_exception_try_enter_decl, t);
3521
3522  t = objc_build_component_ref (cur_try_context->stack_decl,
3523				get_identifier ("buf"));
3524  t = build_fold_addr_expr (t);
3525#ifdef OBJCPLUS
3526  /* Convert _setjmp argument to type that is expected.  */
3527  if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
3528    t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
3529  else
3530    t = convert (ptr_type_node, t);
3531#else
3532  t = convert (ptr_type_node, t);
3533#endif
3534  t = tree_cons (NULL, t, NULL);
3535  sj = build_function_call (objc_setjmp_decl, t);
3536
3537  cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
3538  cond = c_common_truthvalue_conversion (cond);
3539
3540  return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
3541}
3542
3543/* Build:
3544
3545   DECL = objc_exception_extract(&_stack);  */
3546
3547static tree
3548next_sjlj_build_exc_extract (tree decl)
3549{
3550  tree t;
3551
3552  t = build_fold_addr_expr (cur_try_context->stack_decl);
3553  t = tree_cons (NULL, t, NULL);
3554  t = build_function_call (objc_exception_extract_decl, t);
3555  t = convert (TREE_TYPE (decl), t);
3556  t = build2 (MODIFY_EXPR, void_type_node, decl, t);
3557
3558  return t;
3559}
3560
3561/* Build
3562	if (objc_exception_match(obj_get_class(TYPE), _caught)
3563	  BODY
3564	else if (...)
3565	  ...
3566	else
3567	  {
3568	    _rethrow = _caught;
3569	    objc_exception_try_exit(&_stack);
3570	  }
3571   from the sequence of CATCH_EXPRs in the current try context.  */
3572
3573static tree
3574next_sjlj_build_catch_list (void)
3575{
3576  tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3577  tree catch_seq, t;
3578  tree *last = &catch_seq;
3579  bool saw_id = false;
3580
3581  for (; !tsi_end_p (i); tsi_next (&i))
3582    {
3583      tree stmt = tsi_stmt (i);
3584      tree type = CATCH_TYPES (stmt);
3585      tree body = CATCH_BODY (stmt);
3586
3587      if (type == NULL)
3588	{
3589	  *last = body;
3590	  saw_id = true;
3591	  break;
3592	}
3593      else
3594	{
3595	  tree args, cond;
3596
3597	  if (type == error_mark_node)
3598	    cond = error_mark_node;
3599	  else
3600	    {
3601	      args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
3602	      t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
3603	      args = tree_cons (NULL, t, args);
3604	      t = build_function_call (objc_exception_match_decl, args);
3605	      cond = c_common_truthvalue_conversion (t);
3606	    }
3607	  t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
3608	  SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
3609
3610	  *last = t;
3611	  last = &COND_EXPR_ELSE (t);
3612	}
3613    }
3614
3615  if (!saw_id)
3616    {
3617      t = build2 (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
3618		  cur_try_context->caught_decl);
3619      SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3620      append_to_statement_list (t, last);
3621
3622      t = next_sjlj_build_try_exit ();
3623      SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3624      append_to_statement_list (t, last);
3625    }
3626
3627  return catch_seq;
3628}
3629
3630/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
3631   exception handling.  We aim to build:
3632
3633	{
3634	  struct _objc_exception_data _stack;
3635	  id _rethrow = 0;
3636	  try
3637	    {
3638	      objc_exception_try_enter (&_stack);
3639	      if (_setjmp(&_stack.buf))
3640	        {
3641		  id _caught = objc_exception_extract(&_stack);
3642		  objc_exception_try_enter (&_stack);
3643		  if (_setjmp(&_stack.buf))
3644		    _rethrow = objc_exception_extract(&_stack);
3645		  else
3646		    CATCH-LIST
3647	        }
3648	      else
3649		TRY-BLOCK
3650	    }
3651	  finally
3652	    {
3653	      if (!_rethrow)
3654		objc_exception_try_exit(&_stack);
3655	      FINALLY-BLOCK
3656	      if (_rethrow)
3657		objc_exception_throw(_rethrow);
3658	    }
3659	}
3660
3661   If CATCH-LIST is empty, we can omit all of the block containing
3662   "_caught" except for the setting of _rethrow.  Note the use of
3663   a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
3664   but handles goto and other exits from the block.  */
3665
3666static tree
3667next_sjlj_build_try_catch_finally (void)
3668{
3669  tree rethrow_decl, stack_decl, t;
3670  tree catch_seq, try_fin, bind;
3671
3672  /* Create the declarations involved.  */
3673  t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3674  stack_decl = objc_create_temporary_var (t);
3675  cur_try_context->stack_decl = stack_decl;
3676
3677  rethrow_decl = objc_create_temporary_var (objc_object_type);
3678  cur_try_context->rethrow_decl = rethrow_decl;
3679  TREE_CHAIN (rethrow_decl) = stack_decl;
3680
3681  /* Build the outermost variable binding level.  */
3682  bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
3683  SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
3684  TREE_SIDE_EFFECTS (bind) = 1;
3685
3686  /* Initialize rethrow_decl.  */
3687  t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
3688	      convert (objc_object_type, null_pointer_node));
3689  SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3690  append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3691
3692  /* Build the outermost TRY_FINALLY_EXPR.  */
3693  try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
3694  SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
3695  TREE_SIDE_EFFECTS (try_fin) = 1;
3696  append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
3697
3698  /* Create the complete catch sequence.  */
3699  if (cur_try_context->catch_list)
3700    {
3701      tree caught_decl = objc_build_exc_ptr ();
3702      catch_seq = build_stmt (BIND_EXPR, caught_decl, NULL, NULL);
3703      TREE_SIDE_EFFECTS (catch_seq) = 1;
3704
3705      t = next_sjlj_build_exc_extract (caught_decl);
3706      append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3707
3708      t = next_sjlj_build_enter_and_setjmp ();
3709      COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
3710      COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
3711      append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3712    }
3713  else
3714    catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
3715  SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
3716
3717  /* Build the main register-and-try if statement.  */
3718  t = next_sjlj_build_enter_and_setjmp ();
3719  SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3720  COND_EXPR_THEN (t) = catch_seq;
3721  COND_EXPR_ELSE (t) = cur_try_context->try_body;
3722  TREE_OPERAND (try_fin, 0) = t;
3723
3724  /* Build the complete FINALLY statement list.  */
3725  t = next_sjlj_build_try_exit ();
3726  t = build_stmt (COND_EXPR,
3727		  c_common_truthvalue_conversion (rethrow_decl),
3728		  NULL, t);
3729  SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
3730  append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3731
3732  append_to_statement_list (cur_try_context->finally_body,
3733			    &TREE_OPERAND (try_fin, 1));
3734
3735  t = tree_cons (NULL, rethrow_decl, NULL);
3736  t = build_function_call (objc_exception_throw_decl, t);
3737  t = build_stmt (COND_EXPR,
3738		  c_common_truthvalue_conversion (rethrow_decl),
3739		  t, NULL);
3740  SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
3741  append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3742
3743  return bind;
3744}
3745
3746/* Called just after parsing the @try and its associated BODY.  We now
3747   must prepare for the tricky bits -- handling the catches and finally.  */
3748
3749void
3750objc_begin_try_stmt (location_t try_locus, tree body)
3751{
3752  struct objc_try_context *c = xcalloc (1, sizeof (*c));
3753  c->outer = cur_try_context;
3754  c->try_body = body;
3755  c->try_locus = try_locus;
3756  c->end_try_locus = input_location;
3757  cur_try_context = c;
3758
3759  objc_init_exceptions ();
3760
3761  if (flag_objc_sjlj_exceptions)
3762    objc_mark_locals_volatile (NULL);
3763}
3764
3765/* Called just after parsing "@catch (parm)".  Open a binding level,
3766   enter DECL into the binding level, and initialize it.  Leave the
3767   binding level open while the body of the compound statement is parsed.  */
3768
3769void
3770objc_begin_catch_clause (tree decl)
3771{
3772  tree compound, type, t;
3773
3774  /* Begin a new scope that the entire catch clause will live in.  */
3775  compound = c_begin_compound_stmt (true);
3776
3777  /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL.  */
3778  decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
3779  lang_hooks.decls.pushdecl (decl);
3780
3781  /* Since a decl is required here by syntax, don't warn if its unused.  */
3782  /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
3783     be what the previous objc implementation did.  */
3784  TREE_USED (decl) = 1;
3785
3786  /* Verify that the type of the catch is valid.  It must be a pointer
3787     to an Objective-C class, or "id" (which is catch-all).  */
3788  type = TREE_TYPE (decl);
3789
3790  if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3791    type = NULL;
3792  else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3793    {
3794      error ("@catch parameter is not a known Objective-C class type");
3795      type = error_mark_node;
3796    }
3797  else if (cur_try_context->catch_list)
3798    {
3799      /* Examine previous @catch clauses and see if we've already
3800	 caught the type in question.  */
3801      tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3802      for (; !tsi_end_p (i); tsi_next (&i))
3803	{
3804	  tree stmt = tsi_stmt (i);
3805	  t = CATCH_TYPES (stmt);
3806	  if (t == error_mark_node)
3807	    continue;
3808	  if (!t || DERIVED_FROM_P (TREE_TYPE (t), TREE_TYPE (type)))
3809	    {
3810	      warning (0, "exception of type %<%T%> will be caught",
3811		       TREE_TYPE (type));
3812	      warning (0, "%H   by earlier handler for %<%T%>",
3813		       EXPR_LOCUS (stmt), TREE_TYPE (t ? t : objc_object_type));
3814	      break;
3815	    }
3816	}
3817    }
3818
3819  /* Record the data for the catch in the try context so that we can
3820     finalize it later.  */
3821  t = build_stmt (CATCH_EXPR, type, compound);
3822  cur_try_context->current_catch = t;
3823
3824  /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3825  t = objc_build_exc_ptr ();
3826  t = convert (TREE_TYPE (decl), t);
3827  t = build2 (MODIFY_EXPR, void_type_node, decl, t);
3828  add_stmt (t);
3829}
3830
3831/* Called just after parsing the closing brace of a @catch clause.  Close
3832   the open binding level, and record a CATCH_EXPR for it.  */
3833
3834void
3835objc_finish_catch_clause (void)
3836{
3837  tree c = cur_try_context->current_catch;
3838  cur_try_context->current_catch = NULL;
3839  cur_try_context->end_catch_locus = input_location;
3840
3841  CATCH_BODY (c) = c_end_compound_stmt (CATCH_BODY (c), 1);
3842  append_to_statement_list (c, &cur_try_context->catch_list);
3843}
3844
3845/* Called after parsing a @finally clause and its associated BODY.
3846   Record the body for later placement.  */
3847
3848void
3849objc_build_finally_clause (location_t finally_locus, tree body)
3850{
3851  cur_try_context->finally_body = body;
3852  cur_try_context->finally_locus = finally_locus;
3853  cur_try_context->end_finally_locus = input_location;
3854}
3855
3856/* Called to finalize a @try construct.  */
3857
3858tree
3859objc_finish_try_stmt (void)
3860{
3861  struct objc_try_context *c = cur_try_context;
3862  tree stmt;
3863
3864  if (c->catch_list == NULL && c->finally_body == NULL)
3865    error ("%<@try%> without %<@catch%> or %<@finally%>");
3866
3867  /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
3868  if (flag_objc_sjlj_exceptions)
3869    {
3870      if (!cur_try_context->finally_body)
3871	{
3872	  cur_try_context->finally_locus = input_location;
3873	  cur_try_context->end_finally_locus = input_location;
3874	}
3875      stmt = next_sjlj_build_try_catch_finally ();
3876    }
3877  else
3878    {
3879      /* Otherwise, nest the CATCH inside a FINALLY.  */
3880      stmt = c->try_body;
3881      if (c->catch_list)
3882	{
3883          stmt = build_stmt (TRY_CATCH_EXPR, stmt, c->catch_list);
3884	  SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3885	}
3886      if (c->finally_body)
3887	{
3888	  stmt = build_stmt (TRY_FINALLY_EXPR, stmt, c->finally_body);
3889	  SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3890	}
3891    }
3892  add_stmt (stmt);
3893
3894  cur_try_context = c->outer;
3895  free (c);
3896  return stmt;
3897}
3898
3899tree
3900objc_build_throw_stmt (tree throw_expr)
3901{
3902  tree args;
3903
3904  objc_init_exceptions ();
3905
3906  if (throw_expr == NULL)
3907    {
3908      /* If we're not inside a @catch block, there is no "current
3909	 exception" to be rethrown.  */
3910      if (cur_try_context == NULL
3911          || cur_try_context->current_catch == NULL)
3912	{
3913	  error ("%<@throw%> (rethrow) used outside of a @catch block");
3914	  return NULL_TREE;
3915	}
3916
3917      /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3918	 value that we get from the runtime.  */
3919      throw_expr = objc_build_exc_ptr ();
3920    }
3921
3922  /* A throw is just a call to the runtime throw function with the
3923     object as a parameter.  */
3924  args = tree_cons (NULL, throw_expr, NULL);
3925  return add_stmt (build_function_call (objc_exception_throw_decl, args));
3926}
3927
3928tree
3929objc_build_synchronized (location_t start_locus, tree mutex, tree body)
3930{
3931  tree args, call;
3932
3933  /* First lock the mutex.  */
3934  mutex = save_expr (mutex);
3935  args = tree_cons (NULL, mutex, NULL);
3936  call = build_function_call (objc_sync_enter_decl, args);
3937  SET_EXPR_LOCATION (call, start_locus);
3938  add_stmt (call);
3939
3940  /* Build the mutex unlock.  */
3941  args = tree_cons (NULL, mutex, NULL);
3942  call = build_function_call (objc_sync_exit_decl, args);
3943  SET_EXPR_LOCATION (call, input_location);
3944
3945  /* Put the that and the body in a TRY_FINALLY.  */
3946  objc_begin_try_stmt (start_locus, body);
3947  objc_build_finally_clause (input_location, call);
3948  return objc_finish_try_stmt ();
3949}
3950
3951
3952/* Predefine the following data type:
3953
3954   struct _objc_exception_data
3955   {
3956     int buf[OBJC_JBLEN];
3957     void *pointers[4];
3958   }; */
3959
3960/* The following yuckiness should prevent users from having to #include
3961   <setjmp.h> in their code... */
3962
3963/* Define to a harmless positive value so the below code doesn't die.  */
3964#ifndef OBJC_JBLEN
3965#define OBJC_JBLEN 18
3966#endif
3967
3968static void
3969build_next_objc_exception_stuff (void)
3970{
3971  tree field_decl, field_decl_chain, index, temp_type;
3972
3973  objc_exception_data_template
3974    = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3975
3976  /* int buf[OBJC_JBLEN]; */
3977
3978  index = build_index_type (build_int_cst (NULL_TREE, OBJC_JBLEN - 1));
3979  field_decl = create_field_decl (build_array_type (integer_type_node, index),
3980				  "buf");
3981  field_decl_chain = field_decl;
3982
3983  /* void *pointers[4]; */
3984
3985  index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
3986  field_decl = create_field_decl (build_array_type (ptr_type_node, index),
3987				  "pointers");
3988  chainon (field_decl_chain, field_decl);
3989
3990  finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3991
3992  /* int _setjmp(...); */
3993  /* If the user includes <setjmp.h>, this shall be superseded by
3994     'int _setjmp(jmp_buf);' */
3995  temp_type = build_function_type (integer_type_node, NULL_TREE);
3996  objc_setjmp_decl
3997    = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3998
3999  /* id objc_exception_extract(struct _objc_exception_data *); */
4000  temp_type
4001    = build_function_type (objc_object_type,
4002			   tree_cons (NULL_TREE,
4003				      build_pointer_type (objc_exception_data_template),
4004				      OBJC_VOID_AT_END));
4005  objc_exception_extract_decl
4006    = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4007  /* void objc_exception_try_enter(struct _objc_exception_data *); */
4008  /* void objc_exception_try_exit(struct _objc_exception_data *); */
4009  temp_type
4010    = build_function_type (void_type_node,
4011			   tree_cons (NULL_TREE,
4012				      build_pointer_type (objc_exception_data_template),
4013				      OBJC_VOID_AT_END));
4014  objc_exception_try_enter_decl
4015    = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4016  objc_exception_try_exit_decl
4017    = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4018
4019  /* int objc_exception_match(id, id); */
4020  temp_type
4021    = build_function_type (integer_type_node,
4022			   tree_cons (NULL_TREE, objc_object_type,
4023				      tree_cons (NULL_TREE, objc_object_type,
4024						 OBJC_VOID_AT_END)));
4025  objc_exception_match_decl
4026    = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4027
4028  /* id objc_assign_ivar (id, id, unsigned int); */
4029  /* id objc_assign_ivar_Fast (id, id, unsigned int)
4030       __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
4031  temp_type
4032    = build_function_type (objc_object_type,
4033			   tree_cons
4034			   (NULL_TREE, objc_object_type,
4035			    tree_cons (NULL_TREE, objc_object_type,
4036				       tree_cons (NULL_TREE,
4037						  unsigned_type_node,
4038						  OBJC_VOID_AT_END))));
4039  objc_assign_ivar_decl
4040    = builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
4041			NULL, NULL_TREE);
4042#ifdef OFFS_ASSIGNIVAR_FAST
4043  objc_assign_ivar_fast_decl
4044    = builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
4045			NOT_BUILT_IN, NULL, NULL_TREE);
4046  DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
4047    = tree_cons (get_identifier ("hard_coded_address"),
4048		 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
4049		 NULL_TREE);
4050#else
4051  /* Default to slower ivar method.  */
4052  objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
4053#endif
4054
4055  /* id objc_assign_global (id, id *); */
4056  /* id objc_assign_strongCast (id, id *); */
4057  temp_type = build_function_type (objc_object_type,
4058		tree_cons (NULL_TREE, objc_object_type,
4059		    tree_cons (NULL_TREE, build_pointer_type (objc_object_type),
4060			OBJC_VOID_AT_END)));
4061  objc_assign_global_decl
4062	= builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4063  objc_assign_strong_cast_decl
4064	= builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
4065}
4066
4067static void
4068build_objc_exception_stuff (void)
4069{
4070  tree noreturn_list, nothrow_list, temp_type;
4071
4072  noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
4073  nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
4074
4075  /* void objc_exception_throw(id) __attribute__((noreturn)); */
4076  /* void objc_sync_enter(id); */
4077  /* void objc_sync_exit(id); */
4078  temp_type = build_function_type (void_type_node,
4079				   tree_cons (NULL_TREE, objc_object_type,
4080					      OBJC_VOID_AT_END));
4081  objc_exception_throw_decl
4082    = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
4083			noreturn_list);
4084  objc_sync_enter_decl
4085    = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
4086			NULL, nothrow_list);
4087  objc_sync_exit_decl
4088    = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
4089			NULL, nothrow_list);
4090}
4091
4092/* Construct a C struct corresponding to ObjC class CLASS, with the same
4093   name as the class:
4094
4095   struct <classname> {
4096     struct _objc_class *isa;
4097     ...
4098   };  */
4099
4100static void
4101build_private_template (tree class)
4102{
4103  if (!CLASS_STATIC_TEMPLATE (class))
4104    {
4105      tree record = objc_build_struct (class,
4106				       get_class_ivars (class, false),
4107				       CLASS_SUPER_NAME (class));
4108
4109      /* Set the TREE_USED bit for this struct, so that stab generator
4110	 can emit stabs for this struct type.  */
4111      if (flag_debug_only_used_symbols && TYPE_STUB_DECL (record))
4112	TREE_USED (TYPE_STUB_DECL (record)) = 1;
4113    }
4114}
4115
4116/* Begin code generation for protocols...  */
4117
4118/* struct _objc_protocol {
4119     struct _objc_class *isa;
4120     char *protocol_name;
4121     struct _objc_protocol **protocol_list;
4122     struct _objc__method_prototype_list *instance_methods;
4123     struct _objc__method_prototype_list *class_methods;
4124   };  */
4125
4126static void
4127build_protocol_template (void)
4128{
4129  tree field_decl, field_decl_chain;
4130
4131  objc_protocol_template = start_struct (RECORD_TYPE,
4132					 get_identifier (UTAG_PROTOCOL));
4133
4134  /* struct _objc_class *isa; */
4135  field_decl = create_field_decl (build_pointer_type
4136				  (xref_tag (RECORD_TYPE,
4137					     get_identifier (UTAG_CLASS))),
4138				  "isa");
4139  field_decl_chain = field_decl;
4140
4141  /* char *protocol_name; */
4142  field_decl = create_field_decl (string_type_node, "protocol_name");
4143  chainon (field_decl_chain, field_decl);
4144
4145  /* struct _objc_protocol **protocol_list; */
4146  field_decl = create_field_decl (build_pointer_type
4147				  (build_pointer_type
4148				   (objc_protocol_template)),
4149				  "protocol_list");
4150  chainon (field_decl_chain, field_decl);
4151
4152  /* struct _objc__method_prototype_list *instance_methods; */
4153  field_decl = create_field_decl (objc_method_proto_list_ptr,
4154				  "instance_methods");
4155  chainon (field_decl_chain, field_decl);
4156
4157  /* struct _objc__method_prototype_list *class_methods; */
4158  field_decl = create_field_decl (objc_method_proto_list_ptr,
4159				  "class_methods");
4160  chainon (field_decl_chain, field_decl);
4161
4162  finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
4163}
4164
4165static tree
4166build_descriptor_table_initializer (tree type, tree entries)
4167{
4168  tree initlist = NULL_TREE;
4169
4170  do
4171    {
4172      tree eltlist = NULL_TREE;
4173
4174      eltlist
4175	= tree_cons (NULL_TREE,
4176		     build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
4177      eltlist
4178	= tree_cons (NULL_TREE,
4179		     add_objc_string (METHOD_ENCODING (entries),
4180				      meth_var_types),
4181		     eltlist);
4182
4183      initlist
4184	= tree_cons (NULL_TREE,
4185		     objc_build_constructor (type, nreverse (eltlist)),
4186		     initlist);
4187
4188      entries = TREE_CHAIN (entries);
4189    }
4190  while (entries);
4191
4192  return objc_build_constructor (build_array_type (type, 0),
4193				 nreverse (initlist));
4194}
4195
4196/* struct objc_method_prototype_list {
4197     int count;
4198     struct objc_method_prototype {
4199	SEL name;
4200	char *types;
4201     } list[1];
4202   };  */
4203
4204static tree
4205build_method_prototype_list_template (tree list_type, int size)
4206{
4207  tree objc_ivar_list_record;
4208  tree field_decl, field_decl_chain;
4209
4210  /* Generate an unnamed struct definition.  */
4211
4212  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4213
4214  /* int method_count; */
4215  field_decl = create_field_decl (integer_type_node, "method_count");
4216  field_decl_chain = field_decl;
4217
4218  /* struct objc_method method_list[]; */
4219  field_decl = create_field_decl (build_array_type
4220				  (list_type,
4221				   build_index_type
4222				   (build_int_cst (NULL_TREE, size - 1))),
4223				  "method_list");
4224  chainon (field_decl_chain, field_decl);
4225
4226  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4227
4228  return objc_ivar_list_record;
4229}
4230
4231static tree
4232build_method_prototype_template (void)
4233{
4234  tree proto_record;
4235  tree field_decl, field_decl_chain;
4236
4237  proto_record
4238    = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
4239
4240  /* SEL _cmd; */
4241  field_decl = create_field_decl (objc_selector_type, "_cmd");
4242  field_decl_chain = field_decl;
4243
4244  /* char *method_types; */
4245  field_decl = create_field_decl (string_type_node, "method_types");
4246  chainon (field_decl_chain, field_decl);
4247
4248  finish_struct (proto_record, field_decl_chain, NULL_TREE);
4249
4250  return proto_record;
4251}
4252
4253static tree
4254objc_method_parm_type (tree type)
4255{
4256  type = TREE_VALUE (TREE_TYPE (type));
4257  if (TREE_CODE (type) == TYPE_DECL)
4258    type = TREE_TYPE (type);
4259  return type;
4260}
4261
4262static int
4263objc_encoded_type_size (tree type)
4264{
4265  int sz = int_size_in_bytes (type);
4266
4267  /* Make all integer and enum types at least as large
4268     as an int.  */
4269  if (sz > 0 && INTEGRAL_TYPE_P (type))
4270    sz = MAX (sz, int_size_in_bytes (integer_type_node));
4271  /* Treat arrays as pointers, since that's how they're
4272     passed in.  */
4273  else if (TREE_CODE (type) == ARRAY_TYPE)
4274    sz = int_size_in_bytes (ptr_type_node);
4275  return sz;
4276}
4277
4278static tree
4279encode_method_prototype (tree method_decl)
4280{
4281  tree parms;
4282  int parm_offset, i;
4283  char buf[40];
4284  tree result;
4285
4286  /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
4287  encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
4288
4289  /* Encode return type.  */
4290  encode_type (objc_method_parm_type (method_decl),
4291	       obstack_object_size (&util_obstack),
4292	       OBJC_ENCODE_INLINE_DEFS);
4293
4294  /* Stack size.  */
4295  /* The first two arguments (self and _cmd) are pointers; account for
4296     their size.  */
4297  i = int_size_in_bytes (ptr_type_node);
4298  parm_offset = 2 * i;
4299  for (parms = METHOD_SEL_ARGS (method_decl); parms;
4300       parms = TREE_CHAIN (parms))
4301    {
4302      tree type = objc_method_parm_type (parms);
4303      int sz = objc_encoded_type_size (type);
4304
4305      /* If a type size is not known, bail out.  */
4306      if (sz < 0)
4307	{
4308	  error ("type %q+D does not have a known size",
4309		 type);
4310	  /* Pretend that the encoding succeeded; the compilation will
4311	     fail nevertheless.  */
4312	  goto finish_encoding;
4313	}
4314      parm_offset += sz;
4315    }
4316
4317  sprintf (buf, "%d@0:%d", parm_offset, i);
4318  obstack_grow (&util_obstack, buf, strlen (buf));
4319
4320  /* Argument types.  */
4321  parm_offset = 2 * i;
4322  for (parms = METHOD_SEL_ARGS (method_decl); parms;
4323       parms = TREE_CHAIN (parms))
4324    {
4325      tree type = objc_method_parm_type (parms);
4326
4327      /* Process argument qualifiers for user supplied arguments.  */
4328      encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
4329
4330      /* Type.  */
4331      encode_type (type, obstack_object_size (&util_obstack),
4332		   OBJC_ENCODE_INLINE_DEFS);
4333
4334      /* Compute offset.  */
4335      sprintf (buf, "%d", parm_offset);
4336      parm_offset += objc_encoded_type_size (type);
4337
4338      obstack_grow (&util_obstack, buf, strlen (buf));
4339    }
4340
4341  finish_encoding:
4342  obstack_1grow (&util_obstack, '\0');
4343  result = get_identifier (obstack_finish (&util_obstack));
4344  obstack_free (&util_obstack, util_firstobj);
4345  return result;
4346}
4347
4348static tree
4349generate_descriptor_table (tree type, const char *name, int size, tree list,
4350			   tree proto)
4351{
4352  tree decl, initlist;
4353
4354  decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
4355
4356  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
4357  initlist = tree_cons (NULL_TREE, list, initlist);
4358
4359  finish_var_decl (decl, objc_build_constructor (type, nreverse (initlist)));
4360
4361  return decl;
4362}
4363
4364static void
4365generate_method_descriptors (tree protocol)
4366{
4367  tree initlist, chain, method_list_template;
4368  int size;
4369
4370  if (!objc_method_prototype_template)
4371    objc_method_prototype_template = build_method_prototype_template ();
4372
4373  chain = PROTOCOL_CLS_METHODS (protocol);
4374  if (chain)
4375    {
4376      size = list_length (chain);
4377
4378      method_list_template
4379	= build_method_prototype_list_template (objc_method_prototype_template,
4380						size);
4381
4382      initlist
4383	= build_descriptor_table_initializer (objc_method_prototype_template,
4384					      chain);
4385
4386      UOBJC_CLASS_METHODS_decl
4387	= generate_descriptor_table (method_list_template,
4388				     "_OBJC_PROTOCOL_CLASS_METHODS",
4389				     size, initlist, protocol);
4390    }
4391  else
4392    UOBJC_CLASS_METHODS_decl = 0;
4393
4394  chain = PROTOCOL_NST_METHODS (protocol);
4395  if (chain)
4396    {
4397      size = list_length (chain);
4398
4399      method_list_template
4400	= build_method_prototype_list_template (objc_method_prototype_template,
4401						size);
4402      initlist
4403	= build_descriptor_table_initializer (objc_method_prototype_template,
4404					      chain);
4405
4406      UOBJC_INSTANCE_METHODS_decl
4407	= generate_descriptor_table (method_list_template,
4408				     "_OBJC_PROTOCOL_INSTANCE_METHODS",
4409				     size, initlist, protocol);
4410    }
4411  else
4412    UOBJC_INSTANCE_METHODS_decl = 0;
4413}
4414
4415static void
4416generate_protocol_references (tree plist)
4417{
4418  tree lproto;
4419
4420  /* Forward declare protocols referenced.  */
4421  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4422    {
4423      tree proto = TREE_VALUE (lproto);
4424
4425      if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
4426	  && PROTOCOL_NAME (proto))
4427	{
4428          if (! PROTOCOL_FORWARD_DECL (proto))
4429            build_protocol_reference (proto);
4430
4431          if (PROTOCOL_LIST (proto))
4432            generate_protocol_references (PROTOCOL_LIST (proto));
4433        }
4434    }
4435}
4436
4437/* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
4438   current class.  */
4439#ifdef OBJCPLUS
4440static void
4441objc_generate_cxx_ctor_or_dtor (bool dtor)
4442{
4443  tree fn, body, compound_stmt, ivar;
4444
4445  /* - (id) .cxx_construct { ... return self; } */
4446  /* - (void) .cxx_construct { ... }            */
4447
4448  objc_set_method_type (MINUS_EXPR);
4449  objc_start_method_definition
4450   (objc_build_method_signature (build_tree_list (NULL_TREE,
4451						  dtor
4452						  ? void_type_node
4453						  : objc_object_type),
4454				 get_identifier (dtor
4455						 ? TAG_CXX_DESTRUCT
4456						 : TAG_CXX_CONSTRUCT),
4457				 make_node (TREE_LIST),
4458				 false));
4459  body = begin_function_body ();
4460  compound_stmt = begin_compound_stmt (0);
4461
4462  ivar = CLASS_IVARS (implementation_template);
4463  /* Destroy ivars in reverse order.  */
4464  if (dtor)
4465    ivar = nreverse (copy_list (ivar));
4466
4467  for (; ivar; ivar = TREE_CHAIN (ivar))
4468    {
4469      if (TREE_CODE (ivar) == FIELD_DECL)
4470	{
4471	  tree type = TREE_TYPE (ivar);
4472
4473	  /* Call the ivar's default constructor or destructor.  Do not
4474	     call the destructor unless a corresponding constructor call
4475	     has also been made (or is not needed).  */
4476	  if (IS_AGGR_TYPE (type)
4477	      && (dtor
4478		  ? (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
4479		     && (!TYPE_NEEDS_CONSTRUCTING (type)
4480			 || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
4481		  : (TYPE_NEEDS_CONSTRUCTING (type)
4482		     && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))))
4483	    finish_expr_stmt
4484	     (build_special_member_call
4485	      (build_ivar_reference (DECL_NAME (ivar)),
4486	       dtor ? complete_dtor_identifier : complete_ctor_identifier,
4487	       NULL_TREE, type, LOOKUP_NORMAL));
4488	}
4489    }
4490
4491  /* The constructor returns 'self'.  */
4492  if (!dtor)
4493    finish_return_stmt (self_decl);
4494
4495  finish_compound_stmt (compound_stmt);
4496  finish_function_body (body);
4497  fn = current_function_decl;
4498  finish_function ();
4499  objc_finish_method_definition (fn);
4500}
4501
4502/* The following routine will examine the current @interface for any
4503   non-POD C++ ivars requiring non-trivial construction and/or
4504   destruction, and then synthesize special '- .cxx_construct' and/or
4505   '- .cxx_destruct' methods which will run the appropriate
4506   construction or destruction code.  Note that ivars inherited from
4507   super-classes are _not_ considered.  */
4508static void
4509objc_generate_cxx_cdtors (void)
4510{
4511  bool need_ctor = false, need_dtor = false;
4512  tree ivar;
4513
4514  /* We do not want to do this for categories, since they do not have
4515     their own ivars.  */
4516
4517  if (TREE_CODE (objc_implementation_context) != CLASS_IMPLEMENTATION_TYPE)
4518    return;
4519
4520  /* First, determine if we even need a constructor and/or destructor.  */
4521
4522  for (ivar = CLASS_IVARS (implementation_template); ivar;
4523       ivar = TREE_CHAIN (ivar))
4524    {
4525      if (TREE_CODE (ivar) == FIELD_DECL)
4526	{
4527	  tree type = TREE_TYPE (ivar);
4528
4529	  if (IS_AGGR_TYPE (type))
4530	    {
4531	      if (TYPE_NEEDS_CONSTRUCTING (type)
4532		  && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
4533		/* NB: If a default constructor is not available, we will not
4534		   be able to initialize this ivar; the add_instance_variable()
4535		   routine will already have warned about this.  */
4536		need_ctor = true;
4537
4538	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
4539		  && (!TYPE_NEEDS_CONSTRUCTING (type)
4540		      || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
4541		/* NB: If a default constructor is not available, we will not
4542		   call the destructor either, for symmetry.  */
4543		need_dtor = true;
4544	    }
4545	}
4546    }
4547
4548  /* Generate '- .cxx_construct' if needed.  */
4549
4550  if (need_ctor)
4551    objc_generate_cxx_ctor_or_dtor (false);
4552
4553  /* Generate '- .cxx_destruct' if needed.  */
4554
4555  if (need_dtor)
4556    objc_generate_cxx_ctor_or_dtor (true);
4557
4558  /* The 'imp_list' variable points at an imp_entry record for the current
4559     @implementation.  Record the existence of '- .cxx_construct' and/or
4560     '- .cxx_destruct' methods therein; it will be included in the
4561     metadata for the class.  */
4562  if (flag_next_runtime)
4563    imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
4564}
4565#endif
4566
4567/* For each protocol which was referenced either from a @protocol()
4568   expression, or because a class/category implements it (then a
4569   pointer to the protocol is stored in the struct describing the
4570   class/category), we create a statically allocated instance of the
4571   Protocol class.  The code is written in such a way as to generate
4572   as few Protocol objects as possible; we generate a unique Protocol
4573   instance for each protocol, and we don't generate a Protocol
4574   instance if the protocol is never referenced (either from a
4575   @protocol() or from a class/category implementation).  These
4576   statically allocated objects can be referred to via the static
4577   (that is, private to this module) symbols _OBJC_PROTOCOL_n.
4578
4579   The statically allocated Protocol objects that we generate here
4580   need to be fixed up at runtime in order to be used: the 'isa'
4581   pointer of the objects need to be set up to point to the 'Protocol'
4582   class, as known at runtime.
4583
4584   The NeXT runtime fixes up all protocols at program startup time,
4585   before main() is entered.  It uses a low-level trick to look up all
4586   those symbols, then loops on them and fixes them up.
4587
4588   The GNU runtime as well fixes up all protocols before user code
4589   from the module is executed; it requires pointers to those symbols
4590   to be put in the objc_symtab (which is then passed as argument to
4591   the function __objc_exec_class() which the compiler sets up to be
4592   executed automatically when the module is loaded); setup of those
4593   Protocol objects happen in two ways in the GNU runtime: all
4594   Protocol objects referred to by a class or category implementation
4595   are fixed up when the class/category is loaded; all Protocol
4596   objects referred to by a @protocol() expression are added by the
4597   compiler to the list of statically allocated instances to fixup
4598   (the same list holding the statically allocated constant string
4599   objects).  Because, as explained above, the compiler generates as
4600   few Protocol objects as possible, some Protocol object might end up
4601   being referenced multiple times when compiled with the GNU runtime,
4602   and end up being fixed up multiple times at runtime initialization.
4603   But that doesn't hurt, it's just a little inefficient.  */
4604
4605static void
4606generate_protocols (void)
4607{
4608  tree p, encoding;
4609  tree decl;
4610  tree initlist, protocol_name_expr, refs_decl, refs_expr;
4611
4612  /* If a protocol was directly referenced, pull in indirect references.  */
4613  for (p = protocol_chain; p; p = TREE_CHAIN (p))
4614    if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
4615      generate_protocol_references (PROTOCOL_LIST (p));
4616
4617  for (p = protocol_chain; p; p = TREE_CHAIN (p))
4618    {
4619      tree nst_methods = PROTOCOL_NST_METHODS (p);
4620      tree cls_methods = PROTOCOL_CLS_METHODS (p);
4621
4622      /* If protocol wasn't referenced, don't generate any code.  */
4623      decl = PROTOCOL_FORWARD_DECL (p);
4624
4625      if (!decl)
4626	continue;
4627
4628      /* Make sure we link in the Protocol class.  */
4629      add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
4630
4631      while (nst_methods)
4632	{
4633	  if (! METHOD_ENCODING (nst_methods))
4634	    {
4635	      encoding = encode_method_prototype (nst_methods);
4636	      METHOD_ENCODING (nst_methods) = encoding;
4637	    }
4638	  nst_methods = TREE_CHAIN (nst_methods);
4639	}
4640
4641      while (cls_methods)
4642	{
4643	  if (! METHOD_ENCODING (cls_methods))
4644	    {
4645	      encoding = encode_method_prototype (cls_methods);
4646	      METHOD_ENCODING (cls_methods) = encoding;
4647	    }
4648
4649	  cls_methods = TREE_CHAIN (cls_methods);
4650	}
4651      generate_method_descriptors (p);
4652
4653      if (PROTOCOL_LIST (p))
4654	refs_decl = generate_protocol_list (p);
4655      else
4656	refs_decl = 0;
4657
4658      /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
4659      protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
4660
4661      if (refs_decl)
4662	refs_expr = convert (build_pointer_type (build_pointer_type
4663						 (objc_protocol_template)),
4664			     build_unary_op (ADDR_EXPR, refs_decl, 0));
4665      else
4666	refs_expr = build_int_cst (NULL_TREE, 0);
4667
4668      /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
4669	 by generate_method_descriptors, which is called above.  */
4670      initlist = build_protocol_initializer (TREE_TYPE (decl),
4671					     protocol_name_expr, refs_expr,
4672					     UOBJC_INSTANCE_METHODS_decl,
4673					     UOBJC_CLASS_METHODS_decl);
4674      finish_var_decl (decl, initlist);
4675    }
4676}
4677
4678static tree
4679build_protocol_initializer (tree type, tree protocol_name,
4680			    tree protocol_list, tree instance_methods,
4681			    tree class_methods)
4682{
4683  tree initlist = NULL_TREE, expr;
4684  tree cast_type = build_pointer_type
4685		   (xref_tag (RECORD_TYPE,
4686			      get_identifier (UTAG_CLASS)));
4687
4688  /* Filling the "isa" in with one allows the runtime system to
4689     detect that the version change...should remove before final release.  */
4690
4691  expr = build_int_cst (cast_type, PROTOCOL_VERSION);
4692  initlist = tree_cons (NULL_TREE, expr, initlist);
4693  initlist = tree_cons (NULL_TREE, protocol_name, initlist);
4694  initlist = tree_cons (NULL_TREE, protocol_list, initlist);
4695
4696  if (!instance_methods)
4697    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4698  else
4699    {
4700      expr = convert (objc_method_proto_list_ptr,
4701		      build_unary_op (ADDR_EXPR, instance_methods, 0));
4702      initlist = tree_cons (NULL_TREE, expr, initlist);
4703    }
4704
4705  if (!class_methods)
4706    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4707  else
4708    {
4709      expr = convert (objc_method_proto_list_ptr,
4710		      build_unary_op (ADDR_EXPR, class_methods, 0));
4711      initlist = tree_cons (NULL_TREE, expr, initlist);
4712    }
4713
4714  return objc_build_constructor (type, nreverse (initlist));
4715}
4716
4717/* struct _objc_category {
4718     char *category_name;
4719     char *class_name;
4720     struct _objc_method_list *instance_methods;
4721     struct _objc_method_list *class_methods;
4722     struct _objc_protocol_list *protocols;
4723   };   */
4724
4725static void
4726build_category_template (void)
4727{
4728  tree field_decl, field_decl_chain;
4729
4730  objc_category_template = start_struct (RECORD_TYPE,
4731					 get_identifier (UTAG_CATEGORY));
4732
4733  /* char *category_name; */
4734  field_decl = create_field_decl (string_type_node, "category_name");
4735  field_decl_chain = field_decl;
4736
4737  /* char *class_name; */
4738  field_decl = create_field_decl (string_type_node, "class_name");
4739  chainon (field_decl_chain, field_decl);
4740
4741  /* struct _objc_method_list *instance_methods; */
4742  field_decl = create_field_decl (objc_method_list_ptr,
4743				  "instance_methods");
4744  chainon (field_decl_chain, field_decl);
4745
4746  /* struct _objc_method_list *class_methods; */
4747  field_decl = create_field_decl (objc_method_list_ptr,
4748				  "class_methods");
4749  chainon (field_decl_chain, field_decl);
4750
4751  /* struct _objc_protocol **protocol_list; */
4752  field_decl = create_field_decl (build_pointer_type
4753				  (build_pointer_type
4754				   (objc_protocol_template)),
4755				  "protocol_list");
4756  chainon (field_decl_chain, field_decl);
4757
4758  finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4759}
4760
4761/* struct _objc_selector {
4762     SEL sel_id;
4763     char *sel_type;
4764   }; */
4765
4766static void
4767build_selector_template (void)
4768{
4769
4770  tree field_decl, field_decl_chain;
4771
4772  objc_selector_template
4773    = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4774
4775  /* SEL sel_id; */
4776  field_decl = create_field_decl (objc_selector_type, "sel_id");
4777  field_decl_chain = field_decl;
4778
4779  /* char *sel_type; */
4780  field_decl = create_field_decl (string_type_node, "sel_type");
4781  chainon (field_decl_chain, field_decl);
4782
4783  finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4784}
4785
4786/* struct _objc_class {
4787     struct _objc_class *isa;
4788     struct _objc_class *super_class;
4789     char *name;
4790     long version;
4791     long info;
4792     long instance_size;
4793     struct _objc_ivar_list *ivars;
4794     struct _objc_method_list *methods;
4795     #ifdef __NEXT_RUNTIME__
4796       struct objc_cache *cache;
4797     #else
4798       struct sarray *dtable;
4799       struct _objc_class *subclass_list;
4800       struct _objc_class *sibling_class;
4801     #endif
4802     struct _objc_protocol_list *protocols;
4803     #ifdef __NEXT_RUNTIME__
4804       void *sel_id;
4805     #endif
4806     void *gc_object_type;
4807   };  */
4808
4809/* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4810   the NeXT/Apple runtime; still, the compiler must generate them to
4811   maintain backward binary compatibility (and to allow for future
4812   expansion).  */
4813
4814static void
4815build_class_template (void)
4816{
4817  tree field_decl, field_decl_chain;
4818
4819  objc_class_template
4820    = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4821
4822  /* struct _objc_class *isa; */
4823  field_decl = create_field_decl (build_pointer_type (objc_class_template),
4824				  "isa");
4825  field_decl_chain = field_decl;
4826
4827  /* struct _objc_class *super_class; */
4828  field_decl = create_field_decl (build_pointer_type (objc_class_template),
4829				  "super_class");
4830  chainon (field_decl_chain, field_decl);
4831
4832  /* char *name; */
4833  field_decl = create_field_decl (string_type_node, "name");
4834  chainon (field_decl_chain, field_decl);
4835
4836  /* long version; */
4837  field_decl = create_field_decl (long_integer_type_node, "version");
4838  chainon (field_decl_chain, field_decl);
4839
4840  /* long info; */
4841  field_decl = create_field_decl (long_integer_type_node, "info");
4842  chainon (field_decl_chain, field_decl);
4843
4844  /* long instance_size; */
4845  field_decl = create_field_decl (long_integer_type_node, "instance_size");
4846  chainon (field_decl_chain, field_decl);
4847
4848  /* struct _objc_ivar_list *ivars; */
4849  field_decl = create_field_decl (objc_ivar_list_ptr,
4850				  "ivars");
4851  chainon (field_decl_chain, field_decl);
4852
4853  /* struct _objc_method_list *methods; */
4854  field_decl = create_field_decl (objc_method_list_ptr,
4855				  "methods");
4856  chainon (field_decl_chain, field_decl);
4857
4858  if (flag_next_runtime)
4859    {
4860      /* struct objc_cache *cache; */
4861      field_decl = create_field_decl (build_pointer_type
4862				      (xref_tag (RECORD_TYPE,
4863						 get_identifier
4864						 ("objc_cache"))),
4865				      "cache");
4866      chainon (field_decl_chain, field_decl);
4867    }
4868  else
4869    {
4870      /* struct sarray *dtable; */
4871      field_decl = create_field_decl (build_pointer_type
4872				      (xref_tag (RECORD_TYPE,
4873						 get_identifier
4874						 ("sarray"))),
4875				      "dtable");
4876      chainon (field_decl_chain, field_decl);
4877
4878      /* struct objc_class *subclass_list; */
4879      field_decl = create_field_decl (build_pointer_type
4880				      (objc_class_template),
4881				      "subclass_list");
4882      chainon (field_decl_chain, field_decl);
4883
4884      /* struct objc_class *sibling_class; */
4885      field_decl = create_field_decl (build_pointer_type
4886				      (objc_class_template),
4887				      "sibling_class");
4888      chainon (field_decl_chain, field_decl);
4889    }
4890
4891  /* struct _objc_protocol **protocol_list; */
4892  field_decl = create_field_decl (build_pointer_type
4893				  (build_pointer_type
4894				   (xref_tag (RECORD_TYPE,
4895					     get_identifier
4896					     (UTAG_PROTOCOL)))),
4897				  "protocol_list");
4898  chainon (field_decl_chain, field_decl);
4899
4900  if (flag_next_runtime)
4901    {
4902      /* void *sel_id; */
4903      field_decl = create_field_decl (build_pointer_type (void_type_node),
4904				      "sel_id");
4905      chainon (field_decl_chain, field_decl);
4906    }
4907
4908  /* void *gc_object_type; */
4909  field_decl = create_field_decl (build_pointer_type (void_type_node),
4910				  "gc_object_type");
4911  chainon (field_decl_chain, field_decl);
4912
4913  finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
4914}
4915
4916/* Generate appropriate forward declarations for an implementation.  */
4917
4918static void
4919synth_forward_declarations (void)
4920{
4921  tree an_id;
4922
4923  /* static struct objc_class _OBJC_CLASS_<my_name>; */
4924  UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
4925					  objc_class_template);
4926
4927  /* static struct objc_class _OBJC_METACLASS_<my_name>; */
4928  UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
4929						  objc_class_template);
4930
4931  /* Pre-build the following entities - for speed/convenience.  */
4932
4933  an_id = get_identifier ("super_class");
4934  ucls_super_ref = objc_build_component_ref (UOBJC_CLASS_decl, an_id);
4935  uucls_super_ref = objc_build_component_ref (UOBJC_METACLASS_decl, an_id);
4936}
4937
4938static void
4939error_with_ivar (const char *message, tree decl)
4940{
4941  error ("%J%s %qs", decl,
4942         message, gen_declaration (decl));
4943
4944}
4945
4946static void
4947check_ivars (tree inter, tree imp)
4948{
4949  tree intdecls = CLASS_RAW_IVARS (inter);
4950  tree impdecls = CLASS_RAW_IVARS (imp);
4951
4952  while (1)
4953    {
4954      tree t1, t2;
4955
4956#ifdef OBJCPLUS
4957      if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4958	intdecls = TREE_CHAIN (intdecls);
4959#endif
4960      if (intdecls == 0 && impdecls == 0)
4961	break;
4962      if (intdecls == 0 || impdecls == 0)
4963	{
4964	  error ("inconsistent instance variable specification");
4965	  break;
4966	}
4967
4968      t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4969
4970      if (!comptypes (t1, t2)
4971	  || !tree_int_cst_equal (DECL_INITIAL (intdecls),
4972				  DECL_INITIAL (impdecls)))
4973	{
4974	  if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4975	    {
4976	      error_with_ivar ("conflicting instance variable type",
4977			       impdecls);
4978	      error_with_ivar ("previous declaration of",
4979			       intdecls);
4980	    }
4981	  else			/* both the type and the name don't match */
4982	    {
4983	      error ("inconsistent instance variable specification");
4984	      break;
4985	    }
4986	}
4987
4988      else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4989	{
4990	  error_with_ivar ("conflicting instance variable name",
4991			   impdecls);
4992	  error_with_ivar ("previous declaration of",
4993			   intdecls);
4994	}
4995
4996      intdecls = TREE_CHAIN (intdecls);
4997      impdecls = TREE_CHAIN (impdecls);
4998    }
4999}
5000
5001/* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
5002   This needs to be done just once per compilation.  */
5003
5004/* struct _objc_super {
5005     struct _objc_object *self;
5006     struct _objc_class *super_class;
5007   };  */
5008
5009static void
5010build_super_template (void)
5011{
5012  tree field_decl, field_decl_chain;
5013
5014  objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
5015
5016  /* struct _objc_object *self; */
5017  field_decl = create_field_decl (objc_object_type, "self");
5018  field_decl_chain = field_decl;
5019
5020  /* struct _objc_class *super_class; */
5021  field_decl = create_field_decl (build_pointer_type (objc_class_template),
5022				  "super_class");
5023  chainon (field_decl_chain, field_decl);
5024
5025  finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
5026}
5027
5028/* struct _objc_ivar {
5029     char *ivar_name;
5030     char *ivar_type;
5031     int ivar_offset;
5032   };  */
5033
5034static tree
5035build_ivar_template (void)
5036{
5037  tree objc_ivar_id, objc_ivar_record;
5038  tree field_decl, field_decl_chain;
5039
5040  objc_ivar_id = get_identifier (UTAG_IVAR);
5041  objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
5042
5043  /* char *ivar_name; */
5044  field_decl = create_field_decl (string_type_node, "ivar_name");
5045  field_decl_chain = field_decl;
5046
5047  /* char *ivar_type; */
5048  field_decl = create_field_decl (string_type_node, "ivar_type");
5049  chainon (field_decl_chain, field_decl);
5050
5051  /* int ivar_offset; */
5052  field_decl = create_field_decl (integer_type_node, "ivar_offset");
5053  chainon (field_decl_chain, field_decl);
5054
5055  finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
5056
5057  return objc_ivar_record;
5058}
5059
5060/* struct {
5061     int ivar_count;
5062     struct objc_ivar ivar_list[ivar_count];
5063   };  */
5064
5065static tree
5066build_ivar_list_template (tree list_type, int size)
5067{
5068  tree objc_ivar_list_record;
5069  tree field_decl, field_decl_chain;
5070
5071  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
5072
5073  /* int ivar_count; */
5074  field_decl = create_field_decl (integer_type_node, "ivar_count");
5075  field_decl_chain = field_decl;
5076
5077  /* struct objc_ivar ivar_list[]; */
5078  field_decl = create_field_decl (build_array_type
5079				  (list_type,
5080				   build_index_type
5081				   (build_int_cst (NULL_TREE, size - 1))),
5082				  "ivar_list");
5083  chainon (field_decl_chain, field_decl);
5084
5085  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
5086
5087  return objc_ivar_list_record;
5088}
5089
5090/* struct {
5091     struct _objc__method_prototype_list *method_next;
5092     int method_count;
5093     struct objc_method method_list[method_count];
5094   };  */
5095
5096static tree
5097build_method_list_template (tree list_type, int size)
5098{
5099  tree objc_ivar_list_record;
5100  tree field_decl, field_decl_chain;
5101
5102  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
5103
5104  /* struct _objc__method_prototype_list *method_next; */
5105  field_decl = create_field_decl (objc_method_proto_list_ptr,
5106				  "method_next");
5107  field_decl_chain = field_decl;
5108
5109  /* int method_count; */
5110  field_decl = create_field_decl (integer_type_node, "method_count");
5111  chainon (field_decl_chain, field_decl);
5112
5113  /* struct objc_method method_list[]; */
5114  field_decl = create_field_decl (build_array_type
5115				  (list_type,
5116				   build_index_type
5117				   (build_int_cst (NULL_TREE, size - 1))),
5118				  "method_list");
5119  chainon (field_decl_chain, field_decl);
5120
5121  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
5122
5123  return objc_ivar_list_record;
5124}
5125
5126static tree
5127build_ivar_list_initializer (tree type, tree field_decl)
5128{
5129  tree initlist = NULL_TREE;
5130
5131  do
5132    {
5133      tree ivar = NULL_TREE;
5134
5135      /* Set name.  */
5136      if (DECL_NAME (field_decl))
5137	ivar = tree_cons (NULL_TREE,
5138			  add_objc_string (DECL_NAME (field_decl),
5139					   meth_var_names),
5140			  ivar);
5141      else
5142	/* Unnamed bit-field ivar (yuck).  */
5143	ivar = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), ivar);
5144
5145      /* Set type.  */
5146      encode_field_decl (field_decl,
5147			 obstack_object_size (&util_obstack),
5148			 OBJC_ENCODE_DONT_INLINE_DEFS);
5149
5150      /* Null terminate string.  */
5151      obstack_1grow (&util_obstack, 0);
5152      ivar
5153	= tree_cons
5154	  (NULL_TREE,
5155	   add_objc_string (get_identifier (obstack_finish (&util_obstack)),
5156			    meth_var_types),
5157	   ivar);
5158      obstack_free (&util_obstack, util_firstobj);
5159
5160      /* Set offset.  */
5161      ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
5162      initlist = tree_cons (NULL_TREE,
5163			    objc_build_constructor (type, nreverse (ivar)),
5164			    initlist);
5165      do
5166	field_decl = TREE_CHAIN (field_decl);
5167      while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
5168    }
5169  while (field_decl);
5170
5171  return objc_build_constructor (build_array_type (type, 0),
5172				 nreverse (initlist));
5173}
5174
5175static tree
5176generate_ivars_list (tree type, const char *name, int size, tree list)
5177{
5178  tree decl, initlist;
5179
5180  decl = start_var_decl (type, synth_id_with_class_suffix
5181			       (name, objc_implementation_context));
5182
5183  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
5184  initlist = tree_cons (NULL_TREE, list, initlist);
5185
5186  finish_var_decl (decl,
5187		   objc_build_constructor (TREE_TYPE (decl),
5188					   nreverse (initlist)));
5189
5190  return decl;
5191}
5192
5193/* Count only the fields occurring in T.  */
5194
5195static int
5196ivar_list_length (tree t)
5197{
5198  int count = 0;
5199
5200  for (; t; t = TREE_CHAIN (t))
5201    if (TREE_CODE (t) == FIELD_DECL)
5202      ++count;
5203
5204  return count;
5205}
5206
5207static void
5208generate_ivar_lists (void)
5209{
5210  tree initlist, ivar_list_template, chain;
5211  int size;
5212
5213  generating_instance_variables = 1;
5214
5215  if (!objc_ivar_template)
5216    objc_ivar_template = build_ivar_template ();
5217
5218  /* Only generate class variables for the root of the inheritance
5219     hierarchy since these will be the same for every class.  */
5220
5221  if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
5222      && (chain = TYPE_FIELDS (objc_class_template)))
5223    {
5224      size = ivar_list_length (chain);
5225
5226      ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5227      initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5228
5229      UOBJC_CLASS_VARIABLES_decl
5230	= generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
5231			       size, initlist);
5232    }
5233  else
5234    UOBJC_CLASS_VARIABLES_decl = 0;
5235
5236  chain = CLASS_IVARS (implementation_template);
5237  if (chain)
5238    {
5239      size = ivar_list_length (chain);
5240      ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
5241      initlist = build_ivar_list_initializer (objc_ivar_template, chain);
5242
5243      UOBJC_INSTANCE_VARIABLES_decl
5244	= generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
5245			       size, initlist);
5246    }
5247  else
5248    UOBJC_INSTANCE_VARIABLES_decl = 0;
5249
5250  generating_instance_variables = 0;
5251}
5252
5253static tree
5254build_dispatch_table_initializer (tree type, tree entries)
5255{
5256  tree initlist = NULL_TREE;
5257
5258  do
5259    {
5260      tree elemlist = NULL_TREE;
5261
5262      elemlist = tree_cons (NULL_TREE,
5263			    build_selector (METHOD_SEL_NAME (entries)),
5264			    NULL_TREE);
5265
5266      /* Generate the method encoding if we don't have one already.  */
5267      if (! METHOD_ENCODING (entries))
5268	METHOD_ENCODING (entries) =
5269	  encode_method_prototype (entries);
5270
5271      elemlist = tree_cons (NULL_TREE,
5272			    add_objc_string (METHOD_ENCODING (entries),
5273					     meth_var_types),
5274			    elemlist);
5275
5276      elemlist
5277	= tree_cons (NULL_TREE,
5278		     convert (ptr_type_node,
5279			      build_unary_op (ADDR_EXPR,
5280					      METHOD_DEFINITION (entries), 1)),
5281		     elemlist);
5282
5283      initlist = tree_cons (NULL_TREE,
5284			    objc_build_constructor (type, nreverse (elemlist)),
5285			    initlist);
5286
5287      entries = TREE_CHAIN (entries);
5288    }
5289  while (entries);
5290
5291  return objc_build_constructor (build_array_type (type, 0),
5292				 nreverse (initlist));
5293}
5294
5295/* To accomplish method prototyping without generating all kinds of
5296   inane warnings, the definition of the dispatch table entries were
5297   changed from:
5298
5299	struct objc_method { SEL _cmd; ...; id (*_imp)(); };
5300   to:
5301	struct objc_method { SEL _cmd; ...; void *_imp; };  */
5302
5303static tree
5304build_method_template (void)
5305{
5306  tree _SLT_record;
5307  tree field_decl, field_decl_chain;
5308
5309  _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
5310
5311  /* SEL _cmd; */
5312  field_decl = create_field_decl (objc_selector_type, "_cmd");
5313  field_decl_chain = field_decl;
5314
5315  /* char *method_types; */
5316  field_decl = create_field_decl (string_type_node, "method_types");
5317  chainon (field_decl_chain, field_decl);
5318
5319  /* void *_imp; */
5320  field_decl = create_field_decl (build_pointer_type (void_type_node),
5321				  "_imp");
5322  chainon (field_decl_chain, field_decl);
5323
5324  finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
5325
5326  return _SLT_record;
5327}
5328
5329
5330static tree
5331generate_dispatch_table (tree type, const char *name, int size, tree list)
5332{
5333  tree decl, initlist;
5334
5335  decl = start_var_decl (type, synth_id_with_class_suffix
5336			       (name, objc_implementation_context));
5337
5338  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
5339  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
5340  initlist = tree_cons (NULL_TREE, list, initlist);
5341
5342  finish_var_decl (decl,
5343		   objc_build_constructor (TREE_TYPE (decl),
5344					   nreverse (initlist)));
5345
5346  return decl;
5347}
5348
5349static void
5350mark_referenced_methods (void)
5351{
5352  struct imp_entry *impent;
5353  tree chain;
5354
5355  for (impent = imp_list; impent; impent = impent->next)
5356    {
5357      chain = CLASS_CLS_METHODS (impent->imp_context);
5358      while (chain)
5359	{
5360	  cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5361	  chain = TREE_CHAIN (chain);
5362	}
5363
5364      chain = CLASS_NST_METHODS (impent->imp_context);
5365      while (chain)
5366	{
5367	  cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
5368	  chain = TREE_CHAIN (chain);
5369	}
5370    }
5371}
5372
5373static void
5374generate_dispatch_tables (void)
5375{
5376  tree initlist, chain, method_list_template;
5377  int size;
5378
5379  if (!objc_method_template)
5380    objc_method_template = build_method_template ();
5381
5382  chain = CLASS_CLS_METHODS (objc_implementation_context);
5383  if (chain)
5384    {
5385      size = list_length (chain);
5386
5387      method_list_template
5388	= build_method_list_template (objc_method_template, size);
5389      initlist
5390	= build_dispatch_table_initializer (objc_method_template, chain);
5391
5392      UOBJC_CLASS_METHODS_decl
5393	= generate_dispatch_table (method_list_template,
5394				   ((TREE_CODE (objc_implementation_context)
5395				     == CLASS_IMPLEMENTATION_TYPE)
5396				    ? "_OBJC_CLASS_METHODS"
5397				    : "_OBJC_CATEGORY_CLASS_METHODS"),
5398				   size, initlist);
5399    }
5400  else
5401    UOBJC_CLASS_METHODS_decl = 0;
5402
5403  chain = CLASS_NST_METHODS (objc_implementation_context);
5404  if (chain)
5405    {
5406      size = list_length (chain);
5407
5408      method_list_template
5409	= build_method_list_template (objc_method_template, size);
5410      initlist
5411	= build_dispatch_table_initializer (objc_method_template, chain);
5412
5413      if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
5414	UOBJC_INSTANCE_METHODS_decl
5415	  = generate_dispatch_table (method_list_template,
5416				     "_OBJC_INSTANCE_METHODS",
5417				     size, initlist);
5418      else
5419	/* We have a category.  */
5420	UOBJC_INSTANCE_METHODS_decl
5421	  = generate_dispatch_table (method_list_template,
5422				     "_OBJC_CATEGORY_INSTANCE_METHODS",
5423				     size, initlist);
5424    }
5425  else
5426    UOBJC_INSTANCE_METHODS_decl = 0;
5427}
5428
5429static tree
5430generate_protocol_list (tree i_or_p)
5431{
5432  tree initlist;
5433  tree refs_decl, lproto, e, plist;
5434  int size = 0;
5435  const char *ref_name;
5436
5437  if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
5438      || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
5439    plist = CLASS_PROTOCOL_LIST (i_or_p);
5440  else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
5441    plist = PROTOCOL_LIST (i_or_p);
5442  else
5443    abort ();
5444
5445  /* Compute size.  */
5446  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
5447    if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
5448	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
5449      size++;
5450
5451  /* Build initializer.  */
5452  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), NULL_TREE);
5453  e = build_int_cst (build_pointer_type (objc_protocol_template), size);
5454  initlist = tree_cons (NULL_TREE, e, initlist);
5455
5456  for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
5457    {
5458      tree pval = TREE_VALUE (lproto);
5459
5460      if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
5461	  && PROTOCOL_FORWARD_DECL (pval))
5462	{
5463	  e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
5464	  initlist = tree_cons (NULL_TREE, e, initlist);
5465	}
5466    }
5467
5468  /* static struct objc_protocol *refs[n]; */
5469
5470  if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
5471    ref_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p);
5472  else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
5473    ref_name = synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p);
5474  else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
5475    ref_name = synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p);
5476  else
5477    abort ();
5478
5479  refs_decl = start_var_decl
5480	      (build_array_type
5481	       (build_pointer_type (objc_protocol_template),
5482		build_index_type (build_int_cst (NULL_TREE, size + 2))),
5483	       ref_name);
5484
5485  finish_var_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
5486  						      nreverse (initlist)));
5487
5488  return refs_decl;
5489}
5490
5491static tree
5492build_category_initializer (tree type, tree cat_name, tree class_name,
5493			    tree instance_methods, tree class_methods,
5494			    tree protocol_list)
5495{
5496  tree initlist = NULL_TREE, expr;
5497
5498  initlist = tree_cons (NULL_TREE, cat_name, initlist);
5499  initlist = tree_cons (NULL_TREE, class_name, initlist);
5500
5501  if (!instance_methods)
5502    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5503  else
5504    {
5505      expr = convert (objc_method_list_ptr,
5506		      build_unary_op (ADDR_EXPR, instance_methods, 0));
5507      initlist = tree_cons (NULL_TREE, expr, initlist);
5508    }
5509  if (!class_methods)
5510    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5511  else
5512    {
5513      expr = convert (objc_method_list_ptr,
5514		      build_unary_op (ADDR_EXPR, class_methods, 0));
5515      initlist = tree_cons (NULL_TREE, expr, initlist);
5516    }
5517
5518  /* protocol_list = */
5519  if (!protocol_list)
5520     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5521  else
5522    {
5523      expr = convert (build_pointer_type
5524		      (build_pointer_type
5525		       (objc_protocol_template)),
5526		      build_unary_op (ADDR_EXPR, protocol_list, 0));
5527      initlist = tree_cons (NULL_TREE, expr, initlist);
5528    }
5529
5530  return objc_build_constructor (type, nreverse (initlist));
5531}
5532
5533/* struct _objc_class {
5534     struct objc_class *isa;
5535     struct objc_class *super_class;
5536     char *name;
5537     long version;
5538     long info;
5539     long instance_size;
5540     struct objc_ivar_list *ivars;
5541     struct objc_method_list *methods;
5542     if (flag_next_runtime)
5543       struct objc_cache *cache;
5544     else {
5545       struct sarray *dtable;
5546       struct objc_class *subclass_list;
5547       struct objc_class *sibling_class;
5548     }
5549     struct objc_protocol_list *protocols;
5550     if (flag_next_runtime)
5551       void *sel_id;
5552     void *gc_object_type;
5553   };  */
5554
5555static tree
5556build_shared_structure_initializer (tree type, tree isa, tree super,
5557				    tree name, tree size, int status,
5558				    tree dispatch_table, tree ivar_list,
5559				    tree protocol_list)
5560{
5561  tree initlist = NULL_TREE, expr;
5562
5563  /* isa = */
5564  initlist = tree_cons (NULL_TREE, isa, initlist);
5565
5566  /* super_class = */
5567  initlist = tree_cons (NULL_TREE, super, initlist);
5568
5569  /* name = */
5570  initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
5571
5572  /* version = */
5573  initlist = tree_cons (NULL_TREE, build_int_cst (long_integer_type_node, 0),
5574			initlist);
5575
5576  /* info = */
5577  initlist = tree_cons (NULL_TREE,
5578			build_int_cst (long_integer_type_node, status),
5579			initlist);
5580
5581  /* instance_size = */
5582  initlist = tree_cons (NULL_TREE, convert (long_integer_type_node, size),
5583			initlist);
5584
5585  /* objc_ivar_list = */
5586  if (!ivar_list)
5587    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5588  else
5589    {
5590      expr = convert (objc_ivar_list_ptr,
5591		      build_unary_op (ADDR_EXPR, ivar_list, 0));
5592      initlist = tree_cons (NULL_TREE, expr, initlist);
5593    }
5594
5595  /* objc_method_list = */
5596  if (!dispatch_table)
5597    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5598  else
5599    {
5600      expr = convert (objc_method_list_ptr,
5601		      build_unary_op (ADDR_EXPR, dispatch_table, 0));
5602      initlist = tree_cons (NULL_TREE, expr, initlist);
5603    }
5604
5605  if (flag_next_runtime)
5606    /* method_cache = */
5607    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5608  else
5609    {
5610      /* dtable = */
5611      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5612
5613      /* subclass_list = */
5614      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5615
5616      /* sibling_class = */
5617      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5618    }
5619
5620  /* protocol_list = */
5621  if (! protocol_list)
5622    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5623  else
5624    {
5625      expr = convert (build_pointer_type
5626		      (build_pointer_type
5627		       (objc_protocol_template)),
5628		      build_unary_op (ADDR_EXPR, protocol_list, 0));
5629      initlist = tree_cons (NULL_TREE, expr, initlist);
5630    }
5631
5632  if (flag_next_runtime)
5633    /* sel_id = NULL */
5634    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5635
5636  /* gc_object_type = NULL */
5637  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
5638
5639  return objc_build_constructor (type, nreverse (initlist));
5640}
5641
5642/* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
5643
5644static inline tree
5645lookup_category (tree class, tree cat_name)
5646{
5647  tree category = CLASS_CATEGORY_LIST (class);
5648
5649  while (category && CLASS_SUPER_NAME (category) != cat_name)
5650    category = CLASS_CATEGORY_LIST (category);
5651  return category;
5652}
5653
5654/* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
5655
5656static void
5657generate_category (tree cat)
5658{
5659  tree decl;
5660  tree initlist, cat_name_expr, class_name_expr;
5661  tree protocol_decl, category;
5662
5663  add_class_reference (CLASS_NAME (cat));
5664  cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5665
5666  class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5667
5668  category = lookup_category (implementation_template,
5669				CLASS_SUPER_NAME (cat));
5670
5671  if (category && CLASS_PROTOCOL_LIST (category))
5672    {
5673      generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5674      protocol_decl = generate_protocol_list (category);
5675    }
5676  else
5677    protocol_decl = 0;
5678
5679  decl = start_var_decl (objc_category_template,
5680			 synth_id_with_class_suffix
5681			 ("_OBJC_CATEGORY", objc_implementation_context));
5682
5683  initlist = build_category_initializer (TREE_TYPE (decl),
5684					 cat_name_expr, class_name_expr,
5685					 UOBJC_INSTANCE_METHODS_decl,
5686					 UOBJC_CLASS_METHODS_decl,
5687					 protocol_decl);
5688
5689  finish_var_decl (decl, initlist);
5690}
5691
5692/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5693   static struct objc_class _OBJC_CLASS_Foo={ ... };  */
5694
5695static void
5696generate_shared_structures (int cls_flags)
5697{
5698  tree sc_spec, decl_specs, decl;
5699  tree name_expr, super_expr, root_expr;
5700  tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5701  tree cast_type, initlist, protocol_decl;
5702
5703  my_super_id = CLASS_SUPER_NAME (implementation_template);
5704  if (my_super_id)
5705    {
5706      add_class_reference (my_super_id);
5707
5708      /* Compute "my_root_id" - this is required for code generation.
5709         the "isa" for all meta class structures points to the root of
5710         the inheritance hierarchy (e.g. "__Object")...  */
5711      my_root_id = my_super_id;
5712      do
5713	{
5714	  tree my_root_int = lookup_interface (my_root_id);
5715
5716	  if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5717	    my_root_id = CLASS_SUPER_NAME (my_root_int);
5718	  else
5719	    break;
5720	}
5721      while (1);
5722    }
5723  else
5724    /* No super class.  */
5725    my_root_id = CLASS_NAME (implementation_template);
5726
5727  cast_type = build_pointer_type (objc_class_template);
5728  name_expr = add_objc_string (CLASS_NAME (implementation_template),
5729			       class_names);
5730
5731  /* Install class `isa' and `super' pointers at runtime.  */
5732  if (my_super_id)
5733    {
5734      super_expr = add_objc_string (my_super_id, class_names);
5735      super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5736    }
5737  else
5738    super_expr = build_int_cst (NULL_TREE, 0);
5739
5740  root_expr = add_objc_string (my_root_id, class_names);
5741  root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5742
5743  if (CLASS_PROTOCOL_LIST (implementation_template))
5744    {
5745      generate_protocol_references
5746	(CLASS_PROTOCOL_LIST (implementation_template));
5747      protocol_decl = generate_protocol_list (implementation_template);
5748    }
5749  else
5750    protocol_decl = 0;
5751
5752  /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5753
5754  sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5755  decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5756
5757  decl = start_var_decl (objc_class_template,
5758			 IDENTIFIER_POINTER
5759			 (DECL_NAME (UOBJC_METACLASS_decl)));
5760
5761  initlist
5762    = build_shared_structure_initializer
5763      (TREE_TYPE (decl),
5764       root_expr, super_expr, name_expr,
5765       convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5766       2 /*CLS_META*/,
5767       UOBJC_CLASS_METHODS_decl,
5768       UOBJC_CLASS_VARIABLES_decl,
5769       protocol_decl);
5770
5771  finish_var_decl (decl, initlist);
5772
5773  /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5774
5775  decl = start_var_decl (objc_class_template,
5776			 IDENTIFIER_POINTER
5777			 (DECL_NAME (UOBJC_CLASS_decl)));
5778
5779  initlist
5780    = build_shared_structure_initializer
5781      (TREE_TYPE (decl),
5782       build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5783       super_expr, name_expr,
5784       convert (integer_type_node,
5785		TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5786				(implementation_template))),
5787       1 /*CLS_FACTORY*/ | cls_flags,
5788       UOBJC_INSTANCE_METHODS_decl,
5789       UOBJC_INSTANCE_VARIABLES_decl,
5790       protocol_decl);
5791
5792  finish_var_decl (decl, initlist);
5793}
5794
5795
5796static const char *
5797synth_id_with_class_suffix (const char *preamble, tree ctxt)
5798{
5799  static char string[BUFSIZE];
5800
5801  if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5802      || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5803    {
5804      sprintf (string, "%s_%s", preamble,
5805	       IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5806    }
5807  else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5808	   || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5809    {
5810      /* We have a category.  */
5811      const char *const class_name
5812	= IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5813      const char *const class_super_name
5814	= IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5815      sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5816    }
5817  else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5818    {
5819      const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5820      sprintf (string, "%s_%s", preamble, protocol_name);
5821    }
5822  else
5823    abort ();
5824
5825  return string;
5826}
5827
5828/* If type is empty or only type qualifiers are present, add default
5829   type of id (otherwise grokdeclarator will default to int).  */
5830
5831static tree
5832adjust_type_for_id_default (tree type)
5833{
5834  if (!type)
5835    type = make_node (TREE_LIST);
5836
5837  if (!TREE_VALUE (type))
5838    TREE_VALUE (type) = objc_object_type;
5839  else if (TREE_CODE (TREE_VALUE (type)) == RECORD_TYPE
5840	   && TYPED_OBJECT (TREE_VALUE (type)))
5841    error ("can not use an object as parameter to a method");
5842
5843  return type;
5844}
5845
5846/*   Usage:
5847		keyworddecl:
5848			selector ':' '(' typename ')' identifier
5849
5850     Purpose:
5851		Transform an Objective-C keyword argument into
5852		the C equivalent parameter declarator.
5853
5854     In:	key_name, an "identifier_node" (optional).
5855		arg_type, a  "tree_list" (optional).
5856		arg_name, an "identifier_node".
5857
5858     Note:	It would be really nice to strongly type the preceding
5859		arguments in the function prototype; however, then I
5860		could not use the "accessor" macros defined in "tree.h".
5861
5862     Out:	an instance of "keyword_decl".  */
5863
5864tree
5865objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5866{
5867  tree keyword_decl;
5868
5869  /* If no type is specified, default to "id".  */
5870  arg_type = adjust_type_for_id_default (arg_type);
5871
5872  keyword_decl = make_node (KEYWORD_DECL);
5873
5874  TREE_TYPE (keyword_decl) = arg_type;
5875  KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5876  KEYWORD_KEY_NAME (keyword_decl) = key_name;
5877
5878  return keyword_decl;
5879}
5880
5881/* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
5882
5883static tree
5884build_keyword_selector (tree selector)
5885{
5886  int len = 0;
5887  tree key_chain, key_name;
5888  char *buf;
5889
5890  /* Scan the selector to see how much space we'll need.  */
5891  for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5892    {
5893      if (TREE_CODE (selector) == KEYWORD_DECL)
5894	key_name = KEYWORD_KEY_NAME (key_chain);
5895      else if (TREE_CODE (selector) == TREE_LIST)
5896	key_name = TREE_PURPOSE (key_chain);
5897      else
5898	abort ();
5899
5900      if (key_name)
5901	len += IDENTIFIER_LENGTH (key_name) + 1;
5902      else
5903	/* Just a ':' arg.  */
5904	len++;
5905    }
5906
5907  buf = (char *) alloca (len + 1);
5908  /* Start the buffer out as an empty string.  */
5909  buf[0] = '\0';
5910
5911  for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5912    {
5913      if (TREE_CODE (selector) == KEYWORD_DECL)
5914	key_name = KEYWORD_KEY_NAME (key_chain);
5915      else if (TREE_CODE (selector) == TREE_LIST)
5916	{
5917	  key_name = TREE_PURPOSE (key_chain);
5918	  /* The keyword decl chain will later be used as a function argument
5919	     chain.  Unhook the selector itself so as to not confuse other
5920	     parts of the compiler.  */
5921	  TREE_PURPOSE (key_chain) = NULL_TREE;
5922	}
5923      else
5924	abort ();
5925
5926      if (key_name)
5927	strcat (buf, IDENTIFIER_POINTER (key_name));
5928      strcat (buf, ":");
5929    }
5930
5931  return get_identifier (buf);
5932}
5933
5934/* Used for declarations and definitions.  */
5935
5936static tree
5937build_method_decl (enum tree_code code, tree ret_type, tree selector,
5938		   tree add_args, bool ellipsis)
5939{
5940  tree method_decl;
5941
5942  /* If no type is specified, default to "id".  */
5943  ret_type = adjust_type_for_id_default (ret_type);
5944
5945  method_decl = make_node (code);
5946  TREE_TYPE (method_decl) = ret_type;
5947
5948  /* If we have a keyword selector, create an identifier_node that
5949     represents the full selector name (`:' included)...  */
5950  if (TREE_CODE (selector) == KEYWORD_DECL)
5951    {
5952      METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5953      METHOD_SEL_ARGS (method_decl) = selector;
5954      METHOD_ADD_ARGS (method_decl) = add_args;
5955      METHOD_ADD_ARGS_ELLIPSIS_P (method_decl) = ellipsis;
5956    }
5957  else
5958    {
5959      METHOD_SEL_NAME (method_decl) = selector;
5960      METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5961      METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5962    }
5963
5964  return method_decl;
5965}
5966
5967#define METHOD_DEF 0
5968#define METHOD_REF 1
5969
5970/* Used by `build_objc_method_call' and `comp_proto_with_proto'.  Return
5971   an argument list for method METH.  CONTEXT is either METHOD_DEF or
5972   METHOD_REF, saying whether we are trying to define a method or call
5973   one.  SUPERFLAG says this is for a send to super; this makes a
5974   difference for the NeXT calling sequence in which the lookup and
5975   the method call are done together.  If METH is null, user-defined
5976   arguments (i.e., beyond self and _cmd) shall be represented by `...'.  */
5977
5978static tree
5979get_arg_type_list (tree meth, int context, int superflag)
5980{
5981  tree arglist, akey;
5982
5983  /* Receiver type.  */
5984  if (flag_next_runtime && superflag)
5985    arglist = build_tree_list (NULL_TREE, objc_super_type);
5986  else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5987    arglist = build_tree_list (NULL_TREE, objc_instance_type);
5988  else
5989    arglist = build_tree_list (NULL_TREE, objc_object_type);
5990
5991  /* Selector type - will eventually change to `int'.  */
5992  chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
5993
5994  /* No actual method prototype given -- assume that remaining arguments
5995     are `...'.  */
5996  if (!meth)
5997    return arglist;
5998
5999  /* Build a list of argument types.  */
6000  for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
6001    {
6002      tree arg_type = TREE_VALUE (TREE_TYPE (akey));
6003
6004      /* Decay arrays and functions into pointers.  */
6005      if (TREE_CODE (arg_type) == ARRAY_TYPE)
6006	arg_type = build_pointer_type (TREE_TYPE (arg_type));
6007      else if (TREE_CODE (arg_type) == FUNCTION_TYPE)
6008	arg_type = build_pointer_type (arg_type);
6009
6010      chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6011    }
6012
6013  if (METHOD_ADD_ARGS (meth))
6014    {
6015      for (akey = TREE_CHAIN (METHOD_ADD_ARGS (meth));
6016	   akey; akey = TREE_CHAIN (akey))
6017	{
6018	  tree arg_type = TREE_TYPE (TREE_VALUE (akey));
6019
6020	  chainon (arglist, build_tree_list (NULL_TREE, arg_type));
6021	}
6022
6023      if (!METHOD_ADD_ARGS_ELLIPSIS_P (meth))
6024	goto lack_of_ellipsis;
6025    }
6026  else
6027    {
6028     lack_of_ellipsis:
6029      chainon (arglist, OBJC_VOID_AT_END);
6030    }
6031
6032  return arglist;
6033}
6034
6035static tree
6036check_duplicates (hash hsh, int methods, int is_class)
6037{
6038  tree meth = NULL_TREE;
6039
6040  if (hsh)
6041    {
6042      meth = hsh->key;
6043
6044      if (hsh->list)
6045        {
6046	  /* We have two or more methods with the same name but
6047	     different types.  */
6048	  attr loop;
6049
6050	  /* But just how different are those types?  If
6051	     -Wno-strict-selector-match is specified, we shall not
6052	     complain if the differences are solely among types with
6053	     identical size and alignment.  */
6054	  if (!warn_strict_selector_match)
6055	    {
6056	      for (loop = hsh->list; loop; loop = loop->next)
6057		if (!comp_proto_with_proto (meth, loop->value, 0))
6058		  goto issue_warning;
6059
6060	      return meth;
6061	    }
6062
6063	issue_warning:
6064	  warning (0, "multiple %s named %<%c%s%> found",
6065		   methods ? "methods" : "selectors",
6066		   (is_class ? '+' : '-'),
6067		   IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
6068
6069	  warn_with_method (methods ? "using" : "found",
6070			    ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
6071			     ? '-'
6072			     : '+'),
6073			    meth);
6074	  for (loop = hsh->list; loop; loop = loop->next)
6075	    warn_with_method ("also found",
6076			      ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
6077			       ? '-'
6078			       : '+'),
6079			      loop->value);
6080        }
6081    }
6082  return meth;
6083}
6084
6085/* If RECEIVER is a class reference, return the identifier node for
6086   the referenced class.  RECEIVER is created by objc_get_class_reference,
6087   so we check the exact form created depending on which runtimes are
6088   used.  */
6089
6090static tree
6091receiver_is_class_object (tree receiver, int self, int super)
6092{
6093  tree chain, exp, arg;
6094
6095  /* The receiver is 'self' or 'super' in the context of a class method.  */
6096  if (objc_method_context
6097      && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
6098      && (self || super))
6099    return (super
6100	    ? CLASS_SUPER_NAME (implementation_template)
6101	    : CLASS_NAME (implementation_template));
6102
6103  if (flag_next_runtime)
6104    {
6105      /* The receiver is a variable created by
6106         build_class_reference_decl.  */
6107      if (TREE_CODE (receiver) == VAR_DECL && IS_CLASS (TREE_TYPE (receiver)))
6108        /* Look up the identifier.  */
6109	for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
6110	  if (TREE_PURPOSE (chain) == receiver)
6111            return TREE_VALUE (chain);
6112    }
6113
6114  /* The receiver is a function call that returns an id.  Check if
6115     it is a call to objc_getClass, if so, pick up the class name.  */
6116  if (TREE_CODE (receiver) == CALL_EXPR
6117      && (exp = TREE_OPERAND (receiver, 0))
6118      && TREE_CODE (exp) == ADDR_EXPR
6119      && (exp = TREE_OPERAND (exp, 0))
6120      && TREE_CODE (exp) == FUNCTION_DECL
6121      /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
6122	 prototypes for objc_get_class().  Thankfully, they seem to share the
6123	 same function type.  */
6124      && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
6125      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
6126      /* We have a call to objc_get_class/objc_getClass!  */
6127      && (arg = TREE_OPERAND (receiver, 1))
6128      && TREE_CODE (arg) == TREE_LIST
6129      && (arg = TREE_VALUE (arg)))
6130    {
6131      STRIP_NOPS (arg);
6132      if (TREE_CODE (arg) == ADDR_EXPR
6133	  && (arg = TREE_OPERAND (arg, 0))
6134	  && TREE_CODE (arg) == STRING_CST)
6135	/* Finally, we have the class name.  */
6136	return get_identifier (TREE_STRING_POINTER (arg));
6137    }
6138  return 0;
6139}
6140
6141/* If we are currently building a message expr, this holds
6142   the identifier of the selector of the message.  This is
6143   used when printing warnings about argument mismatches.  */
6144
6145static tree current_objc_message_selector = 0;
6146
6147tree
6148objc_message_selector (void)
6149{
6150  return current_objc_message_selector;
6151}
6152
6153/* Construct an expression for sending a message.
6154   MESS has the object to send to in TREE_PURPOSE
6155   and the argument list (including selector) in TREE_VALUE.
6156
6157   (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
6158   (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
6159
6160tree
6161objc_build_message_expr (tree mess)
6162{
6163  tree receiver = TREE_PURPOSE (mess);
6164  tree sel_name;
6165#ifdef OBJCPLUS
6166  tree args = TREE_PURPOSE (TREE_VALUE (mess));
6167#else
6168  tree args = TREE_VALUE (mess);
6169#endif
6170  tree method_params = NULL_TREE;
6171
6172  if (TREE_CODE (receiver) == ERROR_MARK)
6173    return error_mark_node;
6174
6175  /* Obtain the full selector name.  */
6176  if (TREE_CODE (args) == IDENTIFIER_NODE)
6177    /* A unary selector.  */
6178    sel_name = args;
6179  else if (TREE_CODE (args) == TREE_LIST)
6180    sel_name = build_keyword_selector (args);
6181  else
6182    abort ();
6183
6184  /* Build the parameter list to give to the method.  */
6185  if (TREE_CODE (args) == TREE_LIST)
6186#ifdef OBJCPLUS
6187    method_params = chainon (args, TREE_VALUE (TREE_VALUE (mess)));
6188#else
6189    {
6190      tree chain = args, prev = NULL_TREE;
6191
6192      /* We have a keyword selector--check for comma expressions.  */
6193      while (chain)
6194	{
6195	  tree element = TREE_VALUE (chain);
6196
6197	  /* We have a comma expression, must collapse...  */
6198	  if (TREE_CODE (element) == TREE_LIST)
6199	    {
6200	      if (prev)
6201		TREE_CHAIN (prev) = element;
6202	      else
6203		args = element;
6204	    }
6205	  prev = chain;
6206	  chain = TREE_CHAIN (chain);
6207        }
6208      method_params = args;
6209    }
6210#endif
6211
6212#ifdef OBJCPLUS
6213  if (processing_template_decl)
6214    /* Must wait until template instantiation time.  */
6215    return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
6216			 method_params);
6217#endif
6218
6219  return objc_finish_message_expr (receiver, sel_name, method_params);
6220}
6221
6222/* Look up method SEL_NAME that would be suitable for receiver
6223   of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
6224   nonzero), and report on any duplicates.  */
6225
6226static tree
6227lookup_method_in_hash_lists (tree sel_name, int is_class)
6228{
6229  hash method_prototype = NULL;
6230
6231  if (!is_class)
6232    method_prototype = hash_lookup (nst_method_hash_list,
6233				    sel_name);
6234
6235  if (!method_prototype)
6236    {
6237      method_prototype = hash_lookup (cls_method_hash_list,
6238				      sel_name);
6239      is_class = 1;
6240    }
6241
6242  return check_duplicates (method_prototype, 1, is_class);
6243}
6244
6245/* The 'objc_finish_message_expr' routine is called from within
6246   'objc_build_message_expr' for non-template functions.  In the case of
6247   C++ template functions, it is called from 'build_expr_from_tree'
6248   (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
6249
6250tree
6251objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
6252{
6253  tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
6254  tree selector, retval, class_tree;
6255  int self, super, have_cast;
6256
6257  /* Extract the receiver of the message, as well as its type
6258     (where the latter may take the form of a cast or be inferred
6259     from the implementation context).  */
6260  rtype = receiver;
6261  while (TREE_CODE (rtype) == COMPOUND_EXPR
6262	      || TREE_CODE (rtype) == MODIFY_EXPR
6263	      || TREE_CODE (rtype) == NOP_EXPR
6264	      || TREE_CODE (rtype) == CONVERT_EXPR
6265	      || TREE_CODE (rtype) == COMPONENT_REF)
6266    rtype = TREE_OPERAND (rtype, 0);
6267  self = (rtype == self_decl);
6268  super = (rtype == UOBJC_SUPER_decl);
6269  rtype = TREE_TYPE (receiver);
6270  have_cast = (TREE_CODE (receiver) == NOP_EXPR
6271	       || (TREE_CODE (receiver) == COMPOUND_EXPR
6272		   && !IS_SUPER (rtype)));
6273
6274  /* If we are calling [super dealloc], reset our warning flag.  */
6275  if (super && !strcmp ("dealloc", IDENTIFIER_POINTER (sel_name)))
6276    should_call_super_dealloc = 0;
6277
6278  /* If the receiver is a class object, retrieve the corresponding
6279     @interface, if one exists. */
6280  class_tree = receiver_is_class_object (receiver, self, super);
6281
6282  /* Now determine the receiver type (if an explicit cast has not been
6283     provided).  */
6284  if (!have_cast)
6285    {
6286      if (class_tree)
6287	rtype = lookup_interface (class_tree);
6288      /* Handle `self' and `super'.  */
6289      else if (super)
6290	{
6291	  if (!CLASS_SUPER_NAME (implementation_template))
6292	    {
6293	      error ("no super class declared in @interface for %qs",
6294		     IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
6295	      return error_mark_node;
6296	    }
6297	  rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6298	}
6299      else if (self)
6300	rtype = lookup_interface (CLASS_NAME (implementation_template));
6301    }
6302
6303  /* If receiver is of type `id' or `Class' (or if the @interface for a
6304     class is not visible), we shall be satisfied with the existence of
6305     any instance or class method. */
6306  if (objc_is_id (rtype))
6307    {
6308      class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE);
6309      rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
6310		 ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
6311		 : NULL_TREE);
6312      rtype = NULL_TREE;
6313
6314      if (rprotos)
6315	{
6316	  /* If messaging 'id <Protos>' or 'Class <Proto>', first search
6317	     in protocols themselves for the method prototype.  */
6318	  method_prototype
6319	    = lookup_method_in_protocol_list (rprotos, sel_name,
6320					      class_tree != NULL_TREE);
6321
6322	  /* If messaging 'Class <Proto>' but did not find a class method
6323	     prototype, search for an instance method instead, and warn
6324	     about having done so.  */
6325	  if (!method_prototype && !rtype && class_tree != NULL_TREE)
6326	    {
6327	      method_prototype
6328		= lookup_method_in_protocol_list (rprotos, sel_name, 0);
6329
6330	      if (method_prototype)
6331		warning (0, "found %<-%s%> instead of %<+%s%> in protocol(s)",
6332			 IDENTIFIER_POINTER (sel_name),
6333			 IDENTIFIER_POINTER (sel_name));
6334	    }
6335	}
6336    }
6337  else if (rtype)
6338    {
6339      tree orig_rtype = rtype, saved_rtype;
6340
6341      if (TREE_CODE (rtype) == POINTER_TYPE)
6342	rtype = TREE_TYPE (rtype);
6343      /* Traverse typedef aliases */
6344      while (TREE_CODE (rtype) == RECORD_TYPE && OBJC_TYPE_NAME (rtype)
6345	     && TREE_CODE (OBJC_TYPE_NAME (rtype)) == TYPE_DECL
6346	     && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype)))
6347	rtype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype));
6348      saved_rtype = rtype;
6349      if (TYPED_OBJECT (rtype))
6350	{
6351	  rprotos = TYPE_OBJC_PROTOCOL_LIST (rtype);
6352	  rtype = TYPE_OBJC_INTERFACE (rtype);
6353	}
6354      /* If we could not find an @interface declaration, we must have
6355	 only seen a @class declaration; so, we cannot say anything
6356	 more intelligent about which methods the receiver will
6357	 understand. */
6358      if (!rtype || TREE_CODE (rtype) == IDENTIFIER_NODE)
6359	rtype = NULL_TREE;
6360      else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
6361	  || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
6362	{
6363	  /* We have a valid ObjC class name.  Look up the method name
6364	     in the published @interface for the class (and its
6365	     superclasses). */
6366	  method_prototype
6367	    = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
6368
6369	  /* If the method was not found in the @interface, it may still
6370	     exist locally as part of the @implementation.  */
6371	  if (!method_prototype && objc_implementation_context
6372	     && CLASS_NAME (objc_implementation_context)
6373		== OBJC_TYPE_NAME (rtype))
6374	    method_prototype
6375	      = lookup_method
6376		((class_tree
6377		  ? CLASS_CLS_METHODS (objc_implementation_context)
6378		  : CLASS_NST_METHODS (objc_implementation_context)),
6379		  sel_name);
6380
6381	  /* If we haven't found a candidate method by now, try looking for
6382	     it in the protocol list.  */
6383	  if (!method_prototype && rprotos)
6384	    method_prototype
6385	      = lookup_method_in_protocol_list (rprotos, sel_name,
6386						class_tree != NULL_TREE);
6387	}
6388      else
6389	{
6390	  warning (0, "invalid receiver type %qs",
6391		   gen_type_name (orig_rtype));
6392	  /* After issuing the "invalid receiver" warning, perform method
6393	     lookup as if we were messaging 'id'.  */
6394	  rtype = rprotos = NULL_TREE;
6395	}
6396    }
6397
6398
6399  /* For 'id' or 'Class' receivers, search in the global hash table
6400     as a last resort.  For all receivers, warn if protocol searches
6401     have failed.  */
6402  if (!method_prototype)
6403    {
6404      if (rprotos)
6405	warning (0, "%<%c%s%> not found in protocol(s)",
6406		 (class_tree ? '+' : '-'),
6407		 IDENTIFIER_POINTER (sel_name));
6408
6409      if (!rtype)
6410	method_prototype
6411	  = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
6412    }
6413
6414  if (!method_prototype)
6415    {
6416      static bool warn_missing_methods = false;
6417
6418      if (rtype)
6419	warning (0, "%qs may not respond to %<%c%s%>",
6420		 IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
6421		 (class_tree ? '+' : '-'),
6422		 IDENTIFIER_POINTER (sel_name));
6423      /* If we are messaging an 'id' or 'Class' object and made it here,
6424	 then we have failed to find _any_ instance or class method,
6425	 respectively.  */
6426      else
6427	warning (0, "no %<%c%s%> method found",
6428		 (class_tree ? '+' : '-'),
6429		 IDENTIFIER_POINTER (sel_name));
6430
6431      if (!warn_missing_methods)
6432	{
6433	  warning (0, "(Messages without a matching method signature");
6434	  warning (0, "will be assumed to return %<id%> and accept");
6435	  warning (0, "%<...%> as arguments.)");
6436	  warn_missing_methods = true;
6437	}
6438    }
6439
6440  /* Save the selector name for printing error messages.  */
6441  current_objc_message_selector = sel_name;
6442
6443  /* Build the parameters list for looking up the method.
6444     These are the object itself and the selector.  */
6445
6446  if (flag_typed_selectors)
6447    selector = build_typed_selector_reference (sel_name, method_prototype);
6448  else
6449    selector = build_selector_reference (sel_name);
6450
6451  retval = build_objc_method_call (super, method_prototype,
6452				   receiver,
6453				   selector, method_params);
6454
6455  current_objc_message_selector = 0;
6456
6457  return retval;
6458}
6459
6460/* Build a tree expression to send OBJECT the operation SELECTOR,
6461   looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
6462   assuming the method has prototype METHOD_PROTOTYPE.
6463   (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
6464   Use METHOD_PARAMS as list of args to pass to the method.
6465   If SUPER_FLAG is nonzero, we look up the superclass's method.  */
6466
6467static tree
6468build_objc_method_call (int super_flag, tree method_prototype,
6469			tree lookup_object, tree selector,
6470			tree method_params)
6471{
6472  tree sender = (super_flag ? umsg_super_decl :
6473		 (!flag_next_runtime || flag_nil_receivers
6474		  ? (flag_objc_direct_dispatch
6475		     ? umsg_fast_decl
6476		     : umsg_decl)
6477		  : umsg_nonnil_decl));
6478  tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
6479
6480  /* If a prototype for the method to be called exists, then cast
6481     the sender's return type and arguments to match that of the method.
6482     Otherwise, leave sender as is.  */
6483  tree ret_type
6484    = (method_prototype
6485       ? TREE_VALUE (TREE_TYPE (method_prototype))
6486       : objc_object_type);
6487  tree sender_cast
6488    = build_pointer_type
6489      (build_function_type
6490       (ret_type,
6491	get_arg_type_list
6492	(method_prototype, METHOD_REF, super_flag)));
6493  tree method, t;
6494
6495  lookup_object = build_c_cast (rcv_p, lookup_object);
6496
6497  /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
6498  lookup_object = save_expr (lookup_object);
6499
6500  if (flag_next_runtime)
6501    {
6502      /* If we are returning a struct in memory, and the address
6503	 of that memory location is passed as a hidden first
6504	 argument, then change which messenger entry point this
6505	 expr will call.  NB: Note that sender_cast remains
6506	 unchanged (it already has a struct return type).  */
6507      if (!targetm.calls.struct_value_rtx (0, 0)
6508	  && (TREE_CODE (ret_type) == RECORD_TYPE
6509	      || TREE_CODE (ret_type) == UNION_TYPE)
6510	  && targetm.calls.return_in_memory (ret_type, 0))
6511	sender = (super_flag ? umsg_super_stret_decl :
6512		flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
6513
6514      method_params = tree_cons (NULL_TREE, lookup_object,
6515				 tree_cons (NULL_TREE, selector,
6516					    method_params));
6517      method = build_fold_addr_expr (sender);
6518    }
6519  else
6520    {
6521      /* This is the portable (GNU) way.  */
6522      tree object;
6523
6524      /* First, call the lookup function to get a pointer to the method,
6525	 then cast the pointer, then call it with the method arguments.  */
6526
6527      object = (super_flag ? self_decl : lookup_object);
6528
6529      t = tree_cons (NULL_TREE, selector, NULL_TREE);
6530      t = tree_cons (NULL_TREE, lookup_object, t);
6531      method = build_function_call (sender, t);
6532
6533      /* Pass the object to the method.  */
6534      method_params = tree_cons (NULL_TREE, object,
6535				 tree_cons (NULL_TREE, selector,
6536					    method_params));
6537    }
6538
6539  /* ??? Selector is not at this point something we can use inside
6540     the compiler itself.  Set it to garbage for the nonce.  */
6541  t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
6542  return build_function_call (t, method_params);
6543}
6544
6545static void
6546build_protocol_reference (tree p)
6547{
6548  tree decl;
6549  const char *proto_name;
6550
6551  /* static struct _objc_protocol _OBJC_PROTOCOL_<mumble>; */
6552
6553  proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
6554  decl = start_var_decl (objc_protocol_template, proto_name);
6555
6556  PROTOCOL_FORWARD_DECL (p) = decl;
6557}
6558
6559/* This function is called by the parser when (and only when) a
6560   @protocol() expression is found, in order to compile it.  */
6561tree
6562objc_build_protocol_expr (tree protoname)
6563{
6564  tree expr;
6565  tree p = lookup_protocol (protoname);
6566
6567  if (!p)
6568    {
6569      error ("cannot find protocol declaration for %qs",
6570	     IDENTIFIER_POINTER (protoname));
6571      return error_mark_node;
6572    }
6573
6574  if (!PROTOCOL_FORWARD_DECL (p))
6575    build_protocol_reference (p);
6576
6577  expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
6578
6579  /* ??? Ideally we'd build the reference with objc_protocol_type directly,
6580     if we have it, rather than converting it here.  */
6581  expr = convert (objc_protocol_type, expr);
6582
6583  /* The @protocol() expression is being compiled into a pointer to a
6584     statically allocated instance of the Protocol class.  To become
6585     usable at runtime, the 'isa' pointer of the instance need to be
6586     fixed up at runtime by the runtime library, to point to the
6587     actual 'Protocol' class.  */
6588
6589  /* For the GNU runtime, put the static Protocol instance in the list
6590     of statically allocated instances, so that we make sure that its
6591     'isa' pointer is fixed up at runtime by the GNU runtime library
6592     to point to the Protocol class (at runtime, when loading the
6593     module, the GNU runtime library loops on the statically allocated
6594     instances (as found in the defs field in objc_symtab) and fixups
6595     all the 'isa' pointers of those objects).  */
6596  if (! flag_next_runtime)
6597    {
6598      /* This type is a struct containing the fields of a Protocol
6599        object.  (Cfr. objc_protocol_type instead is the type of a pointer
6600        to such a struct).  */
6601      tree protocol_struct_type = xref_tag
6602       (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
6603      tree *chain;
6604
6605      /* Look for the list of Protocol statically allocated instances
6606        to fixup at runtime.  Create a new list to hold Protocol
6607        statically allocated instances, if the list is not found.  At
6608        present there is only another list, holding NSConstantString
6609        static instances to be fixed up at runtime.  */
6610      for (chain = &objc_static_instances;
6611	   *chain && TREE_VALUE (*chain) != protocol_struct_type;
6612	   chain = &TREE_CHAIN (*chain));
6613      if (!*chain)
6614	{
6615         *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6616         add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6617                          class_names);
6618       }
6619
6620      /* Add this statically allocated instance to the Protocol list.  */
6621      TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6622					 PROTOCOL_FORWARD_DECL (p),
6623					 TREE_PURPOSE (*chain));
6624    }
6625
6626
6627  return expr;
6628}
6629
6630/* This function is called by the parser when a @selector() expression
6631   is found, in order to compile it.  It is only called by the parser
6632   and only to compile a @selector().  */
6633tree
6634objc_build_selector_expr (tree selnamelist)
6635{
6636  tree selname;
6637
6638  /* Obtain the full selector name.  */
6639  if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6640    /* A unary selector.  */
6641    selname = selnamelist;
6642  else if (TREE_CODE (selnamelist) == TREE_LIST)
6643    selname = build_keyword_selector (selnamelist);
6644  else
6645    abort ();
6646
6647  /* If we are required to check @selector() expressions as they
6648     are found, check that the selector has been declared.  */
6649  if (warn_undeclared_selector)
6650    {
6651      /* Look the selector up in the list of all known class and
6652         instance methods (up to this line) to check that the selector
6653         exists.  */
6654      hash hsh;
6655
6656      /* First try with instance methods.  */
6657      hsh = hash_lookup (nst_method_hash_list, selname);
6658
6659      /* If not found, try with class methods.  */
6660      if (!hsh)
6661	{
6662	  hsh = hash_lookup (cls_method_hash_list, selname);
6663	}
6664
6665      /* If still not found, print out a warning.  */
6666      if (!hsh)
6667	{
6668	  warning (0, "undeclared selector %qs", IDENTIFIER_POINTER (selname));
6669	}
6670    }
6671
6672
6673  if (flag_typed_selectors)
6674    return build_typed_selector_reference (selname, 0);
6675  else
6676    return build_selector_reference (selname);
6677}
6678
6679tree
6680objc_build_encode_expr (tree type)
6681{
6682  tree result;
6683  const char *string;
6684
6685  encode_type (type, obstack_object_size (&util_obstack),
6686	       OBJC_ENCODE_INLINE_DEFS);
6687  obstack_1grow (&util_obstack, 0);    /* null terminate string */
6688  string = obstack_finish (&util_obstack);
6689
6690  /* Synthesize a string that represents the encoded struct/union.  */
6691  result = my_build_string (strlen (string) + 1, string);
6692  obstack_free (&util_obstack, util_firstobj);
6693  return result;
6694}
6695
6696static tree
6697build_ivar_reference (tree id)
6698{
6699  if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6700    {
6701      /* Historically, a class method that produced objects (factory
6702	 method) would assign `self' to the instance that it
6703	 allocated.  This would effectively turn the class method into
6704	 an instance method.  Following this assignment, the instance
6705	 variables could be accessed.  That practice, while safe,
6706	 violates the simple rule that a class method should not refer
6707	 to an instance variable.  It's better to catch the cases
6708	 where this is done unknowingly than to support the above
6709	 paradigm.  */
6710      warning (0, "instance variable %qs accessed in class method",
6711	       IDENTIFIER_POINTER (id));
6712      self_decl = convert (objc_instance_type, self_decl); /* cast */
6713    }
6714
6715  return objc_build_component_ref (build_indirect_ref (self_decl, "->"), id);
6716}
6717
6718/* Compute a hash value for a given method SEL_NAME.  */
6719
6720static size_t
6721hash_func (tree sel_name)
6722{
6723  const unsigned char *s
6724    = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6725  size_t h = 0;
6726
6727  while (*s)
6728    h = h * 67 + *s++ - 113;
6729  return h;
6730}
6731
6732static void
6733hash_init (void)
6734{
6735  nst_method_hash_list
6736    = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6737  cls_method_hash_list
6738    = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6739
6740  /* Initialize the hash table used to hold the constant string objects.  */
6741  string_htab = htab_create_ggc (31, string_hash,
6742				   string_eq, NULL);
6743
6744  /* Initialize the hash table used to hold EH-volatilized types.  */
6745  volatilized_htab = htab_create_ggc (31, volatilized_hash,
6746				      volatilized_eq, NULL);
6747}
6748
6749/* WARNING!!!!  hash_enter is called with a method, and will peek
6750   inside to find its selector!  But hash_lookup is given a selector
6751   directly, and looks for the selector that's inside the found
6752   entry's key (method) for comparison.  */
6753
6754static void
6755hash_enter (hash *hashlist, tree method)
6756{
6757  hash obj;
6758  int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6759
6760  obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6761  obj->list = 0;
6762  obj->next = hashlist[slot];
6763  obj->key = method;
6764
6765  hashlist[slot] = obj;		/* append to front */
6766}
6767
6768static hash
6769hash_lookup (hash *hashlist, tree sel_name)
6770{
6771  hash target;
6772
6773  target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6774
6775  while (target)
6776    {
6777      if (sel_name == METHOD_SEL_NAME (target->key))
6778	return target;
6779
6780      target = target->next;
6781    }
6782  return 0;
6783}
6784
6785static void
6786hash_add_attr (hash entry, tree value)
6787{
6788  attr obj;
6789
6790  obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6791  obj->next = entry->list;
6792  obj->value = value;
6793
6794  entry->list = obj;		/* append to front */
6795}
6796
6797static tree
6798lookup_method (tree mchain, tree method)
6799{
6800  tree key;
6801
6802  if (TREE_CODE (method) == IDENTIFIER_NODE)
6803    key = method;
6804  else
6805    key = METHOD_SEL_NAME (method);
6806
6807  while (mchain)
6808    {
6809      if (METHOD_SEL_NAME (mchain) == key)
6810	return mchain;
6811
6812      mchain = TREE_CHAIN (mchain);
6813    }
6814  return NULL_TREE;
6815}
6816
6817/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
6818   in INTERFACE, along with any categories and protocols attached thereto.
6819   If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
6820   recursively examine the INTERFACE's superclass.  If OBJC_LOOKUP_CLASS is
6821   set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
6822   be found in INTERFACE or any of its superclasses, look for an _instance_
6823   method of the same name in the root class as a last resort.
6824
6825   If a suitable method cannot be found, return NULL_TREE.  */
6826
6827static tree
6828lookup_method_static (tree interface, tree ident, int flags)
6829{
6830  tree meth = NULL_TREE, root_inter = NULL_TREE;
6831  tree inter = interface;
6832  int is_class = (flags & OBJC_LOOKUP_CLASS);
6833  int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
6834
6835  while (inter)
6836    {
6837      tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6838      tree category = inter;
6839
6840      /* First, look up the method in the class itself.  */
6841      if ((meth = lookup_method (chain, ident)))
6842	return meth;
6843
6844      /* Failing that, look for the method in each category of the class.  */
6845      while ((category = CLASS_CATEGORY_LIST (category)))
6846	{
6847	  chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6848
6849	  /* Check directly in each category.  */
6850	  if ((meth = lookup_method (chain, ident)))
6851	    return meth;
6852
6853	  /* Failing that, check in each category's protocols.  */
6854	  if (CLASS_PROTOCOL_LIST (category))
6855	    {
6856	      if ((meth = (lookup_method_in_protocol_list
6857			   (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6858		return meth;
6859	    }
6860	}
6861
6862      /* If not found in categories, check in protocols of the main class.  */
6863      if (CLASS_PROTOCOL_LIST (inter))
6864	{
6865	  if ((meth = (lookup_method_in_protocol_list
6866		       (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6867	    return meth;
6868	}
6869
6870      /* If we were instructed not to look in superclasses, don't.  */
6871      if (no_superclasses)
6872	return NULL_TREE;
6873
6874      /* Failing that, climb up the inheritance hierarchy.  */
6875      root_inter = inter;
6876      inter = lookup_interface (CLASS_SUPER_NAME (inter));
6877    }
6878  while (inter);
6879
6880  /* If no class (factory) method was found, check if an _instance_
6881     method of the same name exists in the root class.  This is what
6882     the Objective-C runtime will do.  If an instance method was not
6883     found, return 0.  */
6884  return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6885}
6886
6887/* Add the method to the hash list if it doesn't contain an identical
6888   method already. */
6889
6890static void
6891add_method_to_hash_list (hash *hash_list, tree method)
6892{
6893  hash hsh;
6894
6895  if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6896    {
6897      /* Install on a global chain.  */
6898      hash_enter (hash_list, method);
6899    }
6900  else
6901    {
6902      /* Check types against those; if different, add to a list.  */
6903      attr loop;
6904      int already_there = comp_proto_with_proto (method, hsh->key, 1);
6905      for (loop = hsh->list; !already_there && loop; loop = loop->next)
6906	already_there |= comp_proto_with_proto (method, loop->value, 1);
6907      if (!already_there)
6908	hash_add_attr (hsh, method);
6909    }
6910}
6911
6912static tree
6913objc_add_method (tree class, tree method, int is_class)
6914{
6915  tree mth;
6916
6917  if (!(mth = lookup_method (is_class
6918			     ? CLASS_CLS_METHODS (class)
6919			     : CLASS_NST_METHODS (class), method)))
6920    {
6921      /* put method on list in reverse order */
6922      if (is_class)
6923	{
6924	  TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6925	  CLASS_CLS_METHODS (class) = method;
6926	}
6927      else
6928	{
6929	  TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6930	  CLASS_NST_METHODS (class) = method;
6931	}
6932    }
6933  else
6934    {
6935      /* When processing an @interface for a class or category, give hard
6936	 errors on methods with identical selectors but differing argument
6937	 and/or return types. We do not do this for @implementations, because
6938	 C/C++ will do it for us (i.e., there will be duplicate function
6939	 definition errors).  */
6940      if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6941	   || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6942	  && !comp_proto_with_proto (method, mth, 1))
6943	error ("duplicate declaration of method %<%c%s%>",
6944		is_class ? '+' : '-',
6945		IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6946    }
6947
6948  if (is_class)
6949    add_method_to_hash_list (cls_method_hash_list, method);
6950  else
6951    {
6952      add_method_to_hash_list (nst_method_hash_list, method);
6953
6954      /* Instance methods in root classes (and categories thereof)
6955	 may act as class methods as a last resort.  We also add
6956	 instance methods listed in @protocol declarations to
6957	 the class hash table, on the assumption that @protocols
6958	 may be adopted by root classes or categories.  */
6959      if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6960	  || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6961	class = lookup_interface (CLASS_NAME (class));
6962
6963      if (TREE_CODE (class) == PROTOCOL_INTERFACE_TYPE
6964	  || !CLASS_SUPER_NAME (class))
6965	add_method_to_hash_list (cls_method_hash_list, method);
6966    }
6967
6968  return method;
6969}
6970
6971static tree
6972add_class (tree class_name, tree name)
6973{
6974  struct interface_tuple **slot;
6975
6976  /* Put interfaces on list in reverse order.  */
6977  TREE_CHAIN (class_name) = interface_chain;
6978  interface_chain = class_name;
6979
6980  if (interface_htab == NULL)
6981    interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
6982  slot = (struct interface_tuple **)
6983    htab_find_slot_with_hash (interface_htab, name,
6984			      IDENTIFIER_HASH_VALUE (name),
6985			      INSERT);
6986  if (!*slot)
6987    {
6988      *slot = (struct interface_tuple *) ggc_alloc_cleared (sizeof (struct interface_tuple));
6989      (*slot)->id = name;
6990    }
6991  (*slot)->class_name = class_name;
6992
6993  return interface_chain;
6994}
6995
6996static void
6997add_category (tree class, tree category)
6998{
6999  /* Put categories on list in reverse order.  */
7000  tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
7001
7002  if (cat)
7003    {
7004      warning (0, "duplicate interface declaration for category %<%s(%s)%>",
7005	       IDENTIFIER_POINTER (CLASS_NAME (class)),
7006	       IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
7007    }
7008  else
7009    {
7010      CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
7011      CLASS_CATEGORY_LIST (class) = category;
7012    }
7013}
7014
7015/* Called after parsing each instance variable declaration. Necessary to
7016   preserve typedefs and implement public/private...
7017
7018   PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
7019
7020static tree
7021add_instance_variable (tree class, int public, tree field_decl)
7022{
7023  tree field_type = TREE_TYPE (field_decl);
7024  const char *ivar_name = DECL_NAME (field_decl)
7025			  ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
7026			  : "<unnamed>";
7027
7028#ifdef OBJCPLUS
7029  if (TREE_CODE (field_type) == REFERENCE_TYPE)
7030    {
7031      error ("illegal reference type specified for instance variable %qs",
7032	     ivar_name);
7033      /* Return class as is without adding this ivar.  */
7034      return class;
7035    }
7036#endif
7037
7038  if (field_type == error_mark_node || !TYPE_SIZE (field_type)
7039      || TYPE_SIZE (field_type) == error_mark_node)
7040      /* 'type[0]' is allowed, but 'type[]' is not! */
7041    {
7042      error ("instance variable %qs has unknown size", ivar_name);
7043      /* Return class as is without adding this ivar.  */
7044      return class;
7045    }
7046
7047#ifdef OBJCPLUS
7048  /* Check if the ivar being added has a non-POD C++ type.   If so, we will
7049     need to either (1) warn the user about it or (2) generate suitable
7050     constructor/destructor call from '- .cxx_construct' or '- .cxx_destruct'
7051     methods (if '-fobjc-call-cxx-cdtors' was specified).  */
7052  if (IS_AGGR_TYPE (field_type)
7053      && (TYPE_NEEDS_CONSTRUCTING (field_type)
7054	  || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)
7055	  || TYPE_POLYMORPHIC_P (field_type)))
7056    {
7057      const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
7058
7059      if (flag_objc_call_cxx_cdtors)
7060        {
7061	  /* Since the ObjC runtime will be calling the constructors and
7062	     destructors for us, the only thing we can't handle is the lack
7063	     of a default constructor.  */
7064	  if (TYPE_NEEDS_CONSTRUCTING (field_type)
7065	      && !TYPE_HAS_DEFAULT_CONSTRUCTOR (field_type))
7066	    {
7067	      warning (0, "type %qs has no default constructor to call",
7068		       type_name);
7069
7070	      /* If we cannot call a constructor, we should also avoid
7071		 calling the destructor, for symmetry.  */
7072	      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7073		warning (0, "destructor for %qs shall not be run either",
7074			 type_name);
7075	    }
7076        }
7077      else
7078	{
7079	  static bool warn_cxx_ivars = false;
7080
7081	  if (TYPE_POLYMORPHIC_P (field_type))
7082	    {
7083	      /* Vtable pointers are Real Bad(tm), since Obj-C cannot
7084		 initialize them.  */
7085	      error ("type %qs has virtual member functions", type_name);
7086	      error ("illegal aggregate type %qs specified "
7087		     "for instance variable %qs",
7088		     type_name, ivar_name);
7089	      /* Return class as is without adding this ivar.  */
7090	      return class;
7091	    }
7092
7093	  /* User-defined constructors and destructors are not known to Obj-C
7094	     and hence will not be called.  This may or may not be a problem. */
7095	  if (TYPE_NEEDS_CONSTRUCTING (field_type))
7096	    warning (0, "type %qs has a user-defined constructor", type_name);
7097	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
7098	    warning (0, "type %qs has a user-defined destructor", type_name);
7099
7100	  if (!warn_cxx_ivars)
7101	    {
7102	      warning (0, "C++ constructors and destructors will not "
7103		       "be invoked for Objective-C fields");
7104	      warn_cxx_ivars = true;
7105	    }
7106	}
7107    }
7108#endif
7109
7110  /* Overload the public attribute, it is not used for FIELD_DECLs.  */
7111  switch (public)
7112    {
7113    case 0:
7114      TREE_PUBLIC (field_decl) = 0;
7115      TREE_PRIVATE (field_decl) = 0;
7116      TREE_PROTECTED (field_decl) = 1;
7117      break;
7118
7119    case 1:
7120      TREE_PUBLIC (field_decl) = 1;
7121      TREE_PRIVATE (field_decl) = 0;
7122      TREE_PROTECTED (field_decl) = 0;
7123      break;
7124
7125    case 2:
7126      TREE_PUBLIC (field_decl) = 0;
7127      TREE_PRIVATE (field_decl) = 1;
7128      TREE_PROTECTED (field_decl) = 0;
7129      break;
7130
7131    }
7132
7133  CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), field_decl);
7134
7135  return class;
7136}
7137
7138static tree
7139is_ivar (tree decl_chain, tree ident)
7140{
7141  for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
7142    if (DECL_NAME (decl_chain) == ident)
7143      return decl_chain;
7144  return NULL_TREE;
7145}
7146
7147/* True if the ivar is private and we are not in its implementation.  */
7148
7149static int
7150is_private (tree decl)
7151{
7152  return (TREE_PRIVATE (decl)
7153	  && ! is_ivar (CLASS_IVARS (implementation_template),
7154			DECL_NAME (decl)));
7155}
7156
7157/* We have an instance variable reference;, check to see if it is public.  */
7158
7159int
7160objc_is_public (tree expr, tree identifier)
7161{
7162  tree basetype, decl;
7163
7164#ifdef OBJCPLUS
7165  if (processing_template_decl)
7166    return 1;
7167#endif
7168
7169  if (TREE_TYPE (expr) == error_mark_node)
7170    return 1;
7171
7172  basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
7173
7174  if (basetype && TREE_CODE (basetype) == RECORD_TYPE)
7175    {
7176      if (TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
7177	{
7178	  tree class = lookup_interface (OBJC_TYPE_NAME (basetype));
7179
7180	  if (!class)
7181	    {
7182	      error ("cannot find interface declaration for %qs",
7183		     IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
7184	      return 0;
7185	    }
7186
7187	  if ((decl = is_ivar (get_class_ivars (class, true), identifier)))
7188	    {
7189	      if (TREE_PUBLIC (decl))
7190		return 1;
7191
7192	      /* Important difference between the Stepstone translator:
7193		 all instance variables should be public within the context
7194		 of the implementation.  */
7195	      if (objc_implementation_context
7196		 && ((TREE_CODE (objc_implementation_context)
7197		      == CLASS_IMPLEMENTATION_TYPE)
7198		     || (TREE_CODE (objc_implementation_context)
7199			 == CATEGORY_IMPLEMENTATION_TYPE)))
7200		{
7201		  tree curtype = TYPE_MAIN_VARIANT
7202				 (CLASS_STATIC_TEMPLATE
7203				  (implementation_template));
7204
7205		  if (basetype == curtype
7206		      || DERIVED_FROM_P (basetype, curtype))
7207		    {
7208		      int private = is_private (decl);
7209
7210		      if (private)
7211			error ("instance variable %qs is declared private",
7212			       IDENTIFIER_POINTER (DECL_NAME (decl)));
7213
7214		      return !private;
7215		    }
7216		}
7217
7218	      /* The 2.95.2 compiler sometimes allowed C functions to access
7219		 non-@public ivars.  We will let this slide for now...  */
7220	      if (!objc_method_context)
7221	      {
7222		warning (0, "instance variable %qs is %s; "
7223			 "this will be a hard error in the future",
7224			 IDENTIFIER_POINTER (identifier),
7225			 TREE_PRIVATE (decl) ? "@private" : "@protected");
7226		return 1;
7227	      }
7228
7229	      error ("instance variable %qs is declared %s",
7230		     IDENTIFIER_POINTER (identifier),
7231		     TREE_PRIVATE (decl) ? "private" : "protected");
7232	      return 0;
7233	    }
7234	}
7235    }
7236
7237  return 1;
7238}
7239
7240/* Make sure all entries in CHAIN are also in LIST.  */
7241
7242static int
7243check_methods (tree chain, tree list, int mtype)
7244{
7245  int first = 1;
7246
7247  while (chain)
7248    {
7249      if (!lookup_method (list, chain))
7250	{
7251	  if (first)
7252	    {
7253	      if (TREE_CODE (objc_implementation_context)
7254		  == CLASS_IMPLEMENTATION_TYPE)
7255		warning (0, "incomplete implementation of class %qs",
7256			 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
7257	      else if (TREE_CODE (objc_implementation_context)
7258		       == CATEGORY_IMPLEMENTATION_TYPE)
7259		warning (0, "incomplete implementation of category %qs",
7260			 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7261	      first = 0;
7262	    }
7263
7264	  warning (0, "method definition for %<%c%s%> not found",
7265		   mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
7266	}
7267
7268      chain = TREE_CHAIN (chain);
7269    }
7270
7271    return first;
7272}
7273
7274/* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
7275
7276static int
7277conforms_to_protocol (tree class, tree protocol)
7278{
7279   if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
7280     {
7281       tree p = CLASS_PROTOCOL_LIST (class);
7282       while (p && TREE_VALUE (p) != protocol)
7283	 p = TREE_CHAIN (p);
7284
7285       if (!p)
7286	 {
7287	   tree super = (CLASS_SUPER_NAME (class)
7288			 ? lookup_interface (CLASS_SUPER_NAME (class))
7289			 : NULL_TREE);
7290	   int tmp = super ? conforms_to_protocol (super, protocol) : 0;
7291	   if (!tmp)
7292	     return 0;
7293	 }
7294     }
7295
7296   return 1;
7297}
7298
7299/* Make sure all methods in CHAIN are accessible as MTYPE methods in
7300   CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
7301
7302static int
7303check_methods_accessible (tree chain, tree context, int mtype)
7304{
7305  int first = 1;
7306  tree list;
7307  tree base_context = context;
7308
7309  while (chain)
7310    {
7311      context = base_context;
7312      while (context)
7313	{
7314	  if (mtype == '+')
7315	    list = CLASS_CLS_METHODS (context);
7316	  else
7317	    list = CLASS_NST_METHODS (context);
7318
7319	  if (lookup_method (list, chain))
7320	      break;
7321
7322	  else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
7323		   || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
7324	    context = (CLASS_SUPER_NAME (context)
7325		       ? lookup_interface (CLASS_SUPER_NAME (context))
7326		       : NULL_TREE);
7327
7328	  else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
7329		   || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
7330	    context = (CLASS_NAME (context)
7331		       ? lookup_interface (CLASS_NAME (context))
7332		       : NULL_TREE);
7333	  else
7334	    abort ();
7335	}
7336
7337      if (context == NULL_TREE)
7338	{
7339	  if (first)
7340	    {
7341	      if (TREE_CODE (objc_implementation_context)
7342		  == CLASS_IMPLEMENTATION_TYPE)
7343		warning (0, "incomplete implementation of class %qs",
7344			 IDENTIFIER_POINTER
7345			   (CLASS_NAME (objc_implementation_context)));
7346	      else if (TREE_CODE (objc_implementation_context)
7347		       == CATEGORY_IMPLEMENTATION_TYPE)
7348		warning (0, "incomplete implementation of category %qs",
7349			 IDENTIFIER_POINTER
7350			   (CLASS_SUPER_NAME (objc_implementation_context)));
7351	      first = 0;
7352	    }
7353	  warning (0, "method definition for %<%c%s%> not found",
7354		   mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
7355	}
7356
7357      chain = TREE_CHAIN (chain); /* next method...  */
7358    }
7359  return first;
7360}
7361
7362/* Check whether the current interface (accessible via
7363   'objc_implementation_context') actually implements protocol P, along
7364   with any protocols that P inherits.  */
7365
7366static void
7367check_protocol (tree p, const char *type, const char *name)
7368{
7369  if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
7370    {
7371      int f1, f2;
7372
7373      /* Ensure that all protocols have bodies!  */
7374      if (warn_protocol)
7375	{
7376	  f1 = check_methods (PROTOCOL_CLS_METHODS (p),
7377			      CLASS_CLS_METHODS (objc_implementation_context),
7378			      '+');
7379	  f2 = check_methods (PROTOCOL_NST_METHODS (p),
7380			      CLASS_NST_METHODS (objc_implementation_context),
7381			      '-');
7382	}
7383      else
7384	{
7385	  f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
7386					 objc_implementation_context,
7387					 '+');
7388	  f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
7389					 objc_implementation_context,
7390					 '-');
7391	}
7392
7393      if (!f1 || !f2)
7394	warning (0, "%s %qs does not fully implement the %qs protocol",
7395		 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
7396    }
7397
7398  /* Check protocols recursively.  */
7399  if (PROTOCOL_LIST (p))
7400    {
7401      tree subs = PROTOCOL_LIST (p);
7402      tree super_class =
7403	lookup_interface (CLASS_SUPER_NAME (implementation_template));
7404
7405      while (subs)
7406	{
7407	  tree sub = TREE_VALUE (subs);
7408
7409	  /* If the superclass does not conform to the protocols
7410	     inherited by P, then we must!  */
7411	  if (!super_class || !conforms_to_protocol (super_class, sub))
7412	    check_protocol (sub, type, name);
7413	  subs = TREE_CHAIN (subs);
7414	}
7415    }
7416}
7417
7418/* Check whether the current interface (accessible via
7419   'objc_implementation_context') actually implements the protocols listed
7420   in PROTO_LIST.  */
7421
7422static void
7423check_protocols (tree proto_list, const char *type, const char *name)
7424{
7425  for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
7426    {
7427      tree p = TREE_VALUE (proto_list);
7428
7429      check_protocol (p, type, name);
7430    }
7431}
7432
7433/* Make sure that the class CLASS_NAME is defined
7434   CODE says which kind of thing CLASS_NAME ought to be.
7435   It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
7436   CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
7437
7438static tree
7439start_class (enum tree_code code, tree class_name, tree super_name,
7440	     tree protocol_list)
7441{
7442  tree class, decl;
7443
7444#ifdef OBJCPLUS
7445  if (current_namespace != global_namespace) {
7446    error ("Objective-C declarations may only appear in global scope");
7447  }
7448#endif /* OBJCPLUS */
7449
7450  if (objc_implementation_context)
7451    {
7452      warning (0, "%<@end%> missing in implementation context");
7453      finish_class (objc_implementation_context);
7454      objc_ivar_chain = NULL_TREE;
7455      objc_implementation_context = NULL_TREE;
7456    }
7457
7458  class = make_node (code);
7459  TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
7460
7461  /* Check for existence of the super class, if one was specified.  Note
7462     that we must have seen an @interface, not just a @class.  If we
7463     are looking at a @compatibility_alias, traverse it first.  */
7464  if ((code == CLASS_INTERFACE_TYPE || code == CLASS_IMPLEMENTATION_TYPE)
7465      && super_name)
7466    {
7467      tree super = objc_is_class_name (super_name);
7468
7469      if (!super || !lookup_interface (super))
7470	{
7471	  error ("cannot find interface declaration for %qs, superclass of %qs",
7472		 IDENTIFIER_POINTER (super ? super : super_name),
7473		 IDENTIFIER_POINTER (class_name));
7474	  super_name = NULL_TREE;
7475	}
7476      else
7477	super_name = super;
7478    }
7479
7480  CLASS_NAME (class) = class_name;
7481  CLASS_SUPER_NAME (class) = super_name;
7482  CLASS_CLS_METHODS (class) = NULL_TREE;
7483
7484  if (! objc_is_class_name (class_name)
7485      && (decl = lookup_name (class_name)))
7486    {
7487      error ("%qs redeclared as different kind of symbol",
7488	     IDENTIFIER_POINTER (class_name));
7489      error ("previous declaration of %q+D",
7490	     decl);
7491    }
7492
7493  if (code == CLASS_IMPLEMENTATION_TYPE)
7494    {
7495      {
7496        tree chain;
7497
7498        for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
7499           if (TREE_VALUE (chain) == class_name)
7500	     {
7501	       error ("reimplementation of class %qs",
7502		      IDENTIFIER_POINTER (class_name));
7503	       return error_mark_node;
7504	     }
7505        implemented_classes = tree_cons (NULL_TREE, class_name,
7506					 implemented_classes);
7507      }
7508
7509      /* Reset for multiple classes per file.  */
7510      method_slot = 0;
7511
7512      objc_implementation_context = class;
7513
7514      /* Lookup the interface for this implementation.  */
7515
7516      if (!(implementation_template = lookup_interface (class_name)))
7517        {
7518	  warning (0, "cannot find interface declaration for %qs",
7519		   IDENTIFIER_POINTER (class_name));
7520	  add_class (implementation_template = objc_implementation_context,
7521		     class_name);
7522        }
7523
7524      /* If a super class has been specified in the implementation,
7525	 insure it conforms to the one specified in the interface.  */
7526
7527      if (super_name
7528	  && (super_name != CLASS_SUPER_NAME (implementation_template)))
7529        {
7530	  tree previous_name = CLASS_SUPER_NAME (implementation_template);
7531          const char *const name =
7532	    previous_name ? IDENTIFIER_POINTER (previous_name) : "";
7533	  error ("conflicting super class name %qs",
7534		 IDENTIFIER_POINTER (super_name));
7535	  error ("previous declaration of %qs", name);
7536        }
7537
7538      else if (! super_name)
7539	{
7540	  CLASS_SUPER_NAME (objc_implementation_context)
7541	    = CLASS_SUPER_NAME (implementation_template);
7542	}
7543    }
7544
7545  else if (code == CLASS_INTERFACE_TYPE)
7546    {
7547      if (lookup_interface (class_name))
7548#ifdef OBJCPLUS
7549	error ("duplicate interface declaration for class %qs",
7550#else
7551	warning (0, "duplicate interface declaration for class %qs",
7552#endif
7553        IDENTIFIER_POINTER (class_name));
7554      else
7555        add_class (class, class_name);
7556
7557      if (protocol_list)
7558	CLASS_PROTOCOL_LIST (class)
7559	  = lookup_and_install_protocols (protocol_list);
7560    }
7561
7562  else if (code == CATEGORY_INTERFACE_TYPE)
7563    {
7564      tree class_category_is_assoc_with;
7565
7566      /* For a category, class_name is really the name of the class that
7567	 the following set of methods will be associated with. We must
7568	 find the interface so that can derive the objects template.  */
7569
7570      if (!(class_category_is_assoc_with = lookup_interface (class_name)))
7571	{
7572	  error ("cannot find interface declaration for %qs",
7573		 IDENTIFIER_POINTER (class_name));
7574	  exit (FATAL_EXIT_CODE);
7575	}
7576      else
7577        add_category (class_category_is_assoc_with, class);
7578
7579      if (protocol_list)
7580	CLASS_PROTOCOL_LIST (class)
7581	  = lookup_and_install_protocols (protocol_list);
7582    }
7583
7584  else if (code == CATEGORY_IMPLEMENTATION_TYPE)
7585    {
7586      /* Reset for multiple classes per file.  */
7587      method_slot = 0;
7588
7589      objc_implementation_context = class;
7590
7591      /* For a category, class_name is really the name of the class that
7592	 the following set of methods will be associated with.  We must
7593	 find the interface so that can derive the objects template.  */
7594
7595      if (!(implementation_template = lookup_interface (class_name)))
7596        {
7597	  error ("cannot find interface declaration for %qs",
7598		 IDENTIFIER_POINTER (class_name));
7599	  exit (FATAL_EXIT_CODE);
7600        }
7601    }
7602  return class;
7603}
7604
7605static tree
7606continue_class (tree class)
7607{
7608  if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
7609      || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
7610    {
7611      struct imp_entry *imp_entry;
7612
7613      /* Check consistency of the instance variables.  */
7614
7615      if (CLASS_RAW_IVARS (class))
7616	check_ivars (implementation_template, class);
7617
7618      /* code generation */
7619
7620#ifdef OBJCPLUS
7621      push_lang_context (lang_name_c);
7622#endif
7623
7624      build_private_template (implementation_template);
7625      uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
7626      objc_instance_type = build_pointer_type (uprivate_record);
7627
7628      imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
7629
7630      imp_entry->next = imp_list;
7631      imp_entry->imp_context = class;
7632      imp_entry->imp_template = implementation_template;
7633
7634      synth_forward_declarations ();
7635      imp_entry->class_decl = UOBJC_CLASS_decl;
7636      imp_entry->meta_decl = UOBJC_METACLASS_decl;
7637      imp_entry->has_cxx_cdtors = 0;
7638
7639      /* Append to front and increment count.  */
7640      imp_list = imp_entry;
7641      if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
7642	imp_count++;
7643      else
7644	cat_count++;
7645
7646#ifdef OBJCPLUS
7647      pop_lang_context ();
7648#endif /* OBJCPLUS */
7649
7650      return get_class_ivars (implementation_template, true);
7651    }
7652
7653  else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
7654    {
7655#ifdef OBJCPLUS
7656      push_lang_context (lang_name_c);
7657#endif /* OBJCPLUS */
7658
7659      build_private_template (class);
7660
7661#ifdef OBJCPLUS
7662      pop_lang_context ();
7663#endif /* OBJCPLUS */
7664
7665      return NULL_TREE;
7666    }
7667
7668  else
7669    return error_mark_node;
7670}
7671
7672/* This is called once we see the "@end" in an interface/implementation.  */
7673
7674static void
7675finish_class (tree class)
7676{
7677  if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
7678    {
7679      /* All code generation is done in finish_objc.  */
7680
7681      if (implementation_template != objc_implementation_context)
7682	{
7683	  /* Ensure that all method listed in the interface contain bodies.  */
7684	  check_methods (CLASS_CLS_METHODS (implementation_template),
7685			 CLASS_CLS_METHODS (objc_implementation_context), '+');
7686	  check_methods (CLASS_NST_METHODS (implementation_template),
7687			 CLASS_NST_METHODS (objc_implementation_context), '-');
7688
7689	  if (CLASS_PROTOCOL_LIST (implementation_template))
7690	    check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
7691			     "class",
7692			     IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
7693	}
7694    }
7695
7696  else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
7697    {
7698      tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
7699
7700      if (category)
7701	{
7702	  /* Ensure all method listed in the interface contain bodies.  */
7703	  check_methods (CLASS_CLS_METHODS (category),
7704			 CLASS_CLS_METHODS (objc_implementation_context), '+');
7705	  check_methods (CLASS_NST_METHODS (category),
7706			 CLASS_NST_METHODS (objc_implementation_context), '-');
7707
7708	  if (CLASS_PROTOCOL_LIST (category))
7709	    check_protocols (CLASS_PROTOCOL_LIST (category),
7710			     "category",
7711			     IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7712	}
7713    }
7714}
7715
7716static tree
7717add_protocol (tree protocol)
7718{
7719  /* Put protocol on list in reverse order.  */
7720  TREE_CHAIN (protocol) = protocol_chain;
7721  protocol_chain = protocol;
7722  return protocol_chain;
7723}
7724
7725static tree
7726lookup_protocol (tree ident)
7727{
7728  tree chain;
7729
7730  for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7731    if (ident == PROTOCOL_NAME (chain))
7732      return chain;
7733
7734  return NULL_TREE;
7735}
7736
7737/* This function forward declares the protocols named by NAMES.  If
7738   they are already declared or defined, the function has no effect.  */
7739
7740void
7741objc_declare_protocols (tree names)
7742{
7743  tree list;
7744
7745#ifdef OBJCPLUS
7746  if (current_namespace != global_namespace) {
7747    error ("Objective-C declarations may only appear in global scope");
7748  }
7749#endif /* OBJCPLUS */
7750
7751  for (list = names; list; list = TREE_CHAIN (list))
7752    {
7753      tree name = TREE_VALUE (list);
7754
7755      if (lookup_protocol (name) == NULL_TREE)
7756	{
7757	  tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7758
7759	  TYPE_LANG_SLOT_1 (protocol)
7760	    = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7761	  PROTOCOL_NAME (protocol) = name;
7762	  PROTOCOL_LIST (protocol) = NULL_TREE;
7763	  add_protocol (protocol);
7764	  PROTOCOL_DEFINED (protocol) = 0;
7765	  PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7766	}
7767    }
7768}
7769
7770static tree
7771start_protocol (enum tree_code code, tree name, tree list)
7772{
7773  tree protocol;
7774
7775#ifdef OBJCPLUS
7776  if (current_namespace != global_namespace) {
7777    error ("Objective-C declarations may only appear in global scope");
7778  }
7779#endif /* OBJCPLUS */
7780
7781  protocol = lookup_protocol (name);
7782
7783  if (!protocol)
7784    {
7785      protocol = make_node (code);
7786      TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
7787
7788      PROTOCOL_NAME (protocol) = name;
7789      PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7790      add_protocol (protocol);
7791      PROTOCOL_DEFINED (protocol) = 1;
7792      PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7793
7794      check_protocol_recursively (protocol, list);
7795    }
7796  else if (! PROTOCOL_DEFINED (protocol))
7797    {
7798      PROTOCOL_DEFINED (protocol) = 1;
7799      PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7800
7801      check_protocol_recursively (protocol, list);
7802    }
7803  else
7804    {
7805      warning (0, "duplicate declaration for protocol %qs",
7806	       IDENTIFIER_POINTER (name));
7807    }
7808  return protocol;
7809}
7810
7811
7812/* "Encode" a data type into a string, which grows in util_obstack.
7813   ??? What is the FORMAT?  Someone please document this!  */
7814
7815static void
7816encode_type_qualifiers (tree declspecs)
7817{
7818  tree spec;
7819
7820  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7821    {
7822      if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7823	obstack_1grow (&util_obstack, 'n');
7824      else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7825	obstack_1grow (&util_obstack, 'N');
7826      else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7827	obstack_1grow (&util_obstack, 'o');
7828      else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7829	obstack_1grow (&util_obstack, 'O');
7830      else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7831        obstack_1grow (&util_obstack, 'R');
7832      else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7833	obstack_1grow (&util_obstack, 'V');
7834    }
7835}
7836
7837/* Encode a pointer type.  */
7838
7839static void
7840encode_pointer (tree type, int curtype, int format)
7841{
7842  tree pointer_to = TREE_TYPE (type);
7843
7844  if (TREE_CODE (pointer_to) == RECORD_TYPE)
7845    {
7846      if (OBJC_TYPE_NAME (pointer_to)
7847	  && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7848	{
7849	  const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7850
7851	  if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7852	    {
7853	      obstack_1grow (&util_obstack, '@');
7854	      return;
7855	    }
7856	  else if (TYPE_HAS_OBJC_INFO (pointer_to)
7857		   && TYPE_OBJC_INTERFACE (pointer_to))
7858	    {
7859              if (generating_instance_variables)
7860	        {
7861	          obstack_1grow (&util_obstack, '@');
7862	          obstack_1grow (&util_obstack, '"');
7863	          obstack_grow (&util_obstack, name, strlen (name));
7864	          obstack_1grow (&util_obstack, '"');
7865	          return;
7866		}
7867              else
7868	        {
7869	          obstack_1grow (&util_obstack, '@');
7870	          return;
7871		}
7872	    }
7873	  else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7874	    {
7875	      obstack_1grow (&util_obstack, '#');
7876	      return;
7877	    }
7878	  else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7879	    {
7880	      obstack_1grow (&util_obstack, ':');
7881	      return;
7882	    }
7883	}
7884    }
7885  else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7886	   && TYPE_MODE (pointer_to) == QImode)
7887    {
7888      tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7889	          ? OBJC_TYPE_NAME (pointer_to)
7890	          : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7891
7892      if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7893	{
7894	  /* It appears that "r*" means "const char *" rather than
7895	     "char *const".  */
7896	  if (TYPE_READONLY (pointer_to))
7897	    obstack_1grow (&util_obstack, 'r');
7898
7899	  obstack_1grow (&util_obstack, '*');
7900	  return;
7901	}
7902    }
7903
7904  /* We have a type that does not get special treatment.  */
7905
7906  /* NeXT extension */
7907  obstack_1grow (&util_obstack, '^');
7908  encode_type (pointer_to, curtype, format);
7909}
7910
7911static void
7912encode_array (tree type, int curtype, int format)
7913{
7914  tree an_int_cst = TYPE_SIZE (type);
7915  tree array_of = TREE_TYPE (type);
7916  char buffer[40];
7917
7918  /* An incomplete array is treated like a pointer.  */
7919  if (an_int_cst == NULL)
7920    {
7921      encode_pointer (type, curtype, format);
7922      return;
7923    }
7924
7925  if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
7926   sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
7927  else
7928    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
7929	     TREE_INT_CST_LOW (an_int_cst)
7930	      / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
7931
7932  obstack_grow (&util_obstack, buffer, strlen (buffer));
7933  encode_type (array_of, curtype, format);
7934  obstack_1grow (&util_obstack, ']');
7935  return;
7936}
7937
7938static void
7939encode_aggregate_fields (tree type, int pointed_to, int curtype, int format)
7940{
7941  tree field = TYPE_FIELDS (type);
7942
7943  for (; field; field = TREE_CHAIN (field))
7944    {
7945#ifdef OBJCPLUS
7946      /* C++ static members, and things that are not field at all,
7947	 should not appear in the encoding.  */
7948      if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
7949	continue;
7950#endif
7951
7952      /* Recursively encode fields of embedded base classes.  */
7953      if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
7954	  && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
7955	{
7956	  encode_aggregate_fields (TREE_TYPE (field),
7957				   pointed_to, curtype, format);
7958	  continue;
7959	}
7960
7961      if (generating_instance_variables && !pointed_to)
7962	{
7963	  tree fname = DECL_NAME (field);
7964
7965	  obstack_1grow (&util_obstack, '"');
7966
7967	  if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7968	    obstack_grow (&util_obstack,
7969			  IDENTIFIER_POINTER (fname),
7970			  strlen (IDENTIFIER_POINTER (fname)));
7971
7972	  obstack_1grow (&util_obstack, '"');
7973        }
7974
7975      encode_field_decl (field, curtype, format);
7976    }
7977}
7978
7979static void
7980encode_aggregate_within (tree type, int curtype, int format, int left,
7981			 int right)
7982{
7983  tree name;
7984  /* NB: aggregates that are pointed to have slightly different encoding
7985     rules in that you never encode the names of instance variables.  */
7986  int ob_size = obstack_object_size (&util_obstack);
7987  char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
7988  char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
7989  int pointed_to = (c0 == '^' || (c1 == '^' && c0 == 'r'));
7990  int inline_contents
7991   = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7992      && (!pointed_to || ob_size - curtype == (c1 == 'r' ? 2 : 1)));
7993
7994  /* Traverse struct aliases; it is important to get the
7995     original struct and its tag name (if any).  */
7996  type = TYPE_MAIN_VARIANT (type);
7997  name = OBJC_TYPE_NAME (type);
7998  /* Open parenth/bracket.  */
7999  obstack_1grow (&util_obstack, left);
8000
8001  /* Encode the struct/union tag name, or '?' if a tag was
8002     not provided.  Typedef aliases do not qualify.  */
8003  if (name && TREE_CODE (name) == IDENTIFIER_NODE
8004#ifdef OBJCPLUS
8005      /* Did this struct have a tag?  */
8006      && !TYPE_WAS_ANONYMOUS (type)
8007#endif
8008      )
8009    obstack_grow (&util_obstack,
8010		  IDENTIFIER_POINTER (name),
8011		  strlen (IDENTIFIER_POINTER (name)));
8012  else
8013    obstack_1grow (&util_obstack, '?');
8014
8015  /* Encode the types (and possibly names) of the inner fields,
8016     if required.  */
8017  if (inline_contents)
8018    {
8019      obstack_1grow (&util_obstack, '=');
8020      encode_aggregate_fields (type, pointed_to, curtype, format);
8021    }
8022  /* Close parenth/bracket.  */
8023  obstack_1grow (&util_obstack, right);
8024}
8025
8026static void
8027encode_aggregate (tree type, int curtype, int format)
8028{
8029  enum tree_code code = TREE_CODE (type);
8030
8031  switch (code)
8032    {
8033    case RECORD_TYPE:
8034      {
8035	encode_aggregate_within (type, curtype, format, '{', '}');
8036	break;
8037      }
8038    case UNION_TYPE:
8039      {
8040	encode_aggregate_within (type, curtype, format, '(', ')');
8041	break;
8042      }
8043
8044    case ENUMERAL_TYPE:
8045      obstack_1grow (&util_obstack, 'i');
8046      break;
8047
8048    default:
8049      break;
8050    }
8051}
8052
8053/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
8054   field type.  */
8055
8056static void
8057encode_next_bitfield (int width)
8058{
8059  char buffer[40];
8060  sprintf (buffer, "b%d", width);
8061  obstack_grow (&util_obstack, buffer, strlen (buffer));
8062}
8063
8064/* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
8065static void
8066encode_type (tree type, int curtype, int format)
8067{
8068  enum tree_code code = TREE_CODE (type);
8069  char c;
8070
8071  if (TYPE_READONLY (type))
8072    obstack_1grow (&util_obstack, 'r');
8073
8074  if (code == INTEGER_TYPE)
8075    {
8076      switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
8077	{
8078	case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
8079	case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
8080	case 32:
8081	  if (type == long_unsigned_type_node
8082	      || type == long_integer_type_node)
8083	         c = TYPE_UNSIGNED (type) ? 'L' : 'l';
8084	  else
8085	         c = TYPE_UNSIGNED (type) ? 'I' : 'i';
8086	  break;
8087	case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
8088	default: abort ();
8089	}
8090      obstack_1grow (&util_obstack, c);
8091    }
8092
8093  else if (code == REAL_TYPE)
8094    {
8095      /* Floating point types.  */
8096      switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
8097	{
8098	case 32:  c = 'f'; break;
8099	case 64:
8100	case 96:
8101	case 128: c = 'd'; break;
8102	default: abort ();
8103	}
8104      obstack_1grow (&util_obstack, c);
8105    }
8106
8107  else if (code == VOID_TYPE)
8108    obstack_1grow (&util_obstack, 'v');
8109
8110  else if (code == BOOLEAN_TYPE)
8111    obstack_1grow (&util_obstack, 'B');
8112
8113  else if (code == ARRAY_TYPE)
8114    encode_array (type, curtype, format);
8115
8116  else if (code == POINTER_TYPE)
8117    encode_pointer (type, curtype, format);
8118
8119  else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
8120    encode_aggregate (type, curtype, format);
8121
8122  else if (code == FUNCTION_TYPE) /* '?' */
8123    obstack_1grow (&util_obstack, '?');
8124
8125  else if (code == COMPLEX_TYPE)
8126    {
8127      obstack_1grow (&util_obstack, 'j');
8128      encode_type (TREE_TYPE (type), curtype, format);
8129    }
8130}
8131
8132static void
8133encode_gnu_bitfield (int position, tree type, int size)
8134{
8135  enum tree_code code = TREE_CODE (type);
8136  char buffer[40];
8137  char charType = '?';
8138
8139  if (code == INTEGER_TYPE)
8140    {
8141      if (integer_zerop (TYPE_MIN_VALUE (type)))
8142	{
8143	  /* Unsigned integer types.  */
8144
8145	  if (TYPE_MODE (type) == QImode)
8146	    charType = 'C';
8147	  else if (TYPE_MODE (type) == HImode)
8148	    charType = 'S';
8149	  else if (TYPE_MODE (type) == SImode)
8150	    {
8151	      if (type == long_unsigned_type_node)
8152		charType = 'L';
8153	      else
8154		charType = 'I';
8155	    }
8156	  else if (TYPE_MODE (type) == DImode)
8157	    charType = 'Q';
8158	}
8159
8160      else
8161	/* Signed integer types.  */
8162	{
8163	  if (TYPE_MODE (type) == QImode)
8164	    charType = 'c';
8165	  else if (TYPE_MODE (type) == HImode)
8166	    charType = 's';
8167	  else if (TYPE_MODE (type) == SImode)
8168	    {
8169	      if (type == long_integer_type_node)
8170		charType = 'l';
8171	      else
8172		charType = 'i';
8173	    }
8174
8175	  else if (TYPE_MODE (type) == DImode)
8176	    charType = 'q';
8177	}
8178    }
8179  else if (code == ENUMERAL_TYPE)
8180    charType = 'i';
8181  else
8182    abort ();
8183
8184  sprintf (buffer, "b%d%c%d", position, charType, size);
8185  obstack_grow (&util_obstack, buffer, strlen (buffer));
8186}
8187
8188static void
8189encode_field_decl (tree field_decl, int curtype, int format)
8190{
8191  tree type;
8192
8193#ifdef OBJCPLUS
8194  /* C++ static members, and things that are not fields at all,
8195     should not appear in the encoding.  */
8196  if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
8197    return;
8198#endif
8199
8200  type = TREE_TYPE (field_decl);
8201
8202  /* Generate the bitfield typing information, if needed.  Note the difference
8203     between GNU and NeXT runtimes.  */
8204  if (DECL_BIT_FIELD_TYPE (field_decl))
8205    {
8206      int size = tree_low_cst (DECL_SIZE (field_decl), 1);
8207
8208      if (flag_next_runtime)
8209	encode_next_bitfield (size);
8210      else
8211	encode_gnu_bitfield (int_bit_position (field_decl),
8212				  DECL_BIT_FIELD_TYPE (field_decl), size);
8213    }
8214  else
8215    encode_type (TREE_TYPE (field_decl), curtype, format);
8216}
8217
8218static GTY(()) tree objc_parmlist = NULL_TREE;
8219
8220/* Append PARM to a list of formal parameters of a method, making a necessary
8221   array-to-pointer adjustment along the way.  */
8222
8223static void
8224objc_push_parm (tree parm)
8225{
8226  bool relayout_needed = false;
8227  /* Decay arrays and functions into pointers.  */
8228  if (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE)
8229    {
8230      TREE_TYPE (parm) = build_pointer_type (TREE_TYPE (TREE_TYPE (parm)));
8231      relayout_needed = true;
8232    }
8233  else if (TREE_CODE (TREE_TYPE (parm)) == FUNCTION_TYPE)
8234    {
8235      TREE_TYPE (parm) = build_pointer_type (TREE_TYPE (parm));
8236      relayout_needed = true;
8237    }
8238
8239  if (relayout_needed)
8240    relayout_decl (parm);
8241
8242
8243  DECL_ARG_TYPE (parm)
8244    = lang_hooks.types.type_promotes_to (TREE_TYPE (parm));
8245
8246  /* Record constancy and volatility.  */
8247  c_apply_type_quals_to_decl
8248  ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
8249   | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
8250   | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
8251
8252  objc_parmlist = chainon (objc_parmlist, parm);
8253}
8254
8255/* Retrieve the formal parameter list constructed via preceding calls to
8256   objc_push_parm().  */
8257
8258#ifdef OBJCPLUS
8259static tree
8260objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
8261#else
8262static struct c_arg_info *
8263objc_get_parm_info (int have_ellipsis)
8264#endif
8265{
8266#ifdef OBJCPLUS
8267  tree parm_info = objc_parmlist;
8268  objc_parmlist = NULL_TREE;
8269
8270  return parm_info;
8271#else
8272  tree parm_info = objc_parmlist;
8273  struct c_arg_info *arg_info;
8274  /* The C front-end requires an elaborate song and dance at
8275     this point.  */
8276  push_scope ();
8277  declare_parm_level ();
8278  while (parm_info)
8279    {
8280      tree next = TREE_CHAIN (parm_info);
8281
8282      TREE_CHAIN (parm_info) = NULL_TREE;
8283      parm_info = pushdecl (parm_info);
8284      finish_decl (parm_info, NULL_TREE, NULL_TREE);
8285      parm_info = next;
8286    }
8287  arg_info = get_parm_info (have_ellipsis);
8288  pop_scope ();
8289  objc_parmlist = NULL_TREE;
8290  return arg_info;
8291#endif
8292}
8293
8294/* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
8295   method definitions.  In the case of instance methods, we can be more
8296   specific as to the type of 'self'.  */
8297
8298static void
8299synth_self_and_ucmd_args (void)
8300{
8301  tree self_type;
8302
8303  if (objc_method_context
8304      && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
8305    self_type = objc_instance_type;
8306  else
8307    /* Really a `struct objc_class *'. However, we allow people to
8308       assign to self, which changes its type midstream.  */
8309    self_type = objc_object_type;
8310
8311  /* id self; */
8312  objc_push_parm (build_decl (PARM_DECL, self_id, self_type));
8313
8314  /* SEL _cmd; */
8315  objc_push_parm (build_decl (PARM_DECL, ucmd_id, objc_selector_type));
8316}
8317
8318/* Transform an Objective-C method definition into a static C function
8319   definition, synthesizing the first two arguments, "self" and "_cmd",
8320   in the process.  */
8321
8322static void
8323start_method_def (tree method)
8324{
8325  tree parmlist;
8326#ifdef OBJCPLUS
8327  tree parm_info;
8328#else
8329  struct c_arg_info *parm_info;
8330#endif
8331  int have_ellipsis = 0;
8332
8333  /* If we are defining a "dealloc" method in a non-root class, we
8334     will need to check if a [super dealloc] is missing, and warn if
8335     it is.  */
8336  if(CLASS_SUPER_NAME (objc_implementation_context)
8337     && !strcmp ("dealloc", IDENTIFIER_POINTER (METHOD_SEL_NAME (method))))
8338    should_call_super_dealloc = 1;
8339  else
8340    should_call_super_dealloc = 0;
8341
8342  /* Required to implement _msgSuper.  */
8343  objc_method_context = method;
8344  UOBJC_SUPER_decl = NULL_TREE;
8345
8346  /* Generate prototype declarations for arguments..."new-style".  */
8347  synth_self_and_ucmd_args ();
8348
8349  /* Generate argument declarations if a keyword_decl.  */
8350  parmlist = METHOD_SEL_ARGS (method);
8351  while (parmlist)
8352    {
8353      tree type = TREE_VALUE (TREE_TYPE (parmlist)), parm;
8354
8355      parm = build_decl (PARM_DECL, KEYWORD_ARG_NAME (parmlist), type);
8356      objc_push_parm (parm);
8357      parmlist = TREE_CHAIN (parmlist);
8358    }
8359
8360  if (METHOD_ADD_ARGS (method))
8361    {
8362      tree akey;
8363
8364      for (akey = TREE_CHAIN (METHOD_ADD_ARGS (method));
8365	   akey; akey = TREE_CHAIN (akey))
8366	{
8367	  objc_push_parm (TREE_VALUE (akey));
8368	}
8369
8370      if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
8371	have_ellipsis = 1;
8372    }
8373
8374  parm_info = objc_get_parm_info (have_ellipsis);
8375
8376  really_start_method (objc_method_context, parm_info);
8377}
8378
8379static void
8380warn_with_method (const char *message, int mtype, tree method)
8381{
8382  /* Add a readable method name to the warning.  */
8383  warning (0, "%J%s %<%c%s%>", method,
8384           message, mtype, gen_method_decl (method));
8385}
8386
8387/* Return 1 if TYPE1 is equivalent to TYPE2
8388   for purposes of method overloading.  */
8389
8390static int
8391objc_types_are_equivalent (tree type1, tree type2)
8392{
8393  if (type1 == type2)
8394    return 1;
8395
8396  /* Strip away indirections.  */
8397  while ((TREE_CODE (type1) == ARRAY_TYPE || TREE_CODE (type1) == POINTER_TYPE)
8398	 && (TREE_CODE (type1) == TREE_CODE (type2)))
8399    type1 = TREE_TYPE (type1), type2 = TREE_TYPE (type2);
8400  if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
8401    return 0;
8402
8403  type1 = (TYPE_HAS_OBJC_INFO (type1)
8404	   ? TYPE_OBJC_PROTOCOL_LIST (type1)
8405	   : NULL_TREE);
8406  type2 = (TYPE_HAS_OBJC_INFO (type2)
8407	   ? TYPE_OBJC_PROTOCOL_LIST (type2)
8408	   : NULL_TREE);
8409
8410  if (list_length (type1) == list_length (type2))
8411    {
8412      for (; type2; type2 = TREE_CHAIN (type2))
8413	if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
8414	  return 0;
8415      return 1;
8416    }
8417  return 0;
8418}
8419
8420/* Return 1 if TYPE1 has the same size and alignment as TYPE2.  */
8421
8422static int
8423objc_types_share_size_and_alignment (tree type1, tree type2)
8424{
8425  return (simple_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
8426	  && TYPE_ALIGN (type1) == TYPE_ALIGN (type2));
8427}
8428
8429/* Return 1 if PROTO1 is equivalent to PROTO2
8430   for purposes of method overloading.  Ordinarily, the type signatures
8431   should match up exactly, unless STRICT is zero, in which case we
8432   shall allow differences in which the size and alignment of a type
8433   is the same.  */
8434
8435static int
8436comp_proto_with_proto (tree proto1, tree proto2, int strict)
8437{
8438  tree type1, type2;
8439
8440  /* The following test is needed in case there are hashing
8441     collisions.  */
8442  if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
8443    return 0;
8444
8445  /* Compare return types.  */
8446  type1 = TREE_VALUE (TREE_TYPE (proto1));
8447  type2 = TREE_VALUE (TREE_TYPE (proto2));
8448
8449  if (!objc_types_are_equivalent (type1, type2)
8450      && (strict || !objc_types_share_size_and_alignment (type1, type2)))
8451    return 0;
8452
8453  /* Compare argument types.  */
8454  for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
8455       type2 = get_arg_type_list (proto2, METHOD_REF, 0);
8456       type1 && type2;
8457       type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
8458    {
8459      if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2))
8460	  && (strict
8461	      || !objc_types_share_size_and_alignment (TREE_VALUE (type1),
8462						       TREE_VALUE (type2))))
8463	return 0;
8464    }
8465
8466  return (!type1 && !type2);
8467}
8468
8469/* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
8470   this occurs.  ObjC method dispatches are _not_ like C++ virtual
8471   member function dispatches, and we account for the difference here.  */
8472tree
8473#ifdef OBJCPLUS
8474objc_fold_obj_type_ref (tree ref, tree known_type)
8475#else
8476objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
8477			tree known_type ATTRIBUTE_UNUSED)
8478#endif
8479{
8480#ifdef OBJCPLUS
8481  tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
8482
8483  /* If the receiver does not have virtual member functions, there
8484     is nothing we can (or need to) do here.  */
8485  if (!v)
8486    return NULL_TREE;
8487
8488  /* Let C++ handle C++ virtual functions.  */
8489  return cp_fold_obj_type_ref (ref, known_type);
8490#else
8491  /* For plain ObjC, we currently do not need to do anything.  */
8492  return NULL_TREE;
8493#endif
8494}
8495
8496static void
8497objc_start_function (tree name, tree type, tree attrs,
8498#ifdef OBJCPLUS
8499		     tree params
8500#else
8501		     struct c_arg_info *params
8502#endif
8503		     )
8504{
8505  tree fndecl = build_decl (FUNCTION_DECL, name, type);
8506
8507#ifdef OBJCPLUS
8508  DECL_ARGUMENTS (fndecl) = params;
8509  DECL_INITIAL (fndecl) = error_mark_node;
8510  DECL_EXTERNAL (fndecl) = 0;
8511  TREE_STATIC (fndecl) = 1;
8512  retrofit_lang_decl (fndecl);
8513  cplus_decl_attributes (&fndecl, attrs, 0);
8514  start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
8515#else
8516  struct c_label_context_se *nstack_se;
8517  struct c_label_context_vm *nstack_vm;
8518  nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
8519  nstack_se->labels_def = NULL;
8520  nstack_se->labels_used = NULL;
8521  nstack_se->next = label_context_stack_se;
8522  label_context_stack_se = nstack_se;
8523  nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm);
8524  nstack_vm->labels_def = NULL;
8525  nstack_vm->labels_used = NULL;
8526  nstack_vm->scope = 0;
8527  nstack_vm->next = label_context_stack_vm;
8528  label_context_stack_vm = nstack_vm;
8529  current_function_returns_value = 0;  /* Assume, until we see it does.  */
8530  current_function_returns_null = 0;
8531
8532  decl_attributes (&fndecl, attrs, 0);
8533  announce_function (fndecl);
8534  DECL_INITIAL (fndecl) = error_mark_node;
8535  DECL_EXTERNAL (fndecl) = 0;
8536  TREE_STATIC (fndecl) = 1;
8537  current_function_decl = pushdecl (fndecl);
8538  push_scope ();
8539  declare_parm_level ();
8540  DECL_RESULT (current_function_decl)
8541    = build_decl (RESULT_DECL, NULL_TREE,
8542		  TREE_TYPE (TREE_TYPE (current_function_decl)));
8543  DECL_ARTIFICIAL (DECL_RESULT (current_function_decl)) = 1;
8544  DECL_IGNORED_P (DECL_RESULT (current_function_decl)) = 1;
8545  start_fname_decls ();
8546  store_parm_decls_from (params);
8547#endif
8548
8549  TREE_USED (current_function_decl) = 1;
8550}
8551
8552/* - Generate an identifier for the function. the format is "_n_cls",
8553     where 1 <= n <= nMethods, and cls is the name the implementation we
8554     are processing.
8555   - Install the return type from the method declaration.
8556   - If we have a prototype, check for type consistency.  */
8557
8558static void
8559really_start_method (tree method,
8560#ifdef OBJCPLUS
8561		     tree parmlist
8562#else
8563		     struct c_arg_info *parmlist
8564#endif
8565		     )
8566{
8567  tree ret_type, meth_type;
8568  tree method_id;
8569  const char *sel_name, *class_name, *cat_name;
8570  char *buf;
8571
8572  /* Synth the storage class & assemble the return type.  */
8573  ret_type = TREE_VALUE (TREE_TYPE (method));
8574
8575  sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
8576  class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
8577  cat_name = ((TREE_CODE (objc_implementation_context)
8578	       == CLASS_IMPLEMENTATION_TYPE)
8579	      ? NULL
8580	      : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
8581  method_slot++;
8582
8583  /* Make sure this is big enough for any plausible method label.  */
8584  buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
8585			 + (cat_name ? strlen (cat_name) : 0));
8586
8587  OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
8588			 class_name, cat_name, sel_name, method_slot);
8589
8590  method_id = get_identifier (buf);
8591
8592#ifdef OBJCPLUS
8593  /* Objective-C methods cannot be overloaded, so we don't need
8594     the type encoding appended.  It looks bad anyway... */
8595  push_lang_context (lang_name_c);
8596#endif
8597
8598  meth_type
8599    = build_function_type (ret_type,
8600			   get_arg_type_list (method, METHOD_DEF, 0));
8601  objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
8602
8603  /* Set self_decl from the first argument.  */
8604  self_decl = DECL_ARGUMENTS (current_function_decl);
8605
8606  /* Suppress unused warnings.  */
8607  TREE_USED (self_decl) = 1;
8608  TREE_USED (TREE_CHAIN (self_decl)) = 1;
8609#ifdef OBJCPLUS
8610  pop_lang_context ();
8611#endif
8612
8613  METHOD_DEFINITION (method) = current_function_decl;
8614
8615  /* Check consistency...start_function, pushdecl, duplicate_decls.  */
8616
8617  if (implementation_template != objc_implementation_context)
8618    {
8619      tree proto
8620	= lookup_method_static (implementation_template,
8621				METHOD_SEL_NAME (method),
8622				((TREE_CODE (method) == CLASS_METHOD_DECL)
8623				 | OBJC_LOOKUP_NO_SUPER));
8624
8625      if (proto)
8626	{
8627	  if (!comp_proto_with_proto (method, proto, 1))
8628	    {
8629	      char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
8630
8631	      warn_with_method ("conflicting types for", type, method);
8632	      warn_with_method ("previous declaration of", type, proto);
8633	    }
8634	}
8635      else
8636	{
8637	  /* We have a method @implementation even though we did not
8638	     see a corresponding @interface declaration (which is allowed
8639	     by Objective-C rules).  Go ahead and place the method in
8640	     the @interface anyway, so that message dispatch lookups
8641	     will see it.  */
8642	  tree interface = implementation_template;
8643
8644	  if (TREE_CODE (objc_implementation_context)
8645	      == CATEGORY_IMPLEMENTATION_TYPE)
8646	    interface = lookup_category
8647			(interface,
8648			 CLASS_SUPER_NAME (objc_implementation_context));
8649
8650	  if (interface)
8651	    objc_add_method (interface, copy_node (method),
8652			     TREE_CODE (method) == CLASS_METHOD_DECL);
8653	}
8654    }
8655}
8656
8657static void *UOBJC_SUPER_scope = 0;
8658
8659/* _n_Method (id self, SEL sel, ...)
8660     {
8661       struct objc_super _S;
8662       _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
8663     }  */
8664
8665static tree
8666get_super_receiver (void)
8667{
8668  if (objc_method_context)
8669    {
8670      tree super_expr, super_expr_list;
8671
8672      if (!UOBJC_SUPER_decl)
8673      {
8674	UOBJC_SUPER_decl = build_decl (VAR_DECL, get_identifier (TAG_SUPER),
8675				       objc_super_template);
8676	/* This prevents `unused variable' warnings when compiling with -Wall.  */
8677	TREE_USED (UOBJC_SUPER_decl) = 1;
8678	lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
8679        finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
8680	UOBJC_SUPER_scope = objc_get_current_scope ();
8681      }
8682
8683      /* Set receiver to self.  */
8684      super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id);
8685      super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
8686      super_expr_list = super_expr;
8687
8688      /* Set class to begin searching.  */
8689      super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
8690					     get_identifier ("super_class"));
8691
8692      if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8693	{
8694	  /* [_cls, __cls]Super are "pre-built" in
8695	     synth_forward_declarations.  */
8696
8697	  super_expr = build_modify_expr (super_expr, NOP_EXPR,
8698					  ((TREE_CODE (objc_method_context)
8699					    == INSTANCE_METHOD_DECL)
8700					   ? ucls_super_ref
8701					   : uucls_super_ref));
8702	}
8703
8704      else
8705	/* We have a category.  */
8706	{
8707	  tree super_name = CLASS_SUPER_NAME (implementation_template);
8708	  tree super_class;
8709
8710	  /* Barf if super used in a category of Object.  */
8711	  if (!super_name)
8712	    {
8713	      error ("no super class declared in interface for %qs",
8714		    IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
8715	      return error_mark_node;
8716	    }
8717
8718	  if (flag_next_runtime && !flag_zero_link)
8719	    {
8720	      super_class = objc_get_class_reference (super_name);
8721	      if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
8722		/* If we are in a class method, we must retrieve the
8723		   _metaclass_ for the current class, pointed at by
8724		   the class's "isa" pointer.  The following assumes that
8725		   "isa" is the first ivar in a class (which it must be).  */
8726		super_class
8727		  = build_indirect_ref
8728		    (build_c_cast (build_pointer_type (objc_class_type),
8729				   super_class), "unary *");
8730	    }
8731	  else
8732	    {
8733	      add_class_reference (super_name);
8734	      super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
8735			     ? objc_get_class_decl : objc_get_meta_class_decl);
8736	      assemble_external (super_class);
8737	      super_class
8738		= build_function_call
8739		  (super_class,
8740		   build_tree_list
8741		   (NULL_TREE,
8742		    my_build_string_pointer
8743		    (IDENTIFIER_LENGTH (super_name) + 1,
8744		     IDENTIFIER_POINTER (super_name))));
8745	    }
8746
8747	  super_expr
8748	    = build_modify_expr (super_expr, NOP_EXPR,
8749				 build_c_cast (TREE_TYPE (super_expr),
8750					       super_class));
8751	}
8752
8753      super_expr_list = build_compound_expr (super_expr_list, super_expr);
8754
8755      super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
8756      super_expr_list = build_compound_expr (super_expr_list, super_expr);
8757
8758      return super_expr_list;
8759    }
8760  else
8761    {
8762      error ("[super ...] must appear in a method context");
8763      return error_mark_node;
8764    }
8765}
8766
8767/* When exiting a scope, sever links to a 'super' declaration (if any)
8768   therein contained.  */
8769
8770void
8771objc_clear_super_receiver (void)
8772{
8773  if (objc_method_context
8774      && UOBJC_SUPER_scope == objc_get_current_scope ()) {
8775    UOBJC_SUPER_decl = 0;
8776    UOBJC_SUPER_scope = 0;
8777  }
8778}
8779
8780void
8781objc_finish_method_definition (tree fndecl)
8782{
8783  /* We cannot validly inline ObjC methods, at least not without a language
8784     extension to declare that a method need not be dynamically
8785     dispatched, so suppress all thoughts of doing so.  */
8786  DECL_INLINE (fndecl) = 0;
8787  DECL_UNINLINABLE (fndecl) = 1;
8788
8789#ifndef OBJCPLUS
8790  /* The C++ front-end will have called finish_function() for us.  */
8791  finish_function ();
8792#endif
8793
8794  METHOD_ENCODING (objc_method_context)
8795    = encode_method_prototype (objc_method_context);
8796
8797  /* Required to implement _msgSuper. This must be done AFTER finish_function,
8798     since the optimizer may find "may be used before set" errors.  */
8799  objc_method_context = NULL_TREE;
8800
8801  if (should_call_super_dealloc)
8802    warning (0, "method possibly missing a [super dealloc] call");
8803}
8804
8805#if 0
8806int
8807lang_report_error_function (tree decl)
8808{
8809  if (objc_method_context)
8810    {
8811      fprintf (stderr, "In method %qs\n",
8812	       IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8813      return 1;
8814    }
8815
8816  else
8817    return 0;
8818}
8819#endif
8820
8821/* Given a tree DECL node, produce a printable description of it in the given
8822   buffer, overwriting the buffer.  */
8823
8824static char *
8825gen_declaration (tree decl)
8826{
8827  errbuf[0] = '\0';
8828
8829  if (DECL_P (decl))
8830    {
8831      gen_type_name_0 (TREE_TYPE (decl));
8832
8833      if (DECL_NAME (decl))
8834	{
8835	  if (!POINTER_TYPE_P (TREE_TYPE (decl)))
8836	    strcat (errbuf, " ");
8837
8838	  strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
8839	}
8840
8841      if (DECL_INITIAL (decl)
8842	  && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
8843	sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
8844		 TREE_INT_CST_LOW (DECL_INITIAL (decl)));
8845    }
8846
8847  return errbuf;
8848}
8849
8850/* Given a tree TYPE node, produce a printable description of it in the given
8851   buffer, overwriting the buffer.  */
8852
8853static char *
8854gen_type_name_0 (tree type)
8855{
8856  tree orig = type, proto;
8857
8858  if (TYPE_P (type) && TYPE_NAME (type))
8859    type = TYPE_NAME (type);
8860  else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
8861    {
8862      tree inner = TREE_TYPE (type);
8863
8864      while (TREE_CODE (inner) == ARRAY_TYPE)
8865	inner = TREE_TYPE (inner);
8866
8867      gen_type_name_0 (inner);
8868
8869      if (!POINTER_TYPE_P (inner))
8870	strcat (errbuf, " ");
8871
8872      if (POINTER_TYPE_P (type))
8873	strcat (errbuf, "*");
8874      else
8875	while (type != inner)
8876	  {
8877	    strcat (errbuf, "[");
8878
8879	    if (TYPE_DOMAIN (type))
8880	      {
8881		char sz[20];
8882
8883		sprintf (sz, HOST_WIDE_INT_PRINT_DEC,
8884			 (TREE_INT_CST_LOW
8885			  (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1));
8886		strcat (errbuf, sz);
8887	      }
8888
8889	    strcat (errbuf, "]");
8890	    type = TREE_TYPE (type);
8891	  }
8892
8893      goto exit_function;
8894    }
8895
8896  if (TREE_CODE (type) == TYPE_DECL && DECL_NAME (type))
8897    type = DECL_NAME (type);
8898
8899  strcat (errbuf, TREE_CODE (type) == IDENTIFIER_NODE
8900	  	  ? IDENTIFIER_POINTER (type)
8901		  : "");
8902
8903  /* For 'id' and 'Class', adopted protocols are stored in the pointee.  */
8904  if (objc_is_id (orig))
8905    orig = TREE_TYPE (orig);
8906
8907  proto = TYPE_HAS_OBJC_INFO (orig) ? TYPE_OBJC_PROTOCOL_LIST (orig) : NULL_TREE;
8908
8909  if (proto)
8910    {
8911      strcat (errbuf, " <");
8912
8913      while (proto) {
8914	strcat (errbuf,
8915		IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (proto))));
8916	proto = TREE_CHAIN (proto);
8917	strcat (errbuf, proto ? ", " : ">");
8918      }
8919    }
8920
8921 exit_function:
8922  return errbuf;
8923}
8924
8925static char *
8926gen_type_name (tree type)
8927{
8928  errbuf[0] = '\0';
8929
8930  return gen_type_name_0 (type);
8931}
8932
8933/* Given a method tree, put a printable description into the given
8934   buffer (overwriting) and return a pointer to the buffer.  */
8935
8936static char *
8937gen_method_decl (tree method)
8938{
8939  tree chain;
8940
8941  strcpy (errbuf, "(");  /* NB: Do _not_ call strcat() here.  */
8942  gen_type_name_0 (TREE_VALUE (TREE_TYPE (method)));
8943  strcat (errbuf, ")");
8944  chain = METHOD_SEL_ARGS (method);
8945
8946  if (chain)
8947    {
8948      /* We have a chain of keyword_decls.  */
8949      do
8950        {
8951	  if (KEYWORD_KEY_NAME (chain))
8952	    strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8953
8954	  strcat (errbuf, ":(");
8955	  gen_type_name_0 (TREE_VALUE (TREE_TYPE (chain)));
8956	  strcat (errbuf, ")");
8957
8958	  strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8959	  if ((chain = TREE_CHAIN (chain)))
8960	    strcat (errbuf, " ");
8961        }
8962      while (chain);
8963
8964      if (METHOD_ADD_ARGS (method))
8965	{
8966	  chain = TREE_CHAIN (METHOD_ADD_ARGS (method));
8967
8968	  /* Know we have a chain of parm_decls.  */
8969	  while (chain)
8970	    {
8971	      strcat (errbuf, ", ");
8972	      gen_type_name_0 (TREE_TYPE (TREE_VALUE (chain)));
8973	      chain = TREE_CHAIN (chain);
8974	    }
8975
8976	  if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
8977	    strcat (errbuf, ", ...");
8978	}
8979    }
8980
8981  else
8982    /* We have a unary selector.  */
8983    strcat (errbuf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8984
8985  return errbuf;
8986}
8987
8988/* Debug info.  */
8989
8990
8991/* Dump an @interface declaration of the supplied class CHAIN to the
8992   supplied file FP.  Used to implement the -gen-decls option (which
8993   prints out an @interface declaration of all classes compiled in
8994   this run); potentially useful for debugging the compiler too.  */
8995static void
8996dump_interface (FILE *fp, tree chain)
8997{
8998  /* FIXME: A heap overflow here whenever a method (or ivar)
8999     declaration is so long that it doesn't fit in the buffer.  The
9000     code and all the related functions should be rewritten to avoid
9001     using fixed size buffers.  */
9002  const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
9003  tree ivar_decls = CLASS_RAW_IVARS (chain);
9004  tree nst_methods = CLASS_NST_METHODS (chain);
9005  tree cls_methods = CLASS_CLS_METHODS (chain);
9006
9007  fprintf (fp, "\n@interface %s", my_name);
9008
9009  /* CLASS_SUPER_NAME is used to store the superclass name for
9010     classes, and the category name for categories.  */
9011  if (CLASS_SUPER_NAME (chain))
9012    {
9013      const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
9014
9015      if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
9016	  || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
9017	{
9018	  fprintf (fp, " (%s)\n", name);
9019	}
9020      else
9021	{
9022	  fprintf (fp, " : %s\n", name);
9023	}
9024    }
9025  else
9026    fprintf (fp, "\n");
9027
9028  /* FIXME - the following doesn't seem to work at the moment.  */
9029  if (ivar_decls)
9030    {
9031      fprintf (fp, "{\n");
9032      do
9033	{
9034	  fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls));
9035	  ivar_decls = TREE_CHAIN (ivar_decls);
9036	}
9037      while (ivar_decls);
9038      fprintf (fp, "}\n");
9039    }
9040
9041  while (nst_methods)
9042    {
9043      fprintf (fp, "- %s;\n", gen_method_decl (nst_methods));
9044      nst_methods = TREE_CHAIN (nst_methods);
9045    }
9046
9047  while (cls_methods)
9048    {
9049      fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods));
9050      cls_methods = TREE_CHAIN (cls_methods);
9051    }
9052
9053  fprintf (fp, "@end\n");
9054}
9055
9056/* Demangle function for Objective-C */
9057static const char *
9058objc_demangle (const char *mangled)
9059{
9060  char *demangled, *cp;
9061
9062  if (mangled[0] == '_' &&
9063      (mangled[1] == 'i' || mangled[1] == 'c') &&
9064      mangled[2] == '_')
9065    {
9066      cp = demangled = XNEWVEC (char, strlen(mangled) + 2);
9067      if (mangled[1] == 'i')
9068	*cp++ = '-';            /* for instance method */
9069      else
9070	*cp++ = '+';            /* for class method */
9071      *cp++ = '[';              /* opening left brace */
9072      strcpy(cp, mangled+3);    /* tack on the rest of the mangled name */
9073      while (*cp && *cp == '_')
9074	cp++;                   /* skip any initial underbars in class name */
9075      cp = strchr(cp, '_');     /* find first non-initial underbar */
9076      if (cp == NULL)
9077	{
9078	  free(demangled);      /* not mangled name */
9079	  return mangled;
9080	}
9081      if (cp[1] == '_')  /* easy case: no category name */
9082	{
9083	  *cp++ = ' ';            /* replace two '_' with one ' ' */
9084	  strcpy(cp, mangled + (cp - demangled) + 2);
9085	}
9086      else
9087	{
9088	  *cp++ = '(';            /* less easy case: category name */
9089	  cp = strchr(cp, '_');
9090	  if (cp == 0)
9091	    {
9092	      free(demangled);    /* not mangled name */
9093	      return mangled;
9094	    }
9095	  *cp++ = ')';
9096	  *cp++ = ' ';            /* overwriting 1st char of method name... */
9097	  strcpy(cp, mangled + (cp - demangled)); /* get it back */
9098	}
9099      while (*cp && *cp == '_')
9100	cp++;                   /* skip any initial underbars in method name */
9101      for (; *cp; cp++)
9102	if (*cp == '_')
9103	  *cp = ':';            /* replace remaining '_' with ':' */
9104      *cp++ = ']';              /* closing right brace */
9105      *cp++ = 0;                /* string terminator */
9106      return demangled;
9107    }
9108  else
9109    return mangled;             /* not an objc mangled name */
9110}
9111
9112const char *
9113objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
9114{
9115  return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
9116}
9117
9118static void
9119init_objc (void)
9120{
9121  gcc_obstack_init (&util_obstack);
9122  util_firstobj = (char *) obstack_finish (&util_obstack);
9123
9124  errbuf = XNEWVEC (char, 1024 * 10);
9125  hash_init ();
9126  synth_module_prologue ();
9127}
9128
9129static void
9130finish_objc (void)
9131{
9132  struct imp_entry *impent;
9133  tree chain;
9134  /* The internally generated initializers appear to have missing braces.
9135     Don't warn about this.  */
9136  int save_warn_missing_braces = warn_missing_braces;
9137  warn_missing_braces = 0;
9138
9139  /* A missing @end may not be detected by the parser.  */
9140  if (objc_implementation_context)
9141    {
9142      warning (0, "%<@end%> missing in implementation context");
9143      finish_class (objc_implementation_context);
9144      objc_ivar_chain = NULL_TREE;
9145      objc_implementation_context = NULL_TREE;
9146    }
9147
9148  /* Process the static instances here because initialization of objc_symtab
9149     depends on them.  */
9150  if (objc_static_instances)
9151    generate_static_references ();
9152
9153  if (imp_list || class_names_chain
9154      || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
9155    generate_objc_symtab_decl ();
9156
9157  for (impent = imp_list; impent; impent = impent->next)
9158    {
9159      objc_implementation_context = impent->imp_context;
9160      implementation_template = impent->imp_template;
9161
9162      UOBJC_CLASS_decl = impent->class_decl;
9163      UOBJC_METACLASS_decl = impent->meta_decl;
9164
9165      /* Dump the @interface of each class as we compile it, if the
9166	 -gen-decls option is in use.  TODO: Dump the classes in the
9167         order they were found, rather than in reverse order as we
9168         are doing now.  */
9169      if (flag_gen_declaration)
9170	{
9171	  dump_interface (gen_declaration_file, objc_implementation_context);
9172	}
9173
9174      if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
9175	{
9176	  /* all of the following reference the string pool...  */
9177	  generate_ivar_lists ();
9178	  generate_dispatch_tables ();
9179	  generate_shared_structures (impent->has_cxx_cdtors
9180				      ? CLS_HAS_CXX_STRUCTORS
9181				      : 0);
9182	}
9183      else
9184	{
9185	  generate_dispatch_tables ();
9186	  generate_category (objc_implementation_context);
9187	}
9188    }
9189
9190  /* If we are using an array of selectors, we must always
9191     finish up the array decl even if no selectors were used.  */
9192  if (! flag_next_runtime || sel_ref_chain)
9193    build_selector_translation_table ();
9194
9195  if (protocol_chain)
9196    generate_protocols ();
9197
9198  if ((flag_replace_objc_classes && imp_list) || flag_objc_gc)
9199    generate_objc_image_info ();
9200
9201  /* Arrange for ObjC data structures to be initialized at run time.  */
9202  if (objc_implementation_context || class_names_chain || objc_static_instances
9203      || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
9204    {
9205      build_module_descriptor ();
9206
9207      if (!flag_next_runtime)
9208	build_module_initializer_routine ();
9209    }
9210
9211  /* Dump the class references.  This forces the appropriate classes
9212     to be linked into the executable image, preserving unix archive
9213     semantics.  This can be removed when we move to a more dynamically
9214     linked environment.  */
9215
9216  for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
9217    {
9218      handle_class_ref (chain);
9219      if (TREE_PURPOSE (chain))
9220	generate_classref_translation_entry (chain);
9221    }
9222
9223  for (impent = imp_list; impent; impent = impent->next)
9224    handle_impent (impent);
9225
9226  if (warn_selector)
9227    {
9228      int slot;
9229      hash hsh;
9230
9231      /* Run through the selector hash tables and print a warning for any
9232         selector which has multiple methods.  */
9233
9234      for (slot = 0; slot < SIZEHASHTABLE; slot++)
9235	{
9236	  for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
9237	    check_duplicates (hsh, 0, 1);
9238	  for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
9239	    check_duplicates (hsh, 0, 1);
9240	}
9241    }
9242
9243  warn_missing_braces = save_warn_missing_braces;
9244}
9245
9246/* Subroutines of finish_objc.  */
9247
9248static void
9249generate_classref_translation_entry (tree chain)
9250{
9251  tree expr, decl, type;
9252
9253  decl = TREE_PURPOSE (chain);
9254  type = TREE_TYPE (decl);
9255
9256  expr = add_objc_string (TREE_VALUE (chain), class_names);
9257  expr = convert (type, expr); /* cast! */
9258
9259  /* The decl that is the one that we
9260     forward declared in build_class_reference.  */
9261  finish_var_decl (decl, expr);
9262  return;
9263}
9264
9265static void
9266handle_class_ref (tree chain)
9267{
9268  const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
9269  char *string = (char *) alloca (strlen (name) + 30);
9270  tree decl;
9271  tree exp;
9272
9273  sprintf (string, "%sobjc_class_name_%s",
9274	   (flag_next_runtime ? "." : "__"), name);
9275
9276#ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
9277  if (flag_next_runtime)
9278    {
9279      ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
9280      return;
9281    }
9282#endif
9283
9284  /* Make a decl for this name, so we can use its address in a tree.  */
9285  decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
9286  DECL_EXTERNAL (decl) = 1;
9287  TREE_PUBLIC (decl) = 1;
9288
9289  pushdecl (decl);
9290  rest_of_decl_compilation (decl, 0, 0);
9291
9292  /* Make a decl for the address.  */
9293  sprintf (string, "%sobjc_class_ref_%s",
9294	   (flag_next_runtime ? "." : "__"), name);
9295  exp = build1 (ADDR_EXPR, string_type_node, decl);
9296  decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
9297  DECL_INITIAL (decl) = exp;
9298  TREE_STATIC (decl) = 1;
9299  TREE_USED (decl) = 1;
9300  /* Force the output of the decl as this forces the reference of the class.  */
9301  mark_decl_referenced (decl);
9302
9303  pushdecl (decl);
9304  rest_of_decl_compilation (decl, 0, 0);
9305}
9306
9307static void
9308handle_impent (struct imp_entry *impent)
9309{
9310  char *string;
9311
9312  objc_implementation_context = impent->imp_context;
9313  implementation_template = impent->imp_template;
9314
9315  if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
9316    {
9317      const char *const class_name =
9318	IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
9319
9320      string = (char *) alloca (strlen (class_name) + 30);
9321
9322      sprintf (string, "%sobjc_class_name_%s",
9323               (flag_next_runtime ? "." : "__"), class_name);
9324    }
9325  else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
9326    {
9327      const char *const class_name =
9328	IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
9329      const char *const class_super_name =
9330        IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
9331
9332      string = (char *) alloca (strlen (class_name)
9333				+ strlen (class_super_name) + 30);
9334
9335      /* Do the same for categories.  Even though no references to
9336         these symbols are generated automatically by the compiler, it
9337         gives you a handle to pull them into an archive by hand.  */
9338      sprintf (string, "*%sobjc_category_name_%s_%s",
9339               (flag_next_runtime ? "." : "__"), class_name, class_super_name);
9340    }
9341  else
9342    return;
9343
9344#ifdef ASM_DECLARE_CLASS_REFERENCE
9345  if (flag_next_runtime)
9346    {
9347      ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9348      return;
9349    }
9350  else
9351#endif
9352    {
9353      tree decl, init;
9354
9355      init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0);
9356      decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9357      TREE_PUBLIC (decl) = 1;
9358      TREE_READONLY (decl) = 1;
9359      TREE_USED (decl) = 1;
9360      TREE_CONSTANT (decl) = 1;
9361      DECL_CONTEXT (decl) = 0;
9362      DECL_ARTIFICIAL (decl) = 1;
9363      DECL_INITIAL (decl) = init;
9364      assemble_variable (decl, 1, 0, 0);
9365    }
9366}
9367
9368/* The Fix-and-Continue functionality available in Mac OS X 10.3 and
9369   later requires that ObjC translation units participating in F&C be
9370   specially marked.  The following routine accomplishes this.  */
9371
9372/* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9373
9374static void
9375generate_objc_image_info (void)
9376{
9377  tree decl, initlist;
9378  int flags
9379    = ((flag_replace_objc_classes && imp_list ? 1 : 0)
9380       | (flag_objc_gc ? 2 : 0));
9381
9382  decl = start_var_decl (build_array_type
9383			 (integer_type_node,
9384			  build_index_type (build_int_cst (NULL_TREE, 2 - 1))),
9385			 "_OBJC_IMAGE_INFO");
9386
9387  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
9388  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), initlist);
9389  initlist = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
9390
9391  finish_var_decl (decl, initlist);
9392}
9393
9394/* Look up ID as an instance variable.  OTHER contains the result of
9395   the C or C++ lookup, which we may want to use instead.  */
9396
9397tree
9398objc_lookup_ivar (tree other, tree id)
9399{
9400  tree ivar;
9401
9402  /* If we are not inside of an ObjC method, ivar lookup makes no sense.  */
9403  if (!objc_method_context)
9404    return other;
9405
9406  if (!strcmp (IDENTIFIER_POINTER (id), "super"))
9407    /* We have a message to super.  */
9408    return get_super_receiver ();
9409
9410  /* In a class method, look up an instance variable only as a last
9411     resort.  */
9412  if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
9413      && other && other != error_mark_node)
9414    return other;
9415
9416  /* Look up the ivar, but do not use it if it is not accessible.  */
9417  ivar = is_ivar (objc_ivar_chain, id);
9418
9419  if (!ivar || is_private (ivar))
9420    return other;
9421
9422  /* In an instance method, a local variable (or parameter) may hide the
9423     instance variable.  */
9424  if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
9425      && other && other != error_mark_node
9426#ifdef OBJCPLUS
9427      && CP_DECL_CONTEXT (other) != global_namespace)
9428#else
9429      && !DECL_FILE_SCOPE_P (other))
9430#endif
9431    {
9432      warning (0, "local declaration of %qs hides instance variable",
9433	       IDENTIFIER_POINTER (id));
9434
9435      return other;
9436    }
9437
9438  /* At this point, we are either in an instance method with no obscuring
9439     local definitions, or in a class method with no alternate definitions
9440     at all.  */
9441  return build_ivar_reference (id);
9442}
9443
9444/* Possibly rewrite a function CALL into an OBJ_TYPE_REF expression.  This
9445   needs to be done if we are calling a function through a cast.  */
9446
9447tree
9448objc_rewrite_function_call (tree function, tree params)
9449{
9450  if (TREE_CODE (function) == NOP_EXPR
9451      && TREE_CODE (TREE_OPERAND (function, 0)) == ADDR_EXPR
9452      && TREE_CODE (TREE_OPERAND (TREE_OPERAND (function, 0), 0))
9453	 == FUNCTION_DECL)
9454    {
9455      function = build3 (OBJ_TYPE_REF, TREE_TYPE (function),
9456			 TREE_OPERAND (function, 0),
9457			 TREE_VALUE (params), size_zero_node);
9458    }
9459
9460  return function;
9461}
9462
9463/* Look for the special case of OBJC_TYPE_REF with the address of
9464   a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
9465   of its cousins).  */
9466
9467enum gimplify_status
9468objc_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
9469{
9470  enum gimplify_status r0, r1;
9471  if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
9472      && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
9473      && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
9474	 == FUNCTION_DECL)
9475    {
9476      /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
9477	 value of the OBJ_TYPE_REF, so force them to be emitted
9478	 during subexpression evaluation rather than after the
9479	 OBJ_TYPE_REF. This permits objc_msgSend calls in Objective
9480	 C to use direct rather than indirect calls when the
9481	 object expression has a postincrement.  */
9482      r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
9483			  is_gimple_val, fb_rvalue);
9484      r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
9485			  is_gimple_val, fb_rvalue);
9486
9487      return MIN (r0, r1);
9488    }
9489
9490#ifdef OBJCPLUS
9491  return cp_gimplify_expr (expr_p, pre_p, post_p);
9492#else
9493  return c_gimplify_expr (expr_p, pre_p, post_p);
9494#endif
9495}
9496
9497/* Given a CALL expression, find the function being called.  The ObjC
9498   version looks for the OBJ_TYPE_REF_EXPR which is used for objc_msgSend.  */
9499
9500tree
9501objc_get_callee_fndecl (tree call_expr)
9502{
9503  tree addr = TREE_OPERAND (call_expr, 0);
9504  if (TREE_CODE (addr) != OBJ_TYPE_REF)
9505    return 0;
9506
9507  addr = OBJ_TYPE_REF_EXPR (addr);
9508
9509  /* If the address is just `&f' for some function `f', then we know
9510     that `f' is being called.  */
9511  if (TREE_CODE (addr) == ADDR_EXPR
9512      && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
9513    return TREE_OPERAND (addr, 0);
9514
9515  return 0;
9516}
9517
9518#include "gt-objc-objc-act.h"
9519