* dwarfout.c (field_byte_offset): Correctly compute the object's
[official-gcc.git] / gcc / objc / objc-act.c
bloba2842c8c52a5b6b2ce9a3b2120bb44c28765042a
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 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 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 char *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((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));
206 /* We handle printing method names ourselves for ObjC */
207 extern char *(*decl_printable_name) ();
209 /* Misc. bookkeeping */
211 typedef struct hashed_entry *hash;
212 typedef struct hashed_attribute *attr;
214 struct hashed_attribute
216 attr next;
217 tree value;
219 struct hashed_entry
221 attr list;
222 hash next;
223 tree key;
226 static void hash_init PROTO((void));
227 static void hash_enter PROTO((hash *, tree));
228 static hash hash_lookup PROTO((hash *, tree));
229 static void hash_add_attr PROTO((hash, tree));
230 static tree lookup_method PROTO((tree, tree));
231 static tree lookup_instance_method_static PROTO((tree, tree));
232 static tree lookup_class_method_static PROTO((tree, tree));
233 static tree add_class PROTO((tree));
234 static void add_category PROTO((tree, tree));
236 enum string_section
238 class_names, /* class, category, protocol, module names */
239 meth_var_names, /* method and variable names */
240 meth_var_types /* method and variable type descriptors */
243 static tree add_objc_string PROTO((tree,
244 enum string_section));
245 static tree get_objc_string_decl PROTO((tree,
246 enum string_section));
247 static tree build_objc_string_decl PROTO((tree,
248 enum string_section));
249 static tree build_selector_reference_decl PROTO((tree));
251 /* Protocol additions. */
253 static tree add_protocol PROTO((tree));
254 static tree lookup_protocol PROTO((tree));
255 static tree lookup_and_install_protocols PROTO((tree));
257 /* Type encoding. */
259 static void encode_type_qualifiers PROTO((tree));
260 static void encode_pointer PROTO((tree, int, int));
261 static void encode_array PROTO((tree, int, int));
262 static void encode_aggregate PROTO((tree, int, int));
263 static void encode_bitfield PROTO((int, int));
264 static void encode_type PROTO((tree, int, int));
265 static void encode_field_decl PROTO((tree, int, int));
267 static void really_start_method PROTO((tree, tree));
268 static int comp_method_with_proto PROTO((tree, tree));
269 static int comp_proto_with_proto PROTO((tree, tree));
270 static tree get_arg_type_list PROTO((tree, int, int));
271 static tree expr_last PROTO((tree));
273 /* Utilities for debugging and error diagnostics. */
275 static void warn_with_method PROTO((char *, int, tree));
276 static void error_with_ivar PROTO((char *, tree, tree));
277 static char *gen_method_decl PROTO((tree, char *));
278 static char *gen_declaration PROTO((tree, char *));
279 static char *gen_declarator PROTO((tree, char *, char *));
280 static int is_complex_decl PROTO((tree));
281 static void adorn_decl PROTO((tree, char *));
282 static void dump_interface PROTO((FILE *, tree));
284 /* Everything else. */
286 static void objc_fatal PROTO((void))
287 ATTRIBUTE_NORETURN;
288 static tree define_decl PROTO((tree, tree));
289 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
290 static tree lookup_protocol_in_reflist PROTO((tree, tree));
291 static tree create_builtin_decl PROTO((enum tree_code,
292 tree, char *));
293 static tree my_build_string PROTO((int, char *));
294 static void build_objc_symtab_template PROTO((void));
295 static tree init_def_list PROTO((tree));
296 static tree init_objc_symtab PROTO((tree));
297 static void forward_declare_categories PROTO((void));
298 static void generate_objc_symtab_decl PROTO((void));
299 static tree build_selector PROTO((tree));
300 #if 0
301 static tree build_msg_pool_reference PROTO((int));
302 #endif
303 static tree build_typed_selector_reference PROTO((tree, tree));
304 static tree build_selector_reference PROTO((tree));
305 static tree build_class_reference_decl PROTO((tree));
306 static void add_class_reference PROTO((tree));
307 static tree objc_copy_list PROTO((tree, tree *));
308 static tree build_protocol_template PROTO((void));
309 static tree build_descriptor_table_initializer PROTO((tree, tree));
310 static tree build_method_prototype_list_template PROTO((tree, int));
311 static tree build_method_prototype_template PROTO((void));
312 static int forwarding_offset PROTO((tree));
313 static tree encode_method_prototype PROTO((tree, tree));
314 static tree generate_descriptor_table PROTO((tree, char *, 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, char *,
325 int, tree));
326 static tree build_dispatch_table_initializer PROTO((tree, tree));
327 static tree generate_dispatch_table PROTO((tree, 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, char *, char *));
340 static tree encode_method_def PROTO((tree));
341 static void gen_declspecs PROTO((tree, char *, int));
342 static void generate_classref_translation_entry PROTO((tree));
343 static void handle_class_ref PROTO((tree));
345 /*** Private Interface (data) ***/
347 /* Reserved tag definitions. */
349 #define TYPE_ID "id"
350 #define TAG_OBJECT "objc_object"
351 #define TAG_CLASS "objc_class"
352 #define TAG_SUPER "objc_super"
353 #define TAG_SELECTOR "objc_selector"
355 #define UTAG_CLASS "_objc_class"
356 #define UTAG_IVAR "_objc_ivar"
357 #define UTAG_IVAR_LIST "_objc_ivar_list"
358 #define UTAG_METHOD "_objc_method"
359 #define UTAG_METHOD_LIST "_objc_method_list"
360 #define UTAG_CATEGORY "_objc_category"
361 #define UTAG_MODULE "_objc_module"
362 #define UTAG_STATICS "_objc_statics"
363 #define UTAG_SYMTAB "_objc_symtab"
364 #define UTAG_SUPER "_objc_super"
365 #define UTAG_SELECTOR "_objc_selector"
367 #define UTAG_PROTOCOL "_objc_protocol"
368 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
369 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
370 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
372 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
373 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
375 static char *TAG_GETCLASS;
376 static char *TAG_GETMETACLASS;
377 static char *TAG_MSGSEND;
378 static char *TAG_MSGSENDSUPER;
379 static char *TAG_EXECCLASS;
381 /* Set by `continue_class' and checked by `is_public'. */
383 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
384 #define TYPED_OBJECT(type) \
385 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
387 /* Some commonly used instances of "identifier_node". */
389 static tree self_id, ucmd_id;
390 static tree unused_list;
392 static tree self_decl, umsg_decl, umsg_super_decl;
393 static tree objc_get_class_decl, objc_get_meta_class_decl;
395 static tree super_type, selector_type, id_type, objc_class_type;
396 static tree instance_type, protocol_type;
398 /* Type checking macros. */
400 #define IS_ID(TYPE) \
401 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
402 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
403 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
404 #define IS_SUPER(TYPE) \
405 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
407 static tree class_chain = NULL_TREE;
408 static tree alias_chain = NULL_TREE;
409 static tree interface_chain = NULL_TREE;
410 static tree protocol_chain = NULL_TREE;
412 /* Chains to manage selectors that are referenced and defined in the
413 module. */
415 static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */
416 static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */
418 /* Chains to manage uniquing of strings. */
420 static tree class_names_chain = NULL_TREE;
421 static tree meth_var_names_chain = NULL_TREE;
422 static tree meth_var_types_chain = NULL_TREE;
424 /* Hash tables to manage the global pool of method prototypes. */
426 static hash *nst_method_hash_list = 0;
427 static hash *cls_method_hash_list = 0;
429 /* Backend data declarations. */
431 static tree UOBJC_SYMBOLS_decl;
432 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
433 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
434 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
435 static tree UOBJC_SELECTOR_TABLE_decl;
436 static tree UOBJC_MODULES_decl;
437 static tree UOBJC_STRINGS_decl;
439 /* The following are used when compiling a class implementation.
440 implementation_template will normally be an interface, however if
441 none exists this will be equal to implementation_context...it is
442 set in start_class. */
444 static tree implementation_context = NULL_TREE;
445 static tree implementation_template = NULL_TREE;
447 struct imp_entry
449 struct imp_entry *next;
450 tree imp_context;
451 tree imp_template;
452 tree class_decl; /* _OBJC_CLASS_<my_name>; */
453 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
456 static void handle_impent PROTO((struct imp_entry *));
458 static struct imp_entry *imp_list = 0;
459 static int imp_count = 0; /* `@implementation' */
460 static int cat_count = 0; /* `@category' */
462 static tree objc_class_template, objc_category_template, uprivate_record;
463 static tree objc_protocol_template, objc_selector_template;
464 static tree ucls_super_ref, uucls_super_ref;
466 static tree objc_method_template, objc_ivar_template;
467 static tree objc_symtab_template, objc_module_template;
468 static tree objc_super_template, objc_object_reference;
470 static tree objc_object_id, objc_class_id, objc_id_id;
471 static tree constant_string_id;
472 static tree constant_string_type;
473 static tree UOBJC_SUPER_decl;
475 static tree method_context = NULL_TREE;
476 static int method_slot = 0; /* Used by start_method_def, */
478 #define BUFSIZE 1024
480 static char *errbuf; /* Buffer for error diagnostics */
482 /* Data imported from tree.c. */
484 extern enum debug_info_type write_symbols;
486 /* Data imported from toplev.c. */
488 extern char *dump_base_name;
490 /* Generate code for GNU or NeXT runtime environment. */
492 #ifdef NEXT_OBJC_RUNTIME
493 int flag_next_runtime = 1;
494 #else
495 int flag_next_runtime = 0;
496 #endif
498 int flag_typed_selectors;
500 /* Open and close the file for outputting class declarations, if requested. */
502 int flag_gen_declaration = 0;
504 FILE *gen_declaration_file;
506 /* Warn if multiple methods are seen for the same selector, but with
507 different argument types. */
509 int warn_selector = 0;
511 /* Warn if methods required by a protocol are not implemented in the
512 class adopting it. When turned off, methods inherited to that
513 class are also considered implemented */
515 int flag_warn_protocol = 1;
517 /* Tells "encode_pointer/encode_aggregate" whether we are generating
518 type descriptors for instance variables (as opposed to methods).
519 Type descriptors for instance variables contain more information
520 than methods (for static typing and embedded structures). This
521 was added to support features being planned for dbkit2. */
523 static int generating_instance_variables = 0;
525 /* Tells the compiler that this is a special run. Do not perform
526 any compiling, instead we are to test some platform dependent
527 features and output a C header file with appropriate definitions. */
529 static int print_struct_values = 0;
531 /* Some platforms pass small structures through registers versus through
532 an invisible pointer. Determine at what size structure is the
533 transition point between the two possibilities. */
535 void
536 generate_struct_by_value_array ()
538 tree type;
539 tree field_decl, field_decl_chain;
540 int i, j;
541 int aggregate_in_mem[32];
542 int found = 0;
544 /* Presumbaly no platform passes 32 byte structures in a register. */
545 for (i = 1; i < 32; i++)
547 char buffer[5];
549 /* Create an unnamed struct that has `i' character components */
550 type = start_struct (RECORD_TYPE, NULL_TREE);
552 strcpy (buffer, "c1");
553 field_decl = create_builtin_decl (FIELD_DECL,
554 char_type_node,
555 buffer);
556 field_decl_chain = field_decl;
558 for (j = 1; j < i; j++)
560 sprintf (buffer, "c%d", j + 1);
561 field_decl = create_builtin_decl (FIELD_DECL,
562 char_type_node,
563 buffer);
564 chainon (field_decl_chain, field_decl);
566 finish_struct (type, field_decl_chain, NULL_TREE);
568 aggregate_in_mem[i] = aggregate_value_p (type);
569 if (!aggregate_in_mem[i])
570 found = 1;
573 /* We found some structures that are returned in registers instead of memory
574 so output the necessary data. */
575 if (found)
577 for (i = 31; i >= 0; i--)
578 if (!aggregate_in_mem[i])
579 break;
580 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
582 /* The first member of the structure is always 0 because we don't handle
583 structures with 0 members */
584 printf ("static int struct_forward_array[] = {\n 0");
586 for (j = 1; j <= i; j++)
587 printf (", %d", aggregate_in_mem[j]);
588 printf ("\n};\n");
591 exit (0);
594 #if USE_CPPLIB
595 extern char *yy_cur;
596 #endif
598 void
599 lang_init_options ()
601 #if USE_CPPLIB
602 cpp_reader_init (&parse_in);
603 parse_in.opts = &parse_options;
604 cpp_options_init (&parse_options);
605 #endif
608 void
609 lang_init ()
611 #if !USE_CPPLIB
612 /* The beginning of the file is a new line; check for #.
613 With luck, we discover the real source file's name from that
614 and put it in input_filename. */
615 ungetc (check_newline (), finput);
616 #else
617 check_newline ();
618 yy_cur--;
619 #endif
621 /* The line number can be -1 if we had -g3 and the input file
622 had a directive specifying line 0. But we want predefined
623 functions to have a line number of 0, not -1. */
624 if (lineno == -1)
625 lineno = 0;
627 /* If gen_declaration desired, open the output file. */
628 if (flag_gen_declaration)
630 int dump_base_name_length = strlen (dump_base_name);
631 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
632 strcpy (dumpname, dump_base_name);
633 strcat (dumpname, ".decl");
634 gen_declaration_file = fopen (dumpname, "w");
635 if (gen_declaration_file == 0)
636 pfatal_with_name (dumpname);
639 if (flag_next_runtime)
641 TAG_GETCLASS = "objc_getClass";
642 TAG_GETMETACLASS = "objc_getMetaClass";
643 TAG_MSGSEND = "objc_msgSend";
644 TAG_MSGSENDSUPER = "objc_msgSendSuper";
645 TAG_EXECCLASS = "__objc_execClass";
647 else
649 TAG_GETCLASS = "objc_get_class";
650 TAG_GETMETACLASS = "objc_get_meta_class";
651 TAG_MSGSEND = "objc_msg_lookup";
652 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
653 TAG_EXECCLASS = "__objc_exec_class";
654 flag_typed_selectors = 1;
657 if (doing_objc_thang)
658 init_objc ();
660 if (print_struct_values)
661 generate_struct_by_value_array ();
664 static void
665 objc_fatal ()
667 fatal ("Objective-C text in C source file");
670 void
671 finish_file ()
673 if (doing_objc_thang)
674 finish_objc (); /* Objective-C finalization */
676 if (gen_declaration_file)
677 fclose (gen_declaration_file);
680 void
681 lang_finish ()
685 char *
686 lang_identify ()
688 return "objc";
692 lang_decode_option (argc, argv)
693 int argc;
694 char **argv;
696 char *p = argv[0];
697 if (!strcmp (p, "-lang-objc"))
698 doing_objc_thang = 1;
699 else if (!strcmp (p, "-gen-decls"))
700 flag_gen_declaration = 1;
701 else if (!strcmp (p, "-Wselector"))
702 warn_selector = 1;
703 else if (!strcmp (p, "-Wno-selector"))
704 warn_selector = 0;
705 else if (!strcmp (p, "-Wprotocol"))
706 flag_warn_protocol = 1;
707 else if (!strcmp (p, "-Wno-protocol"))
708 flag_warn_protocol = 0;
709 else if (!strcmp (p, "-fgnu-runtime"))
710 flag_next_runtime = 0;
711 else if (!strcmp (p, "-fno-next-runtime"))
712 flag_next_runtime = 0;
713 else if (!strcmp (p, "-fno-gnu-runtime"))
714 flag_next_runtime = 1;
715 else if (!strcmp (p, "-fnext-runtime"))
716 flag_next_runtime = 1;
717 else if (!strcmp (p, "-print-objc-runtime-info"))
718 print_struct_values = 1;
719 else
720 return c_decode_option (argc, argv);
722 return 1;
725 /* used by print-tree.c */
727 void
728 lang_print_xnode (file, node, indent)
729 FILE *file ATTRIBUTE_UNUSED;
730 tree node ATTRIBUTE_UNUSED;
731 int indent ATTRIBUTE_UNUSED;
736 static tree
737 define_decl (declarator, declspecs)
738 tree declarator;
739 tree declspecs;
741 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
742 finish_decl (decl, NULL_TREE, NULL_TREE);
743 return decl;
746 /* Return 1 if LHS and RHS are compatible types for assignment or
747 various other operations. Return 0 if they are incompatible, and
748 return -1 if we choose to not decide. When the operation is
749 REFLEXIVE, check for compatibility in either direction.
751 For statically typed objects, an assignment of the form `a' = `b'
752 is permitted if:
754 `a' is of type "id",
755 `a' and `b' are the same class type, or
756 `a' and `b' are of class types A and B such that B is a descendant of A. */
759 maybe_objc_comptypes (lhs, rhs, reflexive)
760 tree lhs, rhs;
761 int reflexive;
763 if (doing_objc_thang)
764 return objc_comptypes (lhs, rhs, reflexive);
765 return -1;
768 static tree
769 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
770 tree rproto_list;
771 tree sel_name;
772 int class_meth;
774 tree rproto, p;
775 tree fnd = 0;
777 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
779 p = TREE_VALUE (rproto);
781 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
783 if ((fnd = lookup_method (class_meth
784 ? PROTOCOL_CLS_METHODS (p)
785 : PROTOCOL_NST_METHODS (p), sel_name)))
787 else if (PROTOCOL_LIST (p))
788 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
789 sel_name, class_meth);
791 else
793 ; /* An identifier...if we could not find a protocol. */
796 if (fnd)
797 return fnd;
800 return 0;
803 static tree
804 lookup_protocol_in_reflist (rproto_list, lproto)
805 tree rproto_list;
806 tree lproto;
808 tree rproto, p;
810 /* Make sure the protocol is support by the object on the rhs. */
811 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
813 tree fnd = 0;
814 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
816 p = TREE_VALUE (rproto);
818 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
820 if (lproto == p)
821 fnd = lproto;
823 else if (PROTOCOL_LIST (p))
824 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
827 if (fnd)
828 return fnd;
831 else
833 ; /* An identifier...if we could not find a protocol. */
836 return 0;
839 /* Return 1 if LHS and RHS are compatible types for assignment
840 or various other operations. Return 0 if they are incompatible,
841 and return -1 if we choose to not decide. When the operation
842 is REFLEXIVE, check for compatibility in either direction. */
845 objc_comptypes (lhs, rhs, reflexive)
846 tree lhs;
847 tree rhs;
848 int reflexive;
850 /* New clause for protocols. */
852 if (TREE_CODE (lhs) == POINTER_TYPE
853 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
854 && TREE_CODE (rhs) == POINTER_TYPE
855 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
857 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
858 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
860 if (lhs_is_proto)
862 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
863 tree rproto, rproto_list;
864 tree p;
866 if (rhs_is_proto)
868 rproto_list = TYPE_PROTOCOL_LIST (rhs);
870 /* Make sure the protocol is supported by the object
871 on the rhs. */
872 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
874 p = TREE_VALUE (lproto);
875 rproto = lookup_protocol_in_reflist (rproto_list, p);
877 if (!rproto)
878 warning ("object does not conform to the `%s' protocol",
879 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
882 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
884 tree rname = TYPE_NAME (TREE_TYPE (rhs));
885 tree rinter;
887 /* Make sure the protocol is supported by the object
888 on the rhs. */
889 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
891 p = TREE_VALUE (lproto);
892 rproto = 0;
893 rinter = lookup_interface (rname);
895 while (rinter && !rproto)
897 tree cat;
899 rproto_list = CLASS_PROTOCOL_LIST (rinter);
900 rproto = lookup_protocol_in_reflist (rproto_list, p);
902 /* Check for protocols adopted by categories. */
903 cat = CLASS_CATEGORY_LIST (rinter);
904 while (cat && !rproto)
906 rproto_list = CLASS_PROTOCOL_LIST (cat);
907 rproto = lookup_protocol_in_reflist (rproto_list, p);
909 cat = CLASS_CATEGORY_LIST (cat);
912 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
915 if (!rproto)
916 warning ("class `%s' does not implement the `%s' protocol",
917 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
918 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
922 /* May change...based on whether there was any mismatch */
923 return 1;
925 else if (rhs_is_proto)
926 /* Lhs is not a protocol...warn if it is statically typed */
927 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
929 else
930 /* Defer to comptypes .*/
931 return -1;
934 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
935 ; /* Fall thru. This is the case we have been handling all along */
936 else
937 /* Defer to comptypes. */
938 return -1;
940 /* `id' = `<class> *', `<class> *' = `id' */
942 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
943 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
944 return 1;
946 /* `id' = `Class', `Class' = `id' */
948 else if ((TYPE_NAME (lhs) == objc_object_id
949 && TYPE_NAME (rhs) == objc_class_id)
950 || (TYPE_NAME (lhs) == objc_class_id
951 && TYPE_NAME (rhs) == objc_object_id))
952 return 1;
954 /* `<class> *' = `<class> *' */
956 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
958 tree lname = TYPE_NAME (lhs);
959 tree rname = TYPE_NAME (rhs);
960 tree inter;
962 if (lname == rname)
963 return 1;
965 /* If the left hand side is a super class of the right hand side,
966 allow it. */
967 for (inter = lookup_interface (rname); inter;
968 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
969 if (lname == CLASS_SUPER_NAME (inter))
970 return 1;
972 /* Allow the reverse when reflexive. */
973 if (reflexive)
974 for (inter = lookup_interface (lname); inter;
975 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
976 if (rname == CLASS_SUPER_NAME (inter))
977 return 1;
979 return 0;
981 else
982 /* Defer to comptypes. */
983 return -1;
986 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
988 void
989 objc_check_decl (decl)
990 tree decl;
992 tree type = TREE_TYPE (decl);
994 if (TREE_CODE (type) == RECORD_TYPE
995 && TREE_STATIC_TEMPLATE (type)
996 && type != constant_string_type)
998 error_with_decl (decl, "`%s' cannot be statically allocated");
999 fatal ("statically allocated objects not supported");
1003 void
1004 maybe_objc_check_decl (decl)
1005 tree decl;
1007 if (doing_objc_thang)
1008 objc_check_decl (decl);
1011 /* Implement static typing. At this point, we know we have an interface. */
1013 tree
1014 get_static_reference (interface, protocols)
1015 tree interface;
1016 tree protocols;
1018 tree type = xref_tag (RECORD_TYPE, interface);
1020 if (protocols)
1022 tree t, m = TYPE_MAIN_VARIANT (type);
1024 push_obstacks_nochange ();
1025 end_temporary_allocation ();
1026 t = copy_node (type);
1027 TYPE_BINFO (t) = make_tree_vec (2);
1028 pop_obstacks ();
1030 /* Add this type to the chain of variants of TYPE. */
1031 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1032 TYPE_NEXT_VARIANT (m) = t;
1034 /* Look up protocols and install in lang specific list. */
1035 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1037 /* This forces a new pointer type to be created later
1038 (in build_pointer_type)...so that the new template
1039 we just created will actually be used...what a hack! */
1040 if (TYPE_POINTER_TO (t))
1041 TYPE_POINTER_TO (t) = 0;
1043 type = t;
1046 return type;
1049 tree
1050 get_object_reference (protocols)
1051 tree protocols;
1053 tree type_decl = lookup_name (objc_id_id);
1054 tree type;
1056 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1058 type = TREE_TYPE (type_decl);
1059 if (TYPE_MAIN_VARIANT (type) != id_type)
1060 warning ("Unexpected type for `id' (%s)",
1061 gen_declaration (type, errbuf));
1063 else
1064 fatal ("Undefined type `id', please import <objc/objc.h>");
1066 /* This clause creates a new pointer type that is qualified with
1067 the protocol specification...this info is used later to do more
1068 elaborate type checking. */
1070 if (protocols)
1072 tree t, m = TYPE_MAIN_VARIANT (type);
1074 push_obstacks_nochange ();
1075 end_temporary_allocation ();
1076 t = copy_node (type);
1077 TYPE_BINFO (t) = make_tree_vec (2);
1078 pop_obstacks ();
1080 /* Add this type to the chain of variants of TYPE. */
1081 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1082 TYPE_NEXT_VARIANT (m) = t;
1084 /* Look up protocols...and install in lang specific list */
1085 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1087 /* This forces a new pointer type to be created later
1088 (in build_pointer_type)...so that the new template
1089 we just created will actually be used...what a hack! */
1090 if (TYPE_POINTER_TO (t))
1091 TYPE_POINTER_TO (t) = NULL;
1093 type = t;
1095 return type;
1098 static tree
1099 lookup_and_install_protocols (protocols)
1100 tree protocols;
1102 tree proto;
1103 tree prev = NULL;
1104 tree return_value = protocols;
1106 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1108 tree ident = TREE_VALUE (proto);
1109 tree p = lookup_protocol (ident);
1111 if (!p)
1113 error ("Cannot find protocol declaration for `%s'",
1114 IDENTIFIER_POINTER (ident));
1115 if (prev)
1116 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1117 else
1118 return_value = TREE_CHAIN (proto);
1120 else
1122 /* Replace identifier with actual protocol node. */
1123 TREE_VALUE (proto) = p;
1124 prev = proto;
1128 return return_value;
1131 /* Create and push a decl for a built-in external variable or field NAME.
1132 CODE says which.
1133 TYPE is its data type. */
1135 static tree
1136 create_builtin_decl (code, type, name)
1137 enum tree_code code;
1138 tree type;
1139 char *name;
1141 tree decl = build_decl (code, get_identifier (name), type);
1143 if (code == VAR_DECL)
1145 TREE_STATIC (decl) = 1;
1146 make_decl_rtl (decl, 0, 1);
1147 pushdecl (decl);
1150 DECL_ARTIFICIAL (decl) = 1;
1151 return decl;
1154 /* Purpose: "play" parser, creating/installing representations
1155 of the declarations that are required by Objective-C.
1157 Model:
1159 type_spec--------->sc_spec
1160 (tree_list) (tree_list)
1163 identifier_node identifier_node */
1165 static void
1166 synth_module_prologue ()
1168 tree temp_type;
1169 tree super_p;
1171 /* Defined in `objc.h' */
1172 objc_object_id = get_identifier (TAG_OBJECT);
1174 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1176 id_type = build_pointer_type (objc_object_reference);
1178 objc_id_id = get_identifier (TYPE_ID);
1179 objc_class_id = get_identifier (TAG_CLASS);
1181 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1182 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1183 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1185 /* Declare type of selector-objects that represent an operation name. */
1187 #ifdef OBJC_INT_SELECTORS
1188 /* `unsigned int' */
1189 selector_type = unsigned_type_node;
1190 #else
1191 /* `struct objc_selector *' */
1192 selector_type
1193 = build_pointer_type (xref_tag (RECORD_TYPE,
1194 get_identifier (TAG_SELECTOR)));
1195 #endif /* not OBJC_INT_SELECTORS */
1197 /* Forward declare type, or else the prototype for msgSendSuper will
1198 complain. */
1200 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1201 get_identifier (TAG_SUPER)));
1204 /* id objc_msgSend (id, SEL, ...); */
1206 temp_type
1207 = build_function_type (id_type,
1208 tree_cons (NULL_TREE, id_type,
1209 tree_cons (NULL_TREE, selector_type,
1210 NULL_TREE)));
1212 if (! flag_next_runtime)
1214 umsg_decl = build_decl (FUNCTION_DECL,
1215 get_identifier (TAG_MSGSEND), temp_type);
1216 DECL_EXTERNAL (umsg_decl) = 1;
1217 TREE_PUBLIC (umsg_decl) = 1;
1218 DECL_INLINE (umsg_decl) = 1;
1219 DECL_ARTIFICIAL (umsg_decl) = 1;
1221 if (flag_traditional && TAG_MSGSEND[0] != '_')
1222 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1224 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1225 pushdecl (umsg_decl);
1227 else
1228 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
1230 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1232 temp_type
1233 = build_function_type (id_type,
1234 tree_cons (NULL_TREE, super_p,
1235 tree_cons (NULL_TREE, selector_type,
1236 NULL_TREE)));
1238 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1239 temp_type, NOT_BUILT_IN, 0);
1241 /* id objc_getClass (const char *); */
1243 temp_type = build_function_type (id_type,
1244 tree_cons (NULL_TREE,
1245 const_string_type_node,
1246 tree_cons (NULL_TREE, void_type_node,
1247 NULL_TREE)));
1249 objc_get_class_decl
1250 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
1252 /* id objc_getMetaClass (const char *); */
1254 objc_get_meta_class_decl
1255 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
1257 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1259 if (! flag_next_runtime)
1261 if (flag_typed_selectors)
1263 /* Suppress outputting debug symbols, because
1264 dbxout_init hasn'r been called yet. */
1265 enum debug_info_type save_write_symbols = write_symbols;
1266 write_symbols = NO_DEBUG;
1268 build_selector_template ();
1269 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1271 write_symbols = save_write_symbols;
1273 else
1274 temp_type = build_array_type (selector_type, NULL_TREE);
1276 layout_type (temp_type);
1277 UOBJC_SELECTOR_TABLE_decl
1278 = create_builtin_decl (VAR_DECL, temp_type,
1279 "_OBJC_SELECTOR_TABLE");
1281 /* Avoid warning when not sending messages. */
1282 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1285 generate_forward_declaration_to_string_table ();
1287 /* Forward declare constant_string_id and constant_string_type. */
1288 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1289 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1292 /* Custom build_string which sets TREE_TYPE! */
1294 static tree
1295 my_build_string (len, str)
1296 int len;
1297 char *str;
1299 int wide_flag = 0;
1300 tree a_string = build_string (len, str);
1302 /* Some code from combine_strings, which is local to c-parse.y. */
1303 if (TREE_TYPE (a_string) == int_array_type_node)
1304 wide_flag = 1;
1306 TREE_TYPE (a_string)
1307 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1308 build_index_type (build_int_2 (len - 1, 0)));
1310 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1311 TREE_STATIC (a_string) = 1;
1313 return a_string;
1316 /* Return a newly constructed OBJC_STRING_CST node whose value is
1317 the LEN characters at STR.
1318 The TREE_TYPE is not initialized. */
1320 tree
1321 build_objc_string (len, str)
1322 int len;
1323 const char *str;
1325 tree s = build_string (len, str);
1327 TREE_SET_CODE (s, OBJC_STRING_CST);
1328 return s;
1331 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1332 NXConstanString which points at the concatenation of those strings.
1333 We place the string object in the __string_objects section of the
1334 __OBJC segment. The Objective-C runtime will initialize the isa
1335 pointers of the string objects to point at the NXConstandString class
1336 object. */
1338 tree
1339 build_objc_string_object (strings)
1340 tree strings;
1342 tree string, initlist, constructor;
1343 int length;
1345 if (!doing_objc_thang)
1346 objc_fatal ();
1348 if (lookup_interface (constant_string_id) == NULL_TREE)
1350 error ("Cannot find interface declaration for `%s'",
1351 IDENTIFIER_POINTER (constant_string_id));
1352 return error_mark_node;
1355 add_class_reference (constant_string_id);
1357 /* Combine_strings will work for OBJC_STRING_CST's too. */
1358 string = combine_strings (strings);
1359 TREE_SET_CODE (string, STRING_CST);
1360 length = TREE_STRING_LENGTH (string) - 1;
1362 if (! flag_next_runtime)
1364 push_obstacks_nochange ();
1365 end_temporary_allocation ();
1366 if (! TREE_PERMANENT (strings))
1367 string = my_build_string (length + 1,
1368 TREE_STRING_POINTER (string));
1371 /* & ((NXConstantString) {0, string, length}) */
1373 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1374 initlist
1375 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1376 initlist);
1377 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1378 constructor = build_constructor (constant_string_type, nreverse (initlist));
1380 if (!flag_next_runtime)
1382 constructor
1383 = objc_add_static_instance (constructor, constant_string_type);
1384 pop_obstacks ();
1387 return (build_unary_op (ADDR_EXPR, constructor, 1));
1390 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1392 static tree
1393 objc_add_static_instance (constructor, class_decl)
1394 tree constructor, class_decl;
1396 static int num_static_inst;
1397 tree *chain, decl;
1398 char buf[256];
1400 push_obstacks_nochange ();
1401 end_temporary_allocation ();
1403 /* Find the list of static instances for the CLASS_DECL. Create one if
1404 not found. */
1405 for (chain = &objc_static_instances;
1406 *chain && TREE_VALUE (*chain) != class_decl;
1407 chain = &TREE_CHAIN (*chain));
1408 if (!*chain)
1410 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1411 add_objc_string (TYPE_NAME (class_decl), class_names);
1414 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1415 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1416 DECL_COMMON (decl) = 1;
1417 TREE_STATIC (decl) = 1;
1418 DECL_ARTIFICIAL (decl) = 1;
1419 pushdecl_top_level (decl);
1420 rest_of_decl_compilation (decl, 0, 1, 0);
1422 /* Do this here so it gets output later instead of possibly
1423 inside something else we are writing. */
1424 DECL_INITIAL (decl) = constructor;
1426 /* Add the DECL to the head of this CLASS' list. */
1427 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1429 pop_obstacks ();
1430 return decl;
1433 /* Build a static constant CONSTRUCTOR
1434 with type TYPE and elements ELTS. */
1436 static tree
1437 build_constructor (type, elts)
1438 tree type, elts;
1440 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1442 TREE_CONSTANT (constructor) = 1;
1443 TREE_STATIC (constructor) = 1;
1444 TREE_READONLY (constructor) = 1;
1446 return constructor;
1449 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1451 /* Predefine the following data type:
1453 struct _objc_symtab
1455 long sel_ref_cnt;
1456 SEL *refs;
1457 short cls_def_cnt;
1458 short cat_def_cnt;
1459 void *defs[cls_def_cnt + cat_def_cnt];
1460 }; */
1462 static void
1463 build_objc_symtab_template ()
1465 tree field_decl, field_decl_chain, index;
1467 objc_symtab_template
1468 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1470 /* long sel_ref_cnt; */
1472 field_decl = create_builtin_decl (FIELD_DECL,
1473 long_integer_type_node,
1474 "sel_ref_cnt");
1475 field_decl_chain = field_decl;
1477 /* SEL *refs; */
1479 field_decl = create_builtin_decl (FIELD_DECL,
1480 build_pointer_type (selector_type),
1481 "refs");
1482 chainon (field_decl_chain, field_decl);
1484 /* short cls_def_cnt; */
1486 field_decl = create_builtin_decl (FIELD_DECL,
1487 short_integer_type_node,
1488 "cls_def_cnt");
1489 chainon (field_decl_chain, field_decl);
1491 /* short cat_def_cnt; */
1493 field_decl = create_builtin_decl (FIELD_DECL,
1494 short_integer_type_node,
1495 "cat_def_cnt");
1496 chainon (field_decl_chain, field_decl);
1498 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1500 if (!flag_next_runtime)
1501 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1502 else
1503 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1504 imp_count == 0 && cat_count == 0
1505 ? -1 : 0));
1506 field_decl = create_builtin_decl (FIELD_DECL,
1507 build_array_type (ptr_type_node, index),
1508 "defs");
1509 chainon (field_decl_chain, field_decl);
1511 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1514 /* Create the initial value for the `defs' field of _objc_symtab.
1515 This is a CONSTRUCTOR. */
1517 static tree
1518 init_def_list (type)
1519 tree type;
1521 tree expr, initlist = NULL_TREE;
1522 struct imp_entry *impent;
1524 if (imp_count)
1525 for (impent = imp_list; impent; impent = impent->next)
1527 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1529 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1530 initlist = tree_cons (NULL_TREE, expr, initlist);
1534 if (cat_count)
1535 for (impent = imp_list; impent; impent = impent->next)
1537 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1539 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1540 initlist = tree_cons (NULL_TREE, expr, initlist);
1544 if (!flag_next_runtime)
1546 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1547 tree expr;
1549 if (static_instances_decl)
1550 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1551 else
1552 expr = build_int_2 (0, 0);
1554 initlist = tree_cons (NULL_TREE, expr, initlist);
1557 return build_constructor (type, nreverse (initlist));
1560 /* Construct the initial value for all of _objc_symtab. */
1562 static tree
1563 init_objc_symtab (type)
1564 tree type;
1566 tree initlist;
1568 /* sel_ref_cnt = { ..., 5, ... } */
1570 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1572 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1574 if (flag_next_runtime || ! sel_ref_chain)
1575 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1576 else
1577 initlist = tree_cons (NULL_TREE,
1578 build_unary_op (ADDR_EXPR,
1579 UOBJC_SELECTOR_TABLE_decl, 1),
1580 initlist);
1582 /* cls_def_cnt = { ..., 5, ... } */
1584 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1586 /* cat_def_cnt = { ..., 5, ... } */
1588 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1590 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1592 if (imp_count || cat_count || static_instances_decl)
1595 tree field = TYPE_FIELDS (type);
1596 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1598 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1599 initlist);
1602 return build_constructor (type, nreverse (initlist));
1605 /* Push forward-declarations of all the categories
1606 so that init_def_list can use them in a CONSTRUCTOR. */
1608 static void
1609 forward_declare_categories ()
1611 struct imp_entry *impent;
1612 tree sav = implementation_context;
1614 for (impent = imp_list; impent; impent = impent->next)
1616 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1618 /* Set an invisible arg to synth_id_with_class_suffix. */
1619 implementation_context = impent->imp_context;
1620 impent->class_decl
1621 = create_builtin_decl (VAR_DECL, objc_category_template,
1622 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1625 implementation_context = sav;
1628 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1629 and initialized appropriately. */
1631 static void
1632 generate_objc_symtab_decl ()
1634 tree sc_spec;
1636 if (!objc_category_template)
1637 build_category_template ();
1639 /* forward declare categories */
1640 if (cat_count)
1641 forward_declare_categories ();
1643 if (!objc_symtab_template)
1644 build_objc_symtab_template ();
1646 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1648 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1649 tree_cons (NULL_TREE,
1650 objc_symtab_template, sc_spec),
1652 NULL_TREE, NULL_TREE);
1654 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1655 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1656 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1657 finish_decl (UOBJC_SYMBOLS_decl,
1658 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1659 NULL_TREE);
1662 static tree
1663 init_module_descriptor (type)
1664 tree type;
1666 tree initlist, expr;
1668 /* version = { 1, ... } */
1670 expr = build_int_2 (OBJC_VERSION, 0);
1671 initlist = build_tree_list (NULL_TREE, expr);
1673 /* size = { ..., sizeof (struct objc_module), ... } */
1675 expr = size_in_bytes (objc_module_template);
1676 initlist = tree_cons (NULL_TREE, expr, initlist);
1678 /* name = { ..., "foo.m", ... } */
1680 expr = add_objc_string (get_identifier (input_filename), class_names);
1681 initlist = tree_cons (NULL_TREE, expr, initlist);
1683 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1685 if (UOBJC_SYMBOLS_decl)
1686 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1687 else
1688 expr = build_int_2 (0, 0);
1689 initlist = tree_cons (NULL_TREE, expr, initlist);
1691 return build_constructor (type, nreverse (initlist));
1694 /* Write out the data structures to describe Objective C classes defined.
1695 If appropriate, compile and output a setup function to initialize them.
1696 Return a string which is the name of a function to call to initialize
1697 the Objective C data structures for this file (and perhaps for other files
1698 also).
1700 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1702 static char *
1703 build_module_descriptor ()
1705 tree decl_specs, field_decl, field_decl_chain;
1707 objc_module_template
1708 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1710 /* Long version; */
1712 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1713 field_decl = get_identifier ("version");
1714 field_decl
1715 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1716 field_decl_chain = field_decl;
1718 /* long size; */
1720 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1721 field_decl = get_identifier ("size");
1722 field_decl
1723 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1724 chainon (field_decl_chain, field_decl);
1726 /* char *name; */
1728 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1729 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1730 field_decl
1731 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1732 chainon (field_decl_chain, field_decl);
1734 /* struct objc_symtab *symtab; */
1736 decl_specs = get_identifier (UTAG_SYMTAB);
1737 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1738 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1739 field_decl
1740 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1741 chainon (field_decl_chain, field_decl);
1743 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1745 /* Create an instance of "objc_module". */
1747 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1748 build_tree_list (NULL_TREE,
1749 ridpointers[(int) RID_STATIC]));
1751 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1752 decl_specs, 1, NULL_TREE, NULL_TREE);
1754 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1755 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1756 finish_decl (UOBJC_MODULES_decl,
1757 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1758 NULL_TREE);
1760 /* Mark the decl to avoid "defined but not used" warning. */
1761 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1763 /* Generate a constructor call for the module descriptor.
1764 This code was generated by reading the grammar rules
1765 of c-parse.in; Therefore, it may not be the most efficient
1766 way of generating the requisite code. */
1768 if (flag_next_runtime)
1769 return 0;
1772 tree parms, function_decl, decelerator, void_list_node;
1773 tree function_type;
1774 tree init_function_name = get_file_function_name ('I');
1776 /* Declare void __objc_execClass (void *); */
1778 void_list_node = build_tree_list (NULL_TREE, void_type_node);
1779 function_type
1780 = build_function_type (void_type_node,
1781 tree_cons (NULL_TREE, ptr_type_node,
1782 void_list_node));
1783 function_decl = build_decl (FUNCTION_DECL,
1784 get_identifier (TAG_EXECCLASS),
1785 function_type);
1786 DECL_EXTERNAL (function_decl) = 1;
1787 DECL_ARTIFICIAL (function_decl) = 1;
1788 TREE_PUBLIC (function_decl) = 1;
1790 pushdecl (function_decl);
1791 rest_of_decl_compilation (function_decl, 0, 0, 0);
1793 parms
1794 = build_tree_list (NULL_TREE,
1795 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1796 decelerator = build_function_call (function_decl, parms);
1798 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1800 start_function (void_list_node,
1801 build_parse_node (CALL_EXPR, init_function_name,
1802 /* This has the format of the output
1803 of get_parm_info. */
1804 tree_cons (NULL_TREE, NULL_TREE,
1805 void_list_node),
1806 NULL_TREE),
1807 NULL_TREE, NULL_TREE, 0);
1808 #if 0 /* This should be turned back on later
1809 for the systems where collect is not needed. */
1810 /* Make these functions nonglobal
1811 so each file can use the same name. */
1812 TREE_PUBLIC (current_function_decl) = 0;
1813 #endif
1814 TREE_USED (current_function_decl) = 1;
1815 store_parm_decls ();
1817 assemble_external (function_decl);
1818 c_expand_expr_stmt (decelerator);
1820 TREE_PUBLIC (current_function_decl) = 1;
1822 function_decl = current_function_decl;
1823 finish_function (0);
1825 /* Return the name of the constructor function. */
1826 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1830 /* extern const char _OBJC_STRINGS[]; */
1832 static void
1833 generate_forward_declaration_to_string_table ()
1835 tree sc_spec, decl_specs, expr_decl;
1837 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1838 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1840 expr_decl
1841 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1843 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1846 /* Return the DECL of the string IDENT in the SECTION. */
1848 static tree
1849 get_objc_string_decl (ident, section)
1850 tree ident;
1851 enum string_section section;
1853 tree chain;
1855 if (section == class_names)
1856 chain = class_names_chain;
1857 else if (section == meth_var_names)
1858 chain = meth_var_names_chain;
1859 else if (section == meth_var_types)
1860 chain = meth_var_types_chain;
1861 else
1862 abort ();
1864 for (; chain != 0; chain = TREE_VALUE (chain))
1865 if (TREE_VALUE (chain) == ident)
1866 return (TREE_PURPOSE (chain));
1868 abort ();
1869 return NULL_TREE;
1872 /* Output references to all statically allocated objects. Return the DECL
1873 for the array built. */
1875 static void
1876 generate_static_references ()
1878 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1879 tree class_name, class, decl, initlist;
1880 tree cl_chain, in_chain, type;
1881 int num_inst, num_class;
1882 char buf[256];
1884 if (flag_next_runtime)
1885 abort ();
1887 for (cl_chain = objc_static_instances, num_class = 0;
1888 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1890 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1891 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1893 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1894 ident = get_identifier (buf);
1896 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1897 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1898 build_tree_list (NULL_TREE,
1899 ridpointers[(int) RID_STATIC]));
1900 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1901 DECL_CONTEXT (decl) = 0;
1902 DECL_ARTIFICIAL (decl) = 1;
1904 /* Output {class_name, ...}. */
1905 class = TREE_VALUE (cl_chain);
1906 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1907 initlist = build_tree_list (NULL_TREE,
1908 build_unary_op (ADDR_EXPR, class_name, 1));
1910 /* Output {..., instance, ...}. */
1911 for (in_chain = TREE_PURPOSE (cl_chain);
1912 in_chain; in_chain = TREE_CHAIN (in_chain))
1914 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1915 initlist = tree_cons (NULL_TREE, expr, initlist);
1918 /* Output {..., NULL}. */
1919 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1921 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1922 finish_decl (decl, expr, NULL_TREE);
1923 TREE_USED (decl) = 1;
1925 type = build_array_type (build_pointer_type (void_type_node), 0);
1926 decl = build_decl (VAR_DECL, ident, type);
1927 make_decl_rtl (decl, 0, 1);
1928 TREE_USED (decl) = 1;
1929 decls
1930 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1933 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1934 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1935 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1936 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1937 build_tree_list (NULL_TREE,
1938 ridpointers[(int) RID_STATIC]));
1939 static_instances_decl
1940 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1941 TREE_USED (static_instances_decl) = 1;
1942 DECL_CONTEXT (static_instances_decl) = 0;
1943 DECL_ARTIFICIAL (static_instances_decl) = 1;
1944 end_temporary_allocation ();
1945 expr = build_constructor (TREE_TYPE (static_instances_decl),
1946 nreverse (decls));
1947 finish_decl (static_instances_decl, expr, NULL_TREE);
1950 /* Output all strings. */
1952 static void
1953 generate_strings ()
1955 tree sc_spec, decl_specs, expr_decl;
1956 tree chain, string_expr;
1957 tree string, decl;
1959 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1961 string = TREE_VALUE (chain);
1962 decl = TREE_PURPOSE (chain);
1963 sc_spec
1964 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1965 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1966 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1967 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1968 end_temporary_allocation ();
1969 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1970 IDENTIFIER_POINTER (string));
1971 finish_decl (decl, string_expr, NULL_TREE);
1974 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1976 string = TREE_VALUE (chain);
1977 decl = TREE_PURPOSE (chain);
1978 sc_spec
1979 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1980 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1981 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1982 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1983 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1984 IDENTIFIER_POINTER (string));
1985 finish_decl (decl, string_expr, NULL_TREE);
1988 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1990 string = TREE_VALUE (chain);
1991 decl = TREE_PURPOSE (chain);
1992 sc_spec
1993 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1994 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1995 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1996 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1997 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1998 IDENTIFIER_POINTER (string));
1999 finish_decl (decl, string_expr, NULL_TREE);
2003 static tree
2004 build_selector_reference_decl (name)
2005 tree name;
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 (ident);
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 (name)
2238 tree name;
2240 tree decl, ident;
2241 char buf[256];
2242 static int idx = 0;
2244 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2246 push_obstacks_nochange ();
2247 end_temporary_allocation ();
2249 ident = get_identifier (buf);
2251 decl = build_decl (VAR_DECL, ident, objc_class_type);
2252 DECL_EXTERNAL (decl) = 1;
2253 TREE_PUBLIC (decl) = 1;
2254 TREE_USED (decl) = 1;
2255 TREE_READONLY (decl) = 1;
2256 DECL_CONTEXT (decl) = 0;
2257 DECL_ARTIFICIAL (decl) = 1;
2259 make_decl_rtl (decl, 0, 1);
2260 pushdecl_top_level (decl);
2262 pop_obstacks ();
2264 return decl;
2267 /* Create a class reference, but don't create a variable to reference
2268 it. */
2270 static void
2271 add_class_reference (ident)
2272 tree ident;
2274 tree chain;
2276 if ((chain = cls_ref_chain))
2278 tree tail;
2281 if (ident == TREE_VALUE (chain))
2282 return;
2284 tail = chain;
2285 chain = TREE_CHAIN (chain);
2287 while (chain);
2289 /* Append to the end of the list */
2290 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2292 else
2293 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2296 /* Get a class reference, creating it if necessary. Also create the
2297 reference variable. */
2299 tree
2300 get_class_reference (ident)
2301 tree ident;
2303 if (flag_next_runtime)
2305 tree *chain;
2306 tree decl;
2308 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2309 if (TREE_VALUE (*chain) == ident)
2311 if (! TREE_PURPOSE (*chain))
2312 TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
2314 return TREE_PURPOSE (*chain);
2317 decl = build_class_reference_decl (ident);
2318 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2319 return decl;
2321 else
2323 tree params;
2325 add_class_reference (ident);
2327 params = build_tree_list (NULL_TREE,
2328 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2329 IDENTIFIER_POINTER (ident)));
2331 assemble_external (objc_get_class_decl);
2332 return build_function_call (objc_get_class_decl, params);
2336 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2337 of identifier_node that represent the selector. It returns the
2338 offset of the selector from the beginning of the _OBJC_STRINGS
2339 pool. This offset is typically used by init_selector during code
2340 generation.
2342 For each string section we have a chain which maps identifier nodes
2343 to decls for the strings. */
2345 static tree
2346 add_objc_string (ident, section)
2347 tree ident;
2348 enum string_section section;
2350 tree *chain, decl;
2352 if (section == class_names)
2353 chain = &class_names_chain;
2354 else if (section == meth_var_names)
2355 chain = &meth_var_names_chain;
2356 else if (section == meth_var_types)
2357 chain = &meth_var_types_chain;
2358 else
2359 abort ();
2361 while (*chain)
2363 if (TREE_VALUE (*chain) == ident)
2364 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2366 chain = &TREE_CHAIN (*chain);
2369 decl = build_objc_string_decl (ident, section);
2371 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2373 return build_unary_op (ADDR_EXPR, decl, 1);
2376 static tree
2377 build_objc_string_decl (name, section)
2378 tree name;
2379 enum string_section section;
2381 tree decl, ident;
2382 char buf[256];
2383 static int class_names_idx = 0;
2384 static int meth_var_names_idx = 0;
2385 static int meth_var_types_idx = 0;
2387 if (section == class_names)
2388 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2389 else if (section == meth_var_names)
2390 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2391 else if (section == meth_var_types)
2392 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2394 push_obstacks_nochange ();
2395 end_temporary_allocation ();
2396 ident = get_identifier (buf);
2398 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2399 DECL_EXTERNAL (decl) = 1;
2400 TREE_PUBLIC (decl) = 1;
2401 TREE_USED (decl) = 1;
2402 TREE_READONLY (decl) = 1;
2403 TREE_CONSTANT (decl) = 1;
2404 DECL_CONTEXT (decl) = 0;
2405 DECL_ARTIFICIAL (decl) = 1;
2407 make_decl_rtl (decl, 0, 1);
2408 pushdecl_top_level (decl);
2410 pop_obstacks ();
2412 return decl;
2416 void
2417 objc_declare_alias (alias_ident, class_ident)
2418 tree alias_ident;
2419 tree class_ident;
2421 if (!doing_objc_thang)
2422 objc_fatal ();
2424 if (is_class_name (class_ident) != class_ident)
2425 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2426 else if (is_class_name (alias_ident))
2427 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2428 else
2429 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2432 void
2433 objc_declare_class (ident_list)
2434 tree ident_list;
2436 tree list;
2438 if (!doing_objc_thang)
2439 objc_fatal ();
2441 for (list = ident_list; list; list = TREE_CHAIN (list))
2443 tree ident = TREE_VALUE (list);
2444 tree decl;
2446 if ((decl = lookup_name (ident)))
2448 error ("`%s' redeclared as different kind of symbol",
2449 IDENTIFIER_POINTER (ident));
2450 error_with_decl (decl, "previous declaration of `%s'");
2453 if (! is_class_name (ident))
2455 tree record = xref_tag (RECORD_TYPE, ident);
2456 TREE_STATIC_TEMPLATE (record) = 1;
2457 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2462 tree
2463 is_class_name (ident)
2464 tree ident;
2466 tree chain;
2468 if (lookup_interface (ident))
2469 return ident;
2471 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2473 if (ident == TREE_VALUE (chain))
2474 return ident;
2477 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2479 if (ident == TREE_VALUE (chain))
2480 return TREE_PURPOSE (chain);
2483 return 0;
2486 tree
2487 lookup_interface (ident)
2488 tree ident;
2490 tree chain;
2492 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2494 if (ident == CLASS_NAME (chain))
2495 return chain;
2497 return NULL_TREE;
2500 static tree
2501 objc_copy_list (list, head)
2502 tree list;
2503 tree *head;
2505 tree newlist = NULL_TREE, tail = NULL_TREE;
2507 while (list)
2509 tail = copy_node (list);
2511 /* The following statement fixes a bug when inheriting instance
2512 variables that are declared to be bitfields. finish_struct
2513 expects to find the width of the bitfield in DECL_INITIAL,
2514 which it nulls out after processing the decl of the super
2515 class...rather than change the way finish_struct works (which
2516 is risky), I create the situation it expects...s.naroff
2517 (7/23/89). */
2519 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2520 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2522 newlist = chainon (newlist, tail);
2523 list = TREE_CHAIN (list);
2526 *head = newlist;
2527 return tail;
2530 /* Used by: build_private_template, get_class_ivars, and
2531 continue_class. COPY is 1 when called from @defs. In this case
2532 copy all fields. Otherwise don't copy leaf ivars since we rely on
2533 them being side-effected exactly once by finish_struct. */
2535 static tree
2536 build_ivar_chain (interface, copy)
2537 tree interface;
2538 int copy;
2540 tree my_name, super_name, ivar_chain;
2542 my_name = CLASS_NAME (interface);
2543 super_name = CLASS_SUPER_NAME (interface);
2545 /* Possibly copy leaf ivars. */
2546 if (copy)
2547 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2548 else
2549 ivar_chain = CLASS_IVARS (interface);
2551 while (super_name)
2553 tree op1;
2554 tree super_interface = lookup_interface (super_name);
2556 if (!super_interface)
2558 /* fatal did not work with 2 args...should fix */
2559 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2560 IDENTIFIER_POINTER (super_name),
2561 IDENTIFIER_POINTER (my_name));
2562 exit (FATAL_EXIT_CODE);
2565 if (super_interface == interface)
2567 fatal ("Circular inheritance in interface declaration for `%s'",
2568 IDENTIFIER_POINTER (super_name));
2571 interface = super_interface;
2572 my_name = CLASS_NAME (interface);
2573 super_name = CLASS_SUPER_NAME (interface);
2575 op1 = CLASS_IVARS (interface);
2576 if (op1)
2578 tree head, tail = objc_copy_list (op1, &head);
2580 /* Prepend super class ivars...make a copy of the list, we
2581 do not want to alter the original. */
2582 TREE_CHAIN (tail) = ivar_chain;
2583 ivar_chain = head;
2586 return ivar_chain;
2589 /* struct <classname> {
2590 struct objc_class *isa;
2592 }; */
2594 static tree
2595 build_private_template (class)
2596 tree class;
2598 tree ivar_context;
2600 if (CLASS_STATIC_TEMPLATE (class))
2602 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2603 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2605 else
2607 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2609 ivar_context = build_ivar_chain (class, 0);
2611 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2613 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2615 /* mark this record as class template - for class type checking */
2616 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2619 instance_type
2620 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2621 uprivate_record),
2622 build1 (INDIRECT_REF, NULL_TREE,
2623 NULL_TREE)));
2625 return ivar_context;
2628 /* Begin code generation for protocols... */
2630 /* struct objc_protocol {
2631 char *protocol_name;
2632 struct objc_protocol **protocol_list;
2633 struct objc_method_desc *instance_methods;
2634 struct objc_method_desc *class_methods;
2635 }; */
2637 static tree
2638 build_protocol_template ()
2640 tree decl_specs, field_decl, field_decl_chain;
2641 tree template;
2643 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2645 /* struct objc_class *isa; */
2647 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2648 get_identifier (UTAG_CLASS)));
2649 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2650 field_decl
2651 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2652 field_decl_chain = field_decl;
2654 /* char *protocol_name; */
2656 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2657 field_decl
2658 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2659 field_decl
2660 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2661 chainon (field_decl_chain, field_decl);
2663 /* struct objc_protocol **protocol_list; */
2665 decl_specs = build_tree_list (NULL_TREE, template);
2666 field_decl
2667 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2668 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2669 field_decl
2670 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2671 chainon (field_decl_chain, field_decl);
2673 /* struct objc_method_list *instance_methods; */
2675 decl_specs
2676 = build_tree_list (NULL_TREE,
2677 xref_tag (RECORD_TYPE,
2678 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2679 field_decl
2680 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2681 field_decl
2682 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2683 chainon (field_decl_chain, field_decl);
2685 /* struct objc_method_list *class_methods; */
2687 decl_specs
2688 = build_tree_list (NULL_TREE,
2689 xref_tag (RECORD_TYPE,
2690 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2691 field_decl
2692 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2693 field_decl
2694 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2695 chainon (field_decl_chain, field_decl);
2697 return finish_struct (template, field_decl_chain, NULL_TREE);
2700 static tree
2701 build_descriptor_table_initializer (type, entries)
2702 tree type;
2703 tree entries;
2705 tree initlist = NULL_TREE;
2709 tree eltlist = NULL_TREE;
2711 eltlist
2712 = tree_cons (NULL_TREE,
2713 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2714 eltlist
2715 = tree_cons (NULL_TREE,
2716 add_objc_string (METHOD_ENCODING (entries),
2717 meth_var_types),
2718 eltlist);
2720 initlist
2721 = tree_cons (NULL_TREE,
2722 build_constructor (type, nreverse (eltlist)), initlist);
2724 entries = TREE_CHAIN (entries);
2726 while (entries);
2728 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2731 /* struct objc_method_prototype_list {
2732 int count;
2733 struct objc_method_prototype {
2734 SEL name;
2735 char *types;
2736 } list[1];
2737 }; */
2739 static tree
2740 build_method_prototype_list_template (list_type, size)
2741 tree list_type;
2742 int size;
2744 tree objc_ivar_list_record;
2745 tree decl_specs, field_decl, field_decl_chain;
2747 /* Generate an unnamed struct definition. */
2749 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2751 /* int method_count; */
2753 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2754 field_decl = get_identifier ("method_count");
2756 field_decl
2757 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2758 field_decl_chain = field_decl;
2760 /* struct objc_method method_list[]; */
2762 decl_specs = build_tree_list (NULL_TREE, list_type);
2763 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2764 build_int_2 (size, 0));
2766 field_decl
2767 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2768 chainon (field_decl_chain, field_decl);
2770 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2772 return objc_ivar_list_record;
2775 static tree
2776 build_method_prototype_template ()
2778 tree proto_record;
2779 tree decl_specs, field_decl, field_decl_chain;
2781 proto_record
2782 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2784 #ifdef OBJC_INT_SELECTORS
2785 /* unsigned int _cmd; */
2786 decl_specs
2787 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2788 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2789 field_decl = get_identifier ("_cmd");
2790 #else /* OBJC_INT_SELECTORS */
2791 /* struct objc_selector *_cmd; */
2792 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2793 get_identifier (TAG_SELECTOR)), NULL_TREE);
2794 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2795 #endif /* OBJC_INT_SELECTORS */
2797 field_decl
2798 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2799 field_decl_chain = field_decl;
2801 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2802 field_decl
2803 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2804 field_decl
2805 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2806 chainon (field_decl_chain, field_decl);
2808 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2810 return proto_record;
2813 /* True if last call to forwarding_offset yielded a register offset. */
2814 static int offset_is_register;
2816 static int
2817 forwarding_offset (parm)
2818 tree parm;
2820 int offset_in_bytes;
2822 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2824 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2826 /* ??? Here we assume that the parm address is indexed
2827 off the frame pointer or arg pointer.
2828 If that is not true, we produce meaningless results,
2829 but do not crash. */
2830 if (GET_CODE (addr) == PLUS
2831 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2832 offset_in_bytes = INTVAL (XEXP (addr, 1));
2833 else
2834 offset_in_bytes = 0;
2836 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2837 offset_is_register = 0;
2839 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2841 int regno = REGNO (DECL_INCOMING_RTL (parm));
2842 offset_in_bytes = apply_args_register_offset (regno);
2843 offset_is_register = 1;
2845 else
2846 return 0;
2848 /* This is the case where the parm is passed as an int or double
2849 and it is converted to a char, short or float and stored back
2850 in the parmlist. In this case, describe the parm
2851 with the variable's declared type, and adjust the address
2852 if the least significant bytes (which we are using) are not
2853 the first ones. */
2854 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2855 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2856 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2858 return offset_in_bytes;
2861 static tree
2862 encode_method_prototype (method_decl, func_decl)
2863 tree method_decl;
2864 tree func_decl;
2866 tree parms;
2867 int stack_size, i;
2868 tree user_args;
2869 int max_parm_end = 0;
2870 char buf[40];
2871 tree result;
2873 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2874 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2876 /* C type. */
2877 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2878 obstack_object_size (&util_obstack),
2879 OBJC_ENCODE_INLINE_DEFS);
2881 /* Stack size. */
2882 for (parms = DECL_ARGUMENTS (func_decl); parms;
2883 parms = TREE_CHAIN (parms))
2885 int parm_end = (forwarding_offset (parms)
2886 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2887 / BITS_PER_UNIT));
2889 if (!offset_is_register && max_parm_end < parm_end)
2890 max_parm_end = parm_end;
2893 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2895 sprintf (buf, "%d", stack_size);
2896 obstack_grow (&util_obstack, buf, strlen (buf));
2898 user_args = METHOD_SEL_ARGS (method_decl);
2900 /* Argument types. */
2901 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2902 parms = TREE_CHAIN (parms), i++)
2904 /* Process argument qualifiers for user supplied arguments. */
2905 if (i > 1)
2907 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2908 user_args = TREE_CHAIN (user_args);
2911 /* Type. */
2912 encode_type (TREE_TYPE (parms),
2913 obstack_object_size (&util_obstack),
2914 OBJC_ENCODE_INLINE_DEFS);
2916 /* Compute offset. */
2917 sprintf (buf, "%d", forwarding_offset (parms));
2919 /* Indicate register. */
2920 if (offset_is_register)
2921 obstack_1grow (&util_obstack, '+');
2923 obstack_grow (&util_obstack, buf, strlen (buf));
2926 obstack_1grow (&util_obstack, '\0');
2927 result = get_identifier (obstack_finish (&util_obstack));
2928 obstack_free (&util_obstack, util_firstobj);
2929 return result;
2932 static tree
2933 generate_descriptor_table (type, name, size, list, proto)
2934 tree type;
2935 char *name;
2936 int size;
2937 tree list;
2938 tree proto;
2940 tree sc_spec, decl_specs, decl, initlist;
2942 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2943 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2945 decl = start_decl (synth_id_with_class_suffix (name, proto),
2946 decl_specs, 1, NULL_TREE, NULL_TREE);
2948 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2949 initlist = tree_cons (NULL_TREE, list, initlist);
2951 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2952 NULL_TREE);
2954 return decl;
2957 static void
2958 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2959 tree protocol;
2961 static tree objc_method_prototype_template;
2962 tree initlist, chain, method_list_template;
2963 tree cast, variable_length_type;
2964 int size;
2966 if (!objc_method_prototype_template)
2967 objc_method_prototype_template = build_method_prototype_template ();
2969 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2970 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2971 NULL_TREE);
2972 variable_length_type = groktypename (cast);
2974 chain = PROTOCOL_CLS_METHODS (protocol);
2975 if (chain)
2977 size = list_length (chain);
2979 method_list_template
2980 = build_method_prototype_list_template (objc_method_prototype_template,
2981 size);
2983 initlist
2984 = build_descriptor_table_initializer (objc_method_prototype_template,
2985 chain);
2987 UOBJC_CLASS_METHODS_decl
2988 = generate_descriptor_table (method_list_template,
2989 "_OBJC_PROTOCOL_CLASS_METHODS",
2990 size, initlist, protocol);
2991 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2993 else
2994 UOBJC_CLASS_METHODS_decl = 0;
2996 chain = PROTOCOL_NST_METHODS (protocol);
2997 if (chain)
2999 size = list_length (chain);
3001 method_list_template
3002 = build_method_prototype_list_template (objc_method_prototype_template,
3003 size);
3004 initlist
3005 = build_descriptor_table_initializer (objc_method_prototype_template,
3006 chain);
3008 UOBJC_INSTANCE_METHODS_decl
3009 = generate_descriptor_table (method_list_template,
3010 "_OBJC_PROTOCOL_INSTANCE_METHODS",
3011 size, initlist, protocol);
3012 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3014 else
3015 UOBJC_INSTANCE_METHODS_decl = 0;
3018 static tree
3019 build_tmp_function_decl ()
3021 tree decl_specs, expr_decl, parms;
3022 static int xxx = 0;
3023 char buffer[80];
3025 /* struct objc_object *objc_xxx (id, SEL, ...); */
3026 pushlevel (0);
3027 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3028 push_parm_decl (build_tree_list
3029 (build_tree_list (decl_specs,
3030 build1 (INDIRECT_REF, NULL_TREE,
3031 NULL_TREE)),
3032 build_tree_list (NULL_TREE, NULL_TREE)));
3034 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3035 get_identifier (TAG_SELECTOR)));
3036 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
3038 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
3039 build_tree_list (NULL_TREE, NULL_TREE)));
3040 parms = get_parm_info (0);
3041 poplevel (0, 0, 0);
3043 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3044 sprintf (buffer, "__objc_tmp_%x", xxx++);
3045 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
3046 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
3048 return define_decl (expr_decl, decl_specs);
3051 static void
3052 hack_method_prototype (nst_methods, tmp_decl)
3053 tree nst_methods;
3054 tree tmp_decl;
3056 tree parms;
3057 tree parm;
3059 /* Hack to avoid problem with static typing of self arg. */
3060 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
3061 start_method_def (nst_methods);
3062 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
3064 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
3065 parms = get_parm_info (0); /* we have a `, ...' */
3066 else
3067 parms = get_parm_info (1); /* place a `void_at_end' */
3069 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
3071 /* Usually called from store_parm_decls -> init_function_start. */
3073 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
3074 current_function_decl = tmp_decl;
3077 /* Code taken from start_function. */
3078 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3079 /* Promote the value to int before returning it. */
3080 if (TREE_CODE (restype) == INTEGER_TYPE
3081 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3082 restype = integer_type_node;
3083 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3086 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3087 DECL_CONTEXT (parm) = tmp_decl;
3089 init_function_start (tmp_decl, "objc-act", 0);
3091 /* Typically called from expand_function_start for function definitions. */
3092 assign_parms (tmp_decl, 0);
3094 /* install return type */
3095 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3099 static void
3100 generate_protocol_references (plist)
3101 tree plist;
3103 tree lproto;
3105 /* Forward declare protocols referenced. */
3106 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3108 tree proto = TREE_VALUE (lproto);
3110 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3111 && PROTOCOL_NAME (proto))
3113 if (! PROTOCOL_FORWARD_DECL (proto))
3114 build_protocol_reference (proto);
3116 if (PROTOCOL_LIST (proto))
3117 generate_protocol_references (PROTOCOL_LIST (proto));
3122 static void
3123 generate_protocols ()
3125 tree p, tmp_decl, encoding;
3126 tree sc_spec, decl_specs, decl;
3127 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3128 tree cast_type2 = 0;
3130 tmp_decl = build_tmp_function_decl ();
3132 if (! objc_protocol_template)
3133 objc_protocol_template = build_protocol_template ();
3135 /* If a protocol was directly referenced, pull in indirect references. */
3136 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3137 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3138 generate_protocol_references (PROTOCOL_LIST (p));
3140 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3142 tree nst_methods = PROTOCOL_NST_METHODS (p);
3143 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3145 /* If protocol wasn't referenced, don't generate any code. */
3146 if (! PROTOCOL_FORWARD_DECL (p))
3147 continue;
3149 /* Make sure we link in the Protocol class. */
3150 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3152 while (nst_methods)
3154 if (! METHOD_ENCODING (nst_methods))
3156 hack_method_prototype (nst_methods, tmp_decl);
3157 encoding = encode_method_prototype (nst_methods, tmp_decl);
3158 METHOD_ENCODING (nst_methods) = encoding;
3160 nst_methods = TREE_CHAIN (nst_methods);
3163 while (cls_methods)
3165 if (! METHOD_ENCODING (cls_methods))
3167 hack_method_prototype (cls_methods, tmp_decl);
3168 encoding = encode_method_prototype (cls_methods, tmp_decl);
3169 METHOD_ENCODING (cls_methods) = encoding;
3172 cls_methods = TREE_CHAIN (cls_methods);
3174 generate_method_descriptors (p);
3176 if (PROTOCOL_LIST (p))
3177 refs_decl = generate_protocol_list (p);
3178 else
3179 refs_decl = 0;
3181 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3183 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3184 NULL_TREE);
3185 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3187 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3188 decl_specs, 1, NULL_TREE, NULL_TREE);
3190 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3192 if (refs_decl)
3194 if (!cast_type2)
3195 cast_type2
3196 = groktypename
3197 (build_tree_list (build_tree_list (NULL_TREE,
3198 objc_protocol_template),
3199 build1 (INDIRECT_REF, NULL_TREE,
3200 build1 (INDIRECT_REF, NULL_TREE,
3201 NULL_TREE))));
3203 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3204 TREE_TYPE (refs_expr) = cast_type2;
3206 else
3207 refs_expr = build_int_2 (0, 0);
3209 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3210 by generate_method_descriptors, which is called above. */
3211 initlist = build_protocol_initializer (TREE_TYPE (decl),
3212 protocol_name_expr, refs_expr,
3213 UOBJC_INSTANCE_METHODS_decl,
3214 UOBJC_CLASS_METHODS_decl);
3215 finish_decl (decl, initlist, NULL_TREE);
3217 /* Mark the decl as used to avoid "defined but not used" warning. */
3218 TREE_USED (decl) = 1;
3222 static tree
3223 build_protocol_initializer (type, protocol_name, protocol_list,
3224 instance_methods, class_methods)
3225 tree type;
3226 tree protocol_name;
3227 tree protocol_list;
3228 tree instance_methods;
3229 tree class_methods;
3231 tree initlist = NULL_TREE, expr;
3232 static tree cast_type = 0;
3234 if (!cast_type)
3235 cast_type
3236 = groktypename
3237 (build_tree_list
3238 (build_tree_list (NULL_TREE,
3239 xref_tag (RECORD_TYPE,
3240 get_identifier (UTAG_CLASS))),
3241 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3243 /* Filling the "isa" in with one allows the runtime system to
3244 detect that the version change...should remove before final release. */
3246 expr = build_int_2 (PROTOCOL_VERSION, 0);
3247 TREE_TYPE (expr) = cast_type;
3248 initlist = tree_cons (NULL_TREE, expr, initlist);
3249 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3250 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3252 if (!instance_methods)
3253 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3254 else
3256 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3257 initlist = tree_cons (NULL_TREE, expr, initlist);
3260 if (!class_methods)
3261 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3262 else
3264 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3265 initlist = tree_cons (NULL_TREE, expr, initlist);
3268 return build_constructor (type, nreverse (initlist));
3271 /* struct objc_category {
3272 char *category_name;
3273 char *class_name;
3274 struct objc_method_list *instance_methods;
3275 struct objc_method_list *class_methods;
3276 struct objc_protocol_list *protocols;
3277 }; */
3279 static void
3280 build_category_template ()
3282 tree decl_specs, field_decl, field_decl_chain;
3284 objc_category_template = start_struct (RECORD_TYPE,
3285 get_identifier (UTAG_CATEGORY));
3286 /* char *category_name; */
3288 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3289 field_decl
3290 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3291 field_decl
3292 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3293 field_decl_chain = field_decl;
3295 /* char *class_name; */
3297 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3298 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3299 field_decl
3300 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3301 chainon (field_decl_chain, field_decl);
3303 /* struct objc_method_list *instance_methods; */
3305 decl_specs = build_tree_list (NULL_TREE,
3306 xref_tag (RECORD_TYPE,
3307 get_identifier (UTAG_METHOD_LIST)));
3308 field_decl
3309 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3310 field_decl
3311 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3312 chainon (field_decl_chain, field_decl);
3314 /* struct objc_method_list *class_methods; */
3316 decl_specs = build_tree_list (NULL_TREE,
3317 xref_tag (RECORD_TYPE,
3318 get_identifier (UTAG_METHOD_LIST)));
3319 field_decl
3320 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3321 field_decl
3322 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3323 chainon (field_decl_chain, field_decl);
3325 /* struct objc_protocol **protocol_list; */
3327 decl_specs = build_tree_list (NULL_TREE,
3328 xref_tag (RECORD_TYPE,
3329 get_identifier (UTAG_PROTOCOL)));
3330 field_decl
3331 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3332 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3333 field_decl
3334 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3335 chainon (field_decl_chain, field_decl);
3337 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3340 /* struct objc_selector {
3341 void *sel_id;
3342 char *sel_type;
3343 }; */
3345 static void
3346 build_selector_template ()
3349 tree decl_specs, field_decl, field_decl_chain;
3351 objc_selector_template
3352 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3354 /* void *sel_id; */
3356 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3357 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3358 field_decl
3359 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3360 field_decl_chain = field_decl;
3362 /* char *sel_type; */
3364 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3365 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3366 field_decl
3367 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3368 chainon (field_decl_chain, field_decl);
3370 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3373 /* struct objc_class {
3374 struct objc_class *isa;
3375 struct objc_class *super_class;
3376 char *name;
3377 long version;
3378 long info;
3379 long instance_size;
3380 struct objc_ivar_list *ivars;
3381 struct objc_method_list *methods;
3382 if (flag_next_runtime)
3383 struct objc_cache *cache;
3384 else {
3385 struct sarray *dtable;
3386 struct objc_class *subclass_list;
3387 struct objc_class *sibling_class;
3389 struct objc_protocol_list *protocols;
3390 void *gc_object_type;
3391 }; */
3393 static void
3394 build_class_template ()
3396 tree decl_specs, field_decl, field_decl_chain;
3398 objc_class_template
3399 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3401 /* struct objc_class *isa; */
3403 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3404 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3405 field_decl
3406 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3407 field_decl_chain = field_decl;
3409 /* struct objc_class *super_class; */
3411 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3412 field_decl
3413 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3414 field_decl
3415 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3416 chainon (field_decl_chain, field_decl);
3418 /* char *name; */
3420 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3421 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3422 field_decl
3423 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3424 chainon (field_decl_chain, field_decl);
3426 /* long version; */
3428 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3429 field_decl = get_identifier ("version");
3430 field_decl
3431 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3432 chainon (field_decl_chain, field_decl);
3434 /* long info; */
3436 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3437 field_decl = get_identifier ("info");
3438 field_decl
3439 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3440 chainon (field_decl_chain, field_decl);
3442 /* long instance_size; */
3444 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3445 field_decl = get_identifier ("instance_size");
3446 field_decl
3447 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3448 chainon (field_decl_chain, field_decl);
3450 /* struct objc_ivar_list *ivars; */
3452 decl_specs = build_tree_list (NULL_TREE,
3453 xref_tag (RECORD_TYPE,
3454 get_identifier (UTAG_IVAR_LIST)));
3455 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3456 field_decl
3457 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3458 chainon (field_decl_chain, field_decl);
3460 /* struct objc_method_list *methods; */
3462 decl_specs = build_tree_list (NULL_TREE,
3463 xref_tag (RECORD_TYPE,
3464 get_identifier (UTAG_METHOD_LIST)));
3465 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3466 field_decl
3467 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3468 chainon (field_decl_chain, field_decl);
3470 if (flag_next_runtime)
3472 /* struct objc_cache *cache; */
3474 decl_specs = build_tree_list (NULL_TREE,
3475 xref_tag (RECORD_TYPE,
3476 get_identifier ("objc_cache")));
3477 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3478 field_decl = grokfield (input_filename, lineno, field_decl,
3479 decl_specs, NULL_TREE);
3480 chainon (field_decl_chain, field_decl);
3482 else
3484 /* struct sarray *dtable; */
3486 decl_specs = build_tree_list (NULL_TREE,
3487 xref_tag (RECORD_TYPE,
3488 get_identifier ("sarray")));
3489 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3490 field_decl = grokfield (input_filename, lineno, field_decl,
3491 decl_specs, NULL_TREE);
3492 chainon (field_decl_chain, field_decl);
3494 /* struct objc_class *subclass_list; */
3496 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3497 field_decl
3498 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3499 field_decl = grokfield (input_filename, lineno, field_decl,
3500 decl_specs, NULL_TREE);
3501 chainon (field_decl_chain, field_decl);
3503 /* struct objc_class *sibling_class; */
3505 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3506 field_decl
3507 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3508 field_decl = grokfield (input_filename, lineno, field_decl,
3509 decl_specs, NULL_TREE);
3510 chainon (field_decl_chain, field_decl);
3513 /* struct objc_protocol **protocol_list; */
3515 decl_specs = build_tree_list (NULL_TREE,
3516 xref_tag (RECORD_TYPE,
3517 get_identifier (UTAG_PROTOCOL)));
3518 field_decl
3519 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3520 field_decl
3521 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3522 field_decl = grokfield (input_filename, lineno, field_decl,
3523 decl_specs, NULL_TREE);
3524 chainon (field_decl_chain, field_decl);
3526 /* void *sel_id; */
3528 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3529 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3530 field_decl
3531 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3532 chainon (field_decl_chain, field_decl);
3534 /* void *gc_object_type; */
3536 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3537 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3538 field_decl
3539 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3540 chainon (field_decl_chain, field_decl);
3542 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3545 /* Generate appropriate forward declarations for an implementation. */
3547 static void
3548 synth_forward_declarations ()
3550 tree sc_spec, decl_specs, an_id;
3552 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3554 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3556 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3557 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3558 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3559 TREE_USED (UOBJC_CLASS_decl) = 1;
3560 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3562 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3564 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3565 implementation_context);
3567 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3568 TREE_USED (UOBJC_METACLASS_decl) = 1;
3569 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3571 /* Pre-build the following entities - for speed/convenience. */
3573 an_id = get_identifier ("super_class");
3574 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3575 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3578 static void
3579 error_with_ivar (message, decl, rawdecl)
3580 char *message;
3581 tree decl;
3582 tree rawdecl;
3584 count_error (0);
3586 report_error_function (DECL_SOURCE_FILE (decl));
3588 fprintf (stderr, "%s:%d: ",
3589 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3590 bzero (errbuf, BUFSIZE);
3591 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3594 #define USERTYPE(t) \
3595 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3596 || TREE_CODE (t) == ENUMERAL_TYPE)
3598 static void
3599 check_ivars (inter, imp)
3600 tree inter;
3601 tree imp;
3603 tree intdecls = CLASS_IVARS (inter);
3604 tree impdecls = CLASS_IVARS (imp);
3605 tree rawintdecls = CLASS_RAW_IVARS (inter);
3606 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3608 while (1)
3610 tree t1, t2;
3612 if (intdecls == 0 && impdecls == 0)
3613 break;
3614 if (intdecls == 0 || impdecls == 0)
3616 error ("inconsistent instance variable specification");
3617 break;
3620 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3622 if (!comptypes (t1, t2))
3624 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3626 error_with_ivar ("conflicting instance variable type",
3627 impdecls, rawimpdecls);
3628 error_with_ivar ("previous declaration of",
3629 intdecls, rawintdecls);
3631 else /* both the type and the name don't match */
3633 error ("inconsistent instance variable specification");
3634 break;
3638 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3640 error_with_ivar ("conflicting instance variable name",
3641 impdecls, rawimpdecls);
3642 error_with_ivar ("previous declaration of",
3643 intdecls, rawintdecls);
3646 intdecls = TREE_CHAIN (intdecls);
3647 impdecls = TREE_CHAIN (impdecls);
3648 rawintdecls = TREE_CHAIN (rawintdecls);
3649 rawimpdecls = TREE_CHAIN (rawimpdecls);
3653 /* Set super_type to the data type node for struct objc_super *,
3654 first defining struct objc_super itself.
3655 This needs to be done just once per compilation. */
3657 static tree
3658 build_super_template ()
3660 tree record, decl_specs, field_decl, field_decl_chain;
3662 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3664 /* struct objc_object *self; */
3666 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3667 field_decl = get_identifier ("self");
3668 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3669 field_decl = grokfield (input_filename, lineno,
3670 field_decl, decl_specs, NULL_TREE);
3671 field_decl_chain = field_decl;
3673 /* struct objc_class *class; */
3675 decl_specs = get_identifier (UTAG_CLASS);
3676 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3677 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3679 field_decl = grokfield (input_filename, lineno,
3680 field_decl, decl_specs, NULL_TREE);
3681 chainon (field_decl_chain, field_decl);
3683 finish_struct (record, field_decl_chain, NULL_TREE);
3685 /* `struct objc_super *' */
3686 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3687 record),
3688 build1 (INDIRECT_REF,
3689 NULL_TREE, NULL_TREE)));
3690 return record;
3693 /* struct objc_ivar {
3694 char *ivar_name;
3695 char *ivar_type;
3696 int ivar_offset;
3697 }; */
3699 static tree
3700 build_ivar_template ()
3702 tree objc_ivar_id, objc_ivar_record;
3703 tree decl_specs, field_decl, field_decl_chain;
3705 objc_ivar_id = get_identifier (UTAG_IVAR);
3706 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3708 /* char *ivar_name; */
3710 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3711 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3713 field_decl = grokfield (input_filename, lineno, field_decl,
3714 decl_specs, NULL_TREE);
3715 field_decl_chain = field_decl;
3717 /* char *ivar_type; */
3719 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3720 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3722 field_decl = grokfield (input_filename, lineno, field_decl,
3723 decl_specs, NULL_TREE);
3724 chainon (field_decl_chain, field_decl);
3726 /* int ivar_offset; */
3728 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3729 field_decl = get_identifier ("ivar_offset");
3731 field_decl = grokfield (input_filename, lineno, field_decl,
3732 decl_specs, NULL_TREE);
3733 chainon (field_decl_chain, field_decl);
3735 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3737 return objc_ivar_record;
3740 /* struct {
3741 int ivar_count;
3742 struct objc_ivar ivar_list[ivar_count];
3743 }; */
3745 static tree
3746 build_ivar_list_template (list_type, size)
3747 tree list_type;
3748 int size;
3750 tree objc_ivar_list_record;
3751 tree decl_specs, field_decl, field_decl_chain;
3753 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3755 /* int ivar_count; */
3757 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3758 field_decl = get_identifier ("ivar_count");
3760 field_decl = grokfield (input_filename, lineno, field_decl,
3761 decl_specs, NULL_TREE);
3762 field_decl_chain = field_decl;
3764 /* struct objc_ivar ivar_list[]; */
3766 decl_specs = build_tree_list (NULL_TREE, list_type);
3767 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3768 build_int_2 (size, 0));
3770 field_decl = grokfield (input_filename, lineno,
3771 field_decl, decl_specs, NULL_TREE);
3772 chainon (field_decl_chain, field_decl);
3774 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3776 return objc_ivar_list_record;
3779 /* struct {
3780 int method_next;
3781 int method_count;
3782 struct objc_method method_list[method_count];
3783 }; */
3785 static tree
3786 build_method_list_template (list_type, size)
3787 tree list_type;
3788 int size;
3790 tree objc_ivar_list_record;
3791 tree decl_specs, field_decl, field_decl_chain;
3793 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3795 /* int method_next; */
3797 decl_specs
3798 = build_tree_list
3799 (NULL_TREE,
3800 xref_tag (RECORD_TYPE,
3801 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3802 field_decl
3803 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3804 field_decl = grokfield (input_filename, lineno, field_decl,
3805 decl_specs, NULL_TREE);
3806 field_decl_chain = field_decl;
3808 /* int method_count; */
3810 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3811 field_decl = get_identifier ("method_count");
3813 field_decl = grokfield (input_filename, lineno,
3814 field_decl, decl_specs, NULL_TREE);
3815 chainon (field_decl_chain, field_decl);
3817 /* struct objc_method method_list[]; */
3819 decl_specs = build_tree_list (NULL_TREE, list_type);
3820 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3821 build_int_2 (size, 0));
3823 field_decl = grokfield (input_filename, lineno,
3824 field_decl, decl_specs, NULL_TREE);
3825 chainon (field_decl_chain, field_decl);
3827 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3829 return objc_ivar_list_record;
3832 static tree
3833 build_ivar_list_initializer (type, field_decl)
3834 tree type;
3835 tree field_decl;
3837 tree initlist = NULL_TREE;
3841 tree ivar = NULL_TREE;
3843 /* Set name. */
3844 if (DECL_NAME (field_decl))
3845 ivar = tree_cons (NULL_TREE,
3846 add_objc_string (DECL_NAME (field_decl),
3847 meth_var_names),
3848 ivar);
3849 else
3850 /* Unnamed bit-field ivar (yuck). */
3851 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3853 /* Set type. */
3854 encode_field_decl (field_decl,
3855 obstack_object_size (&util_obstack),
3856 OBJC_ENCODE_DONT_INLINE_DEFS);
3858 /* Null terminate string. */
3859 obstack_1grow (&util_obstack, 0);
3860 ivar
3861 = tree_cons
3862 (NULL_TREE,
3863 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3864 meth_var_types),
3865 ivar);
3866 obstack_free (&util_obstack, util_firstobj);
3868 /* set offset */
3869 ivar
3870 = tree_cons
3871 (NULL_TREE,
3872 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3873 / BITS_PER_UNIT),
3875 ivar);
3877 initlist = tree_cons (NULL_TREE,
3878 build_constructor (type, nreverse (ivar)),
3879 initlist);
3881 field_decl = TREE_CHAIN (field_decl);
3883 while (field_decl);
3885 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3888 static tree
3889 generate_ivars_list (type, name, size, list)
3890 tree type;
3891 char *name;
3892 int size;
3893 tree list;
3895 tree sc_spec, decl_specs, decl, initlist;
3897 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3898 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3900 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3901 decl_specs, 1, NULL_TREE, NULL_TREE);
3903 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3904 initlist = tree_cons (NULL_TREE, list, initlist);
3906 finish_decl (decl,
3907 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3908 NULL_TREE);
3910 return decl;
3913 static void
3914 generate_ivar_lists ()
3916 tree initlist, ivar_list_template, chain;
3917 tree cast, variable_length_type;
3918 int size;
3920 generating_instance_variables = 1;
3922 if (!objc_ivar_template)
3923 objc_ivar_template = build_ivar_template ();
3925 cast
3926 = build_tree_list
3927 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3928 get_identifier (UTAG_IVAR_LIST))),
3929 NULL_TREE);
3930 variable_length_type = groktypename (cast);
3932 /* Only generate class variables for the root of the inheritance
3933 hierarchy since these will be the same for every class. */
3935 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3936 && (chain = TYPE_FIELDS (objc_class_template)))
3938 size = list_length (chain);
3940 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3941 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3943 UOBJC_CLASS_VARIABLES_decl
3944 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3945 size, initlist);
3946 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3948 else
3949 UOBJC_CLASS_VARIABLES_decl = 0;
3951 chain = CLASS_IVARS (implementation_template);
3952 if (chain)
3954 size = list_length (chain);
3955 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3956 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3958 UOBJC_INSTANCE_VARIABLES_decl
3959 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3960 size, initlist);
3961 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3963 else
3964 UOBJC_INSTANCE_VARIABLES_decl = 0;
3966 generating_instance_variables = 0;
3969 static tree
3970 build_dispatch_table_initializer (type, entries)
3971 tree type;
3972 tree entries;
3974 tree initlist = NULL_TREE;
3978 tree elemlist = NULL_TREE;
3980 elemlist = tree_cons (NULL_TREE,
3981 build_selector (METHOD_SEL_NAME (entries)),
3982 NULL_TREE);
3984 elemlist = tree_cons (NULL_TREE,
3985 add_objc_string (METHOD_ENCODING (entries),
3986 meth_var_types),
3987 elemlist);
3989 elemlist = tree_cons (NULL_TREE,
3990 build_unary_op (ADDR_EXPR,
3991 METHOD_DEFINITION (entries), 1),
3992 elemlist);
3994 initlist = tree_cons (NULL_TREE,
3995 build_constructor (type, nreverse (elemlist)),
3996 initlist);
3998 entries = TREE_CHAIN (entries);
4000 while (entries);
4002 return build_constructor (build_array_type (type, 0), nreverse (initlist));
4005 /* To accomplish method prototyping without generating all kinds of
4006 inane warnings, the definition of the dispatch table entries were
4007 changed from:
4009 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4011 struct objc_method { SEL _cmd; ...; void *_imp; }; */
4013 static tree
4014 build_method_template ()
4016 tree _SLT_record;
4017 tree decl_specs, field_decl, field_decl_chain;
4019 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4021 #ifdef OBJC_INT_SELECTORS
4022 /* unsigned int _cmd; */
4023 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
4024 NULL_TREE);
4025 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
4026 field_decl = get_identifier ("_cmd");
4027 #else /* not OBJC_INT_SELECTORS */
4028 /* struct objc_selector *_cmd; */
4029 decl_specs = tree_cons (NULL_TREE,
4030 xref_tag (RECORD_TYPE,
4031 get_identifier (TAG_SELECTOR)),
4032 NULL_TREE);
4033 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4034 #endif /* not OBJC_INT_SELECTORS */
4036 field_decl = grokfield (input_filename, lineno, field_decl,
4037 decl_specs, NULL_TREE);
4038 field_decl_chain = field_decl;
4040 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4041 field_decl = build1 (INDIRECT_REF, NULL_TREE,
4042 get_identifier ("method_types"));
4043 field_decl = grokfield (input_filename, lineno, field_decl,
4044 decl_specs, NULL_TREE);
4045 chainon (field_decl_chain, field_decl);
4047 /* void *_imp; */
4049 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4050 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4051 field_decl = grokfield (input_filename, lineno, field_decl,
4052 decl_specs, NULL_TREE);
4053 chainon (field_decl_chain, field_decl);
4055 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4057 return _SLT_record;
4061 static tree
4062 generate_dispatch_table (type, name, size, list)
4063 tree type;
4064 char *name;
4065 int size;
4066 tree list;
4068 tree sc_spec, decl_specs, decl, initlist;
4070 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4071 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4073 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
4074 decl_specs, 1, NULL_TREE, NULL_TREE);
4076 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4077 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4078 initlist = tree_cons (NULL_TREE, list, initlist);
4080 finish_decl (decl,
4081 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4082 NULL_TREE);
4084 return decl;
4087 static void
4088 generate_dispatch_tables ()
4090 tree initlist, chain, method_list_template;
4091 tree cast, variable_length_type;
4092 int size;
4094 if (!objc_method_template)
4095 objc_method_template = build_method_template ();
4097 cast
4098 = build_tree_list
4099 (build_tree_list (NULL_TREE,
4100 xref_tag (RECORD_TYPE,
4101 get_identifier (UTAG_METHOD_LIST))),
4102 NULL_TREE);
4104 variable_length_type = groktypename (cast);
4106 chain = CLASS_CLS_METHODS (implementation_context);
4107 if (chain)
4109 size = list_length (chain);
4111 method_list_template
4112 = build_method_list_template (objc_method_template, size);
4113 initlist
4114 = build_dispatch_table_initializer (objc_method_template, chain);
4116 UOBJC_CLASS_METHODS_decl
4117 = generate_dispatch_table (method_list_template,
4118 ((TREE_CODE (implementation_context)
4119 == CLASS_IMPLEMENTATION_TYPE)
4120 ? "_OBJC_CLASS_METHODS"
4121 : "_OBJC_CATEGORY_CLASS_METHODS"),
4122 size, initlist);
4123 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4125 else
4126 UOBJC_CLASS_METHODS_decl = 0;
4128 chain = CLASS_NST_METHODS (implementation_context);
4129 if (chain)
4131 size = list_length (chain);
4133 method_list_template
4134 = build_method_list_template (objc_method_template, size);
4135 initlist
4136 = build_dispatch_table_initializer (objc_method_template, chain);
4138 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4139 UOBJC_INSTANCE_METHODS_decl
4140 = generate_dispatch_table (method_list_template,
4141 "_OBJC_INSTANCE_METHODS",
4142 size, initlist);
4143 else
4144 /* We have a category. */
4145 UOBJC_INSTANCE_METHODS_decl
4146 = generate_dispatch_table (method_list_template,
4147 "_OBJC_CATEGORY_INSTANCE_METHODS",
4148 size, initlist);
4149 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4151 else
4152 UOBJC_INSTANCE_METHODS_decl = 0;
4155 static tree
4156 generate_protocol_list (i_or_p)
4157 tree i_or_p;
4159 static tree cast_type = 0;
4160 tree initlist, decl_specs, sc_spec;
4161 tree refs_decl, expr_decl, lproto, e, plist;
4162 int size = 0;
4164 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4165 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4166 plist = CLASS_PROTOCOL_LIST (i_or_p);
4167 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4168 plist = PROTOCOL_LIST (i_or_p);
4169 else
4170 abort ();
4172 if (!cast_type)
4173 cast_type
4174 = groktypename
4175 (build_tree_list
4176 (build_tree_list (NULL_TREE,
4177 xref_tag (RECORD_TYPE,
4178 get_identifier (UTAG_PROTOCOL))),
4179 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4181 /* Compute size. */
4182 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4183 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4184 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4185 size++;
4187 /* Build initializer. */
4188 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4190 e = build_int_2 (size, 0);
4191 TREE_TYPE (e) = cast_type;
4192 initlist = tree_cons (NULL_TREE, e, initlist);
4194 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4196 tree pval = TREE_VALUE (lproto);
4198 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4199 && PROTOCOL_FORWARD_DECL (pval))
4201 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4202 initlist = tree_cons (NULL_TREE, e, initlist);
4206 /* static struct objc_protocol *refs[n]; */
4208 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4209 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4210 get_identifier (UTAG_PROTOCOL)),
4211 sc_spec);
4213 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4214 expr_decl = build_nt (ARRAY_REF,
4215 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4216 i_or_p),
4217 build_int_2 (size + 2, 0));
4218 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4219 expr_decl = build_nt (ARRAY_REF,
4220 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4221 i_or_p),
4222 build_int_2 (size + 2, 0));
4223 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4224 expr_decl
4225 = build_nt (ARRAY_REF,
4226 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4227 i_or_p),
4228 build_int_2 (size + 2, 0));
4229 else
4230 abort ();
4232 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4234 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4236 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4237 nreverse (initlist)),
4238 NULL_TREE);
4240 return refs_decl;
4243 static tree
4244 build_category_initializer (type, cat_name, class_name,
4245 instance_methods, class_methods, protocol_list)
4246 tree type;
4247 tree cat_name;
4248 tree class_name;
4249 tree instance_methods;
4250 tree class_methods;
4251 tree protocol_list;
4253 tree initlist = NULL_TREE, expr;
4255 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4256 initlist = tree_cons (NULL_TREE, class_name, initlist);
4258 if (!instance_methods)
4259 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4260 else
4262 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4263 initlist = tree_cons (NULL_TREE, expr, initlist);
4265 if (!class_methods)
4266 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4267 else
4269 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4270 initlist = tree_cons (NULL_TREE, expr, initlist);
4273 /* protocol_list = */
4274 if (!protocol_list)
4275 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4276 else
4278 static tree cast_type2;
4280 if (!cast_type2)
4281 cast_type2
4282 = groktypename
4283 (build_tree_list
4284 (build_tree_list (NULL_TREE,
4285 xref_tag (RECORD_TYPE,
4286 get_identifier (UTAG_PROTOCOL))),
4287 build1 (INDIRECT_REF, NULL_TREE,
4288 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4290 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4291 TREE_TYPE (expr) = cast_type2;
4292 initlist = tree_cons (NULL_TREE, expr, initlist);
4295 return build_constructor (type, nreverse (initlist));
4298 /* struct objc_class {
4299 struct objc_class *isa;
4300 struct objc_class *super_class;
4301 char *name;
4302 long version;
4303 long info;
4304 long instance_size;
4305 struct objc_ivar_list *ivars;
4306 struct objc_method_list *methods;
4307 if (flag_next_runtime)
4308 struct objc_cache *cache;
4309 else {
4310 struct sarray *dtable;
4311 struct objc_class *subclass_list;
4312 struct objc_class *sibling_class;
4314 struct objc_protocol_list *protocols;
4315 void *gc_object_type;
4316 }; */
4318 static tree
4319 build_shared_structure_initializer (type, isa, super, name, size, status,
4320 dispatch_table, ivar_list, protocol_list)
4321 tree type;
4322 tree isa;
4323 tree super;
4324 tree name;
4325 tree size;
4326 int status;
4327 tree dispatch_table;
4328 tree ivar_list;
4329 tree protocol_list;
4331 tree initlist = NULL_TREE, expr;
4333 /* isa = */
4334 initlist = tree_cons (NULL_TREE, isa, initlist);
4336 /* super_class = */
4337 initlist = tree_cons (NULL_TREE, super, initlist);
4339 /* name = */
4340 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4342 /* version = */
4343 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4345 /* info = */
4346 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4348 /* instance_size = */
4349 initlist = tree_cons (NULL_TREE, size, initlist);
4351 /* objc_ivar_list = */
4352 if (!ivar_list)
4353 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4354 else
4356 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4357 initlist = tree_cons (NULL_TREE, expr, initlist);
4360 /* objc_method_list = */
4361 if (!dispatch_table)
4362 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4363 else
4365 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4366 initlist = tree_cons (NULL_TREE, expr, initlist);
4369 if (flag_next_runtime)
4370 /* method_cache = */
4371 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4372 else
4374 /* dtable = */
4375 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4377 /* subclass_list = */
4378 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4380 /* sibling_class = */
4381 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4384 /* protocol_list = */
4385 if (! protocol_list)
4386 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4387 else
4389 static tree cast_type2;
4391 if (!cast_type2)
4392 cast_type2
4393 = groktypename
4394 (build_tree_list
4395 (build_tree_list (NULL_TREE,
4396 xref_tag (RECORD_TYPE,
4397 get_identifier (UTAG_PROTOCOL))),
4398 build1 (INDIRECT_REF, NULL_TREE,
4399 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4401 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4402 TREE_TYPE (expr) = cast_type2;
4403 initlist = tree_cons (NULL_TREE, expr, initlist);
4406 /* gc_object_type = NULL */
4407 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4409 return build_constructor (type, nreverse (initlist));
4412 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4414 static void
4415 generate_category (cat)
4416 tree cat;
4418 tree sc_spec, decl_specs, decl;
4419 tree initlist, cat_name_expr, class_name_expr;
4420 tree protocol_decl, category;
4422 add_class_reference (CLASS_NAME (cat));
4423 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4425 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4427 category = CLASS_CATEGORY_LIST (implementation_template);
4429 /* find the category interface from the class it is associated with */
4430 while (category)
4432 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4433 break;
4434 category = CLASS_CATEGORY_LIST (category);
4437 if (category && CLASS_PROTOCOL_LIST (category))
4439 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4440 protocol_decl = generate_protocol_list (category);
4442 else
4443 protocol_decl = 0;
4445 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4446 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4448 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4449 implementation_context),
4450 decl_specs, 1, NULL_TREE, NULL_TREE);
4452 initlist = build_category_initializer (TREE_TYPE (decl),
4453 cat_name_expr, class_name_expr,
4454 UOBJC_INSTANCE_METHODS_decl,
4455 UOBJC_CLASS_METHODS_decl,
4456 protocol_decl);
4458 TREE_USED (decl) = 1;
4459 finish_decl (decl, initlist, NULL_TREE);
4462 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4463 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4465 static void
4466 generate_shared_structures ()
4468 tree sc_spec, decl_specs, decl;
4469 tree name_expr, super_expr, root_expr;
4470 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4471 tree cast_type, initlist, protocol_decl;
4473 my_super_id = CLASS_SUPER_NAME (implementation_template);
4474 if (my_super_id)
4476 add_class_reference (my_super_id);
4478 /* Compute "my_root_id" - this is required for code generation.
4479 the "isa" for all meta class structures points to the root of
4480 the inheritance hierarchy (e.g. "__Object")... */
4481 my_root_id = my_super_id;
4484 tree my_root_int = lookup_interface (my_root_id);
4486 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4487 my_root_id = CLASS_SUPER_NAME (my_root_int);
4488 else
4489 break;
4491 while (1);
4493 else
4494 /* No super class. */
4495 my_root_id = CLASS_NAME (implementation_template);
4497 cast_type
4498 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4499 objc_class_template),
4500 build1 (INDIRECT_REF,
4501 NULL_TREE, NULL_TREE)));
4503 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4504 class_names);
4506 /* Install class `isa' and `super' pointers at runtime. */
4507 if (my_super_id)
4509 super_expr = add_objc_string (my_super_id, class_names);
4510 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4512 else
4513 super_expr = build_int_2 (0, 0);
4515 root_expr = add_objc_string (my_root_id, class_names);
4516 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4518 if (CLASS_PROTOCOL_LIST (implementation_template))
4520 generate_protocol_references
4521 (CLASS_PROTOCOL_LIST (implementation_template));
4522 protocol_decl = generate_protocol_list (implementation_template);
4524 else
4525 protocol_decl = 0;
4527 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4529 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4530 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4532 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4533 NULL_TREE, NULL_TREE);
4535 initlist
4536 = build_shared_structure_initializer
4537 (TREE_TYPE (decl),
4538 root_expr, super_expr, name_expr,
4539 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4540 / BITS_PER_UNIT),
4542 2 /*CLS_META*/,
4543 UOBJC_CLASS_METHODS_decl,
4544 UOBJC_CLASS_VARIABLES_decl,
4545 protocol_decl);
4547 finish_decl (decl, initlist, NULL_TREE);
4549 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4551 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4552 NULL_TREE, NULL_TREE);
4554 initlist
4555 = build_shared_structure_initializer
4556 (TREE_TYPE (decl),
4557 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4558 super_expr, name_expr,
4559 build_int_2
4560 ((TREE_INT_CST_LOW
4561 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4562 / BITS_PER_UNIT),
4564 1 /*CLS_FACTORY*/,
4565 UOBJC_INSTANCE_METHODS_decl,
4566 UOBJC_INSTANCE_VARIABLES_decl,
4567 protocol_decl);
4569 finish_decl (decl, initlist, NULL_TREE);
4572 static tree
4573 synth_id_with_class_suffix (preamble, ctxt)
4574 char *preamble;
4575 tree ctxt;
4577 char *string;
4578 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4579 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4581 char *class_name
4582 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4583 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4584 sprintf (string, "%s_%s", preamble,
4585 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4587 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4588 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4590 /* We have a category. */
4591 char *class_name
4592 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4593 char *class_super_name
4594 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4595 string = (char *) alloca (strlen (preamble)
4596 + strlen (class_name)
4597 + strlen (class_super_name)
4598 + 3);
4599 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4601 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4603 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4604 string
4605 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4606 sprintf (string, "%s_%s", preamble, protocol_name);
4608 else
4609 abort ();
4611 return get_identifier (string);
4614 static int
4615 is_objc_type_qualifier (node)
4616 tree node;
4618 return (TREE_CODE (node) == IDENTIFIER_NODE
4619 && (node == ridpointers [(int) RID_CONST]
4620 || node == ridpointers [(int) RID_VOLATILE]
4621 || node == ridpointers [(int) RID_IN]
4622 || node == ridpointers [(int) RID_OUT]
4623 || node == ridpointers [(int) RID_INOUT]
4624 || node == ridpointers [(int) RID_BYCOPY]
4625 || node == ridpointers [(int) RID_BYREF]
4626 || node == ridpointers [(int) RID_ONEWAY]));
4629 /* If type is empty or only type qualifiers are present, add default
4630 type of id (otherwise grokdeclarator will default to int). */
4632 static tree
4633 adjust_type_for_id_default (type)
4634 tree type;
4636 tree declspecs, chain;
4638 if (!type)
4639 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4640 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4642 declspecs = TREE_PURPOSE (type);
4644 /* Determine if a typespec is present. */
4645 for (chain = declspecs;
4646 chain;
4647 chain = TREE_CHAIN (chain))
4649 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4650 return type;
4653 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4654 declspecs),
4655 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4658 /* Usage:
4659 keyworddecl:
4660 selector ':' '(' typename ')' identifier
4662 Purpose:
4663 Transform an Objective-C keyword argument into
4664 the C equivalent parameter declarator.
4666 In: key_name, an "identifier_node" (optional).
4667 arg_type, a "tree_list" (optional).
4668 arg_name, an "identifier_node".
4670 Note: It would be really nice to strongly type the preceding
4671 arguments in the function prototype; however, then I
4672 could not use the "accessor" macros defined in "tree.h".
4674 Out: an instance of "keyword_decl". */
4676 tree
4677 build_keyword_decl (key_name, arg_type, arg_name)
4678 tree key_name;
4679 tree arg_type;
4680 tree arg_name;
4682 tree keyword_decl;
4684 /* If no type is specified, default to "id". */
4685 arg_type = adjust_type_for_id_default (arg_type);
4687 keyword_decl = make_node (KEYWORD_DECL);
4689 TREE_TYPE (keyword_decl) = arg_type;
4690 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4691 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4693 return keyword_decl;
4696 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4698 static tree
4699 build_keyword_selector (selector)
4700 tree selector;
4702 int len = 0;
4703 tree key_chain, key_name;
4704 char *buf;
4706 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4708 if (TREE_CODE (selector) == KEYWORD_DECL)
4709 key_name = KEYWORD_KEY_NAME (key_chain);
4710 else if (TREE_CODE (selector) == TREE_LIST)
4711 key_name = TREE_PURPOSE (key_chain);
4712 else
4713 abort ();
4715 if (key_name)
4716 len += IDENTIFIER_LENGTH (key_name) + 1;
4717 else
4718 /* Just a ':' arg. */
4719 len++;
4722 buf = (char *)alloca (len + 1);
4723 bzero (buf, len + 1);
4725 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4727 if (TREE_CODE (selector) == KEYWORD_DECL)
4728 key_name = KEYWORD_KEY_NAME (key_chain);
4729 else if (TREE_CODE (selector) == TREE_LIST)
4730 key_name = TREE_PURPOSE (key_chain);
4731 else
4732 abort ();
4734 if (key_name)
4735 strcat (buf, IDENTIFIER_POINTER (key_name));
4736 strcat (buf, ":");
4739 return get_identifier (buf);
4742 /* Used for declarations and definitions. */
4744 tree
4745 build_method_decl (code, ret_type, selector, add_args)
4746 enum tree_code code;
4747 tree ret_type;
4748 tree selector;
4749 tree add_args;
4751 tree method_decl;
4753 /* If no type is specified, default to "id". */
4754 ret_type = adjust_type_for_id_default (ret_type);
4756 method_decl = make_node (code);
4757 TREE_TYPE (method_decl) = ret_type;
4759 /* If we have a keyword selector, create an identifier_node that
4760 represents the full selector name (`:' included)... */
4761 if (TREE_CODE (selector) == KEYWORD_DECL)
4763 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4764 METHOD_SEL_ARGS (method_decl) = selector;
4765 METHOD_ADD_ARGS (method_decl) = add_args;
4767 else
4769 METHOD_SEL_NAME (method_decl) = selector;
4770 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4771 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4774 return method_decl;
4777 #define METHOD_DEF 0
4778 #define METHOD_REF 1
4780 /* Used by `build_message_expr' and `comp_method_types'. Return an
4781 argument list for method METH. CONTEXT is either METHOD_DEF or
4782 METHOD_REF, saying whether we are trying to define a method or call
4783 one. SUPERFLAG says this is for a send to super; this makes a
4784 difference for the NeXT calling sequence in which the lookup and
4785 the method call are done together. */
4787 static tree
4788 get_arg_type_list (meth, context, superflag)
4789 tree meth;
4790 int context;
4791 int superflag;
4793 tree arglist, akey;
4795 /* Receiver type. */
4796 if (flag_next_runtime && superflag)
4797 arglist = build_tree_list (NULL_TREE, super_type);
4798 else if (context == METHOD_DEF)
4799 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4800 else
4801 arglist = build_tree_list (NULL_TREE, id_type);
4803 /* Selector type - will eventually change to `int'. */
4804 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4806 /* Build a list of argument types. */
4807 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4809 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4810 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4813 if (METHOD_ADD_ARGS (meth) == (tree)1)
4814 /* We have a `, ...' immediately following the selector,
4815 finalize the arglist...simulate get_parm_info (0). */
4817 else if (METHOD_ADD_ARGS (meth))
4819 /* we have a variable length selector */
4820 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4821 chainon (arglist, add_arg_list);
4823 else
4824 /* finalize the arglist...simulate get_parm_info (1) */
4825 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4827 return arglist;
4830 static tree
4831 check_duplicates (hsh)
4832 hash hsh;
4834 tree meth = NULL_TREE;
4836 if (hsh)
4838 meth = hsh->key;
4840 if (hsh->list)
4842 /* We have two methods with the same name and different types. */
4843 attr loop;
4844 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4846 warning ("multiple declarations for method `%s'",
4847 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4849 warn_with_method ("using", type, meth);
4850 for (loop = hsh->list; loop; loop = loop->next)
4851 warn_with_method ("also found", type, loop->value);
4854 return meth;
4857 /* If RECEIVER is a class reference, return the identifier node for the
4858 referenced class. RECEIVER is created by get_class_reference, so we
4859 check the exact form created depending on which runtimes are used. */
4861 static tree
4862 receiver_is_class_object (receiver)
4863 tree receiver;
4865 tree chain, exp, arg;
4866 if (flag_next_runtime)
4868 /* The receiver is a variable created by build_class_reference_decl. */
4869 if (TREE_CODE (receiver) == VAR_DECL
4870 && TREE_TYPE (receiver) == objc_class_type)
4871 /* Look up the identifier. */
4872 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4873 if (TREE_PURPOSE (chain) == receiver)
4874 return TREE_VALUE (chain);
4876 else
4878 /* The receiver is a function call that returns an id. Check if
4879 it is a call to objc_getClass, if so, pick up the class name. */
4880 if ((exp = TREE_OPERAND (receiver, 0))
4881 && TREE_CODE (exp) == ADDR_EXPR
4882 && (exp = TREE_OPERAND (exp, 0))
4883 && TREE_CODE (exp) == FUNCTION_DECL
4884 && exp == objc_get_class_decl
4885 /* we have a call to objc_getClass! */
4886 && (arg = TREE_OPERAND (receiver, 1))
4887 && TREE_CODE (arg) == TREE_LIST
4888 && (arg = TREE_VALUE (arg)))
4890 STRIP_NOPS (arg);
4891 if (TREE_CODE (arg) == ADDR_EXPR
4892 && (arg = TREE_OPERAND (arg, 0))
4893 && TREE_CODE (arg) == STRING_CST)
4894 /* Finally, we have the class name. */
4895 return get_identifier (TREE_STRING_POINTER (arg));
4898 return 0;
4901 /* If we are currently building a message expr, this holds
4902 the identifier of the selector of the message. This is
4903 used when printing warnings about argument mismatches. */
4905 static tree building_objc_message_expr = 0;
4907 tree
4908 maybe_building_objc_message_expr ()
4910 return building_objc_message_expr;
4913 /* Construct an expression for sending a message.
4914 MESS has the object to send to in TREE_PURPOSE
4915 and the argument list (including selector) in TREE_VALUE.
4917 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4918 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4920 tree
4921 build_message_expr (mess)
4922 tree mess;
4924 tree receiver = TREE_PURPOSE (mess);
4925 tree selector, self_object;
4926 tree rtype, sel_name;
4927 tree args = TREE_VALUE (mess);
4928 tree method_params = NULL_TREE;
4929 tree method_prototype = NULL_TREE;
4930 tree retval;
4931 int statically_typed = 0, statically_allocated = 0;
4932 tree class_ident = 0;
4934 /* 1 if this is sending to the superclass. */
4935 int super;
4937 if (!doing_objc_thang)
4938 objc_fatal ();
4940 if (TREE_CODE (receiver) == ERROR_MARK)
4941 return error_mark_node;
4943 /* Determine receiver type. */
4944 rtype = TREE_TYPE (receiver);
4945 super = IS_SUPER (rtype);
4947 if (! super)
4949 if (TREE_STATIC_TEMPLATE (rtype))
4950 statically_allocated = 1;
4951 else if (TREE_CODE (rtype) == POINTER_TYPE
4952 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4953 statically_typed = 1;
4954 else if ((flag_next_runtime
4955 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4956 && (class_ident = receiver_is_class_object (receiver)))
4958 else if (! IS_ID (rtype)
4959 /* Allow any type that matches objc_class_type. */
4960 && ! comptypes (rtype, objc_class_type))
4962 bzero (errbuf, BUFSIZE);
4963 warning ("invalid receiver type `%s'",
4964 gen_declaration (rtype, errbuf));
4967 if (statically_allocated)
4968 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4970 /* Don't evaluate the receiver twice. */
4971 receiver = save_expr (receiver);
4972 self_object = receiver;
4974 else
4975 /* If sending to `super', use current self as the object. */
4976 self_object = self_decl;
4978 /* Obtain the full selector name. */
4980 if (TREE_CODE (args) == IDENTIFIER_NODE)
4981 /* A unary selector. */
4982 sel_name = args;
4983 else if (TREE_CODE (args) == TREE_LIST)
4984 sel_name = build_keyword_selector (args);
4985 else
4986 abort ();
4988 /* Build the parameter list to give to the method. */
4990 method_params = NULL_TREE;
4991 if (TREE_CODE (args) == TREE_LIST)
4993 tree chain = args, prev = NULL_TREE;
4995 /* We have a keyword selector--check for comma expressions. */
4996 while (chain)
4998 tree element = TREE_VALUE (chain);
5000 /* We have a comma expression, must collapse... */
5001 if (TREE_CODE (element) == TREE_LIST)
5003 if (prev)
5004 TREE_CHAIN (prev) = element;
5005 else
5006 args = element;
5008 prev = chain;
5009 chain = TREE_CHAIN (chain);
5011 method_params = args;
5014 /* Determine operation return type. */
5016 if (IS_SUPER (rtype))
5018 tree iface;
5020 if (CLASS_SUPER_NAME (implementation_template))
5022 iface
5023 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5025 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
5026 method_prototype = lookup_instance_method_static (iface, sel_name);
5027 else
5028 method_prototype = lookup_class_method_static (iface, sel_name);
5030 if (iface && !method_prototype)
5031 warning ("`%s' does not respond to `%s'",
5032 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
5033 IDENTIFIER_POINTER (sel_name));
5035 else
5037 error ("no super class declared in interface for `%s'",
5038 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5039 return error_mark_node;
5043 else if (statically_allocated)
5045 tree ctype = TREE_TYPE (rtype);
5046 tree iface = lookup_interface (TYPE_NAME (rtype));
5048 if (iface)
5049 method_prototype = lookup_instance_method_static (iface, sel_name);
5051 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5052 method_prototype
5053 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5054 sel_name, 0);
5056 if (!method_prototype)
5057 warning ("`%s' does not respond to `%s'",
5058 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
5059 IDENTIFIER_POINTER (sel_name));
5061 else if (statically_typed)
5063 tree ctype = TREE_TYPE (rtype);
5065 /* `self' is now statically_typed. All methods should be visible
5066 within the context of the implementation. */
5067 if (implementation_context
5068 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
5070 method_prototype
5071 = lookup_instance_method_static (implementation_template,
5072 sel_name);
5074 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5075 method_prototype
5076 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5077 sel_name, 0);
5079 if (! method_prototype
5080 && implementation_template != implementation_context)
5081 /* The method is not published in the interface. Check
5082 locally. */
5083 method_prototype
5084 = lookup_method (CLASS_NST_METHODS (implementation_context),
5085 sel_name);
5087 else
5089 tree iface;
5091 if ((iface = lookup_interface (TYPE_NAME (ctype))))
5092 method_prototype = lookup_instance_method_static (iface, sel_name);
5094 if (! method_prototype)
5096 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5097 if (protocol_list)
5098 method_prototype
5099 = lookup_method_in_protocol_list (protocol_list,
5100 sel_name, 0);
5104 if (!method_prototype)
5105 warning ("`%s' does not respond to `%s'",
5106 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5107 IDENTIFIER_POINTER (sel_name));
5109 else if (class_ident)
5111 if (implementation_context
5112 && CLASS_NAME (implementation_context) == class_ident)
5114 method_prototype
5115 = lookup_class_method_static (implementation_template, sel_name);
5117 if (!method_prototype
5118 && implementation_template != implementation_context)
5119 /* The method is not published in the interface. Check
5120 locally. */
5121 method_prototype
5122 = lookup_method (CLASS_CLS_METHODS (implementation_context),
5123 sel_name);
5125 else
5127 tree iface;
5129 if ((iface = lookup_interface (class_ident)))
5130 method_prototype = lookup_class_method_static (iface, sel_name);
5133 if (!method_prototype)
5135 warning ("cannot find class (factory) method.");
5136 warning ("return type for `%s' defaults to id",
5137 IDENTIFIER_POINTER (sel_name));
5140 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5142 /* An anonymous object that has been qualified with a protocol. */
5144 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5146 method_prototype = lookup_method_in_protocol_list (protocol_list,
5147 sel_name, 0);
5149 if (!method_prototype)
5151 hash hsh;
5153 warning ("method `%s' not implemented by protocol.",
5154 IDENTIFIER_POINTER (sel_name));
5156 /* Try and find the method signature in the global pools. */
5158 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5159 hsh = hash_lookup (cls_method_hash_list, sel_name);
5161 if (!(method_prototype = check_duplicates (hsh)))
5162 warning ("return type defaults to id");
5165 else
5167 hash hsh;
5169 /* We think we have an instance...loophole: extern id Object; */
5170 hsh = hash_lookup (nst_method_hash_list, sel_name);
5171 if (!hsh)
5172 /* For various loopholes, like sending messages to self in a
5173 factory context. */
5174 hsh = hash_lookup (cls_method_hash_list, sel_name);
5176 method_prototype = check_duplicates (hsh);
5177 if (!method_prototype)
5179 warning ("cannot find method.");
5180 warning ("return type for `%s' defaults to id",
5181 IDENTIFIER_POINTER (sel_name));
5185 /* Save the selector name for printing error messages. */
5186 building_objc_message_expr = sel_name;
5188 /* Build the parameters list for looking up the method.
5189 These are the object itself and the selector. */
5191 if (flag_typed_selectors)
5192 selector = build_typed_selector_reference (sel_name, method_prototype);
5193 else
5194 selector = build_selector_reference (sel_name);
5196 retval = build_objc_method_call (super, method_prototype,
5197 receiver, self_object,
5198 selector, method_params);
5200 building_objc_message_expr = 0;
5202 return retval;
5205 /* Build a tree expression to send OBJECT the operation SELECTOR,
5206 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5207 assuming the method has prototype METHOD_PROTOTYPE.
5208 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5209 Use METHOD_PARAMS as list of args to pass to the method.
5210 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5212 static tree
5213 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5214 selector, method_params)
5215 int super_flag;
5216 tree method_prototype, lookup_object, object, selector, method_params;
5218 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5219 tree rcv_p = (super_flag
5220 ? build_pointer_type (xref_tag (RECORD_TYPE,
5221 get_identifier (TAG_SUPER)))
5222 : id_type);
5224 if (flag_next_runtime)
5226 if (! method_prototype)
5228 method_params = tree_cons (NULL_TREE, lookup_object,
5229 tree_cons (NULL_TREE, selector,
5230 method_params));
5231 assemble_external (sender);
5232 return build_function_call (sender, method_params);
5234 else
5236 /* This is a real kludge, but it is used only for the Next.
5237 Clobber the data type of SENDER temporarily to accept
5238 all the arguments for this operation, and to return
5239 whatever this operation returns. */
5240 tree arglist = NULL_TREE;
5241 tree retval;
5243 /* Save the proper contents of SENDER's data type. */
5244 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5245 tree savret = TREE_TYPE (TREE_TYPE (sender));
5247 /* Install this method's argument types. */
5248 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5249 super_flag);
5250 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5252 /* Install this method's return type. */
5253 TREE_TYPE (TREE_TYPE (sender))
5254 = groktypename (TREE_TYPE (method_prototype));
5256 /* Call SENDER with all the parameters. This will do type
5257 checking using the arg types for this method. */
5258 method_params = tree_cons (NULL_TREE, lookup_object,
5259 tree_cons (NULL_TREE, selector,
5260 method_params));
5261 assemble_external (sender);
5262 retval = build_function_call (sender, method_params);
5264 /* Restore SENDER's return/argument types. */
5265 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5266 TREE_TYPE (TREE_TYPE (sender)) = savret;
5267 return retval;
5270 else
5272 /* This is the portable way.
5273 First call the lookup function to get a pointer to the method,
5274 then cast the pointer, then call it with the method arguments. */
5275 tree method;
5277 /* Avoid trouble since we may evaluate each of these twice. */
5278 object = save_expr (object);
5279 selector = save_expr (selector);
5281 lookup_object = build_c_cast (rcv_p, lookup_object);
5283 assemble_external (sender);
5284 method
5285 = build_function_call (sender,
5286 tree_cons (NULL_TREE, lookup_object,
5287 tree_cons (NULL_TREE, selector,
5288 NULL_TREE)));
5290 /* If we have a method prototype, construct the data type this
5291 method needs, and cast what we got from SENDER into a pointer
5292 to that type. */
5293 if (method_prototype)
5295 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5296 super_flag);
5297 tree valtype = groktypename (TREE_TYPE (method_prototype));
5298 tree fake_function_type = build_function_type (valtype, arglist);
5299 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5301 else
5302 TREE_TYPE (method)
5303 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5305 /* Pass the object to the method. */
5306 assemble_external (method);
5307 return build_function_call (method,
5308 tree_cons (NULL_TREE, object,
5309 tree_cons (NULL_TREE, selector,
5310 method_params)));
5314 static void
5315 build_protocol_reference (p)
5316 tree p;
5318 tree decl, ident, ptype;
5320 push_obstacks_nochange ();
5321 end_temporary_allocation ();
5323 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5325 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5326 ptype
5327 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5328 objc_protocol_template),
5329 NULL_TREE));
5331 if (IDENTIFIER_GLOBAL_VALUE (ident))
5332 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5333 else
5335 decl = build_decl (VAR_DECL, ident, ptype);
5336 DECL_EXTERNAL (decl) = 1;
5337 TREE_PUBLIC (decl) = 1;
5338 TREE_USED (decl) = 1;
5339 DECL_ARTIFICIAL (decl) = 1;
5341 make_decl_rtl (decl, 0, 1);
5342 pushdecl_top_level (decl);
5345 PROTOCOL_FORWARD_DECL (p) = decl;
5346 pop_obstacks ();
5349 tree
5350 build_protocol_expr (protoname)
5351 tree protoname;
5353 tree expr;
5354 tree p;
5356 if (!doing_objc_thang)
5357 objc_fatal ();
5359 p = lookup_protocol (protoname);
5361 if (!p)
5363 error ("Cannot find protocol declaration for `%s'",
5364 IDENTIFIER_POINTER (protoname));
5365 return error_mark_node;
5368 if (!PROTOCOL_FORWARD_DECL (p))
5369 build_protocol_reference (p);
5371 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5373 TREE_TYPE (expr) = protocol_type;
5375 return expr;
5378 tree
5379 build_selector_expr (selnamelist)
5380 tree selnamelist;
5382 tree selname;
5384 if (!doing_objc_thang)
5385 objc_fatal ();
5387 /* Obtain the full selector name. */
5388 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5389 /* A unary selector. */
5390 selname = selnamelist;
5391 else if (TREE_CODE (selnamelist) == TREE_LIST)
5392 selname = build_keyword_selector (selnamelist);
5393 else
5394 abort ();
5396 if (flag_typed_selectors)
5397 return build_typed_selector_reference (selname, 0);
5398 else
5399 return build_selector_reference (selname);
5402 tree
5403 build_encode_expr (type)
5404 tree type;
5406 tree result;
5407 char *string;
5409 if (!doing_objc_thang)
5410 objc_fatal ();
5412 encode_type (type, obstack_object_size (&util_obstack),
5413 OBJC_ENCODE_INLINE_DEFS);
5414 obstack_1grow (&util_obstack, 0); /* null terminate string */
5415 string = obstack_finish (&util_obstack);
5417 /* Synthesize a string that represents the encoded struct/union. */
5418 result = my_build_string (strlen (string) + 1, string);
5419 obstack_free (&util_obstack, util_firstobj);
5420 return result;
5423 tree
5424 build_ivar_reference (id)
5425 tree id;
5427 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5429 /* Historically, a class method that produced objects (factory
5430 method) would assign `self' to the instance that it
5431 allocated. This would effectively turn the class method into
5432 an instance method. Following this assignment, the instance
5433 variables could be accessed. That practice, while safe,
5434 violates the simple rule that a class method should not refer
5435 to an instance variable. It's better to catch the cases
5436 where this is done unknowingly than to support the above
5437 paradigm. */
5438 warning ("instance variable `%s' accessed in class method",
5439 IDENTIFIER_POINTER (id));
5440 TREE_TYPE (self_decl) = instance_type; /* cast */
5443 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5446 #define HASH_ALLOC_LIST_SIZE 170
5447 #define ATTR_ALLOC_LIST_SIZE 170
5448 #define SIZEHASHTABLE 257
5450 /* make positive */
5451 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5453 static void
5454 hash_init ()
5456 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5457 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5459 if (!nst_method_hash_list || !cls_method_hash_list)
5460 perror ("unable to allocate space in objc-tree.c");
5461 else
5463 int i;
5465 for (i = 0; i < SIZEHASHTABLE; i++)
5467 nst_method_hash_list[i] = 0;
5468 cls_method_hash_list[i] = 0;
5473 static void
5474 hash_enter (hashlist, method)
5475 hash *hashlist;
5476 tree method;
5478 static hash hash_alloc_list = 0;
5479 static int hash_alloc_index = 0;
5480 hash obj;
5481 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5483 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5485 hash_alloc_index = 0;
5486 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5487 * HASH_ALLOC_LIST_SIZE);
5488 if (! hash_alloc_list)
5489 perror ("unable to allocate in objc-tree.c");
5491 obj = &hash_alloc_list[hash_alloc_index++];
5492 obj->list = 0;
5493 obj->next = hashlist[slot];
5494 obj->key = method;
5496 hashlist[slot] = obj; /* append to front */
5499 static hash
5500 hash_lookup (hashlist, sel_name)
5501 hash *hashlist;
5502 tree sel_name;
5504 hash target;
5506 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5508 while (target)
5510 if (sel_name == METHOD_SEL_NAME (target->key))
5511 return target;
5513 target = target->next;
5515 return 0;
5518 static void
5519 hash_add_attr (entry, value)
5520 hash entry;
5521 tree value;
5523 static attr attr_alloc_list = 0;
5524 static int attr_alloc_index = 0;
5525 attr obj;
5527 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5529 attr_alloc_index = 0;
5530 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5531 * ATTR_ALLOC_LIST_SIZE);
5532 if (! attr_alloc_list)
5533 perror ("unable to allocate in objc-tree.c");
5535 obj = &attr_alloc_list[attr_alloc_index++];
5536 obj->next = entry->list;
5537 obj->value = value;
5539 entry->list = obj; /* append to front */
5542 static tree
5543 lookup_method (mchain, method)
5544 tree mchain;
5545 tree method;
5547 tree key;
5549 if (TREE_CODE (method) == IDENTIFIER_NODE)
5550 key = method;
5551 else
5552 key = METHOD_SEL_NAME (method);
5554 while (mchain)
5556 if (METHOD_SEL_NAME (mchain) == key)
5557 return mchain;
5558 mchain = TREE_CHAIN (mchain);
5560 return NULL_TREE;
5563 static tree
5564 lookup_instance_method_static (interface, ident)
5565 tree interface;
5566 tree ident;
5568 tree inter = interface;
5569 tree chain = CLASS_NST_METHODS (inter);
5570 tree meth = NULL_TREE;
5574 if ((meth = lookup_method (chain, ident)))
5575 return meth;
5577 if (CLASS_CATEGORY_LIST (inter))
5579 tree category = CLASS_CATEGORY_LIST (inter);
5580 chain = CLASS_NST_METHODS (category);
5584 if ((meth = lookup_method (chain, ident)))
5585 return meth;
5587 /* Check for instance methods in protocols in categories. */
5588 if (CLASS_PROTOCOL_LIST (category))
5590 if ((meth = (lookup_method_in_protocol_list
5591 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5592 return meth;
5595 if ((category = CLASS_CATEGORY_LIST (category)))
5596 chain = CLASS_NST_METHODS (category);
5598 while (category);
5601 if (CLASS_PROTOCOL_LIST (inter))
5603 if ((meth = (lookup_method_in_protocol_list
5604 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5605 return meth;
5608 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5609 chain = CLASS_NST_METHODS (inter);
5611 while (inter);
5613 return meth;
5616 static tree
5617 lookup_class_method_static (interface, ident)
5618 tree interface;
5619 tree ident;
5621 tree inter = interface;
5622 tree chain = CLASS_CLS_METHODS (inter);
5623 tree meth = NULL_TREE;
5624 tree root_inter = NULL_TREE;
5628 if ((meth = lookup_method (chain, ident)))
5629 return meth;
5631 if (CLASS_CATEGORY_LIST (inter))
5633 tree category = CLASS_CATEGORY_LIST (inter);
5634 chain = CLASS_CLS_METHODS (category);
5638 if ((meth = lookup_method (chain, ident)))
5639 return meth;
5641 /* Check for class methods in protocols in categories. */
5642 if (CLASS_PROTOCOL_LIST (category))
5644 if ((meth = (lookup_method_in_protocol_list
5645 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5646 return meth;
5649 if ((category = CLASS_CATEGORY_LIST (category)))
5650 chain = CLASS_CLS_METHODS (category);
5652 while (category);
5655 /* Check for class methods in protocols. */
5656 if (CLASS_PROTOCOL_LIST (inter))
5658 if ((meth = (lookup_method_in_protocol_list
5659 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5660 return meth;
5663 root_inter = inter;
5664 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5665 chain = CLASS_CLS_METHODS (inter);
5667 while (inter);
5669 /* Simulate wrap around. */
5670 return lookup_instance_method_static (root_inter, ident);
5673 tree
5674 add_class_method (class, method)
5675 tree class;
5676 tree method;
5678 tree mth;
5679 hash hsh;
5681 /* We will have allocated the method parameter declarations on the
5682 maybepermanent_obstack. Need to make sure they stick around! */
5683 preserve_data ();
5685 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5687 /* put method on list in reverse order */
5688 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5689 CLASS_CLS_METHODS (class) = method;
5691 else
5693 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5694 error ("duplicate definition of class method `%s'.",
5695 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5696 else
5698 /* Check types; if different, complain. */
5699 if (!comp_proto_with_proto (method, mth))
5700 error ("duplicate declaration of class method `%s'.",
5701 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5705 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5707 /* Install on a global chain. */
5708 hash_enter (cls_method_hash_list, method);
5710 else
5712 /* Check types; if different, add to a list. */
5713 if (!comp_proto_with_proto (method, hsh->key))
5714 hash_add_attr (hsh, method);
5716 return method;
5719 tree
5720 add_instance_method (class, method)
5721 tree class;
5722 tree method;
5724 tree mth;
5725 hash hsh;
5727 /* We will have allocated the method parameter declarations on the
5728 maybepermanent_obstack. Need to make sure they stick around! */
5729 preserve_data ();
5731 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5733 /* Put method on list in reverse order. */
5734 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5735 CLASS_NST_METHODS (class) = method;
5737 else
5739 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5740 error ("duplicate definition of instance method `%s'.",
5741 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5742 else
5744 /* Check types; if different, complain. */
5745 if (!comp_proto_with_proto (method, mth))
5746 error ("duplicate declaration of instance method `%s'.",
5747 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5751 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5753 /* Install on a global chain. */
5754 hash_enter (nst_method_hash_list, method);
5756 else
5758 /* Check types; if different, add to a list. */
5759 if (!comp_proto_with_proto (method, hsh->key))
5760 hash_add_attr (hsh, method);
5762 return method;
5765 static tree
5766 add_class (class)
5767 tree class;
5769 /* Put interfaces on list in reverse order. */
5770 TREE_CHAIN (class) = interface_chain;
5771 interface_chain = class;
5772 return interface_chain;
5775 static void
5776 add_category (class, category)
5777 tree class;
5778 tree category;
5780 /* Put categories on list in reverse order. */
5781 tree cat = CLASS_CATEGORY_LIST (class);
5783 while (cat)
5785 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5786 warning ("duplicate interface declaration for category `%s(%s)'",
5787 IDENTIFIER_POINTER (CLASS_NAME (class)),
5788 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5789 cat = CLASS_CATEGORY_LIST (cat);
5792 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5793 CLASS_CATEGORY_LIST (class) = category;
5796 /* Called after parsing each instance variable declaration. Necessary to
5797 preserve typedefs and implement public/private...
5799 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5801 tree
5802 add_instance_variable (class, public, declarator, declspecs, width)
5803 tree class;
5804 int public;
5805 tree declarator;
5806 tree declspecs;
5807 tree width;
5809 tree field_decl, raw_decl;
5811 raw_decl = build_tree_list (declspecs, declarator);
5813 if (CLASS_RAW_IVARS (class))
5814 chainon (CLASS_RAW_IVARS (class), raw_decl);
5815 else
5816 CLASS_RAW_IVARS (class) = raw_decl;
5818 field_decl = grokfield (input_filename, lineno,
5819 declarator, declspecs, width);
5821 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5822 switch (public)
5824 case 0:
5825 TREE_PUBLIC (field_decl) = 0;
5826 TREE_PRIVATE (field_decl) = 0;
5827 TREE_PROTECTED (field_decl) = 1;
5828 break;
5830 case 1:
5831 TREE_PUBLIC (field_decl) = 1;
5832 TREE_PRIVATE (field_decl) = 0;
5833 TREE_PROTECTED (field_decl) = 0;
5834 break;
5836 case 2:
5837 TREE_PUBLIC (field_decl) = 0;
5838 TREE_PRIVATE (field_decl) = 1;
5839 TREE_PROTECTED (field_decl) = 0;
5840 break;
5844 if (CLASS_IVARS (class))
5845 chainon (CLASS_IVARS (class), field_decl);
5846 else
5847 CLASS_IVARS (class) = field_decl;
5849 return class;
5852 tree
5853 is_ivar (decl_chain, ident)
5854 tree decl_chain;
5855 tree ident;
5857 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5858 if (DECL_NAME (decl_chain) == ident)
5859 return decl_chain;
5860 return NULL_TREE;
5863 /* True if the ivar is private and we are not in its implementation. */
5866 is_private (decl)
5867 tree decl;
5869 if (TREE_PRIVATE (decl)
5870 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5872 error ("instance variable `%s' is declared private",
5873 IDENTIFIER_POINTER (DECL_NAME (decl)));
5874 return 1;
5876 else
5877 return 0;
5880 /* We have an instance variable reference;, check to see if it is public. */
5883 is_public (expr, identifier)
5884 tree expr;
5885 tree identifier;
5887 tree basetype = TREE_TYPE (expr);
5888 enum tree_code code = TREE_CODE (basetype);
5889 tree decl;
5891 if (code == RECORD_TYPE)
5893 if (TREE_STATIC_TEMPLATE (basetype))
5895 if (!lookup_interface (TYPE_NAME (basetype)))
5897 error ("Cannot find interface declaration for `%s'",
5898 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5899 return 0;
5902 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5904 if (TREE_PUBLIC (decl))
5905 return 1;
5907 /* Important difference between the Stepstone translator:
5908 all instance variables should be public within the context
5909 of the implementation. */
5910 if (implementation_context
5911 && (((TREE_CODE (implementation_context)
5912 == CLASS_IMPLEMENTATION_TYPE)
5913 || (TREE_CODE (implementation_context)
5914 == CATEGORY_IMPLEMENTATION_TYPE))
5915 && (CLASS_NAME (implementation_context)
5916 == TYPE_NAME (basetype))))
5917 return ! is_private (decl);
5919 error ("instance variable `%s' is declared %s",
5920 IDENTIFIER_POINTER (identifier),
5921 TREE_PRIVATE (decl) ? "private" : "protected");
5922 return 0;
5926 else if (implementation_context && (basetype == objc_object_reference))
5928 TREE_TYPE (expr) = uprivate_record;
5929 warning ("static access to object of type `id'");
5933 return 1;
5936 /* Implement @defs (<classname>) within struct bodies. */
5938 tree
5939 get_class_ivars (interface)
5940 tree interface;
5942 if (!doing_objc_thang)
5943 objc_fatal ();
5945 return build_ivar_chain (interface, 1);
5948 /* Make sure all entries in CHAIN are also in LIST. */
5950 static int
5951 check_methods (chain, list, mtype)
5952 tree chain;
5953 tree list;
5954 int mtype;
5956 int first = 1;
5958 while (chain)
5960 if (!lookup_method (list, chain))
5962 if (first)
5964 if (TREE_CODE (implementation_context)
5965 == CLASS_IMPLEMENTATION_TYPE)
5966 warning ("incomplete implementation of class `%s'",
5967 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5968 else if (TREE_CODE (implementation_context)
5969 == CATEGORY_IMPLEMENTATION_TYPE)
5970 warning ("incomplete implementation of category `%s'",
5971 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5972 first = 0;
5975 warning ("method definition for `%c%s' not found",
5976 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5979 chain = TREE_CHAIN (chain);
5982 return first;
5985 static int
5986 conforms_to_protocol (class, protocol)
5987 tree class;
5988 tree protocol;
5990 while (protocol)
5992 tree p = CLASS_PROTOCOL_LIST (class);
5994 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5995 p = TREE_CHAIN (p);
5997 if (!p)
5999 tree super = (CLASS_SUPER_NAME (class)
6000 ? lookup_interface (CLASS_SUPER_NAME (class))
6001 : NULL_TREE);
6002 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6003 if (!tmp)
6004 return 0;
6007 protocol = TREE_CHAIN (protocol);
6010 return 1;
6013 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6014 CONTEXT. This is one of two mechanisms to check protocol integrity. */
6016 static int
6017 check_methods_accessible (chain, context, mtype)
6018 tree chain;
6019 tree context;
6020 int mtype;
6022 int first = 1;
6023 tree list;
6024 tree base_context = context;
6026 while (chain)
6028 context = base_context;
6029 while (context)
6031 if (mtype == '+')
6032 list = CLASS_CLS_METHODS (context);
6033 else
6034 list = CLASS_NST_METHODS (context);
6036 if (lookup_method (list, chain))
6037 break;
6039 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6040 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6041 context = (CLASS_SUPER_NAME (context)
6042 ? lookup_interface (CLASS_SUPER_NAME (context))
6043 : NULL_TREE);
6045 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6046 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6047 context = (CLASS_NAME (context)
6048 ? lookup_interface (CLASS_NAME (context))
6049 : NULL_TREE);
6050 else
6051 abort ();
6054 if (context == NULL_TREE)
6056 if (first)
6058 if (TREE_CODE (implementation_context)
6059 == CLASS_IMPLEMENTATION_TYPE)
6060 warning ("incomplete implementation of class `%s'",
6061 IDENTIFIER_POINTER
6062 (CLASS_NAME (implementation_context)));
6063 else if (TREE_CODE (implementation_context)
6064 == CATEGORY_IMPLEMENTATION_TYPE)
6065 warning ("incomplete implementation of category `%s'",
6066 IDENTIFIER_POINTER
6067 (CLASS_SUPER_NAME (implementation_context)));
6068 first = 0;
6070 warning ("method definition for `%c%s' not found",
6071 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6074 chain = TREE_CHAIN (chain); /* next method... */
6076 return first;
6079 static void
6080 check_protocols (proto_list, type, name)
6081 tree proto_list;
6082 char *type;
6083 char *name;
6085 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6087 tree p = TREE_VALUE (proto_list);
6089 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6091 int f1, f2;
6093 /* Ensure that all protocols have bodies. */
6094 if (flag_warn_protocol) {
6095 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6096 CLASS_CLS_METHODS (implementation_context),
6097 '+');
6098 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6099 CLASS_NST_METHODS (implementation_context),
6100 '-');
6101 } else {
6102 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6103 implementation_context,
6104 '+');
6105 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6106 implementation_context,
6107 '-');
6110 if (!f1 || !f2)
6111 warning ("%s `%s' does not fully implement the `%s' protocol",
6112 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6115 else
6117 ; /* An identifier if we could not find a protocol. */
6120 /* Check protocols recursively. */
6121 if (PROTOCOL_LIST (p))
6123 tree super_class
6124 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6125 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
6126 check_protocols (PROTOCOL_LIST (p), type, name);
6131 /* Make sure that the class CLASS_NAME is defined
6132 CODE says which kind of thing CLASS_NAME ought to be.
6133 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6134 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
6136 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
6137 whose matching pop is in continue_class. */
6139 tree
6140 start_class (code, class_name, super_name, protocol_list)
6141 enum tree_code code;
6142 tree class_name;
6143 tree super_name;
6144 tree protocol_list;
6146 tree class, decl;
6148 if (code == CLASS_INTERFACE_TYPE)
6150 push_obstacks_nochange ();
6151 end_temporary_allocation ();
6154 if (!doing_objc_thang)
6155 objc_fatal ();
6157 class = make_node (code);
6158 TYPE_BINFO (class) = make_tree_vec (5);
6160 CLASS_NAME (class) = class_name;
6161 CLASS_SUPER_NAME (class) = super_name;
6162 CLASS_CLS_METHODS (class) = NULL_TREE;
6164 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6166 error ("`%s' redeclared as different kind of symbol",
6167 IDENTIFIER_POINTER (class_name));
6168 error_with_decl (decl, "previous declaration of `%s'");
6171 if (code == CLASS_IMPLEMENTATION_TYPE)
6174 static tree implemented_classes = 0;
6175 tree chain = implemented_classes;
6176 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6177 if (TREE_VALUE (chain) == class_name)
6179 error ("reimplementation of class `%s'",
6180 IDENTIFIER_POINTER (class_name));
6181 return error_mark_node;
6183 implemented_classes = perm_tree_cons (NULL_TREE, class_name,
6184 implemented_classes);
6187 /* Pre-build the following entities - for speed/convenience. */
6188 if (!self_id)
6189 self_id = get_identifier ("self");
6190 if (!ucmd_id)
6191 ucmd_id = get_identifier ("_cmd");
6192 if (!unused_list)
6193 unused_list
6194 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6195 if (!objc_super_template)
6196 objc_super_template = build_super_template ();
6198 /* Reset for multiple classes per file. */
6199 method_slot = 0;
6201 implementation_context = class;
6203 /* Lookup the interface for this implementation. */
6205 if (!(implementation_template = lookup_interface (class_name)))
6207 warning ("Cannot find interface declaration for `%s'",
6208 IDENTIFIER_POINTER (class_name));
6209 add_class (implementation_template = implementation_context);
6212 /* If a super class has been specified in the implementation,
6213 insure it conforms to the one specified in the interface. */
6215 if (super_name
6216 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6218 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6219 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6220 error ("conflicting super class name `%s'",
6221 IDENTIFIER_POINTER (super_name));
6222 error ("previous declaration of `%s'", name);
6225 else if (! super_name)
6227 CLASS_SUPER_NAME (implementation_context)
6228 = CLASS_SUPER_NAME (implementation_template);
6232 else if (code == CLASS_INTERFACE_TYPE)
6234 if (lookup_interface (class_name))
6235 warning ("duplicate interface declaration for class `%s'",
6236 IDENTIFIER_POINTER (class_name));
6237 else
6238 add_class (class);
6240 if (protocol_list)
6241 CLASS_PROTOCOL_LIST (class)
6242 = lookup_and_install_protocols (protocol_list);
6245 else if (code == CATEGORY_INTERFACE_TYPE)
6247 tree class_category_is_assoc_with;
6249 /* For a category, class_name is really the name of the class that
6250 the following set of methods will be associated with. We must
6251 find the interface so that can derive the objects template. */
6253 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6255 error ("Cannot find interface declaration for `%s'",
6256 IDENTIFIER_POINTER (class_name));
6257 exit (FATAL_EXIT_CODE);
6259 else
6260 add_category (class_category_is_assoc_with, class);
6262 if (protocol_list)
6263 CLASS_PROTOCOL_LIST (class)
6264 = lookup_and_install_protocols (protocol_list);
6267 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6269 /* Pre-build the following entities for speed/convenience. */
6270 if (!self_id)
6271 self_id = get_identifier ("self");
6272 if (!ucmd_id)
6273 ucmd_id = get_identifier ("_cmd");
6274 if (!unused_list)
6275 unused_list
6276 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6277 if (!objc_super_template)
6278 objc_super_template = build_super_template ();
6280 /* Reset for multiple classes per file. */
6281 method_slot = 0;
6283 implementation_context = class;
6285 /* For a category, class_name is really the name of the class that
6286 the following set of methods will be associated with. We must
6287 find the interface so that can derive the objects template. */
6289 if (!(implementation_template = lookup_interface (class_name)))
6291 error ("Cannot find interface declaration for `%s'",
6292 IDENTIFIER_POINTER (class_name));
6293 exit (FATAL_EXIT_CODE);
6296 return class;
6299 tree
6300 continue_class (class)
6301 tree class;
6303 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6304 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6306 struct imp_entry *imp_entry;
6307 tree ivar_context;
6309 /* Check consistency of the instance variables. */
6311 if (CLASS_IVARS (class))
6312 check_ivars (implementation_template, class);
6314 /* code generation */
6316 ivar_context = build_private_template (implementation_template);
6318 if (!objc_class_template)
6319 build_class_template ();
6321 if (!(imp_entry
6322 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6323 perror ("unable to allocate in objc-tree.c");
6325 imp_entry->next = imp_list;
6326 imp_entry->imp_context = class;
6327 imp_entry->imp_template = implementation_template;
6329 synth_forward_declarations ();
6330 imp_entry->class_decl = UOBJC_CLASS_decl;
6331 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6333 /* Append to front and increment count. */
6334 imp_list = imp_entry;
6335 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6336 imp_count++;
6337 else
6338 cat_count++;
6340 return ivar_context;
6343 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6345 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6347 if (!TYPE_FIELDS (record))
6349 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6350 CLASS_STATIC_TEMPLATE (class) = record;
6352 /* Mark this record as a class template for static typing. */
6353 TREE_STATIC_TEMPLATE (record) = 1;
6356 return NULL_TREE;
6359 else
6360 return error_mark_node;
6363 /* This is called once we see the "@end" in an interface/implementation. */
6365 void
6366 finish_class (class)
6367 tree class;
6369 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6371 /* All code generation is done in finish_objc. */
6373 if (implementation_template != implementation_context)
6375 /* Ensure that all method listed in the interface contain bodies. */
6376 check_methods (CLASS_CLS_METHODS (implementation_template),
6377 CLASS_CLS_METHODS (implementation_context), '+');
6378 check_methods (CLASS_NST_METHODS (implementation_template),
6379 CLASS_NST_METHODS (implementation_context), '-');
6381 if (CLASS_PROTOCOL_LIST (implementation_template))
6382 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6383 "class",
6384 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6388 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6390 tree category = CLASS_CATEGORY_LIST (implementation_template);
6392 /* Find the category interface from the class it is associated with. */
6393 while (category)
6395 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6396 break;
6397 category = CLASS_CATEGORY_LIST (category);
6400 if (category)
6402 /* Ensure all method listed in the interface contain bodies. */
6403 check_methods (CLASS_CLS_METHODS (category),
6404 CLASS_CLS_METHODS (implementation_context), '+');
6405 check_methods (CLASS_NST_METHODS (category),
6406 CLASS_NST_METHODS (implementation_context), '-');
6408 if (CLASS_PROTOCOL_LIST (category))
6409 check_protocols (CLASS_PROTOCOL_LIST (category),
6410 "category",
6411 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6415 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6417 tree decl_specs;
6418 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6419 char *string = (char *) alloca (strlen (class_name) + 3);
6421 /* extern struct objc_object *_<my_name>; */
6423 sprintf (string, "_%s", class_name);
6425 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6426 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6427 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6428 decl_specs);
6432 static tree
6433 add_protocol (protocol)
6434 tree protocol;
6436 /* Put protocol on list in reverse order. */
6437 TREE_CHAIN (protocol) = protocol_chain;
6438 protocol_chain = protocol;
6439 return protocol_chain;
6442 static tree
6443 lookup_protocol (ident)
6444 tree ident;
6446 tree chain;
6448 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6450 if (ident == PROTOCOL_NAME (chain))
6451 return chain;
6454 return NULL_TREE;
6457 tree
6458 start_protocol (code, name, list)
6459 enum tree_code code;
6460 tree name;
6461 tree list;
6463 tree protocol;
6465 if (!doing_objc_thang)
6466 objc_fatal ();
6468 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6469 if (!objc_protocol_template)
6470 objc_protocol_template = build_protocol_template ();
6472 protocol = make_node (code);
6473 TYPE_BINFO (protocol) = make_tree_vec (2);
6475 PROTOCOL_NAME (protocol) = name;
6476 PROTOCOL_LIST (protocol) = list;
6478 lookup_and_install_protocols (list);
6480 if (lookup_protocol (name))
6481 warning ("duplicate declaration for protocol `%s'",
6482 IDENTIFIER_POINTER (name));
6483 else
6484 add_protocol (protocol);
6486 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6488 return protocol;
6491 void
6492 finish_protocol (protocol)
6493 tree protocol ATTRIBUTE_UNUSED;
6498 /* "Encode" a data type into a string, which grows in util_obstack.
6499 ??? What is the FORMAT? Someone please document this! */
6501 static void
6502 encode_type_qualifiers (declspecs)
6503 tree declspecs;
6505 tree spec;
6507 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6509 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6510 obstack_1grow (&util_obstack, 'r');
6511 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6512 obstack_1grow (&util_obstack, 'n');
6513 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6514 obstack_1grow (&util_obstack, 'N');
6515 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6516 obstack_1grow (&util_obstack, 'o');
6517 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6518 obstack_1grow (&util_obstack, 'O');
6519 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6520 obstack_1grow (&util_obstack, 'R');
6521 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6522 obstack_1grow (&util_obstack, 'V');
6526 /* Encode a pointer type. */
6528 static void
6529 encode_pointer (type, curtype, format)
6530 tree type;
6531 int curtype;
6532 int format;
6534 tree pointer_to = TREE_TYPE (type);
6536 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6538 if (TYPE_NAME (pointer_to)
6539 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6541 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6543 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6545 obstack_1grow (&util_obstack, '@');
6546 return;
6548 else if (TREE_STATIC_TEMPLATE (pointer_to))
6550 if (generating_instance_variables)
6552 obstack_1grow (&util_obstack, '@');
6553 obstack_1grow (&util_obstack, '"');
6554 obstack_grow (&util_obstack, name, strlen (name));
6555 obstack_1grow (&util_obstack, '"');
6556 return;
6558 else
6560 obstack_1grow (&util_obstack, '@');
6561 return;
6564 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6566 obstack_1grow (&util_obstack, '#');
6567 return;
6569 #ifndef OBJC_INT_SELECTORS
6570 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6572 obstack_1grow (&util_obstack, ':');
6573 return;
6575 #endif /* OBJC_INT_SELECTORS */
6578 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6579 && TYPE_MODE (pointer_to) == QImode)
6581 obstack_1grow (&util_obstack, '*');
6582 return;
6585 /* We have a type that does not get special treatment. */
6587 /* NeXT extension */
6588 obstack_1grow (&util_obstack, '^');
6589 encode_type (pointer_to, curtype, format);
6592 static void
6593 encode_array (type, curtype, format)
6594 tree type;
6595 int curtype;
6596 int format;
6598 tree an_int_cst = TYPE_SIZE (type);
6599 tree array_of = TREE_TYPE (type);
6600 char buffer[40];
6602 /* An incomplete array is treated like a pointer. */
6603 if (an_int_cst == NULL)
6605 encode_pointer (type, curtype, format);
6606 return;
6609 sprintf (buffer, "[%ld",
6610 (long) (TREE_INT_CST_LOW (an_int_cst)
6611 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6613 obstack_grow (&util_obstack, buffer, strlen (buffer));
6614 encode_type (array_of, curtype, format);
6615 obstack_1grow (&util_obstack, ']');
6616 return;
6619 static void
6620 encode_aggregate_within (type, curtype, format, left, right)
6621 tree type;
6622 int curtype;
6623 int format;
6624 int left;
6625 int right;
6627 if (obstack_object_size (&util_obstack) > 0
6628 && *(obstack_next_free (&util_obstack) - 1) == '^')
6630 tree name = TYPE_NAME (type);
6632 /* we have a reference; this is a NeXT extension. */
6634 if (obstack_object_size (&util_obstack) - curtype == 1
6635 && format == OBJC_ENCODE_INLINE_DEFS)
6637 /* Output format of struct for first level only. */
6638 tree fields = TYPE_FIELDS (type);
6640 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6642 obstack_1grow (&util_obstack, left);
6643 obstack_grow (&util_obstack,
6644 IDENTIFIER_POINTER (name),
6645 strlen (IDENTIFIER_POINTER (name)));
6646 obstack_1grow (&util_obstack, '=');
6648 else
6650 obstack_1grow (&util_obstack, left);
6651 obstack_grow (&util_obstack, "?=", 2);
6654 for ( ; fields; fields = TREE_CHAIN (fields))
6655 encode_field_decl (fields, curtype, format);
6657 obstack_1grow (&util_obstack, right);
6660 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6662 obstack_1grow (&util_obstack, left);
6663 obstack_grow (&util_obstack,
6664 IDENTIFIER_POINTER (name),
6665 strlen (IDENTIFIER_POINTER (name)));
6666 obstack_1grow (&util_obstack, right);
6669 else
6671 /* We have an untagged structure or a typedef. */
6672 obstack_1grow (&util_obstack, left);
6673 obstack_1grow (&util_obstack, '?');
6674 obstack_1grow (&util_obstack, right);
6678 else
6680 tree name = TYPE_NAME (type);
6681 tree fields = TYPE_FIELDS (type);
6683 if (format == OBJC_ENCODE_INLINE_DEFS
6684 || generating_instance_variables)
6686 obstack_1grow (&util_obstack, left);
6687 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6688 obstack_grow (&util_obstack,
6689 IDENTIFIER_POINTER (name),
6690 strlen (IDENTIFIER_POINTER (name)));
6691 else
6692 obstack_1grow (&util_obstack, '?');
6694 obstack_1grow (&util_obstack, '=');
6696 for (; fields; fields = TREE_CHAIN (fields))
6698 if (generating_instance_variables)
6700 tree fname = DECL_NAME (fields);
6702 obstack_1grow (&util_obstack, '"');
6703 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6705 obstack_grow (&util_obstack,
6706 IDENTIFIER_POINTER (fname),
6707 strlen (IDENTIFIER_POINTER (fname)));
6710 obstack_1grow (&util_obstack, '"');
6713 encode_field_decl (fields, curtype, format);
6716 obstack_1grow (&util_obstack, right);
6719 else
6721 obstack_1grow (&util_obstack, left);
6722 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6723 obstack_grow (&util_obstack,
6724 IDENTIFIER_POINTER (name),
6725 strlen (IDENTIFIER_POINTER (name)));
6726 else
6727 /* We have an untagged structure or a typedef. */
6728 obstack_1grow (&util_obstack, '?');
6730 obstack_1grow (&util_obstack, right);
6735 static void
6736 encode_aggregate (type, curtype, format)
6737 tree type;
6738 int curtype;
6739 int format;
6741 enum tree_code code = TREE_CODE (type);
6743 switch (code)
6745 case RECORD_TYPE:
6747 encode_aggregate_within(type, curtype, format, '{', '}');
6748 break;
6750 case UNION_TYPE:
6752 encode_aggregate_within(type, curtype, format, '(', ')');
6753 break;
6756 case ENUMERAL_TYPE:
6757 obstack_1grow (&util_obstack, 'i');
6758 break;
6760 default:
6761 break;
6765 /* Support bitfields. The current version of Objective-C does not support
6766 them. The string will consist of one or more "b:n"'s where n is an
6767 integer describing the width of the bitfield. Currently, classes in
6768 the kit implement a method "-(char *)describeBitfieldStruct:" that
6769 simulates this. If they do not implement this method, the archiver
6770 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6771 according to the GNU compiler. After looking at the "kit", it appears
6772 that all classes currently rely on this default behavior, rather than
6773 hand generating this string (which is tedious). */
6775 static void
6776 encode_bitfield (width, format)
6777 int width;
6778 int format;
6780 char buffer[40];
6781 sprintf (buffer, "b%d", width);
6782 obstack_grow (&util_obstack, buffer, strlen (buffer));
6785 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6787 static void
6788 encode_type (type, curtype, format)
6789 tree type;
6790 int curtype;
6791 int format;
6793 enum tree_code code = TREE_CODE (type);
6795 if (code == INTEGER_TYPE)
6797 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6798 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6800 /* Unsigned integer types. */
6802 if (TYPE_MODE (type) == QImode)
6803 obstack_1grow (&util_obstack, 'C');
6804 else if (TYPE_MODE (type) == HImode)
6805 obstack_1grow (&util_obstack, 'S');
6806 else if (TYPE_MODE (type) == SImode)
6808 if (type == long_unsigned_type_node)
6809 obstack_1grow (&util_obstack, 'L');
6810 else
6811 obstack_1grow (&util_obstack, 'I');
6813 else if (TYPE_MODE (type) == DImode)
6814 obstack_1grow (&util_obstack, 'Q');
6817 else
6818 /* Signed integer types. */
6820 if (TYPE_MODE (type) == QImode)
6821 obstack_1grow (&util_obstack, 'c');
6822 else if (TYPE_MODE (type) == HImode)
6823 obstack_1grow (&util_obstack, 's');
6824 else if (TYPE_MODE (type) == SImode)
6826 if (type == long_integer_type_node)
6827 obstack_1grow (&util_obstack, 'l');
6828 else
6829 obstack_1grow (&util_obstack, 'i');
6832 else if (TYPE_MODE (type) == DImode)
6833 obstack_1grow (&util_obstack, 'q');
6837 else if (code == REAL_TYPE)
6839 /* Floating point types. */
6841 if (TYPE_MODE (type) == SFmode)
6842 obstack_1grow (&util_obstack, 'f');
6843 else if (TYPE_MODE (type) == DFmode
6844 || TYPE_MODE (type) == TFmode)
6845 obstack_1grow (&util_obstack, 'd');
6848 else if (code == VOID_TYPE)
6849 obstack_1grow (&util_obstack, 'v');
6851 else if (code == ARRAY_TYPE)
6852 encode_array (type, curtype, format);
6854 else if (code == POINTER_TYPE)
6855 encode_pointer (type, curtype, format);
6857 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6858 encode_aggregate (type, curtype, format);
6860 else if (code == FUNCTION_TYPE) /* '?' */
6861 obstack_1grow (&util_obstack, '?');
6864 static void
6865 encode_complete_bitfield (int position, tree type, int size)
6867 enum tree_code code = TREE_CODE (type);
6868 char buffer[40];
6869 char charType = '?';
6871 if (code == INTEGER_TYPE)
6873 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6874 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6876 /* Unsigned integer types. */
6878 if (TYPE_MODE (type) == QImode)
6879 charType = 'C';
6880 else if (TYPE_MODE (type) == HImode)
6881 charType = 'S';
6882 else if (TYPE_MODE (type) == SImode)
6884 if (type == long_unsigned_type_node)
6885 charType = 'L';
6886 else
6887 charType = 'I';
6889 else if (TYPE_MODE (type) == DImode)
6890 charType = 'Q';
6893 else
6894 /* Signed integer types. */
6896 if (TYPE_MODE (type) == QImode)
6897 charType = 'c';
6898 else if (TYPE_MODE (type) == HImode)
6899 charType = 's';
6900 else if (TYPE_MODE (type) == SImode)
6902 if (type == long_integer_type_node)
6903 charType = 'l';
6904 else
6905 charType = 'i';
6908 else if (TYPE_MODE (type) == DImode)
6909 charType = 'q';
6913 else
6914 abort ();
6916 sprintf (buffer, "b%d%c%d", position, charType, size);
6917 obstack_grow (&util_obstack, buffer, strlen (buffer));
6920 static void
6921 encode_field_decl (field_decl, curtype, format)
6922 tree field_decl;
6923 int curtype;
6924 int format;
6926 tree type;
6928 type = TREE_TYPE (field_decl);
6930 /* If this field is obviously a bitfield, or is a bitfield that has been
6931 clobbered to look like a ordinary integer mode, go ahead and generate
6932 the bitfield typing information. */
6933 if (flag_next_runtime)
6935 if (DECL_BIT_FIELD (field_decl))
6936 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6937 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6938 && DECL_FIELD_SIZE (field_decl)
6939 && TYPE_MODE (type) > DECL_MODE (field_decl))
6940 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6941 else
6942 encode_type (TREE_TYPE (field_decl), curtype, format);
6944 else
6946 if (DECL_BIT_FIELD (field_decl)
6947 || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6948 && DECL_FIELD_SIZE (field_decl)
6949 && TYPE_MODE (type) > DECL_MODE (field_decl)))
6951 encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)),
6952 DECL_BIT_FIELD_TYPE (field_decl),
6953 DECL_FIELD_SIZE (field_decl));
6955 else
6956 encode_type (TREE_TYPE (field_decl), curtype, format);
6960 static tree
6961 expr_last (complex_expr)
6962 tree complex_expr;
6964 tree next;
6966 if (complex_expr)
6967 while ((next = TREE_OPERAND (complex_expr, 0)))
6968 complex_expr = next;
6970 return complex_expr;
6973 /* The selector of the current method,
6974 or NULL if we aren't compiling a method. */
6976 tree
6977 maybe_objc_method_name (decl)
6978 tree decl;
6980 if (method_context)
6981 return METHOD_SEL_NAME (method_context);
6982 else
6983 return 0;
6986 /* Transform a method definition into a function definition as follows:
6987 - synthesize the first two arguments, "self" and "_cmd". */
6989 void
6990 start_method_def (method)
6991 tree method;
6993 tree decl_specs;
6995 /* Required to implement _msgSuper. */
6996 method_context = method;
6997 UOBJC_SUPER_decl = NULL_TREE;
6999 /* Must be called BEFORE start_function. */
7000 pushlevel (0);
7002 /* Generate prototype declarations for arguments..."new-style". */
7004 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
7005 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7006 else
7007 /* Really a `struct objc_class *'. However, we allow people to
7008 assign to self, which changes its type midstream. */
7009 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7011 push_parm_decl (build_tree_list
7012 (build_tree_list (decl_specs,
7013 build1 (INDIRECT_REF, NULL_TREE, self_id)),
7014 build_tree_list (unused_list, NULL_TREE)));
7016 #ifdef OBJC_INT_SELECTORS
7017 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
7018 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
7019 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
7020 build_tree_list (unused_list, NULL_TREE)));
7021 #else /* not OBJC_INT_SELECTORS */
7022 decl_specs = build_tree_list (NULL_TREE,
7023 xref_tag (RECORD_TYPE,
7024 get_identifier (TAG_SELECTOR)));
7025 push_parm_decl (build_tree_list
7026 (build_tree_list (decl_specs,
7027 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7028 build_tree_list (unused_list, NULL_TREE)));
7029 #endif /* not OBJC_INT_SELECTORS */
7031 /* Generate argument declarations if a keyword_decl. */
7032 if (METHOD_SEL_ARGS (method))
7034 tree arglist = METHOD_SEL_ARGS (method);
7037 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7038 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7040 if (arg_decl)
7042 tree last_expr = expr_last (arg_decl);
7044 /* Unite the abstract decl with its name. */
7045 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7046 push_parm_decl (build_tree_list
7047 (build_tree_list (arg_spec, arg_decl),
7048 build_tree_list (NULL_TREE, NULL_TREE)));
7050 /* Unhook: restore the abstract declarator. */
7051 TREE_OPERAND (last_expr, 0) = NULL_TREE;
7054 else
7055 push_parm_decl (build_tree_list
7056 (build_tree_list (arg_spec,
7057 KEYWORD_ARG_NAME (arglist)),
7058 build_tree_list (NULL_TREE, NULL_TREE)));
7060 arglist = TREE_CHAIN (arglist);
7062 while (arglist);
7065 if (METHOD_ADD_ARGS (method) > (tree)1)
7067 /* We have a variable length selector - in "prototype" format. */
7068 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7069 while (akey)
7071 /* This must be done prior to calling pushdecl. pushdecl is
7072 going to change our chain on us. */
7073 tree nextkey = TREE_CHAIN (akey);
7074 pushdecl (akey);
7075 akey = nextkey;
7080 static void
7081 warn_with_method (message, mtype, method)
7082 char *message;
7083 int mtype;
7084 tree method;
7086 if (count_error (1) == 0)
7087 return;
7089 report_error_function (DECL_SOURCE_FILE (method));
7091 fprintf (stderr, "%s:%d: warning: ",
7092 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
7093 bzero (errbuf, BUFSIZE);
7094 fprintf (stderr, "%s `%c%s'\n",
7095 message, mtype, gen_method_decl (method, errbuf));
7098 /* Return 1 if METHOD is consistent with PROTO. */
7100 static int
7101 comp_method_with_proto (method, proto)
7102 tree method, proto;
7104 static tree function_type = 0;
7106 /* Create a function_type node once. */
7107 if (!function_type)
7109 push_obstacks_nochange ();
7110 end_temporary_allocation ();
7111 function_type = make_node (FUNCTION_TYPE);
7112 pop_obstacks ();
7115 /* Install argument types - normally set by build_function_type. */
7116 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
7118 /* install return type */
7119 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
7121 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
7124 /* Return 1 if PROTO1 is consistent with PROTO2. */
7126 static int
7127 comp_proto_with_proto (proto1, proto2)
7128 tree proto1, proto2;
7130 static tree function_type1 = 0, function_type2 = 0;
7132 /* Create a couple function_type node's once. */
7133 if (!function_type1)
7135 push_obstacks_nochange ();
7136 end_temporary_allocation ();
7137 function_type1 = make_node (FUNCTION_TYPE);
7138 function_type2 = make_node (FUNCTION_TYPE);
7139 pop_obstacks ();
7142 /* Install argument types; normally set by build_function_type. */
7143 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
7144 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
7146 /* Install return type. */
7147 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
7148 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
7150 return comptypes (function_type1, function_type2);
7153 /* - Generate an identifier for the function. the format is "_n_cls",
7154 where 1 <= n <= nMethods, and cls is the name the implementation we
7155 are processing.
7156 - Install the return type from the method declaration.
7157 - If we have a prototype, check for type consistency. */
7159 static void
7160 really_start_method (method, parmlist)
7161 tree method, parmlist;
7163 tree sc_spec, ret_spec, ret_decl, decl_specs;
7164 tree method_decl, method_id;
7165 char *buf, *sel_name, *class_name, *cat_name;
7167 /* Synth the storage class & assemble the return type. */
7168 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7169 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7170 decl_specs = chainon (sc_spec, ret_spec);
7172 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7173 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
7174 cat_name = ((TREE_CODE (implementation_context)
7175 == CLASS_IMPLEMENTATION_TYPE)
7176 ? NULL
7177 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
7178 method_slot++;
7180 /* Make sure this is big enough for any plausible method label. */
7181 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7182 + (cat_name ? strlen (cat_name) : 0));
7184 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7185 class_name, cat_name, sel_name, method_slot);
7187 method_id = get_identifier (buf);
7189 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7191 /* Check the declarator portion of the return type for the method. */
7192 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7194 /* Unite the complex decl (specified in the abstract decl) with the
7195 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7196 tree save_expr = expr_last (ret_decl);
7198 TREE_OPERAND (save_expr, 0) = method_decl;
7199 method_decl = ret_decl;
7201 /* Fool the parser into thinking it is starting a function. */
7202 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7204 /* Unhook: this has the effect of restoring the abstract declarator. */
7205 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7208 else
7210 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7212 /* Fool the parser into thinking it is starting a function. */
7213 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7215 /* Unhook: this has the effect of restoring the abstract declarator. */
7216 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7219 METHOD_DEFINITION (method) = current_function_decl;
7221 if (implementation_template != implementation_context)
7223 tree proto;
7225 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7226 proto = lookup_instance_method_static (implementation_template,
7227 METHOD_SEL_NAME (method));
7228 else
7229 proto = lookup_class_method_static (implementation_template,
7230 METHOD_SEL_NAME (method));
7232 if (proto && ! comp_method_with_proto (method, proto))
7234 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7236 warn_with_method ("conflicting types for", type, method);
7237 warn_with_method ("previous declaration of", type, proto);
7242 /* The following routine is always called...this "architecture" is to
7243 accommodate "old-style" variable length selectors.
7245 - a:a b:b // prototype ; id c; id d; // old-style. */
7247 void
7248 continue_method_def ()
7250 tree parmlist;
7252 if (METHOD_ADD_ARGS (method_context) == (tree)1)
7253 /* We have a `, ...' immediately following the selector. */
7254 parmlist = get_parm_info (0);
7255 else
7256 parmlist = get_parm_info (1); /* place a `void_at_end' */
7258 /* Set self_decl from the first argument...this global is used by
7259 build_ivar_reference calling build_indirect_ref. */
7260 self_decl = TREE_PURPOSE (parmlist);
7262 poplevel (0, 0, 0);
7263 really_start_method (method_context, parmlist);
7264 store_parm_decls ();
7267 /* Called by the parser, from the `pushlevel' production. */
7269 void
7270 add_objc_decls ()
7272 if (!UOBJC_SUPER_decl)
7274 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7275 build_tree_list (NULL_TREE,
7276 objc_super_template),
7277 0, NULL_TREE, NULL_TREE);
7279 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7281 /* This prevents `unused variable' warnings when compiling with -Wall. */
7282 TREE_USED (UOBJC_SUPER_decl) = 1;
7283 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7287 /* _n_Method (id self, SEL sel, ...)
7289 struct objc_super _S;
7290 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7291 } */
7293 tree
7294 get_super_receiver ()
7296 if (method_context)
7298 tree super_expr, super_expr_list;
7300 /* Set receiver to self. */
7301 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7302 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7303 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7305 /* Set class to begin searching. */
7306 super_expr = build_component_ref (UOBJC_SUPER_decl,
7307 get_identifier ("class"));
7309 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7311 /* [_cls, __cls]Super are "pre-built" in
7312 synth_forward_declarations. */
7314 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7315 ((TREE_CODE (method_context)
7316 == INSTANCE_METHOD_DECL)
7317 ? ucls_super_ref
7318 : uucls_super_ref));
7321 else
7322 /* We have a category. */
7324 tree super_name = CLASS_SUPER_NAME (implementation_template);
7325 tree super_class;
7327 if (!super_name)
7329 error ("no super class declared in interface for `%s'",
7330 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7331 return error_mark_node;
7334 if (flag_next_runtime)
7336 super_class = get_class_reference (super_name);
7337 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7338 super_class
7339 = build_component_ref (build_indirect_ref (super_class, "->"),
7340 get_identifier ("isa"));
7342 else
7344 add_class_reference (super_name);
7345 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7346 ? objc_get_class_decl : objc_get_meta_class_decl);
7347 assemble_external (super_class);
7348 super_class
7349 = build_function_call
7350 (super_class,
7351 build_tree_list
7352 (NULL_TREE,
7353 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7354 IDENTIFIER_POINTER (super_name))));
7357 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7358 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7361 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7363 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7364 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7366 return build_compound_expr (super_expr_list);
7368 else
7370 error ("[super ...] must appear in a method context");
7371 return error_mark_node;
7375 static tree
7376 encode_method_def (func_decl)
7377 tree func_decl;
7379 tree parms;
7380 int stack_size;
7381 int max_parm_end = 0;
7382 char buffer[40];
7383 tree result;
7385 /* Return type. */
7386 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7387 obstack_object_size (&util_obstack),
7388 OBJC_ENCODE_INLINE_DEFS);
7390 /* Stack size. */
7391 for (parms = DECL_ARGUMENTS (func_decl); parms;
7392 parms = TREE_CHAIN (parms))
7394 int parm_end = (forwarding_offset (parms)
7395 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
7396 / BITS_PER_UNIT));
7398 if (!offset_is_register && parm_end > max_parm_end)
7399 max_parm_end = parm_end;
7402 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7404 sprintf (buffer, "%d", stack_size);
7405 obstack_grow (&util_obstack, buffer, strlen (buffer));
7407 /* Argument types. */
7408 for (parms = DECL_ARGUMENTS (func_decl); parms;
7409 parms = TREE_CHAIN (parms))
7411 /* Type. */
7412 encode_type (TREE_TYPE (parms),
7413 obstack_object_size (&util_obstack),
7414 OBJC_ENCODE_INLINE_DEFS);
7416 /* Compute offset. */
7417 sprintf (buffer, "%d", forwarding_offset (parms));
7419 /* Indicate register. */
7420 if (offset_is_register)
7421 obstack_1grow (&util_obstack, '+');
7423 obstack_grow (&util_obstack, buffer, strlen (buffer));
7426 obstack_1grow (&util_obstack, 0);
7427 result = get_identifier (obstack_finish (&util_obstack));
7428 obstack_free (&util_obstack, util_firstobj);
7429 return result;
7432 void
7433 finish_method_def ()
7435 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7437 finish_function (0);
7439 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7440 since the optimizer may find "may be used before set" errors. */
7441 method_context = NULL_TREE;
7444 #if 0
7446 lang_report_error_function (decl)
7447 tree decl;
7449 if (method_context)
7451 fprintf (stderr, "In method `%s'\n",
7452 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7453 return 1;
7456 else
7457 return 0;
7459 #endif
7461 static int
7462 is_complex_decl (type)
7463 tree type;
7465 return (TREE_CODE (type) == ARRAY_TYPE
7466 || TREE_CODE (type) == FUNCTION_TYPE
7467 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7471 /* Code to convert a decl node into text for a declaration in C. */
7473 static char tmpbuf[256];
7475 static void
7476 adorn_decl (decl, str)
7477 tree decl;
7478 char *str;
7480 enum tree_code code = TREE_CODE (decl);
7482 if (code == ARRAY_REF)
7484 tree an_int_cst = TREE_OPERAND (decl, 1);
7486 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7487 sprintf (str + strlen (str), "[%ld]",
7488 (long) TREE_INT_CST_LOW (an_int_cst));
7489 else
7490 strcat (str, "[]");
7493 else if (code == ARRAY_TYPE)
7495 tree an_int_cst = TYPE_SIZE (decl);
7496 tree array_of = TREE_TYPE (decl);
7498 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7499 sprintf (str + strlen (str), "[%ld]",
7500 (long) (TREE_INT_CST_LOW (an_int_cst)
7501 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7502 else
7503 strcat (str, "[]");
7506 else if (code == CALL_EXPR)
7508 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7510 strcat (str, "(");
7511 while (chain)
7513 gen_declaration (chain, str);
7514 chain = TREE_CHAIN (chain);
7515 if (chain)
7516 strcat (str, ", ");
7518 strcat (str, ")");
7521 else if (code == FUNCTION_TYPE)
7523 tree chain = TYPE_ARG_TYPES (decl);
7525 strcat (str, "(");
7526 while (chain && TREE_VALUE (chain) != void_type_node)
7528 gen_declaration (TREE_VALUE (chain), str);
7529 chain = TREE_CHAIN (chain);
7530 if (chain && TREE_VALUE (chain) != void_type_node)
7531 strcat (str, ", ");
7533 strcat (str, ")");
7536 else if (code == INDIRECT_REF)
7538 strcpy (tmpbuf, "*");
7539 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7541 tree chain;
7543 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7544 chain;
7545 chain = TREE_CHAIN (chain))
7547 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7549 strcat (tmpbuf, " ");
7550 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7553 if (str[0])
7554 strcat (tmpbuf, " ");
7556 strcat (tmpbuf, str);
7557 strcpy (str, tmpbuf);
7560 else if (code == POINTER_TYPE)
7562 strcpy (tmpbuf, "*");
7563 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7565 if (TREE_READONLY (decl))
7566 strcat (tmpbuf, " const");
7567 if (TYPE_VOLATILE (decl))
7568 strcat (tmpbuf, " volatile");
7569 if (str[0])
7570 strcat (tmpbuf, " ");
7572 strcat (tmpbuf, str);
7573 strcpy (str, tmpbuf);
7577 static char *
7578 gen_declarator (decl, buf, name)
7579 tree decl;
7580 char *buf;
7581 char *name;
7583 if (decl)
7585 enum tree_code code = TREE_CODE (decl);
7586 char *str;
7587 tree op;
7588 int wrap = 0;
7590 switch (code)
7592 case ARRAY_REF:
7593 case INDIRECT_REF:
7594 case CALL_EXPR:
7595 op = TREE_OPERAND (decl, 0);
7597 /* We have a pointer to a function or array...(*)(), (*)[] */
7598 if ((code == ARRAY_REF || code == CALL_EXPR)
7599 && op && TREE_CODE (op) == INDIRECT_REF)
7600 wrap = 1;
7602 str = gen_declarator (op, buf, name);
7604 if (wrap)
7606 strcpy (tmpbuf, "(");
7607 strcat (tmpbuf, str);
7608 strcat (tmpbuf, ")");
7609 strcpy (str, tmpbuf);
7612 adorn_decl (decl, str);
7613 break;
7615 case ARRAY_TYPE:
7616 case FUNCTION_TYPE:
7617 case POINTER_TYPE:
7618 strcpy (buf, name);
7619 str = buf;
7621 /* This clause is done iteratively rather than recursively. */
7624 op = (is_complex_decl (TREE_TYPE (decl))
7625 ? TREE_TYPE (decl) : NULL_TREE);
7627 adorn_decl (decl, str);
7629 /* We have a pointer to a function or array...(*)(), (*)[] */
7630 if (code == POINTER_TYPE
7631 && op && (TREE_CODE (op) == FUNCTION_TYPE
7632 || TREE_CODE (op) == ARRAY_TYPE))
7634 strcpy (tmpbuf, "(");
7635 strcat (tmpbuf, str);
7636 strcat (tmpbuf, ")");
7637 strcpy (str, tmpbuf);
7640 decl = (is_complex_decl (TREE_TYPE (decl))
7641 ? TREE_TYPE (decl) : NULL_TREE);
7644 while (decl && (code = TREE_CODE (decl)))
7647 break;
7649 case IDENTIFIER_NODE:
7650 /* Will only happen if we are processing a "raw" expr-decl. */
7651 strcpy (buf, IDENTIFIER_POINTER (decl));
7652 return buf;
7654 default:
7655 abort ();
7658 return str;
7661 else
7662 /* We have an abstract declarator or a _DECL node. */
7664 strcpy (buf, name);
7665 return buf;
7669 static void
7670 gen_declspecs (declspecs, buf, raw)
7671 tree declspecs;
7672 char *buf;
7673 int raw;
7675 if (raw)
7677 tree chain;
7679 for (chain = nreverse (copy_list (declspecs));
7680 chain; chain = TREE_CHAIN (chain))
7682 tree aspec = TREE_VALUE (chain);
7684 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7685 strcat (buf, IDENTIFIER_POINTER (aspec));
7686 else if (TREE_CODE (aspec) == RECORD_TYPE)
7688 if (TYPE_NAME (aspec))
7690 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7692 if (! TREE_STATIC_TEMPLATE (aspec))
7693 strcat (buf, "struct ");
7694 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7696 /* NEW!!! */
7697 if (protocol_list)
7699 tree chain = protocol_list;
7701 strcat (buf, " <");
7702 while (chain)
7704 strcat (buf,
7705 IDENTIFIER_POINTER
7706 (PROTOCOL_NAME (TREE_VALUE (chain))));
7707 chain = TREE_CHAIN (chain);
7708 if (chain)
7709 strcat (buf, ", ");
7711 strcat (buf, ">");
7715 else
7716 strcat (buf, "untagged struct");
7719 else if (TREE_CODE (aspec) == UNION_TYPE)
7721 if (TYPE_NAME (aspec))
7723 if (! TREE_STATIC_TEMPLATE (aspec))
7724 strcat (buf, "union ");
7725 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7727 else
7728 strcat (buf, "untagged union");
7731 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7733 if (TYPE_NAME (aspec))
7735 if (! TREE_STATIC_TEMPLATE (aspec))
7736 strcat (buf, "enum ");
7737 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7739 else
7740 strcat (buf, "untagged enum");
7743 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7744 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7746 else if (IS_ID (aspec))
7748 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7750 strcat (buf, "id");
7751 if (protocol_list)
7753 tree chain = protocol_list;
7755 strcat (buf, " <");
7756 while (chain)
7758 strcat (buf,
7759 IDENTIFIER_POINTER
7760 (PROTOCOL_NAME (TREE_VALUE (chain))));
7761 chain = TREE_CHAIN (chain);
7762 if (chain)
7763 strcat (buf, ", ");
7765 strcat (buf, ">");
7768 if (TREE_CHAIN (chain))
7769 strcat (buf, " ");
7772 else
7774 /* Type qualifiers. */
7775 if (TREE_READONLY (declspecs))
7776 strcat (buf, "const ");
7777 if (TYPE_VOLATILE (declspecs))
7778 strcat (buf, "volatile ");
7780 switch (TREE_CODE (declspecs))
7782 /* Type specifiers. */
7784 case INTEGER_TYPE:
7785 declspecs = TYPE_MAIN_VARIANT (declspecs);
7787 /* Signed integer types. */
7789 if (declspecs == short_integer_type_node)
7790 strcat (buf, "short int ");
7791 else if (declspecs == integer_type_node)
7792 strcat (buf, "int ");
7793 else if (declspecs == long_integer_type_node)
7794 strcat (buf, "long int ");
7795 else if (declspecs == long_long_integer_type_node)
7796 strcat (buf, "long long int ");
7797 else if (declspecs == signed_char_type_node
7798 || declspecs == char_type_node)
7799 strcat (buf, "char ");
7801 /* Unsigned integer types. */
7803 else if (declspecs == short_unsigned_type_node)
7804 strcat (buf, "unsigned short ");
7805 else if (declspecs == unsigned_type_node)
7806 strcat (buf, "unsigned int ");
7807 else if (declspecs == long_unsigned_type_node)
7808 strcat (buf, "unsigned long ");
7809 else if (declspecs == long_long_unsigned_type_node)
7810 strcat (buf, "unsigned long long ");
7811 else if (declspecs == unsigned_char_type_node)
7812 strcat (buf, "unsigned char ");
7813 break;
7815 case REAL_TYPE:
7816 declspecs = TYPE_MAIN_VARIANT (declspecs);
7818 if (declspecs == float_type_node)
7819 strcat (buf, "float ");
7820 else if (declspecs == double_type_node)
7821 strcat (buf, "double ");
7822 else if (declspecs == long_double_type_node)
7823 strcat (buf, "long double ");
7824 break;
7826 case RECORD_TYPE:
7827 if (TYPE_NAME (declspecs)
7828 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7830 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7832 if (! TREE_STATIC_TEMPLATE (declspecs))
7833 strcat (buf, "struct ");
7834 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7836 if (protocol_list)
7838 tree chain = protocol_list;
7840 strcat (buf, " <");
7841 while (chain)
7843 strcat (buf,
7844 IDENTIFIER_POINTER
7845 (PROTOCOL_NAME (TREE_VALUE (chain))));
7846 chain = TREE_CHAIN (chain);
7847 if (chain)
7848 strcat (buf, ", ");
7850 strcat (buf, ">");
7854 else
7855 strcat (buf, "untagged struct");
7857 strcat (buf, " ");
7858 break;
7860 case UNION_TYPE:
7861 if (TYPE_NAME (declspecs)
7862 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7864 strcat (buf, "union ");
7865 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7866 strcat (buf, " ");
7869 else
7870 strcat (buf, "untagged union ");
7871 break;
7873 case ENUMERAL_TYPE:
7874 if (TYPE_NAME (declspecs)
7875 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7877 strcat (buf, "enum ");
7878 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7879 strcat (buf, " ");
7882 else
7883 strcat (buf, "untagged enum ");
7884 break;
7886 case VOID_TYPE:
7887 strcat (buf, "void ");
7888 break;
7890 case POINTER_TYPE:
7892 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7894 strcat (buf, "id");
7895 if (protocol_list)
7897 tree chain = protocol_list;
7899 strcat (buf, " <");
7900 while (chain)
7902 strcat (buf,
7903 IDENTIFIER_POINTER
7904 (PROTOCOL_NAME (TREE_VALUE (chain))));
7905 chain = TREE_CHAIN (chain);
7906 if (chain)
7907 strcat (buf, ", ");
7910 strcat (buf, ">");
7913 break;
7915 default:
7916 break;
7921 static char *
7922 gen_declaration (atype_or_adecl, buf)
7923 tree atype_or_adecl;
7924 char *buf;
7926 char declbuf[256];
7928 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7930 tree declspecs; /* "identifier_node", "record_type" */
7931 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7933 /* We have a "raw", abstract declarator (typename). */
7934 declarator = TREE_VALUE (atype_or_adecl);
7935 declspecs = TREE_PURPOSE (atype_or_adecl);
7937 gen_declspecs (declspecs, buf, 1);
7938 if (declarator)
7940 strcat (buf, " ");
7941 strcat (buf, gen_declarator (declarator, declbuf, ""));
7945 else
7947 tree atype;
7948 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7949 tree declarator; /* "array_type", "function_type", "pointer_type". */
7951 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7952 || TREE_CODE (atype_or_adecl) == PARM_DECL
7953 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7954 atype = TREE_TYPE (atype_or_adecl);
7955 else
7956 /* Assume we have a *_type node. */
7957 atype = atype_or_adecl;
7959 if (is_complex_decl (atype))
7961 tree chain;
7963 /* Get the declaration specifier; it is at the end of the list. */
7964 declarator = chain = atype;
7966 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7967 while (is_complex_decl (chain));
7968 declspecs = chain;
7971 else
7973 declspecs = atype;
7974 declarator = NULL_TREE;
7977 gen_declspecs (declspecs, buf, 0);
7979 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7980 || TREE_CODE (atype_or_adecl) == PARM_DECL
7981 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7983 char *decl_name = (DECL_NAME (atype_or_adecl)
7984 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
7985 : "");
7987 if (declarator)
7989 strcat (buf, " ");
7990 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7993 else if (decl_name[0])
7995 strcat (buf, " ");
7996 strcat (buf, decl_name);
7999 else if (declarator)
8001 strcat (buf, " ");
8002 strcat (buf, gen_declarator (declarator, declbuf, ""));
8006 return buf;
8009 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8011 static char *
8012 gen_method_decl (method, buf)
8013 tree method;
8014 char *buf;
8016 tree chain;
8018 if (RAW_TYPESPEC (method) != objc_object_reference)
8020 strcpy (buf, "(");
8021 gen_declaration (TREE_TYPE (method), buf);
8022 strcat (buf, ")");
8025 chain = METHOD_SEL_ARGS (method);
8026 if (chain)
8028 /* We have a chain of keyword_decls. */
8031 if (KEYWORD_KEY_NAME (chain))
8032 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8034 strcat (buf, ":");
8035 if (RAW_TYPESPEC (chain) != objc_object_reference)
8037 strcat (buf, "(");
8038 gen_declaration (TREE_TYPE (chain), buf);
8039 strcat (buf, ")");
8042 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8043 if ((chain = TREE_CHAIN (chain)))
8044 strcat (buf, " ");
8046 while (chain);
8048 if (METHOD_ADD_ARGS (method) == (tree)1)
8049 strcat (buf, ", ...");
8050 else if (METHOD_ADD_ARGS (method))
8052 /* We have a tree list node as generate by get_parm_info. */
8053 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8055 /* Know we have a chain of parm_decls. */
8056 while (chain)
8058 strcat (buf, ", ");
8059 gen_declaration (chain, buf);
8060 chain = TREE_CHAIN (chain);
8065 else
8066 /* We have a unary selector. */
8067 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8069 return buf;
8072 /* Debug info. */
8074 static void
8075 dump_interface (fp, chain)
8076 FILE *fp;
8077 tree chain;
8079 char *buf = (char *)xmalloc (256);
8080 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8081 tree ivar_decls = CLASS_RAW_IVARS (chain);
8082 tree nst_methods = CLASS_NST_METHODS (chain);
8083 tree cls_methods = CLASS_CLS_METHODS (chain);
8085 fprintf (fp, "\n@interface %s", my_name);
8087 if (CLASS_SUPER_NAME (chain))
8089 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8090 fprintf (fp, " : %s\n", super_name);
8092 else
8093 fprintf (fp, "\n");
8095 if (ivar_decls)
8097 fprintf (fp, "{\n");
8100 bzero (buf, 256);
8101 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8102 ivar_decls = TREE_CHAIN (ivar_decls);
8104 while (ivar_decls);
8105 fprintf (fp, "}\n");
8108 while (nst_methods)
8110 bzero (buf, 256);
8111 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8112 nst_methods = TREE_CHAIN (nst_methods);
8115 while (cls_methods)
8117 bzero (buf, 256);
8118 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8119 cls_methods = TREE_CHAIN (cls_methods);
8121 fprintf (fp, "\n@end");
8124 /* Demangle function for Objective-C */
8125 static const char *
8126 objc_demangle (mangled)
8127 const char *mangled;
8129 char *demangled, *cp;
8131 if (mangled[0] == '_' &&
8132 (mangled[1] == 'i' || mangled[1] == 'c') &&
8133 mangled[2] == '_')
8135 cp = demangled = xmalloc(strlen(mangled) + 2);
8136 if (mangled[1] == 'i')
8137 *cp++ = '-'; /* for instance method */
8138 else
8139 *cp++ = '+'; /* for class method */
8140 *cp++ = '['; /* opening left brace */
8141 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8142 while (*cp && *cp == '_')
8143 cp++; /* skip any initial underbars in class name */
8144 cp = strchr(cp, '_'); /* find first non-initial underbar */
8145 if (cp == NULL)
8147 free(demangled); /* not mangled name */
8148 return mangled;
8150 if (cp[1] == '_') /* easy case: no category name */
8152 *cp++ = ' '; /* replace two '_' with one ' ' */
8153 strcpy(cp, mangled + (cp - demangled) + 2);
8155 else
8157 *cp++ = '('; /* less easy case: category name */
8158 cp = strchr(cp, '_');
8159 if (cp == 0)
8161 free(demangled); /* not mangled name */
8162 return mangled;
8164 *cp++ = ')';
8165 *cp++ = ' '; /* overwriting 1st char of method name... */
8166 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8168 while (*cp && *cp == '_')
8169 cp++; /* skip any initial underbars in method name */
8170 for (; *cp; cp++)
8171 if (*cp == '_')
8172 *cp = ':'; /* replace remaining '_' with ':' */
8173 *cp++ = ']'; /* closing right brace */
8174 *cp++ = 0; /* string terminator */
8175 return demangled;
8177 else
8178 return mangled; /* not an objc mangled name */
8181 static const char *
8182 objc_printable_name (decl, kind)
8183 tree decl;
8184 char **kind;
8186 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8189 static void
8190 init_objc ()
8192 /* Add the special tree codes of Objective C to the tables. */
8194 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
8196 gcc_obstack_init (&util_obstack);
8197 util_firstobj = (char *) obstack_finish (&util_obstack);
8199 bcopy (objc_tree_code_type,
8200 tree_code_type + (int) LAST_CODE,
8201 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
8202 bcopy ((char *) objc_tree_code_length,
8203 (char *) (tree_code_length + (int) LAST_CODE),
8204 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8205 * sizeof (int)));
8206 bcopy ((char *) objc_tree_code_name,
8207 (char *) (tree_code_name + (int) LAST_CODE),
8208 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8209 * sizeof (char *)));
8211 errbuf = (char *)xmalloc (BUFSIZE);
8212 hash_init ();
8213 synth_module_prologue ();
8215 /* Change the default error function */
8216 decl_printable_name = (char* (*)()) objc_printable_name;
8219 static void
8220 finish_objc ()
8222 struct imp_entry *impent;
8223 tree chain;
8224 /* The internally generated initializers appear to have missing braces.
8225 Don't warn about this. */
8226 int save_warn_missing_braces = warn_missing_braces;
8227 warn_missing_braces = 0;
8229 generate_forward_declaration_to_string_table ();
8231 #ifdef OBJC_PROLOGUE
8232 OBJC_PROLOGUE;
8233 #endif
8235 /* Process the static instances here because initialization of objc_symtab
8236 depends on them. */
8237 if (objc_static_instances)
8238 generate_static_references ();
8240 if (implementation_context || class_names_chain
8241 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8242 generate_objc_symtab_decl ();
8244 for (impent = imp_list; impent; impent = impent->next)
8246 implementation_context = impent->imp_context;
8247 implementation_template = impent->imp_template;
8249 UOBJC_CLASS_decl = impent->class_decl;
8250 UOBJC_METACLASS_decl = impent->meta_decl;
8252 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8254 /* all of the following reference the string pool... */
8255 generate_ivar_lists ();
8256 generate_dispatch_tables ();
8257 generate_shared_structures ();
8259 else
8261 generate_dispatch_tables ();
8262 generate_category (implementation_context);
8266 /* If we are using an array of selectors, we must always
8267 finish up the array decl even if no selectors were used. */
8268 if (! flag_next_runtime || sel_ref_chain)
8269 build_selector_translation_table ();
8271 if (protocol_chain)
8272 generate_protocols ();
8274 if (implementation_context || class_names_chain || objc_static_instances
8275 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8277 /* Arrange for Objc data structures to be initialized at run time. */
8278 char *init_name = build_module_descriptor ();
8279 if (init_name)
8280 assemble_constructor (init_name);
8283 /* Dump the class references. This forces the appropriate classes
8284 to be linked into the executable image, preserving unix archive
8285 semantics. This can be removed when we move to a more dynamically
8286 linked environment. */
8288 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8290 handle_class_ref (chain);
8291 if (TREE_PURPOSE (chain))
8292 generate_classref_translation_entry (chain);
8295 for (impent = imp_list; impent; impent = impent->next)
8296 handle_impent (impent);
8298 /* Dump the string table last. */
8300 generate_strings ();
8302 if (flag_gen_declaration)
8304 add_class (implementation_context);
8305 dump_interface (gen_declaration_file, implementation_context);
8308 if (warn_selector)
8310 int slot;
8311 hash hsh;
8313 /* Run through the selector hash tables and print a warning for any
8314 selector which has multiple methods. */
8316 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8317 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8318 if (hsh->list)
8320 tree meth = hsh->key;
8321 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8322 ? '-' : '+');
8323 attr loop;
8325 warning ("potential selector conflict for method `%s'",
8326 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8327 warn_with_method ("found", type, meth);
8328 for (loop = hsh->list; loop; loop = loop->next)
8329 warn_with_method ("found", type, loop->value);
8332 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8333 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8334 if (hsh->list)
8336 tree meth = hsh->key;
8337 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8338 ? '-' : '+');
8339 attr loop;
8341 warning ("potential selector conflict for method `%s'",
8342 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8343 warn_with_method ("found", type, meth);
8344 for (loop = hsh->list; loop; loop = loop->next)
8345 warn_with_method ("found", type, loop->value);
8349 warn_missing_braces = save_warn_missing_braces;
8352 /* Subroutines of finish_objc. */
8354 static void
8355 generate_classref_translation_entry (chain)
8356 tree chain;
8358 tree expr, name, decl_specs, decl, sc_spec;
8359 tree type;
8361 type = TREE_TYPE (TREE_PURPOSE (chain));
8363 expr = add_objc_string (TREE_VALUE (chain), class_names);
8364 expr = build_c_cast (type, expr); /* cast! */
8366 name = DECL_NAME (TREE_PURPOSE (chain));
8368 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8370 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8371 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8373 /* The decl that is returned from start_decl is the one that we
8374 forward declared in build_class_reference. */
8375 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8376 finish_decl (decl, expr, NULL_TREE);
8377 return;
8380 static void
8381 handle_class_ref (chain)
8382 tree chain;
8384 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8385 if (! flag_next_runtime)
8387 tree decl;
8388 char *string = (char *) alloca (strlen (name) + 30);
8389 tree exp;
8391 sprintf (string, "%sobjc_class_name_%s",
8392 (flag_next_runtime ? "." : "__"), name);
8394 /* Make a decl for this name, so we can use its address in a tree. */
8395 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8396 DECL_EXTERNAL (decl) = 1;
8397 TREE_PUBLIC (decl) = 1;
8399 pushdecl (decl);
8400 rest_of_decl_compilation (decl, 0, 0, 0);
8402 /* Make following constant read-only (why not)? */
8403 readonly_data_section ();
8405 exp = build1 (ADDR_EXPR, string_type_node, decl);
8407 /* Align the section properly. */
8408 assemble_constant_align (exp);
8410 /* Inform the assembler about this new external thing. */
8411 assemble_external (decl);
8413 /* Output a constant to reference this address. */
8414 output_constant (exp, int_size_in_bytes (string_type_node));
8416 else
8418 /* This overreliance on our assembler (i.e. lack of portability)
8419 should be dealt with at some point. The GNU strategy (above)
8420 won't work either, but it is a start. */
8421 char *string = (char *) alloca (strlen (name) + 30);
8422 sprintf (string, ".reference .objc_class_name_%s", name);
8423 assemble_asm (my_build_string (strlen (string) + 1, string));
8427 static void
8428 handle_impent (impent)
8429 struct imp_entry *impent;
8431 implementation_context = impent->imp_context;
8432 implementation_template = impent->imp_template;
8434 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8436 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8437 char *string = (char *) alloca (strlen (class_name) + 30);
8439 if (flag_next_runtime)
8441 /* Grossly unportable.
8442 People should know better than to assume
8443 such things about assembler syntax! */
8444 sprintf (string, ".objc_class_name_%s=0", class_name);
8445 assemble_asm (my_build_string (strlen (string) + 1, string));
8447 sprintf (string, ".globl .objc_class_name_%s", class_name);
8448 assemble_asm (my_build_string (strlen (string) + 1, string));
8451 else
8453 sprintf (string, "%sobjc_class_name_%s",
8454 (flag_next_runtime ? "." : "__"), class_name);
8455 assemble_global (string);
8456 assemble_label (string);
8460 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8462 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8463 char *class_super_name
8464 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8465 char *string = (char *) alloca (strlen (class_name)
8466 + strlen (class_super_name) + 30);
8468 /* Do the same for categories. Even though no references to these
8469 symbols are generated automatically by the compiler, it gives
8470 you a handle to pull them into an archive by hand. */
8471 if (flag_next_runtime)
8473 /* Grossly unportable. */
8474 sprintf (string, ".objc_category_name_%s_%s=0",
8475 class_name, class_super_name);
8476 assemble_asm (my_build_string (strlen (string) + 1, string));
8478 sprintf (string, ".globl .objc_category_name_%s_%s",
8479 class_name, class_super_name);
8480 assemble_asm (my_build_string (strlen (string) + 1, string));
8483 else
8485 sprintf (string, "%sobjc_category_name_%s_%s",
8486 (flag_next_runtime ? "." : "__"),
8487 class_name, class_super_name);
8488 assemble_global (string);
8489 assemble_label (string);
8494 #ifdef DEBUG
8496 static void
8497 objc_debug (fp)
8498 FILE *fp;
8500 char *buf = (char *)xmalloc (256);
8502 { /* dump function prototypes */
8503 tree loop = UOBJC_MODULES_decl;
8505 fprintf (fp, "\n\nfunction prototypes:\n");
8506 while (loop)
8508 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8510 /* We have a function definition: generate prototype. */
8511 bzero (errbuf, BUFSIZE);
8512 gen_declaration (loop, errbuf);
8513 fprintf (fp, "%s;\n", errbuf);
8515 loop = TREE_CHAIN (loop);
8519 /* Dump global chains. */
8520 tree loop;
8521 int i, index = 0, offset = 0;
8522 hash hashlist;
8524 for (i = 0; i < SIZEHASHTABLE; i++)
8526 if (hashlist = nst_method_hash_list[i])
8528 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8531 bzero (buf, 256);
8532 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8533 hashlist = hashlist->next;
8535 while (hashlist);
8539 for (i = 0; i < SIZEHASHTABLE; i++)
8541 if (hashlist = cls_method_hash_list[i])
8543 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8546 bzero (buf, 256);
8547 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8548 hashlist = hashlist->next;
8550 while (hashlist);
8554 fprintf (fp, "\nsel_refdef_chain:\n");
8555 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8557 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8558 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8559 index++;
8560 /* add one for the '\0' character */
8561 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8564 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8567 #endif
8569 void
8570 print_lang_statistics ()