* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / objc / objc-act.c
blobff449c756f1d82fafbf90f888d9168ae4f733a7b
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by Steve Naroff.
6 This file is part of GNU CC.
8 GNU CC 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.
13 GNU CC 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.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* Purpose: This module implements the Objective-C 4.0 language.
25 compatibility issues (with the Stepstone translator):
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.
38 code generation `options':
42 #include "config.h"
43 #include "system.h"
44 #include "tree.h"
45 #include "rtl.h"
46 #include "expr.h"
47 #include "c-tree.h"
48 #include "c-lex.h"
49 #include "c-common.h"
50 #include "flags.h"
51 #include "objc-act.h"
52 #include "input.h"
53 #include "except.h"
54 #include "function.h"
55 #include "output.h"
56 #include "toplev.h"
57 #include "ggc.h"
58 #include "cpplib.h"
59 #include "debug.h"
60 #include "target.h"
61 #include "varray.h"
62 #include "langhooks.h"
63 #include "langhooks-def.h"
65 /* This is the default way of generating a method name. */
66 /* I am not sure it is really correct.
67 Perhaps there's a danger that it will make name conflicts
68 if method names contain underscores. -- rms. */
69 #ifndef OBJC_GEN_METHOD_LABEL
70 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
71 do { \
72 char *temp; \
73 sprintf ((BUF), "_%s_%s_%s_%s", \
74 ((IS_INST) ? "i" : "c"), \
75 (CLASS_NAME), \
76 ((CAT_NAME)? (CAT_NAME) : ""), \
77 (SEL_NAME)); \
78 for (temp = (BUF); *temp; temp++) \
79 if (*temp == ':') *temp = '_'; \
80 } while (0)
81 #endif
83 /* These need specifying. */
84 #ifndef OBJC_FORWARDING_STACK_OFFSET
85 #define OBJC_FORWARDING_STACK_OFFSET 0
86 #endif
88 #ifndef OBJC_FORWARDING_MIN_OFFSET
89 #define OBJC_FORWARDING_MIN_OFFSET 0
90 #endif
92 /* Define the special tree codes that we use. */
94 /* Table indexed by tree code giving a string containing a character
95 classifying the tree code. */
97 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
99 static const char objc_tree_code_type[] = {
100 'x',
101 #include "objc-tree.def"
103 #undef DEFTREECODE
105 /* Table indexed by tree code giving number of expression
106 operands beyond the fixed part of the node structure.
107 Not used for types or decls. */
109 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
111 static const int objc_tree_code_length[] = {
113 #include "objc-tree.def"
115 #undef DEFTREECODE
117 /* Names of tree components.
118 Used for printing out the tree and error messages. */
119 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
121 static const char * const objc_tree_code_name[] = {
122 "@@dummy",
123 #include "objc-tree.def"
125 #undef DEFTREECODE
127 /* Set up for use of obstacks. */
129 #include "obstack.h"
131 #define obstack_chunk_alloc xmalloc
132 #define obstack_chunk_free free
134 /* This obstack is used to accumulate the encoding of a data type. */
135 static struct obstack util_obstack;
136 /* This points to the beginning of obstack contents,
137 so we can free the whole contents. */
138 char *util_firstobj;
140 /* for encode_method_def */
141 #include "rtl.h"
143 /* The version identifies which language generation and runtime
144 the module (file) was compiled for, and is recorded in the
145 module descriptor. */
147 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
148 #define PROTOCOL_VERSION 2
150 /* (Decide if these can ever be validly changed.) */
151 #define OBJC_ENCODE_INLINE_DEFS 0
152 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
154 /*** Private Interface (procedures) ***/
156 /* Used by compile_file. */
158 static void init_objc PARAMS ((void));
159 static void finish_objc PARAMS ((void));
160 static const char *objc_init PARAMS ((const char *));
161 static void objc_init_options PARAMS ((void));
162 static int objc_decode_option PARAMS ((int, char **));
163 static void objc_post_options PARAMS ((void));
165 /* Code generation. */
167 static void synth_module_prologue PARAMS ((void));
168 static tree build_constructor PARAMS ((tree, tree));
169 static rtx build_module_descriptor PARAMS ((void));
170 static tree init_module_descriptor PARAMS ((tree));
171 static tree build_objc_method_call PARAMS ((int, tree, tree,
172 tree, tree, tree));
173 static void generate_strings PARAMS ((void));
174 static tree get_proto_encoding PARAMS ((tree));
175 static void build_selector_translation_table PARAMS ((void));
176 static tree build_ivar_chain PARAMS ((tree, int));
178 static tree objc_add_static_instance PARAMS ((tree, tree));
180 static tree build_ivar_template PARAMS ((void));
181 static tree build_method_template PARAMS ((void));
182 static tree build_private_template PARAMS ((tree));
183 static void build_class_template PARAMS ((void));
184 static void build_selector_template PARAMS ((void));
185 static void build_category_template PARAMS ((void));
186 static tree build_super_template PARAMS ((void));
187 static tree build_category_initializer PARAMS ((tree, tree, tree,
188 tree, tree, tree));
189 static tree build_protocol_initializer PARAMS ((tree, tree, tree,
190 tree, tree));
192 static void synth_forward_declarations PARAMS ((void));
193 static void generate_ivar_lists PARAMS ((void));
194 static void generate_dispatch_tables PARAMS ((void));
195 static void generate_shared_structures PARAMS ((void));
196 static tree generate_protocol_list PARAMS ((tree));
197 static void generate_forward_declaration_to_string_table PARAMS ((void));
198 static void build_protocol_reference PARAMS ((tree));
200 static tree build_keyword_selector PARAMS ((tree));
201 static tree synth_id_with_class_suffix PARAMS ((const char *, tree));
203 static void generate_static_references PARAMS ((void));
204 static int check_methods_accessible PARAMS ((tree, tree,
205 int));
206 static void encode_aggregate_within PARAMS ((tree, int, int,
207 int, int));
208 static const char *objc_demangle PARAMS ((const char *));
209 static const char *objc_printable_name PARAMS ((tree, int));
210 static void objc_expand_function_end PARAMS ((void));
212 /* Hash tables to manage the global pool of method prototypes. */
214 hash *nst_method_hash_list = 0;
215 hash *cls_method_hash_list = 0;
217 static void hash_init PARAMS ((void));
218 static void hash_enter PARAMS ((hash *, tree));
219 static hash hash_lookup PARAMS ((hash *, tree));
220 static void hash_add_attr PARAMS ((hash, tree));
221 static tree lookup_method PARAMS ((tree, tree));
222 static tree lookup_instance_method_static PARAMS ((tree, tree));
223 static tree lookup_class_method_static PARAMS ((tree, tree));
224 static tree add_class PARAMS ((tree));
225 static void add_category PARAMS ((tree, tree));
227 enum string_section
229 class_names, /* class, category, protocol, module names */
230 meth_var_names, /* method and variable names */
231 meth_var_types /* method and variable type descriptors */
234 static tree add_objc_string PARAMS ((tree,
235 enum string_section));
236 static tree get_objc_string_decl PARAMS ((tree,
237 enum string_section));
238 static tree build_objc_string_decl PARAMS ((enum string_section));
239 static tree build_selector_reference_decl PARAMS ((void));
241 /* Protocol additions. */
243 static tree add_protocol PARAMS ((tree));
244 static tree lookup_protocol PARAMS ((tree));
245 static void check_protocol_recursively PARAMS ((tree, tree));
246 static tree lookup_and_install_protocols PARAMS ((tree));
248 /* Type encoding. */
250 static void encode_type_qualifiers PARAMS ((tree));
251 static void encode_pointer PARAMS ((tree, int, int));
252 static void encode_array PARAMS ((tree, int, int));
253 static void encode_aggregate PARAMS ((tree, int, int));
254 static void encode_bitfield PARAMS ((int));
255 static void encode_type PARAMS ((tree, int, int));
256 static void encode_field_decl PARAMS ((tree, int, int));
258 static void really_start_method PARAMS ((tree, tree));
259 static int comp_method_with_proto PARAMS ((tree, tree));
260 static int comp_proto_with_proto PARAMS ((tree, tree));
261 static tree get_arg_type_list PARAMS ((tree, int, int));
262 static tree expr_last PARAMS ((tree));
264 /* Utilities for debugging and error diagnostics. */
266 static void warn_with_method PARAMS ((const char *, int, tree));
267 static void error_with_ivar PARAMS ((const char *, tree, tree));
268 static char *gen_method_decl PARAMS ((tree, char *));
269 static char *gen_declaration PARAMS ((tree, char *));
270 static void gen_declaration_1 PARAMS ((tree, char *));
271 static char *gen_declarator PARAMS ((tree, char *,
272 const char *));
273 static int is_complex_decl PARAMS ((tree));
274 static void adorn_decl PARAMS ((tree, char *));
275 static void dump_interface PARAMS ((FILE *, tree));
277 /* Everything else. */
279 static tree define_decl PARAMS ((tree, tree));
280 static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int));
281 static tree lookup_protocol_in_reflist PARAMS ((tree, tree));
282 static tree create_builtin_decl PARAMS ((enum tree_code,
283 tree, const char *));
284 static void setup_string_decl PARAMS ((void));
285 static tree my_build_string PARAMS ((int, const char *));
286 static void build_objc_symtab_template PARAMS ((void));
287 static tree init_def_list PARAMS ((tree));
288 static tree init_objc_symtab PARAMS ((tree));
289 static void forward_declare_categories PARAMS ((void));
290 static void generate_objc_symtab_decl PARAMS ((void));
291 static tree build_selector PARAMS ((tree));
292 static tree build_typed_selector_reference PARAMS ((tree, tree));
293 static tree build_selector_reference PARAMS ((tree));
294 static tree build_class_reference_decl PARAMS ((void));
295 static void add_class_reference PARAMS ((tree));
296 static tree objc_copy_list PARAMS ((tree, tree *));
297 static tree build_protocol_template PARAMS ((void));
298 static tree build_descriptor_table_initializer PARAMS ((tree, tree));
299 static tree build_method_prototype_list_template PARAMS ((tree, int));
300 static tree build_method_prototype_template PARAMS ((void));
301 static int forwarding_offset PARAMS ((tree));
302 static tree encode_method_prototype PARAMS ((tree, tree));
303 static tree generate_descriptor_table PARAMS ((tree, const char *,
304 int, tree, tree));
305 static void generate_method_descriptors PARAMS ((tree));
306 static tree build_tmp_function_decl PARAMS ((void));
307 static void hack_method_prototype PARAMS ((tree, tree));
308 static void generate_protocol_references PARAMS ((tree));
309 static void generate_protocols PARAMS ((void));
310 static void check_ivars PARAMS ((tree, tree));
311 static tree build_ivar_list_template PARAMS ((tree, int));
312 static tree build_method_list_template PARAMS ((tree, int));
313 static tree build_ivar_list_initializer PARAMS ((tree, tree));
314 static tree generate_ivars_list PARAMS ((tree, const char *,
315 int, tree));
316 static tree build_dispatch_table_initializer PARAMS ((tree, tree));
317 static tree generate_dispatch_table PARAMS ((tree, const char *,
318 int, tree));
319 static tree build_shared_structure_initializer PARAMS ((tree, tree, tree, tree,
320 tree, int, tree, tree,
321 tree));
322 static void generate_category PARAMS ((tree));
323 static int is_objc_type_qualifier PARAMS ((tree));
324 static tree adjust_type_for_id_default PARAMS ((tree));
325 static tree check_duplicates PARAMS ((hash));
326 static tree receiver_is_class_object PARAMS ((tree));
327 static int check_methods PARAMS ((tree, tree, int));
328 static int conforms_to_protocol PARAMS ((tree, tree));
329 static void check_protocol PARAMS ((tree, const char *,
330 const char *));
331 static void check_protocols PARAMS ((tree, const char *,
332 const char *));
333 static tree encode_method_def PARAMS ((tree));
334 static void gen_declspecs PARAMS ((tree, char *, int));
335 static void generate_classref_translation_entry PARAMS ((tree));
336 static void handle_class_ref PARAMS ((tree));
337 static void generate_struct_by_value_array PARAMS ((void))
338 ATTRIBUTE_NORETURN;
339 static void objc_act_parse_init PARAMS ((void));
340 static void ggc_mark_imp_list PARAMS ((void *));
341 static void ggc_mark_hash_table PARAMS ((void *));
343 /*** Private Interface (data) ***/
345 /* Reserved tag definitions. */
347 #define TYPE_ID "id"
348 #define TAG_OBJECT "objc_object"
349 #define TAG_CLASS "objc_class"
350 #define TAG_SUPER "objc_super"
351 #define TAG_SELECTOR "objc_selector"
353 #define UTAG_CLASS "_objc_class"
354 #define UTAG_IVAR "_objc_ivar"
355 #define UTAG_IVAR_LIST "_objc_ivar_list"
356 #define UTAG_METHOD "_objc_method"
357 #define UTAG_METHOD_LIST "_objc_method_list"
358 #define UTAG_CATEGORY "_objc_category"
359 #define UTAG_MODULE "_objc_module"
360 #define UTAG_STATICS "_objc_statics"
361 #define UTAG_SYMTAB "_objc_symtab"
362 #define UTAG_SUPER "_objc_super"
363 #define UTAG_SELECTOR "_objc_selector"
365 #define UTAG_PROTOCOL "_objc_protocol"
366 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
367 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
368 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
370 #ifdef NEXT_OBJC_RUNTIME
371 #define STRING_OBJECT_CLASS_NAME "NSConstantString"
372 #else
373 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
374 #endif
375 /* Note that the string object global name is only needed for the
376 NeXT runtime. */
377 #define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
379 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
381 static const char *constant_string_class_name = NULL;
383 static const char *TAG_GETCLASS;
384 static const char *TAG_GETMETACLASS;
385 static const char *TAG_MSGSEND;
386 static const char *TAG_MSGSENDSUPER;
387 static const char *TAG_EXECCLASS;
389 /* The OCTI_... enumeration itself in in objc/objc-act.h. */
390 tree objc_global_trees[OCTI_MAX];
392 int objc_receiver_context;
394 static void handle_impent PARAMS ((struct imp_entry *));
396 struct imp_entry *imp_list = 0;
397 int imp_count = 0; /* `@implementation' */
398 int cat_count = 0; /* `@category' */
400 static int method_slot = 0; /* Used by start_method_def, */
402 #define BUFSIZE 1024
404 static char *errbuf; /* Buffer for error diagnostics */
406 /* Data imported from tree.c. */
408 extern enum debug_info_type write_symbols;
410 /* Data imported from toplev.c. */
412 extern const char *dump_base_name;
414 /* Generate code for GNU or NeXT runtime environment. */
416 #ifdef NEXT_OBJC_RUNTIME
417 int flag_next_runtime = 1;
418 #else
419 int flag_next_runtime = 0;
420 #endif
422 int flag_typed_selectors;
424 /* Open and close the file for outputting class declarations, if requested. */
426 int flag_gen_declaration = 0;
428 FILE *gen_declaration_file;
430 /* Warn if multiple methods are seen for the same selector, but with
431 different argument types. */
433 int warn_selector = 0;
435 /* Warn if methods required by a protocol are not implemented in the
436 class adopting it. When turned off, methods inherited to that
437 class are also considered implemented */
439 int flag_warn_protocol = 1;
441 /* Tells "encode_pointer/encode_aggregate" whether we are generating
442 type descriptors for instance variables (as opposed to methods).
443 Type descriptors for instance variables contain more information
444 than methods (for static typing and embedded structures). This
445 was added to support features being planned for dbkit2. */
447 static int generating_instance_variables = 0;
449 /* Tells the compiler that this is a special run. Do not perform
450 any compiling, instead we are to test some platform dependent
451 features and output a C header file with appropriate definitions. */
453 static int print_struct_values = 0;
455 #undef LANG_HOOKS_NAME
456 #define LANG_HOOKS_NAME "GNU Objective-C"
457 #undef LANG_HOOKS_INIT
458 #define LANG_HOOKS_INIT objc_init
459 #undef LANG_HOOKS_FINISH
460 #define LANG_HOOKS_FINISH c_common_finish
461 #undef LANG_HOOKS_INIT_OPTIONS
462 #define LANG_HOOKS_INIT_OPTIONS objc_init_options
463 #undef LANG_HOOKS_DECODE_OPTION
464 #define LANG_HOOKS_DECODE_OPTION objc_decode_option
465 #undef LANG_HOOKS_POST_OPTIONS
466 #define LANG_HOOKS_POST_OPTIONS objc_post_options
467 #undef LANG_HOOKS_PRINT_IDENTIFIER
468 #define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
469 #undef LANG_HOOKS_SET_YYDEBUG
470 #define LANG_HOOKS_SET_YYDEBUG c_set_yydebug
471 /* Inlining hooks same as the C front end. */
472 #undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
473 #define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
474 c_cannot_inline_tree_fn
475 #undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
476 #define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
477 c_disregard_inline_limits
478 #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
479 #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
480 anon_aggr_type_p
482 /* Each front end provides its own. */
483 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
485 static varray_type deferred_fns;
487 /* Post-switch processing. */
488 static void
489 objc_post_options ()
491 c_common_post_options ();
494 /* Some platforms pass small structures through registers versus through
495 an invisible pointer. Determine at what size structure is the
496 transition point between the two possibilities. */
498 static void
499 generate_struct_by_value_array ()
501 tree type;
502 tree field_decl, field_decl_chain;
503 int i, j;
504 int aggregate_in_mem[32];
505 int found = 0;
507 /* Presumably no platform passes 32 byte structures in a register. */
508 for (i = 1; i < 32; i++)
510 char buffer[5];
512 /* Create an unnamed struct that has `i' character components */
513 type = start_struct (RECORD_TYPE, NULL_TREE);
515 strcpy (buffer, "c1");
516 field_decl = create_builtin_decl (FIELD_DECL,
517 char_type_node,
518 buffer);
519 field_decl_chain = field_decl;
521 for (j = 1; j < i; j++)
523 sprintf (buffer, "c%d", j + 1);
524 field_decl = create_builtin_decl (FIELD_DECL,
525 char_type_node,
526 buffer);
527 chainon (field_decl_chain, field_decl);
529 finish_struct (type, field_decl_chain, NULL_TREE);
531 aggregate_in_mem[i] = aggregate_value_p (type);
532 if (!aggregate_in_mem[i])
533 found = 1;
536 /* We found some structures that are returned in registers instead of memory
537 so output the necessary data. */
538 if (found)
540 for (i = 31; i >= 0; i--)
541 if (!aggregate_in_mem[i])
542 break;
543 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
545 /* The first member of the structure is always 0 because we don't handle
546 structures with 0 members */
547 printf ("static int struct_forward_array[] = {\n 0");
549 for (j = 1; j <= i; j++)
550 printf (", %d", aggregate_in_mem[j]);
551 printf ("\n};\n");
554 exit (0);
557 static void
558 objc_init_options ()
560 c_common_init_options (clk_objective_c);
563 static const char *
564 objc_init (filename)
565 const char *filename;
567 filename = c_objc_common_init (filename);
569 decl_printable_name = objc_printable_name;
571 /* Force the line number back to 0; check_newline will have
572 raised it to 1, which will make the builtin functions appear
573 not to be built in. */
574 lineno = 0;
576 /* If gen_declaration desired, open the output file. */
577 if (flag_gen_declaration)
579 register char * const dumpname = concat (dump_base_name, ".decl", NULL);
580 gen_declaration_file = fopen (dumpname, "w");
581 if (gen_declaration_file == 0)
582 fatal_io_error ("can't open %s", dumpname);
583 free (dumpname);
586 if (flag_next_runtime)
588 TAG_GETCLASS = "objc_getClass";
589 TAG_GETMETACLASS = "objc_getMetaClass";
590 TAG_MSGSEND = "objc_msgSend";
591 TAG_MSGSENDSUPER = "objc_msgSendSuper";
592 TAG_EXECCLASS = "__objc_execClass";
594 else
596 TAG_GETCLASS = "objc_get_class";
597 TAG_GETMETACLASS = "objc_get_meta_class";
598 TAG_MSGSEND = "objc_msg_lookup";
599 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
600 TAG_EXECCLASS = "__objc_exec_class";
601 flag_typed_selectors = 1;
604 objc_ellipsis_node = make_node (ERROR_MARK);
606 init_objc ();
608 if (print_struct_values)
609 generate_struct_by_value_array ();
611 objc_act_parse_init ();
613 VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
614 ggc_add_tree_varray_root (&deferred_fns, 1);
616 return filename;
619 /* Register a function tree, so that its optimization and conversion
620 to RTL is only done at the end of the compilation. */
623 defer_fn (fn)
624 tree fn;
626 VARRAY_PUSH_TREE (deferred_fns, fn);
628 return 1;
631 void
632 finish_file ()
634 size_t i;
636 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++)
637 /* Don't output the same function twice. We may run into such
638 situations when an extern inline function is later given a
639 non-extern-inline definition. */
640 if (! TREE_ASM_WRITTEN (VARRAY_TREE (deferred_fns, i)))
641 c_expand_deferred_function (VARRAY_TREE (deferred_fns, i));
642 VARRAY_FREE (deferred_fns);
644 finish_objc (); /* Objective-C finalization */
646 if (gen_declaration_file)
647 fclose (gen_declaration_file);
650 static int
651 objc_decode_option (argc, argv)
652 int argc;
653 char **argv;
655 const char *p = argv[0];
657 if (!strcmp (p, "-gen-decls"))
658 flag_gen_declaration = 1;
659 else if (!strcmp (p, "-Wselector"))
660 warn_selector = 1;
661 else if (!strcmp (p, "-Wno-selector"))
662 warn_selector = 0;
663 else if (!strcmp (p, "-Wprotocol"))
664 flag_warn_protocol = 1;
665 else if (!strcmp (p, "-Wno-protocol"))
666 flag_warn_protocol = 0;
667 else if (!strcmp (p, "-fgnu-runtime"))
668 flag_next_runtime = 0;
669 else if (!strcmp (p, "-fno-next-runtime"))
670 flag_next_runtime = 0;
671 else if (!strcmp (p, "-fno-gnu-runtime"))
672 flag_next_runtime = 1;
673 else if (!strcmp (p, "-fnext-runtime"))
674 flag_next_runtime = 1;
675 else if (!strcmp (p, "-print-objc-runtime-info"))
676 print_struct_values = 1;
677 #define CSTSTRCLASS "-fconstant-string-class="
678 else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
679 if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
680 error ("no class name specified as argument to -fconstant-string-class");
681 constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
683 #undef CSTSTRCLASS
684 else
685 return c_decode_option (argc, argv);
687 return 1;
691 static tree
692 define_decl (declarator, declspecs)
693 tree declarator;
694 tree declspecs;
696 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
697 finish_decl (decl, NULL_TREE, NULL_TREE);
698 return decl;
701 /* Return 1 if LHS and RHS are compatible types for assignment or
702 various other operations. Return 0 if they are incompatible, and
703 return -1 if we choose to not decide. When the operation is
704 REFLEXIVE, check for compatibility in either direction.
706 For statically typed objects, an assignment of the form `a' = `b'
707 is permitted if:
709 `a' is of type "id",
710 `a' and `b' are the same class type, or
711 `a' and `b' are of class types A and B such that B is a descendant of A. */
714 maybe_objc_comptypes (lhs, rhs, reflexive)
715 tree lhs, rhs;
716 int reflexive;
718 return objc_comptypes (lhs, rhs, reflexive);
721 static tree
722 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
723 tree rproto_list;
724 tree sel_name;
725 int class_meth;
727 tree rproto, p;
728 tree fnd = 0;
730 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
732 p = TREE_VALUE (rproto);
734 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
736 if ((fnd = lookup_method (class_meth
737 ? PROTOCOL_CLS_METHODS (p)
738 : PROTOCOL_NST_METHODS (p), sel_name)))
740 else if (PROTOCOL_LIST (p))
741 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
742 sel_name, class_meth);
744 else
746 ; /* An identifier...if we could not find a protocol. */
749 if (fnd)
750 return fnd;
753 return 0;
756 static tree
757 lookup_protocol_in_reflist (rproto_list, lproto)
758 tree rproto_list;
759 tree lproto;
761 tree rproto, p;
763 /* Make sure the protocol is supported by the object on the rhs. */
764 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
766 tree fnd = 0;
767 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
769 p = TREE_VALUE (rproto);
771 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
773 if (lproto == p)
774 fnd = lproto;
776 else if (PROTOCOL_LIST (p))
777 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
780 if (fnd)
781 return fnd;
784 else
786 ; /* An identifier...if we could not find a protocol. */
789 return 0;
792 /* Return 1 if LHS and RHS are compatible types for assignment
793 or various other operations. Return 0 if they are incompatible,
794 and return -1 if we choose to not decide. When the operation
795 is REFLEXIVE, check for compatibility in either direction. */
798 objc_comptypes (lhs, rhs, reflexive)
799 tree lhs;
800 tree rhs;
801 int reflexive;
803 /* New clause for protocols. */
805 if (TREE_CODE (lhs) == POINTER_TYPE
806 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
807 && TREE_CODE (rhs) == POINTER_TYPE
808 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
810 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
811 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
813 if (lhs_is_proto)
815 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
816 tree rproto, rproto_list;
817 tree p;
819 if (rhs_is_proto)
821 rproto_list = TYPE_PROTOCOL_LIST (rhs);
823 /* Make sure the protocol is supported by the object
824 on the rhs. */
825 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
827 p = TREE_VALUE (lproto);
828 rproto = lookup_protocol_in_reflist (rproto_list, p);
830 if (!rproto)
831 warning ("object does not conform to the `%s' protocol",
832 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
835 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
837 tree rname = TYPE_NAME (TREE_TYPE (rhs));
838 tree rinter;
840 /* Make sure the protocol is supported by the object
841 on the rhs. */
842 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
844 p = TREE_VALUE (lproto);
845 rproto = 0;
846 rinter = lookup_interface (rname);
848 while (rinter && !rproto)
850 tree cat;
852 rproto_list = CLASS_PROTOCOL_LIST (rinter);
853 /* If the underlying ObjC class does not have
854 protocols attached to it, perhaps there are
855 "one-off" protocols attached to the rhs?
856 E.g., 'id<MyProt> foo;'. */
857 if (!rproto_list)
858 rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
859 rproto = lookup_protocol_in_reflist (rproto_list, p);
861 /* Check for protocols adopted by categories. */
862 cat = CLASS_CATEGORY_LIST (rinter);
863 while (cat && !rproto)
865 rproto_list = CLASS_PROTOCOL_LIST (cat);
866 rproto = lookup_protocol_in_reflist (rproto_list, p);
868 cat = CLASS_CATEGORY_LIST (cat);
871 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
874 if (!rproto)
875 warning ("class `%s' does not implement the `%s' protocol",
876 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
877 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
881 /* May change...based on whether there was any mismatch */
882 return 1;
884 else if (rhs_is_proto)
885 /* Lhs is not a protocol...warn if it is statically typed */
886 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
888 else
889 /* Defer to comptypes. */
890 return -1;
893 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
894 ; /* Fall thru. This is the case we have been handling all along */
895 else
896 /* Defer to comptypes. */
897 return -1;
899 /* `id' = `<class> *', `<class> *' = `id' */
901 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
902 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
903 return 1;
905 /* `id' = `Class', `Class' = `id' */
907 else if ((TYPE_NAME (lhs) == objc_object_id
908 && TYPE_NAME (rhs) == objc_class_id)
909 || (TYPE_NAME (lhs) == objc_class_id
910 && TYPE_NAME (rhs) == objc_object_id))
911 return 1;
913 /* `<class> *' = `<class> *' */
915 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
917 tree lname = TYPE_NAME (lhs);
918 tree rname = TYPE_NAME (rhs);
919 tree inter;
921 if (lname == rname)
922 return 1;
924 /* If the left hand side is a super class of the right hand side,
925 allow it. */
926 for (inter = lookup_interface (rname); inter;
927 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
928 if (lname == CLASS_SUPER_NAME (inter))
929 return 1;
931 /* Allow the reverse when reflexive. */
932 if (reflexive)
933 for (inter = lookup_interface (lname); inter;
934 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
935 if (rname == CLASS_SUPER_NAME (inter))
936 return 1;
938 return 0;
940 else
941 /* Defer to comptypes. */
942 return -1;
945 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
947 void
948 objc_check_decl (decl)
949 tree decl;
951 tree type = TREE_TYPE (decl);
953 if (TREE_CODE (type) == RECORD_TYPE
954 && TREE_STATIC_TEMPLATE (type)
955 && type != constant_string_type)
956 error_with_decl (decl, "`%s' cannot be statically allocated");
959 void
960 maybe_objc_check_decl (decl)
961 tree decl;
963 objc_check_decl (decl);
966 /* Implement static typing. At this point, we know we have an interface. */
968 tree
969 get_static_reference (interface, protocols)
970 tree interface;
971 tree protocols;
973 tree type = xref_tag (RECORD_TYPE, interface);
975 if (protocols)
977 tree t, m = TYPE_MAIN_VARIANT (type);
979 t = copy_node (type);
980 TYPE_BINFO (t) = make_tree_vec (2);
982 /* Add this type to the chain of variants of TYPE. */
983 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
984 TYPE_NEXT_VARIANT (m) = t;
986 /* Look up protocols and install in lang specific list. Note
987 that the protocol list can have a different lifetime than T! */
988 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
990 /* This forces a new pointer type to be created later
991 (in build_pointer_type)...so that the new template
992 we just created will actually be used...what a hack! */
993 if (TYPE_POINTER_TO (t))
994 TYPE_POINTER_TO (t) = NULL_TREE;
996 type = t;
999 return type;
1002 tree
1003 get_object_reference (protocols)
1004 tree protocols;
1006 tree type_decl = lookup_name (objc_id_id);
1007 tree type;
1009 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1011 type = TREE_TYPE (type_decl);
1012 if (TYPE_MAIN_VARIANT (type) != id_type)
1013 warning ("unexpected type for `id' (%s)",
1014 gen_declaration (type, errbuf));
1016 else
1018 error ("undefined type `id', please import <objc/objc.h>");
1019 return error_mark_node;
1022 /* This clause creates a new pointer type that is qualified with
1023 the protocol specification...this info is used later to do more
1024 elaborate type checking. */
1026 if (protocols)
1028 tree t, m = TYPE_MAIN_VARIANT (type);
1030 t = copy_node (type);
1031 TYPE_BINFO (t) = make_tree_vec (2);
1033 /* Add this type to the chain of variants of TYPE. */
1034 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1035 TYPE_NEXT_VARIANT (m) = t;
1037 /* Look up protocols...and install in lang specific list */
1038 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1040 /* This forces a new pointer type to be created later
1041 (in build_pointer_type)...so that the new template
1042 we just created will actually be used...what a hack! */
1043 if (TYPE_POINTER_TO (t))
1044 TYPE_POINTER_TO (t) = NULL_TREE;
1046 type = t;
1048 return type;
1051 /* Check for circular dependencies in protocols. The arguments are
1052 PROTO, the protocol to check, and LIST, a list of protocol it
1053 conforms to. */
1055 static void
1056 check_protocol_recursively (proto, list)
1057 tree proto;
1058 tree list;
1060 tree p;
1062 for (p = list; p; p = TREE_CHAIN (p))
1064 tree pp = TREE_VALUE (p);
1066 if (TREE_CODE (pp) == IDENTIFIER_NODE)
1067 pp = lookup_protocol (pp);
1069 if (pp == proto)
1070 fatal_error ("protocol `%s' has circular dependency",
1071 IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1072 if (pp)
1073 check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1077 static tree
1078 lookup_and_install_protocols (protocols)
1079 tree protocols;
1081 tree proto;
1082 tree prev = NULL;
1083 tree return_value = protocols;
1085 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1087 tree ident = TREE_VALUE (proto);
1088 tree p = lookup_protocol (ident);
1090 if (!p)
1092 error ("cannot find protocol declaration for `%s'",
1093 IDENTIFIER_POINTER (ident));
1094 if (prev)
1095 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1096 else
1097 return_value = TREE_CHAIN (proto);
1099 else
1101 /* Replace identifier with actual protocol node. */
1102 TREE_VALUE (proto) = p;
1103 prev = proto;
1107 return return_value;
1110 /* Create and push a decl for a built-in external variable or field NAME.
1111 CODE says which.
1112 TYPE is its data type. */
1114 static tree
1115 create_builtin_decl (code, type, name)
1116 enum tree_code code;
1117 tree type;
1118 const char *name;
1120 tree decl = build_decl (code, get_identifier (name), type);
1122 if (code == VAR_DECL)
1124 TREE_STATIC (decl) = 1;
1125 make_decl_rtl (decl, 0);
1126 pushdecl (decl);
1129 DECL_ARTIFICIAL (decl) = 1;
1130 return decl;
1133 /* Find the decl for the constant string class. */
1135 static void
1136 setup_string_decl ()
1138 if (!string_class_decl)
1140 if (!constant_string_global_id)
1141 constant_string_global_id = get_identifier (STRING_OBJECT_GLOBAL_NAME);
1142 string_class_decl = lookup_name (constant_string_global_id);
1146 /* Purpose: "play" parser, creating/installing representations
1147 of the declarations that are required by Objective-C.
1149 Model:
1151 type_spec--------->sc_spec
1152 (tree_list) (tree_list)
1155 identifier_node identifier_node */
1157 static void
1158 synth_module_prologue ()
1160 tree temp_type;
1161 tree super_p;
1163 /* Defined in `objc.h' */
1164 objc_object_id = get_identifier (TAG_OBJECT);
1166 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1168 id_type = build_pointer_type (objc_object_reference);
1170 objc_id_id = get_identifier (TYPE_ID);
1171 objc_class_id = get_identifier (TAG_CLASS);
1173 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1174 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1175 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1177 /* Declare type of selector-objects that represent an operation name. */
1179 /* `struct objc_selector *' */
1180 selector_type
1181 = build_pointer_type (xref_tag (RECORD_TYPE,
1182 get_identifier (TAG_SELECTOR)));
1184 /* Forward declare type, or else the prototype for msgSendSuper will
1185 complain. */
1187 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1188 get_identifier (TAG_SUPER)));
1191 /* id objc_msgSend (id, SEL, ...); */
1193 temp_type
1194 = build_function_type (id_type,
1195 tree_cons (NULL_TREE, id_type,
1196 tree_cons (NULL_TREE, selector_type,
1197 NULL_TREE)));
1199 if (! flag_next_runtime)
1201 umsg_decl = build_decl (FUNCTION_DECL,
1202 get_identifier (TAG_MSGSEND), temp_type);
1203 DECL_EXTERNAL (umsg_decl) = 1;
1204 TREE_PUBLIC (umsg_decl) = 1;
1205 DECL_INLINE (umsg_decl) = 1;
1206 DECL_ARTIFICIAL (umsg_decl) = 1;
1208 if (flag_traditional && TAG_MSGSEND[0] != '_')
1209 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1211 make_decl_rtl (umsg_decl, NULL);
1212 pushdecl (umsg_decl);
1214 else
1215 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
1217 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1219 temp_type
1220 = build_function_type (id_type,
1221 tree_cons (NULL_TREE, super_p,
1222 tree_cons (NULL_TREE, selector_type,
1223 NULL_TREE)));
1225 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1226 temp_type, 0, NOT_BUILT_IN, 0);
1228 /* id objc_getClass (const char *); */
1230 temp_type = build_function_type (id_type,
1231 tree_cons (NULL_TREE,
1232 const_string_type_node,
1233 tree_cons (NULL_TREE, void_type_node,
1234 NULL_TREE)));
1236 objc_get_class_decl
1237 = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
1239 /* id objc_getMetaClass (const char *); */
1241 objc_get_meta_class_decl
1242 = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
1244 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1246 if (! flag_next_runtime)
1248 if (flag_typed_selectors)
1250 /* Suppress outputting debug symbols, because
1251 dbxout_init hasn'r been called yet. */
1252 enum debug_info_type save_write_symbols = write_symbols;
1253 struct gcc_debug_hooks *save_hooks = debug_hooks;
1254 write_symbols = NO_DEBUG;
1255 debug_hooks = &do_nothing_debug_hooks;
1257 build_selector_template ();
1258 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1260 write_symbols = save_write_symbols;
1261 debug_hooks = save_hooks;
1263 else
1264 temp_type = build_array_type (selector_type, NULL_TREE);
1266 layout_type (temp_type);
1267 UOBJC_SELECTOR_TABLE_decl
1268 = create_builtin_decl (VAR_DECL, temp_type,
1269 "_OBJC_SELECTOR_TABLE");
1271 /* Avoid warning when not sending messages. */
1272 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1275 generate_forward_declaration_to_string_table ();
1277 /* Forward declare constant_string_id and constant_string_type. */
1278 if (!constant_string_class_name)
1279 constant_string_class_name = STRING_OBJECT_CLASS_NAME;
1281 constant_string_id = get_identifier (constant_string_class_name);
1282 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1285 /* Custom build_string which sets TREE_TYPE! */
1287 static tree
1288 my_build_string (len, str)
1289 int len;
1290 const char *str;
1292 int wide_flag = 0;
1293 tree a_string = build_string (len, str);
1295 /* Some code from combine_strings, which is local to c-parse.y. */
1296 if (TREE_TYPE (a_string) == int_array_type_node)
1297 wide_flag = 1;
1299 TREE_TYPE (a_string)
1300 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1301 build_index_type (build_int_2 (len - 1, 0)));
1303 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1304 TREE_STATIC (a_string) = 1;
1306 return a_string;
1309 /* Given a chain of STRING_CST's, build a static instance of
1310 NXConstantString which points at the concatenation of those strings.
1311 We place the string object in the __string_objects section of the
1312 __OBJC segment. The Objective-C runtime will initialize the isa
1313 pointers of the string objects to point at the NXConstantString
1314 class object. */
1316 tree
1317 build_objc_string_object (strings)
1318 tree strings;
1320 tree string, initlist, constructor;
1321 int length;
1323 if (lookup_interface (constant_string_id) == NULL_TREE)
1325 error ("cannot find interface declaration for `%s'",
1326 IDENTIFIER_POINTER (constant_string_id));
1327 return error_mark_node;
1330 add_class_reference (constant_string_id);
1332 string = combine_strings (strings);
1333 TREE_SET_CODE (string, STRING_CST);
1334 length = TREE_STRING_LENGTH (string) - 1;
1336 /* & ((NXConstantString) {0, string, length}) */
1338 if (flag_next_runtime)
1340 /* For the NeXT runtime, we can generate a literal reference
1341 to the string class, don't need to run a constructor. */
1342 setup_string_decl ();
1343 if (string_class_decl == NULL_TREE)
1345 error ("cannot find reference tag for class `%s'",
1346 IDENTIFIER_POINTER (constant_string_id));
1347 return error_mark_node;
1349 initlist = build_tree_list
1350 (NULL_TREE,
1351 copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
1353 else
1355 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1358 initlist
1359 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1360 initlist);
1361 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1362 constructor = build_constructor (constant_string_type, nreverse (initlist));
1364 if (!flag_next_runtime)
1366 constructor
1367 = objc_add_static_instance (constructor, constant_string_type);
1370 return (build_unary_op (ADDR_EXPR, constructor, 1));
1373 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1375 static tree
1376 objc_add_static_instance (constructor, class_decl)
1377 tree constructor, class_decl;
1379 static int num_static_inst;
1380 tree *chain, decl;
1381 char buf[256];
1383 /* Find the list of static instances for the CLASS_DECL. Create one if
1384 not found. */
1385 for (chain = &objc_static_instances;
1386 *chain && TREE_VALUE (*chain) != class_decl;
1387 chain = &TREE_CHAIN (*chain));
1388 if (!*chain)
1390 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1391 add_objc_string (TYPE_NAME (class_decl), class_names);
1394 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1395 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1396 DECL_COMMON (decl) = 1;
1397 TREE_STATIC (decl) = 1;
1398 DECL_ARTIFICIAL (decl) = 1;
1399 DECL_INITIAL (decl) = constructor;
1401 /* We may be writing something else just now.
1402 Postpone till end of input. */
1403 DECL_DEFER_OUTPUT (decl) = 1;
1404 pushdecl_top_level (decl);
1405 rest_of_decl_compilation (decl, 0, 1, 0);
1407 /* Add the DECL to the head of this CLASS' list. */
1408 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1410 return decl;
1413 /* Build a static constant CONSTRUCTOR
1414 with type TYPE and elements ELTS. */
1416 static tree
1417 build_constructor (type, elts)
1418 tree type, elts;
1420 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1422 TREE_CONSTANT (constructor) = 1;
1423 TREE_STATIC (constructor) = 1;
1424 TREE_READONLY (constructor) = 1;
1426 return constructor;
1429 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1431 /* Predefine the following data type:
1433 struct _objc_symtab
1435 long sel_ref_cnt;
1436 SEL *refs;
1437 short cls_def_cnt;
1438 short cat_def_cnt;
1439 void *defs[cls_def_cnt + cat_def_cnt];
1440 }; */
1442 static void
1443 build_objc_symtab_template ()
1445 tree field_decl, field_decl_chain, index;
1447 objc_symtab_template
1448 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1450 /* long sel_ref_cnt; */
1452 field_decl = create_builtin_decl (FIELD_DECL,
1453 long_integer_type_node,
1454 "sel_ref_cnt");
1455 field_decl_chain = field_decl;
1457 /* SEL *refs; */
1459 field_decl = create_builtin_decl (FIELD_DECL,
1460 build_pointer_type (selector_type),
1461 "refs");
1462 chainon (field_decl_chain, field_decl);
1464 /* short cls_def_cnt; */
1466 field_decl = create_builtin_decl (FIELD_DECL,
1467 short_integer_type_node,
1468 "cls_def_cnt");
1469 chainon (field_decl_chain, field_decl);
1471 /* short cat_def_cnt; */
1473 field_decl = create_builtin_decl (FIELD_DECL,
1474 short_integer_type_node,
1475 "cat_def_cnt");
1476 chainon (field_decl_chain, field_decl);
1478 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1480 if (!flag_next_runtime)
1481 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1482 else
1483 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1484 imp_count == 0 && cat_count == 0
1485 ? -1 : 0));
1486 field_decl = create_builtin_decl (FIELD_DECL,
1487 build_array_type (ptr_type_node, index),
1488 "defs");
1489 chainon (field_decl_chain, field_decl);
1491 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1494 /* Create the initial value for the `defs' field of _objc_symtab.
1495 This is a CONSTRUCTOR. */
1497 static tree
1498 init_def_list (type)
1499 tree type;
1501 tree expr, initlist = NULL_TREE;
1502 struct imp_entry *impent;
1504 if (imp_count)
1505 for (impent = imp_list; impent; impent = impent->next)
1507 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1509 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1510 initlist = tree_cons (NULL_TREE, expr, initlist);
1514 if (cat_count)
1515 for (impent = imp_list; impent; impent = impent->next)
1517 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1519 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1520 initlist = tree_cons (NULL_TREE, expr, initlist);
1524 if (!flag_next_runtime)
1526 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1527 tree expr;
1529 if (static_instances_decl)
1530 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1531 else
1532 expr = build_int_2 (0, 0);
1534 initlist = tree_cons (NULL_TREE, expr, initlist);
1537 return build_constructor (type, nreverse (initlist));
1540 /* Construct the initial value for all of _objc_symtab. */
1542 static tree
1543 init_objc_symtab (type)
1544 tree type;
1546 tree initlist;
1548 /* sel_ref_cnt = { ..., 5, ... } */
1550 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1552 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1554 if (flag_next_runtime || ! sel_ref_chain)
1555 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1556 else
1557 initlist = tree_cons (NULL_TREE,
1558 build_unary_op (ADDR_EXPR,
1559 UOBJC_SELECTOR_TABLE_decl, 1),
1560 initlist);
1562 /* cls_def_cnt = { ..., 5, ... } */
1564 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1566 /* cat_def_cnt = { ..., 5, ... } */
1568 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1570 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1572 if (imp_count || cat_count || static_instances_decl)
1575 tree field = TYPE_FIELDS (type);
1576 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1578 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1579 initlist);
1582 return build_constructor (type, nreverse (initlist));
1585 /* Push forward-declarations of all the categories
1586 so that init_def_list can use them in a CONSTRUCTOR. */
1588 static void
1589 forward_declare_categories ()
1591 struct imp_entry *impent;
1592 tree sav = objc_implementation_context;
1594 for (impent = imp_list; impent; impent = impent->next)
1596 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1598 /* Set an invisible arg to synth_id_with_class_suffix. */
1599 objc_implementation_context = impent->imp_context;
1600 impent->class_decl
1601 = create_builtin_decl (VAR_DECL, objc_category_template,
1602 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", objc_implementation_context)));
1605 objc_implementation_context = sav;
1608 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1609 and initialized appropriately. */
1611 static void
1612 generate_objc_symtab_decl ()
1614 tree sc_spec;
1616 if (!objc_category_template)
1617 build_category_template ();
1619 /* forward declare categories */
1620 if (cat_count)
1621 forward_declare_categories ();
1623 if (!objc_symtab_template)
1624 build_objc_symtab_template ();
1626 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1628 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1629 tree_cons (NULL_TREE,
1630 objc_symtab_template, sc_spec),
1632 NULL_TREE);
1634 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1635 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1636 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1637 finish_decl (UOBJC_SYMBOLS_decl,
1638 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1639 NULL_TREE);
1642 static tree
1643 init_module_descriptor (type)
1644 tree type;
1646 tree initlist, expr;
1648 /* version = { 1, ... } */
1650 expr = build_int_2 (OBJC_VERSION, 0);
1651 initlist = build_tree_list (NULL_TREE, expr);
1653 /* size = { ..., sizeof (struct objc_module), ... } */
1655 expr = size_in_bytes (objc_module_template);
1656 initlist = tree_cons (NULL_TREE, expr, initlist);
1658 /* name = { ..., "foo.m", ... } */
1660 expr = add_objc_string (get_identifier (input_filename), class_names);
1661 initlist = tree_cons (NULL_TREE, expr, initlist);
1663 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1665 if (UOBJC_SYMBOLS_decl)
1666 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1667 else
1668 expr = build_int_2 (0, 0);
1669 initlist = tree_cons (NULL_TREE, expr, initlist);
1671 return build_constructor (type, nreverse (initlist));
1674 /* Write out the data structures to describe Objective C classes defined.
1675 If appropriate, compile and output a setup function to initialize them.
1676 Return a symbol_ref to the function to call to initialize the Objective C
1677 data structures for this file (and perhaps for other files also).
1679 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1681 static rtx
1682 build_module_descriptor ()
1684 tree decl_specs, field_decl, field_decl_chain;
1686 objc_module_template
1687 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1689 /* Long version; */
1691 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1692 field_decl = get_identifier ("version");
1693 field_decl
1694 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1695 field_decl_chain = field_decl;
1697 /* long size; */
1699 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1700 field_decl = get_identifier ("size");
1701 field_decl
1702 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1703 chainon (field_decl_chain, field_decl);
1705 /* char *name; */
1707 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1708 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1709 field_decl
1710 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1711 chainon (field_decl_chain, field_decl);
1713 /* struct objc_symtab *symtab; */
1715 decl_specs = get_identifier (UTAG_SYMTAB);
1716 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1717 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1718 field_decl
1719 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1720 chainon (field_decl_chain, field_decl);
1722 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1724 /* Create an instance of "objc_module". */
1726 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1727 build_tree_list (NULL_TREE,
1728 ridpointers[(int) RID_STATIC]));
1730 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1731 decl_specs, 1, NULL_TREE);
1733 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1734 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1735 DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
1737 finish_decl (UOBJC_MODULES_decl,
1738 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1739 NULL_TREE);
1741 /* Mark the decl to avoid "defined but not used" warning. */
1742 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1744 /* Generate a constructor call for the module descriptor.
1745 This code was generated by reading the grammar rules
1746 of c-parse.in; Therefore, it may not be the most efficient
1747 way of generating the requisite code. */
1749 if (flag_next_runtime)
1750 return NULL_RTX;
1753 tree parms, execclass_decl, decelerator, void_list_node_1;
1754 tree init_function_name, init_function_decl;
1756 /* Declare void __objc_execClass (void *); */
1758 void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1759 execclass_decl = build_decl (FUNCTION_DECL,
1760 get_identifier (TAG_EXECCLASS),
1761 build_function_type (void_type_node,
1762 tree_cons (NULL_TREE, ptr_type_node,
1763 void_list_node_1)));
1764 DECL_EXTERNAL (execclass_decl) = 1;
1765 DECL_ARTIFICIAL (execclass_decl) = 1;
1766 TREE_PUBLIC (execclass_decl) = 1;
1767 pushdecl (execclass_decl);
1768 rest_of_decl_compilation (execclass_decl, 0, 0, 0);
1769 assemble_external (execclass_decl);
1771 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1773 init_function_name = get_file_function_name ('I');
1774 start_function (void_list_node_1,
1775 build_nt (CALL_EXPR, init_function_name,
1776 tree_cons (NULL_TREE, NULL_TREE,
1777 void_list_node_1),
1778 NULL_TREE),
1779 NULL_TREE);
1780 store_parm_decls ();
1782 init_function_decl = current_function_decl;
1783 TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
1784 TREE_USED (init_function_decl) = 1;
1785 current_function_cannot_inline
1786 = "static constructors and destructors cannot be inlined";
1788 parms
1789 = build_tree_list (NULL_TREE,
1790 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1791 decelerator = build_function_call (execclass_decl, parms);
1793 c_expand_expr_stmt (decelerator);
1795 finish_function (0);
1797 return XEXP (DECL_RTL (init_function_decl), 0);
1801 /* extern const char _OBJC_STRINGS[]; */
1803 static void
1804 generate_forward_declaration_to_string_table ()
1806 tree sc_spec, decl_specs, expr_decl;
1808 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1809 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1811 expr_decl
1812 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1814 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1817 /* Return the DECL of the string IDENT in the SECTION. */
1819 static tree
1820 get_objc_string_decl (ident, section)
1821 tree ident;
1822 enum string_section section;
1824 tree chain;
1826 if (section == class_names)
1827 chain = class_names_chain;
1828 else if (section == meth_var_names)
1829 chain = meth_var_names_chain;
1830 else if (section == meth_var_types)
1831 chain = meth_var_types_chain;
1832 else
1833 abort ();
1835 for (; chain != 0; chain = TREE_VALUE (chain))
1836 if (TREE_VALUE (chain) == ident)
1837 return (TREE_PURPOSE (chain));
1839 abort ();
1840 return NULL_TREE;
1843 /* Output references to all statically allocated objects. Return the DECL
1844 for the array built. */
1846 static void
1847 generate_static_references ()
1849 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1850 tree class_name, class, decl, initlist;
1851 tree cl_chain, in_chain, type;
1852 int num_inst, num_class;
1853 char buf[256];
1855 if (flag_next_runtime)
1856 abort ();
1858 for (cl_chain = objc_static_instances, num_class = 0;
1859 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1861 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1862 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1864 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1865 ident = get_identifier (buf);
1867 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1868 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1869 build_tree_list (NULL_TREE,
1870 ridpointers[(int) RID_STATIC]));
1871 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
1872 DECL_CONTEXT (decl) = 0;
1873 DECL_ARTIFICIAL (decl) = 1;
1875 /* Output {class_name, ...}. */
1876 class = TREE_VALUE (cl_chain);
1877 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1878 initlist = build_tree_list (NULL_TREE,
1879 build_unary_op (ADDR_EXPR, class_name, 1));
1881 /* Output {..., instance, ...}. */
1882 for (in_chain = TREE_PURPOSE (cl_chain);
1883 in_chain; in_chain = TREE_CHAIN (in_chain))
1885 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1886 initlist = tree_cons (NULL_TREE, expr, initlist);
1889 /* Output {..., NULL}. */
1890 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1892 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1893 finish_decl (decl, expr, NULL_TREE);
1894 TREE_USED (decl) = 1;
1896 type = build_array_type (build_pointer_type (void_type_node), 0);
1897 decl = build_decl (VAR_DECL, ident, type);
1898 TREE_USED (decl) = 1;
1899 TREE_STATIC (decl) = 1;
1900 decls
1901 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1904 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1905 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1906 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1907 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1908 build_tree_list (NULL_TREE,
1909 ridpointers[(int) RID_STATIC]));
1910 static_instances_decl
1911 = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
1912 TREE_USED (static_instances_decl) = 1;
1913 DECL_CONTEXT (static_instances_decl) = 0;
1914 DECL_ARTIFICIAL (static_instances_decl) = 1;
1915 expr = build_constructor (TREE_TYPE (static_instances_decl),
1916 nreverse (decls));
1917 finish_decl (static_instances_decl, expr, NULL_TREE);
1920 /* Output all strings. */
1922 static void
1923 generate_strings ()
1925 tree sc_spec, decl_specs, expr_decl;
1926 tree chain, string_expr;
1927 tree string, decl;
1929 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1931 string = TREE_VALUE (chain);
1932 decl = TREE_PURPOSE (chain);
1933 sc_spec
1934 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1935 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1936 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1937 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
1938 DECL_CONTEXT (decl) = NULL_TREE;
1939 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1940 IDENTIFIER_POINTER (string));
1941 finish_decl (decl, string_expr, NULL_TREE);
1944 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1946 string = TREE_VALUE (chain);
1947 decl = TREE_PURPOSE (chain);
1948 sc_spec
1949 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1950 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1951 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1952 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
1953 DECL_CONTEXT (decl) = NULL_TREE;
1954 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1955 IDENTIFIER_POINTER (string));
1956 finish_decl (decl, string_expr, NULL_TREE);
1959 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1961 string = TREE_VALUE (chain);
1962 decl = TREE_PURPOSE (chain);
1963 sc_spec
1964 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1965 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1966 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1967 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
1968 DECL_CONTEXT (decl) = NULL_TREE;
1969 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1970 IDENTIFIER_POINTER (string));
1971 finish_decl (decl, string_expr, NULL_TREE);
1975 static tree
1976 build_selector_reference_decl ()
1978 tree decl, ident;
1979 char buf[256];
1980 static int idx = 0;
1982 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
1984 ident = get_identifier (buf);
1986 decl = build_decl (VAR_DECL, ident, selector_type);
1987 DECL_EXTERNAL (decl) = 1;
1988 TREE_PUBLIC (decl) = 1;
1989 TREE_USED (decl) = 1;
1990 TREE_READONLY (decl) = 1;
1991 DECL_ARTIFICIAL (decl) = 1;
1992 DECL_CONTEXT (decl) = 0;
1994 make_decl_rtl (decl, 0);
1995 pushdecl_top_level (decl);
1997 return decl;
2000 /* Just a handy wrapper for add_objc_string. */
2002 static tree
2003 build_selector (ident)
2004 tree ident;
2006 tree expr = add_objc_string (ident, meth_var_names);
2007 if (flag_typed_selectors)
2008 return expr;
2009 else
2010 return build_c_cast (selector_type, expr); /* cast! */
2013 static void
2014 build_selector_translation_table ()
2016 tree sc_spec, decl_specs;
2017 tree chain, initlist = NULL_TREE;
2018 int offset = 0;
2019 tree decl = NULL_TREE, var_decl, name;
2021 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2023 tree expr;
2025 expr = build_selector (TREE_VALUE (chain));
2027 if (flag_next_runtime)
2029 name = DECL_NAME (TREE_PURPOSE (chain));
2031 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2033 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2034 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2036 var_decl = name;
2038 /* The `decl' that is returned from start_decl is the one that we
2039 forward declared in `build_selector_reference' */
2040 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
2043 /* add one for the '\0' character */
2044 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2046 if (flag_next_runtime)
2047 finish_decl (decl, expr, NULL_TREE);
2048 else
2050 if (flag_typed_selectors)
2052 tree eltlist = NULL_TREE;
2053 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2054 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2055 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2056 expr = build_constructor (objc_selector_template,
2057 nreverse (eltlist));
2059 initlist = tree_cons (NULL_TREE, expr, initlist);
2064 if (! flag_next_runtime)
2066 /* Cause the variable and its initial value to be actually output. */
2067 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2068 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2069 /* NULL terminate the list and fix the decl for output. */
2070 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2071 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
2072 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2073 nreverse (initlist));
2074 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2075 current_function_decl = NULL_TREE;
2079 static tree
2080 get_proto_encoding (proto)
2081 tree proto;
2083 tree encoding;
2084 if (proto)
2086 tree tmp_decl;
2088 if (! METHOD_ENCODING (proto))
2090 tmp_decl = build_tmp_function_decl ();
2091 hack_method_prototype (proto, tmp_decl);
2092 encoding = encode_method_prototype (proto, tmp_decl);
2093 METHOD_ENCODING (proto) = encoding;
2095 else
2096 encoding = METHOD_ENCODING (proto);
2098 return add_objc_string (encoding, meth_var_types);
2100 else
2101 return build_int_2 (0, 0);
2104 /* sel_ref_chain is a list whose "value" fields will be instances of
2105 identifier_node that represent the selector. */
2107 static tree
2108 build_typed_selector_reference (ident, proto)
2109 tree ident, proto;
2111 tree *chain = &sel_ref_chain;
2112 tree expr;
2113 int index = 0;
2115 while (*chain)
2117 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2118 goto return_at_index;
2120 index++;
2121 chain = &TREE_CHAIN (*chain);
2124 *chain = tree_cons (proto, ident, NULL_TREE);
2126 return_at_index:
2127 expr = build_unary_op (ADDR_EXPR,
2128 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2129 build_int_2 (index, 0)),
2131 return build_c_cast (selector_type, expr);
2134 static tree
2135 build_selector_reference (ident)
2136 tree ident;
2138 tree *chain = &sel_ref_chain;
2139 tree expr;
2140 int index = 0;
2142 while (*chain)
2144 if (TREE_VALUE (*chain) == ident)
2145 return (flag_next_runtime
2146 ? TREE_PURPOSE (*chain)
2147 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2148 build_int_2 (index, 0)));
2150 index++;
2151 chain = &TREE_CHAIN (*chain);
2154 expr = build_selector_reference_decl ();
2156 *chain = tree_cons (expr, ident, NULL_TREE);
2158 return (flag_next_runtime
2159 ? expr
2160 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2161 build_int_2 (index, 0)));
2164 static tree
2165 build_class_reference_decl ()
2167 tree decl, ident;
2168 char buf[256];
2169 static int idx = 0;
2171 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2173 ident = get_identifier (buf);
2175 decl = build_decl (VAR_DECL, ident, objc_class_type);
2176 DECL_EXTERNAL (decl) = 1;
2177 TREE_PUBLIC (decl) = 1;
2178 TREE_USED (decl) = 1;
2179 TREE_READONLY (decl) = 1;
2180 DECL_CONTEXT (decl) = 0;
2181 DECL_ARTIFICIAL (decl) = 1;
2183 make_decl_rtl (decl, 0);
2184 pushdecl_top_level (decl);
2186 return decl;
2189 /* Create a class reference, but don't create a variable to reference
2190 it. */
2192 static void
2193 add_class_reference (ident)
2194 tree ident;
2196 tree chain;
2198 if ((chain = cls_ref_chain))
2200 tree tail;
2203 if (ident == TREE_VALUE (chain))
2204 return;
2206 tail = chain;
2207 chain = TREE_CHAIN (chain);
2209 while (chain);
2211 /* Append to the end of the list */
2212 TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2214 else
2215 cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2218 /* Get a class reference, creating it if necessary. Also create the
2219 reference variable. */
2221 tree
2222 get_class_reference (ident)
2223 tree ident;
2225 if (flag_next_runtime)
2227 tree *chain;
2228 tree decl;
2230 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2231 if (TREE_VALUE (*chain) == ident)
2233 if (! TREE_PURPOSE (*chain))
2234 TREE_PURPOSE (*chain) = build_class_reference_decl ();
2236 return TREE_PURPOSE (*chain);
2239 decl = build_class_reference_decl ();
2240 *chain = tree_cons (decl, ident, NULL_TREE);
2241 return decl;
2243 else
2245 tree params;
2247 add_class_reference (ident);
2249 params = build_tree_list (NULL_TREE,
2250 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2251 IDENTIFIER_POINTER (ident)));
2253 assemble_external (objc_get_class_decl);
2254 return build_function_call (objc_get_class_decl, params);
2258 /* For each string section we have a chain which maps identifier nodes
2259 to decls for the strings. */
2261 static tree
2262 add_objc_string (ident, section)
2263 tree ident;
2264 enum string_section section;
2266 tree *chain, decl;
2268 if (section == class_names)
2269 chain = &class_names_chain;
2270 else if (section == meth_var_names)
2271 chain = &meth_var_names_chain;
2272 else if (section == meth_var_types)
2273 chain = &meth_var_types_chain;
2274 else
2275 abort ();
2277 while (*chain)
2279 if (TREE_VALUE (*chain) == ident)
2280 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2282 chain = &TREE_CHAIN (*chain);
2285 decl = build_objc_string_decl (section);
2287 *chain = tree_cons (decl, ident, NULL_TREE);
2289 return build_unary_op (ADDR_EXPR, decl, 1);
2292 static tree
2293 build_objc_string_decl (section)
2294 enum string_section section;
2296 tree decl, ident;
2297 char buf[256];
2298 static int class_names_idx = 0;
2299 static int meth_var_names_idx = 0;
2300 static int meth_var_types_idx = 0;
2302 if (section == class_names)
2303 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2304 else if (section == meth_var_names)
2305 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2306 else if (section == meth_var_types)
2307 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2309 ident = get_identifier (buf);
2311 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2312 DECL_EXTERNAL (decl) = 1;
2313 TREE_PUBLIC (decl) = 1;
2314 TREE_USED (decl) = 1;
2315 TREE_READONLY (decl) = 1;
2316 TREE_CONSTANT (decl) = 1;
2317 DECL_CONTEXT (decl) = 0;
2318 DECL_ARTIFICIAL (decl) = 1;
2320 make_decl_rtl (decl, 0);
2321 pushdecl_top_level (decl);
2323 return decl;
2327 void
2328 objc_declare_alias (alias_ident, class_ident)
2329 tree alias_ident;
2330 tree class_ident;
2332 if (is_class_name (class_ident) != class_ident)
2333 warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2334 else if (is_class_name (alias_ident))
2335 warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2336 else
2337 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2340 void
2341 objc_declare_class (ident_list)
2342 tree ident_list;
2344 tree list;
2346 for (list = ident_list; list; list = TREE_CHAIN (list))
2348 tree ident = TREE_VALUE (list);
2349 tree decl;
2351 if ((decl = lookup_name (ident)))
2353 error ("`%s' redeclared as different kind of symbol",
2354 IDENTIFIER_POINTER (ident));
2355 error_with_decl (decl, "previous declaration of `%s'");
2358 if (! is_class_name (ident))
2360 tree record = xref_tag (RECORD_TYPE, ident);
2361 TREE_STATIC_TEMPLATE (record) = 1;
2362 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2367 tree
2368 is_class_name (ident)
2369 tree ident;
2371 tree chain;
2373 if (lookup_interface (ident))
2374 return ident;
2376 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2378 if (ident == TREE_VALUE (chain))
2379 return ident;
2382 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2384 if (ident == TREE_VALUE (chain))
2385 return TREE_PURPOSE (chain);
2388 return 0;
2391 tree
2392 lookup_interface (ident)
2393 tree ident;
2395 tree chain;
2397 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2399 if (ident == CLASS_NAME (chain))
2400 return chain;
2402 return NULL_TREE;
2405 static tree
2406 objc_copy_list (list, head)
2407 tree list;
2408 tree *head;
2410 tree newlist = NULL_TREE, tail = NULL_TREE;
2412 while (list)
2414 tail = copy_node (list);
2416 /* The following statement fixes a bug when inheriting instance
2417 variables that are declared to be bitfields. finish_struct
2418 expects to find the width of the bitfield in DECL_INITIAL. */
2419 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2420 DECL_INITIAL (tail) = DECL_SIZE (tail);
2422 newlist = chainon (newlist, tail);
2423 list = TREE_CHAIN (list);
2426 *head = newlist;
2427 return tail;
2430 /* Used by: build_private_template, get_class_ivars, and
2431 continue_class. COPY is 1 when called from @defs. In this case
2432 copy all fields. Otherwise don't copy leaf ivars since we rely on
2433 them being side-effected exactly once by finish_struct. */
2435 static tree
2436 build_ivar_chain (interface, copy)
2437 tree interface;
2438 int copy;
2440 tree my_name, super_name, ivar_chain;
2442 my_name = CLASS_NAME (interface);
2443 super_name = CLASS_SUPER_NAME (interface);
2445 /* Possibly copy leaf ivars. */
2446 if (copy)
2447 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2448 else
2449 ivar_chain = CLASS_IVARS (interface);
2451 while (super_name)
2453 tree op1;
2454 tree super_interface = lookup_interface (super_name);
2456 if (!super_interface)
2458 /* fatal did not work with 2 args...should fix */
2459 error ("cannot find interface declaration for `%s', superclass of `%s'",
2460 IDENTIFIER_POINTER (super_name),
2461 IDENTIFIER_POINTER (my_name));
2462 exit (FATAL_EXIT_CODE);
2465 if (super_interface == interface)
2466 fatal_error ("circular inheritance in interface declaration for `%s'",
2467 IDENTIFIER_POINTER (super_name));
2469 interface = super_interface;
2470 my_name = CLASS_NAME (interface);
2471 super_name = CLASS_SUPER_NAME (interface);
2473 op1 = CLASS_IVARS (interface);
2474 if (op1)
2476 tree head, tail = objc_copy_list (op1, &head);
2478 /* Prepend super class ivars...make a copy of the list, we
2479 do not want to alter the original. */
2480 TREE_CHAIN (tail) = ivar_chain;
2481 ivar_chain = head;
2484 return ivar_chain;
2487 /* struct <classname> {
2488 struct objc_class *isa;
2490 }; */
2492 static tree
2493 build_private_template (class)
2494 tree class;
2496 tree ivar_context;
2498 if (CLASS_STATIC_TEMPLATE (class))
2500 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2501 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2503 else
2505 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2507 ivar_context = build_ivar_chain (class, 0);
2509 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2511 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2513 /* mark this record as class template - for class type checking */
2514 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2517 instance_type
2518 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2519 uprivate_record),
2520 build1 (INDIRECT_REF, NULL_TREE,
2521 NULL_TREE)));
2523 return ivar_context;
2526 /* Begin code generation for protocols... */
2528 /* struct objc_protocol {
2529 char *protocol_name;
2530 struct objc_protocol **protocol_list;
2531 struct objc_method_desc *instance_methods;
2532 struct objc_method_desc *class_methods;
2533 }; */
2535 static tree
2536 build_protocol_template ()
2538 tree decl_specs, field_decl, field_decl_chain;
2539 tree template;
2541 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2543 /* struct objc_class *isa; */
2545 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2546 get_identifier (UTAG_CLASS)));
2547 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2548 field_decl
2549 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2550 field_decl_chain = field_decl;
2552 /* char *protocol_name; */
2554 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2555 field_decl
2556 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2557 field_decl
2558 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2559 chainon (field_decl_chain, field_decl);
2561 /* struct objc_protocol **protocol_list; */
2563 decl_specs = build_tree_list (NULL_TREE, template);
2564 field_decl
2565 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2566 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2567 field_decl
2568 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2569 chainon (field_decl_chain, field_decl);
2571 /* struct objc_method_list *instance_methods; */
2573 decl_specs
2574 = build_tree_list (NULL_TREE,
2575 xref_tag (RECORD_TYPE,
2576 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2577 field_decl
2578 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2579 field_decl
2580 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2581 chainon (field_decl_chain, field_decl);
2583 /* struct objc_method_list *class_methods; */
2585 decl_specs
2586 = build_tree_list (NULL_TREE,
2587 xref_tag (RECORD_TYPE,
2588 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2589 field_decl
2590 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2591 field_decl
2592 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2593 chainon (field_decl_chain, field_decl);
2595 return finish_struct (template, field_decl_chain, NULL_TREE);
2598 static tree
2599 build_descriptor_table_initializer (type, entries)
2600 tree type;
2601 tree entries;
2603 tree initlist = NULL_TREE;
2607 tree eltlist = NULL_TREE;
2609 eltlist
2610 = tree_cons (NULL_TREE,
2611 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2612 eltlist
2613 = tree_cons (NULL_TREE,
2614 add_objc_string (METHOD_ENCODING (entries),
2615 meth_var_types),
2616 eltlist);
2618 initlist
2619 = tree_cons (NULL_TREE,
2620 build_constructor (type, nreverse (eltlist)), initlist);
2622 entries = TREE_CHAIN (entries);
2624 while (entries);
2626 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2629 /* struct objc_method_prototype_list {
2630 int count;
2631 struct objc_method_prototype {
2632 SEL name;
2633 char *types;
2634 } list[1];
2635 }; */
2637 static tree
2638 build_method_prototype_list_template (list_type, size)
2639 tree list_type;
2640 int size;
2642 tree objc_ivar_list_record;
2643 tree decl_specs, field_decl, field_decl_chain;
2645 /* Generate an unnamed struct definition. */
2647 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2649 /* int method_count; */
2651 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2652 field_decl = get_identifier ("method_count");
2654 field_decl
2655 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2656 field_decl_chain = field_decl;
2658 /* struct objc_method method_list[]; */
2660 decl_specs = build_tree_list (NULL_TREE, list_type);
2661 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2662 build_int_2 (size, 0));
2664 field_decl
2665 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2666 chainon (field_decl_chain, field_decl);
2668 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2670 return objc_ivar_list_record;
2673 static tree
2674 build_method_prototype_template ()
2676 tree proto_record;
2677 tree decl_specs, field_decl, field_decl_chain;
2679 proto_record
2680 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2682 /* struct objc_selector *_cmd; */
2683 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2684 get_identifier (TAG_SELECTOR)), NULL_TREE);
2685 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2687 field_decl
2688 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2689 field_decl_chain = field_decl;
2691 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2692 field_decl
2693 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2694 field_decl
2695 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2696 chainon (field_decl_chain, field_decl);
2698 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2700 return proto_record;
2703 /* True if last call to forwarding_offset yielded a register offset. */
2704 static int offset_is_register;
2706 static int
2707 forwarding_offset (parm)
2708 tree parm;
2710 int offset_in_bytes;
2712 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2714 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2716 /* ??? Here we assume that the parm address is indexed
2717 off the frame pointer or arg pointer.
2718 If that is not true, we produce meaningless results,
2719 but do not crash. */
2720 if (GET_CODE (addr) == PLUS
2721 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2722 offset_in_bytes = INTVAL (XEXP (addr, 1));
2723 else
2724 offset_in_bytes = 0;
2726 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2727 offset_is_register = 0;
2729 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2731 int regno = REGNO (DECL_INCOMING_RTL (parm));
2732 offset_in_bytes = apply_args_register_offset (regno);
2733 offset_is_register = 1;
2735 else
2736 return 0;
2738 /* This is the case where the parm is passed as an int or double
2739 and it is converted to a char, short or float and stored back
2740 in the parmlist. In this case, describe the parm
2741 with the variable's declared type, and adjust the address
2742 if the least significant bytes (which we are using) are not
2743 the first ones. */
2744 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2745 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2746 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2748 return offset_in_bytes;
2751 static tree
2752 encode_method_prototype (method_decl, func_decl)
2753 tree method_decl;
2754 tree func_decl;
2756 tree parms;
2757 int stack_size, i;
2758 tree user_args;
2759 HOST_WIDE_INT max_parm_end = 0;
2760 char buf[40];
2761 tree result;
2763 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2764 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2766 /* C type. */
2767 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2768 obstack_object_size (&util_obstack),
2769 OBJC_ENCODE_INLINE_DEFS);
2771 /* Stack size. */
2772 for (parms = DECL_ARGUMENTS (func_decl); parms;
2773 parms = TREE_CHAIN (parms))
2775 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
2776 + int_size_in_bytes (TREE_TYPE (parms)));
2778 if (!offset_is_register && max_parm_end < parm_end)
2779 max_parm_end = parm_end;
2782 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2784 sprintf (buf, "%d", stack_size);
2785 obstack_grow (&util_obstack, buf, strlen (buf));
2787 user_args = METHOD_SEL_ARGS (method_decl);
2789 /* Argument types. */
2790 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2791 parms = TREE_CHAIN (parms), i++)
2793 /* Process argument qualifiers for user supplied arguments. */
2794 if (i > 1)
2796 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2797 user_args = TREE_CHAIN (user_args);
2800 /* Type. */
2801 encode_type (TREE_TYPE (parms),
2802 obstack_object_size (&util_obstack),
2803 OBJC_ENCODE_INLINE_DEFS);
2805 /* Compute offset. */
2806 sprintf (buf, "%d", forwarding_offset (parms));
2808 /* Indicate register. */
2809 if (offset_is_register)
2810 obstack_1grow (&util_obstack, '+');
2812 obstack_grow (&util_obstack, buf, strlen (buf));
2815 obstack_1grow (&util_obstack, '\0');
2816 result = get_identifier (obstack_finish (&util_obstack));
2817 obstack_free (&util_obstack, util_firstobj);
2818 return result;
2821 static tree
2822 generate_descriptor_table (type, name, size, list, proto)
2823 tree type;
2824 const char *name;
2825 int size;
2826 tree list;
2827 tree proto;
2829 tree sc_spec, decl_specs, decl, initlist;
2831 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2832 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2834 decl = start_decl (synth_id_with_class_suffix (name, proto),
2835 decl_specs, 1, NULL_TREE);
2836 DECL_CONTEXT (decl) = NULL_TREE;
2838 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2839 initlist = tree_cons (NULL_TREE, list, initlist);
2841 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2842 NULL_TREE);
2844 return decl;
2847 static void
2848 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2849 tree protocol;
2851 tree initlist, chain, method_list_template;
2852 tree cast, variable_length_type;
2853 int size;
2855 if (!objc_method_prototype_template)
2857 objc_method_prototype_template = build_method_prototype_template ();
2860 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2861 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2862 NULL_TREE);
2863 variable_length_type = groktypename (cast);
2865 chain = PROTOCOL_CLS_METHODS (protocol);
2866 if (chain)
2868 size = list_length (chain);
2870 method_list_template
2871 = build_method_prototype_list_template (objc_method_prototype_template,
2872 size);
2874 initlist
2875 = build_descriptor_table_initializer (objc_method_prototype_template,
2876 chain);
2878 UOBJC_CLASS_METHODS_decl
2879 = generate_descriptor_table (method_list_template,
2880 "_OBJC_PROTOCOL_CLASS_METHODS",
2881 size, initlist, protocol);
2882 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2884 else
2885 UOBJC_CLASS_METHODS_decl = 0;
2887 chain = PROTOCOL_NST_METHODS (protocol);
2888 if (chain)
2890 size = list_length (chain);
2892 method_list_template
2893 = build_method_prototype_list_template (objc_method_prototype_template,
2894 size);
2895 initlist
2896 = build_descriptor_table_initializer (objc_method_prototype_template,
2897 chain);
2899 UOBJC_INSTANCE_METHODS_decl
2900 = generate_descriptor_table (method_list_template,
2901 "_OBJC_PROTOCOL_INSTANCE_METHODS",
2902 size, initlist, protocol);
2903 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
2905 else
2906 UOBJC_INSTANCE_METHODS_decl = 0;
2909 /* Generate a temporary FUNCTION_DECL node to be used in
2910 hack_method_prototype below. */
2912 static tree
2913 build_tmp_function_decl ()
2915 tree decl_specs, expr_decl, parms;
2916 static int xxx = 0;
2917 char buffer[80];
2919 /* struct objc_object *objc_xxx (id, SEL, ...); */
2920 pushlevel (0);
2921 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2922 push_parm_decl (build_tree_list
2923 (build_tree_list (decl_specs,
2924 build1 (INDIRECT_REF, NULL_TREE,
2925 NULL_TREE)),
2926 NULL_TREE));
2928 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2929 get_identifier (TAG_SELECTOR)));
2930 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
2932 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
2933 NULL_TREE));
2934 parms = get_parm_info (0);
2935 poplevel (0, 0, 0);
2937 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2938 sprintf (buffer, "__objc_tmp_%x", xxx++);
2939 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
2940 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
2942 return define_decl (expr_decl, decl_specs);
2945 /* Generate the prototypes for protocol methods. This is used to
2946 generate method encodings for these.
2948 NST_METHODS is the method to generate a _DECL node for TMP_DECL is
2949 a decl node to be used. This is also where the return value is
2950 given. */
2952 static void
2953 hack_method_prototype (nst_methods, tmp_decl)
2954 tree nst_methods;
2955 tree tmp_decl;
2957 tree parms;
2958 tree parm;
2960 /* Hack to avoid problem with static typing of self arg. */
2961 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
2962 start_method_def (nst_methods);
2963 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
2965 if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node)
2966 parms = get_parm_info (0); /* we have a `, ...' */
2967 else
2968 parms = get_parm_info (1); /* place a `void_at_end' */
2970 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
2972 /* Usually called from store_parm_decls -> init_function_start. */
2974 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
2975 current_function_decl = tmp_decl;
2978 /* Code taken from start_function. */
2979 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
2980 /* Promote the value to int before returning it. */
2981 if (TREE_CODE (restype) == INTEGER_TYPE
2982 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
2983 restype = integer_type_node;
2984 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
2987 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
2988 DECL_CONTEXT (parm) = tmp_decl;
2990 init_function_start (tmp_decl, "objc-act", 0);
2992 /* Typically called from expand_function_start for function definitions. */
2993 assign_parms (tmp_decl);
2995 /* install return type */
2996 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3000 static void
3001 generate_protocol_references (plist)
3002 tree plist;
3004 tree lproto;
3006 /* Forward declare protocols referenced. */
3007 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3009 tree proto = TREE_VALUE (lproto);
3011 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3012 && PROTOCOL_NAME (proto))
3014 if (! PROTOCOL_FORWARD_DECL (proto))
3015 build_protocol_reference (proto);
3017 if (PROTOCOL_LIST (proto))
3018 generate_protocol_references (PROTOCOL_LIST (proto));
3023 static void
3024 generate_protocols ()
3026 tree p, tmp_decl, encoding;
3027 tree sc_spec, decl_specs, decl;
3028 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3029 tree cast_type2;
3031 tmp_decl = build_tmp_function_decl ();
3033 if (! objc_protocol_template)
3034 objc_protocol_template = build_protocol_template ();
3036 /* If a protocol was directly referenced, pull in indirect references. */
3037 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3038 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3039 generate_protocol_references (PROTOCOL_LIST (p));
3041 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3043 tree nst_methods = PROTOCOL_NST_METHODS (p);
3044 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3046 /* If protocol wasn't referenced, don't generate any code. */
3047 if (! PROTOCOL_FORWARD_DECL (p))
3048 continue;
3050 /* Make sure we link in the Protocol class. */
3051 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3053 while (nst_methods)
3055 if (! METHOD_ENCODING (nst_methods))
3057 hack_method_prototype (nst_methods, tmp_decl);
3058 encoding = encode_method_prototype (nst_methods, tmp_decl);
3059 METHOD_ENCODING (nst_methods) = encoding;
3061 nst_methods = TREE_CHAIN (nst_methods);
3064 while (cls_methods)
3066 if (! METHOD_ENCODING (cls_methods))
3068 hack_method_prototype (cls_methods, tmp_decl);
3069 encoding = encode_method_prototype (cls_methods, tmp_decl);
3070 METHOD_ENCODING (cls_methods) = encoding;
3073 cls_methods = TREE_CHAIN (cls_methods);
3075 generate_method_descriptors (p);
3077 if (PROTOCOL_LIST (p))
3078 refs_decl = generate_protocol_list (p);
3079 else
3080 refs_decl = 0;
3082 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3084 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3085 NULL_TREE);
3086 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3088 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3089 decl_specs, 1, NULL_TREE);
3091 DECL_CONTEXT (decl) = NULL_TREE;
3093 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3095 if (refs_decl)
3097 cast_type2
3098 = groktypename
3099 (build_tree_list (build_tree_list (NULL_TREE,
3100 objc_protocol_template),
3101 build1 (INDIRECT_REF, NULL_TREE,
3102 build1 (INDIRECT_REF, NULL_TREE,
3103 NULL_TREE))));
3105 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3106 TREE_TYPE (refs_expr) = cast_type2;
3108 else
3109 refs_expr = build_int_2 (0, 0);
3111 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3112 by generate_method_descriptors, which is called above. */
3113 initlist = build_protocol_initializer (TREE_TYPE (decl),
3114 protocol_name_expr, refs_expr,
3115 UOBJC_INSTANCE_METHODS_decl,
3116 UOBJC_CLASS_METHODS_decl);
3117 finish_decl (decl, initlist, NULL_TREE);
3119 /* Mark the decl as used to avoid "defined but not used" warning. */
3120 TREE_USED (decl) = 1;
3124 static tree
3125 build_protocol_initializer (type, protocol_name, protocol_list,
3126 instance_methods, class_methods)
3127 tree type;
3128 tree protocol_name;
3129 tree protocol_list;
3130 tree instance_methods;
3131 tree class_methods;
3133 tree initlist = NULL_TREE, expr;
3134 tree cast_type;
3136 cast_type = groktypename
3137 (build_tree_list
3138 (build_tree_list (NULL_TREE,
3139 xref_tag (RECORD_TYPE,
3140 get_identifier (UTAG_CLASS))),
3141 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3143 /* Filling the "isa" in with one allows the runtime system to
3144 detect that the version change...should remove before final release. */
3146 expr = build_int_2 (PROTOCOL_VERSION, 0);
3147 TREE_TYPE (expr) = cast_type;
3148 initlist = tree_cons (NULL_TREE, expr, initlist);
3149 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3150 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3152 if (!instance_methods)
3153 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3154 else
3156 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3157 initlist = tree_cons (NULL_TREE, expr, initlist);
3160 if (!class_methods)
3161 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3162 else
3164 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3165 initlist = tree_cons (NULL_TREE, expr, initlist);
3168 return build_constructor (type, nreverse (initlist));
3171 /* struct objc_category {
3172 char *category_name;
3173 char *class_name;
3174 struct objc_method_list *instance_methods;
3175 struct objc_method_list *class_methods;
3176 struct objc_protocol_list *protocols;
3177 }; */
3179 static void
3180 build_category_template ()
3182 tree decl_specs, field_decl, field_decl_chain;
3184 objc_category_template = start_struct (RECORD_TYPE,
3185 get_identifier (UTAG_CATEGORY));
3186 /* char *category_name; */
3188 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3189 field_decl
3190 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3191 field_decl
3192 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3193 field_decl_chain = field_decl;
3195 /* char *class_name; */
3197 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3198 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3199 field_decl
3200 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3201 chainon (field_decl_chain, field_decl);
3203 /* struct objc_method_list *instance_methods; */
3205 decl_specs = build_tree_list (NULL_TREE,
3206 xref_tag (RECORD_TYPE,
3207 get_identifier (UTAG_METHOD_LIST)));
3208 field_decl
3209 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3210 field_decl
3211 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3212 chainon (field_decl_chain, field_decl);
3214 /* struct objc_method_list *class_methods; */
3216 decl_specs = build_tree_list (NULL_TREE,
3217 xref_tag (RECORD_TYPE,
3218 get_identifier (UTAG_METHOD_LIST)));
3219 field_decl
3220 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3221 field_decl
3222 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3223 chainon (field_decl_chain, field_decl);
3225 /* struct objc_protocol **protocol_list; */
3227 decl_specs = build_tree_list (NULL_TREE,
3228 xref_tag (RECORD_TYPE,
3229 get_identifier (UTAG_PROTOCOL)));
3230 field_decl
3231 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3232 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3233 field_decl
3234 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3235 chainon (field_decl_chain, field_decl);
3237 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3240 /* struct objc_selector {
3241 void *sel_id;
3242 char *sel_type;
3243 }; */
3245 static void
3246 build_selector_template ()
3249 tree decl_specs, field_decl, field_decl_chain;
3251 objc_selector_template
3252 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3254 /* void *sel_id; */
3256 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3257 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3258 field_decl
3259 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3260 field_decl_chain = field_decl;
3262 /* char *sel_type; */
3264 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3265 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3266 field_decl
3267 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3268 chainon (field_decl_chain, field_decl);
3270 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3273 /* struct objc_class {
3274 struct objc_class *isa;
3275 struct objc_class *super_class;
3276 char *name;
3277 long version;
3278 long info;
3279 long instance_size;
3280 struct objc_ivar_list *ivars;
3281 struct objc_method_list *methods;
3282 if (flag_next_runtime)
3283 struct objc_cache *cache;
3284 else {
3285 struct sarray *dtable;
3286 struct objc_class *subclass_list;
3287 struct objc_class *sibling_class;
3289 struct objc_protocol_list *protocols;
3290 void *gc_object_type;
3291 }; */
3293 static void
3294 build_class_template ()
3296 tree decl_specs, field_decl, field_decl_chain;
3298 objc_class_template
3299 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3301 /* struct objc_class *isa; */
3303 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3304 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3305 field_decl
3306 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3307 field_decl_chain = field_decl;
3309 /* struct objc_class *super_class; */
3311 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3312 field_decl
3313 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3314 field_decl
3315 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3316 chainon (field_decl_chain, field_decl);
3318 /* char *name; */
3320 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3321 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3322 field_decl
3323 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3324 chainon (field_decl_chain, field_decl);
3326 /* long version; */
3328 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3329 field_decl = get_identifier ("version");
3330 field_decl
3331 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3332 chainon (field_decl_chain, field_decl);
3334 /* long info; */
3336 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3337 field_decl = get_identifier ("info");
3338 field_decl
3339 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3340 chainon (field_decl_chain, field_decl);
3342 /* long instance_size; */
3344 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3345 field_decl = get_identifier ("instance_size");
3346 field_decl
3347 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3348 chainon (field_decl_chain, field_decl);
3350 /* struct objc_ivar_list *ivars; */
3352 decl_specs = build_tree_list (NULL_TREE,
3353 xref_tag (RECORD_TYPE,
3354 get_identifier (UTAG_IVAR_LIST)));
3355 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3356 field_decl
3357 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3358 chainon (field_decl_chain, field_decl);
3360 /* struct objc_method_list *methods; */
3362 decl_specs = build_tree_list (NULL_TREE,
3363 xref_tag (RECORD_TYPE,
3364 get_identifier (UTAG_METHOD_LIST)));
3365 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3366 field_decl
3367 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3368 chainon (field_decl_chain, field_decl);
3370 if (flag_next_runtime)
3372 /* struct objc_cache *cache; */
3374 decl_specs = build_tree_list (NULL_TREE,
3375 xref_tag (RECORD_TYPE,
3376 get_identifier ("objc_cache")));
3377 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3378 field_decl = grokfield (input_filename, lineno, field_decl,
3379 decl_specs, NULL_TREE);
3380 chainon (field_decl_chain, field_decl);
3382 else
3384 /* struct sarray *dtable; */
3386 decl_specs = build_tree_list (NULL_TREE,
3387 xref_tag (RECORD_TYPE,
3388 get_identifier ("sarray")));
3389 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3390 field_decl = grokfield (input_filename, lineno, field_decl,
3391 decl_specs, NULL_TREE);
3392 chainon (field_decl_chain, field_decl);
3394 /* struct objc_class *subclass_list; */
3396 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3397 field_decl
3398 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3399 field_decl = grokfield (input_filename, lineno, field_decl,
3400 decl_specs, NULL_TREE);
3401 chainon (field_decl_chain, field_decl);
3403 /* struct objc_class *sibling_class; */
3405 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3406 field_decl
3407 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3408 field_decl = grokfield (input_filename, lineno, field_decl,
3409 decl_specs, NULL_TREE);
3410 chainon (field_decl_chain, field_decl);
3413 /* struct objc_protocol **protocol_list; */
3415 decl_specs = build_tree_list (NULL_TREE,
3416 xref_tag (RECORD_TYPE,
3417 get_identifier (UTAG_PROTOCOL)));
3418 field_decl
3419 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3420 field_decl
3421 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3422 field_decl = grokfield (input_filename, lineno, field_decl,
3423 decl_specs, NULL_TREE);
3424 chainon (field_decl_chain, field_decl);
3426 /* void *sel_id; */
3428 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3429 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3430 field_decl
3431 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3432 chainon (field_decl_chain, field_decl);
3434 /* void *gc_object_type; */
3436 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3437 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3438 field_decl
3439 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3440 chainon (field_decl_chain, field_decl);
3442 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3445 /* Generate appropriate forward declarations for an implementation. */
3447 static void
3448 synth_forward_declarations ()
3450 tree sc_spec, decl_specs, an_id;
3452 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3454 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
3456 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3457 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3458 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3459 TREE_USED (UOBJC_CLASS_decl) = 1;
3460 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3462 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3464 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3465 objc_implementation_context);
3467 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3468 TREE_USED (UOBJC_METACLASS_decl) = 1;
3469 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3471 /* Pre-build the following entities - for speed/convenience. */
3473 an_id = get_identifier ("super_class");
3474 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3475 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3478 static void
3479 error_with_ivar (message, decl, rawdecl)
3480 const char *message;
3481 tree decl;
3482 tree rawdecl;
3484 count_error (0);
3486 report_error_function (DECL_SOURCE_FILE (decl));
3488 error_with_file_and_line (DECL_SOURCE_FILE (decl),
3489 DECL_SOURCE_LINE (decl),
3490 "%s `%s'",
3491 message, gen_declaration (rawdecl, errbuf));
3495 #define USERTYPE(t) \
3496 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3497 || TREE_CODE (t) == ENUMERAL_TYPE)
3499 static void
3500 check_ivars (inter, imp)
3501 tree inter;
3502 tree imp;
3504 tree intdecls = CLASS_IVARS (inter);
3505 tree impdecls = CLASS_IVARS (imp);
3506 tree rawintdecls = CLASS_RAW_IVARS (inter);
3507 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3509 while (1)
3511 tree t1, t2;
3513 if (intdecls == 0 && impdecls == 0)
3514 break;
3515 if (intdecls == 0 || impdecls == 0)
3517 error ("inconsistent instance variable specification");
3518 break;
3521 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3523 if (!comptypes (t1, t2))
3525 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3527 error_with_ivar ("conflicting instance variable type",
3528 impdecls, rawimpdecls);
3529 error_with_ivar ("previous declaration of",
3530 intdecls, rawintdecls);
3532 else /* both the type and the name don't match */
3534 error ("inconsistent instance variable specification");
3535 break;
3539 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3541 error_with_ivar ("conflicting instance variable name",
3542 impdecls, rawimpdecls);
3543 error_with_ivar ("previous declaration of",
3544 intdecls, rawintdecls);
3547 intdecls = TREE_CHAIN (intdecls);
3548 impdecls = TREE_CHAIN (impdecls);
3549 rawintdecls = TREE_CHAIN (rawintdecls);
3550 rawimpdecls = TREE_CHAIN (rawimpdecls);
3554 /* Set super_type to the data type node for struct objc_super *,
3555 first defining struct objc_super itself.
3556 This needs to be done just once per compilation. */
3558 static tree
3559 build_super_template ()
3561 tree record, decl_specs, field_decl, field_decl_chain;
3563 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3565 /* struct objc_object *self; */
3567 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3568 field_decl = get_identifier ("self");
3569 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3570 field_decl = grokfield (input_filename, lineno,
3571 field_decl, decl_specs, NULL_TREE);
3572 field_decl_chain = field_decl;
3574 /* struct objc_class *class; */
3576 decl_specs = get_identifier (UTAG_CLASS);
3577 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3578 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3580 field_decl = grokfield (input_filename, lineno,
3581 field_decl, decl_specs, NULL_TREE);
3582 chainon (field_decl_chain, field_decl);
3584 finish_struct (record, field_decl_chain, NULL_TREE);
3586 /* `struct objc_super *' */
3587 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3588 record),
3589 build1 (INDIRECT_REF,
3590 NULL_TREE, NULL_TREE)));
3591 return record;
3594 /* struct objc_ivar {
3595 char *ivar_name;
3596 char *ivar_type;
3597 int ivar_offset;
3598 }; */
3600 static tree
3601 build_ivar_template ()
3603 tree objc_ivar_id, objc_ivar_record;
3604 tree decl_specs, field_decl, field_decl_chain;
3606 objc_ivar_id = get_identifier (UTAG_IVAR);
3607 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3609 /* char *ivar_name; */
3611 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3612 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3614 field_decl = grokfield (input_filename, lineno, field_decl,
3615 decl_specs, NULL_TREE);
3616 field_decl_chain = field_decl;
3618 /* char *ivar_type; */
3620 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3621 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3623 field_decl = grokfield (input_filename, lineno, field_decl,
3624 decl_specs, NULL_TREE);
3625 chainon (field_decl_chain, field_decl);
3627 /* int ivar_offset; */
3629 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3630 field_decl = get_identifier ("ivar_offset");
3632 field_decl = grokfield (input_filename, lineno, field_decl,
3633 decl_specs, NULL_TREE);
3634 chainon (field_decl_chain, field_decl);
3636 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3638 return objc_ivar_record;
3641 /* struct {
3642 int ivar_count;
3643 struct objc_ivar ivar_list[ivar_count];
3644 }; */
3646 static tree
3647 build_ivar_list_template (list_type, size)
3648 tree list_type;
3649 int size;
3651 tree objc_ivar_list_record;
3652 tree decl_specs, field_decl, field_decl_chain;
3654 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3656 /* int ivar_count; */
3658 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3659 field_decl = get_identifier ("ivar_count");
3661 field_decl = grokfield (input_filename, lineno, field_decl,
3662 decl_specs, NULL_TREE);
3663 field_decl_chain = field_decl;
3665 /* struct objc_ivar ivar_list[]; */
3667 decl_specs = build_tree_list (NULL_TREE, list_type);
3668 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3669 build_int_2 (size, 0));
3671 field_decl = grokfield (input_filename, lineno,
3672 field_decl, decl_specs, NULL_TREE);
3673 chainon (field_decl_chain, field_decl);
3675 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3677 return objc_ivar_list_record;
3680 /* struct {
3681 int method_next;
3682 int method_count;
3683 struct objc_method method_list[method_count];
3684 }; */
3686 static tree
3687 build_method_list_template (list_type, size)
3688 tree list_type;
3689 int size;
3691 tree objc_ivar_list_record;
3692 tree decl_specs, field_decl, field_decl_chain;
3694 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3696 /* int method_next; */
3698 decl_specs
3699 = build_tree_list
3700 (NULL_TREE,
3701 xref_tag (RECORD_TYPE,
3702 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3703 field_decl
3704 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3705 field_decl = grokfield (input_filename, lineno, field_decl,
3706 decl_specs, NULL_TREE);
3707 field_decl_chain = field_decl;
3709 /* int method_count; */
3711 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3712 field_decl = get_identifier ("method_count");
3714 field_decl = grokfield (input_filename, lineno,
3715 field_decl, decl_specs, NULL_TREE);
3716 chainon (field_decl_chain, field_decl);
3718 /* struct objc_method method_list[]; */
3720 decl_specs = build_tree_list (NULL_TREE, list_type);
3721 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3722 build_int_2 (size, 0));
3724 field_decl = grokfield (input_filename, lineno,
3725 field_decl, decl_specs, NULL_TREE);
3726 chainon (field_decl_chain, field_decl);
3728 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3730 return objc_ivar_list_record;
3733 static tree
3734 build_ivar_list_initializer (type, field_decl)
3735 tree type;
3736 tree field_decl;
3738 tree initlist = NULL_TREE;
3742 tree ivar = NULL_TREE;
3744 /* Set name. */
3745 if (DECL_NAME (field_decl))
3746 ivar = tree_cons (NULL_TREE,
3747 add_objc_string (DECL_NAME (field_decl),
3748 meth_var_names),
3749 ivar);
3750 else
3751 /* Unnamed bit-field ivar (yuck). */
3752 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3754 /* Set type. */
3755 encode_field_decl (field_decl,
3756 obstack_object_size (&util_obstack),
3757 OBJC_ENCODE_DONT_INLINE_DEFS);
3759 /* Null terminate string. */
3760 obstack_1grow (&util_obstack, 0);
3761 ivar
3762 = tree_cons
3763 (NULL_TREE,
3764 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3765 meth_var_types),
3766 ivar);
3767 obstack_free (&util_obstack, util_firstobj);
3769 /* Set offset. */
3770 ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
3771 initlist = tree_cons (NULL_TREE,
3772 build_constructor (type, nreverse (ivar)),
3773 initlist);
3775 field_decl = TREE_CHAIN (field_decl);
3777 while (field_decl);
3779 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3782 static tree
3783 generate_ivars_list (type, name, size, list)
3784 tree type;
3785 const char *name;
3786 int size;
3787 tree list;
3789 tree sc_spec, decl_specs, decl, initlist;
3791 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3792 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3794 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
3795 decl_specs, 1, NULL_TREE);
3797 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3798 initlist = tree_cons (NULL_TREE, list, initlist);
3800 finish_decl (decl,
3801 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3802 NULL_TREE);
3804 return decl;
3807 static void
3808 generate_ivar_lists ()
3810 tree initlist, ivar_list_template, chain;
3811 tree cast, variable_length_type;
3812 int size;
3814 generating_instance_variables = 1;
3816 if (!objc_ivar_template)
3817 objc_ivar_template = build_ivar_template ();
3819 cast
3820 = build_tree_list
3821 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3822 get_identifier (UTAG_IVAR_LIST))),
3823 NULL_TREE);
3824 variable_length_type = groktypename (cast);
3826 /* Only generate class variables for the root of the inheritance
3827 hierarchy since these will be the same for every class. */
3829 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3830 && (chain = TYPE_FIELDS (objc_class_template)))
3832 size = list_length (chain);
3834 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3835 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3837 UOBJC_CLASS_VARIABLES_decl
3838 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3839 size, initlist);
3840 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3842 else
3843 UOBJC_CLASS_VARIABLES_decl = 0;
3845 chain = CLASS_IVARS (implementation_template);
3846 if (chain)
3848 size = list_length (chain);
3849 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3850 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3852 UOBJC_INSTANCE_VARIABLES_decl
3853 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3854 size, initlist);
3855 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3857 else
3858 UOBJC_INSTANCE_VARIABLES_decl = 0;
3860 generating_instance_variables = 0;
3863 static tree
3864 build_dispatch_table_initializer (type, entries)
3865 tree type;
3866 tree entries;
3868 tree initlist = NULL_TREE;
3872 tree elemlist = NULL_TREE;
3874 elemlist = tree_cons (NULL_TREE,
3875 build_selector (METHOD_SEL_NAME (entries)),
3876 NULL_TREE);
3878 elemlist = tree_cons (NULL_TREE,
3879 add_objc_string (METHOD_ENCODING (entries),
3880 meth_var_types),
3881 elemlist);
3883 elemlist = tree_cons (NULL_TREE,
3884 build_unary_op (ADDR_EXPR,
3885 METHOD_DEFINITION (entries), 1),
3886 elemlist);
3888 initlist = tree_cons (NULL_TREE,
3889 build_constructor (type, nreverse (elemlist)),
3890 initlist);
3892 entries = TREE_CHAIN (entries);
3894 while (entries);
3896 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3899 /* To accomplish method prototyping without generating all kinds of
3900 inane warnings, the definition of the dispatch table entries were
3901 changed from:
3903 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3905 struct objc_method { SEL _cmd; ...; void *_imp; }; */
3907 static tree
3908 build_method_template ()
3910 tree _SLT_record;
3911 tree decl_specs, field_decl, field_decl_chain;
3913 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3915 /* struct objc_selector *_cmd; */
3916 decl_specs = tree_cons (NULL_TREE,
3917 xref_tag (RECORD_TYPE,
3918 get_identifier (TAG_SELECTOR)),
3919 NULL_TREE);
3920 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3922 field_decl = grokfield (input_filename, lineno, field_decl,
3923 decl_specs, NULL_TREE);
3924 field_decl_chain = field_decl;
3926 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3927 field_decl = build1 (INDIRECT_REF, NULL_TREE,
3928 get_identifier ("method_types"));
3929 field_decl = grokfield (input_filename, lineno, field_decl,
3930 decl_specs, NULL_TREE);
3931 chainon (field_decl_chain, field_decl);
3933 /* void *_imp; */
3935 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
3936 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
3937 field_decl = grokfield (input_filename, lineno, field_decl,
3938 decl_specs, NULL_TREE);
3939 chainon (field_decl_chain, field_decl);
3941 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
3943 return _SLT_record;
3947 static tree
3948 generate_dispatch_table (type, name, size, list)
3949 tree type;
3950 const char *name;
3951 int size;
3952 tree list;
3954 tree sc_spec, decl_specs, decl, initlist;
3956 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3957 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3959 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
3960 decl_specs, 1, NULL_TREE);
3962 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
3963 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
3964 initlist = tree_cons (NULL_TREE, list, initlist);
3966 finish_decl (decl,
3967 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3968 NULL_TREE);
3970 return decl;
3973 static void
3974 generate_dispatch_tables ()
3976 tree initlist, chain, method_list_template;
3977 tree cast, variable_length_type;
3978 int size;
3980 if (!objc_method_template)
3981 objc_method_template = build_method_template ();
3983 cast
3984 = build_tree_list
3985 (build_tree_list (NULL_TREE,
3986 xref_tag (RECORD_TYPE,
3987 get_identifier (UTAG_METHOD_LIST))),
3988 NULL_TREE);
3990 variable_length_type = groktypename (cast);
3992 chain = CLASS_CLS_METHODS (objc_implementation_context);
3993 if (chain)
3995 size = list_length (chain);
3997 method_list_template
3998 = build_method_list_template (objc_method_template, size);
3999 initlist
4000 = build_dispatch_table_initializer (objc_method_template, chain);
4002 UOBJC_CLASS_METHODS_decl
4003 = generate_dispatch_table (method_list_template,
4004 ((TREE_CODE (objc_implementation_context)
4005 == CLASS_IMPLEMENTATION_TYPE)
4006 ? "_OBJC_CLASS_METHODS"
4007 : "_OBJC_CATEGORY_CLASS_METHODS"),
4008 size, initlist);
4009 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4011 else
4012 UOBJC_CLASS_METHODS_decl = 0;
4014 chain = CLASS_NST_METHODS (objc_implementation_context);
4015 if (chain)
4017 size = list_length (chain);
4019 method_list_template
4020 = build_method_list_template (objc_method_template, size);
4021 initlist
4022 = build_dispatch_table_initializer (objc_method_template, chain);
4024 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4025 UOBJC_INSTANCE_METHODS_decl
4026 = generate_dispatch_table (method_list_template,
4027 "_OBJC_INSTANCE_METHODS",
4028 size, initlist);
4029 else
4030 /* We have a category. */
4031 UOBJC_INSTANCE_METHODS_decl
4032 = generate_dispatch_table (method_list_template,
4033 "_OBJC_CATEGORY_INSTANCE_METHODS",
4034 size, initlist);
4035 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4037 else
4038 UOBJC_INSTANCE_METHODS_decl = 0;
4041 static tree
4042 generate_protocol_list (i_or_p)
4043 tree i_or_p;
4045 tree initlist, decl_specs, sc_spec;
4046 tree refs_decl, expr_decl, lproto, e, plist;
4047 tree cast_type;
4048 int size = 0;
4050 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4051 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4052 plist = CLASS_PROTOCOL_LIST (i_or_p);
4053 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4054 plist = PROTOCOL_LIST (i_or_p);
4055 else
4056 abort ();
4058 cast_type = groktypename
4059 (build_tree_list
4060 (build_tree_list (NULL_TREE,
4061 xref_tag (RECORD_TYPE,
4062 get_identifier (UTAG_PROTOCOL))),
4063 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4065 /* Compute size. */
4066 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4067 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4068 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4069 size++;
4071 /* Build initializer. */
4072 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4074 e = build_int_2 (size, 0);
4075 TREE_TYPE (e) = cast_type;
4076 initlist = tree_cons (NULL_TREE, e, initlist);
4078 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4080 tree pval = TREE_VALUE (lproto);
4082 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4083 && PROTOCOL_FORWARD_DECL (pval))
4085 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4086 initlist = tree_cons (NULL_TREE, e, initlist);
4090 /* static struct objc_protocol *refs[n]; */
4092 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4093 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4094 get_identifier (UTAG_PROTOCOL)),
4095 sc_spec);
4097 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4098 expr_decl = build_nt (ARRAY_REF,
4099 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4100 i_or_p),
4101 build_int_2 (size + 2, 0));
4102 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4103 expr_decl = build_nt (ARRAY_REF,
4104 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4105 i_or_p),
4106 build_int_2 (size + 2, 0));
4107 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4108 expr_decl
4109 = build_nt (ARRAY_REF,
4110 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4111 i_or_p),
4112 build_int_2 (size + 2, 0));
4113 else
4114 abort ();
4116 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4118 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4119 DECL_CONTEXT (refs_decl) = NULL_TREE;
4121 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4122 nreverse (initlist)),
4123 NULL_TREE);
4125 return refs_decl;
4128 static tree
4129 build_category_initializer (type, cat_name, class_name,
4130 instance_methods, class_methods, protocol_list)
4131 tree type;
4132 tree cat_name;
4133 tree class_name;
4134 tree instance_methods;
4135 tree class_methods;
4136 tree protocol_list;
4138 tree initlist = NULL_TREE, expr;
4140 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4141 initlist = tree_cons (NULL_TREE, class_name, initlist);
4143 if (!instance_methods)
4144 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4145 else
4147 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4148 initlist = tree_cons (NULL_TREE, expr, initlist);
4150 if (!class_methods)
4151 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4152 else
4154 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4155 initlist = tree_cons (NULL_TREE, expr, initlist);
4158 /* protocol_list = */
4159 if (!protocol_list)
4160 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4161 else
4163 tree cast_type2 = groktypename
4164 (build_tree_list
4165 (build_tree_list (NULL_TREE,
4166 xref_tag (RECORD_TYPE,
4167 get_identifier (UTAG_PROTOCOL))),
4168 build1 (INDIRECT_REF, NULL_TREE,
4169 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4171 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4172 TREE_TYPE (expr) = cast_type2;
4173 initlist = tree_cons (NULL_TREE, expr, initlist);
4176 return build_constructor (type, nreverse (initlist));
4179 /* struct objc_class {
4180 struct objc_class *isa;
4181 struct objc_class *super_class;
4182 char *name;
4183 long version;
4184 long info;
4185 long instance_size;
4186 struct objc_ivar_list *ivars;
4187 struct objc_method_list *methods;
4188 if (flag_next_runtime)
4189 struct objc_cache *cache;
4190 else {
4191 struct sarray *dtable;
4192 struct objc_class *subclass_list;
4193 struct objc_class *sibling_class;
4195 struct objc_protocol_list *protocols;
4196 void *gc_object_type;
4197 }; */
4199 static tree
4200 build_shared_structure_initializer (type, isa, super, name, size, status,
4201 dispatch_table, ivar_list, protocol_list)
4202 tree type;
4203 tree isa;
4204 tree super;
4205 tree name;
4206 tree size;
4207 int status;
4208 tree dispatch_table;
4209 tree ivar_list;
4210 tree protocol_list;
4212 tree initlist = NULL_TREE, expr;
4214 /* isa = */
4215 initlist = tree_cons (NULL_TREE, isa, initlist);
4217 /* super_class = */
4218 initlist = tree_cons (NULL_TREE, super, initlist);
4220 /* name = */
4221 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4223 /* version = */
4224 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4226 /* info = */
4227 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4229 /* instance_size = */
4230 initlist = tree_cons (NULL_TREE, size, initlist);
4232 /* objc_ivar_list = */
4233 if (!ivar_list)
4234 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4235 else
4237 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4238 initlist = tree_cons (NULL_TREE, expr, initlist);
4241 /* objc_method_list = */
4242 if (!dispatch_table)
4243 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4244 else
4246 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4247 initlist = tree_cons (NULL_TREE, expr, initlist);
4250 if (flag_next_runtime)
4251 /* method_cache = */
4252 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4253 else
4255 /* dtable = */
4256 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4258 /* subclass_list = */
4259 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4261 /* sibling_class = */
4262 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4265 /* protocol_list = */
4266 if (! protocol_list)
4267 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4268 else
4270 tree cast_type2
4271 = groktypename
4272 (build_tree_list
4273 (build_tree_list (NULL_TREE,
4274 xref_tag (RECORD_TYPE,
4275 get_identifier (UTAG_PROTOCOL))),
4276 build1 (INDIRECT_REF, NULL_TREE,
4277 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4279 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4280 TREE_TYPE (expr) = cast_type2;
4281 initlist = tree_cons (NULL_TREE, expr, initlist);
4284 /* gc_object_type = NULL */
4285 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4287 return build_constructor (type, nreverse (initlist));
4290 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4292 static void
4293 generate_category (cat)
4294 tree cat;
4296 tree sc_spec, decl_specs, decl;
4297 tree initlist, cat_name_expr, class_name_expr;
4298 tree protocol_decl, category;
4300 add_class_reference (CLASS_NAME (cat));
4301 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4303 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4305 category = CLASS_CATEGORY_LIST (implementation_template);
4307 /* find the category interface from the class it is associated with */
4308 while (category)
4310 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4311 break;
4312 category = CLASS_CATEGORY_LIST (category);
4315 if (category && CLASS_PROTOCOL_LIST (category))
4317 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4318 protocol_decl = generate_protocol_list (category);
4320 else
4321 protocol_decl = 0;
4323 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4324 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4326 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4327 objc_implementation_context),
4328 decl_specs, 1, NULL_TREE);
4330 initlist = build_category_initializer (TREE_TYPE (decl),
4331 cat_name_expr, class_name_expr,
4332 UOBJC_INSTANCE_METHODS_decl,
4333 UOBJC_CLASS_METHODS_decl,
4334 protocol_decl);
4336 TREE_USED (decl) = 1;
4337 finish_decl (decl, initlist, NULL_TREE);
4340 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4341 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4343 static void
4344 generate_shared_structures ()
4346 tree sc_spec, decl_specs, decl;
4347 tree name_expr, super_expr, root_expr;
4348 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4349 tree cast_type, initlist, protocol_decl;
4351 my_super_id = CLASS_SUPER_NAME (implementation_template);
4352 if (my_super_id)
4354 add_class_reference (my_super_id);
4356 /* Compute "my_root_id" - this is required for code generation.
4357 the "isa" for all meta class structures points to the root of
4358 the inheritance hierarchy (e.g. "__Object")... */
4359 my_root_id = my_super_id;
4362 tree my_root_int = lookup_interface (my_root_id);
4364 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4365 my_root_id = CLASS_SUPER_NAME (my_root_int);
4366 else
4367 break;
4369 while (1);
4371 else
4372 /* No super class. */
4373 my_root_id = CLASS_NAME (implementation_template);
4375 cast_type
4376 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4377 objc_class_template),
4378 build1 (INDIRECT_REF,
4379 NULL_TREE, NULL_TREE)));
4381 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4382 class_names);
4384 /* Install class `isa' and `super' pointers at runtime. */
4385 if (my_super_id)
4387 super_expr = add_objc_string (my_super_id, class_names);
4388 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4390 else
4391 super_expr = build_int_2 (0, 0);
4393 root_expr = add_objc_string (my_root_id, class_names);
4394 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4396 if (CLASS_PROTOCOL_LIST (implementation_template))
4398 generate_protocol_references
4399 (CLASS_PROTOCOL_LIST (implementation_template));
4400 protocol_decl = generate_protocol_list (implementation_template);
4402 else
4403 protocol_decl = 0;
4405 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4407 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4408 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4410 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4411 NULL_TREE);
4413 initlist
4414 = build_shared_structure_initializer
4415 (TREE_TYPE (decl),
4416 root_expr, super_expr, name_expr,
4417 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
4418 2 /*CLS_META*/,
4419 UOBJC_CLASS_METHODS_decl,
4420 UOBJC_CLASS_VARIABLES_decl,
4421 protocol_decl);
4423 finish_decl (decl, initlist, NULL_TREE);
4425 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4427 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4428 NULL_TREE);
4430 initlist
4431 = build_shared_structure_initializer
4432 (TREE_TYPE (decl),
4433 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4434 super_expr, name_expr,
4435 convert (integer_type_node,
4436 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
4437 (implementation_template))),
4438 1 /*CLS_FACTORY*/,
4439 UOBJC_INSTANCE_METHODS_decl,
4440 UOBJC_INSTANCE_VARIABLES_decl,
4441 protocol_decl);
4443 finish_decl (decl, initlist, NULL_TREE);
4446 static tree
4447 synth_id_with_class_suffix (preamble, ctxt)
4448 const char *preamble;
4449 tree ctxt;
4451 char *string;
4452 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4453 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4455 const char *const class_name
4456 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4457 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4458 sprintf (string, "%s_%s", preamble,
4459 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4461 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4462 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4464 /* We have a category. */
4465 const char *const class_name
4466 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
4467 const char *const class_super_name
4468 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
4469 string = (char *) alloca (strlen (preamble)
4470 + strlen (class_name)
4471 + strlen (class_super_name)
4472 + 3);
4473 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4475 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4477 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4478 string
4479 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4480 sprintf (string, "%s_%s", preamble, protocol_name);
4482 else
4483 abort ();
4485 return get_identifier (string);
4488 static int
4489 is_objc_type_qualifier (node)
4490 tree node;
4492 return (TREE_CODE (node) == IDENTIFIER_NODE
4493 && (node == ridpointers [(int) RID_CONST]
4494 || node == ridpointers [(int) RID_VOLATILE]
4495 || node == ridpointers [(int) RID_IN]
4496 || node == ridpointers [(int) RID_OUT]
4497 || node == ridpointers [(int) RID_INOUT]
4498 || node == ridpointers [(int) RID_BYCOPY]
4499 || node == ridpointers [(int) RID_BYREF]
4500 || node == ridpointers [(int) RID_ONEWAY]));
4503 /* If type is empty or only type qualifiers are present, add default
4504 type of id (otherwise grokdeclarator will default to int). */
4506 static tree
4507 adjust_type_for_id_default (type)
4508 tree type;
4510 tree declspecs, chain;
4512 if (!type)
4513 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4514 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4516 declspecs = TREE_PURPOSE (type);
4518 /* Determine if a typespec is present. */
4519 for (chain = declspecs;
4520 chain;
4521 chain = TREE_CHAIN (chain))
4523 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4524 return type;
4527 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4528 declspecs),
4529 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4532 /* Usage:
4533 keyworddecl:
4534 selector ':' '(' typename ')' identifier
4536 Purpose:
4537 Transform an Objective-C keyword argument into
4538 the C equivalent parameter declarator.
4540 In: key_name, an "identifier_node" (optional).
4541 arg_type, a "tree_list" (optional).
4542 arg_name, an "identifier_node".
4544 Note: It would be really nice to strongly type the preceding
4545 arguments in the function prototype; however, then I
4546 could not use the "accessor" macros defined in "tree.h".
4548 Out: an instance of "keyword_decl". */
4550 tree
4551 build_keyword_decl (key_name, arg_type, arg_name)
4552 tree key_name;
4553 tree arg_type;
4554 tree arg_name;
4556 tree keyword_decl;
4558 /* If no type is specified, default to "id". */
4559 arg_type = adjust_type_for_id_default (arg_type);
4561 keyword_decl = make_node (KEYWORD_DECL);
4563 TREE_TYPE (keyword_decl) = arg_type;
4564 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4565 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4567 return keyword_decl;
4570 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4572 static tree
4573 build_keyword_selector (selector)
4574 tree selector;
4576 int len = 0;
4577 tree key_chain, key_name;
4578 char *buf;
4580 /* Scan the selector to see how much space we'll need. */
4581 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4583 if (TREE_CODE (selector) == KEYWORD_DECL)
4584 key_name = KEYWORD_KEY_NAME (key_chain);
4585 else if (TREE_CODE (selector) == TREE_LIST)
4586 key_name = TREE_PURPOSE (key_chain);
4587 else
4588 abort ();
4590 if (key_name)
4591 len += IDENTIFIER_LENGTH (key_name) + 1;
4592 else
4593 /* Just a ':' arg. */
4594 len++;
4597 buf = (char *) alloca (len + 1);
4598 /* Start the buffer out as an empty string. */
4599 buf[0] = '\0';
4601 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4603 if (TREE_CODE (selector) == KEYWORD_DECL)
4604 key_name = KEYWORD_KEY_NAME (key_chain);
4605 else if (TREE_CODE (selector) == TREE_LIST)
4606 key_name = TREE_PURPOSE (key_chain);
4607 else
4608 abort ();
4610 if (key_name)
4611 strcat (buf, IDENTIFIER_POINTER (key_name));
4612 strcat (buf, ":");
4615 return get_identifier (buf);
4618 /* Used for declarations and definitions. */
4620 tree
4621 build_method_decl (code, ret_type, selector, add_args)
4622 enum tree_code code;
4623 tree ret_type;
4624 tree selector;
4625 tree add_args;
4627 tree method_decl;
4629 /* If no type is specified, default to "id". */
4630 ret_type = adjust_type_for_id_default (ret_type);
4632 method_decl = make_node (code);
4633 TREE_TYPE (method_decl) = ret_type;
4635 /* If we have a keyword selector, create an identifier_node that
4636 represents the full selector name (`:' included)... */
4637 if (TREE_CODE (selector) == KEYWORD_DECL)
4639 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4640 METHOD_SEL_ARGS (method_decl) = selector;
4641 METHOD_ADD_ARGS (method_decl) = add_args;
4643 else
4645 METHOD_SEL_NAME (method_decl) = selector;
4646 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4647 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4650 return method_decl;
4653 #define METHOD_DEF 0
4654 #define METHOD_REF 1
4656 /* Used by `build_objc_method_call' and `comp_method_types'. Return
4657 an argument list for method METH. CONTEXT is either METHOD_DEF or
4658 METHOD_REF, saying whether we are trying to define a method or call
4659 one. SUPERFLAG says this is for a send to super; this makes a
4660 difference for the NeXT calling sequence in which the lookup and
4661 the method call are done together. */
4663 static tree
4664 get_arg_type_list (meth, context, superflag)
4665 tree meth;
4666 int context;
4667 int superflag;
4669 tree arglist, akey;
4671 /* Receiver type. */
4672 if (flag_next_runtime && superflag)
4673 arglist = build_tree_list (NULL_TREE, super_type);
4674 else if (context == METHOD_DEF)
4675 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4676 else
4677 arglist = build_tree_list (NULL_TREE, id_type);
4679 /* Selector type - will eventually change to `int'. */
4680 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4682 /* Build a list of argument types. */
4683 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4685 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4686 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4689 if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
4690 /* We have a `, ...' immediately following the selector,
4691 finalize the arglist...simulate get_parm_info (0). */
4693 else if (METHOD_ADD_ARGS (meth))
4695 /* we have a variable length selector */
4696 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4697 chainon (arglist, add_arg_list);
4699 else
4700 /* finalize the arglist...simulate get_parm_info (1) */
4701 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4703 return arglist;
4706 static tree
4707 check_duplicates (hsh)
4708 hash hsh;
4710 tree meth = NULL_TREE;
4712 if (hsh)
4714 meth = hsh->key;
4716 if (hsh->list)
4718 /* We have two methods with the same name and different types. */
4719 attr loop;
4720 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4722 warning ("multiple declarations for method `%s'",
4723 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4725 warn_with_method ("using", type, meth);
4726 for (loop = hsh->list; loop; loop = loop->next)
4727 warn_with_method ("also found", type, loop->value);
4730 return meth;
4733 /* If RECEIVER is a class reference, return the identifier node for
4734 the referenced class. RECEIVER is created by get_class_reference,
4735 so we check the exact form created depending on which runtimes are
4736 used. */
4738 static tree
4739 receiver_is_class_object (receiver)
4740 tree receiver;
4742 tree chain, exp, arg;
4744 /* The receiver is 'self' in the context of a class method. */
4745 if (objc_method_context
4746 && receiver == self_decl
4747 && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
4749 return CLASS_NAME (objc_implementation_context);
4752 if (flag_next_runtime)
4754 /* The receiver is a variable created by
4755 build_class_reference_decl. */
4756 if (TREE_CODE (receiver) == VAR_DECL
4757 && TREE_TYPE (receiver) == objc_class_type)
4758 /* Look up the identifier. */
4759 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4760 if (TREE_PURPOSE (chain) == receiver)
4761 return TREE_VALUE (chain);
4763 else
4765 /* The receiver is a function call that returns an id. Check if
4766 it is a call to objc_getClass, if so, pick up the class name. */
4767 if (TREE_CODE (receiver) == CALL_EXPR
4768 && (exp = TREE_OPERAND (receiver, 0))
4769 && TREE_CODE (exp) == ADDR_EXPR
4770 && (exp = TREE_OPERAND (exp, 0))
4771 && TREE_CODE (exp) == FUNCTION_DECL
4772 && exp == objc_get_class_decl
4773 /* We have a call to objc_getClass! */
4774 && (arg = TREE_OPERAND (receiver, 1))
4775 && TREE_CODE (arg) == TREE_LIST
4776 && (arg = TREE_VALUE (arg)))
4778 STRIP_NOPS (arg);
4779 if (TREE_CODE (arg) == ADDR_EXPR
4780 && (arg = TREE_OPERAND (arg, 0))
4781 && TREE_CODE (arg) == STRING_CST)
4782 /* Finally, we have the class name. */
4783 return get_identifier (TREE_STRING_POINTER (arg));
4786 return 0;
4789 /* If we are currently building a message expr, this holds
4790 the identifier of the selector of the message. This is
4791 used when printing warnings about argument mismatches. */
4793 static tree building_objc_message_expr = 0;
4795 tree
4796 maybe_building_objc_message_expr ()
4798 return building_objc_message_expr;
4801 /* Construct an expression for sending a message.
4802 MESS has the object to send to in TREE_PURPOSE
4803 and the argument list (including selector) in TREE_VALUE.
4805 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4806 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4808 tree
4809 build_message_expr (mess)
4810 tree mess;
4812 tree receiver = TREE_PURPOSE (mess);
4813 tree sel_name;
4814 tree args = TREE_VALUE (mess);
4815 tree method_params = NULL_TREE;
4817 if (TREE_CODE (receiver) == ERROR_MARK)
4818 return error_mark_node;
4820 /* Obtain the full selector name. */
4821 if (TREE_CODE (args) == IDENTIFIER_NODE)
4822 /* A unary selector. */
4823 sel_name = args;
4824 else if (TREE_CODE (args) == TREE_LIST)
4825 sel_name = build_keyword_selector (args);
4826 else
4827 abort ();
4829 /* Build the parameter list to give to the method. */
4830 if (TREE_CODE (args) == TREE_LIST)
4832 tree chain = args, prev = NULL_TREE;
4834 /* We have a keyword selector--check for comma expressions. */
4835 while (chain)
4837 tree element = TREE_VALUE (chain);
4839 /* We have a comma expression, must collapse... */
4840 if (TREE_CODE (element) == TREE_LIST)
4842 if (prev)
4843 TREE_CHAIN (prev) = element;
4844 else
4845 args = element;
4847 prev = chain;
4848 chain = TREE_CHAIN (chain);
4850 method_params = args;
4853 return finish_message_expr (receiver, sel_name, method_params);
4856 /* The 'finish_message_expr' routine is called from within
4857 'build_message_expr' for non-template functions. In the case of
4858 C++ template functions, it is called from 'build_expr_from_tree'
4859 (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */
4861 tree
4862 finish_message_expr (receiver, sel_name, method_params)
4863 tree receiver, sel_name, method_params;
4865 tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
4866 tree selector, self_object, retval;
4867 int statically_typed = 0, statically_allocated = 0;
4869 /* Determine receiver type. */
4870 tree rtype = TREE_TYPE (receiver);
4871 int super = IS_SUPER (rtype);
4873 if (! super)
4875 if (TREE_STATIC_TEMPLATE (rtype))
4876 statically_allocated = 1;
4877 else if (TREE_CODE (rtype) == POINTER_TYPE
4878 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4879 statically_typed = 1;
4880 else if ((flag_next_runtime
4881 || (IS_ID (rtype)
4882 && (class_ident = receiver_is_class_object (receiver)))))
4884 else if (! IS_ID (rtype)
4885 /* Allow any type that matches objc_class_type. */
4886 && ! comptypes (rtype, objc_class_type))
4888 warning ("invalid receiver type `%s'",
4889 gen_declaration (rtype, errbuf));
4891 if (statically_allocated)
4892 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4894 /* Don't evaluate the receiver twice. */
4895 receiver = save_expr (receiver);
4896 self_object = receiver;
4898 else
4899 /* If sending to `super', use current self as the object. */
4900 self_object = self_decl;
4902 /* Determine operation return type. */
4904 if (super)
4906 tree iface;
4908 if (CLASS_SUPER_NAME (implementation_template))
4910 iface
4911 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4913 if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
4914 method_prototype = lookup_instance_method_static (iface, sel_name);
4915 else
4916 method_prototype = lookup_class_method_static (iface, sel_name);
4918 if (iface && !method_prototype)
4919 warning ("`%s' does not respond to `%s'",
4920 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4921 IDENTIFIER_POINTER (sel_name));
4923 else
4925 error ("no super class declared in interface for `%s'",
4926 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4927 return error_mark_node;
4931 else if (statically_allocated)
4933 tree ctype = TREE_TYPE (rtype);
4934 tree iface = lookup_interface (TYPE_NAME (rtype));
4936 if (iface)
4937 method_prototype = lookup_instance_method_static (iface, sel_name);
4939 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4940 method_prototype
4941 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4942 sel_name, 0);
4944 if (!method_prototype)
4945 warning ("`%s' does not respond to `%s'",
4946 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
4947 IDENTIFIER_POINTER (sel_name));
4949 else if (statically_typed)
4951 tree ctype = TREE_TYPE (rtype);
4953 /* `self' is now statically_typed. All methods should be visible
4954 within the context of the implementation. */
4955 if (objc_implementation_context
4956 && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
4958 method_prototype
4959 = lookup_instance_method_static (implementation_template,
4960 sel_name);
4962 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4963 method_prototype
4964 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4965 sel_name, 0);
4967 if (! method_prototype
4968 && implementation_template != objc_implementation_context)
4969 /* The method is not published in the interface. Check
4970 locally. */
4971 method_prototype
4972 = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
4973 sel_name);
4975 else
4977 tree iface;
4979 if ((iface = lookup_interface (TYPE_NAME (ctype))))
4980 method_prototype = lookup_instance_method_static (iface, sel_name);
4982 if (! method_prototype)
4984 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
4985 if (protocol_list)
4986 method_prototype
4987 = lookup_method_in_protocol_list (protocol_list,
4988 sel_name, 0);
4992 if (!method_prototype)
4993 warning ("`%s' does not respond to `%s'",
4994 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
4995 IDENTIFIER_POINTER (sel_name));
4997 else if (class_ident)
4999 if (objc_implementation_context
5000 && CLASS_NAME (objc_implementation_context) == class_ident)
5002 method_prototype
5003 = lookup_class_method_static (implementation_template, sel_name);
5005 if (!method_prototype
5006 && implementation_template != objc_implementation_context)
5007 /* The method is not published in the interface. Check
5008 locally. */
5009 method_prototype
5010 = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
5011 sel_name);
5013 else
5015 tree iface;
5017 if ((iface = lookup_interface (class_ident)))
5018 method_prototype = lookup_class_method_static (iface, sel_name);
5021 if (!method_prototype)
5023 warning ("cannot find class (factory) method");
5024 warning ("return type for `%s' defaults to id",
5025 IDENTIFIER_POINTER (sel_name));
5028 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5030 /* An anonymous object that has been qualified with a protocol. */
5032 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5034 method_prototype = lookup_method_in_protocol_list (protocol_list,
5035 sel_name, 0);
5037 if (!method_prototype)
5039 hash hsh;
5041 warning ("method `%s' not implemented by protocol",
5042 IDENTIFIER_POINTER (sel_name));
5044 /* Try and find the method signature in the global pools. */
5046 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5047 hsh = hash_lookup (cls_method_hash_list, sel_name);
5049 if (!(method_prototype = check_duplicates (hsh)))
5050 warning ("return type defaults to id");
5053 else
5055 hash hsh;
5057 /* We think we have an instance...loophole: extern id Object; */
5058 hsh = hash_lookup (nst_method_hash_list, sel_name);
5060 if (!hsh)
5061 /* For various loopholes */
5062 hsh = hash_lookup (cls_method_hash_list, sel_name);
5064 method_prototype = check_duplicates (hsh);
5065 if (!method_prototype)
5067 warning ("cannot find method");
5068 warning ("return type for `%s' defaults to id",
5069 IDENTIFIER_POINTER (sel_name));
5073 /* Save the selector name for printing error messages. */
5074 building_objc_message_expr = sel_name;
5076 /* Build the parameters list for looking up the method.
5077 These are the object itself and the selector. */
5079 if (flag_typed_selectors)
5080 selector = build_typed_selector_reference (sel_name, method_prototype);
5081 else
5082 selector = build_selector_reference (sel_name);
5084 retval = build_objc_method_call (super, method_prototype,
5085 receiver, self_object,
5086 selector, method_params);
5088 building_objc_message_expr = 0;
5090 return retval;
5093 /* Build a tree expression to send OBJECT the operation SELECTOR,
5094 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5095 assuming the method has prototype METHOD_PROTOTYPE.
5096 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5097 Use METHOD_PARAMS as list of args to pass to the method.
5098 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5100 static tree
5101 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5102 selector, method_params)
5103 int super_flag;
5104 tree method_prototype, lookup_object, object, selector, method_params;
5106 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5107 tree rcv_p = (super_flag
5108 ? build_pointer_type (xref_tag (RECORD_TYPE,
5109 get_identifier (TAG_SUPER)))
5110 : id_type);
5112 if (flag_next_runtime)
5114 if (! method_prototype)
5116 method_params = tree_cons (NULL_TREE, lookup_object,
5117 tree_cons (NULL_TREE, selector,
5118 method_params));
5119 assemble_external (sender);
5120 return build_function_call (sender, method_params);
5122 else
5124 /* This is a real kludge, but it is used only for the Next.
5125 Clobber the data type of SENDER temporarily to accept
5126 all the arguments for this operation, and to return
5127 whatever this operation returns. */
5128 tree arglist = NULL_TREE, retval, savarg, savret;
5129 tree ret_type = groktypename (TREE_TYPE (method_prototype));
5131 /* Save the proper contents of SENDER's data type. */
5132 savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5133 savret = TREE_TYPE (TREE_TYPE (sender));
5135 /* Install this method's argument types. */
5136 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5137 super_flag);
5138 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5140 /* Install this method's return type. */
5141 TREE_TYPE (TREE_TYPE (sender)) = ret_type;
5143 /* Call SENDER with all the parameters. This will do type
5144 checking using the arg types for this method. */
5145 method_params = tree_cons (NULL_TREE, lookup_object,
5146 tree_cons (NULL_TREE, selector,
5147 method_params));
5148 assemble_external (sender);
5149 retval = build_function_call (sender, method_params);
5151 /* Restore SENDER's return/argument types. */
5152 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5153 TREE_TYPE (TREE_TYPE (sender)) = savret;
5154 return retval;
5157 else
5159 /* This is the portable way.
5160 First call the lookup function to get a pointer to the method,
5161 then cast the pointer, then call it with the method arguments. */
5162 tree method;
5164 /* Avoid trouble since we may evaluate each of these twice. */
5165 object = save_expr (object);
5166 selector = save_expr (selector);
5168 lookup_object = build_c_cast (rcv_p, lookup_object);
5170 assemble_external (sender);
5171 method
5172 = build_function_call (sender,
5173 tree_cons (NULL_TREE, lookup_object,
5174 tree_cons (NULL_TREE, selector,
5175 NULL_TREE)));
5177 /* If we have a method prototype, construct the data type this
5178 method needs, and cast what we got from SENDER into a pointer
5179 to that type. */
5180 if (method_prototype)
5182 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5183 super_flag);
5184 tree valtype = groktypename (TREE_TYPE (method_prototype));
5185 tree fake_function_type = build_function_type (valtype, arglist);
5186 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5188 else
5189 TREE_TYPE (method)
5190 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5192 /* Pass the object to the method. */
5193 assemble_external (method);
5194 return build_function_call (method,
5195 tree_cons (NULL_TREE, object,
5196 tree_cons (NULL_TREE, selector,
5197 method_params)));
5201 static void
5202 build_protocol_reference (p)
5203 tree p;
5205 tree decl, ident, ptype;
5207 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5209 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5210 ptype
5211 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5212 objc_protocol_template),
5213 NULL_TREE));
5215 if (IDENTIFIER_GLOBAL_VALUE (ident))
5216 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5217 else
5219 decl = build_decl (VAR_DECL, ident, ptype);
5220 DECL_EXTERNAL (decl) = 1;
5221 TREE_PUBLIC (decl) = 1;
5222 TREE_USED (decl) = 1;
5223 DECL_ARTIFICIAL (decl) = 1;
5225 make_decl_rtl (decl, 0);
5226 pushdecl_top_level (decl);
5229 PROTOCOL_FORWARD_DECL (p) = decl;
5232 tree
5233 build_protocol_expr (protoname)
5234 tree protoname;
5236 tree expr;
5237 tree p = lookup_protocol (protoname);
5239 if (!p)
5241 error ("cannot find protocol declaration for `%s'",
5242 IDENTIFIER_POINTER (protoname));
5243 return error_mark_node;
5246 if (!PROTOCOL_FORWARD_DECL (p))
5247 build_protocol_reference (p);
5249 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5251 TREE_TYPE (expr) = protocol_type;
5253 return expr;
5256 tree
5257 build_selector_expr (selnamelist)
5258 tree selnamelist;
5260 tree selname;
5262 /* Obtain the full selector name. */
5263 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5264 /* A unary selector. */
5265 selname = selnamelist;
5266 else if (TREE_CODE (selnamelist) == TREE_LIST)
5267 selname = build_keyword_selector (selnamelist);
5268 else
5269 abort ();
5271 if (flag_typed_selectors)
5272 return build_typed_selector_reference (selname, 0);
5273 else
5274 return build_selector_reference (selname);
5277 tree
5278 build_encode_expr (type)
5279 tree type;
5281 tree result;
5282 const char *string;
5284 encode_type (type, obstack_object_size (&util_obstack),
5285 OBJC_ENCODE_INLINE_DEFS);
5286 obstack_1grow (&util_obstack, 0); /* null terminate string */
5287 string = obstack_finish (&util_obstack);
5289 /* Synthesize a string that represents the encoded struct/union. */
5290 result = my_build_string (strlen (string) + 1, string);
5291 obstack_free (&util_obstack, util_firstobj);
5292 return result;
5295 tree
5296 build_ivar_reference (id)
5297 tree id;
5299 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
5301 /* Historically, a class method that produced objects (factory
5302 method) would assign `self' to the instance that it
5303 allocated. This would effectively turn the class method into
5304 an instance method. Following this assignment, the instance
5305 variables could be accessed. That practice, while safe,
5306 violates the simple rule that a class method should not refer
5307 to an instance variable. It's better to catch the cases
5308 where this is done unknowingly than to support the above
5309 paradigm. */
5310 warning ("instance variable `%s' accessed in class method",
5311 IDENTIFIER_POINTER (id));
5312 TREE_TYPE (self_decl) = instance_type; /* cast */
5315 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5317 \f/* Make the hash value positive. */
5318 #define HASHFUNCTION(key) ((size_t) key & 0x7fffffff)
5320 static void
5321 hash_init ()
5323 nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
5324 cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
5327 /* WARNING!!!! hash_enter is called with a method, and will peek
5328 inside to find its selector! But hash_lookup is given a selector
5329 directly, and looks for the selector that's inside the found
5330 entry's key (method) for comparison. */
5332 static void
5333 hash_enter (hashlist, method)
5334 hash *hashlist;
5335 tree method;
5337 static hash hash_alloc_list = 0;
5338 static int hash_alloc_index = 0;
5339 hash obj;
5340 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5342 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5344 hash_alloc_index = 0;
5345 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5346 * HASH_ALLOC_LIST_SIZE);
5348 obj = &hash_alloc_list[hash_alloc_index++];
5349 obj->list = 0;
5350 obj->next = hashlist[slot];
5351 obj->key = method;
5353 hashlist[slot] = obj; /* append to front */
5356 static hash
5357 hash_lookup (hashlist, sel_name)
5358 hash *hashlist;
5359 tree sel_name;
5361 hash target;
5363 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5365 while (target)
5367 if (sel_name == METHOD_SEL_NAME (target->key))
5368 return target;
5370 target = target->next;
5372 return 0;
5375 static void
5376 hash_add_attr (entry, value)
5377 hash entry;
5378 tree value;
5380 static attr attr_alloc_list = 0;
5381 static int attr_alloc_index = 0;
5382 attr obj;
5384 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5386 attr_alloc_index = 0;
5387 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5388 * ATTR_ALLOC_LIST_SIZE);
5390 obj = &attr_alloc_list[attr_alloc_index++];
5391 obj->next = entry->list;
5392 obj->value = value;
5394 entry->list = obj; /* append to front */
5397 static tree
5398 lookup_method (mchain, method)
5399 tree mchain;
5400 tree method;
5402 tree key;
5404 if (TREE_CODE (method) == IDENTIFIER_NODE)
5405 key = method;
5406 else
5407 key = METHOD_SEL_NAME (method);
5409 while (mchain)
5411 if (METHOD_SEL_NAME (mchain) == key)
5412 return mchain;
5413 mchain = TREE_CHAIN (mchain);
5415 return NULL_TREE;
5418 static tree
5419 lookup_instance_method_static (interface, ident)
5420 tree interface;
5421 tree ident;
5423 tree inter = interface;
5424 tree chain = CLASS_NST_METHODS (inter);
5425 tree meth = NULL_TREE;
5429 if ((meth = lookup_method (chain, ident)))
5430 return meth;
5432 if (CLASS_CATEGORY_LIST (inter))
5434 tree category = CLASS_CATEGORY_LIST (inter);
5435 chain = CLASS_NST_METHODS (category);
5439 if ((meth = lookup_method (chain, ident)))
5440 return meth;
5442 /* Check for instance methods in protocols in categories. */
5443 if (CLASS_PROTOCOL_LIST (category))
5445 if ((meth = (lookup_method_in_protocol_list
5446 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5447 return meth;
5450 if ((category = CLASS_CATEGORY_LIST (category)))
5451 chain = CLASS_NST_METHODS (category);
5453 while (category);
5456 if (CLASS_PROTOCOL_LIST (inter))
5458 if ((meth = (lookup_method_in_protocol_list
5459 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5460 return meth;
5463 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5464 chain = CLASS_NST_METHODS (inter);
5466 while (inter);
5468 return meth;
5471 static tree
5472 lookup_class_method_static (interface, ident)
5473 tree interface;
5474 tree ident;
5476 tree inter = interface;
5477 tree chain = CLASS_CLS_METHODS (inter);
5478 tree meth = NULL_TREE;
5479 tree root_inter = NULL_TREE;
5483 if ((meth = lookup_method (chain, ident)))
5484 return meth;
5486 if (CLASS_CATEGORY_LIST (inter))
5488 tree category = CLASS_CATEGORY_LIST (inter);
5489 chain = CLASS_CLS_METHODS (category);
5493 if ((meth = lookup_method (chain, ident)))
5494 return meth;
5496 /* Check for class methods in protocols in categories. */
5497 if (CLASS_PROTOCOL_LIST (category))
5499 if ((meth = (lookup_method_in_protocol_list
5500 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5501 return meth;
5504 if ((category = CLASS_CATEGORY_LIST (category)))
5505 chain = CLASS_CLS_METHODS (category);
5507 while (category);
5510 /* Check for class methods in protocols. */
5511 if (CLASS_PROTOCOL_LIST (inter))
5513 if ((meth = (lookup_method_in_protocol_list
5514 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5515 return meth;
5518 root_inter = inter;
5519 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5520 chain = CLASS_CLS_METHODS (inter);
5522 while (inter);
5524 /* If no class (factory) method was found, check if an _instance_
5525 method of the same name exists in the root class. This is what
5526 the Objective-C runtime will do. */
5527 return lookup_instance_method_static (root_inter, ident);
5530 tree
5531 add_class_method (class, method)
5532 tree class;
5533 tree method;
5535 tree mth;
5536 hash hsh;
5538 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5540 /* put method on list in reverse order */
5541 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5542 CLASS_CLS_METHODS (class) = method;
5544 else
5546 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5547 error ("duplicate definition of class method `%s'",
5548 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5549 else
5551 /* Check types; if different, complain. */
5552 if (!comp_proto_with_proto (method, mth))
5553 error ("duplicate declaration of class method `%s'",
5554 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5558 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5560 /* Install on a global chain. */
5561 hash_enter (cls_method_hash_list, method);
5563 else
5565 /* Check types; if different, add to a list. */
5566 if (!comp_proto_with_proto (method, hsh->key))
5567 hash_add_attr (hsh, method);
5569 return method;
5572 tree
5573 add_instance_method (class, method)
5574 tree class;
5575 tree method;
5577 tree mth;
5578 hash hsh;
5580 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5582 /* Put method on list in reverse order. */
5583 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5584 CLASS_NST_METHODS (class) = method;
5586 else
5588 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5589 error ("duplicate definition of instance method `%s'",
5590 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5591 else
5593 /* Check types; if different, complain. */
5594 if (!comp_proto_with_proto (method, mth))
5595 error ("duplicate declaration of instance method `%s'",
5596 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5600 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5602 /* Install on a global chain. */
5603 hash_enter (nst_method_hash_list, method);
5605 else
5607 /* Check types; if different, add to a list. */
5608 if (!comp_proto_with_proto (method, hsh->key))
5609 hash_add_attr (hsh, method);
5611 return method;
5614 static tree
5615 add_class (class)
5616 tree class;
5618 /* Put interfaces on list in reverse order. */
5619 TREE_CHAIN (class) = interface_chain;
5620 interface_chain = class;
5621 return interface_chain;
5624 static void
5625 add_category (class, category)
5626 tree class;
5627 tree category;
5629 /* Put categories on list in reverse order. */
5630 tree cat = CLASS_CATEGORY_LIST (class);
5632 while (cat)
5634 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5635 warning ("duplicate interface declaration for category `%s(%s)'",
5636 IDENTIFIER_POINTER (CLASS_NAME (class)),
5637 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5638 cat = CLASS_CATEGORY_LIST (cat);
5641 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5642 CLASS_CATEGORY_LIST (class) = category;
5645 /* Called after parsing each instance variable declaration. Necessary to
5646 preserve typedefs and implement public/private...
5648 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5650 tree
5651 add_instance_variable (class, public, declarator, declspecs, width)
5652 tree class;
5653 int public;
5654 tree declarator;
5655 tree declspecs;
5656 tree width;
5658 tree field_decl, raw_decl;
5660 raw_decl = build_tree_list (declspecs, declarator);
5662 if (CLASS_RAW_IVARS (class))
5663 chainon (CLASS_RAW_IVARS (class), raw_decl);
5664 else
5665 CLASS_RAW_IVARS (class) = raw_decl;
5667 field_decl = grokfield (input_filename, lineno,
5668 declarator, declspecs, width);
5670 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5671 switch (public)
5673 case 0:
5674 TREE_PUBLIC (field_decl) = 0;
5675 TREE_PRIVATE (field_decl) = 0;
5676 TREE_PROTECTED (field_decl) = 1;
5677 break;
5679 case 1:
5680 TREE_PUBLIC (field_decl) = 1;
5681 TREE_PRIVATE (field_decl) = 0;
5682 TREE_PROTECTED (field_decl) = 0;
5683 break;
5685 case 2:
5686 TREE_PUBLIC (field_decl) = 0;
5687 TREE_PRIVATE (field_decl) = 1;
5688 TREE_PROTECTED (field_decl) = 0;
5689 break;
5693 if (CLASS_IVARS (class))
5694 chainon (CLASS_IVARS (class), field_decl);
5695 else
5696 CLASS_IVARS (class) = field_decl;
5698 return class;
5701 tree
5702 is_ivar (decl_chain, ident)
5703 tree decl_chain;
5704 tree ident;
5706 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5707 if (DECL_NAME (decl_chain) == ident)
5708 return decl_chain;
5709 return NULL_TREE;
5712 /* True if the ivar is private and we are not in its implementation. */
5715 is_private (decl)
5716 tree decl;
5718 if (TREE_PRIVATE (decl)
5719 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5721 error ("instance variable `%s' is declared private",
5722 IDENTIFIER_POINTER (DECL_NAME (decl)));
5723 return 1;
5725 else
5726 return 0;
5729 /* We have an instance variable reference;, check to see if it is public. */
5732 is_public (expr, identifier)
5733 tree expr;
5734 tree identifier;
5736 tree basetype = TREE_TYPE (expr);
5737 enum tree_code code = TREE_CODE (basetype);
5738 tree decl;
5740 if (code == RECORD_TYPE)
5742 if (TREE_STATIC_TEMPLATE (basetype))
5744 if (!lookup_interface (TYPE_NAME (basetype)))
5746 error ("cannot find interface declaration for `%s'",
5747 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5748 return 0;
5751 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5753 if (TREE_PUBLIC (decl))
5754 return 1;
5756 /* Important difference between the Stepstone translator:
5757 all instance variables should be public within the context
5758 of the implementation. */
5759 if (objc_implementation_context
5760 && (((TREE_CODE (objc_implementation_context)
5761 == CLASS_IMPLEMENTATION_TYPE)
5762 || (TREE_CODE (objc_implementation_context)
5763 == CATEGORY_IMPLEMENTATION_TYPE))
5764 && (CLASS_NAME (objc_implementation_context)
5765 == TYPE_NAME (basetype))))
5766 return ! is_private (decl);
5768 error ("instance variable `%s' is declared %s",
5769 IDENTIFIER_POINTER (identifier),
5770 TREE_PRIVATE (decl) ? "private" : "protected");
5771 return 0;
5775 else if (objc_implementation_context && (basetype == objc_object_reference))
5777 TREE_TYPE (expr) = uprivate_record;
5778 warning ("static access to object of type `id'");
5782 return 1;
5785 /* Implement @defs (<classname>) within struct bodies. */
5787 tree
5788 get_class_ivars (interface)
5789 tree interface;
5791 /* Make sure we copy the leaf ivars in case @defs is used in a local
5792 context. Otherwise finish_struct will overwrite the layout info
5793 using temporary storage. */
5794 return build_ivar_chain (interface, 1);
5797 /* Make sure all entries in CHAIN are also in LIST. */
5799 static int
5800 check_methods (chain, list, mtype)
5801 tree chain;
5802 tree list;
5803 int mtype;
5805 int first = 1;
5807 while (chain)
5809 if (!lookup_method (list, chain))
5811 if (first)
5813 if (TREE_CODE (objc_implementation_context)
5814 == CLASS_IMPLEMENTATION_TYPE)
5815 warning ("incomplete implementation of class `%s'",
5816 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
5817 else if (TREE_CODE (objc_implementation_context)
5818 == CATEGORY_IMPLEMENTATION_TYPE)
5819 warning ("incomplete implementation of category `%s'",
5820 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
5821 first = 0;
5824 warning ("method definition for `%c%s' not found",
5825 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5828 chain = TREE_CHAIN (chain);
5831 return first;
5834 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */
5836 static int
5837 conforms_to_protocol (class, protocol)
5838 tree class;
5839 tree protocol;
5841 if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
5843 tree p = CLASS_PROTOCOL_LIST (class);
5844 while (p && TREE_VALUE (p) != protocol)
5845 p = TREE_CHAIN (p);
5847 if (!p)
5849 tree super = (CLASS_SUPER_NAME (class)
5850 ? lookup_interface (CLASS_SUPER_NAME (class))
5851 : NULL_TREE);
5852 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5853 if (!tmp)
5854 return 0;
5858 return 1;
5861 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5862 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5864 static int
5865 check_methods_accessible (chain, context, mtype)
5866 tree chain;
5867 tree context;
5868 int mtype;
5870 int first = 1;
5871 tree list;
5872 tree base_context = context;
5874 while (chain)
5876 context = base_context;
5877 while (context)
5879 if (mtype == '+')
5880 list = CLASS_CLS_METHODS (context);
5881 else
5882 list = CLASS_NST_METHODS (context);
5884 if (lookup_method (list, chain))
5885 break;
5887 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5888 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5889 context = (CLASS_SUPER_NAME (context)
5890 ? lookup_interface (CLASS_SUPER_NAME (context))
5891 : NULL_TREE);
5893 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5894 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5895 context = (CLASS_NAME (context)
5896 ? lookup_interface (CLASS_NAME (context))
5897 : NULL_TREE);
5898 else
5899 abort ();
5902 if (context == NULL_TREE)
5904 if (first)
5906 if (TREE_CODE (objc_implementation_context)
5907 == CLASS_IMPLEMENTATION_TYPE)
5908 warning ("incomplete implementation of class `%s'",
5909 IDENTIFIER_POINTER
5910 (CLASS_NAME (objc_implementation_context)));
5911 else if (TREE_CODE (objc_implementation_context)
5912 == CATEGORY_IMPLEMENTATION_TYPE)
5913 warning ("incomplete implementation of category `%s'",
5914 IDENTIFIER_POINTER
5915 (CLASS_SUPER_NAME (objc_implementation_context)));
5916 first = 0;
5918 warning ("method definition for `%c%s' not found",
5919 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5922 chain = TREE_CHAIN (chain); /* next method... */
5924 return first;
5927 /* Check whether the current interface (accessible via
5928 'objc_implementation_context') actually implements protocol P, along
5929 with any protocols that P inherits. */
5931 static void
5932 check_protocol (p, type, name)
5933 tree p;
5934 const char *type;
5935 const char *name;
5937 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
5939 int f1, f2;
5941 /* Ensure that all protocols have bodies! */
5942 if (flag_warn_protocol)
5944 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
5945 CLASS_CLS_METHODS (objc_implementation_context),
5946 '+');
5947 f2 = check_methods (PROTOCOL_NST_METHODS (p),
5948 CLASS_NST_METHODS (objc_implementation_context),
5949 '-');
5951 else
5953 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
5954 objc_implementation_context,
5955 '+');
5956 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
5957 objc_implementation_context,
5958 '-');
5961 if (!f1 || !f2)
5962 warning ("%s `%s' does not fully implement the `%s' protocol",
5963 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
5966 /* Check protocols recursively. */
5967 if (PROTOCOL_LIST (p))
5969 tree subs = PROTOCOL_LIST (p);
5970 tree super_class =
5971 lookup_interface (CLASS_SUPER_NAME (implementation_template));
5972 while (subs)
5974 tree sub = TREE_VALUE (subs);
5976 /* If the superclass does not conform to the protocols
5977 inherited by P, then we must! */
5978 if (!super_class || !conforms_to_protocol (super_class, sub))
5979 check_protocol (sub, type, name);
5980 subs = TREE_CHAIN (subs);
5985 /* Check whether the current interface (accessible via
5986 'objc_implementation_context') actually implements the protocols listed
5987 in PROTO_LIST. */
5989 static void
5990 check_protocols (proto_list, type, name)
5991 tree proto_list;
5992 const char *type;
5993 const char *name;
5995 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
5997 tree p = TREE_VALUE (proto_list);
5999 check_protocol (p, type, name);
6003 /* Make sure that the class CLASS_NAME is defined
6004 CODE says which kind of thing CLASS_NAME ought to be.
6005 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6006 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
6008 tree
6009 start_class (code, class_name, super_name, protocol_list)
6010 enum tree_code code;
6011 tree class_name;
6012 tree super_name;
6013 tree protocol_list;
6015 tree class, decl;
6017 if (objc_implementation_context)
6019 warning ("`@end' missing in implementation context");
6020 finish_class (objc_implementation_context);
6021 objc_ivar_chain = NULL_TREE;
6022 objc_implementation_context = NULL_TREE;
6025 class = make_node (code);
6026 TYPE_BINFO (class) = make_tree_vec (5);
6028 CLASS_NAME (class) = class_name;
6029 CLASS_SUPER_NAME (class) = super_name;
6030 CLASS_CLS_METHODS (class) = NULL_TREE;
6032 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6034 error ("`%s' redeclared as different kind of symbol",
6035 IDENTIFIER_POINTER (class_name));
6036 error_with_decl (decl, "previous declaration of `%s'");
6039 if (code == CLASS_IMPLEMENTATION_TYPE)
6042 tree chain;
6044 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6045 if (TREE_VALUE (chain) == class_name)
6047 error ("reimplementation of class `%s'",
6048 IDENTIFIER_POINTER (class_name));
6049 return error_mark_node;
6051 implemented_classes = tree_cons (NULL_TREE, class_name,
6052 implemented_classes);
6055 /* Pre-build the following entities - for speed/convenience. */
6056 if (!self_id)
6057 self_id = get_identifier ("self");
6058 if (!ucmd_id)
6059 ucmd_id = get_identifier ("_cmd");
6060 if (!unused_list)
6061 unused_list
6062 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6063 if (!objc_super_template)
6064 objc_super_template = build_super_template ();
6066 /* Reset for multiple classes per file. */
6067 method_slot = 0;
6069 objc_implementation_context = class;
6071 /* Lookup the interface for this implementation. */
6073 if (!(implementation_template = lookup_interface (class_name)))
6075 warning ("cannot find interface declaration for `%s'",
6076 IDENTIFIER_POINTER (class_name));
6077 add_class (implementation_template = objc_implementation_context);
6080 /* If a super class has been specified in the implementation,
6081 insure it conforms to the one specified in the interface. */
6083 if (super_name
6084 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6086 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6087 const char *const name =
6088 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6089 error ("conflicting super class name `%s'",
6090 IDENTIFIER_POINTER (super_name));
6091 error ("previous declaration of `%s'", name);
6094 else if (! super_name)
6096 CLASS_SUPER_NAME (objc_implementation_context)
6097 = CLASS_SUPER_NAME (implementation_template);
6101 else if (code == CLASS_INTERFACE_TYPE)
6103 if (lookup_interface (class_name))
6104 warning ("duplicate interface declaration for class `%s'",
6105 IDENTIFIER_POINTER (class_name));
6106 else
6107 add_class (class);
6109 if (protocol_list)
6110 CLASS_PROTOCOL_LIST (class)
6111 = lookup_and_install_protocols (protocol_list);
6114 else if (code == CATEGORY_INTERFACE_TYPE)
6116 tree class_category_is_assoc_with;
6118 /* For a category, class_name is really the name of the class that
6119 the following set of methods will be associated with. We must
6120 find the interface so that can derive the objects template. */
6122 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6124 error ("cannot find interface declaration for `%s'",
6125 IDENTIFIER_POINTER (class_name));
6126 exit (FATAL_EXIT_CODE);
6128 else
6129 add_category (class_category_is_assoc_with, class);
6131 if (protocol_list)
6132 CLASS_PROTOCOL_LIST (class)
6133 = lookup_and_install_protocols (protocol_list);
6136 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6138 /* Pre-build the following entities for speed/convenience. */
6139 if (!self_id)
6140 self_id = get_identifier ("self");
6141 if (!ucmd_id)
6142 ucmd_id = get_identifier ("_cmd");
6143 if (!unused_list)
6144 unused_list
6145 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6146 if (!objc_super_template)
6147 objc_super_template = build_super_template ();
6149 /* Reset for multiple classes per file. */
6150 method_slot = 0;
6152 objc_implementation_context = class;
6154 /* For a category, class_name is really the name of the class that
6155 the following set of methods will be associated with. We must
6156 find the interface so that can derive the objects template. */
6158 if (!(implementation_template = lookup_interface (class_name)))
6160 error ("cannot find interface declaration for `%s'",
6161 IDENTIFIER_POINTER (class_name));
6162 exit (FATAL_EXIT_CODE);
6165 return class;
6168 tree
6169 continue_class (class)
6170 tree class;
6172 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6173 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6175 struct imp_entry *imp_entry;
6176 tree ivar_context;
6178 /* Check consistency of the instance variables. */
6180 if (CLASS_IVARS (class))
6181 check_ivars (implementation_template, class);
6183 /* code generation */
6185 ivar_context = build_private_template (implementation_template);
6187 if (!objc_class_template)
6188 build_class_template ();
6190 imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry));
6192 imp_entry->next = imp_list;
6193 imp_entry->imp_context = class;
6194 imp_entry->imp_template = implementation_template;
6196 synth_forward_declarations ();
6197 imp_entry->class_decl = UOBJC_CLASS_decl;
6198 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6200 /* Append to front and increment count. */
6201 imp_list = imp_entry;
6202 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6203 imp_count++;
6204 else
6205 cat_count++;
6207 return ivar_context;
6210 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6212 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6214 if (!TYPE_FIELDS (record))
6216 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6217 CLASS_STATIC_TEMPLATE (class) = record;
6219 /* Mark this record as a class template for static typing. */
6220 TREE_STATIC_TEMPLATE (record) = 1;
6223 return NULL_TREE;
6226 else
6227 return error_mark_node;
6230 /* This is called once we see the "@end" in an interface/implementation. */
6232 void
6233 finish_class (class)
6234 tree class;
6236 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6238 /* All code generation is done in finish_objc. */
6240 if (implementation_template != objc_implementation_context)
6242 /* Ensure that all method listed in the interface contain bodies. */
6243 check_methods (CLASS_CLS_METHODS (implementation_template),
6244 CLASS_CLS_METHODS (objc_implementation_context), '+');
6245 check_methods (CLASS_NST_METHODS (implementation_template),
6246 CLASS_NST_METHODS (objc_implementation_context), '-');
6248 if (CLASS_PROTOCOL_LIST (implementation_template))
6249 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6250 "class",
6251 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6255 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6257 tree category = CLASS_CATEGORY_LIST (implementation_template);
6259 /* Find the category interface from the class it is associated with. */
6260 while (category)
6262 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6263 break;
6264 category = CLASS_CATEGORY_LIST (category);
6267 if (category)
6269 /* Ensure all method listed in the interface contain bodies. */
6270 check_methods (CLASS_CLS_METHODS (category),
6271 CLASS_CLS_METHODS (objc_implementation_context), '+');
6272 check_methods (CLASS_NST_METHODS (category),
6273 CLASS_NST_METHODS (objc_implementation_context), '-');
6275 if (CLASS_PROTOCOL_LIST (category))
6276 check_protocols (CLASS_PROTOCOL_LIST (category),
6277 "category",
6278 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6282 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6284 tree decl_specs;
6285 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6286 char *string = (char *) alloca (strlen (class_name) + 3);
6288 /* extern struct objc_object *_<my_name>; */
6290 sprintf (string, "_%s", class_name);
6292 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6293 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6294 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6295 decl_specs);
6299 static tree
6300 add_protocol (protocol)
6301 tree protocol;
6303 /* Put protocol on list in reverse order. */
6304 TREE_CHAIN (protocol) = protocol_chain;
6305 protocol_chain = protocol;
6306 return protocol_chain;
6309 static tree
6310 lookup_protocol (ident)
6311 tree ident;
6313 tree chain;
6315 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6317 if (ident == PROTOCOL_NAME (chain))
6318 return chain;
6321 return NULL_TREE;
6324 /* This function forward declares the protocols named by NAMES. If
6325 they are already declared or defined, the function has no effect. */
6327 void
6328 objc_declare_protocols (names)
6329 tree names;
6331 tree list;
6333 for (list = names; list; list = TREE_CHAIN (list))
6335 tree name = TREE_VALUE (list);
6337 if (lookup_protocol (name) == NULL_TREE)
6339 tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6341 TYPE_BINFO (protocol) = make_tree_vec (2);
6342 PROTOCOL_NAME (protocol) = name;
6343 PROTOCOL_LIST (protocol) = NULL_TREE;
6344 add_protocol (protocol);
6345 PROTOCOL_DEFINED (protocol) = 0;
6346 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6351 tree
6352 start_protocol (code, name, list)
6353 enum tree_code code;
6354 tree name;
6355 tree list;
6357 tree protocol;
6359 /* This is as good a place as any. Need to invoke
6360 push_tag_toplevel. */
6361 if (!objc_protocol_template)
6362 objc_protocol_template = build_protocol_template ();
6364 protocol = lookup_protocol (name);
6366 if (!protocol)
6368 protocol = make_node (code);
6369 TYPE_BINFO (protocol) = make_tree_vec (2);
6371 PROTOCOL_NAME (protocol) = name;
6372 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6373 add_protocol (protocol);
6374 PROTOCOL_DEFINED (protocol) = 1;
6375 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6377 check_protocol_recursively (protocol, list);
6379 else if (! PROTOCOL_DEFINED (protocol))
6381 PROTOCOL_DEFINED (protocol) = 1;
6382 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6384 check_protocol_recursively (protocol, list);
6386 else
6388 warning ("duplicate declaration for protocol `%s'",
6389 IDENTIFIER_POINTER (name));
6391 return protocol;
6394 void
6395 finish_protocol (protocol)
6396 tree protocol ATTRIBUTE_UNUSED;
6401 /* "Encode" a data type into a string, which grows in util_obstack.
6402 ??? What is the FORMAT? Someone please document this! */
6404 static void
6405 encode_type_qualifiers (declspecs)
6406 tree declspecs;
6408 tree spec;
6410 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6412 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6413 obstack_1grow (&util_obstack, 'r');
6414 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6415 obstack_1grow (&util_obstack, 'n');
6416 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6417 obstack_1grow (&util_obstack, 'N');
6418 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6419 obstack_1grow (&util_obstack, 'o');
6420 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6421 obstack_1grow (&util_obstack, 'O');
6422 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6423 obstack_1grow (&util_obstack, 'R');
6424 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6425 obstack_1grow (&util_obstack, 'V');
6429 /* Encode a pointer type. */
6431 static void
6432 encode_pointer (type, curtype, format)
6433 tree type;
6434 int curtype;
6435 int format;
6437 tree pointer_to = TREE_TYPE (type);
6439 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6441 if (TYPE_NAME (pointer_to)
6442 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6444 const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6446 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6448 obstack_1grow (&util_obstack, '@');
6449 return;
6451 else if (TREE_STATIC_TEMPLATE (pointer_to))
6453 if (generating_instance_variables)
6455 obstack_1grow (&util_obstack, '@');
6456 obstack_1grow (&util_obstack, '"');
6457 obstack_grow (&util_obstack, name, strlen (name));
6458 obstack_1grow (&util_obstack, '"');
6459 return;
6461 else
6463 obstack_1grow (&util_obstack, '@');
6464 return;
6467 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6469 obstack_1grow (&util_obstack, '#');
6470 return;
6472 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6474 obstack_1grow (&util_obstack, ':');
6475 return;
6479 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6480 && TYPE_MODE (pointer_to) == QImode)
6482 obstack_1grow (&util_obstack, '*');
6483 return;
6486 /* We have a type that does not get special treatment. */
6488 /* NeXT extension */
6489 obstack_1grow (&util_obstack, '^');
6490 encode_type (pointer_to, curtype, format);
6493 static void
6494 encode_array (type, curtype, format)
6495 tree type;
6496 int curtype;
6497 int format;
6499 tree an_int_cst = TYPE_SIZE (type);
6500 tree array_of = TREE_TYPE (type);
6501 char buffer[40];
6503 /* An incomplete array is treated like a pointer. */
6504 if (an_int_cst == NULL)
6506 encode_pointer (type, curtype, format);
6507 return;
6510 sprintf (buffer, "[%ld",
6511 (long) (TREE_INT_CST_LOW (an_int_cst)
6512 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6514 obstack_grow (&util_obstack, buffer, strlen (buffer));
6515 encode_type (array_of, curtype, format);
6516 obstack_1grow (&util_obstack, ']');
6517 return;
6520 static void
6521 encode_aggregate_within (type, curtype, format, left, right)
6522 tree type;
6523 int curtype;
6524 int format;
6525 int left;
6526 int right;
6528 /* The RECORD_TYPE may in fact be a typedef! For purposes
6529 of encoding, we need the real underlying enchilada. */
6530 if (TYPE_MAIN_VARIANT (type))
6531 type = TYPE_MAIN_VARIANT (type);
6533 if (obstack_object_size (&util_obstack) > 0
6534 && *(obstack_next_free (&util_obstack) - 1) == '^')
6536 tree name = TYPE_NAME (type);
6538 /* we have a reference; this is a NeXT extension. */
6540 if (obstack_object_size (&util_obstack) - curtype == 1
6541 && format == OBJC_ENCODE_INLINE_DEFS)
6543 /* Output format of struct for first level only. */
6544 tree fields = TYPE_FIELDS (type);
6546 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6548 obstack_1grow (&util_obstack, left);
6549 obstack_grow (&util_obstack,
6550 IDENTIFIER_POINTER (name),
6551 strlen (IDENTIFIER_POINTER (name)));
6552 obstack_1grow (&util_obstack, '=');
6554 else
6556 obstack_1grow (&util_obstack, left);
6557 obstack_grow (&util_obstack, "?=", 2);
6560 for ( ; fields; fields = TREE_CHAIN (fields))
6561 encode_field_decl (fields, curtype, format);
6563 obstack_1grow (&util_obstack, right);
6566 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6568 obstack_1grow (&util_obstack, left);
6569 obstack_grow (&util_obstack,
6570 IDENTIFIER_POINTER (name),
6571 strlen (IDENTIFIER_POINTER (name)));
6572 obstack_1grow (&util_obstack, right);
6575 else
6577 /* We have an untagged structure or a typedef. */
6578 obstack_1grow (&util_obstack, left);
6579 obstack_1grow (&util_obstack, '?');
6580 obstack_1grow (&util_obstack, right);
6584 else
6586 tree name = TYPE_NAME (type);
6587 tree fields = TYPE_FIELDS (type);
6589 if (format == OBJC_ENCODE_INLINE_DEFS
6590 || generating_instance_variables)
6592 obstack_1grow (&util_obstack, left);
6593 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6594 obstack_grow (&util_obstack,
6595 IDENTIFIER_POINTER (name),
6596 strlen (IDENTIFIER_POINTER (name)));
6597 else
6598 obstack_1grow (&util_obstack, '?');
6600 obstack_1grow (&util_obstack, '=');
6602 for (; fields; fields = TREE_CHAIN (fields))
6604 if (generating_instance_variables)
6606 tree fname = DECL_NAME (fields);
6608 obstack_1grow (&util_obstack, '"');
6609 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6611 obstack_grow (&util_obstack,
6612 IDENTIFIER_POINTER (fname),
6613 strlen (IDENTIFIER_POINTER (fname)));
6616 obstack_1grow (&util_obstack, '"');
6619 encode_field_decl (fields, curtype, format);
6622 obstack_1grow (&util_obstack, right);
6625 else
6627 obstack_1grow (&util_obstack, left);
6628 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6629 obstack_grow (&util_obstack,
6630 IDENTIFIER_POINTER (name),
6631 strlen (IDENTIFIER_POINTER (name)));
6632 else
6633 /* We have an untagged structure or a typedef. */
6634 obstack_1grow (&util_obstack, '?');
6636 obstack_1grow (&util_obstack, right);
6641 static void
6642 encode_aggregate (type, curtype, format)
6643 tree type;
6644 int curtype;
6645 int format;
6647 enum tree_code code = TREE_CODE (type);
6649 switch (code)
6651 case RECORD_TYPE:
6653 encode_aggregate_within(type, curtype, format, '{', '}');
6654 break;
6656 case UNION_TYPE:
6658 encode_aggregate_within(type, curtype, format, '(', ')');
6659 break;
6662 case ENUMERAL_TYPE:
6663 obstack_1grow (&util_obstack, 'i');
6664 break;
6666 default:
6667 break;
6671 /* Support bitfields. The current version of Objective-C does not support
6672 them. The string will consist of one or more "b:n"'s where n is an
6673 integer describing the width of the bitfield. Currently, classes in
6674 the kit implement a method "-(char *)describeBitfieldStruct:" that
6675 simulates this. If they do not implement this method, the archiver
6676 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6677 according to the GNU compiler. After looking at the "kit", it appears
6678 that all classes currently rely on this default behavior, rather than
6679 hand generating this string (which is tedious). */
6681 static void
6682 encode_bitfield (width)
6683 int width;
6685 char buffer[40];
6686 sprintf (buffer, "b%d", width);
6687 obstack_grow (&util_obstack, buffer, strlen (buffer));
6690 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6692 static void
6693 encode_type (type, curtype, format)
6694 tree type;
6695 int curtype;
6696 int format;
6698 enum tree_code code = TREE_CODE (type);
6700 if (code == INTEGER_TYPE)
6702 if (integer_zerop (TYPE_MIN_VALUE (type)))
6704 /* Unsigned integer types. */
6706 if (TYPE_MODE (type) == QImode)
6707 obstack_1grow (&util_obstack, 'C');
6708 else if (TYPE_MODE (type) == HImode)
6709 obstack_1grow (&util_obstack, 'S');
6710 else if (TYPE_MODE (type) == SImode)
6712 if (type == long_unsigned_type_node)
6713 obstack_1grow (&util_obstack, 'L');
6714 else
6715 obstack_1grow (&util_obstack, 'I');
6717 else if (TYPE_MODE (type) == DImode)
6718 obstack_1grow (&util_obstack, 'Q');
6721 else
6722 /* Signed integer types. */
6724 if (TYPE_MODE (type) == QImode)
6725 obstack_1grow (&util_obstack, 'c');
6726 else if (TYPE_MODE (type) == HImode)
6727 obstack_1grow (&util_obstack, 's');
6728 else if (TYPE_MODE (type) == SImode)
6730 if (type == long_integer_type_node)
6731 obstack_1grow (&util_obstack, 'l');
6732 else
6733 obstack_1grow (&util_obstack, 'i');
6736 else if (TYPE_MODE (type) == DImode)
6737 obstack_1grow (&util_obstack, 'q');
6741 else if (code == REAL_TYPE)
6743 /* Floating point types. */
6745 if (TYPE_MODE (type) == SFmode)
6746 obstack_1grow (&util_obstack, 'f');
6747 else if (TYPE_MODE (type) == DFmode
6748 || TYPE_MODE (type) == TFmode)
6749 obstack_1grow (&util_obstack, 'd');
6752 else if (code == VOID_TYPE)
6753 obstack_1grow (&util_obstack, 'v');
6755 else if (code == ARRAY_TYPE)
6756 encode_array (type, curtype, format);
6758 else if (code == POINTER_TYPE)
6759 encode_pointer (type, curtype, format);
6761 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6762 encode_aggregate (type, curtype, format);
6764 else if (code == FUNCTION_TYPE) /* '?' */
6765 obstack_1grow (&util_obstack, '?');
6768 static void
6769 encode_complete_bitfield (int position, tree type, int size)
6771 enum tree_code code = TREE_CODE (type);
6772 char buffer[40];
6773 char charType = '?';
6775 if (code == INTEGER_TYPE)
6777 if (integer_zerop (TYPE_MIN_VALUE (type)))
6779 /* Unsigned integer types. */
6781 if (TYPE_MODE (type) == QImode)
6782 charType = 'C';
6783 else if (TYPE_MODE (type) == HImode)
6784 charType = 'S';
6785 else if (TYPE_MODE (type) == SImode)
6787 if (type == long_unsigned_type_node)
6788 charType = 'L';
6789 else
6790 charType = 'I';
6792 else if (TYPE_MODE (type) == DImode)
6793 charType = 'Q';
6796 else
6797 /* Signed integer types. */
6799 if (TYPE_MODE (type) == QImode)
6800 charType = 'c';
6801 else if (TYPE_MODE (type) == HImode)
6802 charType = 's';
6803 else if (TYPE_MODE (type) == SImode)
6805 if (type == long_integer_type_node)
6806 charType = 'l';
6807 else
6808 charType = 'i';
6811 else if (TYPE_MODE (type) == DImode)
6812 charType = 'q';
6816 else
6817 abort ();
6819 sprintf (buffer, "b%d%c%d", position, charType, size);
6820 obstack_grow (&util_obstack, buffer, strlen (buffer));
6823 static void
6824 encode_field_decl (field_decl, curtype, format)
6825 tree field_decl;
6826 int curtype;
6827 int format;
6829 tree type;
6831 type = TREE_TYPE (field_decl);
6833 /* If this field is obviously a bitfield, or is a bitfield that has been
6834 clobbered to look like a ordinary integer mode, go ahead and generate
6835 the bitfield typing information. */
6836 if (flag_next_runtime)
6838 if (DECL_BIT_FIELD (field_decl))
6839 encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6840 else
6841 encode_type (TREE_TYPE (field_decl), curtype, format);
6843 else
6845 if (DECL_BIT_FIELD (field_decl))
6846 encode_complete_bitfield (int_bit_position (field_decl),
6847 DECL_BIT_FIELD_TYPE (field_decl),
6848 tree_low_cst (DECL_SIZE (field_decl), 1));
6849 else
6850 encode_type (TREE_TYPE (field_decl), curtype, format);
6854 static tree
6855 expr_last (complex_expr)
6856 tree complex_expr;
6858 tree next;
6860 if (complex_expr)
6861 while ((next = TREE_OPERAND (complex_expr, 0)))
6862 complex_expr = next;
6864 return complex_expr;
6867 /* Transform a method definition into a function definition as follows:
6868 - synthesize the first two arguments, "self" and "_cmd". */
6870 void
6871 start_method_def (method)
6872 tree method;
6874 tree decl_specs;
6876 /* Required to implement _msgSuper. */
6877 objc_method_context = method;
6878 UOBJC_SUPER_decl = NULL_TREE;
6880 /* Must be called BEFORE start_function. */
6881 pushlevel (0);
6883 /* Generate prototype declarations for arguments..."new-style". */
6885 if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
6886 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6887 else
6888 /* Really a `struct objc_class *'. However, we allow people to
6889 assign to self, which changes its type midstream. */
6890 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6892 push_parm_decl (build_tree_list
6893 (build_tree_list (decl_specs,
6894 build1 (INDIRECT_REF, NULL_TREE, self_id)),
6895 unused_list));
6897 decl_specs = build_tree_list (NULL_TREE,
6898 xref_tag (RECORD_TYPE,
6899 get_identifier (TAG_SELECTOR)));
6900 push_parm_decl (build_tree_list
6901 (build_tree_list (decl_specs,
6902 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6903 unused_list));
6905 /* Generate argument declarations if a keyword_decl. */
6906 if (METHOD_SEL_ARGS (method))
6908 tree arglist = METHOD_SEL_ARGS (method);
6911 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6912 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6914 if (arg_decl)
6916 tree last_expr = expr_last (arg_decl);
6918 /* Unite the abstract decl with its name. */
6919 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6920 push_parm_decl (build_tree_list
6921 (build_tree_list (arg_spec, arg_decl),
6922 NULL_TREE));
6924 /* Unhook: restore the abstract declarator. */
6925 TREE_OPERAND (last_expr, 0) = NULL_TREE;
6928 else
6929 push_parm_decl (build_tree_list
6930 (build_tree_list (arg_spec,
6931 KEYWORD_ARG_NAME (arglist)),
6932 NULL_TREE));
6934 arglist = TREE_CHAIN (arglist);
6936 while (arglist);
6939 if (METHOD_ADD_ARGS (method) != NULL_TREE
6940 && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
6942 /* We have a variable length selector - in "prototype" format. */
6943 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6944 while (akey)
6946 /* This must be done prior to calling pushdecl. pushdecl is
6947 going to change our chain on us. */
6948 tree nextkey = TREE_CHAIN (akey);
6949 pushdecl (akey);
6950 akey = nextkey;
6955 static void
6956 warn_with_method (message, mtype, method)
6957 const char *message;
6958 int mtype;
6959 tree method;
6961 if (count_error (1) == 0)
6962 return;
6964 report_error_function (DECL_SOURCE_FILE (method));
6966 /* Add a readable method name to the warning. */
6967 warning_with_file_and_line (DECL_SOURCE_FILE (method),
6968 DECL_SOURCE_LINE (method),
6969 "%s `%c%s'",
6970 message, mtype,
6971 gen_method_decl (method, errbuf));
6974 /* Return 1 if METHOD is consistent with PROTO. */
6976 static int
6977 comp_method_with_proto (method, proto)
6978 tree method, proto;
6980 /* Create a function template node at most once. */
6981 if (!function1_template)
6982 function1_template = make_node (FUNCTION_TYPE);
6984 /* Install argument types - normally set by build_function_type. */
6985 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
6987 /* install return type */
6988 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
6990 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
6993 /* Return 1 if PROTO1 is consistent with PROTO2. */
6995 static int
6996 comp_proto_with_proto (proto0, proto1)
6997 tree proto0, proto1;
6999 /* Create a couple of function_template nodes at most once. */
7000 if (!function1_template)
7001 function1_template = make_node (FUNCTION_TYPE);
7002 if (!function2_template)
7003 function2_template = make_node (FUNCTION_TYPE);
7005 /* Install argument types; normally set by build_function_type. */
7006 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
7007 TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
7009 /* Install return type. */
7010 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
7011 TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
7013 return comptypes (function1_template, function2_template);
7016 /* - Generate an identifier for the function. the format is "_n_cls",
7017 where 1 <= n <= nMethods, and cls is the name the implementation we
7018 are processing.
7019 - Install the return type from the method declaration.
7020 - If we have a prototype, check for type consistency. */
7022 static void
7023 really_start_method (method, parmlist)
7024 tree method, parmlist;
7026 tree sc_spec, ret_spec, ret_decl, decl_specs;
7027 tree method_decl, method_id;
7028 const char *sel_name, *class_name, *cat_name;
7029 char *buf;
7031 /* Synth the storage class & assemble the return type. */
7032 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7033 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7034 decl_specs = chainon (sc_spec, ret_spec);
7036 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7037 class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7038 cat_name = ((TREE_CODE (objc_implementation_context)
7039 == CLASS_IMPLEMENTATION_TYPE)
7040 ? NULL
7041 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7042 method_slot++;
7044 /* Make sure this is big enough for any plausible method label. */
7045 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7046 + (cat_name ? strlen (cat_name) : 0));
7048 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7049 class_name, cat_name, sel_name, method_slot);
7051 method_id = get_identifier (buf);
7053 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7055 /* Check the declarator portion of the return type for the method. */
7056 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7058 /* Unite the complex decl (specified in the abstract decl) with the
7059 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7060 tree save_expr = expr_last (ret_decl);
7062 TREE_OPERAND (save_expr, 0) = method_decl;
7063 method_decl = ret_decl;
7065 /* Fool the parser into thinking it is starting a function. */
7066 start_function (decl_specs, method_decl, NULL_TREE);
7068 /* Unhook: this has the effect of restoring the abstract declarator. */
7069 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7072 else
7074 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7076 /* Fool the parser into thinking it is starting a function. */
7077 start_function (decl_specs, method_decl, NULL_TREE);
7079 /* Unhook: this has the effect of restoring the abstract declarator. */
7080 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7083 METHOD_DEFINITION (method) = current_function_decl;
7085 /* Check consistency...start_function, pushdecl, duplicate_decls. */
7087 if (implementation_template != objc_implementation_context)
7089 tree proto;
7091 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7092 proto = lookup_instance_method_static (implementation_template,
7093 METHOD_SEL_NAME (method));
7094 else
7095 proto = lookup_class_method_static (implementation_template,
7096 METHOD_SEL_NAME (method));
7098 if (proto && ! comp_method_with_proto (method, proto))
7100 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7102 warn_with_method ("conflicting types for", type, method);
7103 warn_with_method ("previous declaration of", type, proto);
7108 /* The following routine is always called...this "architecture" is to
7109 accommodate "old-style" variable length selectors.
7111 - a:a b:b // prototype ; id c; id d; // old-style. */
7113 void
7114 continue_method_def ()
7116 tree parmlist;
7118 if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7119 /* We have a `, ...' immediately following the selector. */
7120 parmlist = get_parm_info (0);
7121 else
7122 parmlist = get_parm_info (1); /* place a `void_at_end' */
7124 /* Set self_decl from the first argument...this global is used by
7125 build_ivar_reference calling build_indirect_ref. */
7126 self_decl = TREE_PURPOSE (parmlist);
7128 poplevel (0, 0, 0);
7129 really_start_method (objc_method_context, parmlist);
7130 store_parm_decls ();
7133 /* Called by the parser, from the `pushlevel' production. */
7135 void
7136 add_objc_decls ()
7138 if (!UOBJC_SUPER_decl)
7140 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7141 build_tree_list (NULL_TREE,
7142 objc_super_template),
7143 0, NULL_TREE);
7145 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7147 /* This prevents `unused variable' warnings when compiling with -Wall. */
7148 TREE_USED (UOBJC_SUPER_decl) = 1;
7149 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7153 /* _n_Method (id self, SEL sel, ...)
7155 struct objc_super _S;
7156 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7157 } */
7159 tree
7160 get_super_receiver ()
7162 if (objc_method_context)
7164 tree super_expr, super_expr_list;
7166 /* Set receiver to self. */
7167 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7168 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7169 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7171 /* Set class to begin searching. */
7172 super_expr = build_component_ref (UOBJC_SUPER_decl,
7173 get_identifier ("class"));
7175 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7177 /* [_cls, __cls]Super are "pre-built" in
7178 synth_forward_declarations. */
7180 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7181 ((TREE_CODE (objc_method_context)
7182 == INSTANCE_METHOD_DECL)
7183 ? ucls_super_ref
7184 : uucls_super_ref));
7187 else
7188 /* We have a category. */
7190 tree super_name = CLASS_SUPER_NAME (implementation_template);
7191 tree super_class;
7193 /* Barf if super used in a category of Object. */
7194 if (!super_name)
7196 error ("no super class declared in interface for `%s'",
7197 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7198 return error_mark_node;
7201 if (flag_next_runtime)
7203 super_class = get_class_reference (super_name);
7204 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7205 super_class
7206 = build_component_ref (build_indirect_ref (super_class, "->"),
7207 get_identifier ("isa"));
7209 else
7211 add_class_reference (super_name);
7212 super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7213 ? objc_get_class_decl : objc_get_meta_class_decl);
7214 assemble_external (super_class);
7215 super_class
7216 = build_function_call
7217 (super_class,
7218 build_tree_list
7219 (NULL_TREE,
7220 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7221 IDENTIFIER_POINTER (super_name))));
7224 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7225 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7228 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7230 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7231 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7233 return build_compound_expr (super_expr_list);
7235 else
7237 error ("[super ...] must appear in a method context");
7238 return error_mark_node;
7242 static tree
7243 encode_method_def (func_decl)
7244 tree func_decl;
7246 tree parms;
7247 int stack_size;
7248 HOST_WIDE_INT max_parm_end = 0;
7249 char buffer[40];
7250 tree result;
7252 /* Return type. */
7253 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7254 obstack_object_size (&util_obstack),
7255 OBJC_ENCODE_INLINE_DEFS);
7257 /* Stack size. */
7258 for (parms = DECL_ARGUMENTS (func_decl); parms;
7259 parms = TREE_CHAIN (parms))
7261 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7262 + int_size_in_bytes (TREE_TYPE (parms)));
7264 if (! offset_is_register && parm_end > max_parm_end)
7265 max_parm_end = parm_end;
7268 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7270 sprintf (buffer, "%d", stack_size);
7271 obstack_grow (&util_obstack, buffer, strlen (buffer));
7273 /* Argument types. */
7274 for (parms = DECL_ARGUMENTS (func_decl); parms;
7275 parms = TREE_CHAIN (parms))
7277 /* Type. */
7278 encode_type (TREE_TYPE (parms),
7279 obstack_object_size (&util_obstack),
7280 OBJC_ENCODE_INLINE_DEFS);
7282 /* Compute offset. */
7283 sprintf (buffer, "%d", forwarding_offset (parms));
7285 /* Indicate register. */
7286 if (offset_is_register)
7287 obstack_1grow (&util_obstack, '+');
7289 obstack_grow (&util_obstack, buffer, strlen (buffer));
7292 /* Null terminate string. */
7293 obstack_1grow (&util_obstack, 0);
7294 result = get_identifier (obstack_finish (&util_obstack));
7295 obstack_free (&util_obstack, util_firstobj);
7296 return result;
7299 static void
7300 objc_expand_function_end ()
7302 METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
7305 void
7306 finish_method_def ()
7308 lang_expand_function_end = objc_expand_function_end;
7309 finish_function (0);
7310 lang_expand_function_end = NULL;
7312 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7313 since the optimizer may find "may be used before set" errors. */
7314 objc_method_context = NULL_TREE;
7317 #if 0
7319 lang_report_error_function (decl)
7320 tree decl;
7322 if (objc_method_context)
7324 fprintf (stderr, "In method `%s'\n",
7325 IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7326 return 1;
7329 else
7330 return 0;
7332 #endif
7334 static int
7335 is_complex_decl (type)
7336 tree type;
7338 return (TREE_CODE (type) == ARRAY_TYPE
7339 || TREE_CODE (type) == FUNCTION_TYPE
7340 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7344 /* Code to convert a decl node into text for a declaration in C. */
7346 static char tmpbuf[256];
7348 static void
7349 adorn_decl (decl, str)
7350 tree decl;
7351 char *str;
7353 enum tree_code code = TREE_CODE (decl);
7355 if (code == ARRAY_REF)
7357 tree an_int_cst = TREE_OPERAND (decl, 1);
7359 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7360 sprintf (str + strlen (str), "[%ld]",
7361 (long) TREE_INT_CST_LOW (an_int_cst));
7362 else
7363 strcat (str, "[]");
7366 else if (code == ARRAY_TYPE)
7368 tree an_int_cst = TYPE_SIZE (decl);
7369 tree array_of = TREE_TYPE (decl);
7371 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7372 sprintf (str + strlen (str), "[%ld]",
7373 (long) (TREE_INT_CST_LOW (an_int_cst)
7374 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7375 else
7376 strcat (str, "[]");
7379 else if (code == CALL_EXPR)
7381 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7383 strcat (str, "(");
7384 while (chain)
7386 gen_declaration_1 (chain, str);
7387 chain = TREE_CHAIN (chain);
7388 if (chain)
7389 strcat (str, ", ");
7391 strcat (str, ")");
7394 else if (code == FUNCTION_TYPE)
7396 tree chain = TYPE_ARG_TYPES (decl);
7398 strcat (str, "(");
7399 while (chain && TREE_VALUE (chain) != void_type_node)
7401 gen_declaration_1 (TREE_VALUE (chain), str);
7402 chain = TREE_CHAIN (chain);
7403 if (chain && TREE_VALUE (chain) != void_type_node)
7404 strcat (str, ", ");
7406 strcat (str, ")");
7409 else if (code == INDIRECT_REF)
7411 strcpy (tmpbuf, "*");
7412 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7414 tree chain;
7416 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7417 chain;
7418 chain = TREE_CHAIN (chain))
7420 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7422 strcat (tmpbuf, " ");
7423 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7426 if (str[0])
7427 strcat (tmpbuf, " ");
7429 strcat (tmpbuf, str);
7430 strcpy (str, tmpbuf);
7433 else if (code == POINTER_TYPE)
7435 strcpy (tmpbuf, "*");
7436 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7438 if (TREE_READONLY (decl))
7439 strcat (tmpbuf, " const");
7440 if (TYPE_VOLATILE (decl))
7441 strcat (tmpbuf, " volatile");
7442 if (str[0])
7443 strcat (tmpbuf, " ");
7445 strcat (tmpbuf, str);
7446 strcpy (str, tmpbuf);
7450 static char *
7451 gen_declarator (decl, buf, name)
7452 tree decl;
7453 char *buf;
7454 const char *name;
7456 if (decl)
7458 enum tree_code code = TREE_CODE (decl);
7459 char *str;
7460 tree op;
7461 int wrap = 0;
7463 switch (code)
7465 case ARRAY_REF:
7466 case INDIRECT_REF:
7467 case CALL_EXPR:
7468 op = TREE_OPERAND (decl, 0);
7470 /* We have a pointer to a function or array...(*)(), (*)[] */
7471 if ((code == ARRAY_REF || code == CALL_EXPR)
7472 && op && TREE_CODE (op) == INDIRECT_REF)
7473 wrap = 1;
7475 str = gen_declarator (op, buf, name);
7477 if (wrap)
7479 strcpy (tmpbuf, "(");
7480 strcat (tmpbuf, str);
7481 strcat (tmpbuf, ")");
7482 strcpy (str, tmpbuf);
7485 adorn_decl (decl, str);
7486 break;
7488 case ARRAY_TYPE:
7489 case FUNCTION_TYPE:
7490 case POINTER_TYPE:
7491 strcpy (buf, name);
7492 str = buf;
7494 /* This clause is done iteratively rather than recursively. */
7497 op = (is_complex_decl (TREE_TYPE (decl))
7498 ? TREE_TYPE (decl) : NULL_TREE);
7500 adorn_decl (decl, str);
7502 /* We have a pointer to a function or array...(*)(), (*)[] */
7503 if (code == POINTER_TYPE
7504 && op && (TREE_CODE (op) == FUNCTION_TYPE
7505 || TREE_CODE (op) == ARRAY_TYPE))
7507 strcpy (tmpbuf, "(");
7508 strcat (tmpbuf, str);
7509 strcat (tmpbuf, ")");
7510 strcpy (str, tmpbuf);
7513 decl = (is_complex_decl (TREE_TYPE (decl))
7514 ? TREE_TYPE (decl) : NULL_TREE);
7517 while (decl && (code = TREE_CODE (decl)))
7520 break;
7522 case IDENTIFIER_NODE:
7523 /* Will only happen if we are processing a "raw" expr-decl. */
7524 strcpy (buf, IDENTIFIER_POINTER (decl));
7525 return buf;
7527 default:
7528 abort ();
7531 return str;
7534 else
7535 /* We have an abstract declarator or a _DECL node. */
7537 strcpy (buf, name);
7538 return buf;
7542 static void
7543 gen_declspecs (declspecs, buf, raw)
7544 tree declspecs;
7545 char *buf;
7546 int raw;
7548 if (raw)
7550 tree chain;
7552 for (chain = nreverse (copy_list (declspecs));
7553 chain; chain = TREE_CHAIN (chain))
7555 tree aspec = TREE_VALUE (chain);
7557 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7558 strcat (buf, IDENTIFIER_POINTER (aspec));
7559 else if (TREE_CODE (aspec) == RECORD_TYPE)
7561 if (TYPE_NAME (aspec))
7563 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7565 if (! TREE_STATIC_TEMPLATE (aspec))
7566 strcat (buf, "struct ");
7567 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7569 /* NEW!!! */
7570 if (protocol_list)
7572 tree chain = protocol_list;
7574 strcat (buf, " <");
7575 while (chain)
7577 strcat (buf,
7578 IDENTIFIER_POINTER
7579 (PROTOCOL_NAME (TREE_VALUE (chain))));
7580 chain = TREE_CHAIN (chain);
7581 if (chain)
7582 strcat (buf, ", ");
7584 strcat (buf, ">");
7588 else
7589 strcat (buf, "untagged struct");
7592 else if (TREE_CODE (aspec) == UNION_TYPE)
7594 if (TYPE_NAME (aspec))
7596 if (! TREE_STATIC_TEMPLATE (aspec))
7597 strcat (buf, "union ");
7598 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7600 else
7601 strcat (buf, "untagged union");
7604 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7606 if (TYPE_NAME (aspec))
7608 if (! TREE_STATIC_TEMPLATE (aspec))
7609 strcat (buf, "enum ");
7610 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7612 else
7613 strcat (buf, "untagged enum");
7616 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7617 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7619 else if (IS_ID (aspec))
7621 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7623 strcat (buf, "id");
7624 if (protocol_list)
7626 tree chain = protocol_list;
7628 strcat (buf, " <");
7629 while (chain)
7631 strcat (buf,
7632 IDENTIFIER_POINTER
7633 (PROTOCOL_NAME (TREE_VALUE (chain))));
7634 chain = TREE_CHAIN (chain);
7635 if (chain)
7636 strcat (buf, ", ");
7638 strcat (buf, ">");
7641 if (TREE_CHAIN (chain))
7642 strcat (buf, " ");
7645 else
7647 /* Type qualifiers. */
7648 if (TREE_READONLY (declspecs))
7649 strcat (buf, "const ");
7650 if (TYPE_VOLATILE (declspecs))
7651 strcat (buf, "volatile ");
7653 switch (TREE_CODE (declspecs))
7655 /* Type specifiers. */
7657 case INTEGER_TYPE:
7658 declspecs = TYPE_MAIN_VARIANT (declspecs);
7660 /* Signed integer types. */
7662 if (declspecs == short_integer_type_node)
7663 strcat (buf, "short int ");
7664 else if (declspecs == integer_type_node)
7665 strcat (buf, "int ");
7666 else if (declspecs == long_integer_type_node)
7667 strcat (buf, "long int ");
7668 else if (declspecs == long_long_integer_type_node)
7669 strcat (buf, "long long int ");
7670 else if (declspecs == signed_char_type_node
7671 || declspecs == char_type_node)
7672 strcat (buf, "char ");
7674 /* Unsigned integer types. */
7676 else if (declspecs == short_unsigned_type_node)
7677 strcat (buf, "unsigned short ");
7678 else if (declspecs == unsigned_type_node)
7679 strcat (buf, "unsigned int ");
7680 else if (declspecs == long_unsigned_type_node)
7681 strcat (buf, "unsigned long ");
7682 else if (declspecs == long_long_unsigned_type_node)
7683 strcat (buf, "unsigned long long ");
7684 else if (declspecs == unsigned_char_type_node)
7685 strcat (buf, "unsigned char ");
7686 break;
7688 case REAL_TYPE:
7689 declspecs = TYPE_MAIN_VARIANT (declspecs);
7691 if (declspecs == float_type_node)
7692 strcat (buf, "float ");
7693 else if (declspecs == double_type_node)
7694 strcat (buf, "double ");
7695 else if (declspecs == long_double_type_node)
7696 strcat (buf, "long double ");
7697 break;
7699 case RECORD_TYPE:
7700 if (TYPE_NAME (declspecs)
7701 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7703 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7705 if (! TREE_STATIC_TEMPLATE (declspecs))
7706 strcat (buf, "struct ");
7707 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7709 if (protocol_list)
7711 tree chain = protocol_list;
7713 strcat (buf, " <");
7714 while (chain)
7716 strcat (buf,
7717 IDENTIFIER_POINTER
7718 (PROTOCOL_NAME (TREE_VALUE (chain))));
7719 chain = TREE_CHAIN (chain);
7720 if (chain)
7721 strcat (buf, ", ");
7723 strcat (buf, ">");
7727 else
7728 strcat (buf, "untagged struct");
7730 strcat (buf, " ");
7731 break;
7733 case UNION_TYPE:
7734 if (TYPE_NAME (declspecs)
7735 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7737 strcat (buf, "union ");
7738 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7739 strcat (buf, " ");
7742 else
7743 strcat (buf, "untagged union ");
7744 break;
7746 case ENUMERAL_TYPE:
7747 if (TYPE_NAME (declspecs)
7748 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7750 strcat (buf, "enum ");
7751 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7752 strcat (buf, " ");
7755 else
7756 strcat (buf, "untagged enum ");
7757 break;
7759 case VOID_TYPE:
7760 strcat (buf, "void ");
7761 break;
7763 case POINTER_TYPE:
7765 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7767 strcat (buf, "id");
7768 if (protocol_list)
7770 tree chain = protocol_list;
7772 strcat (buf, " <");
7773 while (chain)
7775 strcat (buf,
7776 IDENTIFIER_POINTER
7777 (PROTOCOL_NAME (TREE_VALUE (chain))));
7778 chain = TREE_CHAIN (chain);
7779 if (chain)
7780 strcat (buf, ", ");
7783 strcat (buf, ">");
7786 break;
7788 default:
7789 break;
7794 /* Given a tree node, produce a printable description of it in the given
7795 buffer, overwriting the buffer. */
7797 static char *
7798 gen_declaration (atype_or_adecl, buf)
7799 tree atype_or_adecl;
7800 char *buf;
7802 buf[0] = '\0';
7803 gen_declaration_1 (atype_or_adecl, buf);
7804 return buf;
7807 /* Given a tree node, append a printable description to the end of the
7808 given buffer. */
7810 static void
7811 gen_declaration_1 (atype_or_adecl, buf)
7812 tree atype_or_adecl;
7813 char *buf;
7815 char declbuf[256];
7817 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7819 tree declspecs; /* "identifier_node", "record_type" */
7820 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7822 /* We have a "raw", abstract declarator (typename). */
7823 declarator = TREE_VALUE (atype_or_adecl);
7824 declspecs = TREE_PURPOSE (atype_or_adecl);
7826 gen_declspecs (declspecs, buf, 1);
7827 if (declarator)
7829 strcat (buf, " ");
7830 strcat (buf, gen_declarator (declarator, declbuf, ""));
7834 else
7836 tree atype;
7837 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7838 tree declarator; /* "array_type", "function_type", "pointer_type". */
7840 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7841 || TREE_CODE (atype_or_adecl) == PARM_DECL
7842 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7843 atype = TREE_TYPE (atype_or_adecl);
7844 else
7845 /* Assume we have a *_type node. */
7846 atype = atype_or_adecl;
7848 if (is_complex_decl (atype))
7850 tree chain;
7852 /* Get the declaration specifier; it is at the end of the list. */
7853 declarator = chain = atype;
7855 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7856 while (is_complex_decl (chain));
7857 declspecs = chain;
7860 else
7862 declspecs = atype;
7863 declarator = NULL_TREE;
7866 gen_declspecs (declspecs, buf, 0);
7868 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7869 || TREE_CODE (atype_or_adecl) == PARM_DECL
7870 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7872 const char *const decl_name =
7873 (DECL_NAME (atype_or_adecl)
7874 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
7876 if (declarator)
7878 strcat (buf, " ");
7879 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7882 else if (decl_name[0])
7884 strcat (buf, " ");
7885 strcat (buf, decl_name);
7888 else if (declarator)
7890 strcat (buf, " ");
7891 strcat (buf, gen_declarator (declarator, declbuf, ""));
7896 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7898 /* Given a method tree, put a printable description into the given
7899 buffer (overwriting) and return a pointer to the buffer. */
7901 static char *
7902 gen_method_decl (method, buf)
7903 tree method;
7904 char *buf;
7906 tree chain;
7908 buf[0] = '\0';
7909 if (RAW_TYPESPEC (method) != objc_object_reference)
7911 strcat (buf, "(");
7912 gen_declaration_1 (TREE_TYPE (method), buf);
7913 strcat (buf, ")");
7916 chain = METHOD_SEL_ARGS (method);
7917 if (chain)
7919 /* We have a chain of keyword_decls. */
7922 if (KEYWORD_KEY_NAME (chain))
7923 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7925 strcat (buf, ":");
7926 if (RAW_TYPESPEC (chain) != objc_object_reference)
7928 strcat (buf, "(");
7929 gen_declaration_1 (TREE_TYPE (chain), buf);
7930 strcat (buf, ")");
7933 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7934 if ((chain = TREE_CHAIN (chain)))
7935 strcat (buf, " ");
7937 while (chain);
7939 if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
7940 strcat (buf, ", ...");
7941 else if (METHOD_ADD_ARGS (method))
7943 /* We have a tree list node as generate by get_parm_info. */
7944 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7946 /* Know we have a chain of parm_decls. */
7947 while (chain)
7949 strcat (buf, ", ");
7950 gen_declaration_1 (chain, buf);
7951 chain = TREE_CHAIN (chain);
7956 else
7957 /* We have a unary selector. */
7958 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7960 return buf;
7963 /* Debug info. */
7965 static void
7966 dump_interface (fp, chain)
7967 FILE *fp;
7968 tree chain;
7970 char *buf = (char *)xmalloc (256);
7971 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7972 tree ivar_decls = CLASS_RAW_IVARS (chain);
7973 tree nst_methods = CLASS_NST_METHODS (chain);
7974 tree cls_methods = CLASS_CLS_METHODS (chain);
7976 fprintf (fp, "\n@interface %s", my_name);
7978 if (CLASS_SUPER_NAME (chain))
7980 const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7981 fprintf (fp, " : %s\n", super_name);
7983 else
7984 fprintf (fp, "\n");
7986 if (ivar_decls)
7988 fprintf (fp, "{\n");
7991 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7992 ivar_decls = TREE_CHAIN (ivar_decls);
7994 while (ivar_decls);
7995 fprintf (fp, "}\n");
7998 while (nst_methods)
8000 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8001 nst_methods = TREE_CHAIN (nst_methods);
8004 while (cls_methods)
8006 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8007 cls_methods = TREE_CHAIN (cls_methods);
8009 fprintf (fp, "\n@end");
8012 /* Demangle function for Objective-C */
8013 static const char *
8014 objc_demangle (mangled)
8015 const char *mangled;
8017 char *demangled, *cp;
8019 if (mangled[0] == '_' &&
8020 (mangled[1] == 'i' || mangled[1] == 'c') &&
8021 mangled[2] == '_')
8023 cp = demangled = xmalloc(strlen(mangled) + 2);
8024 if (mangled[1] == 'i')
8025 *cp++ = '-'; /* for instance method */
8026 else
8027 *cp++ = '+'; /* for class method */
8028 *cp++ = '['; /* opening left brace */
8029 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8030 while (*cp && *cp == '_')
8031 cp++; /* skip any initial underbars in class name */
8032 cp = strchr(cp, '_'); /* find first non-initial underbar */
8033 if (cp == NULL)
8035 free(demangled); /* not mangled name */
8036 return mangled;
8038 if (cp[1] == '_') /* easy case: no category name */
8040 *cp++ = ' '; /* replace two '_' with one ' ' */
8041 strcpy(cp, mangled + (cp - demangled) + 2);
8043 else
8045 *cp++ = '('; /* less easy case: category name */
8046 cp = strchr(cp, '_');
8047 if (cp == 0)
8049 free(demangled); /* not mangled name */
8050 return mangled;
8052 *cp++ = ')';
8053 *cp++ = ' '; /* overwriting 1st char of method name... */
8054 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8056 while (*cp && *cp == '_')
8057 cp++; /* skip any initial underbars in method name */
8058 for (; *cp; cp++)
8059 if (*cp == '_')
8060 *cp = ':'; /* replace remaining '_' with ':' */
8061 *cp++ = ']'; /* closing right brace */
8062 *cp++ = 0; /* string terminator */
8063 return demangled;
8065 else
8066 return mangled; /* not an objc mangled name */
8069 static const char *
8070 objc_printable_name (decl, kind)
8071 tree decl;
8072 int kind ATTRIBUTE_UNUSED;
8074 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8077 static void
8078 init_objc ()
8080 /* Add the special tree codes of Objective C to the tables. */
8082 gcc_obstack_init (&util_obstack);
8083 util_firstobj = (char *) obstack_finish (&util_obstack);
8085 memcpy (tree_code_type + (int) LAST_BASE_TREE_CODE,
8086 objc_tree_code_type,
8087 (int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE);
8088 memcpy (tree_code_length + (int) LAST_BASE_TREE_CODE,
8089 objc_tree_code_length,
8090 (((int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE) * sizeof (int)));
8091 memcpy (tree_code_name + (int) LAST_BASE_TREE_CODE,
8092 objc_tree_code_name,
8093 (((int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE) * sizeof (char *)));
8095 errbuf = (char *)xmalloc (BUFSIZE);
8096 hash_init ();
8097 synth_module_prologue ();
8100 static void
8101 finish_objc ()
8103 struct imp_entry *impent;
8104 tree chain;
8105 /* The internally generated initializers appear to have missing braces.
8106 Don't warn about this. */
8107 int save_warn_missing_braces = warn_missing_braces;
8108 warn_missing_braces = 0;
8110 /* A missing @end may not be detected by the parser. */
8111 if (objc_implementation_context)
8113 warning ("`@end' missing in implementation context");
8114 finish_class (objc_implementation_context);
8115 objc_ivar_chain = NULL_TREE;
8116 objc_implementation_context = NULL_TREE;
8119 generate_forward_declaration_to_string_table ();
8121 #ifdef OBJC_PROLOGUE
8122 OBJC_PROLOGUE;
8123 #endif
8125 /* Process the static instances here because initialization of objc_symtab
8126 depends on them. */
8127 if (objc_static_instances)
8128 generate_static_references ();
8130 if (imp_list || class_names_chain
8131 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8132 generate_objc_symtab_decl ();
8134 for (impent = imp_list; impent; impent = impent->next)
8136 objc_implementation_context = impent->imp_context;
8137 implementation_template = impent->imp_template;
8139 UOBJC_CLASS_decl = impent->class_decl;
8140 UOBJC_METACLASS_decl = impent->meta_decl;
8142 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8144 /* all of the following reference the string pool... */
8145 generate_ivar_lists ();
8146 generate_dispatch_tables ();
8147 generate_shared_structures ();
8149 else
8151 generate_dispatch_tables ();
8152 generate_category (objc_implementation_context);
8156 /* If we are using an array of selectors, we must always
8157 finish up the array decl even if no selectors were used. */
8158 if (! flag_next_runtime || sel_ref_chain)
8159 build_selector_translation_table ();
8161 if (protocol_chain)
8162 generate_protocols ();
8164 if (objc_implementation_context || class_names_chain || objc_static_instances
8165 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8167 /* Arrange for Objc data structures to be initialized at run time. */
8168 rtx init_sym = build_module_descriptor ();
8169 if (init_sym && targetm.have_ctors_dtors)
8170 (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8173 /* Dump the class references. This forces the appropriate classes
8174 to be linked into the executable image, preserving unix archive
8175 semantics. This can be removed when we move to a more dynamically
8176 linked environment. */
8178 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8180 handle_class_ref (chain);
8181 if (TREE_PURPOSE (chain))
8182 generate_classref_translation_entry (chain);
8185 for (impent = imp_list; impent; impent = impent->next)
8186 handle_impent (impent);
8188 /* Dump the string table last. */
8190 generate_strings ();
8192 if (flag_gen_declaration)
8194 add_class (objc_implementation_context);
8195 dump_interface (gen_declaration_file, objc_implementation_context);
8198 if (warn_selector)
8200 int slot;
8201 hash hsh;
8203 /* Run through the selector hash tables and print a warning for any
8204 selector which has multiple methods. */
8206 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8207 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8208 if (hsh->list)
8210 tree meth = hsh->key;
8211 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8212 ? '-' : '+');
8213 attr loop;
8215 warning ("potential selector conflict for method `%s'",
8216 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8217 warn_with_method ("found", type, meth);
8218 for (loop = hsh->list; loop; loop = loop->next)
8219 warn_with_method ("found", type, loop->value);
8222 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8223 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8224 if (hsh->list)
8226 tree meth = hsh->key;
8227 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8228 ? '-' : '+');
8229 attr loop;
8231 warning ("potential selector conflict for method `%s'",
8232 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8233 warn_with_method ("found", type, meth);
8234 for (loop = hsh->list; loop; loop = loop->next)
8235 warn_with_method ("found", type, loop->value);
8239 warn_missing_braces = save_warn_missing_braces;
8242 /* Subroutines of finish_objc. */
8244 static void
8245 generate_classref_translation_entry (chain)
8246 tree chain;
8248 tree expr, name, decl_specs, decl, sc_spec;
8249 tree type;
8251 type = TREE_TYPE (TREE_PURPOSE (chain));
8253 expr = add_objc_string (TREE_VALUE (chain), class_names);
8254 expr = build_c_cast (type, expr); /* cast! */
8256 name = DECL_NAME (TREE_PURPOSE (chain));
8258 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8260 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8261 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8263 /* The decl that is returned from start_decl is the one that we
8264 forward declared in build_class_reference. */
8265 decl = start_decl (name, decl_specs, 1, NULL_TREE);
8266 DECL_CONTEXT (decl) = NULL_TREE;
8267 finish_decl (decl, expr, NULL_TREE);
8268 return;
8271 static void
8272 handle_class_ref (chain)
8273 tree chain;
8275 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8276 char *string = (char *) alloca (strlen (name) + 30);
8277 tree decl;
8278 tree exp;
8280 sprintf (string, "%sobjc_class_name_%s",
8281 (flag_next_runtime ? "." : "__"), name);
8283 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8284 if (flag_next_runtime)
8286 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8287 return;
8289 #endif
8291 /* Make a decl for this name, so we can use its address in a tree. */
8292 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8293 DECL_EXTERNAL (decl) = 1;
8294 TREE_PUBLIC (decl) = 1;
8296 pushdecl (decl);
8297 rest_of_decl_compilation (decl, 0, 0, 0);
8299 /* Make a decl for the address. */
8300 sprintf (string, "%sobjc_class_ref_%s",
8301 (flag_next_runtime ? "." : "__"), name);
8302 exp = build1 (ADDR_EXPR, string_type_node, decl);
8303 decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8304 DECL_INITIAL (decl) = exp;
8305 TREE_STATIC (decl) = 1;
8307 pushdecl (decl);
8308 rest_of_decl_compilation (decl, 0, 0, 0);
8311 static void
8312 handle_impent (impent)
8313 struct imp_entry *impent;
8315 char *string;
8317 objc_implementation_context = impent->imp_context;
8318 implementation_template = impent->imp_template;
8320 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8322 const char *const class_name =
8323 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8325 string = (char *) alloca (strlen (class_name) + 30);
8327 sprintf (string, "*%sobjc_class_name_%s",
8328 (flag_next_runtime ? "." : "__"), class_name);
8330 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8332 const char *const class_name =
8333 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8334 const char *const class_super_name =
8335 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8337 string = (char *) alloca (strlen (class_name)
8338 + strlen (class_super_name) + 30);
8340 /* Do the same for categories. Even though no references to
8341 these symbols are generated automatically by the compiler, it
8342 gives you a handle to pull them into an archive by hand. */
8343 sprintf (string, "*%sobjc_category_name_%s_%s",
8344 (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8346 else
8347 return;
8349 #ifdef ASM_DECLARE_CLASS_REFERENCE
8350 if (flag_next_runtime)
8352 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8353 return;
8355 #endif
8357 /* (Should this be a routine in varasm.c?) */
8358 readonly_data_section ();
8359 assemble_global (string);
8360 assemble_align (UNITS_PER_WORD);
8361 assemble_label (string);
8362 assemble_zeros (UNITS_PER_WORD);
8365 static void
8366 ggc_mark_imp_list (arg)
8367 void *arg;
8369 struct imp_entry *impent;
8371 for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
8373 ggc_mark_tree (impent->imp_context);
8374 ggc_mark_tree (impent->imp_template);
8375 ggc_mark_tree (impent->class_decl);
8376 ggc_mark_tree (impent->meta_decl);
8380 static void
8381 ggc_mark_hash_table (arg)
8382 void *arg;
8384 hash *hash_table = *(hash **)arg;
8385 hash hst;
8386 attr list;
8387 int i;
8389 if (hash_table == NULL)
8390 return;
8391 for (i = 0; i < SIZEHASHTABLE; i++)
8392 for (hst = hash_table [i]; hst; hst = hst->next)
8394 ggc_mark_tree (hst->key);
8395 for (list = hst->list; list; list = list->next)
8396 ggc_mark_tree (list->value);
8400 /* Add GC roots for variables local to this file. */
8401 static void
8402 objc_act_parse_init ()
8404 ggc_add_tree_root (objc_global_trees, OCTI_MAX);
8405 ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list);
8406 ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table);
8407 ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table);
8410 /* Look up ID as an instance variable. */
8411 tree
8412 lookup_objc_ivar (id)
8413 tree id;
8415 tree decl;
8417 if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8418 /* we have a message to super */
8419 return get_super_receiver ();
8420 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8422 if (is_private (decl))
8423 return error_mark_node;
8424 else
8425 return build_ivar_reference (id);
8427 else
8428 return 0;