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