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