* class.c (check_bitfield_decl): New function, split out from
[official-gcc.git] / gcc / objc / objc-act.c
blob5cb797b2de738b5a00f2095d8ca8b44036bc013a
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 93-95, 97, 1998 Free Software Foundation, Inc.
3 Contributed by Steve Naroff.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Purpose: This module implements the Objective-C 4.0 language.
24 compatibility issues (with the Stepstone translator):
26 - does not recognize the following 3.3 constructs.
27 @requires, @classes, @messages, = (...)
28 - methods with variable arguments must conform to ANSI standard.
29 - tagged structure definitions that appear in BOTH the interface
30 and implementation are not allowed.
31 - public/private: all instance variables are public within the
32 context of the implementation...I consider this to be a bug in
33 the translator.
34 - statically allocated objects are not supported. the user will
35 receive an error if this service is requested.
37 code generation `options':
39 - OBJC_INT_SELECTORS */
41 #include "config.h"
42 #include "system.h"
43 #include "tree.h"
44 #include "c-tree.h"
45 #include "c-lex.h"
46 #include "flags.h"
47 #include "objc-act.h"
48 #include "input.h"
49 #include "except.h"
50 #include "function.h"
51 #include "output.h"
52 #include "toplev.h"
54 #if USE_CPPLIB
55 #include "cpplib.h"
56 extern cpp_reader parse_in;
57 extern cpp_options parse_options;
58 #endif
60 /* This is the default way of generating a method name. */
61 /* I am not sure it is really correct.
62 Perhaps there's a danger that it will make name conflicts
63 if method names contain underscores. -- rms. */
64 #ifndef OBJC_GEN_METHOD_LABEL
65 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
66 do { \
67 char *temp; \
68 sprintf ((BUF), "_%s_%s_%s_%s", \
69 ((IS_INST) ? "i" : "c"), \
70 (CLASS_NAME), \
71 ((CAT_NAME)? (CAT_NAME) : ""), \
72 (SEL_NAME)); \
73 for (temp = (BUF); *temp; temp++) \
74 if (*temp == ':') *temp = '_'; \
75 } while (0)
76 #endif
78 /* These need specifying. */
79 #ifndef OBJC_FORWARDING_STACK_OFFSET
80 #define OBJC_FORWARDING_STACK_OFFSET 0
81 #endif
83 #ifndef OBJC_FORWARDING_MIN_OFFSET
84 #define OBJC_FORWARDING_MIN_OFFSET 0
85 #endif
87 /* Define the special tree codes that we use. */
89 /* Table indexed by tree code giving a string containing a character
90 classifying the tree code. Possibilities are
91 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
93 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
95 static const char objc_tree_code_type[] = {
96 'x',
97 #include "objc-tree.def"
99 #undef DEFTREECODE
101 /* Table indexed by tree code giving number of expression
102 operands beyond the fixed part of the node structure.
103 Not used for types or decls. */
105 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
107 static const int objc_tree_code_length[] = {
109 #include "objc-tree.def"
111 #undef DEFTREECODE
113 /* Names of tree components.
114 Used for printing out the tree and error messages. */
115 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
117 static const char * const objc_tree_code_name[] = {
118 "@@dummy",
119 #include "objc-tree.def"
121 #undef DEFTREECODE
123 /* Set up for use of obstacks. */
125 #include "obstack.h"
127 #define obstack_chunk_alloc xmalloc
128 #define obstack_chunk_free free
130 /* This obstack is used to accumulate the encoding of a data type. */
131 static struct obstack util_obstack;
132 /* This points to the beginning of obstack contents,
133 so we can free the whole contents. */
134 char *util_firstobj;
136 /* List of classes with list of their static instances. */
137 static tree objc_static_instances = NULL_TREE;
139 /* The declaration of the array administrating the static instances. */
140 static tree static_instances_decl = NULL_TREE;
142 /* for encode_method_def */
143 #include "rtl.h"
144 #include "c-parse.h"
146 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
147 #define PROTOCOL_VERSION 2
149 #define OBJC_ENCODE_INLINE_DEFS 0
150 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
152 /*** Private Interface (procedures) ***/
154 /* Used by compile_file. */
156 static void init_objc PROTO((void));
157 static void finish_objc PROTO((void));
159 /* Code generation. */
161 static void synth_module_prologue PROTO((void));
162 static tree build_constructor PROTO((tree, tree));
163 static char *build_module_descriptor PROTO((void));
164 static tree init_module_descriptor PROTO((tree));
165 static tree build_objc_method_call PROTO((int, tree, tree,
166 tree, tree, tree));
167 static void generate_strings PROTO((void));
168 static tree get_proto_encoding PROTO((tree));
169 static void build_selector_translation_table PROTO((void));
170 static tree build_ivar_chain PROTO((tree, int));
172 static tree objc_add_static_instance PROTO((tree, tree));
174 static tree build_ivar_template PROTO((void));
175 static tree build_method_template PROTO((void));
176 static tree build_private_template PROTO((tree));
177 static void build_class_template PROTO((void));
178 static void build_selector_template PROTO((void));
179 static void build_category_template PROTO((void));
180 static tree build_super_template PROTO((void));
181 static tree build_category_initializer PROTO((tree, tree, tree,
182 tree, tree, tree));
183 static tree build_protocol_initializer PROTO((tree, tree, tree,
184 tree, tree));
186 static void synth_forward_declarations PROTO((void));
187 static void generate_ivar_lists PROTO((void));
188 static void generate_dispatch_tables PROTO((void));
189 static void generate_shared_structures PROTO((void));
190 static tree generate_protocol_list PROTO((tree));
191 static void generate_forward_declaration_to_string_table PROTO((void));
192 static void build_protocol_reference PROTO((tree));
194 #if 0
195 static tree init_selector PROTO((int));
196 #endif
197 static tree build_keyword_selector PROTO((tree));
198 static tree synth_id_with_class_suffix PROTO((const char *, tree));
200 static void generate_static_references PROTO((void));
201 static int check_methods_accessible PROTO((tree, tree,
202 int));
203 static void encode_aggregate_within PROTO((tree, int, int,
204 int, int));
205 static const char *objc_demangle PROTO((const char *));
206 static const char *objc_printable_name PROTO((tree, int));
208 /* Misc. bookkeeping */
210 typedef struct hashed_entry *hash;
211 typedef struct hashed_attribute *attr;
213 struct hashed_attribute
215 attr next;
216 tree value;
218 struct hashed_entry
220 attr list;
221 hash next;
222 tree key;
225 static void hash_init PROTO((void));
226 static void hash_enter PROTO((hash *, tree));
227 static hash hash_lookup PROTO((hash *, tree));
228 static void hash_add_attr PROTO((hash, tree));
229 static tree lookup_method PROTO((tree, tree));
230 static tree lookup_instance_method_static PROTO((tree, tree));
231 static tree lookup_class_method_static PROTO((tree, tree));
232 static tree add_class PROTO((tree));
233 static void add_category PROTO((tree, tree));
235 enum string_section
237 class_names, /* class, category, protocol, module names */
238 meth_var_names, /* method and variable names */
239 meth_var_types /* method and variable type descriptors */
242 static tree add_objc_string PROTO((tree,
243 enum string_section));
244 static tree get_objc_string_decl PROTO((tree,
245 enum string_section));
246 static tree build_objc_string_decl PROTO((enum string_section));
247 static tree build_selector_reference_decl PROTO((void));
249 /* Protocol additions. */
251 static tree add_protocol PROTO((tree));
252 static tree lookup_protocol PROTO((tree));
253 static tree lookup_and_install_protocols PROTO((tree));
255 /* Type encoding. */
257 static void encode_type_qualifiers PROTO((tree));
258 static void encode_pointer PROTO((tree, int, int));
259 static void encode_array PROTO((tree, int, int));
260 static void encode_aggregate PROTO((tree, int, int));
261 static void encode_bitfield PROTO((int));
262 static void encode_type PROTO((tree, int, int));
263 static void encode_field_decl PROTO((tree, int, int));
265 static void really_start_method PROTO((tree, tree));
266 static int comp_method_with_proto PROTO((tree, tree));
267 static int comp_proto_with_proto PROTO((tree, tree));
268 static tree get_arg_type_list PROTO((tree, int, int));
269 static tree expr_last PROTO((tree));
271 /* Utilities for debugging and error diagnostics. */
273 static void warn_with_method PROTO((const char *, int, tree));
274 static void error_with_ivar PROTO((const char *, tree, tree));
275 static char *gen_method_decl PROTO((tree, char *));
276 static char *gen_declaration PROTO((tree, char *));
277 static char *gen_declarator PROTO((tree, char *,
278 const char *));
279 static int is_complex_decl PROTO((tree));
280 static void adorn_decl PROTO((tree, char *));
281 static void dump_interface PROTO((FILE *, tree));
283 /* Everything else. */
285 static void objc_fatal PROTO((void))
286 ATTRIBUTE_NORETURN;
287 static tree define_decl PROTO((tree, tree));
288 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
289 static tree lookup_protocol_in_reflist PROTO((tree, tree));
290 static tree create_builtin_decl PROTO((enum tree_code,
291 tree, const char *));
292 static tree my_build_string PROTO((int, const char *));
293 static void build_objc_symtab_template PROTO((void));
294 static tree init_def_list PROTO((tree));
295 static tree init_objc_symtab PROTO((tree));
296 static void forward_declare_categories PROTO((void));
297 static void generate_objc_symtab_decl PROTO((void));
298 static tree build_selector PROTO((tree));
299 #if 0
300 static tree build_msg_pool_reference PROTO((int));
301 #endif
302 static tree build_typed_selector_reference PROTO((tree, tree));
303 static tree build_selector_reference PROTO((tree));
304 static tree build_class_reference_decl PROTO((void));
305 static void add_class_reference PROTO((tree));
306 static tree objc_copy_list PROTO((tree, tree *));
307 static tree build_protocol_template PROTO((void));
308 static tree build_descriptor_table_initializer PROTO((tree, tree));
309 static tree build_method_prototype_list_template PROTO((tree, int));
310 static tree build_method_prototype_template PROTO((void));
311 static int forwarding_offset PROTO((tree));
312 static tree encode_method_prototype PROTO((tree, tree));
313 static tree generate_descriptor_table PROTO((tree, const char *,
314 int, tree, tree));
315 static void generate_method_descriptors PROTO((tree));
316 static tree build_tmp_function_decl PROTO((void));
317 static void hack_method_prototype PROTO((tree, tree));
318 static void generate_protocol_references PROTO((tree));
319 static void generate_protocols PROTO((void));
320 static void check_ivars PROTO((tree, tree));
321 static tree build_ivar_list_template PROTO((tree, int));
322 static tree build_method_list_template PROTO((tree, int));
323 static tree build_ivar_list_initializer PROTO((tree, tree));
324 static tree generate_ivars_list PROTO((tree, const char *,
325 int, tree));
326 static tree build_dispatch_table_initializer PROTO((tree, tree));
327 static tree generate_dispatch_table PROTO((tree, const char *,
328 int, tree));
329 static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree,
330 tree, int, tree, tree,
331 tree));
332 static void generate_category PROTO((tree));
333 static int is_objc_type_qualifier PROTO((tree));
334 static tree adjust_type_for_id_default PROTO((tree));
335 static tree check_duplicates PROTO((hash));
336 static tree receiver_is_class_object PROTO((tree));
337 static int check_methods PROTO((tree, tree, int));
338 static int conforms_to_protocol PROTO((tree, tree));
339 static void check_protocols PROTO((tree, const char *,
340 const char *));
341 static tree encode_method_def PROTO((tree));
342 static void gen_declspecs PROTO((tree, char *, int));
343 static void generate_classref_translation_entry PROTO((tree));
344 static void handle_class_ref PROTO((tree));
345 static void generate_struct_by_value_array PROTO((void))
346 ATTRIBUTE_NORETURN;
348 /*** Private Interface (data) ***/
350 /* Reserved tag definitions. */
352 #define TYPE_ID "id"
353 #define TAG_OBJECT "objc_object"
354 #define TAG_CLASS "objc_class"
355 #define TAG_SUPER "objc_super"
356 #define TAG_SELECTOR "objc_selector"
358 #define UTAG_CLASS "_objc_class"
359 #define UTAG_IVAR "_objc_ivar"
360 #define UTAG_IVAR_LIST "_objc_ivar_list"
361 #define UTAG_METHOD "_objc_method"
362 #define UTAG_METHOD_LIST "_objc_method_list"
363 #define UTAG_CATEGORY "_objc_category"
364 #define UTAG_MODULE "_objc_module"
365 #define UTAG_STATICS "_objc_statics"
366 #define UTAG_SYMTAB "_objc_symtab"
367 #define UTAG_SUPER "_objc_super"
368 #define UTAG_SELECTOR "_objc_selector"
370 #define UTAG_PROTOCOL "_objc_protocol"
371 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
372 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
373 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
375 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
376 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
378 static const char *TAG_GETCLASS;
379 static const char *TAG_GETMETACLASS;
380 static const char *TAG_MSGSEND;
381 static const char *TAG_MSGSENDSUPER;
382 static const char *TAG_EXECCLASS;
384 /* Set by `continue_class' and checked by `is_public'. */
386 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
387 #define TYPED_OBJECT(type) \
388 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
390 /* Some commonly used instances of "identifier_node". */
392 static tree self_id, ucmd_id;
393 static tree unused_list;
395 static tree self_decl, umsg_decl, umsg_super_decl;
396 static tree objc_get_class_decl, objc_get_meta_class_decl;
398 static tree super_type, selector_type, id_type, objc_class_type;
399 static tree instance_type, protocol_type;
401 /* Type checking macros. */
403 #define IS_ID(TYPE) \
404 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
405 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
406 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
407 #define IS_SUPER(TYPE) \
408 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
410 static tree class_chain = NULL_TREE;
411 static tree alias_chain = NULL_TREE;
412 static tree interface_chain = NULL_TREE;
413 static tree protocol_chain = NULL_TREE;
415 /* Chains to manage selectors that are referenced and defined in the
416 module. */
418 static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */
419 static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */
421 /* Chains to manage uniquing of strings. */
423 static tree class_names_chain = NULL_TREE;
424 static tree meth_var_names_chain = NULL_TREE;
425 static tree meth_var_types_chain = NULL_TREE;
427 /* Hash tables to manage the global pool of method prototypes. */
429 static hash *nst_method_hash_list = 0;
430 static hash *cls_method_hash_list = 0;
432 /* Backend data declarations. */
434 static tree UOBJC_SYMBOLS_decl;
435 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
436 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
437 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
438 static tree UOBJC_SELECTOR_TABLE_decl;
439 static tree UOBJC_MODULES_decl;
440 static tree UOBJC_STRINGS_decl;
442 /* The following are used when compiling a class implementation.
443 implementation_template will normally be an interface, however if
444 none exists this will be equal to implementation_context...it is
445 set in start_class. */
447 static tree implementation_context = NULL_TREE;
448 static tree implementation_template = NULL_TREE;
450 struct imp_entry
452 struct imp_entry *next;
453 tree imp_context;
454 tree imp_template;
455 tree class_decl; /* _OBJC_CLASS_<my_name>; */
456 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
459 static void handle_impent PROTO((struct imp_entry *));
461 static struct imp_entry *imp_list = 0;
462 static int imp_count = 0; /* `@implementation' */
463 static int cat_count = 0; /* `@category' */
465 static tree objc_class_template, objc_category_template, uprivate_record;
466 static tree objc_protocol_template, objc_selector_template;
467 static tree ucls_super_ref, uucls_super_ref;
469 static tree objc_method_template, objc_ivar_template;
470 static tree objc_symtab_template, objc_module_template;
471 static tree objc_super_template, objc_object_reference;
473 static tree objc_object_id, objc_class_id, objc_id_id;
474 static tree constant_string_id;
475 static tree constant_string_type;
476 static tree UOBJC_SUPER_decl;
478 static tree method_context = NULL_TREE;
479 static int method_slot = 0; /* Used by start_method_def, */
481 #define BUFSIZE 1024
483 static char *errbuf; /* Buffer for error diagnostics */
485 /* Data imported from tree.c. */
487 extern enum debug_info_type write_symbols;
489 /* Data imported from toplev.c. */
491 extern const char *dump_base_name;
493 /* Generate code for GNU or NeXT runtime environment. */
495 #ifdef NEXT_OBJC_RUNTIME
496 int flag_next_runtime = 1;
497 #else
498 int flag_next_runtime = 0;
499 #endif
501 int flag_typed_selectors;
503 /* Open and close the file for outputting class declarations, if requested. */
505 int flag_gen_declaration = 0;
507 FILE *gen_declaration_file;
509 /* Warn if multiple methods are seen for the same selector, but with
510 different argument types. */
512 int warn_selector = 0;
514 /* Warn if methods required by a protocol are not implemented in the
515 class adopting it. When turned off, methods inherited to that
516 class are also considered implemented */
518 int flag_warn_protocol = 1;
520 /* Tells "encode_pointer/encode_aggregate" whether we are generating
521 type descriptors for instance variables (as opposed to methods).
522 Type descriptors for instance variables contain more information
523 than methods (for static typing and embedded structures). This
524 was added to support features being planned for dbkit2. */
526 static int generating_instance_variables = 0;
528 /* Tells the compiler that this is a special run. Do not perform
529 any compiling, instead we are to test some platform dependent
530 features and output a C header file with appropriate definitions. */
532 static int print_struct_values = 0;
534 /* Some platforms pass small structures through registers versus through
535 an invisible pointer. Determine at what size structure is the
536 transition point between the two possibilities. */
538 static void
539 generate_struct_by_value_array ()
541 tree type;
542 tree field_decl, field_decl_chain;
543 int i, j;
544 int aggregate_in_mem[32];
545 int found = 0;
547 /* Presumbaly no platform passes 32 byte structures in a register. */
548 for (i = 1; i < 32; i++)
550 char buffer[5];
552 /* Create an unnamed struct that has `i' character components */
553 type = start_struct (RECORD_TYPE, NULL_TREE);
555 strcpy (buffer, "c1");
556 field_decl = create_builtin_decl (FIELD_DECL,
557 char_type_node,
558 buffer);
559 field_decl_chain = field_decl;
561 for (j = 1; j < i; j++)
563 sprintf (buffer, "c%d", j + 1);
564 field_decl = create_builtin_decl (FIELD_DECL,
565 char_type_node,
566 buffer);
567 chainon (field_decl_chain, field_decl);
569 finish_struct (type, field_decl_chain, NULL_TREE);
571 aggregate_in_mem[i] = aggregate_value_p (type);
572 if (!aggregate_in_mem[i])
573 found = 1;
576 /* We found some structures that are returned in registers instead of memory
577 so output the necessary data. */
578 if (found)
580 for (i = 31; i >= 0; i--)
581 if (!aggregate_in_mem[i])
582 break;
583 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
585 /* The first member of the structure is always 0 because we don't handle
586 structures with 0 members */
587 printf ("static int struct_forward_array[] = {\n 0");
589 for (j = 1; j <= i; j++)
590 printf (", %d", aggregate_in_mem[j]);
591 printf ("\n};\n");
594 exit (0);
597 #if USE_CPPLIB
598 extern char *yy_cur;
599 #endif
601 void
602 lang_init_options ()
604 #if USE_CPPLIB
605 cpp_reader_init (&parse_in);
606 parse_in.opts = &parse_options;
607 cpp_options_init (&parse_options);
608 #endif
611 void
612 lang_init ()
614 #if !USE_CPPLIB
615 /* The beginning of the file is a new line; check for #.
616 With luck, we discover the real source file's name from that
617 and put it in input_filename. */
618 ungetc (check_newline (), finput);
619 #else
620 check_newline ();
621 yy_cur--;
622 #endif
624 /* The line number can be -1 if we had -g3 and the input file
625 had a directive specifying line 0. But we want predefined
626 functions to have a line number of 0, not -1. */
627 if (lineno == -1)
628 lineno = 0;
630 /* If gen_declaration desired, open the output file. */
631 if (flag_gen_declaration)
633 register char * const dumpname = concat (dumpname, ".decl", NULL);
634 gen_declaration_file = fopen (dumpname, "w");
635 if (gen_declaration_file == 0)
636 pfatal_with_name (dumpname);
637 free (dumpname);
640 if (flag_next_runtime)
642 TAG_GETCLASS = "objc_getClass";
643 TAG_GETMETACLASS = "objc_getMetaClass";
644 TAG_MSGSEND = "objc_msgSend";
645 TAG_MSGSENDSUPER = "objc_msgSendSuper";
646 TAG_EXECCLASS = "__objc_execClass";
648 else
650 TAG_GETCLASS = "objc_get_class";
651 TAG_GETMETACLASS = "objc_get_meta_class";
652 TAG_MSGSEND = "objc_msg_lookup";
653 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
654 TAG_EXECCLASS = "__objc_exec_class";
655 flag_typed_selectors = 1;
658 if (doing_objc_thang)
659 init_objc ();
661 if (print_struct_values)
662 generate_struct_by_value_array ();
665 static void
666 objc_fatal ()
668 fatal ("Objective-C text in C source file");
671 void
672 finish_file ()
674 if (doing_objc_thang)
675 finish_objc (); /* Objective-C finalization */
677 if (gen_declaration_file)
678 fclose (gen_declaration_file);
681 void
682 lang_finish ()
686 const char *
687 lang_identify ()
689 return "objc";
693 lang_decode_option (argc, argv)
694 int argc;
695 char **argv;
697 const char *p = argv[0];
698 if (!strcmp (p, "-lang-objc"))
699 doing_objc_thang = 1;
700 else if (!strcmp (p, "-gen-decls"))
701 flag_gen_declaration = 1;
702 else if (!strcmp (p, "-Wselector"))
703 warn_selector = 1;
704 else if (!strcmp (p, "-Wno-selector"))
705 warn_selector = 0;
706 else if (!strcmp (p, "-Wprotocol"))
707 flag_warn_protocol = 1;
708 else if (!strcmp (p, "-Wno-protocol"))
709 flag_warn_protocol = 0;
710 else if (!strcmp (p, "-fgnu-runtime"))
711 flag_next_runtime = 0;
712 else if (!strcmp (p, "-fno-next-runtime"))
713 flag_next_runtime = 0;
714 else if (!strcmp (p, "-fno-gnu-runtime"))
715 flag_next_runtime = 1;
716 else if (!strcmp (p, "-fnext-runtime"))
717 flag_next_runtime = 1;
718 else if (!strcmp (p, "-print-objc-runtime-info"))
719 print_struct_values = 1;
720 else
721 return c_decode_option (argc, argv);
723 return 1;
726 /* used by print-tree.c */
728 void
729 lang_print_xnode (file, node, indent)
730 FILE *file ATTRIBUTE_UNUSED;
731 tree node ATTRIBUTE_UNUSED;
732 int indent ATTRIBUTE_UNUSED;
737 static tree
738 define_decl (declarator, declspecs)
739 tree declarator;
740 tree declspecs;
742 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
743 finish_decl (decl, NULL_TREE, NULL_TREE);
744 return decl;
747 /* Return 1 if LHS and RHS are compatible types for assignment or
748 various other operations. Return 0 if they are incompatible, and
749 return -1 if we choose to not decide. When the operation is
750 REFLEXIVE, check for compatibility in either direction.
752 For statically typed objects, an assignment of the form `a' = `b'
753 is permitted if:
755 `a' is of type "id",
756 `a' and `b' are the same class type, or
757 `a' and `b' are of class types A and B such that B is a descendant of A. */
760 maybe_objc_comptypes (lhs, rhs, reflexive)
761 tree lhs, rhs;
762 int reflexive;
764 if (doing_objc_thang)
765 return objc_comptypes (lhs, rhs, reflexive);
766 return -1;
769 static tree
770 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
771 tree rproto_list;
772 tree sel_name;
773 int class_meth;
775 tree rproto, p;
776 tree fnd = 0;
778 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
780 p = TREE_VALUE (rproto);
782 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
784 if ((fnd = lookup_method (class_meth
785 ? PROTOCOL_CLS_METHODS (p)
786 : PROTOCOL_NST_METHODS (p), sel_name)))
788 else if (PROTOCOL_LIST (p))
789 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
790 sel_name, class_meth);
792 else
794 ; /* An identifier...if we could not find a protocol. */
797 if (fnd)
798 return fnd;
801 return 0;
804 static tree
805 lookup_protocol_in_reflist (rproto_list, lproto)
806 tree rproto_list;
807 tree lproto;
809 tree rproto, p;
811 /* Make sure the protocol is support by the object on the rhs. */
812 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
814 tree fnd = 0;
815 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
817 p = TREE_VALUE (rproto);
819 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
821 if (lproto == p)
822 fnd = lproto;
824 else if (PROTOCOL_LIST (p))
825 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
828 if (fnd)
829 return fnd;
832 else
834 ; /* An identifier...if we could not find a protocol. */
837 return 0;
840 /* Return 1 if LHS and RHS are compatible types for assignment
841 or various other operations. Return 0 if they are incompatible,
842 and return -1 if we choose to not decide. When the operation
843 is REFLEXIVE, check for compatibility in either direction. */
846 objc_comptypes (lhs, rhs, reflexive)
847 tree lhs;
848 tree rhs;
849 int reflexive;
851 /* New clause for protocols. */
853 if (TREE_CODE (lhs) == POINTER_TYPE
854 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
855 && TREE_CODE (rhs) == POINTER_TYPE
856 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
858 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
859 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
861 if (lhs_is_proto)
863 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
864 tree rproto, rproto_list;
865 tree p;
867 if (rhs_is_proto)
869 rproto_list = TYPE_PROTOCOL_LIST (rhs);
871 /* Make sure the protocol is supported by the object
872 on the rhs. */
873 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
875 p = TREE_VALUE (lproto);
876 rproto = lookup_protocol_in_reflist (rproto_list, p);
878 if (!rproto)
879 warning ("object does not conform to the `%s' protocol",
880 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
883 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
885 tree rname = TYPE_NAME (TREE_TYPE (rhs));
886 tree rinter;
888 /* Make sure the protocol is supported by the object
889 on the rhs. */
890 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
892 p = TREE_VALUE (lproto);
893 rproto = 0;
894 rinter = lookup_interface (rname);
896 while (rinter && !rproto)
898 tree cat;
900 rproto_list = CLASS_PROTOCOL_LIST (rinter);
901 rproto = lookup_protocol_in_reflist (rproto_list, p);
903 /* Check for protocols adopted by categories. */
904 cat = CLASS_CATEGORY_LIST (rinter);
905 while (cat && !rproto)
907 rproto_list = CLASS_PROTOCOL_LIST (cat);
908 rproto = lookup_protocol_in_reflist (rproto_list, p);
910 cat = CLASS_CATEGORY_LIST (cat);
913 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
916 if (!rproto)
917 warning ("class `%s' does not implement the `%s' protocol",
918 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
919 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
923 /* May change...based on whether there was any mismatch */
924 return 1;
926 else if (rhs_is_proto)
927 /* Lhs is not a protocol...warn if it is statically typed */
928 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
930 else
931 /* Defer to comptypes .*/
932 return -1;
935 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
936 ; /* Fall thru. This is the case we have been handling all along */
937 else
938 /* Defer to comptypes. */
939 return -1;
941 /* `id' = `<class> *', `<class> *' = `id' */
943 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
944 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
945 return 1;
947 /* `id' = `Class', `Class' = `id' */
949 else if ((TYPE_NAME (lhs) == objc_object_id
950 && TYPE_NAME (rhs) == objc_class_id)
951 || (TYPE_NAME (lhs) == objc_class_id
952 && TYPE_NAME (rhs) == objc_object_id))
953 return 1;
955 /* `<class> *' = `<class> *' */
957 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
959 tree lname = TYPE_NAME (lhs);
960 tree rname = TYPE_NAME (rhs);
961 tree inter;
963 if (lname == rname)
964 return 1;
966 /* If the left hand side is a super class of the right hand side,
967 allow it. */
968 for (inter = lookup_interface (rname); inter;
969 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
970 if (lname == CLASS_SUPER_NAME (inter))
971 return 1;
973 /* Allow the reverse when reflexive. */
974 if (reflexive)
975 for (inter = lookup_interface (lname); inter;
976 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
977 if (rname == CLASS_SUPER_NAME (inter))
978 return 1;
980 return 0;
982 else
983 /* Defer to comptypes. */
984 return -1;
987 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
989 void
990 objc_check_decl (decl)
991 tree decl;
993 tree type = TREE_TYPE (decl);
995 if (TREE_CODE (type) == RECORD_TYPE
996 && TREE_STATIC_TEMPLATE (type)
997 && type != constant_string_type)
999 error_with_decl (decl, "`%s' cannot be statically allocated");
1000 fatal ("statically allocated objects not supported");
1004 void
1005 maybe_objc_check_decl (decl)
1006 tree decl;
1008 if (doing_objc_thang)
1009 objc_check_decl (decl);
1012 /* Implement static typing. At this point, we know we have an interface. */
1014 tree
1015 get_static_reference (interface, protocols)
1016 tree interface;
1017 tree protocols;
1019 tree type = xref_tag (RECORD_TYPE, interface);
1021 if (protocols)
1023 tree t, m = TYPE_MAIN_VARIANT (type);
1025 push_obstacks_nochange ();
1026 end_temporary_allocation ();
1027 t = copy_node (type);
1028 TYPE_BINFO (t) = make_tree_vec (2);
1029 pop_obstacks ();
1031 /* Add this type to the chain of variants of TYPE. */
1032 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1033 TYPE_NEXT_VARIANT (m) = t;
1035 /* Look up protocols and install in lang specific list. */
1036 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1038 /* This forces a new pointer type to be created later
1039 (in build_pointer_type)...so that the new template
1040 we just created will actually be used...what a hack! */
1041 if (TYPE_POINTER_TO (t))
1042 TYPE_POINTER_TO (t) = 0;
1044 type = t;
1047 return type;
1050 tree
1051 get_object_reference (protocols)
1052 tree protocols;
1054 tree type_decl = lookup_name (objc_id_id);
1055 tree type;
1057 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1059 type = TREE_TYPE (type_decl);
1060 if (TYPE_MAIN_VARIANT (type) != id_type)
1061 warning ("Unexpected type for `id' (%s)",
1062 gen_declaration (type, errbuf));
1064 else
1065 fatal ("Undefined type `id', please import <objc/objc.h>");
1067 /* This clause creates a new pointer type that is qualified with
1068 the protocol specification...this info is used later to do more
1069 elaborate type checking. */
1071 if (protocols)
1073 tree t, m = TYPE_MAIN_VARIANT (type);
1075 push_obstacks_nochange ();
1076 end_temporary_allocation ();
1077 t = copy_node (type);
1078 TYPE_BINFO (t) = make_tree_vec (2);
1079 pop_obstacks ();
1081 /* Add this type to the chain of variants of TYPE. */
1082 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1083 TYPE_NEXT_VARIANT (m) = t;
1085 /* Look up protocols...and install in lang specific list */
1086 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1088 /* This forces a new pointer type to be created later
1089 (in build_pointer_type)...so that the new template
1090 we just created will actually be used...what a hack! */
1091 if (TYPE_POINTER_TO (t))
1092 TYPE_POINTER_TO (t) = NULL;
1094 type = t;
1096 return type;
1099 static tree
1100 lookup_and_install_protocols (protocols)
1101 tree protocols;
1103 tree proto;
1104 tree prev = NULL;
1105 tree return_value = protocols;
1107 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1109 tree ident = TREE_VALUE (proto);
1110 tree p = lookup_protocol (ident);
1112 if (!p)
1114 error ("Cannot find protocol declaration for `%s'",
1115 IDENTIFIER_POINTER (ident));
1116 if (prev)
1117 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1118 else
1119 return_value = TREE_CHAIN (proto);
1121 else
1123 /* Replace identifier with actual protocol node. */
1124 TREE_VALUE (proto) = p;
1125 prev = proto;
1129 return return_value;
1132 /* Create and push a decl for a built-in external variable or field NAME.
1133 CODE says which.
1134 TYPE is its data type. */
1136 static tree
1137 create_builtin_decl (code, type, name)
1138 enum tree_code code;
1139 tree type;
1140 const char *name;
1142 tree decl = build_decl (code, get_identifier (name), type);
1144 if (code == VAR_DECL)
1146 TREE_STATIC (decl) = 1;
1147 make_decl_rtl (decl, 0, 1);
1148 pushdecl (decl);
1151 DECL_ARTIFICIAL (decl) = 1;
1152 return decl;
1155 /* Purpose: "play" parser, creating/installing representations
1156 of the declarations that are required by Objective-C.
1158 Model:
1160 type_spec--------->sc_spec
1161 (tree_list) (tree_list)
1164 identifier_node identifier_node */
1166 static void
1167 synth_module_prologue ()
1169 tree temp_type;
1170 tree super_p;
1172 /* Defined in `objc.h' */
1173 objc_object_id = get_identifier (TAG_OBJECT);
1175 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1177 id_type = build_pointer_type (objc_object_reference);
1179 objc_id_id = get_identifier (TYPE_ID);
1180 objc_class_id = get_identifier (TAG_CLASS);
1182 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1183 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1184 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1186 /* Declare type of selector-objects that represent an operation name. */
1188 #ifdef OBJC_INT_SELECTORS
1189 /* `unsigned int' */
1190 selector_type = unsigned_type_node;
1191 #else
1192 /* `struct objc_selector *' */
1193 selector_type
1194 = build_pointer_type (xref_tag (RECORD_TYPE,
1195 get_identifier (TAG_SELECTOR)));
1196 #endif /* not OBJC_INT_SELECTORS */
1198 /* Forward declare type, or else the prototype for msgSendSuper will
1199 complain. */
1201 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1202 get_identifier (TAG_SUPER)));
1205 /* id objc_msgSend (id, SEL, ...); */
1207 temp_type
1208 = build_function_type (id_type,
1209 tree_cons (NULL_TREE, id_type,
1210 tree_cons (NULL_TREE, selector_type,
1211 NULL_TREE)));
1213 if (! flag_next_runtime)
1215 umsg_decl = build_decl (FUNCTION_DECL,
1216 get_identifier (TAG_MSGSEND), temp_type);
1217 DECL_EXTERNAL (umsg_decl) = 1;
1218 TREE_PUBLIC (umsg_decl) = 1;
1219 DECL_INLINE (umsg_decl) = 1;
1220 DECL_ARTIFICIAL (umsg_decl) = 1;
1222 if (flag_traditional && TAG_MSGSEND[0] != '_')
1223 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1225 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1226 pushdecl (umsg_decl);
1228 else
1229 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
1231 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1233 temp_type
1234 = build_function_type (id_type,
1235 tree_cons (NULL_TREE, super_p,
1236 tree_cons (NULL_TREE, selector_type,
1237 NULL_TREE)));
1239 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1240 temp_type, 0, NOT_BUILT_IN, 0);
1242 /* id objc_getClass (const char *); */
1244 temp_type = build_function_type (id_type,
1245 tree_cons (NULL_TREE,
1246 const_string_type_node,
1247 tree_cons (NULL_TREE, void_type_node,
1248 NULL_TREE)));
1250 objc_get_class_decl
1251 = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
1253 /* id objc_getMetaClass (const char *); */
1255 objc_get_meta_class_decl
1256 = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
1258 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1260 if (! flag_next_runtime)
1262 if (flag_typed_selectors)
1264 /* Suppress outputting debug symbols, because
1265 dbxout_init hasn'r been called yet. */
1266 enum debug_info_type save_write_symbols = write_symbols;
1267 write_symbols = NO_DEBUG;
1269 build_selector_template ();
1270 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1272 write_symbols = save_write_symbols;
1274 else
1275 temp_type = build_array_type (selector_type, NULL_TREE);
1277 layout_type (temp_type);
1278 UOBJC_SELECTOR_TABLE_decl
1279 = create_builtin_decl (VAR_DECL, temp_type,
1280 "_OBJC_SELECTOR_TABLE");
1282 /* Avoid warning when not sending messages. */
1283 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1286 generate_forward_declaration_to_string_table ();
1288 /* Forward declare constant_string_id and constant_string_type. */
1289 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1290 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1293 /* Custom build_string which sets TREE_TYPE! */
1295 static tree
1296 my_build_string (len, str)
1297 int len;
1298 const char *str;
1300 int wide_flag = 0;
1301 tree a_string = build_string (len, str);
1303 /* Some code from combine_strings, which is local to c-parse.y. */
1304 if (TREE_TYPE (a_string) == int_array_type_node)
1305 wide_flag = 1;
1307 TREE_TYPE (a_string)
1308 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1309 build_index_type (build_int_2 (len - 1, 0)));
1311 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1312 TREE_STATIC (a_string) = 1;
1314 return a_string;
1317 /* Return a newly constructed OBJC_STRING_CST node whose value is
1318 the LEN characters at STR.
1319 The TREE_TYPE is not initialized. */
1321 tree
1322 build_objc_string (len, str)
1323 int len;
1324 const char *str;
1326 tree s = build_string (len, str);
1328 TREE_SET_CODE (s, OBJC_STRING_CST);
1329 return s;
1332 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1333 NXConstanString which points at the concatenation of those strings.
1334 We place the string object in the __string_objects section of the
1335 __OBJC segment. The Objective-C runtime will initialize the isa
1336 pointers of the string objects to point at the NXConstandString class
1337 object. */
1339 tree
1340 build_objc_string_object (strings)
1341 tree strings;
1343 tree string, initlist, constructor;
1344 int length;
1346 if (!doing_objc_thang)
1347 objc_fatal ();
1349 if (lookup_interface (constant_string_id) == NULL_TREE)
1351 error ("Cannot find interface declaration for `%s'",
1352 IDENTIFIER_POINTER (constant_string_id));
1353 return error_mark_node;
1356 add_class_reference (constant_string_id);
1358 /* Combine_strings will work for OBJC_STRING_CST's too. */
1359 string = combine_strings (strings);
1360 TREE_SET_CODE (string, STRING_CST);
1361 length = TREE_STRING_LENGTH (string) - 1;
1363 if (! flag_next_runtime)
1365 push_obstacks_nochange ();
1366 end_temporary_allocation ();
1367 if (! TREE_PERMANENT (strings))
1368 string = my_build_string (length + 1,
1369 TREE_STRING_POINTER (string));
1372 /* & ((NXConstantString) {0, string, length}) */
1374 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1375 initlist
1376 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1377 initlist);
1378 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1379 constructor = build_constructor (constant_string_type, nreverse (initlist));
1381 if (!flag_next_runtime)
1383 constructor
1384 = objc_add_static_instance (constructor, constant_string_type);
1385 pop_obstacks ();
1388 return (build_unary_op (ADDR_EXPR, constructor, 1));
1391 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1393 static tree
1394 objc_add_static_instance (constructor, class_decl)
1395 tree constructor, class_decl;
1397 static int num_static_inst;
1398 tree *chain, decl;
1399 char buf[256];
1401 push_obstacks_nochange ();
1402 end_temporary_allocation ();
1404 /* Find the list of static instances for the CLASS_DECL. Create one if
1405 not found. */
1406 for (chain = &objc_static_instances;
1407 *chain && TREE_VALUE (*chain) != class_decl;
1408 chain = &TREE_CHAIN (*chain));
1409 if (!*chain)
1411 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1412 add_objc_string (TYPE_NAME (class_decl), class_names);
1415 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1416 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1417 DECL_COMMON (decl) = 1;
1418 TREE_STATIC (decl) = 1;
1419 DECL_ARTIFICIAL (decl) = 1;
1420 pushdecl_top_level (decl);
1421 rest_of_decl_compilation (decl, 0, 1, 0);
1423 /* Do this here so it gets output later instead of possibly
1424 inside something else we are writing. */
1425 DECL_INITIAL (decl) = constructor;
1427 /* Add the DECL to the head of this CLASS' list. */
1428 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1430 pop_obstacks ();
1431 return decl;
1434 /* Build a static constant CONSTRUCTOR
1435 with type TYPE and elements ELTS. */
1437 static tree
1438 build_constructor (type, elts)
1439 tree type, elts;
1441 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1443 TREE_CONSTANT (constructor) = 1;
1444 TREE_STATIC (constructor) = 1;
1445 TREE_READONLY (constructor) = 1;
1447 return constructor;
1450 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1452 /* Predefine the following data type:
1454 struct _objc_symtab
1456 long sel_ref_cnt;
1457 SEL *refs;
1458 short cls_def_cnt;
1459 short cat_def_cnt;
1460 void *defs[cls_def_cnt + cat_def_cnt];
1461 }; */
1463 static void
1464 build_objc_symtab_template ()
1466 tree field_decl, field_decl_chain, index;
1468 objc_symtab_template
1469 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1471 /* long sel_ref_cnt; */
1473 field_decl = create_builtin_decl (FIELD_DECL,
1474 long_integer_type_node,
1475 "sel_ref_cnt");
1476 field_decl_chain = field_decl;
1478 /* SEL *refs; */
1480 field_decl = create_builtin_decl (FIELD_DECL,
1481 build_pointer_type (selector_type),
1482 "refs");
1483 chainon (field_decl_chain, field_decl);
1485 /* short cls_def_cnt; */
1487 field_decl = create_builtin_decl (FIELD_DECL,
1488 short_integer_type_node,
1489 "cls_def_cnt");
1490 chainon (field_decl_chain, field_decl);
1492 /* short cat_def_cnt; */
1494 field_decl = create_builtin_decl (FIELD_DECL,
1495 short_integer_type_node,
1496 "cat_def_cnt");
1497 chainon (field_decl_chain, field_decl);
1499 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1501 if (!flag_next_runtime)
1502 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1503 else
1504 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1505 imp_count == 0 && cat_count == 0
1506 ? -1 : 0));
1507 field_decl = create_builtin_decl (FIELD_DECL,
1508 build_array_type (ptr_type_node, index),
1509 "defs");
1510 chainon (field_decl_chain, field_decl);
1512 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1515 /* Create the initial value for the `defs' field of _objc_symtab.
1516 This is a CONSTRUCTOR. */
1518 static tree
1519 init_def_list (type)
1520 tree type;
1522 tree expr, initlist = NULL_TREE;
1523 struct imp_entry *impent;
1525 if (imp_count)
1526 for (impent = imp_list; impent; impent = impent->next)
1528 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1530 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1531 initlist = tree_cons (NULL_TREE, expr, initlist);
1535 if (cat_count)
1536 for (impent = imp_list; impent; impent = impent->next)
1538 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1540 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1541 initlist = tree_cons (NULL_TREE, expr, initlist);
1545 if (!flag_next_runtime)
1547 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1548 tree expr;
1550 if (static_instances_decl)
1551 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1552 else
1553 expr = build_int_2 (0, 0);
1555 initlist = tree_cons (NULL_TREE, expr, initlist);
1558 return build_constructor (type, nreverse (initlist));
1561 /* Construct the initial value for all of _objc_symtab. */
1563 static tree
1564 init_objc_symtab (type)
1565 tree type;
1567 tree initlist;
1569 /* sel_ref_cnt = { ..., 5, ... } */
1571 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1573 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1575 if (flag_next_runtime || ! sel_ref_chain)
1576 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1577 else
1578 initlist = tree_cons (NULL_TREE,
1579 build_unary_op (ADDR_EXPR,
1580 UOBJC_SELECTOR_TABLE_decl, 1),
1581 initlist);
1583 /* cls_def_cnt = { ..., 5, ... } */
1585 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1587 /* cat_def_cnt = { ..., 5, ... } */
1589 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1591 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1593 if (imp_count || cat_count || static_instances_decl)
1596 tree field = TYPE_FIELDS (type);
1597 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1599 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1600 initlist);
1603 return build_constructor (type, nreverse (initlist));
1606 /* Push forward-declarations of all the categories
1607 so that init_def_list can use them in a CONSTRUCTOR. */
1609 static void
1610 forward_declare_categories ()
1612 struct imp_entry *impent;
1613 tree sav = implementation_context;
1615 for (impent = imp_list; impent; impent = impent->next)
1617 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1619 /* Set an invisible arg to synth_id_with_class_suffix. */
1620 implementation_context = impent->imp_context;
1621 impent->class_decl
1622 = create_builtin_decl (VAR_DECL, objc_category_template,
1623 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1626 implementation_context = sav;
1629 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1630 and initialized appropriately. */
1632 static void
1633 generate_objc_symtab_decl ()
1635 tree sc_spec;
1637 if (!objc_category_template)
1638 build_category_template ();
1640 /* forward declare categories */
1641 if (cat_count)
1642 forward_declare_categories ();
1644 if (!objc_symtab_template)
1645 build_objc_symtab_template ();
1647 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1649 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1650 tree_cons (NULL_TREE,
1651 objc_symtab_template, sc_spec),
1653 NULL_TREE, NULL_TREE);
1655 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1656 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1657 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1658 finish_decl (UOBJC_SYMBOLS_decl,
1659 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1660 NULL_TREE);
1663 static tree
1664 init_module_descriptor (type)
1665 tree type;
1667 tree initlist, expr;
1669 /* version = { 1, ... } */
1671 expr = build_int_2 (OBJC_VERSION, 0);
1672 initlist = build_tree_list (NULL_TREE, expr);
1674 /* size = { ..., sizeof (struct objc_module), ... } */
1676 expr = size_in_bytes (objc_module_template);
1677 initlist = tree_cons (NULL_TREE, expr, initlist);
1679 /* name = { ..., "foo.m", ... } */
1681 expr = add_objc_string (get_identifier (input_filename), class_names);
1682 initlist = tree_cons (NULL_TREE, expr, initlist);
1684 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1686 if (UOBJC_SYMBOLS_decl)
1687 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1688 else
1689 expr = build_int_2 (0, 0);
1690 initlist = tree_cons (NULL_TREE, expr, initlist);
1692 return build_constructor (type, nreverse (initlist));
1695 /* Write out the data structures to describe Objective C classes defined.
1696 If appropriate, compile and output a setup function to initialize them.
1697 Return a string which is the name of a function to call to initialize
1698 the Objective C data structures for this file (and perhaps for other files
1699 also).
1701 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1703 static char *
1704 build_module_descriptor ()
1706 tree decl_specs, field_decl, field_decl_chain;
1708 objc_module_template
1709 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1711 /* Long version; */
1713 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1714 field_decl = get_identifier ("version");
1715 field_decl
1716 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1717 field_decl_chain = field_decl;
1719 /* long size; */
1721 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1722 field_decl = get_identifier ("size");
1723 field_decl
1724 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1725 chainon (field_decl_chain, field_decl);
1727 /* char *name; */
1729 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1730 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1731 field_decl
1732 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1733 chainon (field_decl_chain, field_decl);
1735 /* struct objc_symtab *symtab; */
1737 decl_specs = get_identifier (UTAG_SYMTAB);
1738 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1739 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1740 field_decl
1741 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1742 chainon (field_decl_chain, field_decl);
1744 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1746 /* Create an instance of "objc_module". */
1748 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1749 build_tree_list (NULL_TREE,
1750 ridpointers[(int) RID_STATIC]));
1752 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1753 decl_specs, 1, NULL_TREE, NULL_TREE);
1755 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1756 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1757 finish_decl (UOBJC_MODULES_decl,
1758 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1759 NULL_TREE);
1761 /* Mark the decl to avoid "defined but not used" warning. */
1762 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1764 /* Generate a constructor call for the module descriptor.
1765 This code was generated by reading the grammar rules
1766 of c-parse.in; Therefore, it may not be the most efficient
1767 way of generating the requisite code. */
1769 if (flag_next_runtime)
1770 return 0;
1773 tree parms, function_decl, decelerator, void_list_node_1;
1774 tree function_type;
1775 tree init_function_name = get_file_function_name ('I');
1777 /* Declare void __objc_execClass (void *); */
1779 void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1780 function_type
1781 = build_function_type (void_type_node,
1782 tree_cons (NULL_TREE, ptr_type_node,
1783 void_list_node_1));
1784 function_decl = build_decl (FUNCTION_DECL,
1785 get_identifier (TAG_EXECCLASS),
1786 function_type);
1787 DECL_EXTERNAL (function_decl) = 1;
1788 DECL_ARTIFICIAL (function_decl) = 1;
1789 TREE_PUBLIC (function_decl) = 1;
1791 pushdecl (function_decl);
1792 rest_of_decl_compilation (function_decl, 0, 0, 0);
1794 parms
1795 = build_tree_list (NULL_TREE,
1796 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1797 decelerator = build_function_call (function_decl, parms);
1799 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1801 start_function (void_list_node_1,
1802 build_parse_node (CALL_EXPR, init_function_name,
1803 /* This has the format of the output
1804 of get_parm_info. */
1805 tree_cons (NULL_TREE, NULL_TREE,
1806 void_list_node_1),
1807 NULL_TREE),
1808 NULL_TREE, NULL_TREE, 0);
1809 #if 0 /* This should be turned back on later
1810 for the systems where collect is not needed. */
1811 /* Make these functions nonglobal
1812 so each file can use the same name. */
1813 TREE_PUBLIC (current_function_decl) = 0;
1814 #endif
1815 TREE_USED (current_function_decl) = 1;
1816 store_parm_decls ();
1818 assemble_external (function_decl);
1819 c_expand_expr_stmt (decelerator);
1821 TREE_PUBLIC (current_function_decl) = 1;
1823 function_decl = current_function_decl;
1824 finish_function (0);
1826 /* Return the name of the constructor function. */
1827 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1831 /* extern const char _OBJC_STRINGS[]; */
1833 static void
1834 generate_forward_declaration_to_string_table ()
1836 tree sc_spec, decl_specs, expr_decl;
1838 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1839 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1841 expr_decl
1842 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1844 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1847 /* Return the DECL of the string IDENT in the SECTION. */
1849 static tree
1850 get_objc_string_decl (ident, section)
1851 tree ident;
1852 enum string_section section;
1854 tree chain;
1856 if (section == class_names)
1857 chain = class_names_chain;
1858 else if (section == meth_var_names)
1859 chain = meth_var_names_chain;
1860 else if (section == meth_var_types)
1861 chain = meth_var_types_chain;
1862 else
1863 abort ();
1865 for (; chain != 0; chain = TREE_VALUE (chain))
1866 if (TREE_VALUE (chain) == ident)
1867 return (TREE_PURPOSE (chain));
1869 abort ();
1870 return NULL_TREE;
1873 /* Output references to all statically allocated objects. Return the DECL
1874 for the array built. */
1876 static void
1877 generate_static_references ()
1879 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1880 tree class_name, class, decl, initlist;
1881 tree cl_chain, in_chain, type;
1882 int num_inst, num_class;
1883 char buf[256];
1885 if (flag_next_runtime)
1886 abort ();
1888 for (cl_chain = objc_static_instances, num_class = 0;
1889 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1891 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1892 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1894 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1895 ident = get_identifier (buf);
1897 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1898 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1899 build_tree_list (NULL_TREE,
1900 ridpointers[(int) RID_STATIC]));
1901 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1902 DECL_CONTEXT (decl) = 0;
1903 DECL_ARTIFICIAL (decl) = 1;
1905 /* Output {class_name, ...}. */
1906 class = TREE_VALUE (cl_chain);
1907 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1908 initlist = build_tree_list (NULL_TREE,
1909 build_unary_op (ADDR_EXPR, class_name, 1));
1911 /* Output {..., instance, ...}. */
1912 for (in_chain = TREE_PURPOSE (cl_chain);
1913 in_chain; in_chain = TREE_CHAIN (in_chain))
1915 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1916 initlist = tree_cons (NULL_TREE, expr, initlist);
1919 /* Output {..., NULL}. */
1920 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1922 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1923 finish_decl (decl, expr, NULL_TREE);
1924 TREE_USED (decl) = 1;
1926 type = build_array_type (build_pointer_type (void_type_node), 0);
1927 decl = build_decl (VAR_DECL, ident, type);
1928 make_decl_rtl (decl, 0, 1);
1929 TREE_USED (decl) = 1;
1930 decls
1931 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1934 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1935 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1936 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1937 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1938 build_tree_list (NULL_TREE,
1939 ridpointers[(int) RID_STATIC]));
1940 static_instances_decl
1941 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1942 TREE_USED (static_instances_decl) = 1;
1943 DECL_CONTEXT (static_instances_decl) = 0;
1944 DECL_ARTIFICIAL (static_instances_decl) = 1;
1945 end_temporary_allocation ();
1946 expr = build_constructor (TREE_TYPE (static_instances_decl),
1947 nreverse (decls));
1948 finish_decl (static_instances_decl, expr, NULL_TREE);
1951 /* Output all strings. */
1953 static void
1954 generate_strings ()
1956 tree sc_spec, decl_specs, expr_decl;
1957 tree chain, string_expr;
1958 tree string, decl;
1960 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1962 string = TREE_VALUE (chain);
1963 decl = TREE_PURPOSE (chain);
1964 sc_spec
1965 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1966 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1967 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1968 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1969 end_temporary_allocation ();
1970 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1971 IDENTIFIER_POINTER (string));
1972 finish_decl (decl, string_expr, NULL_TREE);
1975 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1977 string = TREE_VALUE (chain);
1978 decl = TREE_PURPOSE (chain);
1979 sc_spec
1980 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1981 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1982 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1983 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1984 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1985 IDENTIFIER_POINTER (string));
1986 finish_decl (decl, string_expr, NULL_TREE);
1989 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1991 string = TREE_VALUE (chain);
1992 decl = TREE_PURPOSE (chain);
1993 sc_spec
1994 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1995 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1996 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1997 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1998 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1999 IDENTIFIER_POINTER (string));
2000 finish_decl (decl, string_expr, NULL_TREE);
2004 static tree
2005 build_selector_reference_decl ()
2007 tree decl, ident;
2008 char buf[256];
2009 static int idx = 0;
2011 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
2013 push_obstacks_nochange ();
2014 end_temporary_allocation ();
2016 ident = get_identifier (buf);
2018 decl = build_decl (VAR_DECL, ident, selector_type);
2019 DECL_EXTERNAL (decl) = 1;
2020 TREE_PUBLIC (decl) = 1;
2021 TREE_USED (decl) = 1;
2022 TREE_READONLY (decl) = 1;
2023 DECL_ARTIFICIAL (decl) = 1;
2024 DECL_CONTEXT (decl) = 0;
2026 make_decl_rtl (decl, 0, 1);
2027 pushdecl_top_level (decl);
2029 pop_obstacks ();
2031 return decl;
2034 /* Just a handy wrapper for add_objc_string. */
2036 static tree
2037 build_selector (ident)
2038 tree ident;
2040 tree expr = add_objc_string (ident, meth_var_names);
2041 if (flag_typed_selectors)
2042 return expr;
2043 else
2044 return build_c_cast (selector_type, expr); /* cast! */
2047 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
2048 The cast stops the compiler from issuing the following message:
2049 grok.m: warning: initialization of non-const * pointer from const *
2050 grok.m: warning: initialization between incompatible pointer types. */
2052 #if 0
2053 static tree
2054 build_msg_pool_reference (offset)
2055 int offset;
2057 tree expr = build_int_2 (offset, 0);
2058 tree cast;
2060 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
2061 expr = build_unary_op (ADDR_EXPR, expr, 0);
2063 cast = build_tree_list (build_tree_list (NULL_TREE,
2064 ridpointers[(int) RID_CHAR]),
2065 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
2066 TREE_TYPE (expr) = groktypename (cast);
2067 return expr;
2070 static tree
2071 init_selector (offset)
2072 int offset;
2074 tree expr = build_msg_pool_reference (offset);
2075 TREE_TYPE (expr) = selector_type;
2076 return expr;
2078 #endif
2080 static void
2081 build_selector_translation_table ()
2083 tree sc_spec, decl_specs;
2084 tree chain, initlist = NULL_TREE;
2085 int offset = 0;
2086 tree decl = NULL_TREE, var_decl, name;
2088 /* The corresponding pop_obstacks is in finish_decl,
2089 called at the end of this function. */
2090 if (! flag_next_runtime)
2091 push_obstacks_nochange ();
2093 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2095 tree expr;
2097 expr = build_selector (TREE_VALUE (chain));
2099 if (flag_next_runtime)
2101 name = DECL_NAME (TREE_PURPOSE (chain));
2103 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2105 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2106 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2108 var_decl = name;
2110 /* The `decl' that is returned from start_decl is the one that we
2111 forward declared in `build_selector_reference' */
2112 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2115 /* add one for the '\0' character */
2116 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2118 if (flag_next_runtime)
2119 finish_decl (decl, expr, NULL_TREE);
2120 else
2122 if (flag_typed_selectors)
2124 tree eltlist = NULL_TREE;
2125 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2126 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2127 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2128 expr = build_constructor (objc_selector_template,
2129 nreverse (eltlist));
2131 initlist = tree_cons (NULL_TREE, expr, initlist);
2136 if (! flag_next_runtime)
2138 /* Cause the variable and its initial value to be actually output. */
2139 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2140 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2141 /* NULL terminate the list and fix the decl for output. */
2142 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2143 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
2144 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2145 nreverse (initlist));
2146 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2147 current_function_decl = NULL_TREE;
2151 static tree
2152 get_proto_encoding (proto)
2153 tree proto;
2155 tree encoding;
2156 if (proto)
2158 tree tmp_decl;
2160 if (! METHOD_ENCODING (proto))
2162 tmp_decl = build_tmp_function_decl ();
2163 hack_method_prototype (proto, tmp_decl);
2164 encoding = encode_method_prototype (proto, tmp_decl);
2165 METHOD_ENCODING (proto) = encoding;
2167 else
2168 encoding = METHOD_ENCODING (proto);
2170 return add_objc_string (encoding, meth_var_types);
2172 else
2173 return build_int_2 (0, 0);
2176 /* sel_ref_chain is a list whose "value" fields will be instances of
2177 identifier_node that represent the selector. */
2179 static tree
2180 build_typed_selector_reference (ident, proto)
2181 tree ident, proto;
2183 tree *chain = &sel_ref_chain;
2184 tree expr;
2185 int index = 0;
2187 while (*chain)
2189 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2190 goto return_at_index;
2192 index++;
2193 chain = &TREE_CHAIN (*chain);
2196 *chain = perm_tree_cons (proto, ident, NULL_TREE);
2198 return_at_index:
2199 expr = build_unary_op (ADDR_EXPR,
2200 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2201 build_int_2 (index, 0)),
2203 return build_c_cast (selector_type, expr);
2206 static tree
2207 build_selector_reference (ident)
2208 tree ident;
2210 tree *chain = &sel_ref_chain;
2211 tree expr;
2212 int index = 0;
2214 while (*chain)
2216 if (TREE_VALUE (*chain) == ident)
2217 return (flag_next_runtime
2218 ? TREE_PURPOSE (*chain)
2219 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2220 build_int_2 (index, 0)));
2222 index++;
2223 chain = &TREE_CHAIN (*chain);
2226 expr = build_selector_reference_decl ();
2228 *chain = perm_tree_cons (expr, ident, NULL_TREE);
2230 return (flag_next_runtime
2231 ? expr
2232 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2233 build_int_2 (index, 0)));
2236 static tree
2237 build_class_reference_decl ()
2239 tree decl, ident;
2240 char buf[256];
2241 static int idx = 0;
2243 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2245 push_obstacks_nochange ();
2246 end_temporary_allocation ();
2248 ident = get_identifier (buf);
2250 decl = build_decl (VAR_DECL, ident, objc_class_type);
2251 DECL_EXTERNAL (decl) = 1;
2252 TREE_PUBLIC (decl) = 1;
2253 TREE_USED (decl) = 1;
2254 TREE_READONLY (decl) = 1;
2255 DECL_CONTEXT (decl) = 0;
2256 DECL_ARTIFICIAL (decl) = 1;
2258 make_decl_rtl (decl, 0, 1);
2259 pushdecl_top_level (decl);
2261 pop_obstacks ();
2263 return decl;
2266 /* Create a class reference, but don't create a variable to reference
2267 it. */
2269 static void
2270 add_class_reference (ident)
2271 tree ident;
2273 tree chain;
2275 if ((chain = cls_ref_chain))
2277 tree tail;
2280 if (ident == TREE_VALUE (chain))
2281 return;
2283 tail = chain;
2284 chain = TREE_CHAIN (chain);
2286 while (chain);
2288 /* Append to the end of the list */
2289 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2291 else
2292 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2295 /* Get a class reference, creating it if necessary. Also create the
2296 reference variable. */
2298 tree
2299 get_class_reference (ident)
2300 tree ident;
2302 if (flag_next_runtime)
2304 tree *chain;
2305 tree decl;
2307 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2308 if (TREE_VALUE (*chain) == ident)
2310 if (! TREE_PURPOSE (*chain))
2311 TREE_PURPOSE (*chain) = build_class_reference_decl ();
2313 return TREE_PURPOSE (*chain);
2316 decl = build_class_reference_decl ();
2317 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2318 return decl;
2320 else
2322 tree params;
2324 add_class_reference (ident);
2326 params = build_tree_list (NULL_TREE,
2327 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2328 IDENTIFIER_POINTER (ident)));
2330 assemble_external (objc_get_class_decl);
2331 return build_function_call (objc_get_class_decl, params);
2335 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2336 of identifier_node that represent the selector. It returns the
2337 offset of the selector from the beginning of the _OBJC_STRINGS
2338 pool. This offset is typically used by init_selector during code
2339 generation.
2341 For each string section we have a chain which maps identifier nodes
2342 to decls for the strings. */
2344 static tree
2345 add_objc_string (ident, section)
2346 tree ident;
2347 enum string_section section;
2349 tree *chain, decl;
2351 if (section == class_names)
2352 chain = &class_names_chain;
2353 else if (section == meth_var_names)
2354 chain = &meth_var_names_chain;
2355 else if (section == meth_var_types)
2356 chain = &meth_var_types_chain;
2357 else
2358 abort ();
2360 while (*chain)
2362 if (TREE_VALUE (*chain) == ident)
2363 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2365 chain = &TREE_CHAIN (*chain);
2368 decl = build_objc_string_decl (section);
2370 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2372 return build_unary_op (ADDR_EXPR, decl, 1);
2375 static tree
2376 build_objc_string_decl (section)
2377 enum string_section section;
2379 tree decl, ident;
2380 char buf[256];
2381 static int class_names_idx = 0;
2382 static int meth_var_names_idx = 0;
2383 static int meth_var_types_idx = 0;
2385 if (section == class_names)
2386 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2387 else if (section == meth_var_names)
2388 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2389 else if (section == meth_var_types)
2390 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2392 push_obstacks_nochange ();
2393 end_temporary_allocation ();
2394 ident = get_identifier (buf);
2396 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2397 DECL_EXTERNAL (decl) = 1;
2398 TREE_PUBLIC (decl) = 1;
2399 TREE_USED (decl) = 1;
2400 TREE_READONLY (decl) = 1;
2401 TREE_CONSTANT (decl) = 1;
2402 DECL_CONTEXT (decl) = 0;
2403 DECL_ARTIFICIAL (decl) = 1;
2405 make_decl_rtl (decl, 0, 1);
2406 pushdecl_top_level (decl);
2408 pop_obstacks ();
2410 return decl;
2414 void
2415 objc_declare_alias (alias_ident, class_ident)
2416 tree alias_ident;
2417 tree class_ident;
2419 if (!doing_objc_thang)
2420 objc_fatal ();
2422 if (is_class_name (class_ident) != class_ident)
2423 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2424 else if (is_class_name (alias_ident))
2425 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2426 else
2427 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2430 void
2431 objc_declare_class (ident_list)
2432 tree ident_list;
2434 tree list;
2436 if (!doing_objc_thang)
2437 objc_fatal ();
2439 for (list = ident_list; list; list = TREE_CHAIN (list))
2441 tree ident = TREE_VALUE (list);
2442 tree decl;
2444 if ((decl = lookup_name (ident)))
2446 error ("`%s' redeclared as different kind of symbol",
2447 IDENTIFIER_POINTER (ident));
2448 error_with_decl (decl, "previous declaration of `%s'");
2451 if (! is_class_name (ident))
2453 tree record = xref_tag (RECORD_TYPE, ident);
2454 TREE_STATIC_TEMPLATE (record) = 1;
2455 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2460 tree
2461 is_class_name (ident)
2462 tree ident;
2464 tree chain;
2466 if (lookup_interface (ident))
2467 return ident;
2469 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2471 if (ident == TREE_VALUE (chain))
2472 return ident;
2475 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2477 if (ident == TREE_VALUE (chain))
2478 return TREE_PURPOSE (chain);
2481 return 0;
2484 tree
2485 lookup_interface (ident)
2486 tree ident;
2488 tree chain;
2490 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2492 if (ident == CLASS_NAME (chain))
2493 return chain;
2495 return NULL_TREE;
2498 static tree
2499 objc_copy_list (list, head)
2500 tree list;
2501 tree *head;
2503 tree newlist = NULL_TREE, tail = NULL_TREE;
2505 while (list)
2507 tail = copy_node (list);
2509 /* The following statement fixes a bug when inheriting instance
2510 variables that are declared to be bitfields. finish_struct
2511 expects to find the width of the bitfield in DECL_INITIAL,
2512 which it nulls out after processing the decl of the super
2513 class...rather than change the way finish_struct works (which
2514 is risky), I create the situation it expects...s.naroff
2515 (7/23/89). */
2517 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2518 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2520 newlist = chainon (newlist, tail);
2521 list = TREE_CHAIN (list);
2524 *head = newlist;
2525 return tail;
2528 /* Used by: build_private_template, get_class_ivars, and
2529 continue_class. COPY is 1 when called from @defs. In this case
2530 copy all fields. Otherwise don't copy leaf ivars since we rely on
2531 them being side-effected exactly once by finish_struct. */
2533 static tree
2534 build_ivar_chain (interface, copy)
2535 tree interface;
2536 int copy;
2538 tree my_name, super_name, ivar_chain;
2540 my_name = CLASS_NAME (interface);
2541 super_name = CLASS_SUPER_NAME (interface);
2543 /* Possibly copy leaf ivars. */
2544 if (copy)
2545 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2546 else
2547 ivar_chain = CLASS_IVARS (interface);
2549 while (super_name)
2551 tree op1;
2552 tree super_interface = lookup_interface (super_name);
2554 if (!super_interface)
2556 /* fatal did not work with 2 args...should fix */
2557 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2558 IDENTIFIER_POINTER (super_name),
2559 IDENTIFIER_POINTER (my_name));
2560 exit (FATAL_EXIT_CODE);
2563 if (super_interface == interface)
2565 fatal ("Circular inheritance in interface declaration for `%s'",
2566 IDENTIFIER_POINTER (super_name));
2569 interface = super_interface;
2570 my_name = CLASS_NAME (interface);
2571 super_name = CLASS_SUPER_NAME (interface);
2573 op1 = CLASS_IVARS (interface);
2574 if (op1)
2576 tree head, tail = objc_copy_list (op1, &head);
2578 /* Prepend super class ivars...make a copy of the list, we
2579 do not want to alter the original. */
2580 TREE_CHAIN (tail) = ivar_chain;
2581 ivar_chain = head;
2584 return ivar_chain;
2587 /* struct <classname> {
2588 struct objc_class *isa;
2590 }; */
2592 static tree
2593 build_private_template (class)
2594 tree class;
2596 tree ivar_context;
2598 if (CLASS_STATIC_TEMPLATE (class))
2600 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2601 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2603 else
2605 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2607 ivar_context = build_ivar_chain (class, 0);
2609 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2611 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2613 /* mark this record as class template - for class type checking */
2614 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2617 instance_type
2618 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2619 uprivate_record),
2620 build1 (INDIRECT_REF, NULL_TREE,
2621 NULL_TREE)));
2623 return ivar_context;
2626 /* Begin code generation for protocols... */
2628 /* struct objc_protocol {
2629 char *protocol_name;
2630 struct objc_protocol **protocol_list;
2631 struct objc_method_desc *instance_methods;
2632 struct objc_method_desc *class_methods;
2633 }; */
2635 static tree
2636 build_protocol_template ()
2638 tree decl_specs, field_decl, field_decl_chain;
2639 tree template;
2641 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2643 /* struct objc_class *isa; */
2645 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2646 get_identifier (UTAG_CLASS)));
2647 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2648 field_decl
2649 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2650 field_decl_chain = field_decl;
2652 /* char *protocol_name; */
2654 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2655 field_decl
2656 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2657 field_decl
2658 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2659 chainon (field_decl_chain, field_decl);
2661 /* struct objc_protocol **protocol_list; */
2663 decl_specs = build_tree_list (NULL_TREE, template);
2664 field_decl
2665 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2666 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2667 field_decl
2668 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2669 chainon (field_decl_chain, field_decl);
2671 /* struct objc_method_list *instance_methods; */
2673 decl_specs
2674 = build_tree_list (NULL_TREE,
2675 xref_tag (RECORD_TYPE,
2676 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2677 field_decl
2678 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2679 field_decl
2680 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2681 chainon (field_decl_chain, field_decl);
2683 /* struct objc_method_list *class_methods; */
2685 decl_specs
2686 = build_tree_list (NULL_TREE,
2687 xref_tag (RECORD_TYPE,
2688 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2689 field_decl
2690 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2691 field_decl
2692 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2693 chainon (field_decl_chain, field_decl);
2695 return finish_struct (template, field_decl_chain, NULL_TREE);
2698 static tree
2699 build_descriptor_table_initializer (type, entries)
2700 tree type;
2701 tree entries;
2703 tree initlist = NULL_TREE;
2707 tree eltlist = NULL_TREE;
2709 eltlist
2710 = tree_cons (NULL_TREE,
2711 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2712 eltlist
2713 = tree_cons (NULL_TREE,
2714 add_objc_string (METHOD_ENCODING (entries),
2715 meth_var_types),
2716 eltlist);
2718 initlist
2719 = tree_cons (NULL_TREE,
2720 build_constructor (type, nreverse (eltlist)), initlist);
2722 entries = TREE_CHAIN (entries);
2724 while (entries);
2726 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2729 /* struct objc_method_prototype_list {
2730 int count;
2731 struct objc_method_prototype {
2732 SEL name;
2733 char *types;
2734 } list[1];
2735 }; */
2737 static tree
2738 build_method_prototype_list_template (list_type, size)
2739 tree list_type;
2740 int size;
2742 tree objc_ivar_list_record;
2743 tree decl_specs, field_decl, field_decl_chain;
2745 /* Generate an unnamed struct definition. */
2747 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2749 /* int method_count; */
2751 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2752 field_decl = get_identifier ("method_count");
2754 field_decl
2755 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2756 field_decl_chain = field_decl;
2758 /* struct objc_method method_list[]; */
2760 decl_specs = build_tree_list (NULL_TREE, list_type);
2761 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2762 build_int_2 (size, 0));
2764 field_decl
2765 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2766 chainon (field_decl_chain, field_decl);
2768 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2770 return objc_ivar_list_record;
2773 static tree
2774 build_method_prototype_template ()
2776 tree proto_record;
2777 tree decl_specs, field_decl, field_decl_chain;
2779 proto_record
2780 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2782 #ifdef OBJC_INT_SELECTORS
2783 /* unsigned int _cmd; */
2784 decl_specs
2785 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2786 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2787 field_decl = get_identifier ("_cmd");
2788 #else /* OBJC_INT_SELECTORS */
2789 /* struct objc_selector *_cmd; */
2790 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2791 get_identifier (TAG_SELECTOR)), NULL_TREE);
2792 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2793 #endif /* OBJC_INT_SELECTORS */
2795 field_decl
2796 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2797 field_decl_chain = field_decl;
2799 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2800 field_decl
2801 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2802 field_decl
2803 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2804 chainon (field_decl_chain, field_decl);
2806 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2808 return proto_record;
2811 /* True if last call to forwarding_offset yielded a register offset. */
2812 static int offset_is_register;
2814 static int
2815 forwarding_offset (parm)
2816 tree parm;
2818 int offset_in_bytes;
2820 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2822 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2824 /* ??? Here we assume that the parm address is indexed
2825 off the frame pointer or arg pointer.
2826 If that is not true, we produce meaningless results,
2827 but do not crash. */
2828 if (GET_CODE (addr) == PLUS
2829 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2830 offset_in_bytes = INTVAL (XEXP (addr, 1));
2831 else
2832 offset_in_bytes = 0;
2834 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2835 offset_is_register = 0;
2837 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2839 int regno = REGNO (DECL_INCOMING_RTL (parm));
2840 offset_in_bytes = apply_args_register_offset (regno);
2841 offset_is_register = 1;
2843 else
2844 return 0;
2846 /* This is the case where the parm is passed as an int or double
2847 and it is converted to a char, short or float and stored back
2848 in the parmlist. In this case, describe the parm
2849 with the variable's declared type, and adjust the address
2850 if the least significant bytes (which we are using) are not
2851 the first ones. */
2852 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2853 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2854 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2856 return offset_in_bytes;
2859 static tree
2860 encode_method_prototype (method_decl, func_decl)
2861 tree method_decl;
2862 tree func_decl;
2864 tree parms;
2865 int stack_size, i;
2866 tree user_args;
2867 int max_parm_end = 0;
2868 char buf[40];
2869 tree result;
2871 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2872 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2874 /* C type. */
2875 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2876 obstack_object_size (&util_obstack),
2877 OBJC_ENCODE_INLINE_DEFS);
2879 /* Stack size. */
2880 for (parms = DECL_ARGUMENTS (func_decl); parms;
2881 parms = TREE_CHAIN (parms))
2883 int parm_end = (forwarding_offset (parms)
2884 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2885 / BITS_PER_UNIT));
2887 if (!offset_is_register && max_parm_end < parm_end)
2888 max_parm_end = parm_end;
2891 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2893 sprintf (buf, "%d", stack_size);
2894 obstack_grow (&util_obstack, buf, strlen (buf));
2896 user_args = METHOD_SEL_ARGS (method_decl);
2898 /* Argument types. */
2899 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2900 parms = TREE_CHAIN (parms), i++)
2902 /* Process argument qualifiers for user supplied arguments. */
2903 if (i > 1)
2905 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2906 user_args = TREE_CHAIN (user_args);
2909 /* Type. */
2910 encode_type (TREE_TYPE (parms),
2911 obstack_object_size (&util_obstack),
2912 OBJC_ENCODE_INLINE_DEFS);
2914 /* Compute offset. */
2915 sprintf (buf, "%d", forwarding_offset (parms));
2917 /* Indicate register. */
2918 if (offset_is_register)
2919 obstack_1grow (&util_obstack, '+');
2921 obstack_grow (&util_obstack, buf, strlen (buf));
2924 obstack_1grow (&util_obstack, '\0');
2925 result = get_identifier (obstack_finish (&util_obstack));
2926 obstack_free (&util_obstack, util_firstobj);
2927 return result;
2930 static tree
2931 generate_descriptor_table (type, name, size, list, proto)
2932 tree type;
2933 const char *name;
2934 int size;
2935 tree list;
2936 tree proto;
2938 tree sc_spec, decl_specs, decl, initlist;
2940 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2941 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2943 decl = start_decl (synth_id_with_class_suffix (name, proto),
2944 decl_specs, 1, NULL_TREE, NULL_TREE);
2946 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2947 initlist = tree_cons (NULL_TREE, list, initlist);
2949 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2950 NULL_TREE);
2952 return decl;
2955 static void
2956 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2957 tree protocol;
2959 static tree objc_method_prototype_template;
2960 tree initlist, chain, method_list_template;
2961 tree cast, variable_length_type;
2962 int size;
2964 if (!objc_method_prototype_template)
2965 objc_method_prototype_template = build_method_prototype_template ();
2967 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2968 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2969 NULL_TREE);
2970 variable_length_type = groktypename (cast);
2972 chain = PROTOCOL_CLS_METHODS (protocol);
2973 if (chain)
2975 size = list_length (chain);
2977 method_list_template
2978 = build_method_prototype_list_template (objc_method_prototype_template,
2979 size);
2981 initlist
2982 = build_descriptor_table_initializer (objc_method_prototype_template,
2983 chain);
2985 UOBJC_CLASS_METHODS_decl
2986 = generate_descriptor_table (method_list_template,
2987 "_OBJC_PROTOCOL_CLASS_METHODS",
2988 size, initlist, protocol);
2989 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2991 else
2992 UOBJC_CLASS_METHODS_decl = 0;
2994 chain = PROTOCOL_NST_METHODS (protocol);
2995 if (chain)
2997 size = list_length (chain);
2999 method_list_template
3000 = build_method_prototype_list_template (objc_method_prototype_template,
3001 size);
3002 initlist
3003 = build_descriptor_table_initializer (objc_method_prototype_template,
3004 chain);
3006 UOBJC_INSTANCE_METHODS_decl
3007 = generate_descriptor_table (method_list_template,
3008 "_OBJC_PROTOCOL_INSTANCE_METHODS",
3009 size, initlist, protocol);
3010 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3012 else
3013 UOBJC_INSTANCE_METHODS_decl = 0;
3016 static tree
3017 build_tmp_function_decl ()
3019 tree decl_specs, expr_decl, parms;
3020 static int xxx = 0;
3021 char buffer[80];
3023 /* struct objc_object *objc_xxx (id, SEL, ...); */
3024 pushlevel (0);
3025 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3026 push_parm_decl (build_tree_list
3027 (build_tree_list (decl_specs,
3028 build1 (INDIRECT_REF, NULL_TREE,
3029 NULL_TREE)),
3030 build_tree_list (NULL_TREE, NULL_TREE)));
3032 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3033 get_identifier (TAG_SELECTOR)));
3034 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
3036 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
3037 build_tree_list (NULL_TREE, NULL_TREE)));
3038 parms = get_parm_info (0);
3039 poplevel (0, 0, 0);
3041 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3042 sprintf (buffer, "__objc_tmp_%x", xxx++);
3043 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
3044 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
3046 return define_decl (expr_decl, decl_specs);
3049 static void
3050 hack_method_prototype (nst_methods, tmp_decl)
3051 tree nst_methods;
3052 tree tmp_decl;
3054 tree parms;
3055 tree parm;
3057 /* Hack to avoid problem with static typing of self arg. */
3058 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
3059 start_method_def (nst_methods);
3060 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
3062 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
3063 parms = get_parm_info (0); /* we have a `, ...' */
3064 else
3065 parms = get_parm_info (1); /* place a `void_at_end' */
3067 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
3069 /* Usually called from store_parm_decls -> init_function_start. */
3071 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
3072 current_function_decl = tmp_decl;
3075 /* Code taken from start_function. */
3076 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3077 /* Promote the value to int before returning it. */
3078 if (TREE_CODE (restype) == INTEGER_TYPE
3079 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3080 restype = integer_type_node;
3081 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3084 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3085 DECL_CONTEXT (parm) = tmp_decl;
3087 init_function_start (tmp_decl, "objc-act", 0);
3089 /* Typically called from expand_function_start for function definitions. */
3090 assign_parms (tmp_decl);
3092 /* install return type */
3093 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3097 static void
3098 generate_protocol_references (plist)
3099 tree plist;
3101 tree lproto;
3103 /* Forward declare protocols referenced. */
3104 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3106 tree proto = TREE_VALUE (lproto);
3108 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3109 && PROTOCOL_NAME (proto))
3111 if (! PROTOCOL_FORWARD_DECL (proto))
3112 build_protocol_reference (proto);
3114 if (PROTOCOL_LIST (proto))
3115 generate_protocol_references (PROTOCOL_LIST (proto));
3120 static void
3121 generate_protocols ()
3123 tree p, tmp_decl, encoding;
3124 tree sc_spec, decl_specs, decl;
3125 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3126 tree cast_type2 = 0;
3128 tmp_decl = build_tmp_function_decl ();
3130 if (! objc_protocol_template)
3131 objc_protocol_template = build_protocol_template ();
3133 /* If a protocol was directly referenced, pull in indirect references. */
3134 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3135 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3136 generate_protocol_references (PROTOCOL_LIST (p));
3138 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3140 tree nst_methods = PROTOCOL_NST_METHODS (p);
3141 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3143 /* If protocol wasn't referenced, don't generate any code. */
3144 if (! PROTOCOL_FORWARD_DECL (p))
3145 continue;
3147 /* Make sure we link in the Protocol class. */
3148 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3150 while (nst_methods)
3152 if (! METHOD_ENCODING (nst_methods))
3154 hack_method_prototype (nst_methods, tmp_decl);
3155 encoding = encode_method_prototype (nst_methods, tmp_decl);
3156 METHOD_ENCODING (nst_methods) = encoding;
3158 nst_methods = TREE_CHAIN (nst_methods);
3161 while (cls_methods)
3163 if (! METHOD_ENCODING (cls_methods))
3165 hack_method_prototype (cls_methods, tmp_decl);
3166 encoding = encode_method_prototype (cls_methods, tmp_decl);
3167 METHOD_ENCODING (cls_methods) = encoding;
3170 cls_methods = TREE_CHAIN (cls_methods);
3172 generate_method_descriptors (p);
3174 if (PROTOCOL_LIST (p))
3175 refs_decl = generate_protocol_list (p);
3176 else
3177 refs_decl = 0;
3179 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3181 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3182 NULL_TREE);
3183 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3185 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3186 decl_specs, 1, NULL_TREE, NULL_TREE);
3188 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3190 if (refs_decl)
3192 if (!cast_type2)
3193 cast_type2
3194 = groktypename
3195 (build_tree_list (build_tree_list (NULL_TREE,
3196 objc_protocol_template),
3197 build1 (INDIRECT_REF, NULL_TREE,
3198 build1 (INDIRECT_REF, NULL_TREE,
3199 NULL_TREE))));
3201 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3202 TREE_TYPE (refs_expr) = cast_type2;
3204 else
3205 refs_expr = build_int_2 (0, 0);
3207 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3208 by generate_method_descriptors, which is called above. */
3209 initlist = build_protocol_initializer (TREE_TYPE (decl),
3210 protocol_name_expr, refs_expr,
3211 UOBJC_INSTANCE_METHODS_decl,
3212 UOBJC_CLASS_METHODS_decl);
3213 finish_decl (decl, initlist, NULL_TREE);
3215 /* Mark the decl as used to avoid "defined but not used" warning. */
3216 TREE_USED (decl) = 1;
3220 static tree
3221 build_protocol_initializer (type, protocol_name, protocol_list,
3222 instance_methods, class_methods)
3223 tree type;
3224 tree protocol_name;
3225 tree protocol_list;
3226 tree instance_methods;
3227 tree class_methods;
3229 tree initlist = NULL_TREE, expr;
3230 static tree cast_type = 0;
3232 if (!cast_type)
3233 cast_type
3234 = groktypename
3235 (build_tree_list
3236 (build_tree_list (NULL_TREE,
3237 xref_tag (RECORD_TYPE,
3238 get_identifier (UTAG_CLASS))),
3239 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3241 /* Filling the "isa" in with one allows the runtime system to
3242 detect that the version change...should remove before final release. */
3244 expr = build_int_2 (PROTOCOL_VERSION, 0);
3245 TREE_TYPE (expr) = cast_type;
3246 initlist = tree_cons (NULL_TREE, expr, initlist);
3247 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3248 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3250 if (!instance_methods)
3251 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3252 else
3254 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3255 initlist = tree_cons (NULL_TREE, expr, initlist);
3258 if (!class_methods)
3259 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3260 else
3262 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3263 initlist = tree_cons (NULL_TREE, expr, initlist);
3266 return build_constructor (type, nreverse (initlist));
3269 /* struct objc_category {
3270 char *category_name;
3271 char *class_name;
3272 struct objc_method_list *instance_methods;
3273 struct objc_method_list *class_methods;
3274 struct objc_protocol_list *protocols;
3275 }; */
3277 static void
3278 build_category_template ()
3280 tree decl_specs, field_decl, field_decl_chain;
3282 objc_category_template = start_struct (RECORD_TYPE,
3283 get_identifier (UTAG_CATEGORY));
3284 /* char *category_name; */
3286 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3287 field_decl
3288 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3289 field_decl
3290 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3291 field_decl_chain = field_decl;
3293 /* char *class_name; */
3295 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3296 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3297 field_decl
3298 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3299 chainon (field_decl_chain, field_decl);
3301 /* struct objc_method_list *instance_methods; */
3303 decl_specs = build_tree_list (NULL_TREE,
3304 xref_tag (RECORD_TYPE,
3305 get_identifier (UTAG_METHOD_LIST)));
3306 field_decl
3307 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3308 field_decl
3309 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3310 chainon (field_decl_chain, field_decl);
3312 /* struct objc_method_list *class_methods; */
3314 decl_specs = build_tree_list (NULL_TREE,
3315 xref_tag (RECORD_TYPE,
3316 get_identifier (UTAG_METHOD_LIST)));
3317 field_decl
3318 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3319 field_decl
3320 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3321 chainon (field_decl_chain, field_decl);
3323 /* struct objc_protocol **protocol_list; */
3325 decl_specs = build_tree_list (NULL_TREE,
3326 xref_tag (RECORD_TYPE,
3327 get_identifier (UTAG_PROTOCOL)));
3328 field_decl
3329 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3330 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3331 field_decl
3332 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3333 chainon (field_decl_chain, field_decl);
3335 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3338 /* struct objc_selector {
3339 void *sel_id;
3340 char *sel_type;
3341 }; */
3343 static void
3344 build_selector_template ()
3347 tree decl_specs, field_decl, field_decl_chain;
3349 objc_selector_template
3350 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3352 /* void *sel_id; */
3354 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3355 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3356 field_decl
3357 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3358 field_decl_chain = field_decl;
3360 /* char *sel_type; */
3362 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3363 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3364 field_decl
3365 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3366 chainon (field_decl_chain, field_decl);
3368 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3371 /* struct objc_class {
3372 struct objc_class *isa;
3373 struct objc_class *super_class;
3374 char *name;
3375 long version;
3376 long info;
3377 long instance_size;
3378 struct objc_ivar_list *ivars;
3379 struct objc_method_list *methods;
3380 if (flag_next_runtime)
3381 struct objc_cache *cache;
3382 else {
3383 struct sarray *dtable;
3384 struct objc_class *subclass_list;
3385 struct objc_class *sibling_class;
3387 struct objc_protocol_list *protocols;
3388 void *gc_object_type;
3389 }; */
3391 static void
3392 build_class_template ()
3394 tree decl_specs, field_decl, field_decl_chain;
3396 objc_class_template
3397 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3399 /* struct objc_class *isa; */
3401 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3402 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3403 field_decl
3404 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3405 field_decl_chain = field_decl;
3407 /* struct objc_class *super_class; */
3409 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3410 field_decl
3411 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3412 field_decl
3413 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3414 chainon (field_decl_chain, field_decl);
3416 /* char *name; */
3418 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3419 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3420 field_decl
3421 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3422 chainon (field_decl_chain, field_decl);
3424 /* long version; */
3426 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3427 field_decl = get_identifier ("version");
3428 field_decl
3429 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3430 chainon (field_decl_chain, field_decl);
3432 /* long info; */
3434 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3435 field_decl = get_identifier ("info");
3436 field_decl
3437 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3438 chainon (field_decl_chain, field_decl);
3440 /* long instance_size; */
3442 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3443 field_decl = get_identifier ("instance_size");
3444 field_decl
3445 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3446 chainon (field_decl_chain, field_decl);
3448 /* struct objc_ivar_list *ivars; */
3450 decl_specs = build_tree_list (NULL_TREE,
3451 xref_tag (RECORD_TYPE,
3452 get_identifier (UTAG_IVAR_LIST)));
3453 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3454 field_decl
3455 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3456 chainon (field_decl_chain, field_decl);
3458 /* struct objc_method_list *methods; */
3460 decl_specs = build_tree_list (NULL_TREE,
3461 xref_tag (RECORD_TYPE,
3462 get_identifier (UTAG_METHOD_LIST)));
3463 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3464 field_decl
3465 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3466 chainon (field_decl_chain, field_decl);
3468 if (flag_next_runtime)
3470 /* struct objc_cache *cache; */
3472 decl_specs = build_tree_list (NULL_TREE,
3473 xref_tag (RECORD_TYPE,
3474 get_identifier ("objc_cache")));
3475 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3476 field_decl = grokfield (input_filename, lineno, field_decl,
3477 decl_specs, NULL_TREE);
3478 chainon (field_decl_chain, field_decl);
3480 else
3482 /* struct sarray *dtable; */
3484 decl_specs = build_tree_list (NULL_TREE,
3485 xref_tag (RECORD_TYPE,
3486 get_identifier ("sarray")));
3487 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3488 field_decl = grokfield (input_filename, lineno, field_decl,
3489 decl_specs, NULL_TREE);
3490 chainon (field_decl_chain, field_decl);
3492 /* struct objc_class *subclass_list; */
3494 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3495 field_decl
3496 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3497 field_decl = grokfield (input_filename, lineno, field_decl,
3498 decl_specs, NULL_TREE);
3499 chainon (field_decl_chain, field_decl);
3501 /* struct objc_class *sibling_class; */
3503 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3504 field_decl
3505 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3506 field_decl = grokfield (input_filename, lineno, field_decl,
3507 decl_specs, NULL_TREE);
3508 chainon (field_decl_chain, field_decl);
3511 /* struct objc_protocol **protocol_list; */
3513 decl_specs = build_tree_list (NULL_TREE,
3514 xref_tag (RECORD_TYPE,
3515 get_identifier (UTAG_PROTOCOL)));
3516 field_decl
3517 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3518 field_decl
3519 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3520 field_decl = grokfield (input_filename, lineno, field_decl,
3521 decl_specs, NULL_TREE);
3522 chainon (field_decl_chain, field_decl);
3524 /* void *sel_id; */
3526 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3527 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3528 field_decl
3529 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3530 chainon (field_decl_chain, field_decl);
3532 /* void *gc_object_type; */
3534 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3535 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3536 field_decl
3537 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3538 chainon (field_decl_chain, field_decl);
3540 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3543 /* Generate appropriate forward declarations for an implementation. */
3545 static void
3546 synth_forward_declarations ()
3548 tree sc_spec, decl_specs, an_id;
3550 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3552 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3554 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3555 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3556 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3557 TREE_USED (UOBJC_CLASS_decl) = 1;
3558 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3560 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3562 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3563 implementation_context);
3565 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3566 TREE_USED (UOBJC_METACLASS_decl) = 1;
3567 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3569 /* Pre-build the following entities - for speed/convenience. */
3571 an_id = get_identifier ("super_class");
3572 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3573 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3576 static void
3577 error_with_ivar (message, decl, rawdecl)
3578 const char *message;
3579 tree decl;
3580 tree rawdecl;
3582 count_error (0);
3584 report_error_function (DECL_SOURCE_FILE (decl));
3586 fprintf (stderr, "%s:%d: ",
3587 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3588 bzero (errbuf, BUFSIZE);
3589 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3592 #define USERTYPE(t) \
3593 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3594 || TREE_CODE (t) == ENUMERAL_TYPE)
3596 static void
3597 check_ivars (inter, imp)
3598 tree inter;
3599 tree imp;
3601 tree intdecls = CLASS_IVARS (inter);
3602 tree impdecls = CLASS_IVARS (imp);
3603 tree rawintdecls = CLASS_RAW_IVARS (inter);
3604 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3606 while (1)
3608 tree t1, t2;
3610 if (intdecls == 0 && impdecls == 0)
3611 break;
3612 if (intdecls == 0 || impdecls == 0)
3614 error ("inconsistent instance variable specification");
3615 break;
3618 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3620 if (!comptypes (t1, t2))
3622 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3624 error_with_ivar ("conflicting instance variable type",
3625 impdecls, rawimpdecls);
3626 error_with_ivar ("previous declaration of",
3627 intdecls, rawintdecls);
3629 else /* both the type and the name don't match */
3631 error ("inconsistent instance variable specification");
3632 break;
3636 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3638 error_with_ivar ("conflicting instance variable name",
3639 impdecls, rawimpdecls);
3640 error_with_ivar ("previous declaration of",
3641 intdecls, rawintdecls);
3644 intdecls = TREE_CHAIN (intdecls);
3645 impdecls = TREE_CHAIN (impdecls);
3646 rawintdecls = TREE_CHAIN (rawintdecls);
3647 rawimpdecls = TREE_CHAIN (rawimpdecls);
3651 /* Set super_type to the data type node for struct objc_super *,
3652 first defining struct objc_super itself.
3653 This needs to be done just once per compilation. */
3655 static tree
3656 build_super_template ()
3658 tree record, decl_specs, field_decl, field_decl_chain;
3660 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3662 /* struct objc_object *self; */
3664 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3665 field_decl = get_identifier ("self");
3666 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3667 field_decl = grokfield (input_filename, lineno,
3668 field_decl, decl_specs, NULL_TREE);
3669 field_decl_chain = field_decl;
3671 /* struct objc_class *class; */
3673 decl_specs = get_identifier (UTAG_CLASS);
3674 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3675 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3677 field_decl = grokfield (input_filename, lineno,
3678 field_decl, decl_specs, NULL_TREE);
3679 chainon (field_decl_chain, field_decl);
3681 finish_struct (record, field_decl_chain, NULL_TREE);
3683 /* `struct objc_super *' */
3684 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3685 record),
3686 build1 (INDIRECT_REF,
3687 NULL_TREE, NULL_TREE)));
3688 return record;
3691 /* struct objc_ivar {
3692 char *ivar_name;
3693 char *ivar_type;
3694 int ivar_offset;
3695 }; */
3697 static tree
3698 build_ivar_template ()
3700 tree objc_ivar_id, objc_ivar_record;
3701 tree decl_specs, field_decl, field_decl_chain;
3703 objc_ivar_id = get_identifier (UTAG_IVAR);
3704 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3706 /* char *ivar_name; */
3708 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3709 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3711 field_decl = grokfield (input_filename, lineno, field_decl,
3712 decl_specs, NULL_TREE);
3713 field_decl_chain = field_decl;
3715 /* char *ivar_type; */
3717 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3718 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3720 field_decl = grokfield (input_filename, lineno, field_decl,
3721 decl_specs, NULL_TREE);
3722 chainon (field_decl_chain, field_decl);
3724 /* int ivar_offset; */
3726 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3727 field_decl = get_identifier ("ivar_offset");
3729 field_decl = grokfield (input_filename, lineno, field_decl,
3730 decl_specs, NULL_TREE);
3731 chainon (field_decl_chain, field_decl);
3733 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3735 return objc_ivar_record;
3738 /* struct {
3739 int ivar_count;
3740 struct objc_ivar ivar_list[ivar_count];
3741 }; */
3743 static tree
3744 build_ivar_list_template (list_type, size)
3745 tree list_type;
3746 int size;
3748 tree objc_ivar_list_record;
3749 tree decl_specs, field_decl, field_decl_chain;
3751 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3753 /* int ivar_count; */
3755 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3756 field_decl = get_identifier ("ivar_count");
3758 field_decl = grokfield (input_filename, lineno, field_decl,
3759 decl_specs, NULL_TREE);
3760 field_decl_chain = field_decl;
3762 /* struct objc_ivar ivar_list[]; */
3764 decl_specs = build_tree_list (NULL_TREE, list_type);
3765 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3766 build_int_2 (size, 0));
3768 field_decl = grokfield (input_filename, lineno,
3769 field_decl, decl_specs, NULL_TREE);
3770 chainon (field_decl_chain, field_decl);
3772 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3774 return objc_ivar_list_record;
3777 /* struct {
3778 int method_next;
3779 int method_count;
3780 struct objc_method method_list[method_count];
3781 }; */
3783 static tree
3784 build_method_list_template (list_type, size)
3785 tree list_type;
3786 int size;
3788 tree objc_ivar_list_record;
3789 tree decl_specs, field_decl, field_decl_chain;
3791 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3793 /* int method_next; */
3795 decl_specs
3796 = build_tree_list
3797 (NULL_TREE,
3798 xref_tag (RECORD_TYPE,
3799 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3800 field_decl
3801 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3802 field_decl = grokfield (input_filename, lineno, field_decl,
3803 decl_specs, NULL_TREE);
3804 field_decl_chain = field_decl;
3806 /* int method_count; */
3808 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3809 field_decl = get_identifier ("method_count");
3811 field_decl = grokfield (input_filename, lineno,
3812 field_decl, decl_specs, NULL_TREE);
3813 chainon (field_decl_chain, field_decl);
3815 /* struct objc_method method_list[]; */
3817 decl_specs = build_tree_list (NULL_TREE, list_type);
3818 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3819 build_int_2 (size, 0));
3821 field_decl = grokfield (input_filename, lineno,
3822 field_decl, decl_specs, NULL_TREE);
3823 chainon (field_decl_chain, field_decl);
3825 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3827 return objc_ivar_list_record;
3830 static tree
3831 build_ivar_list_initializer (type, field_decl)
3832 tree type;
3833 tree field_decl;
3835 tree initlist = NULL_TREE;
3839 tree ivar = NULL_TREE;
3841 /* Set name. */
3842 if (DECL_NAME (field_decl))
3843 ivar = tree_cons (NULL_TREE,
3844 add_objc_string (DECL_NAME (field_decl),
3845 meth_var_names),
3846 ivar);
3847 else
3848 /* Unnamed bit-field ivar (yuck). */
3849 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3851 /* Set type. */
3852 encode_field_decl (field_decl,
3853 obstack_object_size (&util_obstack),
3854 OBJC_ENCODE_DONT_INLINE_DEFS);
3856 /* Null terminate string. */
3857 obstack_1grow (&util_obstack, 0);
3858 ivar
3859 = tree_cons
3860 (NULL_TREE,
3861 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3862 meth_var_types),
3863 ivar);
3864 obstack_free (&util_obstack, util_firstobj);
3866 /* set offset */
3867 ivar
3868 = tree_cons
3869 (NULL_TREE,
3870 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3871 / BITS_PER_UNIT),
3873 ivar);
3875 initlist = tree_cons (NULL_TREE,
3876 build_constructor (type, nreverse (ivar)),
3877 initlist);
3879 field_decl = TREE_CHAIN (field_decl);
3881 while (field_decl);
3883 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3886 static tree
3887 generate_ivars_list (type, name, size, list)
3888 tree type;
3889 const char *name;
3890 int size;
3891 tree list;
3893 tree sc_spec, decl_specs, decl, initlist;
3895 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3896 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3898 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3899 decl_specs, 1, NULL_TREE, NULL_TREE);
3901 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3902 initlist = tree_cons (NULL_TREE, list, initlist);
3904 finish_decl (decl,
3905 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3906 NULL_TREE);
3908 return decl;
3911 static void
3912 generate_ivar_lists ()
3914 tree initlist, ivar_list_template, chain;
3915 tree cast, variable_length_type;
3916 int size;
3918 generating_instance_variables = 1;
3920 if (!objc_ivar_template)
3921 objc_ivar_template = build_ivar_template ();
3923 cast
3924 = build_tree_list
3925 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3926 get_identifier (UTAG_IVAR_LIST))),
3927 NULL_TREE);
3928 variable_length_type = groktypename (cast);
3930 /* Only generate class variables for the root of the inheritance
3931 hierarchy since these will be the same for every class. */
3933 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3934 && (chain = TYPE_FIELDS (objc_class_template)))
3936 size = list_length (chain);
3938 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3939 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3941 UOBJC_CLASS_VARIABLES_decl
3942 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3943 size, initlist);
3944 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3946 else
3947 UOBJC_CLASS_VARIABLES_decl = 0;
3949 chain = CLASS_IVARS (implementation_template);
3950 if (chain)
3952 size = list_length (chain);
3953 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3954 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3956 UOBJC_INSTANCE_VARIABLES_decl
3957 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3958 size, initlist);
3959 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3961 else
3962 UOBJC_INSTANCE_VARIABLES_decl = 0;
3964 generating_instance_variables = 0;
3967 static tree
3968 build_dispatch_table_initializer (type, entries)
3969 tree type;
3970 tree entries;
3972 tree initlist = NULL_TREE;
3976 tree elemlist = NULL_TREE;
3978 elemlist = tree_cons (NULL_TREE,
3979 build_selector (METHOD_SEL_NAME (entries)),
3980 NULL_TREE);
3982 elemlist = tree_cons (NULL_TREE,
3983 add_objc_string (METHOD_ENCODING (entries),
3984 meth_var_types),
3985 elemlist);
3987 elemlist = tree_cons (NULL_TREE,
3988 build_unary_op (ADDR_EXPR,
3989 METHOD_DEFINITION (entries), 1),
3990 elemlist);
3992 initlist = tree_cons (NULL_TREE,
3993 build_constructor (type, nreverse (elemlist)),
3994 initlist);
3996 entries = TREE_CHAIN (entries);
3998 while (entries);
4000 return build_constructor (build_array_type (type, 0), nreverse (initlist));
4003 /* To accomplish method prototyping without generating all kinds of
4004 inane warnings, the definition of the dispatch table entries were
4005 changed from:
4007 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4009 struct objc_method { SEL _cmd; ...; void *_imp; }; */
4011 static tree
4012 build_method_template ()
4014 tree _SLT_record;
4015 tree decl_specs, field_decl, field_decl_chain;
4017 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4019 #ifdef OBJC_INT_SELECTORS
4020 /* unsigned int _cmd; */
4021 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
4022 NULL_TREE);
4023 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
4024 field_decl = get_identifier ("_cmd");
4025 #else /* not OBJC_INT_SELECTORS */
4026 /* struct objc_selector *_cmd; */
4027 decl_specs = tree_cons (NULL_TREE,
4028 xref_tag (RECORD_TYPE,
4029 get_identifier (TAG_SELECTOR)),
4030 NULL_TREE);
4031 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4032 #endif /* not OBJC_INT_SELECTORS */
4034 field_decl = grokfield (input_filename, lineno, field_decl,
4035 decl_specs, NULL_TREE);
4036 field_decl_chain = field_decl;
4038 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4039 field_decl = build1 (INDIRECT_REF, NULL_TREE,
4040 get_identifier ("method_types"));
4041 field_decl = grokfield (input_filename, lineno, field_decl,
4042 decl_specs, NULL_TREE);
4043 chainon (field_decl_chain, field_decl);
4045 /* void *_imp; */
4047 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4048 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4049 field_decl = grokfield (input_filename, lineno, field_decl,
4050 decl_specs, NULL_TREE);
4051 chainon (field_decl_chain, field_decl);
4053 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4055 return _SLT_record;
4059 static tree
4060 generate_dispatch_table (type, name, size, list)
4061 tree type;
4062 const char *name;
4063 int size;
4064 tree list;
4066 tree sc_spec, decl_specs, decl, initlist;
4068 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4069 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4071 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
4072 decl_specs, 1, NULL_TREE, NULL_TREE);
4074 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4075 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4076 initlist = tree_cons (NULL_TREE, list, initlist);
4078 finish_decl (decl,
4079 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4080 NULL_TREE);
4082 return decl;
4085 static void
4086 generate_dispatch_tables ()
4088 tree initlist, chain, method_list_template;
4089 tree cast, variable_length_type;
4090 int size;
4092 if (!objc_method_template)
4093 objc_method_template = build_method_template ();
4095 cast
4096 = build_tree_list
4097 (build_tree_list (NULL_TREE,
4098 xref_tag (RECORD_TYPE,
4099 get_identifier (UTAG_METHOD_LIST))),
4100 NULL_TREE);
4102 variable_length_type = groktypename (cast);
4104 chain = CLASS_CLS_METHODS (implementation_context);
4105 if (chain)
4107 size = list_length (chain);
4109 method_list_template
4110 = build_method_list_template (objc_method_template, size);
4111 initlist
4112 = build_dispatch_table_initializer (objc_method_template, chain);
4114 UOBJC_CLASS_METHODS_decl
4115 = generate_dispatch_table (method_list_template,
4116 ((TREE_CODE (implementation_context)
4117 == CLASS_IMPLEMENTATION_TYPE)
4118 ? "_OBJC_CLASS_METHODS"
4119 : "_OBJC_CATEGORY_CLASS_METHODS"),
4120 size, initlist);
4121 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4123 else
4124 UOBJC_CLASS_METHODS_decl = 0;
4126 chain = CLASS_NST_METHODS (implementation_context);
4127 if (chain)
4129 size = list_length (chain);
4131 method_list_template
4132 = build_method_list_template (objc_method_template, size);
4133 initlist
4134 = build_dispatch_table_initializer (objc_method_template, chain);
4136 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4137 UOBJC_INSTANCE_METHODS_decl
4138 = generate_dispatch_table (method_list_template,
4139 "_OBJC_INSTANCE_METHODS",
4140 size, initlist);
4141 else
4142 /* We have a category. */
4143 UOBJC_INSTANCE_METHODS_decl
4144 = generate_dispatch_table (method_list_template,
4145 "_OBJC_CATEGORY_INSTANCE_METHODS",
4146 size, initlist);
4147 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4149 else
4150 UOBJC_INSTANCE_METHODS_decl = 0;
4153 static tree
4154 generate_protocol_list (i_or_p)
4155 tree i_or_p;
4157 static tree cast_type = 0;
4158 tree initlist, decl_specs, sc_spec;
4159 tree refs_decl, expr_decl, lproto, e, plist;
4160 int size = 0;
4162 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4163 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4164 plist = CLASS_PROTOCOL_LIST (i_or_p);
4165 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4166 plist = PROTOCOL_LIST (i_or_p);
4167 else
4168 abort ();
4170 if (!cast_type)
4171 cast_type
4172 = groktypename
4173 (build_tree_list
4174 (build_tree_list (NULL_TREE,
4175 xref_tag (RECORD_TYPE,
4176 get_identifier (UTAG_PROTOCOL))),
4177 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4179 /* Compute size. */
4180 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4181 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4182 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4183 size++;
4185 /* Build initializer. */
4186 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4188 e = build_int_2 (size, 0);
4189 TREE_TYPE (e) = cast_type;
4190 initlist = tree_cons (NULL_TREE, e, initlist);
4192 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4194 tree pval = TREE_VALUE (lproto);
4196 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4197 && PROTOCOL_FORWARD_DECL (pval))
4199 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4200 initlist = tree_cons (NULL_TREE, e, initlist);
4204 /* static struct objc_protocol *refs[n]; */
4206 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4207 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4208 get_identifier (UTAG_PROTOCOL)),
4209 sc_spec);
4211 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4212 expr_decl = build_nt (ARRAY_REF,
4213 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4214 i_or_p),
4215 build_int_2 (size + 2, 0));
4216 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4217 expr_decl = build_nt (ARRAY_REF,
4218 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4219 i_or_p),
4220 build_int_2 (size + 2, 0));
4221 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4222 expr_decl
4223 = build_nt (ARRAY_REF,
4224 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4225 i_or_p),
4226 build_int_2 (size + 2, 0));
4227 else
4228 abort ();
4230 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4232 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4234 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4235 nreverse (initlist)),
4236 NULL_TREE);
4238 return refs_decl;
4241 static tree
4242 build_category_initializer (type, cat_name, class_name,
4243 instance_methods, class_methods, protocol_list)
4244 tree type;
4245 tree cat_name;
4246 tree class_name;
4247 tree instance_methods;
4248 tree class_methods;
4249 tree protocol_list;
4251 tree initlist = NULL_TREE, expr;
4253 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4254 initlist = tree_cons (NULL_TREE, class_name, initlist);
4256 if (!instance_methods)
4257 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4258 else
4260 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4261 initlist = tree_cons (NULL_TREE, expr, initlist);
4263 if (!class_methods)
4264 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4265 else
4267 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4268 initlist = tree_cons (NULL_TREE, expr, initlist);
4271 /* protocol_list = */
4272 if (!protocol_list)
4273 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4274 else
4276 static tree cast_type2;
4278 if (!cast_type2)
4279 cast_type2
4280 = groktypename
4281 (build_tree_list
4282 (build_tree_list (NULL_TREE,
4283 xref_tag (RECORD_TYPE,
4284 get_identifier (UTAG_PROTOCOL))),
4285 build1 (INDIRECT_REF, NULL_TREE,
4286 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4288 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4289 TREE_TYPE (expr) = cast_type2;
4290 initlist = tree_cons (NULL_TREE, expr, initlist);
4293 return build_constructor (type, nreverse (initlist));
4296 /* struct objc_class {
4297 struct objc_class *isa;
4298 struct objc_class *super_class;
4299 char *name;
4300 long version;
4301 long info;
4302 long instance_size;
4303 struct objc_ivar_list *ivars;
4304 struct objc_method_list *methods;
4305 if (flag_next_runtime)
4306 struct objc_cache *cache;
4307 else {
4308 struct sarray *dtable;
4309 struct objc_class *subclass_list;
4310 struct objc_class *sibling_class;
4312 struct objc_protocol_list *protocols;
4313 void *gc_object_type;
4314 }; */
4316 static tree
4317 build_shared_structure_initializer (type, isa, super, name, size, status,
4318 dispatch_table, ivar_list, protocol_list)
4319 tree type;
4320 tree isa;
4321 tree super;
4322 tree name;
4323 tree size;
4324 int status;
4325 tree dispatch_table;
4326 tree ivar_list;
4327 tree protocol_list;
4329 tree initlist = NULL_TREE, expr;
4331 /* isa = */
4332 initlist = tree_cons (NULL_TREE, isa, initlist);
4334 /* super_class = */
4335 initlist = tree_cons (NULL_TREE, super, initlist);
4337 /* name = */
4338 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4340 /* version = */
4341 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4343 /* info = */
4344 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4346 /* instance_size = */
4347 initlist = tree_cons (NULL_TREE, size, initlist);
4349 /* objc_ivar_list = */
4350 if (!ivar_list)
4351 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4352 else
4354 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4355 initlist = tree_cons (NULL_TREE, expr, initlist);
4358 /* objc_method_list = */
4359 if (!dispatch_table)
4360 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4361 else
4363 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4364 initlist = tree_cons (NULL_TREE, expr, initlist);
4367 if (flag_next_runtime)
4368 /* method_cache = */
4369 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4370 else
4372 /* dtable = */
4373 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4375 /* subclass_list = */
4376 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4378 /* sibling_class = */
4379 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4382 /* protocol_list = */
4383 if (! protocol_list)
4384 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4385 else
4387 static tree cast_type2;
4389 if (!cast_type2)
4390 cast_type2
4391 = groktypename
4392 (build_tree_list
4393 (build_tree_list (NULL_TREE,
4394 xref_tag (RECORD_TYPE,
4395 get_identifier (UTAG_PROTOCOL))),
4396 build1 (INDIRECT_REF, NULL_TREE,
4397 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4399 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4400 TREE_TYPE (expr) = cast_type2;
4401 initlist = tree_cons (NULL_TREE, expr, initlist);
4404 /* gc_object_type = NULL */
4405 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4407 return build_constructor (type, nreverse (initlist));
4410 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4412 static void
4413 generate_category (cat)
4414 tree cat;
4416 tree sc_spec, decl_specs, decl;
4417 tree initlist, cat_name_expr, class_name_expr;
4418 tree protocol_decl, category;
4420 add_class_reference (CLASS_NAME (cat));
4421 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4423 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4425 category = CLASS_CATEGORY_LIST (implementation_template);
4427 /* find the category interface from the class it is associated with */
4428 while (category)
4430 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4431 break;
4432 category = CLASS_CATEGORY_LIST (category);
4435 if (category && CLASS_PROTOCOL_LIST (category))
4437 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4438 protocol_decl = generate_protocol_list (category);
4440 else
4441 protocol_decl = 0;
4443 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4444 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4446 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4447 implementation_context),
4448 decl_specs, 1, NULL_TREE, NULL_TREE);
4450 initlist = build_category_initializer (TREE_TYPE (decl),
4451 cat_name_expr, class_name_expr,
4452 UOBJC_INSTANCE_METHODS_decl,
4453 UOBJC_CLASS_METHODS_decl,
4454 protocol_decl);
4456 TREE_USED (decl) = 1;
4457 finish_decl (decl, initlist, NULL_TREE);
4460 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4461 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4463 static void
4464 generate_shared_structures ()
4466 tree sc_spec, decl_specs, decl;
4467 tree name_expr, super_expr, root_expr;
4468 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4469 tree cast_type, initlist, protocol_decl;
4471 my_super_id = CLASS_SUPER_NAME (implementation_template);
4472 if (my_super_id)
4474 add_class_reference (my_super_id);
4476 /* Compute "my_root_id" - this is required for code generation.
4477 the "isa" for all meta class structures points to the root of
4478 the inheritance hierarchy (e.g. "__Object")... */
4479 my_root_id = my_super_id;
4482 tree my_root_int = lookup_interface (my_root_id);
4484 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4485 my_root_id = CLASS_SUPER_NAME (my_root_int);
4486 else
4487 break;
4489 while (1);
4491 else
4492 /* No super class. */
4493 my_root_id = CLASS_NAME (implementation_template);
4495 cast_type
4496 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4497 objc_class_template),
4498 build1 (INDIRECT_REF,
4499 NULL_TREE, NULL_TREE)));
4501 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4502 class_names);
4504 /* Install class `isa' and `super' pointers at runtime. */
4505 if (my_super_id)
4507 super_expr = add_objc_string (my_super_id, class_names);
4508 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4510 else
4511 super_expr = build_int_2 (0, 0);
4513 root_expr = add_objc_string (my_root_id, class_names);
4514 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4516 if (CLASS_PROTOCOL_LIST (implementation_template))
4518 generate_protocol_references
4519 (CLASS_PROTOCOL_LIST (implementation_template));
4520 protocol_decl = generate_protocol_list (implementation_template);
4522 else
4523 protocol_decl = 0;
4525 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4527 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4528 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4530 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4531 NULL_TREE, NULL_TREE);
4533 initlist
4534 = build_shared_structure_initializer
4535 (TREE_TYPE (decl),
4536 root_expr, super_expr, name_expr,
4537 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4538 / BITS_PER_UNIT),
4540 2 /*CLS_META*/,
4541 UOBJC_CLASS_METHODS_decl,
4542 UOBJC_CLASS_VARIABLES_decl,
4543 protocol_decl);
4545 finish_decl (decl, initlist, NULL_TREE);
4547 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4549 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4550 NULL_TREE, NULL_TREE);
4552 initlist
4553 = build_shared_structure_initializer
4554 (TREE_TYPE (decl),
4555 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4556 super_expr, name_expr,
4557 build_int_2
4558 ((TREE_INT_CST_LOW
4559 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4560 / BITS_PER_UNIT),
4562 1 /*CLS_FACTORY*/,
4563 UOBJC_INSTANCE_METHODS_decl,
4564 UOBJC_INSTANCE_VARIABLES_decl,
4565 protocol_decl);
4567 finish_decl (decl, initlist, NULL_TREE);
4570 static tree
4571 synth_id_with_class_suffix (preamble, ctxt)
4572 const char *preamble;
4573 tree ctxt;
4575 char *string;
4576 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4577 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4579 const char *class_name
4580 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4581 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4582 sprintf (string, "%s_%s", preamble,
4583 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4585 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4586 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4588 /* We have a category. */
4589 const char *class_name
4590 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4591 const char *class_super_name
4592 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4593 string = (char *) alloca (strlen (preamble)
4594 + strlen (class_name)
4595 + strlen (class_super_name)
4596 + 3);
4597 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4599 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4601 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4602 string
4603 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4604 sprintf (string, "%s_%s", preamble, protocol_name);
4606 else
4607 abort ();
4609 return get_identifier (string);
4612 static int
4613 is_objc_type_qualifier (node)
4614 tree node;
4616 return (TREE_CODE (node) == IDENTIFIER_NODE
4617 && (node == ridpointers [(int) RID_CONST]
4618 || node == ridpointers [(int) RID_VOLATILE]
4619 || node == ridpointers [(int) RID_IN]
4620 || node == ridpointers [(int) RID_OUT]
4621 || node == ridpointers [(int) RID_INOUT]
4622 || node == ridpointers [(int) RID_BYCOPY]
4623 || node == ridpointers [(int) RID_BYREF]
4624 || node == ridpointers [(int) RID_ONEWAY]));
4627 /* If type is empty or only type qualifiers are present, add default
4628 type of id (otherwise grokdeclarator will default to int). */
4630 static tree
4631 adjust_type_for_id_default (type)
4632 tree type;
4634 tree declspecs, chain;
4636 if (!type)
4637 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4638 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4640 declspecs = TREE_PURPOSE (type);
4642 /* Determine if a typespec is present. */
4643 for (chain = declspecs;
4644 chain;
4645 chain = TREE_CHAIN (chain))
4647 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4648 return type;
4651 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4652 declspecs),
4653 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4656 /* Usage:
4657 keyworddecl:
4658 selector ':' '(' typename ')' identifier
4660 Purpose:
4661 Transform an Objective-C keyword argument into
4662 the C equivalent parameter declarator.
4664 In: key_name, an "identifier_node" (optional).
4665 arg_type, a "tree_list" (optional).
4666 arg_name, an "identifier_node".
4668 Note: It would be really nice to strongly type the preceding
4669 arguments in the function prototype; however, then I
4670 could not use the "accessor" macros defined in "tree.h".
4672 Out: an instance of "keyword_decl". */
4674 tree
4675 build_keyword_decl (key_name, arg_type, arg_name)
4676 tree key_name;
4677 tree arg_type;
4678 tree arg_name;
4680 tree keyword_decl;
4682 /* If no type is specified, default to "id". */
4683 arg_type = adjust_type_for_id_default (arg_type);
4685 keyword_decl = make_node (KEYWORD_DECL);
4687 TREE_TYPE (keyword_decl) = arg_type;
4688 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4689 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4691 return keyword_decl;
4694 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4696 static tree
4697 build_keyword_selector (selector)
4698 tree selector;
4700 int len = 0;
4701 tree key_chain, key_name;
4702 char *buf;
4704 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4706 if (TREE_CODE (selector) == KEYWORD_DECL)
4707 key_name = KEYWORD_KEY_NAME (key_chain);
4708 else if (TREE_CODE (selector) == TREE_LIST)
4709 key_name = TREE_PURPOSE (key_chain);
4710 else
4711 abort ();
4713 if (key_name)
4714 len += IDENTIFIER_LENGTH (key_name) + 1;
4715 else
4716 /* Just a ':' arg. */
4717 len++;
4720 buf = (char *)alloca (len + 1);
4721 bzero (buf, len + 1);
4723 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4725 if (TREE_CODE (selector) == KEYWORD_DECL)
4726 key_name = KEYWORD_KEY_NAME (key_chain);
4727 else if (TREE_CODE (selector) == TREE_LIST)
4728 key_name = TREE_PURPOSE (key_chain);
4729 else
4730 abort ();
4732 if (key_name)
4733 strcat (buf, IDENTIFIER_POINTER (key_name));
4734 strcat (buf, ":");
4737 return get_identifier (buf);
4740 /* Used for declarations and definitions. */
4742 tree
4743 build_method_decl (code, ret_type, selector, add_args)
4744 enum tree_code code;
4745 tree ret_type;
4746 tree selector;
4747 tree add_args;
4749 tree method_decl;
4751 /* If no type is specified, default to "id". */
4752 ret_type = adjust_type_for_id_default (ret_type);
4754 method_decl = make_node (code);
4755 TREE_TYPE (method_decl) = ret_type;
4757 /* If we have a keyword selector, create an identifier_node that
4758 represents the full selector name (`:' included)... */
4759 if (TREE_CODE (selector) == KEYWORD_DECL)
4761 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4762 METHOD_SEL_ARGS (method_decl) = selector;
4763 METHOD_ADD_ARGS (method_decl) = add_args;
4765 else
4767 METHOD_SEL_NAME (method_decl) = selector;
4768 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4769 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4772 return method_decl;
4775 #define METHOD_DEF 0
4776 #define METHOD_REF 1
4778 /* Used by `build_message_expr' and `comp_method_types'. Return an
4779 argument list for method METH. CONTEXT is either METHOD_DEF or
4780 METHOD_REF, saying whether we are trying to define a method or call
4781 one. SUPERFLAG says this is for a send to super; this makes a
4782 difference for the NeXT calling sequence in which the lookup and
4783 the method call are done together. */
4785 static tree
4786 get_arg_type_list (meth, context, superflag)
4787 tree meth;
4788 int context;
4789 int superflag;
4791 tree arglist, akey;
4793 /* Receiver type. */
4794 if (flag_next_runtime && superflag)
4795 arglist = build_tree_list (NULL_TREE, super_type);
4796 else if (context == METHOD_DEF)
4797 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4798 else
4799 arglist = build_tree_list (NULL_TREE, id_type);
4801 /* Selector type - will eventually change to `int'. */
4802 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4804 /* Build a list of argument types. */
4805 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4807 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4808 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4811 if (METHOD_ADD_ARGS (meth) == (tree)1)
4812 /* We have a `, ...' immediately following the selector,
4813 finalize the arglist...simulate get_parm_info (0). */
4815 else if (METHOD_ADD_ARGS (meth))
4817 /* we have a variable length selector */
4818 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4819 chainon (arglist, add_arg_list);
4821 else
4822 /* finalize the arglist...simulate get_parm_info (1) */
4823 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4825 return arglist;
4828 static tree
4829 check_duplicates (hsh)
4830 hash hsh;
4832 tree meth = NULL_TREE;
4834 if (hsh)
4836 meth = hsh->key;
4838 if (hsh->list)
4840 /* We have two methods with the same name and different types. */
4841 attr loop;
4842 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4844 warning ("multiple declarations for method `%s'",
4845 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4847 warn_with_method ("using", type, meth);
4848 for (loop = hsh->list; loop; loop = loop->next)
4849 warn_with_method ("also found", type, loop->value);
4852 return meth;
4855 /* If RECEIVER is a class reference, return the identifier node for the
4856 referenced class. RECEIVER is created by get_class_reference, so we
4857 check the exact form created depending on which runtimes are used. */
4859 static tree
4860 receiver_is_class_object (receiver)
4861 tree receiver;
4863 tree chain, exp, arg;
4864 if (flag_next_runtime)
4866 /* The receiver is a variable created by build_class_reference_decl. */
4867 if (TREE_CODE (receiver) == VAR_DECL
4868 && TREE_TYPE (receiver) == objc_class_type)
4869 /* Look up the identifier. */
4870 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4871 if (TREE_PURPOSE (chain) == receiver)
4872 return TREE_VALUE (chain);
4874 else
4876 /* The receiver is a function call that returns an id. Check if
4877 it is a call to objc_getClass, if so, pick up the class name. */
4878 if ((exp = TREE_OPERAND (receiver, 0))
4879 && TREE_CODE (exp) == ADDR_EXPR
4880 && (exp = TREE_OPERAND (exp, 0))
4881 && TREE_CODE (exp) == FUNCTION_DECL
4882 && exp == objc_get_class_decl
4883 /* we have a call to objc_getClass! */
4884 && (arg = TREE_OPERAND (receiver, 1))
4885 && TREE_CODE (arg) == TREE_LIST
4886 && (arg = TREE_VALUE (arg)))
4888 STRIP_NOPS (arg);
4889 if (TREE_CODE (arg) == ADDR_EXPR
4890 && (arg = TREE_OPERAND (arg, 0))
4891 && TREE_CODE (arg) == STRING_CST)
4892 /* Finally, we have the class name. */
4893 return get_identifier (TREE_STRING_POINTER (arg));
4896 return 0;
4899 /* If we are currently building a message expr, this holds
4900 the identifier of the selector of the message. This is
4901 used when printing warnings about argument mismatches. */
4903 static tree building_objc_message_expr = 0;
4905 tree
4906 maybe_building_objc_message_expr ()
4908 return building_objc_message_expr;
4911 /* Construct an expression for sending a message.
4912 MESS has the object to send to in TREE_PURPOSE
4913 and the argument list (including selector) in TREE_VALUE.
4915 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4916 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4918 tree
4919 build_message_expr (mess)
4920 tree mess;
4922 tree receiver = TREE_PURPOSE (mess);
4923 tree selector, self_object;
4924 tree rtype, sel_name;
4925 tree args = TREE_VALUE (mess);
4926 tree method_params = NULL_TREE;
4927 tree method_prototype = NULL_TREE;
4928 tree retval;
4929 int statically_typed = 0, statically_allocated = 0;
4930 tree class_ident = 0;
4932 /* 1 if this is sending to the superclass. */
4933 int super;
4935 if (!doing_objc_thang)
4936 objc_fatal ();
4938 if (TREE_CODE (receiver) == ERROR_MARK)
4939 return error_mark_node;
4941 /* Determine receiver type. */
4942 rtype = TREE_TYPE (receiver);
4943 super = IS_SUPER (rtype);
4945 if (! super)
4947 if (TREE_STATIC_TEMPLATE (rtype))
4948 statically_allocated = 1;
4949 else if (TREE_CODE (rtype) == POINTER_TYPE
4950 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4951 statically_typed = 1;
4952 else if ((flag_next_runtime
4953 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4954 && (class_ident = receiver_is_class_object (receiver)))
4956 else if (! IS_ID (rtype)
4957 /* Allow any type that matches objc_class_type. */
4958 && ! comptypes (rtype, objc_class_type))
4960 bzero (errbuf, BUFSIZE);
4961 warning ("invalid receiver type `%s'",
4962 gen_declaration (rtype, errbuf));
4965 if (statically_allocated)
4966 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4968 /* Don't evaluate the receiver twice. */
4969 receiver = save_expr (receiver);
4970 self_object = receiver;
4972 else
4973 /* If sending to `super', use current self as the object. */
4974 self_object = self_decl;
4976 /* Obtain the full selector name. */
4978 if (TREE_CODE (args) == IDENTIFIER_NODE)
4979 /* A unary selector. */
4980 sel_name = args;
4981 else if (TREE_CODE (args) == TREE_LIST)
4982 sel_name = build_keyword_selector (args);
4983 else
4984 abort ();
4986 /* Build the parameter list to give to the method. */
4988 method_params = NULL_TREE;
4989 if (TREE_CODE (args) == TREE_LIST)
4991 tree chain = args, prev = NULL_TREE;
4993 /* We have a keyword selector--check for comma expressions. */
4994 while (chain)
4996 tree element = TREE_VALUE (chain);
4998 /* We have a comma expression, must collapse... */
4999 if (TREE_CODE (element) == TREE_LIST)
5001 if (prev)
5002 TREE_CHAIN (prev) = element;
5003 else
5004 args = element;
5006 prev = chain;
5007 chain = TREE_CHAIN (chain);
5009 method_params = args;
5012 /* Determine operation return type. */
5014 if (IS_SUPER (rtype))
5016 tree iface;
5018 if (CLASS_SUPER_NAME (implementation_template))
5020 iface
5021 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5023 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
5024 method_prototype = lookup_instance_method_static (iface, sel_name);
5025 else
5026 method_prototype = lookup_class_method_static (iface, sel_name);
5028 if (iface && !method_prototype)
5029 warning ("`%s' does not respond to `%s'",
5030 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
5031 IDENTIFIER_POINTER (sel_name));
5033 else
5035 error ("no super class declared in interface for `%s'",
5036 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5037 return error_mark_node;
5041 else if (statically_allocated)
5043 tree ctype = TREE_TYPE (rtype);
5044 tree iface = lookup_interface (TYPE_NAME (rtype));
5046 if (iface)
5047 method_prototype = lookup_instance_method_static (iface, sel_name);
5049 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5050 method_prototype
5051 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5052 sel_name, 0);
5054 if (!method_prototype)
5055 warning ("`%s' does not respond to `%s'",
5056 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
5057 IDENTIFIER_POINTER (sel_name));
5059 else if (statically_typed)
5061 tree ctype = TREE_TYPE (rtype);
5063 /* `self' is now statically_typed. All methods should be visible
5064 within the context of the implementation. */
5065 if (implementation_context
5066 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
5068 method_prototype
5069 = lookup_instance_method_static (implementation_template,
5070 sel_name);
5072 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5073 method_prototype
5074 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5075 sel_name, 0);
5077 if (! method_prototype
5078 && implementation_template != implementation_context)
5079 /* The method is not published in the interface. Check
5080 locally. */
5081 method_prototype
5082 = lookup_method (CLASS_NST_METHODS (implementation_context),
5083 sel_name);
5085 else
5087 tree iface;
5089 if ((iface = lookup_interface (TYPE_NAME (ctype))))
5090 method_prototype = lookup_instance_method_static (iface, sel_name);
5092 if (! method_prototype)
5094 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5095 if (protocol_list)
5096 method_prototype
5097 = lookup_method_in_protocol_list (protocol_list,
5098 sel_name, 0);
5102 if (!method_prototype)
5103 warning ("`%s' does not respond to `%s'",
5104 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5105 IDENTIFIER_POINTER (sel_name));
5107 else if (class_ident)
5109 if (implementation_context
5110 && CLASS_NAME (implementation_context) == class_ident)
5112 method_prototype
5113 = lookup_class_method_static (implementation_template, sel_name);
5115 if (!method_prototype
5116 && implementation_template != implementation_context)
5117 /* The method is not published in the interface. Check
5118 locally. */
5119 method_prototype
5120 = lookup_method (CLASS_CLS_METHODS (implementation_context),
5121 sel_name);
5123 else
5125 tree iface;
5127 if ((iface = lookup_interface (class_ident)))
5128 method_prototype = lookup_class_method_static (iface, sel_name);
5131 if (!method_prototype)
5133 warning ("cannot find class (factory) method.");
5134 warning ("return type for `%s' defaults to id",
5135 IDENTIFIER_POINTER (sel_name));
5138 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5140 /* An anonymous object that has been qualified with a protocol. */
5142 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5144 method_prototype = lookup_method_in_protocol_list (protocol_list,
5145 sel_name, 0);
5147 if (!method_prototype)
5149 hash hsh;
5151 warning ("method `%s' not implemented by protocol.",
5152 IDENTIFIER_POINTER (sel_name));
5154 /* Try and find the method signature in the global pools. */
5156 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5157 hsh = hash_lookup (cls_method_hash_list, sel_name);
5159 if (!(method_prototype = check_duplicates (hsh)))
5160 warning ("return type defaults to id");
5163 else
5165 hash hsh;
5167 /* We think we have an instance...loophole: extern id Object; */
5168 hsh = hash_lookup (nst_method_hash_list, sel_name);
5169 if (!hsh)
5170 /* For various loopholes, like sending messages to self in a
5171 factory context. */
5172 hsh = hash_lookup (cls_method_hash_list, sel_name);
5174 method_prototype = check_duplicates (hsh);
5175 if (!method_prototype)
5177 warning ("cannot find method.");
5178 warning ("return type for `%s' defaults to id",
5179 IDENTIFIER_POINTER (sel_name));
5183 /* Save the selector name for printing error messages. */
5184 building_objc_message_expr = sel_name;
5186 /* Build the parameters list for looking up the method.
5187 These are the object itself and the selector. */
5189 if (flag_typed_selectors)
5190 selector = build_typed_selector_reference (sel_name, method_prototype);
5191 else
5192 selector = build_selector_reference (sel_name);
5194 retval = build_objc_method_call (super, method_prototype,
5195 receiver, self_object,
5196 selector, method_params);
5198 building_objc_message_expr = 0;
5200 return retval;
5203 /* Build a tree expression to send OBJECT the operation SELECTOR,
5204 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5205 assuming the method has prototype METHOD_PROTOTYPE.
5206 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5207 Use METHOD_PARAMS as list of args to pass to the method.
5208 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5210 static tree
5211 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5212 selector, method_params)
5213 int super_flag;
5214 tree method_prototype, lookup_object, object, selector, method_params;
5216 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5217 tree rcv_p = (super_flag
5218 ? build_pointer_type (xref_tag (RECORD_TYPE,
5219 get_identifier (TAG_SUPER)))
5220 : id_type);
5222 if (flag_next_runtime)
5224 if (! method_prototype)
5226 method_params = tree_cons (NULL_TREE, lookup_object,
5227 tree_cons (NULL_TREE, selector,
5228 method_params));
5229 assemble_external (sender);
5230 return build_function_call (sender, method_params);
5232 else
5234 /* This is a real kludge, but it is used only for the Next.
5235 Clobber the data type of SENDER temporarily to accept
5236 all the arguments for this operation, and to return
5237 whatever this operation returns. */
5238 tree arglist = NULL_TREE;
5239 tree retval;
5241 /* Save the proper contents of SENDER's data type. */
5242 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5243 tree savret = TREE_TYPE (TREE_TYPE (sender));
5245 /* Install this method's argument types. */
5246 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5247 super_flag);
5248 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5250 /* Install this method's return type. */
5251 TREE_TYPE (TREE_TYPE (sender))
5252 = groktypename (TREE_TYPE (method_prototype));
5254 /* Call SENDER with all the parameters. This will do type
5255 checking using the arg types for this method. */
5256 method_params = tree_cons (NULL_TREE, lookup_object,
5257 tree_cons (NULL_TREE, selector,
5258 method_params));
5259 assemble_external (sender);
5260 retval = build_function_call (sender, method_params);
5262 /* Restore SENDER's return/argument types. */
5263 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5264 TREE_TYPE (TREE_TYPE (sender)) = savret;
5265 return retval;
5268 else
5270 /* This is the portable way.
5271 First call the lookup function to get a pointer to the method,
5272 then cast the pointer, then call it with the method arguments. */
5273 tree method;
5275 /* Avoid trouble since we may evaluate each of these twice. */
5276 object = save_expr (object);
5277 selector = save_expr (selector);
5279 lookup_object = build_c_cast (rcv_p, lookup_object);
5281 assemble_external (sender);
5282 method
5283 = build_function_call (sender,
5284 tree_cons (NULL_TREE, lookup_object,
5285 tree_cons (NULL_TREE, selector,
5286 NULL_TREE)));
5288 /* If we have a method prototype, construct the data type this
5289 method needs, and cast what we got from SENDER into a pointer
5290 to that type. */
5291 if (method_prototype)
5293 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5294 super_flag);
5295 tree valtype = groktypename (TREE_TYPE (method_prototype));
5296 tree fake_function_type = build_function_type (valtype, arglist);
5297 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5299 else
5300 TREE_TYPE (method)
5301 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5303 /* Pass the object to the method. */
5304 assemble_external (method);
5305 return build_function_call (method,
5306 tree_cons (NULL_TREE, object,
5307 tree_cons (NULL_TREE, selector,
5308 method_params)));
5312 static void
5313 build_protocol_reference (p)
5314 tree p;
5316 tree decl, ident, ptype;
5318 push_obstacks_nochange ();
5319 end_temporary_allocation ();
5321 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5323 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5324 ptype
5325 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5326 objc_protocol_template),
5327 NULL_TREE));
5329 if (IDENTIFIER_GLOBAL_VALUE (ident))
5330 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5331 else
5333 decl = build_decl (VAR_DECL, ident, ptype);
5334 DECL_EXTERNAL (decl) = 1;
5335 TREE_PUBLIC (decl) = 1;
5336 TREE_USED (decl) = 1;
5337 DECL_ARTIFICIAL (decl) = 1;
5339 make_decl_rtl (decl, 0, 1);
5340 pushdecl_top_level (decl);
5343 PROTOCOL_FORWARD_DECL (p) = decl;
5344 pop_obstacks ();
5347 tree
5348 build_protocol_expr (protoname)
5349 tree protoname;
5351 tree expr;
5352 tree p;
5354 if (!doing_objc_thang)
5355 objc_fatal ();
5357 p = lookup_protocol (protoname);
5359 if (!p)
5361 error ("Cannot find protocol declaration for `%s'",
5362 IDENTIFIER_POINTER (protoname));
5363 return error_mark_node;
5366 if (!PROTOCOL_FORWARD_DECL (p))
5367 build_protocol_reference (p);
5369 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5371 TREE_TYPE (expr) = protocol_type;
5373 return expr;
5376 tree
5377 build_selector_expr (selnamelist)
5378 tree selnamelist;
5380 tree selname;
5382 if (!doing_objc_thang)
5383 objc_fatal ();
5385 /* Obtain the full selector name. */
5386 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5387 /* A unary selector. */
5388 selname = selnamelist;
5389 else if (TREE_CODE (selnamelist) == TREE_LIST)
5390 selname = build_keyword_selector (selnamelist);
5391 else
5392 abort ();
5394 if (flag_typed_selectors)
5395 return build_typed_selector_reference (selname, 0);
5396 else
5397 return build_selector_reference (selname);
5400 tree
5401 build_encode_expr (type)
5402 tree type;
5404 tree result;
5405 const char *string;
5407 if (!doing_objc_thang)
5408 objc_fatal ();
5410 encode_type (type, obstack_object_size (&util_obstack),
5411 OBJC_ENCODE_INLINE_DEFS);
5412 obstack_1grow (&util_obstack, 0); /* null terminate string */
5413 string = obstack_finish (&util_obstack);
5415 /* Synthesize a string that represents the encoded struct/union. */
5416 result = my_build_string (strlen (string) + 1, string);
5417 obstack_free (&util_obstack, util_firstobj);
5418 return result;
5421 tree
5422 build_ivar_reference (id)
5423 tree id;
5425 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5427 /* Historically, a class method that produced objects (factory
5428 method) would assign `self' to the instance that it
5429 allocated. This would effectively turn the class method into
5430 an instance method. Following this assignment, the instance
5431 variables could be accessed. That practice, while safe,
5432 violates the simple rule that a class method should not refer
5433 to an instance variable. It's better to catch the cases
5434 where this is done unknowingly than to support the above
5435 paradigm. */
5436 warning ("instance variable `%s' accessed in class method",
5437 IDENTIFIER_POINTER (id));
5438 TREE_TYPE (self_decl) = instance_type; /* cast */
5441 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5444 #define HASH_ALLOC_LIST_SIZE 170
5445 #define ATTR_ALLOC_LIST_SIZE 170
5446 #define SIZEHASHTABLE 257
5448 /* make positive */
5449 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5451 static void
5452 hash_init ()
5454 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5455 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5457 if (!nst_method_hash_list || !cls_method_hash_list)
5458 perror ("unable to allocate space in objc-tree.c");
5459 else
5461 int i;
5463 for (i = 0; i < SIZEHASHTABLE; i++)
5465 nst_method_hash_list[i] = 0;
5466 cls_method_hash_list[i] = 0;
5471 static void
5472 hash_enter (hashlist, method)
5473 hash *hashlist;
5474 tree method;
5476 static hash hash_alloc_list = 0;
5477 static int hash_alloc_index = 0;
5478 hash obj;
5479 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5481 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5483 hash_alloc_index = 0;
5484 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5485 * HASH_ALLOC_LIST_SIZE);
5486 if (! hash_alloc_list)
5487 perror ("unable to allocate in objc-tree.c");
5489 obj = &hash_alloc_list[hash_alloc_index++];
5490 obj->list = 0;
5491 obj->next = hashlist[slot];
5492 obj->key = method;
5494 hashlist[slot] = obj; /* append to front */
5497 static hash
5498 hash_lookup (hashlist, sel_name)
5499 hash *hashlist;
5500 tree sel_name;
5502 hash target;
5504 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5506 while (target)
5508 if (sel_name == METHOD_SEL_NAME (target->key))
5509 return target;
5511 target = target->next;
5513 return 0;
5516 static void
5517 hash_add_attr (entry, value)
5518 hash entry;
5519 tree value;
5521 static attr attr_alloc_list = 0;
5522 static int attr_alloc_index = 0;
5523 attr obj;
5525 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5527 attr_alloc_index = 0;
5528 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5529 * ATTR_ALLOC_LIST_SIZE);
5530 if (! attr_alloc_list)
5531 perror ("unable to allocate in objc-tree.c");
5533 obj = &attr_alloc_list[attr_alloc_index++];
5534 obj->next = entry->list;
5535 obj->value = value;
5537 entry->list = obj; /* append to front */
5540 static tree
5541 lookup_method (mchain, method)
5542 tree mchain;
5543 tree method;
5545 tree key;
5547 if (TREE_CODE (method) == IDENTIFIER_NODE)
5548 key = method;
5549 else
5550 key = METHOD_SEL_NAME (method);
5552 while (mchain)
5554 if (METHOD_SEL_NAME (mchain) == key)
5555 return mchain;
5556 mchain = TREE_CHAIN (mchain);
5558 return NULL_TREE;
5561 static tree
5562 lookup_instance_method_static (interface, ident)
5563 tree interface;
5564 tree ident;
5566 tree inter = interface;
5567 tree chain = CLASS_NST_METHODS (inter);
5568 tree meth = NULL_TREE;
5572 if ((meth = lookup_method (chain, ident)))
5573 return meth;
5575 if (CLASS_CATEGORY_LIST (inter))
5577 tree category = CLASS_CATEGORY_LIST (inter);
5578 chain = CLASS_NST_METHODS (category);
5582 if ((meth = lookup_method (chain, ident)))
5583 return meth;
5585 /* Check for instance methods in protocols in categories. */
5586 if (CLASS_PROTOCOL_LIST (category))
5588 if ((meth = (lookup_method_in_protocol_list
5589 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5590 return meth;
5593 if ((category = CLASS_CATEGORY_LIST (category)))
5594 chain = CLASS_NST_METHODS (category);
5596 while (category);
5599 if (CLASS_PROTOCOL_LIST (inter))
5601 if ((meth = (lookup_method_in_protocol_list
5602 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5603 return meth;
5606 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5607 chain = CLASS_NST_METHODS (inter);
5609 while (inter);
5611 return meth;
5614 static tree
5615 lookup_class_method_static (interface, ident)
5616 tree interface;
5617 tree ident;
5619 tree inter = interface;
5620 tree chain = CLASS_CLS_METHODS (inter);
5621 tree meth = NULL_TREE;
5622 tree root_inter = NULL_TREE;
5626 if ((meth = lookup_method (chain, ident)))
5627 return meth;
5629 if (CLASS_CATEGORY_LIST (inter))
5631 tree category = CLASS_CATEGORY_LIST (inter);
5632 chain = CLASS_CLS_METHODS (category);
5636 if ((meth = lookup_method (chain, ident)))
5637 return meth;
5639 /* Check for class methods in protocols in categories. */
5640 if (CLASS_PROTOCOL_LIST (category))
5642 if ((meth = (lookup_method_in_protocol_list
5643 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5644 return meth;
5647 if ((category = CLASS_CATEGORY_LIST (category)))
5648 chain = CLASS_CLS_METHODS (category);
5650 while (category);
5653 /* Check for class methods in protocols. */
5654 if (CLASS_PROTOCOL_LIST (inter))
5656 if ((meth = (lookup_method_in_protocol_list
5657 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5658 return meth;
5661 root_inter = inter;
5662 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5663 chain = CLASS_CLS_METHODS (inter);
5665 while (inter);
5667 /* Simulate wrap around. */
5668 return lookup_instance_method_static (root_inter, ident);
5671 tree
5672 add_class_method (class, method)
5673 tree class;
5674 tree method;
5676 tree mth;
5677 hash hsh;
5679 /* We will have allocated the method parameter declarations on the
5680 maybepermanent_obstack. Need to make sure they stick around! */
5681 preserve_data ();
5683 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5685 /* put method on list in reverse order */
5686 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5687 CLASS_CLS_METHODS (class) = method;
5689 else
5691 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5692 error ("duplicate definition of class method `%s'.",
5693 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5694 else
5696 /* Check types; if different, complain. */
5697 if (!comp_proto_with_proto (method, mth))
5698 error ("duplicate declaration of class method `%s'.",
5699 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5703 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5705 /* Install on a global chain. */
5706 hash_enter (cls_method_hash_list, method);
5708 else
5710 /* Check types; if different, add to a list. */
5711 if (!comp_proto_with_proto (method, hsh->key))
5712 hash_add_attr (hsh, method);
5714 return method;
5717 tree
5718 add_instance_method (class, method)
5719 tree class;
5720 tree method;
5722 tree mth;
5723 hash hsh;
5725 /* We will have allocated the method parameter declarations on the
5726 maybepermanent_obstack. Need to make sure they stick around! */
5727 preserve_data ();
5729 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5731 /* Put method on list in reverse order. */
5732 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5733 CLASS_NST_METHODS (class) = method;
5735 else
5737 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5738 error ("duplicate definition of instance method `%s'.",
5739 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5740 else
5742 /* Check types; if different, complain. */
5743 if (!comp_proto_with_proto (method, mth))
5744 error ("duplicate declaration of instance method `%s'.",
5745 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5749 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5751 /* Install on a global chain. */
5752 hash_enter (nst_method_hash_list, method);
5754 else
5756 /* Check types; if different, add to a list. */
5757 if (!comp_proto_with_proto (method, hsh->key))
5758 hash_add_attr (hsh, method);
5760 return method;
5763 static tree
5764 add_class (class)
5765 tree class;
5767 /* Put interfaces on list in reverse order. */
5768 TREE_CHAIN (class) = interface_chain;
5769 interface_chain = class;
5770 return interface_chain;
5773 static void
5774 add_category (class, category)
5775 tree class;
5776 tree category;
5778 /* Put categories on list in reverse order. */
5779 tree cat = CLASS_CATEGORY_LIST (class);
5781 while (cat)
5783 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5784 warning ("duplicate interface declaration for category `%s(%s)'",
5785 IDENTIFIER_POINTER (CLASS_NAME (class)),
5786 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5787 cat = CLASS_CATEGORY_LIST (cat);
5790 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5791 CLASS_CATEGORY_LIST (class) = category;
5794 /* Called after parsing each instance variable declaration. Necessary to
5795 preserve typedefs and implement public/private...
5797 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5799 tree
5800 add_instance_variable (class, public, declarator, declspecs, width)
5801 tree class;
5802 int public;
5803 tree declarator;
5804 tree declspecs;
5805 tree width;
5807 tree field_decl, raw_decl;
5809 raw_decl = build_tree_list (declspecs, declarator);
5811 if (CLASS_RAW_IVARS (class))
5812 chainon (CLASS_RAW_IVARS (class), raw_decl);
5813 else
5814 CLASS_RAW_IVARS (class) = raw_decl;
5816 field_decl = grokfield (input_filename, lineno,
5817 declarator, declspecs, width);
5819 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5820 switch (public)
5822 case 0:
5823 TREE_PUBLIC (field_decl) = 0;
5824 TREE_PRIVATE (field_decl) = 0;
5825 TREE_PROTECTED (field_decl) = 1;
5826 break;
5828 case 1:
5829 TREE_PUBLIC (field_decl) = 1;
5830 TREE_PRIVATE (field_decl) = 0;
5831 TREE_PROTECTED (field_decl) = 0;
5832 break;
5834 case 2:
5835 TREE_PUBLIC (field_decl) = 0;
5836 TREE_PRIVATE (field_decl) = 1;
5837 TREE_PROTECTED (field_decl) = 0;
5838 break;
5842 if (CLASS_IVARS (class))
5843 chainon (CLASS_IVARS (class), field_decl);
5844 else
5845 CLASS_IVARS (class) = field_decl;
5847 return class;
5850 tree
5851 is_ivar (decl_chain, ident)
5852 tree decl_chain;
5853 tree ident;
5855 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5856 if (DECL_NAME (decl_chain) == ident)
5857 return decl_chain;
5858 return NULL_TREE;
5861 /* True if the ivar is private and we are not in its implementation. */
5864 is_private (decl)
5865 tree decl;
5867 if (TREE_PRIVATE (decl)
5868 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5870 error ("instance variable `%s' is declared private",
5871 IDENTIFIER_POINTER (DECL_NAME (decl)));
5872 return 1;
5874 else
5875 return 0;
5878 /* We have an instance variable reference;, check to see if it is public. */
5881 is_public (expr, identifier)
5882 tree expr;
5883 tree identifier;
5885 tree basetype = TREE_TYPE (expr);
5886 enum tree_code code = TREE_CODE (basetype);
5887 tree decl;
5889 if (code == RECORD_TYPE)
5891 if (TREE_STATIC_TEMPLATE (basetype))
5893 if (!lookup_interface (TYPE_NAME (basetype)))
5895 error ("Cannot find interface declaration for `%s'",
5896 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5897 return 0;
5900 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5902 if (TREE_PUBLIC (decl))
5903 return 1;
5905 /* Important difference between the Stepstone translator:
5906 all instance variables should be public within the context
5907 of the implementation. */
5908 if (implementation_context
5909 && (((TREE_CODE (implementation_context)
5910 == CLASS_IMPLEMENTATION_TYPE)
5911 || (TREE_CODE (implementation_context)
5912 == CATEGORY_IMPLEMENTATION_TYPE))
5913 && (CLASS_NAME (implementation_context)
5914 == TYPE_NAME (basetype))))
5915 return ! is_private (decl);
5917 error ("instance variable `%s' is declared %s",
5918 IDENTIFIER_POINTER (identifier),
5919 TREE_PRIVATE (decl) ? "private" : "protected");
5920 return 0;
5924 else if (implementation_context && (basetype == objc_object_reference))
5926 TREE_TYPE (expr) = uprivate_record;
5927 warning ("static access to object of type `id'");
5931 return 1;
5934 /* Implement @defs (<classname>) within struct bodies. */
5936 tree
5937 get_class_ivars (interface)
5938 tree interface;
5940 if (!doing_objc_thang)
5941 objc_fatal ();
5943 return build_ivar_chain (interface, 1);
5946 /* Make sure all entries in CHAIN are also in LIST. */
5948 static int
5949 check_methods (chain, list, mtype)
5950 tree chain;
5951 tree list;
5952 int mtype;
5954 int first = 1;
5956 while (chain)
5958 if (!lookup_method (list, chain))
5960 if (first)
5962 if (TREE_CODE (implementation_context)
5963 == CLASS_IMPLEMENTATION_TYPE)
5964 warning ("incomplete implementation of class `%s'",
5965 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5966 else if (TREE_CODE (implementation_context)
5967 == CATEGORY_IMPLEMENTATION_TYPE)
5968 warning ("incomplete implementation of category `%s'",
5969 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5970 first = 0;
5973 warning ("method definition for `%c%s' not found",
5974 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5977 chain = TREE_CHAIN (chain);
5980 return first;
5983 static int
5984 conforms_to_protocol (class, protocol)
5985 tree class;
5986 tree protocol;
5988 while (protocol)
5990 tree p = CLASS_PROTOCOL_LIST (class);
5992 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5993 p = TREE_CHAIN (p);
5995 if (!p)
5997 tree super = (CLASS_SUPER_NAME (class)
5998 ? lookup_interface (CLASS_SUPER_NAME (class))
5999 : NULL_TREE);
6000 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6001 if (!tmp)
6002 return 0;
6005 protocol = TREE_CHAIN (protocol);
6008 return 1;
6011 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6012 CONTEXT. This is one of two mechanisms to check protocol integrity. */
6014 static int
6015 check_methods_accessible (chain, context, mtype)
6016 tree chain;
6017 tree context;
6018 int mtype;
6020 int first = 1;
6021 tree list;
6022 tree base_context = context;
6024 while (chain)
6026 context = base_context;
6027 while (context)
6029 if (mtype == '+')
6030 list = CLASS_CLS_METHODS (context);
6031 else
6032 list = CLASS_NST_METHODS (context);
6034 if (lookup_method (list, chain))
6035 break;
6037 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6038 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6039 context = (CLASS_SUPER_NAME (context)
6040 ? lookup_interface (CLASS_SUPER_NAME (context))
6041 : NULL_TREE);
6043 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6044 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6045 context = (CLASS_NAME (context)
6046 ? lookup_interface (CLASS_NAME (context))
6047 : NULL_TREE);
6048 else
6049 abort ();
6052 if (context == NULL_TREE)
6054 if (first)
6056 if (TREE_CODE (implementation_context)
6057 == CLASS_IMPLEMENTATION_TYPE)
6058 warning ("incomplete implementation of class `%s'",
6059 IDENTIFIER_POINTER
6060 (CLASS_NAME (implementation_context)));
6061 else if (TREE_CODE (implementation_context)
6062 == CATEGORY_IMPLEMENTATION_TYPE)
6063 warning ("incomplete implementation of category `%s'",
6064 IDENTIFIER_POINTER
6065 (CLASS_SUPER_NAME (implementation_context)));
6066 first = 0;
6068 warning ("method definition for `%c%s' not found",
6069 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6072 chain = TREE_CHAIN (chain); /* next method... */
6074 return first;
6077 static void
6078 check_protocols (proto_list, type, name)
6079 tree proto_list;
6080 const char *type;
6081 const char *name;
6083 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6085 tree p = TREE_VALUE (proto_list);
6087 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6089 int f1, f2;
6091 /* Ensure that all protocols have bodies. */
6092 if (flag_warn_protocol) {
6093 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6094 CLASS_CLS_METHODS (implementation_context),
6095 '+');
6096 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6097 CLASS_NST_METHODS (implementation_context),
6098 '-');
6099 } else {
6100 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6101 implementation_context,
6102 '+');
6103 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6104 implementation_context,
6105 '-');
6108 if (!f1 || !f2)
6109 warning ("%s `%s' does not fully implement the `%s' protocol",
6110 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6113 else
6115 ; /* An identifier if we could not find a protocol. */
6118 /* Check protocols recursively. */
6119 if (PROTOCOL_LIST (p))
6121 tree super_class
6122 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6123 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
6124 check_protocols (PROTOCOL_LIST (p), type, name);
6129 /* Make sure that the class CLASS_NAME is defined
6130 CODE says which kind of thing CLASS_NAME ought to be.
6131 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6132 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
6134 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
6135 whose matching pop is in continue_class. */
6137 tree
6138 start_class (code, class_name, super_name, protocol_list)
6139 enum tree_code code;
6140 tree class_name;
6141 tree super_name;
6142 tree protocol_list;
6144 tree class, decl;
6146 if (code == CLASS_INTERFACE_TYPE)
6148 push_obstacks_nochange ();
6149 end_temporary_allocation ();
6152 if (!doing_objc_thang)
6153 objc_fatal ();
6155 class = make_node (code);
6156 TYPE_BINFO (class) = make_tree_vec (5);
6158 CLASS_NAME (class) = class_name;
6159 CLASS_SUPER_NAME (class) = super_name;
6160 CLASS_CLS_METHODS (class) = NULL_TREE;
6162 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6164 error ("`%s' redeclared as different kind of symbol",
6165 IDENTIFIER_POINTER (class_name));
6166 error_with_decl (decl, "previous declaration of `%s'");
6169 if (code == CLASS_IMPLEMENTATION_TYPE)
6172 static tree implemented_classes = 0;
6173 tree chain = implemented_classes;
6174 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6175 if (TREE_VALUE (chain) == class_name)
6177 error ("reimplementation of class `%s'",
6178 IDENTIFIER_POINTER (class_name));
6179 return error_mark_node;
6181 implemented_classes = perm_tree_cons (NULL_TREE, class_name,
6182 implemented_classes);
6185 /* Pre-build the following entities - for speed/convenience. */
6186 if (!self_id)
6187 self_id = get_identifier ("self");
6188 if (!ucmd_id)
6189 ucmd_id = get_identifier ("_cmd");
6190 if (!unused_list)
6191 unused_list
6192 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6193 if (!objc_super_template)
6194 objc_super_template = build_super_template ();
6196 /* Reset for multiple classes per file. */
6197 method_slot = 0;
6199 implementation_context = class;
6201 /* Lookup the interface for this implementation. */
6203 if (!(implementation_template = lookup_interface (class_name)))
6205 warning ("Cannot find interface declaration for `%s'",
6206 IDENTIFIER_POINTER (class_name));
6207 add_class (implementation_template = implementation_context);
6210 /* If a super class has been specified in the implementation,
6211 insure it conforms to the one specified in the interface. */
6213 if (super_name
6214 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6216 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6217 const char *name =
6218 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6219 error ("conflicting super class name `%s'",
6220 IDENTIFIER_POINTER (super_name));
6221 error ("previous declaration of `%s'", name);
6224 else if (! super_name)
6226 CLASS_SUPER_NAME (implementation_context)
6227 = CLASS_SUPER_NAME (implementation_template);
6231 else if (code == CLASS_INTERFACE_TYPE)
6233 if (lookup_interface (class_name))
6234 warning ("duplicate interface declaration for class `%s'",
6235 IDENTIFIER_POINTER (class_name));
6236 else
6237 add_class (class);
6239 if (protocol_list)
6240 CLASS_PROTOCOL_LIST (class)
6241 = lookup_and_install_protocols (protocol_list);
6244 else if (code == CATEGORY_INTERFACE_TYPE)
6246 tree class_category_is_assoc_with;
6248 /* For a category, class_name is really the name of the class that
6249 the following set of methods will be associated with. We must
6250 find the interface so that can derive the objects template. */
6252 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6254 error ("Cannot find interface declaration for `%s'",
6255 IDENTIFIER_POINTER (class_name));
6256 exit (FATAL_EXIT_CODE);
6258 else
6259 add_category (class_category_is_assoc_with, class);
6261 if (protocol_list)
6262 CLASS_PROTOCOL_LIST (class)
6263 = lookup_and_install_protocols (protocol_list);
6266 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6268 /* Pre-build the following entities for speed/convenience. */
6269 if (!self_id)
6270 self_id = get_identifier ("self");
6271 if (!ucmd_id)
6272 ucmd_id = get_identifier ("_cmd");
6273 if (!unused_list)
6274 unused_list
6275 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6276 if (!objc_super_template)
6277 objc_super_template = build_super_template ();
6279 /* Reset for multiple classes per file. */
6280 method_slot = 0;
6282 implementation_context = class;
6284 /* For a category, class_name is really the name of the class that
6285 the following set of methods will be associated with. We must
6286 find the interface so that can derive the objects template. */
6288 if (!(implementation_template = lookup_interface (class_name)))
6290 error ("Cannot find interface declaration for `%s'",
6291 IDENTIFIER_POINTER (class_name));
6292 exit (FATAL_EXIT_CODE);
6295 return class;
6298 tree
6299 continue_class (class)
6300 tree class;
6302 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6303 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6305 struct imp_entry *imp_entry;
6306 tree ivar_context;
6308 /* Check consistency of the instance variables. */
6310 if (CLASS_IVARS (class))
6311 check_ivars (implementation_template, class);
6313 /* code generation */
6315 ivar_context = build_private_template (implementation_template);
6317 if (!objc_class_template)
6318 build_class_template ();
6320 if (!(imp_entry
6321 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6322 perror ("unable to allocate in objc-tree.c");
6324 imp_entry->next = imp_list;
6325 imp_entry->imp_context = class;
6326 imp_entry->imp_template = implementation_template;
6328 synth_forward_declarations ();
6329 imp_entry->class_decl = UOBJC_CLASS_decl;
6330 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6332 /* Append to front and increment count. */
6333 imp_list = imp_entry;
6334 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6335 imp_count++;
6336 else
6337 cat_count++;
6339 return ivar_context;
6342 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6344 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6346 if (!TYPE_FIELDS (record))
6348 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6349 CLASS_STATIC_TEMPLATE (class) = record;
6351 /* Mark this record as a class template for static typing. */
6352 TREE_STATIC_TEMPLATE (record) = 1;
6355 return NULL_TREE;
6358 else
6359 return error_mark_node;
6362 /* This is called once we see the "@end" in an interface/implementation. */
6364 void
6365 finish_class (class)
6366 tree class;
6368 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6370 /* All code generation is done in finish_objc. */
6372 if (implementation_template != implementation_context)
6374 /* Ensure that all method listed in the interface contain bodies. */
6375 check_methods (CLASS_CLS_METHODS (implementation_template),
6376 CLASS_CLS_METHODS (implementation_context), '+');
6377 check_methods (CLASS_NST_METHODS (implementation_template),
6378 CLASS_NST_METHODS (implementation_context), '-');
6380 if (CLASS_PROTOCOL_LIST (implementation_template))
6381 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6382 "class",
6383 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6387 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6389 tree category = CLASS_CATEGORY_LIST (implementation_template);
6391 /* Find the category interface from the class it is associated with. */
6392 while (category)
6394 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6395 break;
6396 category = CLASS_CATEGORY_LIST (category);
6399 if (category)
6401 /* Ensure all method listed in the interface contain bodies. */
6402 check_methods (CLASS_CLS_METHODS (category),
6403 CLASS_CLS_METHODS (implementation_context), '+');
6404 check_methods (CLASS_NST_METHODS (category),
6405 CLASS_NST_METHODS (implementation_context), '-');
6407 if (CLASS_PROTOCOL_LIST (category))
6408 check_protocols (CLASS_PROTOCOL_LIST (category),
6409 "category",
6410 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6414 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6416 tree decl_specs;
6417 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6418 char *string = (char *) alloca (strlen (class_name) + 3);
6420 /* extern struct objc_object *_<my_name>; */
6422 sprintf (string, "_%s", class_name);
6424 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6425 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6426 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6427 decl_specs);
6431 static tree
6432 add_protocol (protocol)
6433 tree protocol;
6435 /* Put protocol on list in reverse order. */
6436 TREE_CHAIN (protocol) = protocol_chain;
6437 protocol_chain = protocol;
6438 return protocol_chain;
6441 static tree
6442 lookup_protocol (ident)
6443 tree ident;
6445 tree chain;
6447 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6449 if (ident == PROTOCOL_NAME (chain))
6450 return chain;
6453 return NULL_TREE;
6456 tree
6457 start_protocol (code, name, list)
6458 enum tree_code code;
6459 tree name;
6460 tree list;
6462 tree protocol;
6464 if (!doing_objc_thang)
6465 objc_fatal ();
6467 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6468 if (!objc_protocol_template)
6469 objc_protocol_template = build_protocol_template ();
6471 protocol = make_node (code);
6472 TYPE_BINFO (protocol) = make_tree_vec (2);
6474 PROTOCOL_NAME (protocol) = name;
6475 PROTOCOL_LIST (protocol) = list;
6477 lookup_and_install_protocols (list);
6479 if (lookup_protocol (name))
6480 warning ("duplicate declaration for protocol `%s'",
6481 IDENTIFIER_POINTER (name));
6482 else
6483 add_protocol (protocol);
6485 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6487 return protocol;
6490 void
6491 finish_protocol (protocol)
6492 tree protocol ATTRIBUTE_UNUSED;
6497 /* "Encode" a data type into a string, which grows in util_obstack.
6498 ??? What is the FORMAT? Someone please document this! */
6500 static void
6501 encode_type_qualifiers (declspecs)
6502 tree declspecs;
6504 tree spec;
6506 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6508 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6509 obstack_1grow (&util_obstack, 'r');
6510 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6511 obstack_1grow (&util_obstack, 'n');
6512 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6513 obstack_1grow (&util_obstack, 'N');
6514 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6515 obstack_1grow (&util_obstack, 'o');
6516 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6517 obstack_1grow (&util_obstack, 'O');
6518 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6519 obstack_1grow (&util_obstack, 'R');
6520 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6521 obstack_1grow (&util_obstack, 'V');
6525 /* Encode a pointer type. */
6527 static void
6528 encode_pointer (type, curtype, format)
6529 tree type;
6530 int curtype;
6531 int format;
6533 tree pointer_to = TREE_TYPE (type);
6535 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6537 if (TYPE_NAME (pointer_to)
6538 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6540 const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6542 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6544 obstack_1grow (&util_obstack, '@');
6545 return;
6547 else if (TREE_STATIC_TEMPLATE (pointer_to))
6549 if (generating_instance_variables)
6551 obstack_1grow (&util_obstack, '@');
6552 obstack_1grow (&util_obstack, '"');
6553 obstack_grow (&util_obstack, name, strlen (name));
6554 obstack_1grow (&util_obstack, '"');
6555 return;
6557 else
6559 obstack_1grow (&util_obstack, '@');
6560 return;
6563 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6565 obstack_1grow (&util_obstack, '#');
6566 return;
6568 #ifndef OBJC_INT_SELECTORS
6569 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6571 obstack_1grow (&util_obstack, ':');
6572 return;
6574 #endif /* OBJC_INT_SELECTORS */
6577 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6578 && TYPE_MODE (pointer_to) == QImode)
6580 obstack_1grow (&util_obstack, '*');
6581 return;
6584 /* We have a type that does not get special treatment. */
6586 /* NeXT extension */
6587 obstack_1grow (&util_obstack, '^');
6588 encode_type (pointer_to, curtype, format);
6591 static void
6592 encode_array (type, curtype, format)
6593 tree type;
6594 int curtype;
6595 int format;
6597 tree an_int_cst = TYPE_SIZE (type);
6598 tree array_of = TREE_TYPE (type);
6599 char buffer[40];
6601 /* An incomplete array is treated like a pointer. */
6602 if (an_int_cst == NULL)
6604 encode_pointer (type, curtype, format);
6605 return;
6608 sprintf (buffer, "[%ld",
6609 (long) (TREE_INT_CST_LOW (an_int_cst)
6610 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6612 obstack_grow (&util_obstack, buffer, strlen (buffer));
6613 encode_type (array_of, curtype, format);
6614 obstack_1grow (&util_obstack, ']');
6615 return;
6618 static void
6619 encode_aggregate_within (type, curtype, format, left, right)
6620 tree type;
6621 int curtype;
6622 int format;
6623 int left;
6624 int right;
6626 if (obstack_object_size (&util_obstack) > 0
6627 && *(obstack_next_free (&util_obstack) - 1) == '^')
6629 tree name = TYPE_NAME (type);
6631 /* we have a reference; this is a NeXT extension. */
6633 if (obstack_object_size (&util_obstack) - curtype == 1
6634 && format == OBJC_ENCODE_INLINE_DEFS)
6636 /* Output format of struct for first level only. */
6637 tree fields = TYPE_FIELDS (type);
6639 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6641 obstack_1grow (&util_obstack, left);
6642 obstack_grow (&util_obstack,
6643 IDENTIFIER_POINTER (name),
6644 strlen (IDENTIFIER_POINTER (name)));
6645 obstack_1grow (&util_obstack, '=');
6647 else
6649 obstack_1grow (&util_obstack, left);
6650 obstack_grow (&util_obstack, "?=", 2);
6653 for ( ; fields; fields = TREE_CHAIN (fields))
6654 encode_field_decl (fields, curtype, format);
6656 obstack_1grow (&util_obstack, right);
6659 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6661 obstack_1grow (&util_obstack, left);
6662 obstack_grow (&util_obstack,
6663 IDENTIFIER_POINTER (name),
6664 strlen (IDENTIFIER_POINTER (name)));
6665 obstack_1grow (&util_obstack, right);
6668 else
6670 /* We have an untagged structure or a typedef. */
6671 obstack_1grow (&util_obstack, left);
6672 obstack_1grow (&util_obstack, '?');
6673 obstack_1grow (&util_obstack, right);
6677 else
6679 tree name = TYPE_NAME (type);
6680 tree fields = TYPE_FIELDS (type);
6682 if (format == OBJC_ENCODE_INLINE_DEFS
6683 || generating_instance_variables)
6685 obstack_1grow (&util_obstack, left);
6686 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6687 obstack_grow (&util_obstack,
6688 IDENTIFIER_POINTER (name),
6689 strlen (IDENTIFIER_POINTER (name)));
6690 else
6691 obstack_1grow (&util_obstack, '?');
6693 obstack_1grow (&util_obstack, '=');
6695 for (; fields; fields = TREE_CHAIN (fields))
6697 if (generating_instance_variables)
6699 tree fname = DECL_NAME (fields);
6701 obstack_1grow (&util_obstack, '"');
6702 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6704 obstack_grow (&util_obstack,
6705 IDENTIFIER_POINTER (fname),
6706 strlen (IDENTIFIER_POINTER (fname)));
6709 obstack_1grow (&util_obstack, '"');
6712 encode_field_decl (fields, curtype, format);
6715 obstack_1grow (&util_obstack, right);
6718 else
6720 obstack_1grow (&util_obstack, left);
6721 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6722 obstack_grow (&util_obstack,
6723 IDENTIFIER_POINTER (name),
6724 strlen (IDENTIFIER_POINTER (name)));
6725 else
6726 /* We have an untagged structure or a typedef. */
6727 obstack_1grow (&util_obstack, '?');
6729 obstack_1grow (&util_obstack, right);
6734 static void
6735 encode_aggregate (type, curtype, format)
6736 tree type;
6737 int curtype;
6738 int format;
6740 enum tree_code code = TREE_CODE (type);
6742 switch (code)
6744 case RECORD_TYPE:
6746 encode_aggregate_within(type, curtype, format, '{', '}');
6747 break;
6749 case UNION_TYPE:
6751 encode_aggregate_within(type, curtype, format, '(', ')');
6752 break;
6755 case ENUMERAL_TYPE:
6756 obstack_1grow (&util_obstack, 'i');
6757 break;
6759 default:
6760 break;
6764 /* Support bitfields. The current version of Objective-C does not support
6765 them. The string will consist of one or more "b:n"'s where n is an
6766 integer describing the width of the bitfield. Currently, classes in
6767 the kit implement a method "-(char *)describeBitfieldStruct:" that
6768 simulates this. If they do not implement this method, the archiver
6769 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6770 according to the GNU compiler. After looking at the "kit", it appears
6771 that all classes currently rely on this default behavior, rather than
6772 hand generating this string (which is tedious). */
6774 static void
6775 encode_bitfield (width)
6776 int width;
6778 char buffer[40];
6779 sprintf (buffer, "b%d", width);
6780 obstack_grow (&util_obstack, buffer, strlen (buffer));
6783 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6785 static void
6786 encode_type (type, curtype, format)
6787 tree type;
6788 int curtype;
6789 int format;
6791 enum tree_code code = TREE_CODE (type);
6793 if (code == INTEGER_TYPE)
6795 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6796 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6798 /* Unsigned integer types. */
6800 if (TYPE_MODE (type) == QImode)
6801 obstack_1grow (&util_obstack, 'C');
6802 else if (TYPE_MODE (type) == HImode)
6803 obstack_1grow (&util_obstack, 'S');
6804 else if (TYPE_MODE (type) == SImode)
6806 if (type == long_unsigned_type_node)
6807 obstack_1grow (&util_obstack, 'L');
6808 else
6809 obstack_1grow (&util_obstack, 'I');
6811 else if (TYPE_MODE (type) == DImode)
6812 obstack_1grow (&util_obstack, 'Q');
6815 else
6816 /* Signed integer types. */
6818 if (TYPE_MODE (type) == QImode)
6819 obstack_1grow (&util_obstack, 'c');
6820 else if (TYPE_MODE (type) == HImode)
6821 obstack_1grow (&util_obstack, 's');
6822 else if (TYPE_MODE (type) == SImode)
6824 if (type == long_integer_type_node)
6825 obstack_1grow (&util_obstack, 'l');
6826 else
6827 obstack_1grow (&util_obstack, 'i');
6830 else if (TYPE_MODE (type) == DImode)
6831 obstack_1grow (&util_obstack, 'q');
6835 else if (code == REAL_TYPE)
6837 /* Floating point types. */
6839 if (TYPE_MODE (type) == SFmode)
6840 obstack_1grow (&util_obstack, 'f');
6841 else if (TYPE_MODE (type) == DFmode
6842 || TYPE_MODE (type) == TFmode)
6843 obstack_1grow (&util_obstack, 'd');
6846 else if (code == VOID_TYPE)
6847 obstack_1grow (&util_obstack, 'v');
6849 else if (code == ARRAY_TYPE)
6850 encode_array (type, curtype, format);
6852 else if (code == POINTER_TYPE)
6853 encode_pointer (type, curtype, format);
6855 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6856 encode_aggregate (type, curtype, format);
6858 else if (code == FUNCTION_TYPE) /* '?' */
6859 obstack_1grow (&util_obstack, '?');
6862 static void
6863 encode_complete_bitfield (int position, tree type, int size)
6865 enum tree_code code = TREE_CODE (type);
6866 char buffer[40];
6867 char charType = '?';
6869 if (code == INTEGER_TYPE)
6871 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6872 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6874 /* Unsigned integer types. */
6876 if (TYPE_MODE (type) == QImode)
6877 charType = 'C';
6878 else if (TYPE_MODE (type) == HImode)
6879 charType = 'S';
6880 else if (TYPE_MODE (type) == SImode)
6882 if (type == long_unsigned_type_node)
6883 charType = 'L';
6884 else
6885 charType = 'I';
6887 else if (TYPE_MODE (type) == DImode)
6888 charType = 'Q';
6891 else
6892 /* Signed integer types. */
6894 if (TYPE_MODE (type) == QImode)
6895 charType = 'c';
6896 else if (TYPE_MODE (type) == HImode)
6897 charType = 's';
6898 else if (TYPE_MODE (type) == SImode)
6900 if (type == long_integer_type_node)
6901 charType = 'l';
6902 else
6903 charType = 'i';
6906 else if (TYPE_MODE (type) == DImode)
6907 charType = 'q';
6911 else
6912 abort ();
6914 sprintf (buffer, "b%d%c%d", position, charType, size);
6915 obstack_grow (&util_obstack, buffer, strlen (buffer));
6918 static void
6919 encode_field_decl (field_decl, curtype, format)
6920 tree field_decl;
6921 int curtype;
6922 int format;
6924 tree type;
6926 type = TREE_TYPE (field_decl);
6928 /* If this field is obviously a bitfield, or is a bitfield that has been
6929 clobbered to look like a ordinary integer mode, go ahead and generate
6930 the bitfield typing information. */
6931 if (flag_next_runtime)
6933 if (DECL_BIT_FIELD (field_decl))
6934 encode_bitfield (DECL_FIELD_SIZE (field_decl));
6935 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6936 && DECL_FIELD_SIZE (field_decl)
6937 && TYPE_MODE (type) > DECL_MODE (field_decl))
6938 encode_bitfield (DECL_FIELD_SIZE (field_decl));
6939 else
6940 encode_type (TREE_TYPE (field_decl), curtype, format);
6942 else
6944 if (DECL_BIT_FIELD (field_decl)
6945 || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6946 && DECL_FIELD_SIZE (field_decl)
6947 && TYPE_MODE (type) > DECL_MODE (field_decl)))
6949 encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)),
6950 DECL_BIT_FIELD_TYPE (field_decl),
6951 DECL_FIELD_SIZE (field_decl));
6953 else
6954 encode_type (TREE_TYPE (field_decl), curtype, format);
6958 static tree
6959 expr_last (complex_expr)
6960 tree complex_expr;
6962 tree next;
6964 if (complex_expr)
6965 while ((next = TREE_OPERAND (complex_expr, 0)))
6966 complex_expr = next;
6968 return complex_expr;
6971 /* The selector of the current method,
6972 or NULL if we aren't compiling a method. */
6974 tree
6975 maybe_objc_method_name (decl)
6976 tree decl ATTRIBUTE_UNUSED;
6978 if (method_context)
6979 return METHOD_SEL_NAME (method_context);
6980 else
6981 return 0;
6984 /* Transform a method definition into a function definition as follows:
6985 - synthesize the first two arguments, "self" and "_cmd". */
6987 void
6988 start_method_def (method)
6989 tree method;
6991 tree decl_specs;
6993 /* Required to implement _msgSuper. */
6994 method_context = method;
6995 UOBJC_SUPER_decl = NULL_TREE;
6997 /* Must be called BEFORE start_function. */
6998 pushlevel (0);
7000 /* Generate prototype declarations for arguments..."new-style". */
7002 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
7003 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7004 else
7005 /* Really a `struct objc_class *'. However, we allow people to
7006 assign to self, which changes its type midstream. */
7007 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7009 push_parm_decl (build_tree_list
7010 (build_tree_list (decl_specs,
7011 build1 (INDIRECT_REF, NULL_TREE, self_id)),
7012 build_tree_list (unused_list, NULL_TREE)));
7014 #ifdef OBJC_INT_SELECTORS
7015 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
7016 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
7017 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
7018 build_tree_list (unused_list, NULL_TREE)));
7019 #else /* not OBJC_INT_SELECTORS */
7020 decl_specs = build_tree_list (NULL_TREE,
7021 xref_tag (RECORD_TYPE,
7022 get_identifier (TAG_SELECTOR)));
7023 push_parm_decl (build_tree_list
7024 (build_tree_list (decl_specs,
7025 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7026 build_tree_list (unused_list, NULL_TREE)));
7027 #endif /* not OBJC_INT_SELECTORS */
7029 /* Generate argument declarations if a keyword_decl. */
7030 if (METHOD_SEL_ARGS (method))
7032 tree arglist = METHOD_SEL_ARGS (method);
7035 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7036 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7038 if (arg_decl)
7040 tree last_expr = expr_last (arg_decl);
7042 /* Unite the abstract decl with its name. */
7043 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7044 push_parm_decl (build_tree_list
7045 (build_tree_list (arg_spec, arg_decl),
7046 build_tree_list (NULL_TREE, NULL_TREE)));
7048 /* Unhook: restore the abstract declarator. */
7049 TREE_OPERAND (last_expr, 0) = NULL_TREE;
7052 else
7053 push_parm_decl (build_tree_list
7054 (build_tree_list (arg_spec,
7055 KEYWORD_ARG_NAME (arglist)),
7056 build_tree_list (NULL_TREE, NULL_TREE)));
7058 arglist = TREE_CHAIN (arglist);
7060 while (arglist);
7063 if (METHOD_ADD_ARGS (method) > (tree)1)
7065 /* We have a variable length selector - in "prototype" format. */
7066 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7067 while (akey)
7069 /* This must be done prior to calling pushdecl. pushdecl is
7070 going to change our chain on us. */
7071 tree nextkey = TREE_CHAIN (akey);
7072 pushdecl (akey);
7073 akey = nextkey;
7078 static void
7079 warn_with_method (message, mtype, method)
7080 const char *message;
7081 int mtype;
7082 tree method;
7084 if (count_error (1) == 0)
7085 return;
7087 report_error_function (DECL_SOURCE_FILE (method));
7089 fprintf (stderr, "%s:%d: warning: ",
7090 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
7091 bzero (errbuf, BUFSIZE);
7092 fprintf (stderr, "%s `%c%s'\n",
7093 message, mtype, gen_method_decl (method, errbuf));
7096 /* Return 1 if METHOD is consistent with PROTO. */
7098 static int
7099 comp_method_with_proto (method, proto)
7100 tree method, proto;
7102 static tree function_type = 0;
7104 /* Create a function_type node once. */
7105 if (!function_type)
7107 push_obstacks_nochange ();
7108 end_temporary_allocation ();
7109 function_type = make_node (FUNCTION_TYPE);
7110 pop_obstacks ();
7113 /* Install argument types - normally set by build_function_type. */
7114 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
7116 /* install return type */
7117 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
7119 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
7122 /* Return 1 if PROTO1 is consistent with PROTO2. */
7124 static int
7125 comp_proto_with_proto (proto1, proto2)
7126 tree proto1, proto2;
7128 static tree function_type1 = 0, function_type2 = 0;
7130 /* Create a couple function_type node's once. */
7131 if (!function_type1)
7133 push_obstacks_nochange ();
7134 end_temporary_allocation ();
7135 function_type1 = make_node (FUNCTION_TYPE);
7136 function_type2 = make_node (FUNCTION_TYPE);
7137 pop_obstacks ();
7140 /* Install argument types; normally set by build_function_type. */
7141 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
7142 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
7144 /* Install return type. */
7145 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
7146 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
7148 return comptypes (function_type1, function_type2);
7151 /* - Generate an identifier for the function. the format is "_n_cls",
7152 where 1 <= n <= nMethods, and cls is the name the implementation we
7153 are processing.
7154 - Install the return type from the method declaration.
7155 - If we have a prototype, check for type consistency. */
7157 static void
7158 really_start_method (method, parmlist)
7159 tree method, parmlist;
7161 tree sc_spec, ret_spec, ret_decl, decl_specs;
7162 tree method_decl, method_id;
7163 const char *sel_name, *class_name, *cat_name;
7164 char *buf;
7166 /* Synth the storage class & assemble the return type. */
7167 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7168 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7169 decl_specs = chainon (sc_spec, ret_spec);
7171 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7172 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
7173 cat_name = ((TREE_CODE (implementation_context)
7174 == CLASS_IMPLEMENTATION_TYPE)
7175 ? NULL
7176 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
7177 method_slot++;
7179 /* Make sure this is big enough for any plausible method label. */
7180 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7181 + (cat_name ? strlen (cat_name) : 0));
7183 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7184 class_name, cat_name, sel_name, method_slot);
7186 method_id = get_identifier (buf);
7188 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7190 /* Check the declarator portion of the return type for the method. */
7191 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7193 /* Unite the complex decl (specified in the abstract decl) with the
7194 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7195 tree save_expr = expr_last (ret_decl);
7197 TREE_OPERAND (save_expr, 0) = method_decl;
7198 method_decl = ret_decl;
7200 /* Fool the parser into thinking it is starting a function. */
7201 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7203 /* Unhook: this has the effect of restoring the abstract declarator. */
7204 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7207 else
7209 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7211 /* Fool the parser into thinking it is starting a function. */
7212 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7214 /* Unhook: this has the effect of restoring the abstract declarator. */
7215 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7218 METHOD_DEFINITION (method) = current_function_decl;
7220 if (implementation_template != implementation_context)
7222 tree proto;
7224 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7225 proto = lookup_instance_method_static (implementation_template,
7226 METHOD_SEL_NAME (method));
7227 else
7228 proto = lookup_class_method_static (implementation_template,
7229 METHOD_SEL_NAME (method));
7231 if (proto && ! comp_method_with_proto (method, proto))
7233 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7235 warn_with_method ("conflicting types for", type, method);
7236 warn_with_method ("previous declaration of", type, proto);
7241 /* The following routine is always called...this "architecture" is to
7242 accommodate "old-style" variable length selectors.
7244 - a:a b:b // prototype ; id c; id d; // old-style. */
7246 void
7247 continue_method_def ()
7249 tree parmlist;
7251 if (METHOD_ADD_ARGS (method_context) == (tree)1)
7252 /* We have a `, ...' immediately following the selector. */
7253 parmlist = get_parm_info (0);
7254 else
7255 parmlist = get_parm_info (1); /* place a `void_at_end' */
7257 /* Set self_decl from the first argument...this global is used by
7258 build_ivar_reference calling build_indirect_ref. */
7259 self_decl = TREE_PURPOSE (parmlist);
7261 poplevel (0, 0, 0);
7262 really_start_method (method_context, parmlist);
7263 store_parm_decls ();
7266 /* Called by the parser, from the `pushlevel' production. */
7268 void
7269 add_objc_decls ()
7271 if (!UOBJC_SUPER_decl)
7273 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7274 build_tree_list (NULL_TREE,
7275 objc_super_template),
7276 0, NULL_TREE, NULL_TREE);
7278 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7280 /* This prevents `unused variable' warnings when compiling with -Wall. */
7281 TREE_USED (UOBJC_SUPER_decl) = 1;
7282 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7286 /* _n_Method (id self, SEL sel, ...)
7288 struct objc_super _S;
7289 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7290 } */
7292 tree
7293 get_super_receiver ()
7295 if (method_context)
7297 tree super_expr, super_expr_list;
7299 /* Set receiver to self. */
7300 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7301 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7302 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7304 /* Set class to begin searching. */
7305 super_expr = build_component_ref (UOBJC_SUPER_decl,
7306 get_identifier ("class"));
7308 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7310 /* [_cls, __cls]Super are "pre-built" in
7311 synth_forward_declarations. */
7313 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7314 ((TREE_CODE (method_context)
7315 == INSTANCE_METHOD_DECL)
7316 ? ucls_super_ref
7317 : uucls_super_ref));
7320 else
7321 /* We have a category. */
7323 tree super_name = CLASS_SUPER_NAME (implementation_template);
7324 tree super_class;
7326 if (!super_name)
7328 error ("no super class declared in interface for `%s'",
7329 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7330 return error_mark_node;
7333 if (flag_next_runtime)
7335 super_class = get_class_reference (super_name);
7336 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7337 super_class
7338 = build_component_ref (build_indirect_ref (super_class, "->"),
7339 get_identifier ("isa"));
7341 else
7343 add_class_reference (super_name);
7344 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7345 ? objc_get_class_decl : objc_get_meta_class_decl);
7346 assemble_external (super_class);
7347 super_class
7348 = build_function_call
7349 (super_class,
7350 build_tree_list
7351 (NULL_TREE,
7352 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7353 IDENTIFIER_POINTER (super_name))));
7356 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7357 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7360 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7362 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7363 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7365 return build_compound_expr (super_expr_list);
7367 else
7369 error ("[super ...] must appear in a method context");
7370 return error_mark_node;
7374 static tree
7375 encode_method_def (func_decl)
7376 tree func_decl;
7378 tree parms;
7379 int stack_size;
7380 int max_parm_end = 0;
7381 char buffer[40];
7382 tree result;
7384 /* Return type. */
7385 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7386 obstack_object_size (&util_obstack),
7387 OBJC_ENCODE_INLINE_DEFS);
7389 /* Stack size. */
7390 for (parms = DECL_ARGUMENTS (func_decl); parms;
7391 parms = TREE_CHAIN (parms))
7393 int parm_end = (forwarding_offset (parms)
7394 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
7395 / BITS_PER_UNIT));
7397 if (!offset_is_register && parm_end > max_parm_end)
7398 max_parm_end = parm_end;
7401 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7403 sprintf (buffer, "%d", stack_size);
7404 obstack_grow (&util_obstack, buffer, strlen (buffer));
7406 /* Argument types. */
7407 for (parms = DECL_ARGUMENTS (func_decl); parms;
7408 parms = TREE_CHAIN (parms))
7410 /* Type. */
7411 encode_type (TREE_TYPE (parms),
7412 obstack_object_size (&util_obstack),
7413 OBJC_ENCODE_INLINE_DEFS);
7415 /* Compute offset. */
7416 sprintf (buffer, "%d", forwarding_offset (parms));
7418 /* Indicate register. */
7419 if (offset_is_register)
7420 obstack_1grow (&util_obstack, '+');
7422 obstack_grow (&util_obstack, buffer, strlen (buffer));
7425 obstack_1grow (&util_obstack, 0);
7426 result = get_identifier (obstack_finish (&util_obstack));
7427 obstack_free (&util_obstack, util_firstobj);
7428 return result;
7431 void
7432 finish_method_def ()
7434 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7436 finish_function (0);
7438 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7439 since the optimizer may find "may be used before set" errors. */
7440 method_context = NULL_TREE;
7443 #if 0
7445 lang_report_error_function (decl)
7446 tree decl;
7448 if (method_context)
7450 fprintf (stderr, "In method `%s'\n",
7451 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7452 return 1;
7455 else
7456 return 0;
7458 #endif
7460 static int
7461 is_complex_decl (type)
7462 tree type;
7464 return (TREE_CODE (type) == ARRAY_TYPE
7465 || TREE_CODE (type) == FUNCTION_TYPE
7466 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7470 /* Code to convert a decl node into text for a declaration in C. */
7472 static char tmpbuf[256];
7474 static void
7475 adorn_decl (decl, str)
7476 tree decl;
7477 char *str;
7479 enum tree_code code = TREE_CODE (decl);
7481 if (code == ARRAY_REF)
7483 tree an_int_cst = TREE_OPERAND (decl, 1);
7485 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7486 sprintf (str + strlen (str), "[%ld]",
7487 (long) TREE_INT_CST_LOW (an_int_cst));
7488 else
7489 strcat (str, "[]");
7492 else if (code == ARRAY_TYPE)
7494 tree an_int_cst = TYPE_SIZE (decl);
7495 tree array_of = TREE_TYPE (decl);
7497 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7498 sprintf (str + strlen (str), "[%ld]",
7499 (long) (TREE_INT_CST_LOW (an_int_cst)
7500 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7501 else
7502 strcat (str, "[]");
7505 else if (code == CALL_EXPR)
7507 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7509 strcat (str, "(");
7510 while (chain)
7512 gen_declaration (chain, str);
7513 chain = TREE_CHAIN (chain);
7514 if (chain)
7515 strcat (str, ", ");
7517 strcat (str, ")");
7520 else if (code == FUNCTION_TYPE)
7522 tree chain = TYPE_ARG_TYPES (decl);
7524 strcat (str, "(");
7525 while (chain && TREE_VALUE (chain) != void_type_node)
7527 gen_declaration (TREE_VALUE (chain), str);
7528 chain = TREE_CHAIN (chain);
7529 if (chain && TREE_VALUE (chain) != void_type_node)
7530 strcat (str, ", ");
7532 strcat (str, ")");
7535 else if (code == INDIRECT_REF)
7537 strcpy (tmpbuf, "*");
7538 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7540 tree chain;
7542 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7543 chain;
7544 chain = TREE_CHAIN (chain))
7546 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7548 strcat (tmpbuf, " ");
7549 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7552 if (str[0])
7553 strcat (tmpbuf, " ");
7555 strcat (tmpbuf, str);
7556 strcpy (str, tmpbuf);
7559 else if (code == POINTER_TYPE)
7561 strcpy (tmpbuf, "*");
7562 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7564 if (TREE_READONLY (decl))
7565 strcat (tmpbuf, " const");
7566 if (TYPE_VOLATILE (decl))
7567 strcat (tmpbuf, " volatile");
7568 if (str[0])
7569 strcat (tmpbuf, " ");
7571 strcat (tmpbuf, str);
7572 strcpy (str, tmpbuf);
7576 static char *
7577 gen_declarator (decl, buf, name)
7578 tree decl;
7579 char *buf;
7580 const char *name;
7582 if (decl)
7584 enum tree_code code = TREE_CODE (decl);
7585 char *str;
7586 tree op;
7587 int wrap = 0;
7589 switch (code)
7591 case ARRAY_REF:
7592 case INDIRECT_REF:
7593 case CALL_EXPR:
7594 op = TREE_OPERAND (decl, 0);
7596 /* We have a pointer to a function or array...(*)(), (*)[] */
7597 if ((code == ARRAY_REF || code == CALL_EXPR)
7598 && op && TREE_CODE (op) == INDIRECT_REF)
7599 wrap = 1;
7601 str = gen_declarator (op, buf, name);
7603 if (wrap)
7605 strcpy (tmpbuf, "(");
7606 strcat (tmpbuf, str);
7607 strcat (tmpbuf, ")");
7608 strcpy (str, tmpbuf);
7611 adorn_decl (decl, str);
7612 break;
7614 case ARRAY_TYPE:
7615 case FUNCTION_TYPE:
7616 case POINTER_TYPE:
7617 strcpy (buf, name);
7618 str = buf;
7620 /* This clause is done iteratively rather than recursively. */
7623 op = (is_complex_decl (TREE_TYPE (decl))
7624 ? TREE_TYPE (decl) : NULL_TREE);
7626 adorn_decl (decl, str);
7628 /* We have a pointer to a function or array...(*)(), (*)[] */
7629 if (code == POINTER_TYPE
7630 && op && (TREE_CODE (op) == FUNCTION_TYPE
7631 || TREE_CODE (op) == ARRAY_TYPE))
7633 strcpy (tmpbuf, "(");
7634 strcat (tmpbuf, str);
7635 strcat (tmpbuf, ")");
7636 strcpy (str, tmpbuf);
7639 decl = (is_complex_decl (TREE_TYPE (decl))
7640 ? TREE_TYPE (decl) : NULL_TREE);
7643 while (decl && (code = TREE_CODE (decl)))
7646 break;
7648 case IDENTIFIER_NODE:
7649 /* Will only happen if we are processing a "raw" expr-decl. */
7650 strcpy (buf, IDENTIFIER_POINTER (decl));
7651 return buf;
7653 default:
7654 abort ();
7657 return str;
7660 else
7661 /* We have an abstract declarator or a _DECL node. */
7663 strcpy (buf, name);
7664 return buf;
7668 static void
7669 gen_declspecs (declspecs, buf, raw)
7670 tree declspecs;
7671 char *buf;
7672 int raw;
7674 if (raw)
7676 tree chain;
7678 for (chain = nreverse (copy_list (declspecs));
7679 chain; chain = TREE_CHAIN (chain))
7681 tree aspec = TREE_VALUE (chain);
7683 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7684 strcat (buf, IDENTIFIER_POINTER (aspec));
7685 else if (TREE_CODE (aspec) == RECORD_TYPE)
7687 if (TYPE_NAME (aspec))
7689 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7691 if (! TREE_STATIC_TEMPLATE (aspec))
7692 strcat (buf, "struct ");
7693 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7695 /* NEW!!! */
7696 if (protocol_list)
7698 tree chain = protocol_list;
7700 strcat (buf, " <");
7701 while (chain)
7703 strcat (buf,
7704 IDENTIFIER_POINTER
7705 (PROTOCOL_NAME (TREE_VALUE (chain))));
7706 chain = TREE_CHAIN (chain);
7707 if (chain)
7708 strcat (buf, ", ");
7710 strcat (buf, ">");
7714 else
7715 strcat (buf, "untagged struct");
7718 else if (TREE_CODE (aspec) == UNION_TYPE)
7720 if (TYPE_NAME (aspec))
7722 if (! TREE_STATIC_TEMPLATE (aspec))
7723 strcat (buf, "union ");
7724 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7726 else
7727 strcat (buf, "untagged union");
7730 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7732 if (TYPE_NAME (aspec))
7734 if (! TREE_STATIC_TEMPLATE (aspec))
7735 strcat (buf, "enum ");
7736 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7738 else
7739 strcat (buf, "untagged enum");
7742 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7743 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7745 else if (IS_ID (aspec))
7747 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7749 strcat (buf, "id");
7750 if (protocol_list)
7752 tree chain = protocol_list;
7754 strcat (buf, " <");
7755 while (chain)
7757 strcat (buf,
7758 IDENTIFIER_POINTER
7759 (PROTOCOL_NAME (TREE_VALUE (chain))));
7760 chain = TREE_CHAIN (chain);
7761 if (chain)
7762 strcat (buf, ", ");
7764 strcat (buf, ">");
7767 if (TREE_CHAIN (chain))
7768 strcat (buf, " ");
7771 else
7773 /* Type qualifiers. */
7774 if (TREE_READONLY (declspecs))
7775 strcat (buf, "const ");
7776 if (TYPE_VOLATILE (declspecs))
7777 strcat (buf, "volatile ");
7779 switch (TREE_CODE (declspecs))
7781 /* Type specifiers. */
7783 case INTEGER_TYPE:
7784 declspecs = TYPE_MAIN_VARIANT (declspecs);
7786 /* Signed integer types. */
7788 if (declspecs == short_integer_type_node)
7789 strcat (buf, "short int ");
7790 else if (declspecs == integer_type_node)
7791 strcat (buf, "int ");
7792 else if (declspecs == long_integer_type_node)
7793 strcat (buf, "long int ");
7794 else if (declspecs == long_long_integer_type_node)
7795 strcat (buf, "long long int ");
7796 else if (declspecs == signed_char_type_node
7797 || declspecs == char_type_node)
7798 strcat (buf, "char ");
7800 /* Unsigned integer types. */
7802 else if (declspecs == short_unsigned_type_node)
7803 strcat (buf, "unsigned short ");
7804 else if (declspecs == unsigned_type_node)
7805 strcat (buf, "unsigned int ");
7806 else if (declspecs == long_unsigned_type_node)
7807 strcat (buf, "unsigned long ");
7808 else if (declspecs == long_long_unsigned_type_node)
7809 strcat (buf, "unsigned long long ");
7810 else if (declspecs == unsigned_char_type_node)
7811 strcat (buf, "unsigned char ");
7812 break;
7814 case REAL_TYPE:
7815 declspecs = TYPE_MAIN_VARIANT (declspecs);
7817 if (declspecs == float_type_node)
7818 strcat (buf, "float ");
7819 else if (declspecs == double_type_node)
7820 strcat (buf, "double ");
7821 else if (declspecs == long_double_type_node)
7822 strcat (buf, "long double ");
7823 break;
7825 case RECORD_TYPE:
7826 if (TYPE_NAME (declspecs)
7827 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7829 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7831 if (! TREE_STATIC_TEMPLATE (declspecs))
7832 strcat (buf, "struct ");
7833 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7835 if (protocol_list)
7837 tree chain = protocol_list;
7839 strcat (buf, " <");
7840 while (chain)
7842 strcat (buf,
7843 IDENTIFIER_POINTER
7844 (PROTOCOL_NAME (TREE_VALUE (chain))));
7845 chain = TREE_CHAIN (chain);
7846 if (chain)
7847 strcat (buf, ", ");
7849 strcat (buf, ">");
7853 else
7854 strcat (buf, "untagged struct");
7856 strcat (buf, " ");
7857 break;
7859 case UNION_TYPE:
7860 if (TYPE_NAME (declspecs)
7861 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7863 strcat (buf, "union ");
7864 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7865 strcat (buf, " ");
7868 else
7869 strcat (buf, "untagged union ");
7870 break;
7872 case ENUMERAL_TYPE:
7873 if (TYPE_NAME (declspecs)
7874 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7876 strcat (buf, "enum ");
7877 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7878 strcat (buf, " ");
7881 else
7882 strcat (buf, "untagged enum ");
7883 break;
7885 case VOID_TYPE:
7886 strcat (buf, "void ");
7887 break;
7889 case POINTER_TYPE:
7891 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7893 strcat (buf, "id");
7894 if (protocol_list)
7896 tree chain = protocol_list;
7898 strcat (buf, " <");
7899 while (chain)
7901 strcat (buf,
7902 IDENTIFIER_POINTER
7903 (PROTOCOL_NAME (TREE_VALUE (chain))));
7904 chain = TREE_CHAIN (chain);
7905 if (chain)
7906 strcat (buf, ", ");
7909 strcat (buf, ">");
7912 break;
7914 default:
7915 break;
7920 static char *
7921 gen_declaration (atype_or_adecl, buf)
7922 tree atype_or_adecl;
7923 char *buf;
7925 char declbuf[256];
7927 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7929 tree declspecs; /* "identifier_node", "record_type" */
7930 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7932 /* We have a "raw", abstract declarator (typename). */
7933 declarator = TREE_VALUE (atype_or_adecl);
7934 declspecs = TREE_PURPOSE (atype_or_adecl);
7936 gen_declspecs (declspecs, buf, 1);
7937 if (declarator)
7939 strcat (buf, " ");
7940 strcat (buf, gen_declarator (declarator, declbuf, ""));
7944 else
7946 tree atype;
7947 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7948 tree declarator; /* "array_type", "function_type", "pointer_type". */
7950 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7951 || TREE_CODE (atype_or_adecl) == PARM_DECL
7952 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7953 atype = TREE_TYPE (atype_or_adecl);
7954 else
7955 /* Assume we have a *_type node. */
7956 atype = atype_or_adecl;
7958 if (is_complex_decl (atype))
7960 tree chain;
7962 /* Get the declaration specifier; it is at the end of the list. */
7963 declarator = chain = atype;
7965 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7966 while (is_complex_decl (chain));
7967 declspecs = chain;
7970 else
7972 declspecs = atype;
7973 declarator = NULL_TREE;
7976 gen_declspecs (declspecs, buf, 0);
7978 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7979 || TREE_CODE (atype_or_adecl) == PARM_DECL
7980 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7982 const char *decl_name =
7983 (DECL_NAME (atype_or_adecl)
7984 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
7986 if (declarator)
7988 strcat (buf, " ");
7989 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7992 else if (decl_name[0])
7994 strcat (buf, " ");
7995 strcat (buf, decl_name);
7998 else if (declarator)
8000 strcat (buf, " ");
8001 strcat (buf, gen_declarator (declarator, declbuf, ""));
8005 return buf;
8008 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8010 static char *
8011 gen_method_decl (method, buf)
8012 tree method;
8013 char *buf;
8015 tree chain;
8017 if (RAW_TYPESPEC (method) != objc_object_reference)
8019 strcpy (buf, "(");
8020 gen_declaration (TREE_TYPE (method), buf);
8021 strcat (buf, ")");
8024 chain = METHOD_SEL_ARGS (method);
8025 if (chain)
8027 /* We have a chain of keyword_decls. */
8030 if (KEYWORD_KEY_NAME (chain))
8031 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8033 strcat (buf, ":");
8034 if (RAW_TYPESPEC (chain) != objc_object_reference)
8036 strcat (buf, "(");
8037 gen_declaration (TREE_TYPE (chain), buf);
8038 strcat (buf, ")");
8041 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8042 if ((chain = TREE_CHAIN (chain)))
8043 strcat (buf, " ");
8045 while (chain);
8047 if (METHOD_ADD_ARGS (method) == (tree)1)
8048 strcat (buf, ", ...");
8049 else if (METHOD_ADD_ARGS (method))
8051 /* We have a tree list node as generate by get_parm_info. */
8052 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8054 /* Know we have a chain of parm_decls. */
8055 while (chain)
8057 strcat (buf, ", ");
8058 gen_declaration (chain, buf);
8059 chain = TREE_CHAIN (chain);
8064 else
8065 /* We have a unary selector. */
8066 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8068 return buf;
8071 /* Debug info. */
8073 static void
8074 dump_interface (fp, chain)
8075 FILE *fp;
8076 tree chain;
8078 char *buf = (char *)xmalloc (256);
8079 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8080 tree ivar_decls = CLASS_RAW_IVARS (chain);
8081 tree nst_methods = CLASS_NST_METHODS (chain);
8082 tree cls_methods = CLASS_CLS_METHODS (chain);
8084 fprintf (fp, "\n@interface %s", my_name);
8086 if (CLASS_SUPER_NAME (chain))
8088 const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8089 fprintf (fp, " : %s\n", super_name);
8091 else
8092 fprintf (fp, "\n");
8094 if (ivar_decls)
8096 fprintf (fp, "{\n");
8099 bzero (buf, 256);
8100 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8101 ivar_decls = TREE_CHAIN (ivar_decls);
8103 while (ivar_decls);
8104 fprintf (fp, "}\n");
8107 while (nst_methods)
8109 bzero (buf, 256);
8110 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8111 nst_methods = TREE_CHAIN (nst_methods);
8114 while (cls_methods)
8116 bzero (buf, 256);
8117 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8118 cls_methods = TREE_CHAIN (cls_methods);
8120 fprintf (fp, "\n@end");
8123 /* Demangle function for Objective-C */
8124 static const char *
8125 objc_demangle (mangled)
8126 const char *mangled;
8128 char *demangled, *cp;
8130 if (mangled[0] == '_' &&
8131 (mangled[1] == 'i' || mangled[1] == 'c') &&
8132 mangled[2] == '_')
8134 cp = demangled = xmalloc(strlen(mangled) + 2);
8135 if (mangled[1] == 'i')
8136 *cp++ = '-'; /* for instance method */
8137 else
8138 *cp++ = '+'; /* for class method */
8139 *cp++ = '['; /* opening left brace */
8140 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8141 while (*cp && *cp == '_')
8142 cp++; /* skip any initial underbars in class name */
8143 cp = strchr(cp, '_'); /* find first non-initial underbar */
8144 if (cp == NULL)
8146 free(demangled); /* not mangled name */
8147 return mangled;
8149 if (cp[1] == '_') /* easy case: no category name */
8151 *cp++ = ' '; /* replace two '_' with one ' ' */
8152 strcpy(cp, mangled + (cp - demangled) + 2);
8154 else
8156 *cp++ = '('; /* less easy case: category name */
8157 cp = strchr(cp, '_');
8158 if (cp == 0)
8160 free(demangled); /* not mangled name */
8161 return mangled;
8163 *cp++ = ')';
8164 *cp++ = ' '; /* overwriting 1st char of method name... */
8165 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8167 while (*cp && *cp == '_')
8168 cp++; /* skip any initial underbars in method name */
8169 for (; *cp; cp++)
8170 if (*cp == '_')
8171 *cp = ':'; /* replace remaining '_' with ':' */
8172 *cp++ = ']'; /* closing right brace */
8173 *cp++ = 0; /* string terminator */
8174 return demangled;
8176 else
8177 return mangled; /* not an objc mangled name */
8180 static const char *
8181 objc_printable_name (decl, kind)
8182 tree decl;
8183 int kind ATTRIBUTE_UNUSED;
8185 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8188 static void
8189 init_objc ()
8191 /* Add the special tree codes of Objective C to the tables. */
8193 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
8195 gcc_obstack_init (&util_obstack);
8196 util_firstobj = (char *) obstack_finish (&util_obstack);
8198 memcpy (tree_code_type + (int) LAST_CODE,
8199 objc_tree_code_type,
8200 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
8201 memcpy (tree_code_length + (int) LAST_CODE,
8202 objc_tree_code_length,
8203 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (int)));
8204 memcpy (tree_code_name + (int) LAST_CODE,
8205 objc_tree_code_name,
8206 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (char *)));
8208 errbuf = (char *)xmalloc (BUFSIZE);
8209 hash_init ();
8210 synth_module_prologue ();
8212 /* Change the default error function */
8213 decl_printable_name = objc_printable_name;
8216 static void
8217 finish_objc ()
8219 struct imp_entry *impent;
8220 tree chain;
8221 /* The internally generated initializers appear to have missing braces.
8222 Don't warn about this. */
8223 int save_warn_missing_braces = warn_missing_braces;
8224 warn_missing_braces = 0;
8226 generate_forward_declaration_to_string_table ();
8228 #ifdef OBJC_PROLOGUE
8229 OBJC_PROLOGUE;
8230 #endif
8232 /* Process the static instances here because initialization of objc_symtab
8233 depends on them. */
8234 if (objc_static_instances)
8235 generate_static_references ();
8237 if (implementation_context || class_names_chain
8238 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8239 generate_objc_symtab_decl ();
8241 for (impent = imp_list; impent; impent = impent->next)
8243 implementation_context = impent->imp_context;
8244 implementation_template = impent->imp_template;
8246 UOBJC_CLASS_decl = impent->class_decl;
8247 UOBJC_METACLASS_decl = impent->meta_decl;
8249 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8251 /* all of the following reference the string pool... */
8252 generate_ivar_lists ();
8253 generate_dispatch_tables ();
8254 generate_shared_structures ();
8256 else
8258 generate_dispatch_tables ();
8259 generate_category (implementation_context);
8263 /* If we are using an array of selectors, we must always
8264 finish up the array decl even if no selectors were used. */
8265 if (! flag_next_runtime || sel_ref_chain)
8266 build_selector_translation_table ();
8268 if (protocol_chain)
8269 generate_protocols ();
8271 if (implementation_context || class_names_chain || objc_static_instances
8272 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8274 /* Arrange for Objc data structures to be initialized at run time. */
8275 char *init_name = build_module_descriptor ();
8276 if (init_name)
8277 assemble_constructor (init_name);
8280 /* Dump the class references. This forces the appropriate classes
8281 to be linked into the executable image, preserving unix archive
8282 semantics. This can be removed when we move to a more dynamically
8283 linked environment. */
8285 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8287 handle_class_ref (chain);
8288 if (TREE_PURPOSE (chain))
8289 generate_classref_translation_entry (chain);
8292 for (impent = imp_list; impent; impent = impent->next)
8293 handle_impent (impent);
8295 /* Dump the string table last. */
8297 generate_strings ();
8299 if (flag_gen_declaration)
8301 add_class (implementation_context);
8302 dump_interface (gen_declaration_file, implementation_context);
8305 if (warn_selector)
8307 int slot;
8308 hash hsh;
8310 /* Run through the selector hash tables and print a warning for any
8311 selector which has multiple methods. */
8313 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8314 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8315 if (hsh->list)
8317 tree meth = hsh->key;
8318 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8319 ? '-' : '+');
8320 attr loop;
8322 warning ("potential selector conflict for method `%s'",
8323 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8324 warn_with_method ("found", type, meth);
8325 for (loop = hsh->list; loop; loop = loop->next)
8326 warn_with_method ("found", type, loop->value);
8329 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8330 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8331 if (hsh->list)
8333 tree meth = hsh->key;
8334 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8335 ? '-' : '+');
8336 attr loop;
8338 warning ("potential selector conflict for method `%s'",
8339 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8340 warn_with_method ("found", type, meth);
8341 for (loop = hsh->list; loop; loop = loop->next)
8342 warn_with_method ("found", type, loop->value);
8346 warn_missing_braces = save_warn_missing_braces;
8349 /* Subroutines of finish_objc. */
8351 static void
8352 generate_classref_translation_entry (chain)
8353 tree chain;
8355 tree expr, name, decl_specs, decl, sc_spec;
8356 tree type;
8358 type = TREE_TYPE (TREE_PURPOSE (chain));
8360 expr = add_objc_string (TREE_VALUE (chain), class_names);
8361 expr = build_c_cast (type, expr); /* cast! */
8363 name = DECL_NAME (TREE_PURPOSE (chain));
8365 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8367 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8368 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8370 /* The decl that is returned from start_decl is the one that we
8371 forward declared in build_class_reference. */
8372 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8373 finish_decl (decl, expr, NULL_TREE);
8374 return;
8377 static void
8378 handle_class_ref (chain)
8379 tree chain;
8381 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8382 if (! flag_next_runtime)
8384 tree decl;
8385 char *string = (char *) alloca (strlen (name) + 30);
8386 tree exp;
8388 sprintf (string, "%sobjc_class_name_%s",
8389 (flag_next_runtime ? "." : "__"), name);
8391 /* Make a decl for this name, so we can use its address in a tree. */
8392 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8393 DECL_EXTERNAL (decl) = 1;
8394 TREE_PUBLIC (decl) = 1;
8396 pushdecl (decl);
8397 rest_of_decl_compilation (decl, 0, 0, 0);
8399 /* Make following constant read-only (why not)? */
8400 readonly_data_section ();
8402 exp = build1 (ADDR_EXPR, string_type_node, decl);
8404 /* Align the section properly. */
8405 assemble_constant_align (exp);
8407 /* Inform the assembler about this new external thing. */
8408 assemble_external (decl);
8410 /* Output a constant to reference this address. */
8411 output_constant (exp, int_size_in_bytes (string_type_node));
8413 else
8415 /* This overreliance on our assembler (i.e. lack of portability)
8416 should be dealt with at some point. The GNU strategy (above)
8417 won't work either, but it is a start. */
8418 char *string = (char *) alloca (strlen (name) + 30);
8419 sprintf (string, ".reference .objc_class_name_%s", name);
8420 assemble_asm (my_build_string (strlen (string) + 1, string));
8424 static void
8425 handle_impent (impent)
8426 struct imp_entry *impent;
8428 implementation_context = impent->imp_context;
8429 implementation_template = impent->imp_template;
8431 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8433 const char *class_name =
8434 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8435 char *string = (char *) alloca (strlen (class_name) + 30);
8437 if (flag_next_runtime)
8439 /* Grossly unportable.
8440 People should know better than to assume
8441 such things about assembler syntax! */
8442 sprintf (string, ".objc_class_name_%s=0", class_name);
8443 assemble_asm (my_build_string (strlen (string) + 1, string));
8445 sprintf (string, ".globl .objc_class_name_%s", class_name);
8446 assemble_asm (my_build_string (strlen (string) + 1, string));
8449 else
8451 sprintf (string, "%sobjc_class_name_%s",
8452 (flag_next_runtime ? "." : "__"), class_name);
8453 assemble_global (string);
8454 assemble_label (string);
8458 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8460 const char *class_name =
8461 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8462 const char *class_super_name =
8463 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8464 char *string = (char *) alloca (strlen (class_name)
8465 + strlen (class_super_name) + 30);
8467 /* Do the same for categories. Even though no references to these
8468 symbols are generated automatically by the compiler, it gives
8469 you a handle to pull them into an archive by hand. */
8470 if (flag_next_runtime)
8472 /* Grossly unportable. */
8473 sprintf (string, ".objc_category_name_%s_%s=0",
8474 class_name, class_super_name);
8475 assemble_asm (my_build_string (strlen (string) + 1, string));
8477 sprintf (string, ".globl .objc_category_name_%s_%s",
8478 class_name, class_super_name);
8479 assemble_asm (my_build_string (strlen (string) + 1, string));
8482 else
8484 sprintf (string, "%sobjc_category_name_%s_%s",
8485 (flag_next_runtime ? "." : "__"),
8486 class_name, class_super_name);
8487 assemble_global (string);
8488 assemble_label (string);
8493 #ifdef DEBUG
8495 static void
8496 objc_debug (fp)
8497 FILE *fp;
8499 char *buf = (char *)xmalloc (256);
8501 { /* dump function prototypes */
8502 tree loop = UOBJC_MODULES_decl;
8504 fprintf (fp, "\n\nfunction prototypes:\n");
8505 while (loop)
8507 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8509 /* We have a function definition: generate prototype. */
8510 bzero (errbuf, BUFSIZE);
8511 gen_declaration (loop, errbuf);
8512 fprintf (fp, "%s;\n", errbuf);
8514 loop = TREE_CHAIN (loop);
8518 /* Dump global chains. */
8519 tree loop;
8520 int i, index = 0, offset = 0;
8521 hash hashlist;
8523 for (i = 0; i < SIZEHASHTABLE; i++)
8525 if (hashlist = nst_method_hash_list[i])
8527 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8530 bzero (buf, 256);
8531 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8532 hashlist = hashlist->next;
8534 while (hashlist);
8538 for (i = 0; i < SIZEHASHTABLE; i++)
8540 if (hashlist = cls_method_hash_list[i])
8542 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8545 bzero (buf, 256);
8546 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8547 hashlist = hashlist->next;
8549 while (hashlist);
8553 fprintf (fp, "\nsel_refdef_chain:\n");
8554 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8556 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8557 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8558 index++;
8559 /* add one for the '\0' character */
8560 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8563 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8566 #endif
8568 void
8569 print_lang_statistics ()