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