Undo June 11th change
[official-gcc.git] / gcc / objc / objc-act.c
blobe1cde90b094c3da90e9b0f4aeebc5acf432d6412
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 static int cpp_initialized;
59 #endif
61 /* This is the default way of generating a method name. */
62 /* I am not sure it is really correct.
63 Perhaps there's a danger that it will make name conflicts
64 if method names contain underscores. -- rms. */
65 #ifndef OBJC_GEN_METHOD_LABEL
66 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
67 do { \
68 char *temp; \
69 sprintf ((BUF), "_%s_%s_%s_%s", \
70 ((IS_INST) ? "i" : "c"), \
71 (CLASS_NAME), \
72 ((CAT_NAME)? (CAT_NAME) : ""), \
73 (SEL_NAME)); \
74 for (temp = (BUF); *temp; temp++) \
75 if (*temp == ':') *temp = '_'; \
76 } while (0)
77 #endif
79 /* These need specifying. */
80 #ifndef OBJC_FORWARDING_STACK_OFFSET
81 #define OBJC_FORWARDING_STACK_OFFSET 0
82 #endif
84 #ifndef OBJC_FORWARDING_MIN_OFFSET
85 #define OBJC_FORWARDING_MIN_OFFSET 0
86 #endif
88 /* Define the special tree codes that we use. */
90 /* Table indexed by tree code giving a string containing a character
91 classifying the tree code. Possibilities are
92 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
94 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
96 char objc_tree_code_type[] = {
97 'x',
98 #include "objc-tree.def"
100 #undef DEFTREECODE
102 /* Table indexed by tree code giving number of expression
103 operands beyond the fixed part of the node structure.
104 Not used for types or decls. */
106 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
108 int objc_tree_code_length[] = {
110 #include "objc-tree.def"
112 #undef DEFTREECODE
114 /* Names of tree components.
115 Used for printing out the tree and error messages. */
116 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
118 char *objc_tree_code_name[] = {
119 "@@dummy",
120 #include "objc-tree.def"
122 #undef DEFTREECODE
124 /* Set up for use of obstacks. */
126 #include "obstack.h"
128 #define obstack_chunk_alloc xmalloc
129 #define obstack_chunk_free free
131 /* This obstack is used to accumulate the encoding of a data type. */
132 static struct obstack util_obstack;
133 /* This points to the beginning of obstack contents,
134 so we can free the whole contents. */
135 char *util_firstobj;
137 /* List of classes with list of their static instances. */
138 static tree objc_static_instances = NULL_TREE;
140 /* The declaration of the array administrating the static instances. */
141 static tree static_instances_decl = NULL_TREE;
143 /* for encode_method_def */
144 #include "rtl.h"
145 #include "c-parse.h"
147 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
148 #define PROTOCOL_VERSION 2
150 #define OBJC_ENCODE_INLINE_DEFS 0
151 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
153 /*** Private Interface (procedures) ***/
155 /* Used by compile_file. */
157 static void init_objc PROTO((void));
158 static void finish_objc PROTO((void));
160 /* Code generation. */
162 static void synth_module_prologue PROTO((void));
163 static tree build_constructor PROTO((tree, tree));
164 static char *build_module_descriptor PROTO((void));
165 static tree init_module_descriptor PROTO((tree));
166 static tree build_objc_method_call PROTO((int, tree, tree,
167 tree, tree, tree));
168 static void generate_strings PROTO((void));
169 static tree get_proto_encoding PROTO((tree));
170 static void build_selector_translation_table PROTO((void));
171 static tree build_ivar_chain PROTO((tree, int));
173 static tree objc_add_static_instance PROTO((tree, tree));
175 static tree build_ivar_template PROTO((void));
176 static tree build_method_template PROTO((void));
177 static tree build_private_template PROTO((tree));
178 static void build_class_template PROTO((void));
179 static void build_selector_template PROTO((void));
180 static void build_category_template PROTO((void));
181 static tree build_super_template PROTO((void));
182 static tree build_category_initializer PROTO((tree, tree, tree,
183 tree, tree, tree));
184 static tree build_protocol_initializer PROTO((tree, tree, tree,
185 tree, tree));
187 static void synth_forward_declarations PROTO((void));
188 static void generate_ivar_lists PROTO((void));
189 static void generate_dispatch_tables PROTO((void));
190 static void generate_shared_structures PROTO((void));
191 static tree generate_protocol_list PROTO((tree));
192 static void generate_forward_declaration_to_string_table PROTO((void));
193 static void build_protocol_reference PROTO((tree));
195 static tree init_selector PROTO((int));
196 static tree build_keyword_selector PROTO((tree));
197 static tree synth_id_with_class_suffix PROTO((char *, tree));
199 static void generate_static_references PROTO((void));
200 static int check_methods_accessible PROTO((tree, tree,
201 int));
202 static void encode_aggregate_within PROTO((tree, int, int,
203 int, int));
205 /* We handle printing method names ourselves for ObjC */
206 extern char *(*decl_printable_name) ();
208 /* Misc. bookkeeping */
210 typedef struct hashed_entry *hash;
211 typedef struct hashed_attribute *attr;
213 struct hashed_attribute
215 attr next;
216 tree value;
218 struct hashed_entry
220 attr list;
221 hash next;
222 tree key;
225 static void hash_init PROTO((void));
226 static void hash_enter PROTO((hash *, tree));
227 static hash hash_lookup PROTO((hash *, tree));
228 static void hash_add_attr PROTO((hash, tree));
229 static tree lookup_method PROTO((tree, tree));
230 static tree lookup_instance_method_static PROTO((tree, tree));
231 static tree lookup_class_method_static PROTO((tree, tree));
232 static tree add_class PROTO((tree));
233 static void add_category PROTO((tree, tree));
235 enum string_section
237 class_names, /* class, category, protocol, module names */
238 meth_var_names, /* method and variable names */
239 meth_var_types /* method and variable type descriptors */
242 static tree add_objc_string PROTO((tree,
243 enum string_section));
244 static tree get_objc_string_decl PROTO((tree,
245 enum string_section));
246 static tree build_objc_string_decl PROTO((tree,
247 enum string_section));
248 static tree build_selector_reference_decl PROTO((tree));
250 /* Protocol additions. */
252 static tree add_protocol PROTO((tree));
253 static tree lookup_protocol PROTO((tree));
254 static tree lookup_and_install_protocols PROTO((tree));
256 /* Type encoding. */
258 static void encode_type_qualifiers PROTO((tree));
259 static void encode_pointer PROTO((tree, int, int));
260 static void encode_array PROTO((tree, int, int));
261 static void encode_aggregate PROTO((tree, int, int));
262 static void encode_bitfield PROTO((int, int));
263 static void encode_type PROTO((tree, int, int));
264 static void encode_field_decl PROTO((tree, int, int));
266 static void really_start_method PROTO((tree, tree));
267 static int comp_method_with_proto PROTO((tree, tree));
268 static int comp_proto_with_proto PROTO((tree, tree));
269 static tree get_arg_type_list PROTO((tree, int, int));
270 static tree expr_last PROTO((tree));
272 /* Utilities for debugging and error diagnostics. */
274 static void warn_with_method PROTO((char *, int, tree));
275 static void error_with_ivar PROTO((char *, tree, tree));
276 static char *gen_method_decl PROTO((tree, char *));
277 static char *gen_declaration PROTO((tree, char *));
278 static char *gen_declarator PROTO((tree, char *, char *));
279 static int is_complex_decl PROTO((tree));
280 static void adorn_decl PROTO((tree, char *));
281 static void dump_interface PROTO((FILE *, tree));
283 /* Everything else. */
285 static void objc_fatal PROTO((void));
286 static tree define_decl PROTO((tree, tree));
287 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
288 static tree lookup_protocol_in_reflist PROTO((tree, tree));
289 static tree create_builtin_decl PROTO((enum tree_code,
290 tree, char *));
291 static tree my_build_string PROTO((int, char *));
292 static void build_objc_symtab_template PROTO((void));
293 static tree init_def_list PROTO((tree));
294 static tree init_objc_symtab PROTO((tree));
295 static void forward_declare_categories PROTO((void));
296 static void generate_objc_symtab_decl PROTO((void));
297 static tree build_selector PROTO((tree));
298 static tree build_msg_pool_reference PROTO((int));
299 static tree build_typed_selector_reference PROTO((tree, tree));
300 static tree build_selector_reference PROTO((tree));
301 static tree build_class_reference_decl PROTO((tree));
302 static void add_class_reference PROTO((tree));
303 static tree objc_copy_list PROTO((tree, tree *));
304 static tree build_protocol_template PROTO((void));
305 static tree build_descriptor_table_initializer PROTO((tree, tree));
306 static tree build_method_prototype_list_template PROTO((tree, int));
307 static tree build_method_prototype_template PROTO((void));
308 static int forwarding_offset PROTO((tree));
309 static tree encode_method_prototype PROTO((tree, tree));
310 static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree));
311 static void generate_method_descriptors PROTO((tree));
312 static tree build_tmp_function_decl PROTO((void));
313 static void hack_method_prototype PROTO((tree, tree));
314 static void generate_protocol_references PROTO((tree));
315 static void generate_protocols PROTO((void));
316 static void check_ivars PROTO((tree, tree));
317 static tree build_ivar_list_template PROTO((tree, int));
318 static tree build_method_list_template PROTO((tree, int));
319 static tree build_ivar_list_initializer PROTO((tree, tree));
320 static tree generate_ivars_list PROTO((tree, char *,
321 int, tree));
322 static tree build_dispatch_table_initializer PROTO((tree, tree));
323 static tree generate_dispatch_table PROTO((tree, char *,
324 int, tree));
325 static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree,
326 tree, int, tree, tree,
327 tree));
328 static void generate_category PROTO((tree));
329 static int is_objc_type_qualifier PROTO((tree));
330 static tree adjust_type_for_id_default PROTO((tree));
331 static tree check_duplicates PROTO((hash));
332 static tree receiver_is_class_object PROTO((tree));
333 static int check_methods PROTO((tree, tree, int));
334 static int conforms_to_protocol PROTO((tree, tree));
335 static void check_protocols PROTO((tree, char *, char *));
336 static tree encode_method_def PROTO((tree));
337 static void gen_declspecs PROTO((tree, char *, int));
338 static void generate_classref_translation_entry PROTO((tree));
339 static void handle_class_ref PROTO((tree));
341 /*** Private Interface (data) ***/
343 /* Reserved tag definitions. */
345 #define TYPE_ID "id"
346 #define TAG_OBJECT "objc_object"
347 #define TAG_CLASS "objc_class"
348 #define TAG_SUPER "objc_super"
349 #define TAG_SELECTOR "objc_selector"
351 #define UTAG_CLASS "_objc_class"
352 #define UTAG_IVAR "_objc_ivar"
353 #define UTAG_IVAR_LIST "_objc_ivar_list"
354 #define UTAG_METHOD "_objc_method"
355 #define UTAG_METHOD_LIST "_objc_method_list"
356 #define UTAG_CATEGORY "_objc_category"
357 #define UTAG_MODULE "_objc_module"
358 #define UTAG_STATICS "_objc_statics"
359 #define UTAG_SYMTAB "_objc_symtab"
360 #define UTAG_SUPER "_objc_super"
361 #define UTAG_SELECTOR "_objc_selector"
363 #define UTAG_PROTOCOL "_objc_protocol"
364 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
365 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
366 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
368 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
369 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
371 static char *TAG_GETCLASS;
372 static char *TAG_GETMETACLASS;
373 static char *TAG_MSGSEND;
374 static char *TAG_MSGSENDSUPER;
375 static char *TAG_EXECCLASS;
377 /* Set by `continue_class' and checked by `is_public'. */
379 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
380 #define TYPED_OBJECT(type) \
381 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
383 /* Some commonly used instances of "identifier_node". */
385 static tree self_id, ucmd_id;
386 static tree unused_list;
388 static tree self_decl, umsg_decl, umsg_super_decl;
389 static tree objc_get_class_decl, objc_get_meta_class_decl;
391 static tree super_type, selector_type, id_type, objc_class_type;
392 static tree instance_type, protocol_type;
394 /* Type checking macros. */
396 #define IS_ID(TYPE) \
397 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
398 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
399 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
400 #define IS_SUPER(TYPE) \
401 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
403 static tree class_chain = NULL_TREE;
404 static tree alias_chain = NULL_TREE;
405 static tree interface_chain = NULL_TREE;
406 static tree protocol_chain = NULL_TREE;
408 /* Chains to manage selectors that are referenced and defined in the
409 module. */
411 static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */
412 static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */
414 /* Chains to manage uniquing of strings. */
416 static tree class_names_chain = NULL_TREE;
417 static tree meth_var_names_chain = NULL_TREE;
418 static tree meth_var_types_chain = NULL_TREE;
420 /* Hash tables to manage the global pool of method prototypes. */
422 static hash *nst_method_hash_list = 0;
423 static hash *cls_method_hash_list = 0;
425 /* Backend data declarations. */
427 static tree UOBJC_SYMBOLS_decl;
428 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
429 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
430 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
431 static tree UOBJC_SELECTOR_TABLE_decl;
432 static tree UOBJC_MODULES_decl;
433 static tree UOBJC_STRINGS_decl;
435 /* The following are used when compiling a class implementation.
436 implementation_template will normally be an interface, however if
437 none exists this will be equal to implementation_context...it is
438 set in start_class. */
440 static tree implementation_context = NULL_TREE;
441 static tree implementation_template = NULL_TREE;
443 struct imp_entry
445 struct imp_entry *next;
446 tree imp_context;
447 tree imp_template;
448 tree class_decl; /* _OBJC_CLASS_<my_name>; */
449 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
452 static void handle_impent PROTO((struct imp_entry *));
454 static struct imp_entry *imp_list = 0;
455 static int imp_count = 0; /* `@implementation' */
456 static int cat_count = 0; /* `@category' */
458 static tree objc_class_template, objc_category_template, uprivate_record;
459 static tree objc_protocol_template, objc_selector_template;
460 static tree ucls_super_ref, uucls_super_ref;
462 static tree objc_method_template, objc_ivar_template;
463 static tree objc_symtab_template, objc_module_template;
464 static tree objc_super_template, objc_object_reference;
466 static tree objc_object_id, objc_class_id, objc_id_id;
467 static tree constant_string_id;
468 static tree constant_string_type;
469 static tree UOBJC_SUPER_decl;
471 static tree method_context = NULL_TREE;
472 static int method_slot = 0; /* Used by start_method_def, */
474 #define BUFSIZE 1024
476 static char *errbuf; /* Buffer for error diagnostics */
478 /* Data imported from tree.c. */
480 extern enum debug_info_type write_symbols;
482 /* Data imported from toplev.c. */
484 extern char *dump_base_name;
486 /* Generate code for GNU or NeXT runtime environment. */
488 #ifdef NEXT_OBJC_RUNTIME
489 int flag_next_runtime = 1;
490 #else
491 int flag_next_runtime = 0;
492 #endif
494 int flag_typed_selectors;
496 /* Open and close the file for outputting class declarations, if requested. */
498 int flag_gen_declaration = 0;
500 FILE *gen_declaration_file;
502 /* Warn if multiple methods are seen for the same selector, but with
503 different argument types. */
505 int warn_selector = 0;
507 /* Warn if methods required by a protocol are not implemented in the
508 class adopting it. When turned off, methods inherited to that
509 class are also considered implemented */
511 int flag_warn_protocol = 1;
513 /* Tells "encode_pointer/encode_aggregate" whether we are generating
514 type descriptors for instance variables (as opposed to methods).
515 Type descriptors for instance variables contain more information
516 than methods (for static typing and embedded structures). This
517 was added to support features being planned for dbkit2. */
519 static int generating_instance_variables = 0;
521 /* Tells the compiler that this is a special run. Do not perform
522 any compiling, instead we are to test some platform dependent
523 features and output a C header file with appropriate definitions. */
525 static int print_struct_values = 0;
527 /* Some platforms pass small structures through registers versus through
528 an invisible pointer. Determine at what size structure is the
529 transition point between the two possibilities. */
531 void
532 generate_struct_by_value_array ()
534 tree type;
535 tree field_decl, field_decl_chain;
536 int i, j;
537 int aggregate_in_mem[32];
538 int found = 0;
540 /* Presumbaly no platform passes 32 byte structures in a register. */
541 for (i = 1; i < 32; i++)
543 char buffer[5];
545 /* Create an unnamed struct that has `i' character components */
546 type = start_struct (RECORD_TYPE, NULL_TREE);
548 strcpy (buffer, "c1");
549 field_decl = create_builtin_decl (FIELD_DECL,
550 char_type_node,
551 buffer);
552 field_decl_chain = field_decl;
554 for (j = 1; j < i; j++)
556 sprintf (buffer, "c%d", j + 1);
557 field_decl = create_builtin_decl (FIELD_DECL,
558 char_type_node,
559 buffer);
560 chainon (field_decl_chain, field_decl);
562 finish_struct (type, field_decl_chain, NULL_TREE);
564 aggregate_in_mem[i] = aggregate_value_p (type);
565 if (!aggregate_in_mem[i])
566 found = 1;
569 /* We found some structures that are returned in registers instead of memory
570 so output the necessary data. */
571 if (found)
573 for (i = 31; i >= 0; i--)
574 if (!aggregate_in_mem[i])
575 break;
576 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
578 /* The first member of the structure is always 0 because we don't handle
579 structures with 0 members */
580 printf ("static int struct_forward_array[] = {\n 0");
582 for (j = 1; j <= i; j++)
583 printf (", %d", aggregate_in_mem[j]);
584 printf ("\n};\n");
587 exit (0);
590 void
591 lang_init_options ()
595 void
596 lang_init ()
598 #if !USE_CPPLIB
599 /* The beginning of the file is a new line; check for #.
600 With luck, we discover the real source file's name from that
601 and put it in input_filename. */
602 ungetc (check_newline (), finput);
603 #endif
605 /* The line number can be -1 if we had -g3 and the input file
606 had a directive specifying line 0. But we want predefined
607 functions to have a line number of 0, not -1. */
608 if (lineno == -1)
609 lineno = 0;
611 /* If gen_declaration desired, open the output file. */
612 if (flag_gen_declaration)
614 int dump_base_name_length = strlen (dump_base_name);
615 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
616 strcpy (dumpname, dump_base_name);
617 strcat (dumpname, ".decl");
618 gen_declaration_file = fopen (dumpname, "w");
619 if (gen_declaration_file == 0)
620 pfatal_with_name (dumpname);
623 if (flag_next_runtime)
625 TAG_GETCLASS = "objc_getClass";
626 TAG_GETMETACLASS = "objc_getMetaClass";
627 TAG_MSGSEND = "objc_msgSend";
628 TAG_MSGSENDSUPER = "objc_msgSendSuper";
629 TAG_EXECCLASS = "__objc_execClass";
631 else
633 TAG_GETCLASS = "objc_get_class";
634 TAG_GETMETACLASS = "objc_get_meta_class";
635 TAG_MSGSEND = "objc_msg_lookup";
636 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
637 TAG_EXECCLASS = "__objc_exec_class";
638 flag_typed_selectors = 1;
641 if (doing_objc_thang)
642 init_objc ();
644 if (print_struct_values)
645 generate_struct_by_value_array ();
648 static void
649 objc_fatal ()
651 fatal ("Objective-C text in C source file");
654 void
655 finish_file ()
657 if (doing_objc_thang)
658 finish_objc (); /* Objective-C finalization */
660 if (gen_declaration_file)
661 fclose (gen_declaration_file);
664 void
665 lang_finish ()
669 char *
670 lang_identify ()
672 return "objc";
676 lang_decode_option (argc, argv)
677 int argc;
678 char **argv;
680 char *p = argv[0];
681 #if USE_CPPLIB
682 if (! cpp_initialized)
684 cpp_reader_init (&parse_in);
685 parse_in.data = &parse_options;
686 cpp_options_init (&parse_options);
687 cpp_initialized = 1;
689 #endif
690 if (!strcmp (p, "-lang-objc"))
691 doing_objc_thang = 1;
692 else if (!strcmp (p, "-gen-decls"))
693 flag_gen_declaration = 1;
694 else if (!strcmp (p, "-Wselector"))
695 warn_selector = 1;
696 else if (!strcmp (p, "-Wno-selector"))
697 warn_selector = 0;
698 else if (!strcmp (p, "-Wprotocol"))
699 flag_warn_protocol = 1;
700 else if (!strcmp (p, "-Wno-protocol"))
701 flag_warn_protocol = 0;
702 else if (!strcmp (p, "-fgnu-runtime"))
703 flag_next_runtime = 0;
704 else if (!strcmp (p, "-fno-next-runtime"))
705 flag_next_runtime = 0;
706 else if (!strcmp (p, "-fno-gnu-runtime"))
707 flag_next_runtime = 1;
708 else if (!strcmp (p, "-fnext-runtime"))
709 flag_next_runtime = 1;
710 else if (!strcmp (p, "-print-objc-runtime-info"))
711 print_struct_values = 1;
712 else
713 return c_decode_option (argc, argv);
715 return 1;
718 /* used by print-tree.c */
720 void
721 lang_print_xnode (file, node, indent)
722 FILE *file ATTRIBUTE_UNUSED;
723 tree node ATTRIBUTE_UNUSED;
724 int indent ATTRIBUTE_UNUSED;
729 static tree
730 define_decl (declarator, declspecs)
731 tree declarator;
732 tree declspecs;
734 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
735 finish_decl (decl, NULL_TREE, NULL_TREE);
736 return decl;
739 /* Return 1 if LHS and RHS are compatible types for assignment or
740 various other operations. Return 0 if they are incompatible, and
741 return -1 if we choose to not decide. When the operation is
742 REFLEXIVE, check for compatibility in either direction.
744 For statically typed objects, an assignment of the form `a' = `b'
745 is permitted if:
747 `a' is of type "id",
748 `a' and `b' are the same class type, or
749 `a' and `b' are of class types A and B such that B is a descendant of A. */
752 maybe_objc_comptypes (lhs, rhs, reflexive)
753 tree lhs, rhs;
754 int reflexive;
756 if (doing_objc_thang)
757 return objc_comptypes (lhs, rhs, reflexive);
758 return -1;
761 static tree
762 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
763 tree rproto_list;
764 tree sel_name;
765 int class_meth;
767 tree rproto, p;
768 tree fnd = 0;
770 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
772 p = TREE_VALUE (rproto);
774 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
776 if ((fnd = lookup_method (class_meth
777 ? PROTOCOL_CLS_METHODS (p)
778 : PROTOCOL_NST_METHODS (p), sel_name)))
780 else if (PROTOCOL_LIST (p))
781 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
782 sel_name, class_meth);
784 else
786 ; /* An identifier...if we could not find a protocol. */
789 if (fnd)
790 return fnd;
793 return 0;
796 static tree
797 lookup_protocol_in_reflist (rproto_list, lproto)
798 tree rproto_list;
799 tree lproto;
801 tree rproto, p;
803 /* Make sure the protocol is support by the object on the rhs. */
804 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
806 tree fnd = 0;
807 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
809 p = TREE_VALUE (rproto);
811 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
813 if (lproto == p)
814 fnd = lproto;
816 else if (PROTOCOL_LIST (p))
817 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
820 if (fnd)
821 return fnd;
824 else
826 ; /* An identifier...if we could not find a protocol. */
829 return 0;
832 /* Return 1 if LHS and RHS are compatible types for assignment
833 or various other operations. Return 0 if they are incompatible,
834 and return -1 if we choose to not decide. When the operation
835 is REFLEXIVE, check for compatibility in either direction. */
838 objc_comptypes (lhs, rhs, reflexive)
839 tree lhs;
840 tree rhs;
841 int reflexive;
843 /* New clause for protocols. */
845 if (TREE_CODE (lhs) == POINTER_TYPE
846 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
847 && TREE_CODE (rhs) == POINTER_TYPE
848 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
850 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
851 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
853 if (lhs_is_proto)
855 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
856 tree rproto, rproto_list;
857 tree p;
859 if (rhs_is_proto)
861 rproto_list = TYPE_PROTOCOL_LIST (rhs);
863 /* Make sure the protocol is supported by the object
864 on the rhs. */
865 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
867 p = TREE_VALUE (lproto);
868 rproto = lookup_protocol_in_reflist (rproto_list, p);
870 if (!rproto)
871 warning ("object does not conform to the `%s' protocol",
872 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
875 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
877 tree rname = TYPE_NAME (TREE_TYPE (rhs));
878 tree rinter;
880 /* Make sure the protocol is supported by the object
881 on the rhs. */
882 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
884 p = TREE_VALUE (lproto);
885 rproto = 0;
886 rinter = lookup_interface (rname);
888 while (rinter && !rproto)
890 tree cat;
892 rproto_list = CLASS_PROTOCOL_LIST (rinter);
893 rproto = lookup_protocol_in_reflist (rproto_list, p);
895 /* Check for protocols adopted by categories. */
896 cat = CLASS_CATEGORY_LIST (rinter);
897 while (cat && !rproto)
899 rproto_list = CLASS_PROTOCOL_LIST (cat);
900 rproto = lookup_protocol_in_reflist (rproto_list, p);
902 cat = CLASS_CATEGORY_LIST (cat);
905 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
908 if (!rproto)
909 warning ("class `%s' does not implement the `%s' protocol",
910 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
911 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
915 /* May change...based on whether there was any mismatch */
916 return 1;
918 else if (rhs_is_proto)
919 /* Lhs is not a protocol...warn if it is statically typed */
920 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
922 else
923 /* Defer to comptypes .*/
924 return -1;
927 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
928 ; /* Fall thru. This is the case we have been handling all along */
929 else
930 /* Defer to comptypes. */
931 return -1;
933 /* `id' = `<class> *', `<class> *' = `id' */
935 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
936 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
937 return 1;
939 /* `id' = `Class', `Class' = `id' */
941 else if ((TYPE_NAME (lhs) == objc_object_id
942 && TYPE_NAME (rhs) == objc_class_id)
943 || (TYPE_NAME (lhs) == objc_class_id
944 && TYPE_NAME (rhs) == objc_object_id))
945 return 1;
947 /* `<class> *' = `<class> *' */
949 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
951 tree lname = TYPE_NAME (lhs);
952 tree rname = TYPE_NAME (rhs);
953 tree inter;
955 if (lname == rname)
956 return 1;
958 /* If the left hand side is a super class of the right hand side,
959 allow it. */
960 for (inter = lookup_interface (rname); inter;
961 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
962 if (lname == CLASS_SUPER_NAME (inter))
963 return 1;
965 /* Allow the reverse when reflexive. */
966 if (reflexive)
967 for (inter = lookup_interface (lname); inter;
968 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
969 if (rname == CLASS_SUPER_NAME (inter))
970 return 1;
972 return 0;
974 else
975 /* Defer to comptypes. */
976 return -1;
979 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
981 void
982 objc_check_decl (decl)
983 tree decl;
985 tree type = TREE_TYPE (decl);
987 if (TREE_CODE (type) == RECORD_TYPE
988 && TREE_STATIC_TEMPLATE (type)
989 && type != constant_string_type)
991 error_with_decl (decl, "`%s' cannot be statically allocated");
992 fatal ("statically allocated objects not supported");
996 void
997 maybe_objc_check_decl (decl)
998 tree decl;
1000 if (doing_objc_thang)
1001 objc_check_decl (decl);
1004 /* Implement static typing. At this point, we know we have an interface. */
1006 tree
1007 get_static_reference (interface, protocols)
1008 tree interface;
1009 tree protocols;
1011 tree type = xref_tag (RECORD_TYPE, interface);
1013 if (protocols)
1015 tree t, m = TYPE_MAIN_VARIANT (type);
1017 push_obstacks_nochange ();
1018 end_temporary_allocation ();
1019 t = copy_node (type);
1020 TYPE_BINFO (t) = make_tree_vec (2);
1021 pop_obstacks ();
1023 /* Add this type to the chain of variants of TYPE. */
1024 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1025 TYPE_NEXT_VARIANT (m) = t;
1027 /* Look up protocols and install in lang specific list. */
1028 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1030 /* This forces a new pointer type to be created later
1031 (in build_pointer_type)...so that the new template
1032 we just created will actually be used...what a hack! */
1033 if (TYPE_POINTER_TO (t))
1034 TYPE_POINTER_TO (t) = 0;
1036 type = t;
1039 return type;
1042 tree
1043 get_object_reference (protocols)
1044 tree protocols;
1046 tree type_decl = lookup_name (objc_id_id);
1047 tree type;
1049 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1051 type = TREE_TYPE (type_decl);
1052 if (TYPE_MAIN_VARIANT (type) != id_type)
1053 warning ("Unexpected type for `id' (%s)",
1054 gen_declaration (type, errbuf));
1056 else
1057 fatal ("Undefined type `id', please import <objc/objc.h>");
1059 /* This clause creates a new pointer type that is qualified with
1060 the protocol specification...this info is used later to do more
1061 elaborate type checking. */
1063 if (protocols)
1065 tree t, m = TYPE_MAIN_VARIANT (type);
1067 push_obstacks_nochange ();
1068 end_temporary_allocation ();
1069 t = copy_node (type);
1070 TYPE_BINFO (t) = make_tree_vec (2);
1071 pop_obstacks ();
1073 /* Add this type to the chain of variants of TYPE. */
1074 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1075 TYPE_NEXT_VARIANT (m) = t;
1077 /* Look up protocols...and install in lang specific list */
1078 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1080 /* This forces a new pointer type to be created later
1081 (in build_pointer_type)...so that the new template
1082 we just created will actually be used...what a hack! */
1083 if (TYPE_POINTER_TO (t))
1084 TYPE_POINTER_TO (t) = NULL;
1086 type = t;
1088 return type;
1091 static tree
1092 lookup_and_install_protocols (protocols)
1093 tree protocols;
1095 tree proto;
1096 tree prev = NULL;
1097 tree return_value = protocols;
1099 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1101 tree ident = TREE_VALUE (proto);
1102 tree p = lookup_protocol (ident);
1104 if (!p)
1106 error ("Cannot find protocol declaration for `%s'",
1107 IDENTIFIER_POINTER (ident));
1108 if (prev)
1109 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1110 else
1111 return_value = TREE_CHAIN (proto);
1113 else
1115 /* Replace identifier with actual protocol node. */
1116 TREE_VALUE (proto) = p;
1117 prev = proto;
1121 return return_value;
1124 /* Create and push a decl for a built-in external variable or field NAME.
1125 CODE says which.
1126 TYPE is its data type. */
1128 static tree
1129 create_builtin_decl (code, type, name)
1130 enum tree_code code;
1131 tree type;
1132 char *name;
1134 tree decl = build_decl (code, get_identifier (name), type);
1136 if (code == VAR_DECL)
1138 TREE_STATIC (decl) = 1;
1139 make_decl_rtl (decl, 0, 1);
1140 pushdecl (decl);
1143 DECL_ARTIFICIAL (decl) = 1;
1144 return decl;
1147 /* Purpose: "play" parser, creating/installing representations
1148 of the declarations that are required by Objective-C.
1150 Model:
1152 type_spec--------->sc_spec
1153 (tree_list) (tree_list)
1156 identifier_node identifier_node */
1158 static void
1159 synth_module_prologue ()
1161 tree temp_type;
1162 tree super_p;
1164 /* Defined in `objc.h' */
1165 objc_object_id = get_identifier (TAG_OBJECT);
1167 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1169 id_type = build_pointer_type (objc_object_reference);
1171 objc_id_id = get_identifier (TYPE_ID);
1172 objc_class_id = get_identifier (TAG_CLASS);
1174 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1175 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1176 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1178 /* Declare type of selector-objects that represent an operation name. */
1180 #ifdef OBJC_INT_SELECTORS
1181 /* `unsigned int' */
1182 selector_type = unsigned_type_node;
1183 #else
1184 /* `struct objc_selector *' */
1185 selector_type
1186 = build_pointer_type (xref_tag (RECORD_TYPE,
1187 get_identifier (TAG_SELECTOR)));
1188 #endif /* not OBJC_INT_SELECTORS */
1190 /* Forward declare type, or else the prototype for msgSendSuper will
1191 complain. */
1193 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1194 get_identifier (TAG_SUPER)));
1197 /* id objc_msgSend (id, SEL, ...); */
1199 temp_type
1200 = build_function_type (id_type,
1201 tree_cons (NULL_TREE, id_type,
1202 tree_cons (NULL_TREE, selector_type,
1203 NULL_TREE)));
1205 if (! flag_next_runtime)
1207 umsg_decl = build_decl (FUNCTION_DECL,
1208 get_identifier (TAG_MSGSEND), temp_type);
1209 DECL_EXTERNAL (umsg_decl) = 1;
1210 TREE_PUBLIC (umsg_decl) = 1;
1211 DECL_INLINE (umsg_decl) = 1;
1212 DECL_ARTIFICIAL (umsg_decl) = 1;
1214 if (flag_traditional && TAG_MSGSEND[0] != '_')
1215 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1217 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1218 pushdecl (umsg_decl);
1220 else
1221 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
1223 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1225 temp_type
1226 = build_function_type (id_type,
1227 tree_cons (NULL_TREE, super_p,
1228 tree_cons (NULL_TREE, selector_type,
1229 NULL_TREE)));
1231 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1232 temp_type, NOT_BUILT_IN, 0);
1234 /* id objc_getClass (const char *); */
1236 temp_type = build_function_type (id_type,
1237 tree_cons (NULL_TREE,
1238 const_string_type_node,
1239 tree_cons (NULL_TREE, void_type_node,
1240 NULL_TREE)));
1242 objc_get_class_decl
1243 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
1245 /* id objc_getMetaClass (const char *); */
1247 objc_get_meta_class_decl
1248 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
1250 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1252 if (! flag_next_runtime)
1254 if (flag_typed_selectors)
1256 /* Suppress outputting debug symbols, because
1257 dbxout_init hasn'r been called yet. */
1258 enum debug_info_type save_write_symbols = write_symbols;
1259 write_symbols = NO_DEBUG;
1261 build_selector_template ();
1262 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1264 write_symbols = save_write_symbols;
1266 else
1267 temp_type = build_array_type (selector_type, NULL_TREE);
1269 layout_type (temp_type);
1270 UOBJC_SELECTOR_TABLE_decl
1271 = create_builtin_decl (VAR_DECL, temp_type,
1272 "_OBJC_SELECTOR_TABLE");
1274 /* Avoid warning when not sending messages. */
1275 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1278 generate_forward_declaration_to_string_table ();
1280 /* Forward declare constant_string_id and constant_string_type. */
1281 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1282 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1285 /* Custom build_string which sets TREE_TYPE! */
1287 static tree
1288 my_build_string (len, str)
1289 int len;
1290 char *str;
1292 int wide_flag = 0;
1293 tree a_string = build_string (len, str);
1295 /* Some code from combine_strings, which is local to c-parse.y. */
1296 if (TREE_TYPE (a_string) == int_array_type_node)
1297 wide_flag = 1;
1299 TREE_TYPE (a_string)
1300 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1301 build_index_type (build_int_2 (len - 1, 0)));
1303 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1304 TREE_STATIC (a_string) = 1;
1306 return a_string;
1309 /* Return a newly constructed OBJC_STRING_CST node whose value is
1310 the LEN characters at STR.
1311 The TREE_TYPE is not initialized. */
1313 tree
1314 build_objc_string (len, str)
1315 int len;
1316 char *str;
1318 tree s = build_string (len, str);
1320 TREE_SET_CODE (s, OBJC_STRING_CST);
1321 return s;
1324 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1325 NXConstanString which points at the concatenation of those strings.
1326 We place the string object in the __string_objects section of the
1327 __OBJC segment. The Objective-C runtime will initialize the isa
1328 pointers of the string objects to point at the NXConstandString class
1329 object. */
1331 tree
1332 build_objc_string_object (strings)
1333 tree strings;
1335 tree string, initlist, constructor;
1336 int length;
1338 if (!doing_objc_thang)
1339 objc_fatal ();
1341 if (lookup_interface (constant_string_id) == NULL_TREE)
1343 error ("Cannot find interface declaration for `%s'",
1344 IDENTIFIER_POINTER (constant_string_id));
1345 return error_mark_node;
1348 add_class_reference (constant_string_id);
1350 /* Combine_strings will work for OBJC_STRING_CST's too. */
1351 string = combine_strings (strings);
1352 TREE_SET_CODE (string, STRING_CST);
1353 length = TREE_STRING_LENGTH (string) - 1;
1355 if (! flag_next_runtime)
1357 push_obstacks_nochange ();
1358 end_temporary_allocation ();
1359 if (! TREE_PERMANENT (strings))
1360 string = my_build_string (length + 1,
1361 TREE_STRING_POINTER (string));
1364 /* & ((NXConstantString) {0, string, length}) */
1366 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1367 initlist
1368 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1369 initlist);
1370 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1371 constructor = build_constructor (constant_string_type, nreverse (initlist));
1373 if (!flag_next_runtime)
1375 constructor
1376 = objc_add_static_instance (constructor, constant_string_type);
1377 pop_obstacks ();
1380 return (build_unary_op (ADDR_EXPR, constructor, 1));
1383 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1385 static tree
1386 objc_add_static_instance (constructor, class_decl)
1387 tree constructor, class_decl;
1389 static int num_static_inst;
1390 tree *chain, decl;
1391 char buf[256];
1393 push_obstacks_nochange ();
1394 end_temporary_allocation ();
1396 /* Find the list of static instances for the CLASS_DECL. Create one if
1397 not found. */
1398 for (chain = &objc_static_instances;
1399 *chain && TREE_VALUE (*chain) != class_decl;
1400 chain = &TREE_CHAIN (*chain));
1401 if (!*chain)
1403 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1404 add_objc_string (TYPE_NAME (class_decl), class_names);
1407 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1408 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1409 DECL_COMMON (decl) = 1;
1410 TREE_STATIC (decl) = 1;
1411 DECL_ARTIFICIAL (decl) = 1;
1412 pushdecl_top_level (decl);
1413 rest_of_decl_compilation (decl, 0, 1, 0);
1415 /* Do this here so it gets output later instead of possibly
1416 inside something else we are writing. */
1417 DECL_INITIAL (decl) = constructor;
1419 /* Add the DECL to the head of this CLASS' list. */
1420 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1422 pop_obstacks ();
1423 return decl;
1426 /* Build a static constant CONSTRUCTOR
1427 with type TYPE and elements ELTS. */
1429 static tree
1430 build_constructor (type, elts)
1431 tree type, elts;
1433 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1435 TREE_CONSTANT (constructor) = 1;
1436 TREE_STATIC (constructor) = 1;
1437 TREE_READONLY (constructor) = 1;
1439 return constructor;
1442 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1444 /* Predefine the following data type:
1446 struct _objc_symtab
1448 long sel_ref_cnt;
1449 SEL *refs;
1450 short cls_def_cnt;
1451 short cat_def_cnt;
1452 void *defs[cls_def_cnt + cat_def_cnt];
1453 }; */
1455 static void
1456 build_objc_symtab_template ()
1458 tree field_decl, field_decl_chain, index;
1460 objc_symtab_template
1461 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1463 /* long sel_ref_cnt; */
1465 field_decl = create_builtin_decl (FIELD_DECL,
1466 long_integer_type_node,
1467 "sel_ref_cnt");
1468 field_decl_chain = field_decl;
1470 /* SEL *refs; */
1472 field_decl = create_builtin_decl (FIELD_DECL,
1473 build_pointer_type (selector_type),
1474 "refs");
1475 chainon (field_decl_chain, field_decl);
1477 /* short cls_def_cnt; */
1479 field_decl = create_builtin_decl (FIELD_DECL,
1480 short_integer_type_node,
1481 "cls_def_cnt");
1482 chainon (field_decl_chain, field_decl);
1484 /* short cat_def_cnt; */
1486 field_decl = create_builtin_decl (FIELD_DECL,
1487 short_integer_type_node,
1488 "cat_def_cnt");
1489 chainon (field_decl_chain, field_decl);
1491 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1493 if (!flag_next_runtime)
1494 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1495 else
1496 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1497 imp_count == 0 && cat_count == 0
1498 ? -1 : 0));
1499 field_decl = create_builtin_decl (FIELD_DECL,
1500 build_array_type (ptr_type_node, index),
1501 "defs");
1502 chainon (field_decl_chain, field_decl);
1504 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1507 /* Create the initial value for the `defs' field of _objc_symtab.
1508 This is a CONSTRUCTOR. */
1510 static tree
1511 init_def_list (type)
1512 tree type;
1514 tree expr, initlist = NULL_TREE;
1515 struct imp_entry *impent;
1517 if (imp_count)
1518 for (impent = imp_list; impent; impent = impent->next)
1520 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1522 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1523 initlist = tree_cons (NULL_TREE, expr, initlist);
1527 if (cat_count)
1528 for (impent = imp_list; impent; impent = impent->next)
1530 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1532 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1533 initlist = tree_cons (NULL_TREE, expr, initlist);
1537 if (!flag_next_runtime)
1539 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1540 tree expr;
1542 if (static_instances_decl)
1543 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1544 else
1545 expr = build_int_2 (0, 0);
1547 initlist = tree_cons (NULL_TREE, expr, initlist);
1550 return build_constructor (type, nreverse (initlist));
1553 /* Construct the initial value for all of _objc_symtab. */
1555 static tree
1556 init_objc_symtab (type)
1557 tree type;
1559 tree initlist;
1561 /* sel_ref_cnt = { ..., 5, ... } */
1563 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1565 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1567 if (flag_next_runtime || ! sel_ref_chain)
1568 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1569 else
1570 initlist = tree_cons (NULL_TREE,
1571 build_unary_op (ADDR_EXPR,
1572 UOBJC_SELECTOR_TABLE_decl, 1),
1573 initlist);
1575 /* cls_def_cnt = { ..., 5, ... } */
1577 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1579 /* cat_def_cnt = { ..., 5, ... } */
1581 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1583 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1585 if (imp_count || cat_count || static_instances_decl)
1588 tree field = TYPE_FIELDS (type);
1589 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1591 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1592 initlist);
1595 return build_constructor (type, nreverse (initlist));
1598 /* Push forward-declarations of all the categories
1599 so that init_def_list can use them in a CONSTRUCTOR. */
1601 static void
1602 forward_declare_categories ()
1604 struct imp_entry *impent;
1605 tree sav = implementation_context;
1607 for (impent = imp_list; impent; impent = impent->next)
1609 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1611 /* Set an invisible arg to synth_id_with_class_suffix. */
1612 implementation_context = impent->imp_context;
1613 impent->class_decl
1614 = create_builtin_decl (VAR_DECL, objc_category_template,
1615 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1618 implementation_context = sav;
1621 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1622 and initialized appropriately. */
1624 static void
1625 generate_objc_symtab_decl ()
1627 tree sc_spec;
1629 if (!objc_category_template)
1630 build_category_template ();
1632 /* forward declare categories */
1633 if (cat_count)
1634 forward_declare_categories ();
1636 if (!objc_symtab_template)
1637 build_objc_symtab_template ();
1639 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1641 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1642 tree_cons (NULL_TREE,
1643 objc_symtab_template, sc_spec),
1645 NULL_TREE, NULL_TREE);
1647 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1648 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1649 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1650 finish_decl (UOBJC_SYMBOLS_decl,
1651 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1652 NULL_TREE);
1655 static tree
1656 init_module_descriptor (type)
1657 tree type;
1659 tree initlist, expr;
1661 /* version = { 1, ... } */
1663 expr = build_int_2 (OBJC_VERSION, 0);
1664 initlist = build_tree_list (NULL_TREE, expr);
1666 /* size = { ..., sizeof (struct objc_module), ... } */
1668 expr = size_in_bytes (objc_module_template);
1669 initlist = tree_cons (NULL_TREE, expr, initlist);
1671 /* name = { ..., "foo.m", ... } */
1673 expr = add_objc_string (get_identifier (input_filename), class_names);
1674 initlist = tree_cons (NULL_TREE, expr, initlist);
1676 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1678 if (UOBJC_SYMBOLS_decl)
1679 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1680 else
1681 expr = build_int_2 (0, 0);
1682 initlist = tree_cons (NULL_TREE, expr, initlist);
1684 return build_constructor (type, nreverse (initlist));
1687 /* Write out the data structures to describe Objective C classes defined.
1688 If appropriate, compile and output a setup function to initialize them.
1689 Return a string which is the name of a function to call to initialize
1690 the Objective C data structures for this file (and perhaps for other files
1691 also).
1693 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1695 static char *
1696 build_module_descriptor ()
1698 tree decl_specs, field_decl, field_decl_chain;
1700 objc_module_template
1701 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1703 /* Long version; */
1705 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1706 field_decl = get_identifier ("version");
1707 field_decl
1708 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1709 field_decl_chain = field_decl;
1711 /* long size; */
1713 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1714 field_decl = get_identifier ("size");
1715 field_decl
1716 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1717 chainon (field_decl_chain, field_decl);
1719 /* char *name; */
1721 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1722 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1723 field_decl
1724 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1725 chainon (field_decl_chain, field_decl);
1727 /* struct objc_symtab *symtab; */
1729 decl_specs = get_identifier (UTAG_SYMTAB);
1730 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1731 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1732 field_decl
1733 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1734 chainon (field_decl_chain, field_decl);
1736 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1738 /* Create an instance of "objc_module". */
1740 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1741 build_tree_list (NULL_TREE,
1742 ridpointers[(int) RID_STATIC]));
1744 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1745 decl_specs, 1, NULL_TREE, NULL_TREE);
1747 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1748 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1749 finish_decl (UOBJC_MODULES_decl,
1750 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1751 NULL_TREE);
1753 /* Mark the decl to avoid "defined but not used" warning. */
1754 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1756 /* Generate a constructor call for the module descriptor.
1757 This code was generated by reading the grammar rules
1758 of c-parse.in; Therefore, it may not be the most efficient
1759 way of generating the requisite code. */
1761 if (flag_next_runtime)
1762 return 0;
1765 tree parms, function_decl, decelerator, void_list_node;
1766 tree function_type;
1767 tree init_function_name = get_file_function_name ('I');
1769 /* Declare void __objc_execClass (void *); */
1771 void_list_node = build_tree_list (NULL_TREE, void_type_node);
1772 function_type
1773 = build_function_type (void_type_node,
1774 tree_cons (NULL_TREE, ptr_type_node,
1775 void_list_node));
1776 function_decl = build_decl (FUNCTION_DECL,
1777 get_identifier (TAG_EXECCLASS),
1778 function_type);
1779 DECL_EXTERNAL (function_decl) = 1;
1780 DECL_ARTIFICIAL (function_decl) = 1;
1781 TREE_PUBLIC (function_decl) = 1;
1783 pushdecl (function_decl);
1784 rest_of_decl_compilation (function_decl, 0, 0, 0);
1786 parms
1787 = build_tree_list (NULL_TREE,
1788 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1789 decelerator = build_function_call (function_decl, parms);
1791 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1793 start_function (void_list_node,
1794 build_parse_node (CALL_EXPR, init_function_name,
1795 /* This has the format of the output
1796 of get_parm_info. */
1797 tree_cons (NULL_TREE, NULL_TREE,
1798 void_list_node),
1799 NULL_TREE),
1800 NULL_TREE, NULL_TREE, 0);
1801 #if 0 /* This should be turned back on later
1802 for the systems where collect is not needed. */
1803 /* Make these functions nonglobal
1804 so each file can use the same name. */
1805 TREE_PUBLIC (current_function_decl) = 0;
1806 #endif
1807 TREE_USED (current_function_decl) = 1;
1808 store_parm_decls ();
1810 assemble_external (function_decl);
1811 c_expand_expr_stmt (decelerator);
1813 TREE_PUBLIC (current_function_decl) = 1;
1815 function_decl = current_function_decl;
1816 finish_function (0);
1818 /* Return the name of the constructor function. */
1819 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1823 /* extern const char _OBJC_STRINGS[]; */
1825 static void
1826 generate_forward_declaration_to_string_table ()
1828 tree sc_spec, decl_specs, expr_decl;
1830 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1831 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1833 expr_decl
1834 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1836 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1839 /* Return the DECL of the string IDENT in the SECTION. */
1841 static tree
1842 get_objc_string_decl (ident, section)
1843 tree ident;
1844 enum string_section section;
1846 tree chain;
1848 if (section == class_names)
1849 chain = class_names_chain;
1850 else if (section == meth_var_names)
1851 chain = meth_var_names_chain;
1852 else if (section == meth_var_types)
1853 chain = meth_var_types_chain;
1855 for (; chain != 0; chain = TREE_VALUE (chain))
1856 if (TREE_VALUE (chain) == ident)
1857 return (TREE_PURPOSE (chain));
1859 abort ();
1860 return NULL_TREE;
1863 /* Output references to all statically allocated objects. Return the DECL
1864 for the array built. */
1866 static void
1867 generate_static_references ()
1869 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1870 tree class_name, class, decl, initlist;
1871 tree cl_chain, in_chain, type;
1872 int num_inst, num_class;
1873 char buf[256];
1875 if (flag_next_runtime)
1876 abort ();
1878 for (cl_chain = objc_static_instances, num_class = 0;
1879 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1881 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1882 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1884 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1885 ident = get_identifier (buf);
1887 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1888 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1889 build_tree_list (NULL_TREE,
1890 ridpointers[(int) RID_STATIC]));
1891 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1892 DECL_CONTEXT (decl) = 0;
1893 DECL_ARTIFICIAL (decl) = 1;
1895 /* Output {class_name, ...}. */
1896 class = TREE_VALUE (cl_chain);
1897 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1898 initlist = build_tree_list (NULL_TREE,
1899 build_unary_op (ADDR_EXPR, class_name, 1));
1901 /* Output {..., instance, ...}. */
1902 for (in_chain = TREE_PURPOSE (cl_chain);
1903 in_chain; in_chain = TREE_CHAIN (in_chain))
1905 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1906 initlist = tree_cons (NULL_TREE, expr, initlist);
1909 /* Output {..., NULL}. */
1910 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1912 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1913 finish_decl (decl, expr, NULL_TREE);
1914 TREE_USED (decl) = 1;
1916 type = build_array_type (build_pointer_type (void_type_node), 0);
1917 decl = build_decl (VAR_DECL, ident, type);
1918 make_decl_rtl (decl, 0, 1);
1919 TREE_USED (decl) = 1;
1920 decls
1921 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1924 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1925 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1926 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1927 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1928 build_tree_list (NULL_TREE,
1929 ridpointers[(int) RID_STATIC]));
1930 static_instances_decl
1931 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1932 TREE_USED (static_instances_decl) = 1;
1933 DECL_CONTEXT (static_instances_decl) = 0;
1934 DECL_ARTIFICIAL (static_instances_decl) = 1;
1935 end_temporary_allocation ();
1936 expr = build_constructor (TREE_TYPE (static_instances_decl),
1937 nreverse (decls));
1938 finish_decl (static_instances_decl, expr, NULL_TREE);
1941 /* Output all strings. */
1943 static void
1944 generate_strings ()
1946 tree sc_spec, decl_specs, expr_decl;
1947 tree chain, string_expr;
1948 tree string, decl;
1950 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1952 string = TREE_VALUE (chain);
1953 decl = TREE_PURPOSE (chain);
1954 sc_spec
1955 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1956 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1957 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1958 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1959 end_temporary_allocation ();
1960 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1961 IDENTIFIER_POINTER (string));
1962 finish_decl (decl, string_expr, NULL_TREE);
1965 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1967 string = TREE_VALUE (chain);
1968 decl = TREE_PURPOSE (chain);
1969 sc_spec
1970 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1971 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1972 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1973 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1974 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1975 IDENTIFIER_POINTER (string));
1976 finish_decl (decl, string_expr, NULL_TREE);
1979 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1981 string = TREE_VALUE (chain);
1982 decl = TREE_PURPOSE (chain);
1983 sc_spec
1984 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1985 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1986 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1987 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1988 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1989 IDENTIFIER_POINTER (string));
1990 finish_decl (decl, string_expr, NULL_TREE);
1994 static tree
1995 build_selector_reference_decl (name)
1996 tree name;
1998 tree decl, ident;
1999 char buf[256];
2000 static int idx = 0;
2002 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
2004 push_obstacks_nochange ();
2005 end_temporary_allocation ();
2007 ident = get_identifier (buf);
2009 decl = build_decl (VAR_DECL, ident, selector_type);
2010 DECL_EXTERNAL (decl) = 1;
2011 TREE_PUBLIC (decl) = 1;
2012 TREE_USED (decl) = 1;
2013 TREE_READONLY (decl) = 1;
2014 DECL_ARTIFICIAL (decl) = 1;
2015 DECL_CONTEXT (decl) = 0;
2017 make_decl_rtl (decl, 0, 1);
2018 pushdecl_top_level (decl);
2020 pop_obstacks ();
2022 return decl;
2025 /* Just a handy wrapper for add_objc_string. */
2027 static tree
2028 build_selector (ident)
2029 tree ident;
2031 tree expr = add_objc_string (ident, meth_var_names);
2032 if (flag_typed_selectors)
2033 return expr;
2034 else
2035 return build_c_cast (selector_type, expr); /* cast! */
2038 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
2039 The cast stops the compiler from issuing the following message:
2040 grok.m: warning: initialization of non-const * pointer from const *
2041 grok.m: warning: initialization between incompatible pointer types. */
2043 static tree
2044 build_msg_pool_reference (offset)
2045 int offset;
2047 tree expr = build_int_2 (offset, 0);
2048 tree cast;
2050 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
2051 expr = build_unary_op (ADDR_EXPR, expr, 0);
2053 cast = build_tree_list (build_tree_list (NULL_TREE,
2054 ridpointers[(int) RID_CHAR]),
2055 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
2056 TREE_TYPE (expr) = groktypename (cast);
2057 return expr;
2060 static tree
2061 init_selector (offset)
2062 int offset;
2064 tree expr = build_msg_pool_reference (offset);
2065 TREE_TYPE (expr) = selector_type;
2066 return expr;
2069 static void
2070 build_selector_translation_table ()
2072 tree sc_spec, decl_specs;
2073 tree chain, initlist = NULL_TREE;
2074 int offset = 0;
2075 tree decl, var_decl, name;
2077 /* The corresponding pop_obstacks is in finish_decl,
2078 called at the end of this function. */
2079 if (! flag_next_runtime)
2080 push_obstacks_nochange ();
2082 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2084 tree expr;
2086 expr = build_selector (TREE_VALUE (chain));
2088 if (flag_next_runtime)
2090 name = DECL_NAME (TREE_PURPOSE (chain));
2092 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2094 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2095 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2097 var_decl = name;
2099 /* The `decl' that is returned from start_decl is the one that we
2100 forward declared in `build_selector_reference' */
2101 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2104 /* add one for the '\0' character */
2105 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2107 if (flag_next_runtime)
2108 finish_decl (decl, expr, NULL_TREE);
2109 else
2111 if (flag_typed_selectors)
2113 tree eltlist = NULL_TREE;
2114 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2115 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2116 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2117 expr = build_constructor (objc_selector_template,
2118 nreverse (eltlist));
2120 initlist = tree_cons (NULL_TREE, expr, initlist);
2125 if (! flag_next_runtime)
2127 /* Cause the variable and its initial value to be actually output. */
2128 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2129 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2130 /* NULL terminate the list and fix the decl for output. */
2131 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2132 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
2133 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2134 nreverse (initlist));
2135 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2136 current_function_decl = NULL_TREE;
2140 static tree
2141 get_proto_encoding (proto)
2142 tree proto;
2144 tree encoding;
2145 if (proto)
2147 tree tmp_decl;
2149 if (! METHOD_ENCODING (proto))
2151 tmp_decl = build_tmp_function_decl ();
2152 hack_method_prototype (proto, tmp_decl);
2153 encoding = encode_method_prototype (proto, tmp_decl);
2154 METHOD_ENCODING (proto) = encoding;
2156 else
2157 encoding = METHOD_ENCODING (proto);
2159 return add_objc_string (encoding, meth_var_types);
2161 else
2162 return build_int_2 (0, 0);
2165 /* sel_ref_chain is a list whose "value" fields will be instances of
2166 identifier_node that represent the selector. */
2168 static tree
2169 build_typed_selector_reference (ident, proto)
2170 tree ident, proto;
2172 tree *chain = &sel_ref_chain;
2173 tree expr;
2174 int index = 0;
2176 while (*chain)
2178 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2179 goto return_at_index;
2181 index++;
2182 chain = &TREE_CHAIN (*chain);
2185 *chain = perm_tree_cons (proto, ident, NULL_TREE);
2187 return_at_index:
2188 expr = build_unary_op (ADDR_EXPR,
2189 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2190 build_int_2 (index, 0)),
2192 return build_c_cast (selector_type, expr);
2195 static tree
2196 build_selector_reference (ident)
2197 tree ident;
2199 tree *chain = &sel_ref_chain;
2200 tree expr;
2201 int index = 0;
2203 while (*chain)
2205 if (TREE_VALUE (*chain) == ident)
2206 return (flag_next_runtime
2207 ? TREE_PURPOSE (*chain)
2208 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2209 build_int_2 (index, 0)));
2211 index++;
2212 chain = &TREE_CHAIN (*chain);
2215 expr = build_selector_reference_decl (ident);
2217 *chain = perm_tree_cons (expr, ident, NULL_TREE);
2219 return (flag_next_runtime
2220 ? expr
2221 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2222 build_int_2 (index, 0)));
2225 static tree
2226 build_class_reference_decl (name)
2227 tree name;
2229 tree decl, ident;
2230 char buf[256];
2231 static int idx = 0;
2233 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2235 push_obstacks_nochange ();
2236 end_temporary_allocation ();
2238 ident = get_identifier (buf);
2240 decl = build_decl (VAR_DECL, ident, objc_class_type);
2241 DECL_EXTERNAL (decl) = 1;
2242 TREE_PUBLIC (decl) = 1;
2243 TREE_USED (decl) = 1;
2244 TREE_READONLY (decl) = 1;
2245 DECL_CONTEXT (decl) = 0;
2246 DECL_ARTIFICIAL (decl) = 1;
2248 make_decl_rtl (decl, 0, 1);
2249 pushdecl_top_level (decl);
2251 pop_obstacks ();
2253 return decl;
2256 /* Create a class reference, but don't create a variable to reference
2257 it. */
2259 static void
2260 add_class_reference (ident)
2261 tree ident;
2263 tree chain;
2265 if ((chain = cls_ref_chain))
2267 tree tail;
2270 if (ident == TREE_VALUE (chain))
2271 return;
2273 tail = chain;
2274 chain = TREE_CHAIN (chain);
2276 while (chain);
2278 /* Append to the end of the list */
2279 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2281 else
2282 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2285 /* Get a class reference, creating it if necessary. Also create the
2286 reference variable. */
2288 tree
2289 get_class_reference (ident)
2290 tree ident;
2292 if (flag_next_runtime)
2294 tree *chain;
2295 tree decl;
2297 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2298 if (TREE_VALUE (*chain) == ident)
2300 if (! TREE_PURPOSE (*chain))
2301 TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
2303 return TREE_PURPOSE (*chain);
2306 decl = build_class_reference_decl (ident);
2307 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2308 return decl;
2310 else
2312 tree params;
2314 add_class_reference (ident);
2316 params = build_tree_list (NULL_TREE,
2317 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2318 IDENTIFIER_POINTER (ident)));
2320 assemble_external (objc_get_class_decl);
2321 return build_function_call (objc_get_class_decl, params);
2325 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2326 of identifier_node that represent the selector. It returns the
2327 offset of the selector from the beginning of the _OBJC_STRINGS
2328 pool. This offset is typically used by init_selector during code
2329 generation.
2331 For each string section we have a chain which maps identifier nodes
2332 to decls for the strings. */
2334 static tree
2335 add_objc_string (ident, section)
2336 tree ident;
2337 enum string_section section;
2339 tree *chain, decl;
2341 if (section == class_names)
2342 chain = &class_names_chain;
2343 else if (section == meth_var_names)
2344 chain = &meth_var_names_chain;
2345 else if (section == meth_var_types)
2346 chain = &meth_var_types_chain;
2348 while (*chain)
2350 if (TREE_VALUE (*chain) == ident)
2351 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2353 chain = &TREE_CHAIN (*chain);
2356 decl = build_objc_string_decl (ident, section);
2358 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2360 return build_unary_op (ADDR_EXPR, decl, 1);
2363 static tree
2364 build_objc_string_decl (name, section)
2365 tree name;
2366 enum string_section section;
2368 tree decl, ident;
2369 char buf[256];
2370 static int class_names_idx = 0;
2371 static int meth_var_names_idx = 0;
2372 static int meth_var_types_idx = 0;
2374 if (section == class_names)
2375 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2376 else if (section == meth_var_names)
2377 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2378 else if (section == meth_var_types)
2379 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2381 push_obstacks_nochange ();
2382 end_temporary_allocation ();
2383 ident = get_identifier (buf);
2385 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2386 DECL_EXTERNAL (decl) = 1;
2387 TREE_PUBLIC (decl) = 1;
2388 TREE_USED (decl) = 1;
2389 TREE_READONLY (decl) = 1;
2390 TREE_CONSTANT (decl) = 1;
2391 DECL_CONTEXT (decl) = 0;
2392 DECL_ARTIFICIAL (decl) = 1;
2394 make_decl_rtl (decl, 0, 1);
2395 pushdecl_top_level (decl);
2397 pop_obstacks ();
2399 return decl;
2403 void
2404 objc_declare_alias (alias_ident, class_ident)
2405 tree alias_ident;
2406 tree class_ident;
2408 if (!doing_objc_thang)
2409 objc_fatal ();
2411 if (is_class_name (class_ident) != class_ident)
2412 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2413 else if (is_class_name (alias_ident))
2414 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2415 else
2416 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2419 void
2420 objc_declare_class (ident_list)
2421 tree ident_list;
2423 tree list;
2425 if (!doing_objc_thang)
2426 objc_fatal ();
2428 for (list = ident_list; list; list = TREE_CHAIN (list))
2430 tree ident = TREE_VALUE (list);
2431 tree decl;
2433 if ((decl = lookup_name (ident)))
2435 error ("`%s' redeclared as different kind of symbol",
2436 IDENTIFIER_POINTER (ident));
2437 error_with_decl (decl, "previous declaration of `%s'");
2440 if (! is_class_name (ident))
2442 tree record = xref_tag (RECORD_TYPE, ident);
2443 TREE_STATIC_TEMPLATE (record) = 1;
2444 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2449 tree
2450 is_class_name (ident)
2451 tree ident;
2453 tree chain;
2455 if (lookup_interface (ident))
2456 return ident;
2458 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2460 if (ident == TREE_VALUE (chain))
2461 return ident;
2464 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2466 if (ident == TREE_VALUE (chain))
2467 return TREE_PURPOSE (chain);
2470 return 0;
2473 tree
2474 lookup_interface (ident)
2475 tree ident;
2477 tree chain;
2479 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2481 if (ident == CLASS_NAME (chain))
2482 return chain;
2484 return NULL_TREE;
2487 static tree
2488 objc_copy_list (list, head)
2489 tree list;
2490 tree *head;
2492 tree newlist = NULL_TREE, tail = NULL_TREE;
2494 while (list)
2496 tail = copy_node (list);
2498 /* The following statement fixes a bug when inheriting instance
2499 variables that are declared to be bitfields. finish_struct
2500 expects to find the width of the bitfield in DECL_INITIAL,
2501 which it nulls out after processing the decl of the super
2502 class...rather than change the way finish_struct works (which
2503 is risky), I create the situation it expects...s.naroff
2504 (7/23/89). */
2506 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2507 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2509 newlist = chainon (newlist, tail);
2510 list = TREE_CHAIN (list);
2513 *head = newlist;
2514 return tail;
2517 /* Used by: build_private_template, get_class_ivars, and
2518 continue_class. COPY is 1 when called from @defs. In this case
2519 copy all fields. Otherwise don't copy leaf ivars since we rely on
2520 them being side-effected exactly once by finish_struct. */
2522 static tree
2523 build_ivar_chain (interface, copy)
2524 tree interface;
2525 int copy;
2527 tree my_name, super_name, ivar_chain;
2529 my_name = CLASS_NAME (interface);
2530 super_name = CLASS_SUPER_NAME (interface);
2532 /* Possibly copy leaf ivars. */
2533 if (copy)
2534 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2535 else
2536 ivar_chain = CLASS_IVARS (interface);
2538 while (super_name)
2540 tree op1;
2541 tree super_interface = lookup_interface (super_name);
2543 if (!super_interface)
2545 /* fatal did not work with 2 args...should fix */
2546 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2547 IDENTIFIER_POINTER (super_name),
2548 IDENTIFIER_POINTER (my_name));
2549 exit (FATAL_EXIT_CODE);
2552 if (super_interface == interface)
2554 fatal ("Circular inheritance in interface declaration for `%s'",
2555 IDENTIFIER_POINTER (super_name));
2558 interface = super_interface;
2559 my_name = CLASS_NAME (interface);
2560 super_name = CLASS_SUPER_NAME (interface);
2562 op1 = CLASS_IVARS (interface);
2563 if (op1)
2565 tree head, tail = objc_copy_list (op1, &head);
2567 /* Prepend super class ivars...make a copy of the list, we
2568 do not want to alter the original. */
2569 TREE_CHAIN (tail) = ivar_chain;
2570 ivar_chain = head;
2573 return ivar_chain;
2576 /* struct <classname> {
2577 struct objc_class *isa;
2579 }; */
2581 static tree
2582 build_private_template (class)
2583 tree class;
2585 tree ivar_context;
2587 if (CLASS_STATIC_TEMPLATE (class))
2589 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2590 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2592 else
2594 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2596 ivar_context = build_ivar_chain (class, 0);
2598 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2600 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2602 /* mark this record as class template - for class type checking */
2603 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2606 instance_type
2607 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2608 uprivate_record),
2609 build1 (INDIRECT_REF, NULL_TREE,
2610 NULL_TREE)));
2612 return ivar_context;
2615 /* Begin code generation for protocols... */
2617 /* struct objc_protocol {
2618 char *protocol_name;
2619 struct objc_protocol **protocol_list;
2620 struct objc_method_desc *instance_methods;
2621 struct objc_method_desc *class_methods;
2622 }; */
2624 static tree
2625 build_protocol_template ()
2627 tree decl_specs, field_decl, field_decl_chain;
2628 tree template;
2630 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2632 /* struct objc_class *isa; */
2634 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2635 get_identifier (UTAG_CLASS)));
2636 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2637 field_decl
2638 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2639 field_decl_chain = field_decl;
2641 /* char *protocol_name; */
2643 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2644 field_decl
2645 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2646 field_decl
2647 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2648 chainon (field_decl_chain, field_decl);
2650 /* struct objc_protocol **protocol_list; */
2652 decl_specs = build_tree_list (NULL_TREE, template);
2653 field_decl
2654 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2655 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2656 field_decl
2657 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2658 chainon (field_decl_chain, field_decl);
2660 /* struct objc_method_list *instance_methods; */
2662 decl_specs
2663 = build_tree_list (NULL_TREE,
2664 xref_tag (RECORD_TYPE,
2665 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2666 field_decl
2667 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2668 field_decl
2669 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2670 chainon (field_decl_chain, field_decl);
2672 /* struct objc_method_list *class_methods; */
2674 decl_specs
2675 = build_tree_list (NULL_TREE,
2676 xref_tag (RECORD_TYPE,
2677 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2678 field_decl
2679 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2680 field_decl
2681 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2682 chainon (field_decl_chain, field_decl);
2684 return finish_struct (template, field_decl_chain, NULL_TREE);
2687 static tree
2688 build_descriptor_table_initializer (type, entries)
2689 tree type;
2690 tree entries;
2692 tree initlist = NULL_TREE;
2696 tree eltlist = NULL_TREE;
2698 eltlist
2699 = tree_cons (NULL_TREE,
2700 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2701 eltlist
2702 = tree_cons (NULL_TREE,
2703 add_objc_string (METHOD_ENCODING (entries),
2704 meth_var_types),
2705 eltlist);
2707 initlist
2708 = tree_cons (NULL_TREE,
2709 build_constructor (type, nreverse (eltlist)), initlist);
2711 entries = TREE_CHAIN (entries);
2713 while (entries);
2715 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2718 /* struct objc_method_prototype_list {
2719 int count;
2720 struct objc_method_prototype {
2721 SEL name;
2722 char *types;
2723 } list[1];
2724 }; */
2726 static tree
2727 build_method_prototype_list_template (list_type, size)
2728 tree list_type;
2729 int size;
2731 tree objc_ivar_list_record;
2732 tree decl_specs, field_decl, field_decl_chain;
2734 /* Generate an unnamed struct definition. */
2736 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2738 /* int method_count; */
2740 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2741 field_decl = get_identifier ("method_count");
2743 field_decl
2744 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2745 field_decl_chain = field_decl;
2747 /* struct objc_method method_list[]; */
2749 decl_specs = build_tree_list (NULL_TREE, list_type);
2750 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2751 build_int_2 (size, 0));
2753 field_decl
2754 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2755 chainon (field_decl_chain, field_decl);
2757 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2759 return objc_ivar_list_record;
2762 static tree
2763 build_method_prototype_template ()
2765 tree proto_record;
2766 tree decl_specs, field_decl, field_decl_chain;
2768 proto_record
2769 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2771 #ifdef OBJC_INT_SELECTORS
2772 /* unsigned int _cmd; */
2773 decl_specs
2774 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2775 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2776 field_decl = get_identifier ("_cmd");
2777 #else /* OBJC_INT_SELECTORS */
2778 /* struct objc_selector *_cmd; */
2779 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2780 get_identifier (TAG_SELECTOR)), NULL_TREE);
2781 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2782 #endif /* OBJC_INT_SELECTORS */
2784 field_decl
2785 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2786 field_decl_chain = field_decl;
2788 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2789 field_decl
2790 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2791 field_decl
2792 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2793 chainon (field_decl_chain, field_decl);
2795 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2797 return proto_record;
2800 /* True if last call to forwarding_offset yielded a register offset. */
2801 static int offset_is_register;
2803 static int
2804 forwarding_offset (parm)
2805 tree parm;
2807 int offset_in_bytes;
2809 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2811 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2813 /* ??? Here we assume that the parm address is indexed
2814 off the frame pointer or arg pointer.
2815 If that is not true, we produce meaningless results,
2816 but do not crash. */
2817 if (GET_CODE (addr) == PLUS
2818 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2819 offset_in_bytes = INTVAL (XEXP (addr, 1));
2820 else
2821 offset_in_bytes = 0;
2823 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2824 offset_is_register = 0;
2826 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2828 int regno = REGNO (DECL_INCOMING_RTL (parm));
2829 offset_in_bytes = apply_args_register_offset (regno);
2830 offset_is_register = 1;
2832 else
2833 return 0;
2835 /* This is the case where the parm is passed as an int or double
2836 and it is converted to a char, short or float and stored back
2837 in the parmlist. In this case, describe the parm
2838 with the variable's declared type, and adjust the address
2839 if the least significant bytes (which we are using) are not
2840 the first ones. */
2841 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2842 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2843 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2845 return offset_in_bytes;
2848 static tree
2849 encode_method_prototype (method_decl, func_decl)
2850 tree method_decl;
2851 tree func_decl;
2853 tree parms;
2854 int stack_size, i;
2855 tree user_args;
2856 int max_parm_end = 0;
2857 char buf[40];
2858 tree result;
2860 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2861 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2863 /* C type. */
2864 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2865 obstack_object_size (&util_obstack),
2866 OBJC_ENCODE_INLINE_DEFS);
2868 /* Stack size. */
2869 for (parms = DECL_ARGUMENTS (func_decl); parms;
2870 parms = TREE_CHAIN (parms))
2872 int parm_end = (forwarding_offset (parms)
2873 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2874 / BITS_PER_UNIT));
2876 if (!offset_is_register && max_parm_end < parm_end)
2877 max_parm_end = parm_end;
2880 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2882 sprintf (buf, "%d", stack_size);
2883 obstack_grow (&util_obstack, buf, strlen (buf));
2885 user_args = METHOD_SEL_ARGS (method_decl);
2887 /* Argument types. */
2888 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2889 parms = TREE_CHAIN (parms), i++)
2891 /* Process argument qualifiers for user supplied arguments. */
2892 if (i > 1)
2894 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2895 user_args = TREE_CHAIN (user_args);
2898 /* Type. */
2899 encode_type (TREE_TYPE (parms),
2900 obstack_object_size (&util_obstack),
2901 OBJC_ENCODE_INLINE_DEFS);
2903 /* Compute offset. */
2904 sprintf (buf, "%d", forwarding_offset (parms));
2906 /* Indicate register. */
2907 if (offset_is_register)
2908 obstack_1grow (&util_obstack, '+');
2910 obstack_grow (&util_obstack, buf, strlen (buf));
2913 obstack_1grow (&util_obstack, '\0');
2914 result = get_identifier (obstack_finish (&util_obstack));
2915 obstack_free (&util_obstack, util_firstobj);
2916 return result;
2919 static tree
2920 generate_descriptor_table (type, name, size, list, proto)
2921 tree type;
2922 char *name;
2923 int size;
2924 tree list;
2925 tree proto;
2927 tree sc_spec, decl_specs, decl, initlist;
2929 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2930 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2932 decl = start_decl (synth_id_with_class_suffix (name, proto),
2933 decl_specs, 1, NULL_TREE, NULL_TREE);
2935 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2936 initlist = tree_cons (NULL_TREE, list, initlist);
2938 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2939 NULL_TREE);
2941 return decl;
2944 static void
2945 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2946 tree protocol;
2948 static tree objc_method_prototype_template;
2949 tree initlist, chain, method_list_template;
2950 tree cast, variable_length_type;
2951 int size;
2953 if (!objc_method_prototype_template)
2954 objc_method_prototype_template = build_method_prototype_template ();
2956 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2957 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2958 NULL_TREE);
2959 variable_length_type = groktypename (cast);
2961 chain = PROTOCOL_CLS_METHODS (protocol);
2962 if (chain)
2964 size = list_length (chain);
2966 method_list_template
2967 = build_method_prototype_list_template (objc_method_prototype_template,
2968 size);
2970 initlist
2971 = build_descriptor_table_initializer (objc_method_prototype_template,
2972 chain);
2974 UOBJC_CLASS_METHODS_decl
2975 = generate_descriptor_table (method_list_template,
2976 "_OBJC_PROTOCOL_CLASS_METHODS",
2977 size, initlist, protocol);
2978 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2980 else
2981 UOBJC_CLASS_METHODS_decl = 0;
2983 chain = PROTOCOL_NST_METHODS (protocol);
2984 if (chain)
2986 size = list_length (chain);
2988 method_list_template
2989 = build_method_prototype_list_template (objc_method_prototype_template,
2990 size);
2991 initlist
2992 = build_descriptor_table_initializer (objc_method_prototype_template,
2993 chain);
2995 UOBJC_INSTANCE_METHODS_decl
2996 = generate_descriptor_table (method_list_template,
2997 "_OBJC_PROTOCOL_INSTANCE_METHODS",
2998 size, initlist, protocol);
2999 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3001 else
3002 UOBJC_INSTANCE_METHODS_decl = 0;
3005 static tree
3006 build_tmp_function_decl ()
3008 tree decl_specs, expr_decl, parms;
3009 static int xxx = 0;
3010 char buffer[80];
3012 /* struct objc_object *objc_xxx (id, SEL, ...); */
3013 pushlevel (0);
3014 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3015 push_parm_decl (build_tree_list
3016 (build_tree_list (decl_specs,
3017 build1 (INDIRECT_REF, NULL_TREE,
3018 NULL_TREE)),
3019 build_tree_list (NULL_TREE, NULL_TREE)));
3021 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3022 get_identifier (TAG_SELECTOR)));
3023 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
3025 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
3026 build_tree_list (NULL_TREE, NULL_TREE)));
3027 parms = get_parm_info (0);
3028 poplevel (0, 0, 0);
3030 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3031 sprintf (buffer, "__objc_tmp_%x", xxx++);
3032 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
3033 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
3035 return define_decl (expr_decl, decl_specs);
3038 static void
3039 hack_method_prototype (nst_methods, tmp_decl)
3040 tree nst_methods;
3041 tree tmp_decl;
3043 tree parms;
3044 tree parm;
3046 /* Hack to avoid problem with static typing of self arg. */
3047 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
3048 start_method_def (nst_methods);
3049 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
3051 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
3052 parms = get_parm_info (0); /* we have a `, ...' */
3053 else
3054 parms = get_parm_info (1); /* place a `void_at_end' */
3056 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
3058 /* Usually called from store_parm_decls -> init_function_start. */
3060 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
3061 current_function_decl = tmp_decl;
3064 /* Code taken from start_function. */
3065 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3066 /* Promote the value to int before returning it. */
3067 if (TREE_CODE (restype) == INTEGER_TYPE
3068 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3069 restype = integer_type_node;
3070 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3073 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3074 DECL_CONTEXT (parm) = tmp_decl;
3076 init_function_start (tmp_decl, "objc-act", 0);
3078 /* Typically called from expand_function_start for function definitions. */
3079 assign_parms (tmp_decl, 0);
3081 /* install return type */
3082 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3086 static void
3087 generate_protocol_references (plist)
3088 tree plist;
3090 tree lproto;
3092 /* Forward declare protocols referenced. */
3093 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3095 tree proto = TREE_VALUE (lproto);
3097 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3098 && PROTOCOL_NAME (proto))
3100 if (! PROTOCOL_FORWARD_DECL (proto))
3101 build_protocol_reference (proto);
3103 if (PROTOCOL_LIST (proto))
3104 generate_protocol_references (PROTOCOL_LIST (proto));
3109 static void
3110 generate_protocols ()
3112 tree p, tmp_decl, encoding;
3113 tree sc_spec, decl_specs, decl;
3114 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3115 tree cast_type2 = 0;
3117 tmp_decl = build_tmp_function_decl ();
3119 if (! objc_protocol_template)
3120 objc_protocol_template = build_protocol_template ();
3122 /* If a protocol was directly referenced, pull in indirect references. */
3123 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3124 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3125 generate_protocol_references (PROTOCOL_LIST (p));
3127 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3129 tree nst_methods = PROTOCOL_NST_METHODS (p);
3130 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3132 /* If protocol wasn't referenced, don't generate any code. */
3133 if (! PROTOCOL_FORWARD_DECL (p))
3134 continue;
3136 /* Make sure we link in the Protocol class. */
3137 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3139 while (nst_methods)
3141 if (! METHOD_ENCODING (nst_methods))
3143 hack_method_prototype (nst_methods, tmp_decl);
3144 encoding = encode_method_prototype (nst_methods, tmp_decl);
3145 METHOD_ENCODING (nst_methods) = encoding;
3147 nst_methods = TREE_CHAIN (nst_methods);
3150 while (cls_methods)
3152 if (! METHOD_ENCODING (cls_methods))
3154 hack_method_prototype (cls_methods, tmp_decl);
3155 encoding = encode_method_prototype (cls_methods, tmp_decl);
3156 METHOD_ENCODING (cls_methods) = encoding;
3159 cls_methods = TREE_CHAIN (cls_methods);
3161 generate_method_descriptors (p);
3163 if (PROTOCOL_LIST (p))
3164 refs_decl = generate_protocol_list (p);
3165 else
3166 refs_decl = 0;
3168 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3170 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3171 NULL_TREE);
3172 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3174 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3175 decl_specs, 1, NULL_TREE, NULL_TREE);
3177 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3179 if (refs_decl)
3181 if (!cast_type2)
3182 cast_type2
3183 = groktypename
3184 (build_tree_list (build_tree_list (NULL_TREE,
3185 objc_protocol_template),
3186 build1 (INDIRECT_REF, NULL_TREE,
3187 build1 (INDIRECT_REF, NULL_TREE,
3188 NULL_TREE))));
3190 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3191 TREE_TYPE (refs_expr) = cast_type2;
3193 else
3194 refs_expr = build_int_2 (0, 0);
3196 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3197 by generate_method_descriptors, which is called above. */
3198 initlist = build_protocol_initializer (TREE_TYPE (decl),
3199 protocol_name_expr, refs_expr,
3200 UOBJC_INSTANCE_METHODS_decl,
3201 UOBJC_CLASS_METHODS_decl);
3202 finish_decl (decl, initlist, NULL_TREE);
3204 /* Mark the decl as used to avoid "defined but not used" warning. */
3205 TREE_USED (decl) = 1;
3209 static tree
3210 build_protocol_initializer (type, protocol_name, protocol_list,
3211 instance_methods, class_methods)
3212 tree type;
3213 tree protocol_name;
3214 tree protocol_list;
3215 tree instance_methods;
3216 tree class_methods;
3218 tree initlist = NULL_TREE, expr;
3219 static tree cast_type = 0;
3221 if (!cast_type)
3222 cast_type
3223 = groktypename
3224 (build_tree_list
3225 (build_tree_list (NULL_TREE,
3226 xref_tag (RECORD_TYPE,
3227 get_identifier (UTAG_CLASS))),
3228 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3230 /* Filling the "isa" in with one allows the runtime system to
3231 detect that the version change...should remove before final release. */
3233 expr = build_int_2 (PROTOCOL_VERSION, 0);
3234 TREE_TYPE (expr) = cast_type;
3235 initlist = tree_cons (NULL_TREE, expr, initlist);
3236 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3237 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3239 if (!instance_methods)
3240 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3241 else
3243 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3244 initlist = tree_cons (NULL_TREE, expr, initlist);
3247 if (!class_methods)
3248 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3249 else
3251 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3252 initlist = tree_cons (NULL_TREE, expr, initlist);
3255 return build_constructor (type, nreverse (initlist));
3258 /* struct objc_category {
3259 char *category_name;
3260 char *class_name;
3261 struct objc_method_list *instance_methods;
3262 struct objc_method_list *class_methods;
3263 struct objc_protocol_list *protocols;
3264 }; */
3266 static void
3267 build_category_template ()
3269 tree decl_specs, field_decl, field_decl_chain;
3271 objc_category_template = start_struct (RECORD_TYPE,
3272 get_identifier (UTAG_CATEGORY));
3273 /* char *category_name; */
3275 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3276 field_decl
3277 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3278 field_decl
3279 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3280 field_decl_chain = field_decl;
3282 /* char *class_name; */
3284 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3285 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3286 field_decl
3287 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3288 chainon (field_decl_chain, field_decl);
3290 /* struct objc_method_list *instance_methods; */
3292 decl_specs = build_tree_list (NULL_TREE,
3293 xref_tag (RECORD_TYPE,
3294 get_identifier (UTAG_METHOD_LIST)));
3295 field_decl
3296 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3297 field_decl
3298 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3299 chainon (field_decl_chain, field_decl);
3301 /* struct objc_method_list *class_methods; */
3303 decl_specs = build_tree_list (NULL_TREE,
3304 xref_tag (RECORD_TYPE,
3305 get_identifier (UTAG_METHOD_LIST)));
3306 field_decl
3307 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3308 field_decl
3309 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3310 chainon (field_decl_chain, field_decl);
3312 /* struct objc_protocol **protocol_list; */
3314 decl_specs = build_tree_list (NULL_TREE,
3315 xref_tag (RECORD_TYPE,
3316 get_identifier (UTAG_PROTOCOL)));
3317 field_decl
3318 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3319 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3320 field_decl
3321 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3322 chainon (field_decl_chain, field_decl);
3324 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3327 /* struct objc_selector {
3328 void *sel_id;
3329 char *sel_type;
3330 }; */
3332 static void
3333 build_selector_template ()
3336 tree decl_specs, field_decl, field_decl_chain;
3338 objc_selector_template
3339 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3341 /* void *sel_id; */
3343 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3344 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3345 field_decl
3346 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3347 field_decl_chain = field_decl;
3349 /* char *sel_type; */
3351 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3352 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3353 field_decl
3354 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3355 chainon (field_decl_chain, field_decl);
3357 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3360 /* struct objc_class {
3361 struct objc_class *isa;
3362 struct objc_class *super_class;
3363 char *name;
3364 long version;
3365 long info;
3366 long instance_size;
3367 struct objc_ivar_list *ivars;
3368 struct objc_method_list *methods;
3369 if (flag_next_runtime)
3370 struct objc_cache *cache;
3371 else {
3372 struct sarray *dtable;
3373 struct objc_class *subclass_list;
3374 struct objc_class *sibling_class;
3376 struct objc_protocol_list *protocols;
3377 }; */
3379 static void
3380 build_class_template ()
3382 tree decl_specs, field_decl, field_decl_chain;
3384 objc_class_template
3385 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3387 /* struct objc_class *isa; */
3389 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3390 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3391 field_decl
3392 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3393 field_decl_chain = field_decl;
3395 /* struct objc_class *super_class; */
3397 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3398 field_decl
3399 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3400 field_decl
3401 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3402 chainon (field_decl_chain, field_decl);
3404 /* char *name; */
3406 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3407 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3408 field_decl
3409 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3410 chainon (field_decl_chain, field_decl);
3412 /* long version; */
3414 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3415 field_decl = get_identifier ("version");
3416 field_decl
3417 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3418 chainon (field_decl_chain, field_decl);
3420 /* long info; */
3422 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3423 field_decl = get_identifier ("info");
3424 field_decl
3425 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3426 chainon (field_decl_chain, field_decl);
3428 /* long instance_size; */
3430 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3431 field_decl = get_identifier ("instance_size");
3432 field_decl
3433 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3434 chainon (field_decl_chain, field_decl);
3436 /* struct objc_ivar_list *ivars; */
3438 decl_specs = build_tree_list (NULL_TREE,
3439 xref_tag (RECORD_TYPE,
3440 get_identifier (UTAG_IVAR_LIST)));
3441 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3442 field_decl
3443 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3444 chainon (field_decl_chain, field_decl);
3446 /* struct objc_method_list *methods; */
3448 decl_specs = build_tree_list (NULL_TREE,
3449 xref_tag (RECORD_TYPE,
3450 get_identifier (UTAG_METHOD_LIST)));
3451 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3452 field_decl
3453 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3454 chainon (field_decl_chain, field_decl);
3456 if (flag_next_runtime)
3458 /* struct objc_cache *cache; */
3460 decl_specs = build_tree_list (NULL_TREE,
3461 xref_tag (RECORD_TYPE,
3462 get_identifier ("objc_cache")));
3463 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3464 field_decl = grokfield (input_filename, lineno, field_decl,
3465 decl_specs, NULL_TREE);
3466 chainon (field_decl_chain, field_decl);
3468 else
3470 /* struct sarray *dtable; */
3472 decl_specs = build_tree_list (NULL_TREE,
3473 xref_tag (RECORD_TYPE,
3474 get_identifier ("sarray")));
3475 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3476 field_decl = grokfield (input_filename, lineno, field_decl,
3477 decl_specs, NULL_TREE);
3478 chainon (field_decl_chain, field_decl);
3480 /* struct objc_class *subclass_list; */
3482 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3483 field_decl
3484 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3485 field_decl = grokfield (input_filename, lineno, field_decl,
3486 decl_specs, NULL_TREE);
3487 chainon (field_decl_chain, field_decl);
3489 /* struct objc_class *sibling_class; */
3491 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3492 field_decl
3493 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3494 field_decl = grokfield (input_filename, lineno, field_decl,
3495 decl_specs, NULL_TREE);
3496 chainon (field_decl_chain, field_decl);
3499 /* struct objc_protocol **protocol_list; */
3501 decl_specs = build_tree_list (NULL_TREE,
3502 xref_tag (RECORD_TYPE,
3503 get_identifier (UTAG_PROTOCOL)));
3504 field_decl
3505 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3506 field_decl
3507 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3508 field_decl = grokfield (input_filename, lineno, field_decl,
3509 decl_specs, NULL_TREE);
3510 chainon (field_decl_chain, field_decl);
3513 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3516 /* Generate appropriate forward declarations for an implementation. */
3518 static void
3519 synth_forward_declarations ()
3521 tree sc_spec, decl_specs, an_id;
3523 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3525 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3527 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3528 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3529 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3530 TREE_USED (UOBJC_CLASS_decl) = 1;
3531 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3533 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3535 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3536 implementation_context);
3538 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3539 TREE_USED (UOBJC_METACLASS_decl) = 1;
3540 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3542 /* Pre-build the following entities - for speed/convenience. */
3544 an_id = get_identifier ("super_class");
3545 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3546 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3549 static void
3550 error_with_ivar (message, decl, rawdecl)
3551 char *message;
3552 tree decl;
3553 tree rawdecl;
3555 count_error (0);
3557 report_error_function (DECL_SOURCE_FILE (decl));
3559 fprintf (stderr, "%s:%d: ",
3560 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3561 bzero (errbuf, BUFSIZE);
3562 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3565 #define USERTYPE(t) \
3566 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3567 || TREE_CODE (t) == ENUMERAL_TYPE)
3569 static void
3570 check_ivars (inter, imp)
3571 tree inter;
3572 tree imp;
3574 tree intdecls = CLASS_IVARS (inter);
3575 tree impdecls = CLASS_IVARS (imp);
3576 tree rawintdecls = CLASS_RAW_IVARS (inter);
3577 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3579 while (1)
3581 tree t1, t2;
3583 if (intdecls == 0 && impdecls == 0)
3584 break;
3585 if (intdecls == 0 || impdecls == 0)
3587 error ("inconsistent instance variable specification");
3588 break;
3591 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3593 if (!comptypes (t1, t2))
3595 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3597 error_with_ivar ("conflicting instance variable type",
3598 impdecls, rawimpdecls);
3599 error_with_ivar ("previous declaration of",
3600 intdecls, rawintdecls);
3602 else /* both the type and the name don't match */
3604 error ("inconsistent instance variable specification");
3605 break;
3609 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3611 error_with_ivar ("conflicting instance variable name",
3612 impdecls, rawimpdecls);
3613 error_with_ivar ("previous declaration of",
3614 intdecls, rawintdecls);
3617 intdecls = TREE_CHAIN (intdecls);
3618 impdecls = TREE_CHAIN (impdecls);
3619 rawintdecls = TREE_CHAIN (rawintdecls);
3620 rawimpdecls = TREE_CHAIN (rawimpdecls);
3624 /* Set super_type to the data type node for struct objc_super *,
3625 first defining struct objc_super itself.
3626 This needs to be done just once per compilation. */
3628 static tree
3629 build_super_template ()
3631 tree record, decl_specs, field_decl, field_decl_chain;
3633 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3635 /* struct objc_object *self; */
3637 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3638 field_decl = get_identifier ("self");
3639 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3640 field_decl = grokfield (input_filename, lineno,
3641 field_decl, decl_specs, NULL_TREE);
3642 field_decl_chain = field_decl;
3644 /* struct objc_class *class; */
3646 decl_specs = get_identifier (UTAG_CLASS);
3647 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3648 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3650 field_decl = grokfield (input_filename, lineno,
3651 field_decl, decl_specs, NULL_TREE);
3652 chainon (field_decl_chain, field_decl);
3654 finish_struct (record, field_decl_chain, NULL_TREE);
3656 /* `struct objc_super *' */
3657 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3658 record),
3659 build1 (INDIRECT_REF,
3660 NULL_TREE, NULL_TREE)));
3661 return record;
3664 /* struct objc_ivar {
3665 char *ivar_name;
3666 char *ivar_type;
3667 int ivar_offset;
3668 }; */
3670 static tree
3671 build_ivar_template ()
3673 tree objc_ivar_id, objc_ivar_record;
3674 tree decl_specs, field_decl, field_decl_chain;
3676 objc_ivar_id = get_identifier (UTAG_IVAR);
3677 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3679 /* char *ivar_name; */
3681 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3682 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3684 field_decl = grokfield (input_filename, lineno, field_decl,
3685 decl_specs, NULL_TREE);
3686 field_decl_chain = field_decl;
3688 /* char *ivar_type; */
3690 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3691 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3693 field_decl = grokfield (input_filename, lineno, field_decl,
3694 decl_specs, NULL_TREE);
3695 chainon (field_decl_chain, field_decl);
3697 /* int ivar_offset; */
3699 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3700 field_decl = get_identifier ("ivar_offset");
3702 field_decl = grokfield (input_filename, lineno, field_decl,
3703 decl_specs, NULL_TREE);
3704 chainon (field_decl_chain, field_decl);
3706 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3708 return objc_ivar_record;
3711 /* struct {
3712 int ivar_count;
3713 struct objc_ivar ivar_list[ivar_count];
3714 }; */
3716 static tree
3717 build_ivar_list_template (list_type, size)
3718 tree list_type;
3719 int size;
3721 tree objc_ivar_list_record;
3722 tree decl_specs, field_decl, field_decl_chain;
3724 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3726 /* int ivar_count; */
3728 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3729 field_decl = get_identifier ("ivar_count");
3731 field_decl = grokfield (input_filename, lineno, field_decl,
3732 decl_specs, NULL_TREE);
3733 field_decl_chain = field_decl;
3735 /* struct objc_ivar ivar_list[]; */
3737 decl_specs = build_tree_list (NULL_TREE, list_type);
3738 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3739 build_int_2 (size, 0));
3741 field_decl = grokfield (input_filename, lineno,
3742 field_decl, decl_specs, NULL_TREE);
3743 chainon (field_decl_chain, field_decl);
3745 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3747 return objc_ivar_list_record;
3750 /* struct {
3751 int method_next;
3752 int method_count;
3753 struct objc_method method_list[method_count];
3754 }; */
3756 static tree
3757 build_method_list_template (list_type, size)
3758 tree list_type;
3759 int size;
3761 tree objc_ivar_list_record;
3762 tree decl_specs, field_decl, field_decl_chain;
3764 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3766 /* int method_next; */
3768 decl_specs
3769 = build_tree_list
3770 (NULL_TREE,
3771 xref_tag (RECORD_TYPE,
3772 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3773 field_decl
3774 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3775 field_decl = grokfield (input_filename, lineno, field_decl,
3776 decl_specs, NULL_TREE);
3777 field_decl_chain = field_decl;
3779 /* int method_count; */
3781 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3782 field_decl = get_identifier ("method_count");
3784 field_decl = grokfield (input_filename, lineno,
3785 field_decl, decl_specs, NULL_TREE);
3786 chainon (field_decl_chain, field_decl);
3788 /* struct objc_method method_list[]; */
3790 decl_specs = build_tree_list (NULL_TREE, list_type);
3791 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3792 build_int_2 (size, 0));
3794 field_decl = grokfield (input_filename, lineno,
3795 field_decl, decl_specs, NULL_TREE);
3796 chainon (field_decl_chain, field_decl);
3798 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3800 return objc_ivar_list_record;
3803 static tree
3804 build_ivar_list_initializer (type, field_decl)
3805 tree type;
3806 tree field_decl;
3808 tree initlist = NULL_TREE;
3812 tree ivar = NULL_TREE;
3814 /* Set name. */
3815 if (DECL_NAME (field_decl))
3816 ivar = tree_cons (NULL_TREE,
3817 add_objc_string (DECL_NAME (field_decl),
3818 meth_var_names),
3819 ivar);
3820 else
3821 /* Unnamed bit-field ivar (yuck). */
3822 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3824 /* Set type. */
3825 encode_field_decl (field_decl,
3826 obstack_object_size (&util_obstack),
3827 OBJC_ENCODE_DONT_INLINE_DEFS);
3829 /* Null terminate string. */
3830 obstack_1grow (&util_obstack, 0);
3831 ivar
3832 = tree_cons
3833 (NULL_TREE,
3834 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3835 meth_var_types),
3836 ivar);
3837 obstack_free (&util_obstack, util_firstobj);
3839 /* set offset */
3840 ivar
3841 = tree_cons
3842 (NULL_TREE,
3843 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3844 / BITS_PER_UNIT),
3846 ivar);
3848 initlist = tree_cons (NULL_TREE,
3849 build_constructor (type, nreverse (ivar)),
3850 initlist);
3852 field_decl = TREE_CHAIN (field_decl);
3854 while (field_decl);
3856 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3859 static tree
3860 generate_ivars_list (type, name, size, list)
3861 tree type;
3862 char *name;
3863 int size;
3864 tree list;
3866 tree sc_spec, decl_specs, decl, initlist;
3868 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3869 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3871 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3872 decl_specs, 1, NULL_TREE, NULL_TREE);
3874 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3875 initlist = tree_cons (NULL_TREE, list, initlist);
3877 finish_decl (decl,
3878 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3879 NULL_TREE);
3881 return decl;
3884 static void
3885 generate_ivar_lists ()
3887 tree initlist, ivar_list_template, chain;
3888 tree cast, variable_length_type;
3889 int size;
3891 generating_instance_variables = 1;
3893 if (!objc_ivar_template)
3894 objc_ivar_template = build_ivar_template ();
3896 cast
3897 = build_tree_list
3898 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3899 get_identifier (UTAG_IVAR_LIST))),
3900 NULL_TREE);
3901 variable_length_type = groktypename (cast);
3903 /* Only generate class variables for the root of the inheritance
3904 hierarchy since these will be the same for every class. */
3906 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3907 && (chain = TYPE_FIELDS (objc_class_template)))
3909 size = list_length (chain);
3911 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3912 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3914 UOBJC_CLASS_VARIABLES_decl
3915 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3916 size, initlist);
3917 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3919 else
3920 UOBJC_CLASS_VARIABLES_decl = 0;
3922 chain = CLASS_IVARS (implementation_template);
3923 if (chain)
3925 size = list_length (chain);
3926 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3927 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3929 UOBJC_INSTANCE_VARIABLES_decl
3930 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3931 size, initlist);
3932 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3934 else
3935 UOBJC_INSTANCE_VARIABLES_decl = 0;
3937 generating_instance_variables = 0;
3940 static tree
3941 build_dispatch_table_initializer (type, entries)
3942 tree type;
3943 tree entries;
3945 tree initlist = NULL_TREE;
3949 tree elemlist = NULL_TREE;
3951 elemlist = tree_cons (NULL_TREE,
3952 build_selector (METHOD_SEL_NAME (entries)),
3953 NULL_TREE);
3955 elemlist = tree_cons (NULL_TREE,
3956 add_objc_string (METHOD_ENCODING (entries),
3957 meth_var_types),
3958 elemlist);
3960 elemlist = tree_cons (NULL_TREE,
3961 build_unary_op (ADDR_EXPR,
3962 METHOD_DEFINITION (entries), 1),
3963 elemlist);
3965 initlist = tree_cons (NULL_TREE,
3966 build_constructor (type, nreverse (elemlist)),
3967 initlist);
3969 entries = TREE_CHAIN (entries);
3971 while (entries);
3973 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3976 /* To accomplish method prototyping without generating all kinds of
3977 inane warnings, the definition of the dispatch table entries were
3978 changed from:
3980 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3982 struct objc_method { SEL _cmd; ...; void *_imp; }; */
3984 static tree
3985 build_method_template ()
3987 tree _SLT_record;
3988 tree decl_specs, field_decl, field_decl_chain;
3990 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3992 #ifdef OBJC_INT_SELECTORS
3993 /* unsigned int _cmd; */
3994 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
3995 NULL_TREE);
3996 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
3997 field_decl = get_identifier ("_cmd");
3998 #else /* not OBJC_INT_SELECTORS */
3999 /* struct objc_selector *_cmd; */
4000 decl_specs = tree_cons (NULL_TREE,
4001 xref_tag (RECORD_TYPE,
4002 get_identifier (TAG_SELECTOR)),
4003 NULL_TREE);
4004 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4005 #endif /* not OBJC_INT_SELECTORS */
4007 field_decl = grokfield (input_filename, lineno, field_decl,
4008 decl_specs, NULL_TREE);
4009 field_decl_chain = field_decl;
4011 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4012 field_decl = build1 (INDIRECT_REF, NULL_TREE,
4013 get_identifier ("method_types"));
4014 field_decl = grokfield (input_filename, lineno, field_decl,
4015 decl_specs, NULL_TREE);
4016 chainon (field_decl_chain, field_decl);
4018 /* void *_imp; */
4020 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4021 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4022 field_decl = grokfield (input_filename, lineno, field_decl,
4023 decl_specs, NULL_TREE);
4024 chainon (field_decl_chain, field_decl);
4026 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4028 return _SLT_record;
4032 static tree
4033 generate_dispatch_table (type, name, size, list)
4034 tree type;
4035 char *name;
4036 int size;
4037 tree list;
4039 tree sc_spec, decl_specs, decl, initlist;
4041 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4042 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4044 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
4045 decl_specs, 1, NULL_TREE, NULL_TREE);
4047 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4048 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4049 initlist = tree_cons (NULL_TREE, list, initlist);
4051 finish_decl (decl,
4052 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4053 NULL_TREE);
4055 return decl;
4058 static void
4059 generate_dispatch_tables ()
4061 tree initlist, chain, method_list_template;
4062 tree cast, variable_length_type;
4063 int size;
4065 if (!objc_method_template)
4066 objc_method_template = build_method_template ();
4068 cast
4069 = build_tree_list
4070 (build_tree_list (NULL_TREE,
4071 xref_tag (RECORD_TYPE,
4072 get_identifier (UTAG_METHOD_LIST))),
4073 NULL_TREE);
4075 variable_length_type = groktypename (cast);
4077 chain = CLASS_CLS_METHODS (implementation_context);
4078 if (chain)
4080 size = list_length (chain);
4082 method_list_template
4083 = build_method_list_template (objc_method_template, size);
4084 initlist
4085 = build_dispatch_table_initializer (objc_method_template, chain);
4087 UOBJC_CLASS_METHODS_decl
4088 = generate_dispatch_table (method_list_template,
4089 ((TREE_CODE (implementation_context)
4090 == CLASS_IMPLEMENTATION_TYPE)
4091 ? "_OBJC_CLASS_METHODS"
4092 : "_OBJC_CATEGORY_CLASS_METHODS"),
4093 size, initlist);
4094 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4096 else
4097 UOBJC_CLASS_METHODS_decl = 0;
4099 chain = CLASS_NST_METHODS (implementation_context);
4100 if (chain)
4102 size = list_length (chain);
4104 method_list_template
4105 = build_method_list_template (objc_method_template, size);
4106 initlist
4107 = build_dispatch_table_initializer (objc_method_template, chain);
4109 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4110 UOBJC_INSTANCE_METHODS_decl
4111 = generate_dispatch_table (method_list_template,
4112 "_OBJC_INSTANCE_METHODS",
4113 size, initlist);
4114 else
4115 /* We have a category. */
4116 UOBJC_INSTANCE_METHODS_decl
4117 = generate_dispatch_table (method_list_template,
4118 "_OBJC_CATEGORY_INSTANCE_METHODS",
4119 size, initlist);
4120 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4122 else
4123 UOBJC_INSTANCE_METHODS_decl = 0;
4126 static tree
4127 generate_protocol_list (i_or_p)
4128 tree i_or_p;
4130 static tree cast_type = 0;
4131 tree initlist, decl_specs, sc_spec;
4132 tree refs_decl, expr_decl, lproto, e, plist;
4133 int size = 0;
4135 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4136 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4137 plist = CLASS_PROTOCOL_LIST (i_or_p);
4138 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4139 plist = PROTOCOL_LIST (i_or_p);
4140 else
4141 abort ();
4143 if (!cast_type)
4144 cast_type
4145 = groktypename
4146 (build_tree_list
4147 (build_tree_list (NULL_TREE,
4148 xref_tag (RECORD_TYPE,
4149 get_identifier (UTAG_PROTOCOL))),
4150 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4152 /* Compute size. */
4153 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4154 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4155 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4156 size++;
4158 /* Build initializer. */
4159 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4161 e = build_int_2 (size, 0);
4162 TREE_TYPE (e) = cast_type;
4163 initlist = tree_cons (NULL_TREE, e, initlist);
4165 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4167 tree pval = TREE_VALUE (lproto);
4169 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4170 && PROTOCOL_FORWARD_DECL (pval))
4172 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4173 initlist = tree_cons (NULL_TREE, e, initlist);
4177 /* static struct objc_protocol *refs[n]; */
4179 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4180 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4181 get_identifier (UTAG_PROTOCOL)),
4182 sc_spec);
4184 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4185 expr_decl = build_nt (ARRAY_REF,
4186 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4187 i_or_p),
4188 build_int_2 (size + 2, 0));
4189 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4190 expr_decl = build_nt (ARRAY_REF,
4191 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4192 i_or_p),
4193 build_int_2 (size + 2, 0));
4194 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4195 expr_decl
4196 = build_nt (ARRAY_REF,
4197 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4198 i_or_p),
4199 build_int_2 (size + 2, 0));
4201 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4203 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4205 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4206 nreverse (initlist)),
4207 NULL_TREE);
4209 return refs_decl;
4212 static tree
4213 build_category_initializer (type, cat_name, class_name,
4214 instance_methods, class_methods, protocol_list)
4215 tree type;
4216 tree cat_name;
4217 tree class_name;
4218 tree instance_methods;
4219 tree class_methods;
4220 tree protocol_list;
4222 tree initlist = NULL_TREE, expr;
4224 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4225 initlist = tree_cons (NULL_TREE, class_name, initlist);
4227 if (!instance_methods)
4228 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4229 else
4231 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4232 initlist = tree_cons (NULL_TREE, expr, initlist);
4234 if (!class_methods)
4235 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4236 else
4238 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4239 initlist = tree_cons (NULL_TREE, expr, initlist);
4242 /* protocol_list = */
4243 if (!protocol_list)
4244 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4245 else
4247 static tree cast_type2;
4249 if (!cast_type2)
4250 cast_type2
4251 = groktypename
4252 (build_tree_list
4253 (build_tree_list (NULL_TREE,
4254 xref_tag (RECORD_TYPE,
4255 get_identifier (UTAG_PROTOCOL))),
4256 build1 (INDIRECT_REF, NULL_TREE,
4257 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4259 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4260 TREE_TYPE (expr) = cast_type2;
4261 initlist = tree_cons (NULL_TREE, expr, initlist);
4264 return build_constructor (type, nreverse (initlist));
4267 /* struct objc_class {
4268 struct objc_class *isa;
4269 struct objc_class *super_class;
4270 char *name;
4271 long version;
4272 long info;
4273 long instance_size;
4274 struct objc_ivar_list *ivars;
4275 struct objc_method_list *methods;
4276 if (flag_next_runtime)
4277 struct objc_cache *cache;
4278 else {
4279 struct sarray *dtable;
4280 struct objc_class *subclass_list;
4281 struct objc_class *sibling_class;
4283 struct objc_protocol_list *protocols;
4284 }; */
4286 static tree
4287 build_shared_structure_initializer (type, isa, super, name, size, status,
4288 dispatch_table, ivar_list, protocol_list)
4289 tree type;
4290 tree isa;
4291 tree super;
4292 tree name;
4293 tree size;
4294 int status;
4295 tree dispatch_table;
4296 tree ivar_list;
4297 tree protocol_list;
4299 tree initlist = NULL_TREE, expr;
4301 /* isa = */
4302 initlist = tree_cons (NULL_TREE, isa, initlist);
4304 /* super_class = */
4305 initlist = tree_cons (NULL_TREE, super, initlist);
4307 /* name = */
4308 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4310 /* version = */
4311 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4313 /* info = */
4314 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4316 /* instance_size = */
4317 initlist = tree_cons (NULL_TREE, size, initlist);
4319 /* objc_ivar_list = */
4320 if (!ivar_list)
4321 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4322 else
4324 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4325 initlist = tree_cons (NULL_TREE, expr, initlist);
4328 /* objc_method_list = */
4329 if (!dispatch_table)
4330 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4331 else
4333 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4334 initlist = tree_cons (NULL_TREE, expr, initlist);
4337 if (flag_next_runtime)
4338 /* method_cache = */
4339 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4340 else
4342 /* dtable = */
4343 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4345 /* subclass_list = */
4346 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4348 /* sibling_class = */
4349 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4352 /* protocol_list = */
4353 if (! protocol_list)
4354 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4355 else
4357 static tree cast_type2;
4359 if (!cast_type2)
4360 cast_type2
4361 = groktypename
4362 (build_tree_list
4363 (build_tree_list (NULL_TREE,
4364 xref_tag (RECORD_TYPE,
4365 get_identifier (UTAG_PROTOCOL))),
4366 build1 (INDIRECT_REF, NULL_TREE,
4367 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4369 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4370 TREE_TYPE (expr) = cast_type2;
4371 initlist = tree_cons (NULL_TREE, expr, initlist);
4374 return build_constructor (type, nreverse (initlist));
4377 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4379 static void
4380 generate_category (cat)
4381 tree cat;
4383 tree sc_spec, decl_specs, decl;
4384 tree initlist, cat_name_expr, class_name_expr;
4385 tree protocol_decl, category;
4387 add_class_reference (CLASS_NAME (cat));
4388 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4390 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4392 category = CLASS_CATEGORY_LIST (implementation_template);
4394 /* find the category interface from the class it is associated with */
4395 while (category)
4397 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4398 break;
4399 category = CLASS_CATEGORY_LIST (category);
4402 if (category && CLASS_PROTOCOL_LIST (category))
4404 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4405 protocol_decl = generate_protocol_list (category);
4407 else
4408 protocol_decl = 0;
4410 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4411 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4413 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4414 implementation_context),
4415 decl_specs, 1, NULL_TREE, NULL_TREE);
4417 initlist = build_category_initializer (TREE_TYPE (decl),
4418 cat_name_expr, class_name_expr,
4419 UOBJC_INSTANCE_METHODS_decl,
4420 UOBJC_CLASS_METHODS_decl,
4421 protocol_decl);
4423 TREE_USED (decl) = 1;
4424 finish_decl (decl, initlist, NULL_TREE);
4427 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4428 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4430 static void
4431 generate_shared_structures ()
4433 tree sc_spec, decl_specs, decl;
4434 tree name_expr, super_expr, root_expr;
4435 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4436 tree cast_type, initlist, protocol_decl;
4438 my_super_id = CLASS_SUPER_NAME (implementation_template);
4439 if (my_super_id)
4441 add_class_reference (my_super_id);
4443 /* Compute "my_root_id" - this is required for code generation.
4444 the "isa" for all meta class structures points to the root of
4445 the inheritance hierarchy (e.g. "__Object")... */
4446 my_root_id = my_super_id;
4449 tree my_root_int = lookup_interface (my_root_id);
4451 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4452 my_root_id = CLASS_SUPER_NAME (my_root_int);
4453 else
4454 break;
4456 while (1);
4458 else
4459 /* No super class. */
4460 my_root_id = CLASS_NAME (implementation_template);
4462 cast_type
4463 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4464 objc_class_template),
4465 build1 (INDIRECT_REF,
4466 NULL_TREE, NULL_TREE)));
4468 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4469 class_names);
4471 /* Install class `isa' and `super' pointers at runtime. */
4472 if (my_super_id)
4474 super_expr = add_objc_string (my_super_id, class_names);
4475 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4477 else
4478 super_expr = build_int_2 (0, 0);
4480 root_expr = add_objc_string (my_root_id, class_names);
4481 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4483 if (CLASS_PROTOCOL_LIST (implementation_template))
4485 generate_protocol_references
4486 (CLASS_PROTOCOL_LIST (implementation_template));
4487 protocol_decl = generate_protocol_list (implementation_template);
4489 else
4490 protocol_decl = 0;
4492 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4494 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4495 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4497 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4498 NULL_TREE, NULL_TREE);
4500 initlist
4501 = build_shared_structure_initializer
4502 (TREE_TYPE (decl),
4503 root_expr, super_expr, name_expr,
4504 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4505 / BITS_PER_UNIT),
4507 2 /*CLS_META*/,
4508 UOBJC_CLASS_METHODS_decl,
4509 UOBJC_CLASS_VARIABLES_decl,
4510 protocol_decl);
4512 finish_decl (decl, initlist, NULL_TREE);
4514 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4516 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4517 NULL_TREE, NULL_TREE);
4519 initlist
4520 = build_shared_structure_initializer
4521 (TREE_TYPE (decl),
4522 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4523 super_expr, name_expr,
4524 build_int_2
4525 ((TREE_INT_CST_LOW
4526 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4527 / BITS_PER_UNIT),
4529 1 /*CLS_FACTORY*/,
4530 UOBJC_INSTANCE_METHODS_decl,
4531 UOBJC_INSTANCE_VARIABLES_decl,
4532 protocol_decl);
4534 finish_decl (decl, initlist, NULL_TREE);
4537 static tree
4538 synth_id_with_class_suffix (preamble, ctxt)
4539 char *preamble;
4540 tree ctxt;
4542 char *string;
4543 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4544 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4546 char *class_name
4547 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4548 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4549 sprintf (string, "%s_%s", preamble,
4550 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4552 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4553 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4555 /* We have a category. */
4556 char *class_name
4557 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4558 char *class_super_name
4559 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4560 string = (char *) alloca (strlen (preamble)
4561 + strlen (class_name)
4562 + strlen (class_super_name)
4563 + 3);
4564 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4566 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4568 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4569 string
4570 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4571 sprintf (string, "%s_%s", preamble, protocol_name);
4573 return get_identifier (string);
4576 static int
4577 is_objc_type_qualifier (node)
4578 tree node;
4580 return (TREE_CODE (node) == IDENTIFIER_NODE
4581 && (node == ridpointers [(int) RID_CONST]
4582 || node == ridpointers [(int) RID_VOLATILE]
4583 || node == ridpointers [(int) RID_IN]
4584 || node == ridpointers [(int) RID_OUT]
4585 || node == ridpointers [(int) RID_INOUT]
4586 || node == ridpointers [(int) RID_BYCOPY]
4587 || node == ridpointers [(int) RID_ONEWAY]));
4590 /* If type is empty or only type qualifiers are present, add default
4591 type of id (otherwise grokdeclarator will default to int). */
4593 static tree
4594 adjust_type_for_id_default (type)
4595 tree type;
4597 tree declspecs, chain;
4599 if (!type)
4600 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4601 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4603 declspecs = TREE_PURPOSE (type);
4605 /* Determine if a typespec is present. */
4606 for (chain = declspecs;
4607 chain;
4608 chain = TREE_CHAIN (chain))
4610 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4611 return type;
4614 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4615 declspecs),
4616 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4619 /* Usage:
4620 keyworddecl:
4621 selector ':' '(' typename ')' identifier
4623 Purpose:
4624 Transform an Objective-C keyword argument into
4625 the C equivalent parameter declarator.
4627 In: key_name, an "identifier_node" (optional).
4628 arg_type, a "tree_list" (optional).
4629 arg_name, an "identifier_node".
4631 Note: It would be really nice to strongly type the preceding
4632 arguments in the function prototype; however, then I
4633 could not use the "accessor" macros defined in "tree.h".
4635 Out: an instance of "keyword_decl". */
4637 tree
4638 build_keyword_decl (key_name, arg_type, arg_name)
4639 tree key_name;
4640 tree arg_type;
4641 tree arg_name;
4643 tree keyword_decl;
4645 /* If no type is specified, default to "id". */
4646 arg_type = adjust_type_for_id_default (arg_type);
4648 keyword_decl = make_node (KEYWORD_DECL);
4650 TREE_TYPE (keyword_decl) = arg_type;
4651 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4652 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4654 return keyword_decl;
4657 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4659 static tree
4660 build_keyword_selector (selector)
4661 tree selector;
4663 int len = 0;
4664 tree key_chain, key_name;
4665 char *buf;
4667 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4669 if (TREE_CODE (selector) == KEYWORD_DECL)
4670 key_name = KEYWORD_KEY_NAME (key_chain);
4671 else if (TREE_CODE (selector) == TREE_LIST)
4672 key_name = TREE_PURPOSE (key_chain);
4674 if (key_name)
4675 len += IDENTIFIER_LENGTH (key_name) + 1;
4676 else
4677 /* Just a ':' arg. */
4678 len++;
4681 buf = (char *)alloca (len + 1);
4682 bzero (buf, len + 1);
4684 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4686 if (TREE_CODE (selector) == KEYWORD_DECL)
4687 key_name = KEYWORD_KEY_NAME (key_chain);
4688 else if (TREE_CODE (selector) == TREE_LIST)
4689 key_name = TREE_PURPOSE (key_chain);
4691 if (key_name)
4692 strcat (buf, IDENTIFIER_POINTER (key_name));
4693 strcat (buf, ":");
4696 return get_identifier (buf);
4699 /* Used for declarations and definitions. */
4701 tree
4702 build_method_decl (code, ret_type, selector, add_args)
4703 enum tree_code code;
4704 tree ret_type;
4705 tree selector;
4706 tree add_args;
4708 tree method_decl;
4710 /* If no type is specified, default to "id". */
4711 ret_type = adjust_type_for_id_default (ret_type);
4713 method_decl = make_node (code);
4714 TREE_TYPE (method_decl) = ret_type;
4716 /* If we have a keyword selector, create an identifier_node that
4717 represents the full selector name (`:' included)... */
4718 if (TREE_CODE (selector) == KEYWORD_DECL)
4720 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4721 METHOD_SEL_ARGS (method_decl) = selector;
4722 METHOD_ADD_ARGS (method_decl) = add_args;
4724 else
4726 METHOD_SEL_NAME (method_decl) = selector;
4727 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4728 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4731 return method_decl;
4734 #define METHOD_DEF 0
4735 #define METHOD_REF 1
4737 /* Used by `build_message_expr' and `comp_method_types'. Return an
4738 argument list for method METH. CONTEXT is either METHOD_DEF or
4739 METHOD_REF, saying whether we are trying to define a method or call
4740 one. SUPERFLAG says this is for a send to super; this makes a
4741 difference for the NeXT calling sequence in which the lookup and
4742 the method call are done together. */
4744 static tree
4745 get_arg_type_list (meth, context, superflag)
4746 tree meth;
4747 int context;
4748 int superflag;
4750 tree arglist, akey;
4752 /* Receiver type. */
4753 if (flag_next_runtime && superflag)
4754 arglist = build_tree_list (NULL_TREE, super_type);
4755 else if (context == METHOD_DEF)
4756 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4757 else
4758 arglist = build_tree_list (NULL_TREE, id_type);
4760 /* Selector type - will eventually change to `int'. */
4761 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4763 /* Build a list of argument types. */
4764 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4766 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4767 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4770 if (METHOD_ADD_ARGS (meth) == (tree)1)
4771 /* We have a `, ...' immediately following the selector,
4772 finalize the arglist...simulate get_parm_info (0). */
4774 else if (METHOD_ADD_ARGS (meth))
4776 /* we have a variable length selector */
4777 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4778 chainon (arglist, add_arg_list);
4780 else
4781 /* finalize the arglist...simulate get_parm_info (1) */
4782 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4784 return arglist;
4787 static tree
4788 check_duplicates (hsh)
4789 hash hsh;
4791 tree meth = NULL_TREE;
4793 if (hsh)
4795 meth = hsh->key;
4797 if (hsh->list)
4799 /* We have two methods with the same name and different types. */
4800 attr loop;
4801 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4803 warning ("multiple declarations for method `%s'",
4804 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4806 warn_with_method ("using", type, meth);
4807 for (loop = hsh->list; loop; loop = loop->next)
4808 warn_with_method ("also found", type, loop->value);
4811 return meth;
4814 /* If RECEIVER is a class reference, return the identifier node for the
4815 referenced class. RECEIVER is created by get_class_reference, so we
4816 check the exact form created depending on which runtimes are used. */
4818 static tree
4819 receiver_is_class_object (receiver)
4820 tree receiver;
4822 tree chain, exp, arg;
4823 if (flag_next_runtime)
4825 /* The receiver is a variable created by build_class_reference_decl. */
4826 if (TREE_CODE (receiver) == VAR_DECL
4827 && TREE_TYPE (receiver) == objc_class_type)
4828 /* Look up the identifier. */
4829 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4830 if (TREE_PURPOSE (chain) == receiver)
4831 return TREE_VALUE (chain);
4833 else
4835 /* The receiver is a function call that returns an id. Check if
4836 it is a call to objc_getClass, if so, pick up the class name. */
4837 if ((exp = TREE_OPERAND (receiver, 0))
4838 && TREE_CODE (exp) == ADDR_EXPR
4839 && (exp = TREE_OPERAND (exp, 0))
4840 && TREE_CODE (exp) == FUNCTION_DECL
4841 && exp == objc_get_class_decl
4842 /* we have a call to objc_getClass! */
4843 && (arg = TREE_OPERAND (receiver, 1))
4844 && TREE_CODE (arg) == TREE_LIST
4845 && (arg = TREE_VALUE (arg)))
4847 STRIP_NOPS (arg);
4848 if (TREE_CODE (arg) == ADDR_EXPR
4849 && (arg = TREE_OPERAND (arg, 0))
4850 && TREE_CODE (arg) == STRING_CST)
4851 /* Finally, we have the class name. */
4852 return get_identifier (TREE_STRING_POINTER (arg));
4855 return 0;
4858 /* If we are currently building a message expr, this holds
4859 the identifier of the selector of the message. This is
4860 used when printing warnings about argument mismatches. */
4862 static tree building_objc_message_expr = 0;
4864 tree
4865 maybe_building_objc_message_expr ()
4867 return building_objc_message_expr;
4870 /* Construct an expression for sending a message.
4871 MESS has the object to send to in TREE_PURPOSE
4872 and the argument list (including selector) in TREE_VALUE.
4874 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4875 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4877 tree
4878 build_message_expr (mess)
4879 tree mess;
4881 tree receiver = TREE_PURPOSE (mess);
4882 tree selector, self_object;
4883 tree rtype, sel_name;
4884 tree args = TREE_VALUE (mess);
4885 tree method_params = NULL_TREE;
4886 tree method_prototype = NULL_TREE;
4887 tree retval;
4888 int statically_typed = 0, statically_allocated = 0;
4889 tree class_ident = 0;
4891 /* 1 if this is sending to the superclass. */
4892 int super;
4894 if (!doing_objc_thang)
4895 objc_fatal ();
4897 if (TREE_CODE (receiver) == ERROR_MARK)
4898 return error_mark_node;
4900 /* Determine receiver type. */
4901 rtype = TREE_TYPE (receiver);
4902 super = IS_SUPER (rtype);
4904 if (! super)
4906 if (TREE_STATIC_TEMPLATE (rtype))
4907 statically_allocated = 1;
4908 else if (TREE_CODE (rtype) == POINTER_TYPE
4909 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4910 statically_typed = 1;
4911 else if ((flag_next_runtime
4912 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4913 && (class_ident = receiver_is_class_object (receiver)))
4915 else if (! IS_ID (rtype)
4916 /* Allow any type that matches objc_class_type. */
4917 && ! comptypes (rtype, objc_class_type))
4919 bzero (errbuf, BUFSIZE);
4920 warning ("invalid receiver type `%s'",
4921 gen_declaration (rtype, errbuf));
4924 if (statically_allocated)
4925 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4927 /* Don't evaluate the receiver twice. */
4928 receiver = save_expr (receiver);
4929 self_object = receiver;
4931 else
4932 /* If sending to `super', use current self as the object. */
4933 self_object = self_decl;
4935 /* Obtain the full selector name. */
4937 if (TREE_CODE (args) == IDENTIFIER_NODE)
4938 /* A unary selector. */
4939 sel_name = args;
4940 else if (TREE_CODE (args) == TREE_LIST)
4941 sel_name = build_keyword_selector (args);
4943 /* Build the parameter list to give to the method. */
4945 method_params = NULL_TREE;
4946 if (TREE_CODE (args) == TREE_LIST)
4948 tree chain = args, prev = NULL_TREE;
4950 /* We have a keyword selector--check for comma expressions. */
4951 while (chain)
4953 tree element = TREE_VALUE (chain);
4955 /* We have a comma expression, must collapse... */
4956 if (TREE_CODE (element) == TREE_LIST)
4958 if (prev)
4959 TREE_CHAIN (prev) = element;
4960 else
4961 args = element;
4963 prev = chain;
4964 chain = TREE_CHAIN (chain);
4966 method_params = args;
4969 /* Determine operation return type. */
4971 if (IS_SUPER (rtype))
4973 tree iface;
4975 if (CLASS_SUPER_NAME (implementation_template))
4977 iface
4978 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4980 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4981 method_prototype = lookup_instance_method_static (iface, sel_name);
4982 else
4983 method_prototype = lookup_class_method_static (iface, sel_name);
4985 if (iface && !method_prototype)
4986 warning ("`%s' does not respond to `%s'",
4987 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4988 IDENTIFIER_POINTER (sel_name));
4990 else
4992 error ("no super class declared in interface for `%s'",
4993 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4994 return error_mark_node;
4998 else if (statically_allocated)
5000 tree ctype = TREE_TYPE (rtype);
5001 tree iface = lookup_interface (TYPE_NAME (rtype));
5003 if (iface)
5004 method_prototype = lookup_instance_method_static (iface, sel_name);
5006 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5007 method_prototype
5008 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5009 sel_name, 0);
5011 if (!method_prototype)
5012 warning ("`%s' does not respond to `%s'",
5013 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
5014 IDENTIFIER_POINTER (sel_name));
5016 else if (statically_typed)
5018 tree ctype = TREE_TYPE (rtype);
5020 /* `self' is now statically_typed. All methods should be visible
5021 within the context of the implementation. */
5022 if (implementation_context
5023 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
5025 method_prototype
5026 = lookup_instance_method_static (implementation_template,
5027 sel_name);
5029 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5030 method_prototype
5031 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5032 sel_name, 0);
5034 if (! method_prototype
5035 && implementation_template != implementation_context)
5036 /* The method is not published in the interface. Check
5037 locally. */
5038 method_prototype
5039 = lookup_method (CLASS_NST_METHODS (implementation_context),
5040 sel_name);
5042 else
5044 tree iface;
5046 if ((iface = lookup_interface (TYPE_NAME (ctype))))
5047 method_prototype = lookup_instance_method_static (iface, sel_name);
5049 if (! method_prototype)
5051 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5052 if (protocol_list)
5053 method_prototype
5054 = lookup_method_in_protocol_list (protocol_list,
5055 sel_name, 0);
5059 if (!method_prototype)
5060 warning ("`%s' does not respond to `%s'",
5061 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5062 IDENTIFIER_POINTER (sel_name));
5064 else if (class_ident)
5066 if (implementation_context
5067 && CLASS_NAME (implementation_context) == class_ident)
5069 method_prototype
5070 = lookup_class_method_static (implementation_template, sel_name);
5072 if (!method_prototype
5073 && implementation_template != implementation_context)
5074 /* The method is not published in the interface. Check
5075 locally. */
5076 method_prototype
5077 = lookup_method (CLASS_CLS_METHODS (implementation_context),
5078 sel_name);
5080 else
5082 tree iface;
5084 if ((iface = lookup_interface (class_ident)))
5085 method_prototype = lookup_class_method_static (iface, sel_name);
5088 if (!method_prototype)
5090 warning ("cannot find class (factory) method.");
5091 warning ("return type for `%s' defaults to id",
5092 IDENTIFIER_POINTER (sel_name));
5095 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5097 /* An anonymous object that has been qualified with a protocol. */
5099 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5101 method_prototype = lookup_method_in_protocol_list (protocol_list,
5102 sel_name, 0);
5104 if (!method_prototype)
5106 hash hsh;
5108 warning ("method `%s' not implemented by protocol.",
5109 IDENTIFIER_POINTER (sel_name));
5111 /* Try and find the method signature in the global pools. */
5113 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5114 hsh = hash_lookup (cls_method_hash_list, sel_name);
5116 if (!(method_prototype = check_duplicates (hsh)))
5117 warning ("return type defaults to id");
5120 else
5122 hash hsh;
5124 /* We think we have an instance...loophole: extern id Object; */
5125 hsh = hash_lookup (nst_method_hash_list, sel_name);
5126 if (!hsh)
5127 /* For various loopholes, like sending messages to self in a
5128 factory context. */
5129 hsh = hash_lookup (cls_method_hash_list, sel_name);
5131 method_prototype = check_duplicates (hsh);
5132 if (!method_prototype)
5134 warning ("cannot find method.");
5135 warning ("return type for `%s' defaults to id",
5136 IDENTIFIER_POINTER (sel_name));
5140 /* Save the selector name for printing error messages. */
5141 building_objc_message_expr = sel_name;
5143 /* Build the parameters list for looking up the method.
5144 These are the object itself and the selector. */
5146 if (flag_typed_selectors)
5147 selector = build_typed_selector_reference (sel_name, method_prototype);
5148 else
5149 selector = build_selector_reference (sel_name);
5151 retval = build_objc_method_call (super, method_prototype,
5152 receiver, self_object,
5153 selector, method_params);
5155 building_objc_message_expr = 0;
5157 return retval;
5160 /* Build a tree expression to send OBJECT the operation SELECTOR,
5161 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5162 assuming the method has prototype METHOD_PROTOTYPE.
5163 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5164 Use METHOD_PARAMS as list of args to pass to the method.
5165 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5167 static tree
5168 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5169 selector, method_params)
5170 int super_flag;
5171 tree method_prototype, lookup_object, object, selector, method_params;
5173 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5174 tree rcv_p = (super_flag
5175 ? build_pointer_type (xref_tag (RECORD_TYPE,
5176 get_identifier (TAG_SUPER)))
5177 : id_type);
5179 if (flag_next_runtime)
5181 if (! method_prototype)
5183 method_params = tree_cons (NULL_TREE, lookup_object,
5184 tree_cons (NULL_TREE, selector,
5185 method_params));
5186 assemble_external (sender);
5187 return build_function_call (sender, method_params);
5189 else
5191 /* This is a real kludge, but it is used only for the Next.
5192 Clobber the data type of SENDER temporarily to accept
5193 all the arguments for this operation, and to return
5194 whatever this operation returns. */
5195 tree arglist = NULL_TREE;
5196 tree retval;
5198 /* Save the proper contents of SENDER's data type. */
5199 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5200 tree savret = TREE_TYPE (TREE_TYPE (sender));
5202 /* Install this method's argument types. */
5203 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5204 super_flag);
5205 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5207 /* Install this method's return type. */
5208 TREE_TYPE (TREE_TYPE (sender))
5209 = groktypename (TREE_TYPE (method_prototype));
5211 /* Call SENDER with all the parameters. This will do type
5212 checking using the arg types for this method. */
5213 method_params = tree_cons (NULL_TREE, lookup_object,
5214 tree_cons (NULL_TREE, selector,
5215 method_params));
5216 assemble_external (sender);
5217 retval = build_function_call (sender, method_params);
5219 /* Restore SENDER's return/argument types. */
5220 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5221 TREE_TYPE (TREE_TYPE (sender)) = savret;
5222 return retval;
5225 else
5227 /* This is the portable way.
5228 First call the lookup function to get a pointer to the method,
5229 then cast the pointer, then call it with the method arguments. */
5230 tree method;
5232 /* Avoid trouble since we may evaluate each of these twice. */
5233 object = save_expr (object);
5234 selector = save_expr (selector);
5236 lookup_object = build_c_cast (rcv_p, lookup_object);
5238 assemble_external (sender);
5239 method
5240 = build_function_call (sender,
5241 tree_cons (NULL_TREE, lookup_object,
5242 tree_cons (NULL_TREE, selector,
5243 NULL_TREE)));
5245 /* If we have a method prototype, construct the data type this
5246 method needs, and cast what we got from SENDER into a pointer
5247 to that type. */
5248 if (method_prototype)
5250 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5251 super_flag);
5252 tree valtype = groktypename (TREE_TYPE (method_prototype));
5253 tree fake_function_type = build_function_type (valtype, arglist);
5254 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5256 else
5257 TREE_TYPE (method)
5258 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5260 /* Pass the object to the method. */
5261 assemble_external (method);
5262 return build_function_call (method,
5263 tree_cons (NULL_TREE, object,
5264 tree_cons (NULL_TREE, selector,
5265 method_params)));
5269 static void
5270 build_protocol_reference (p)
5271 tree p;
5273 tree decl, ident, ptype;
5275 push_obstacks_nochange ();
5276 end_temporary_allocation ();
5278 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5280 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5281 ptype
5282 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5283 objc_protocol_template),
5284 NULL_TREE));
5286 if (IDENTIFIER_GLOBAL_VALUE (ident))
5287 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5288 else
5290 decl = build_decl (VAR_DECL, ident, ptype);
5291 DECL_EXTERNAL (decl) = 1;
5292 TREE_PUBLIC (decl) = 1;
5293 TREE_USED (decl) = 1;
5294 DECL_ARTIFICIAL (decl) = 1;
5296 make_decl_rtl (decl, 0, 1);
5297 pushdecl_top_level (decl);
5300 PROTOCOL_FORWARD_DECL (p) = decl;
5301 pop_obstacks ();
5304 tree
5305 build_protocol_expr (protoname)
5306 tree protoname;
5308 tree expr;
5309 tree p;
5311 if (!doing_objc_thang)
5312 objc_fatal ();
5314 p = lookup_protocol (protoname);
5316 if (!p)
5318 error ("Cannot find protocol declaration for `%s'",
5319 IDENTIFIER_POINTER (protoname));
5320 return error_mark_node;
5323 if (!PROTOCOL_FORWARD_DECL (p))
5324 build_protocol_reference (p);
5326 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5328 TREE_TYPE (expr) = protocol_type;
5330 return expr;
5333 tree
5334 build_selector_expr (selnamelist)
5335 tree selnamelist;
5337 tree selname;
5339 if (!doing_objc_thang)
5340 objc_fatal ();
5342 /* Obtain the full selector name. */
5343 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5344 /* A unary selector. */
5345 selname = selnamelist;
5346 else if (TREE_CODE (selnamelist) == TREE_LIST)
5347 selname = build_keyword_selector (selnamelist);
5349 if (flag_typed_selectors)
5350 return build_typed_selector_reference (selname, 0);
5351 else
5352 return build_selector_reference (selname);
5355 tree
5356 build_encode_expr (type)
5357 tree type;
5359 tree result;
5360 char *string;
5362 if (!doing_objc_thang)
5363 objc_fatal ();
5365 encode_type (type, obstack_object_size (&util_obstack),
5366 OBJC_ENCODE_INLINE_DEFS);
5367 obstack_1grow (&util_obstack, 0); /* null terminate string */
5368 string = obstack_finish (&util_obstack);
5370 /* Synthesize a string that represents the encoded struct/union. */
5371 result = my_build_string (strlen (string) + 1, string);
5372 obstack_free (&util_obstack, util_firstobj);
5373 return result;
5376 tree
5377 build_ivar_reference (id)
5378 tree id;
5380 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5382 /* Historically, a class method that produced objects (factory
5383 method) would assign `self' to the instance that it
5384 allocated. This would effectively turn the class method into
5385 an instance method. Following this assignment, the instance
5386 variables could be accessed. That practice, while safe,
5387 violates the simple rule that a class method should not refer
5388 to an instance variable. It's better to catch the cases
5389 where this is done unknowingly than to support the above
5390 paradigm. */
5391 warning ("instance variable `%s' accessed in class method",
5392 IDENTIFIER_POINTER (id));
5393 TREE_TYPE (self_decl) = instance_type; /* cast */
5396 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5399 #define HASH_ALLOC_LIST_SIZE 170
5400 #define ATTR_ALLOC_LIST_SIZE 170
5401 #define SIZEHASHTABLE 257
5403 /* make positive */
5404 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5406 static void
5407 hash_init ()
5409 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5410 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5412 if (!nst_method_hash_list || !cls_method_hash_list)
5413 perror ("unable to allocate space in objc-tree.c");
5414 else
5416 int i;
5418 for (i = 0; i < SIZEHASHTABLE; i++)
5420 nst_method_hash_list[i] = 0;
5421 cls_method_hash_list[i] = 0;
5426 static void
5427 hash_enter (hashlist, method)
5428 hash *hashlist;
5429 tree method;
5431 static hash hash_alloc_list = 0;
5432 static int hash_alloc_index = 0;
5433 hash obj;
5434 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5436 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5438 hash_alloc_index = 0;
5439 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5440 * HASH_ALLOC_LIST_SIZE);
5441 if (! hash_alloc_list)
5442 perror ("unable to allocate in objc-tree.c");
5444 obj = &hash_alloc_list[hash_alloc_index++];
5445 obj->list = 0;
5446 obj->next = hashlist[slot];
5447 obj->key = method;
5449 hashlist[slot] = obj; /* append to front */
5452 static hash
5453 hash_lookup (hashlist, sel_name)
5454 hash *hashlist;
5455 tree sel_name;
5457 hash target;
5459 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5461 while (target)
5463 if (sel_name == METHOD_SEL_NAME (target->key))
5464 return target;
5466 target = target->next;
5468 return 0;
5471 static void
5472 hash_add_attr (entry, value)
5473 hash entry;
5474 tree value;
5476 static attr attr_alloc_list = 0;
5477 static int attr_alloc_index = 0;
5478 attr obj;
5480 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5482 attr_alloc_index = 0;
5483 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5484 * ATTR_ALLOC_LIST_SIZE);
5485 if (! attr_alloc_list)
5486 perror ("unable to allocate in objc-tree.c");
5488 obj = &attr_alloc_list[attr_alloc_index++];
5489 obj->next = entry->list;
5490 obj->value = value;
5492 entry->list = obj; /* append to front */
5495 static tree
5496 lookup_method (mchain, method)
5497 tree mchain;
5498 tree method;
5500 tree key;
5502 if (TREE_CODE (method) == IDENTIFIER_NODE)
5503 key = method;
5504 else
5505 key = METHOD_SEL_NAME (method);
5507 while (mchain)
5509 if (METHOD_SEL_NAME (mchain) == key)
5510 return mchain;
5511 mchain = TREE_CHAIN (mchain);
5513 return NULL_TREE;
5516 static tree
5517 lookup_instance_method_static (interface, ident)
5518 tree interface;
5519 tree ident;
5521 tree inter = interface;
5522 tree chain = CLASS_NST_METHODS (inter);
5523 tree meth = NULL_TREE;
5527 if ((meth = lookup_method (chain, ident)))
5528 return meth;
5530 if (CLASS_CATEGORY_LIST (inter))
5532 tree category = CLASS_CATEGORY_LIST (inter);
5533 chain = CLASS_NST_METHODS (category);
5537 if ((meth = lookup_method (chain, ident)))
5538 return meth;
5540 /* Check for instance methods in protocols in categories. */
5541 if (CLASS_PROTOCOL_LIST (category))
5543 if ((meth = (lookup_method_in_protocol_list
5544 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5545 return meth;
5548 if ((category = CLASS_CATEGORY_LIST (category)))
5549 chain = CLASS_NST_METHODS (category);
5551 while (category);
5554 if (CLASS_PROTOCOL_LIST (inter))
5556 if ((meth = (lookup_method_in_protocol_list
5557 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5558 return meth;
5561 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5562 chain = CLASS_NST_METHODS (inter);
5564 while (inter);
5566 return meth;
5569 static tree
5570 lookup_class_method_static (interface, ident)
5571 tree interface;
5572 tree ident;
5574 tree inter = interface;
5575 tree chain = CLASS_CLS_METHODS (inter);
5576 tree meth = NULL_TREE;
5577 tree root_inter = NULL_TREE;
5581 if ((meth = lookup_method (chain, ident)))
5582 return meth;
5584 if (CLASS_CATEGORY_LIST (inter))
5586 tree category = CLASS_CATEGORY_LIST (inter);
5587 chain = CLASS_CLS_METHODS (category);
5591 if ((meth = lookup_method (chain, ident)))
5592 return meth;
5594 /* Check for class methods in protocols in categories. */
5595 if (CLASS_PROTOCOL_LIST (category))
5597 if ((meth = (lookup_method_in_protocol_list
5598 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5599 return meth;
5602 if ((category = CLASS_CATEGORY_LIST (category)))
5603 chain = CLASS_CLS_METHODS (category);
5605 while (category);
5608 /* Check for class methods in protocols. */
5609 if (CLASS_PROTOCOL_LIST (inter))
5611 if ((meth = (lookup_method_in_protocol_list
5612 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5613 return meth;
5616 root_inter = inter;
5617 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5618 chain = CLASS_CLS_METHODS (inter);
5620 while (inter);
5622 /* Simulate wrap around. */
5623 return lookup_instance_method_static (root_inter, ident);
5626 tree
5627 add_class_method (class, method)
5628 tree class;
5629 tree method;
5631 tree mth;
5632 hash hsh;
5634 /* We will have allocated the method parameter declarations on the
5635 maybepermanent_obstack. Need to make sure they stick around! */
5636 preserve_data ();
5638 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5640 /* put method on list in reverse order */
5641 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5642 CLASS_CLS_METHODS (class) = method;
5644 else
5646 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5647 error ("duplicate definition of class method `%s'.",
5648 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5649 else
5651 /* Check types; if different, complain. */
5652 if (!comp_proto_with_proto (method, mth))
5653 error ("duplicate declaration of class method `%s'.",
5654 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5658 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5660 /* Install on a global chain. */
5661 hash_enter (cls_method_hash_list, method);
5663 else
5665 /* Check types; if different, add to a list. */
5666 if (!comp_proto_with_proto (method, hsh->key))
5667 hash_add_attr (hsh, method);
5669 return method;
5672 tree
5673 add_instance_method (class, method)
5674 tree class;
5675 tree method;
5677 tree mth;
5678 hash hsh;
5680 /* We will have allocated the method parameter declarations on the
5681 maybepermanent_obstack. Need to make sure they stick around! */
5682 preserve_data ();
5684 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5686 /* Put method on list in reverse order. */
5687 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5688 CLASS_NST_METHODS (class) = method;
5690 else
5692 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5693 error ("duplicate definition of instance method `%s'.",
5694 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5695 else
5697 /* Check types; if different, complain. */
5698 if (!comp_proto_with_proto (method, mth))
5699 error ("duplicate declaration of instance method `%s'.",
5700 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5704 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5706 /* Install on a global chain. */
5707 hash_enter (nst_method_hash_list, method);
5709 else
5711 /* Check types; if different, add to a list. */
5712 if (!comp_proto_with_proto (method, hsh->key))
5713 hash_add_attr (hsh, method);
5715 return method;
5718 static tree
5719 add_class (class)
5720 tree class;
5722 /* Put interfaces on list in reverse order. */
5723 TREE_CHAIN (class) = interface_chain;
5724 interface_chain = class;
5725 return interface_chain;
5728 static void
5729 add_category (class, category)
5730 tree class;
5731 tree category;
5733 /* Put categories on list in reverse order. */
5734 tree cat = CLASS_CATEGORY_LIST (class);
5736 while (cat)
5738 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5739 warning ("duplicate interface declaration for category `%s(%s)'",
5740 IDENTIFIER_POINTER (CLASS_NAME (class)),
5741 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5742 cat = CLASS_CATEGORY_LIST (cat);
5745 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5746 CLASS_CATEGORY_LIST (class) = category;
5749 /* Called after parsing each instance variable declaration. Necessary to
5750 preserve typedefs and implement public/private...
5752 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5754 tree
5755 add_instance_variable (class, public, declarator, declspecs, width)
5756 tree class;
5757 int public;
5758 tree declarator;
5759 tree declspecs;
5760 tree width;
5762 tree field_decl, raw_decl;
5764 raw_decl = build_tree_list (declspecs, declarator);
5766 if (CLASS_RAW_IVARS (class))
5767 chainon (CLASS_RAW_IVARS (class), raw_decl);
5768 else
5769 CLASS_RAW_IVARS (class) = raw_decl;
5771 field_decl = grokfield (input_filename, lineno,
5772 declarator, declspecs, width);
5774 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5775 switch (public)
5777 case 0:
5778 TREE_PUBLIC (field_decl) = 0;
5779 TREE_PRIVATE (field_decl) = 0;
5780 TREE_PROTECTED (field_decl) = 1;
5781 break;
5783 case 1:
5784 TREE_PUBLIC (field_decl) = 1;
5785 TREE_PRIVATE (field_decl) = 0;
5786 TREE_PROTECTED (field_decl) = 0;
5787 break;
5789 case 2:
5790 TREE_PUBLIC (field_decl) = 0;
5791 TREE_PRIVATE (field_decl) = 1;
5792 TREE_PROTECTED (field_decl) = 0;
5793 break;
5797 if (CLASS_IVARS (class))
5798 chainon (CLASS_IVARS (class), field_decl);
5799 else
5800 CLASS_IVARS (class) = field_decl;
5802 return class;
5805 tree
5806 is_ivar (decl_chain, ident)
5807 tree decl_chain;
5808 tree ident;
5810 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5811 if (DECL_NAME (decl_chain) == ident)
5812 return decl_chain;
5813 return NULL_TREE;
5816 /* True if the ivar is private and we are not in its implementation. */
5819 is_private (decl)
5820 tree decl;
5822 if (TREE_PRIVATE (decl)
5823 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5825 error ("instance variable `%s' is declared private",
5826 IDENTIFIER_POINTER (DECL_NAME (decl)));
5827 return 1;
5829 else
5830 return 0;
5833 /* We have an instance variable reference;, check to see if it is public. */
5836 is_public (expr, identifier)
5837 tree expr;
5838 tree identifier;
5840 tree basetype = TREE_TYPE (expr);
5841 enum tree_code code = TREE_CODE (basetype);
5842 tree decl;
5844 if (code == RECORD_TYPE)
5846 if (TREE_STATIC_TEMPLATE (basetype))
5848 if (!lookup_interface (TYPE_NAME (basetype)))
5850 error ("Cannot find interface declaration for `%s'",
5851 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5852 return 0;
5855 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5857 if (TREE_PUBLIC (decl))
5858 return 1;
5860 /* Important difference between the Stepstone translator:
5861 all instance variables should be public within the context
5862 of the implementation. */
5863 if (implementation_context
5864 && (((TREE_CODE (implementation_context)
5865 == CLASS_IMPLEMENTATION_TYPE)
5866 || (TREE_CODE (implementation_context)
5867 == CATEGORY_IMPLEMENTATION_TYPE))
5868 && (CLASS_NAME (implementation_context)
5869 == TYPE_NAME (basetype))))
5870 return ! is_private (decl);
5872 error ("instance variable `%s' is declared %s",
5873 IDENTIFIER_POINTER (identifier),
5874 TREE_PRIVATE (decl) ? "private" : "protected");
5875 return 0;
5879 else if (implementation_context && (basetype == objc_object_reference))
5881 TREE_TYPE (expr) = uprivate_record;
5882 warning ("static access to object of type `id'");
5886 return 1;
5889 /* Implement @defs (<classname>) within struct bodies. */
5891 tree
5892 get_class_ivars (interface)
5893 tree interface;
5895 if (!doing_objc_thang)
5896 objc_fatal ();
5898 return build_ivar_chain (interface, 1);
5901 /* Make sure all entries in CHAIN are also in LIST. */
5903 static int
5904 check_methods (chain, list, mtype)
5905 tree chain;
5906 tree list;
5907 int mtype;
5909 int first = 1;
5911 while (chain)
5913 if (!lookup_method (list, chain))
5915 if (first)
5917 if (TREE_CODE (implementation_context)
5918 == CLASS_IMPLEMENTATION_TYPE)
5919 warning ("incomplete implementation of class `%s'",
5920 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5921 else if (TREE_CODE (implementation_context)
5922 == CATEGORY_IMPLEMENTATION_TYPE)
5923 warning ("incomplete implementation of category `%s'",
5924 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5925 first = 0;
5928 warning ("method definition for `%c%s' not found",
5929 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5932 chain = TREE_CHAIN (chain);
5935 return first;
5938 static int
5939 conforms_to_protocol (class, protocol)
5940 tree class;
5941 tree protocol;
5943 while (protocol)
5945 tree p = CLASS_PROTOCOL_LIST (class);
5947 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5948 p = TREE_CHAIN (p);
5950 if (!p)
5952 tree super = (CLASS_SUPER_NAME (class)
5953 ? lookup_interface (CLASS_SUPER_NAME (class))
5954 : NULL_TREE);
5955 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5956 if (!tmp)
5957 return 0;
5960 protocol = TREE_CHAIN (protocol);
5963 return 1;
5966 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5967 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5969 static int
5970 check_methods_accessible (chain, context, mtype)
5971 tree chain;
5972 tree context;
5973 int mtype;
5975 int first = 1;
5976 tree list;
5977 tree base_context = context;
5979 while (chain)
5981 context = base_context;
5982 while (context)
5984 if (mtype == '+')
5985 list = CLASS_CLS_METHODS (context);
5986 else
5987 list = CLASS_NST_METHODS (context);
5989 if (lookup_method (list, chain))
5990 break;
5992 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5993 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5994 context = (CLASS_SUPER_NAME (context)
5995 ? lookup_interface (CLASS_SUPER_NAME (context))
5996 : NULL_TREE);
5998 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5999 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6000 context = (CLASS_NAME (context)
6001 ? lookup_interface (CLASS_NAME (context))
6002 : NULL_TREE);
6003 else
6004 abort ();
6007 if (context == NULL_TREE)
6009 if (first)
6011 if (TREE_CODE (implementation_context)
6012 == CLASS_IMPLEMENTATION_TYPE)
6013 warning ("incomplete implementation of class `%s'",
6014 IDENTIFIER_POINTER
6015 (CLASS_NAME (implementation_context)));
6016 else if (TREE_CODE (implementation_context)
6017 == CATEGORY_IMPLEMENTATION_TYPE)
6018 warning ("incomplete implementation of category `%s'",
6019 IDENTIFIER_POINTER
6020 (CLASS_SUPER_NAME (implementation_context)));
6021 first = 0;
6023 warning ("method definition for `%c%s' not found",
6024 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6027 chain = TREE_CHAIN (chain); /* next method... */
6029 return first;
6032 static void
6033 check_protocols (proto_list, type, name)
6034 tree proto_list;
6035 char *type;
6036 char *name;
6038 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6040 tree p = TREE_VALUE (proto_list);
6042 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6044 int f1, f2;
6046 /* Ensure that all protocols have bodies. */
6047 if (flag_warn_protocol) {
6048 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6049 CLASS_CLS_METHODS (implementation_context),
6050 '+');
6051 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6052 CLASS_NST_METHODS (implementation_context),
6053 '-');
6054 } else {
6055 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6056 implementation_context,
6057 '+');
6058 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6059 implementation_context,
6060 '-');
6063 if (!f1 || !f2)
6064 warning ("%s `%s' does not fully implement the `%s' protocol",
6065 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6068 else
6070 ; /* An identifier if we could not find a protocol. */
6073 /* Check protocols recursively. */
6074 if (PROTOCOL_LIST (p))
6076 tree super_class
6077 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6078 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
6079 check_protocols (PROTOCOL_LIST (p), type, name);
6084 /* Make sure that the class CLASS_NAME is defined
6085 CODE says which kind of thing CLASS_NAME ought to be.
6086 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6087 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
6089 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
6090 whose matching pop is in continue_class. */
6092 tree
6093 start_class (code, class_name, super_name, protocol_list)
6094 enum tree_code code;
6095 tree class_name;
6096 tree super_name;
6097 tree protocol_list;
6099 tree class, decl;
6101 if (code == CLASS_INTERFACE_TYPE)
6103 push_obstacks_nochange ();
6104 end_temporary_allocation ();
6107 if (!doing_objc_thang)
6108 objc_fatal ();
6110 class = make_node (code);
6111 TYPE_BINFO (class) = make_tree_vec (5);
6113 CLASS_NAME (class) = class_name;
6114 CLASS_SUPER_NAME (class) = super_name;
6115 CLASS_CLS_METHODS (class) = NULL_TREE;
6117 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6119 error ("`%s' redeclared as different kind of symbol",
6120 IDENTIFIER_POINTER (class_name));
6121 error_with_decl (decl, "previous declaration of `%s'");
6124 if (code == CLASS_IMPLEMENTATION_TYPE)
6127 static tree implemented_classes = 0;
6128 tree chain = implemented_classes;
6129 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6130 if (TREE_VALUE (chain) == class_name)
6132 error ("reimplementation of class `%s'",
6133 IDENTIFIER_POINTER (class_name));
6134 return error_mark_node;
6136 implemented_classes = perm_tree_cons (NULL_TREE, class_name,
6137 implemented_classes);
6140 /* Pre-build the following entities - for speed/convenience. */
6141 if (!self_id)
6142 self_id = get_identifier ("self");
6143 if (!ucmd_id)
6144 ucmd_id = get_identifier ("_cmd");
6145 if (!unused_list)
6146 unused_list
6147 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6148 if (!objc_super_template)
6149 objc_super_template = build_super_template ();
6151 /* Reset for multiple classes per file. */
6152 method_slot = 0;
6154 implementation_context = class;
6156 /* Lookup the interface for this implementation. */
6158 if (!(implementation_template = lookup_interface (class_name)))
6160 warning ("Cannot find interface declaration for `%s'",
6161 IDENTIFIER_POINTER (class_name));
6162 add_class (implementation_template = implementation_context);
6165 /* If a super class has been specified in the implementation,
6166 insure it conforms to the one specified in the interface. */
6168 if (super_name
6169 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6171 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6172 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6173 error ("conflicting super class name `%s'",
6174 IDENTIFIER_POINTER (super_name));
6175 error ("previous declaration of `%s'", name);
6178 else if (! super_name)
6180 CLASS_SUPER_NAME (implementation_context)
6181 = CLASS_SUPER_NAME (implementation_template);
6185 else if (code == CLASS_INTERFACE_TYPE)
6187 if (lookup_interface (class_name))
6188 warning ("duplicate interface declaration for class `%s'",
6189 IDENTIFIER_POINTER (class_name));
6190 else
6191 add_class (class);
6193 if (protocol_list)
6194 CLASS_PROTOCOL_LIST (class)
6195 = lookup_and_install_protocols (protocol_list);
6198 else if (code == CATEGORY_INTERFACE_TYPE)
6200 tree class_category_is_assoc_with;
6202 /* For a category, class_name is really the name of the class that
6203 the following set of methods will be associated with. We must
6204 find the interface so that can derive the objects template. */
6206 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6208 error ("Cannot find interface declaration for `%s'",
6209 IDENTIFIER_POINTER (class_name));
6210 exit (FATAL_EXIT_CODE);
6212 else
6213 add_category (class_category_is_assoc_with, class);
6215 if (protocol_list)
6216 CLASS_PROTOCOL_LIST (class)
6217 = lookup_and_install_protocols (protocol_list);
6220 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6222 /* Pre-build the following entities for speed/convenience. */
6223 if (!self_id)
6224 self_id = get_identifier ("self");
6225 if (!ucmd_id)
6226 ucmd_id = get_identifier ("_cmd");
6227 if (!unused_list)
6228 unused_list
6229 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6230 if (!objc_super_template)
6231 objc_super_template = build_super_template ();
6233 /* Reset for multiple classes per file. */
6234 method_slot = 0;
6236 implementation_context = class;
6238 /* For a category, class_name is really the name of the class that
6239 the following set of methods will be associated with. We must
6240 find the interface so that can derive the objects template. */
6242 if (!(implementation_template = lookup_interface (class_name)))
6244 error ("Cannot find interface declaration for `%s'",
6245 IDENTIFIER_POINTER (class_name));
6246 exit (FATAL_EXIT_CODE);
6249 return class;
6252 tree
6253 continue_class (class)
6254 tree class;
6256 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6257 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6259 struct imp_entry *imp_entry;
6260 tree ivar_context;
6262 /* Check consistency of the instance variables. */
6264 if (CLASS_IVARS (class))
6265 check_ivars (implementation_template, class);
6267 /* code generation */
6269 ivar_context = build_private_template (implementation_template);
6271 if (!objc_class_template)
6272 build_class_template ();
6274 if (!(imp_entry
6275 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6276 perror ("unable to allocate in objc-tree.c");
6278 imp_entry->next = imp_list;
6279 imp_entry->imp_context = class;
6280 imp_entry->imp_template = implementation_template;
6282 synth_forward_declarations ();
6283 imp_entry->class_decl = UOBJC_CLASS_decl;
6284 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6286 /* Append to front and increment count. */
6287 imp_list = imp_entry;
6288 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6289 imp_count++;
6290 else
6291 cat_count++;
6293 return ivar_context;
6296 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6298 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6300 if (!TYPE_FIELDS (record))
6302 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6303 CLASS_STATIC_TEMPLATE (class) = record;
6305 /* Mark this record as a class template for static typing. */
6306 TREE_STATIC_TEMPLATE (record) = 1;
6309 return NULL_TREE;
6312 else
6313 return error_mark_node;
6316 /* This is called once we see the "@end" in an interface/implementation. */
6318 void
6319 finish_class (class)
6320 tree class;
6322 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6324 /* All code generation is done in finish_objc. */
6326 if (implementation_template != implementation_context)
6328 /* Ensure that all method listed in the interface contain bodies. */
6329 check_methods (CLASS_CLS_METHODS (implementation_template),
6330 CLASS_CLS_METHODS (implementation_context), '+');
6331 check_methods (CLASS_NST_METHODS (implementation_template),
6332 CLASS_NST_METHODS (implementation_context), '-');
6334 if (CLASS_PROTOCOL_LIST (implementation_template))
6335 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6336 "class",
6337 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6341 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6343 tree category = CLASS_CATEGORY_LIST (implementation_template);
6345 /* Find the category interface from the class it is associated with. */
6346 while (category)
6348 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6349 break;
6350 category = CLASS_CATEGORY_LIST (category);
6353 if (category)
6355 /* Ensure all method listed in the interface contain bodies. */
6356 check_methods (CLASS_CLS_METHODS (category),
6357 CLASS_CLS_METHODS (implementation_context), '+');
6358 check_methods (CLASS_NST_METHODS (category),
6359 CLASS_NST_METHODS (implementation_context), '-');
6361 if (CLASS_PROTOCOL_LIST (category))
6362 check_protocols (CLASS_PROTOCOL_LIST (category),
6363 "category",
6364 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6368 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6370 tree decl_specs;
6371 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6372 char *string = (char *) alloca (strlen (class_name) + 3);
6374 /* extern struct objc_object *_<my_name>; */
6376 sprintf (string, "_%s", class_name);
6378 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6379 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6380 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6381 decl_specs);
6385 static tree
6386 add_protocol (protocol)
6387 tree protocol;
6389 /* Put protocol on list in reverse order. */
6390 TREE_CHAIN (protocol) = protocol_chain;
6391 protocol_chain = protocol;
6392 return protocol_chain;
6395 static tree
6396 lookup_protocol (ident)
6397 tree ident;
6399 tree chain;
6401 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6403 if (ident == PROTOCOL_NAME (chain))
6404 return chain;
6407 return NULL_TREE;
6410 tree
6411 start_protocol (code, name, list)
6412 enum tree_code code;
6413 tree name;
6414 tree list;
6416 tree protocol;
6418 if (!doing_objc_thang)
6419 objc_fatal ();
6421 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6422 if (!objc_protocol_template)
6423 objc_protocol_template = build_protocol_template ();
6425 protocol = make_node (code);
6426 TYPE_BINFO (protocol) = make_tree_vec (2);
6428 PROTOCOL_NAME (protocol) = name;
6429 PROTOCOL_LIST (protocol) = list;
6431 lookup_and_install_protocols (list);
6433 if (lookup_protocol (name))
6434 warning ("duplicate declaration for protocol `%s'",
6435 IDENTIFIER_POINTER (name));
6436 else
6437 add_protocol (protocol);
6439 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6441 return protocol;
6444 void
6445 finish_protocol (protocol)
6446 tree protocol ATTRIBUTE_UNUSED;
6451 /* "Encode" a data type into a string, which grows in util_obstack.
6452 ??? What is the FORMAT? Someone please document this! */
6454 static void
6455 encode_type_qualifiers (declspecs)
6456 tree declspecs;
6458 tree spec;
6460 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6462 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6463 obstack_1grow (&util_obstack, 'r');
6464 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6465 obstack_1grow (&util_obstack, 'n');
6466 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6467 obstack_1grow (&util_obstack, 'N');
6468 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6469 obstack_1grow (&util_obstack, 'o');
6470 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6471 obstack_1grow (&util_obstack, 'O');
6472 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6473 obstack_1grow (&util_obstack, 'V');
6477 /* Encode a pointer type. */
6479 static void
6480 encode_pointer (type, curtype, format)
6481 tree type;
6482 int curtype;
6483 int format;
6485 tree pointer_to = TREE_TYPE (type);
6487 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6489 if (TYPE_NAME (pointer_to)
6490 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6492 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6494 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6496 obstack_1grow (&util_obstack, '@');
6497 return;
6499 else if (TREE_STATIC_TEMPLATE (pointer_to))
6501 if (generating_instance_variables)
6503 obstack_1grow (&util_obstack, '@');
6504 obstack_1grow (&util_obstack, '"');
6505 obstack_grow (&util_obstack, name, strlen (name));
6506 obstack_1grow (&util_obstack, '"');
6507 return;
6509 else
6511 obstack_1grow (&util_obstack, '@');
6512 return;
6515 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6517 obstack_1grow (&util_obstack, '#');
6518 return;
6520 #ifndef OBJC_INT_SELECTORS
6521 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6523 obstack_1grow (&util_obstack, ':');
6524 return;
6526 #endif /* OBJC_INT_SELECTORS */
6529 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6530 && TYPE_MODE (pointer_to) == QImode)
6532 obstack_1grow (&util_obstack, '*');
6533 return;
6536 /* We have a type that does not get special treatment. */
6538 /* NeXT extension */
6539 obstack_1grow (&util_obstack, '^');
6540 encode_type (pointer_to, curtype, format);
6543 static void
6544 encode_array (type, curtype, format)
6545 tree type;
6546 int curtype;
6547 int format;
6549 tree an_int_cst = TYPE_SIZE (type);
6550 tree array_of = TREE_TYPE (type);
6551 char buffer[40];
6553 /* An incomplete array is treated like a pointer. */
6554 if (an_int_cst == NULL)
6556 encode_pointer (type, curtype, format);
6557 return;
6560 sprintf (buffer, "[%d",
6561 (TREE_INT_CST_LOW (an_int_cst)
6562 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6564 obstack_grow (&util_obstack, buffer, strlen (buffer));
6565 encode_type (array_of, curtype, format);
6566 obstack_1grow (&util_obstack, ']');
6567 return;
6570 static void
6571 encode_aggregate_within (type, curtype, format, left, right)
6572 tree type;
6573 int curtype;
6574 int format;
6575 int left;
6576 int right;
6578 if (obstack_object_size (&util_obstack) > 0
6579 && *(obstack_next_free (&util_obstack) - 1) == '^')
6581 tree name = TYPE_NAME (type);
6583 /* we have a reference; this is a NeXT extension. */
6585 if (obstack_object_size (&util_obstack) - curtype == 1
6586 && format == OBJC_ENCODE_INLINE_DEFS)
6588 /* Output format of struct for first level only. */
6589 tree fields = TYPE_FIELDS (type);
6591 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6593 obstack_1grow (&util_obstack, left);
6594 obstack_grow (&util_obstack,
6595 IDENTIFIER_POINTER (name),
6596 strlen (IDENTIFIER_POINTER (name)));
6597 obstack_1grow (&util_obstack, '=');
6599 else
6601 obstack_1grow (&util_obstack, left);
6602 obstack_grow (&util_obstack, "?=", 2);
6605 for ( ; fields; fields = TREE_CHAIN (fields))
6606 encode_field_decl (fields, curtype, format);
6608 obstack_1grow (&util_obstack, right);
6611 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6613 obstack_1grow (&util_obstack, left);
6614 obstack_grow (&util_obstack,
6615 IDENTIFIER_POINTER (name),
6616 strlen (IDENTIFIER_POINTER (name)));
6617 obstack_1grow (&util_obstack, right);
6620 else
6622 /* We have an untagged structure or a typedef. */
6623 obstack_1grow (&util_obstack, left);
6624 obstack_1grow (&util_obstack, '?');
6625 obstack_1grow (&util_obstack, right);
6629 else
6631 tree name = TYPE_NAME (type);
6632 tree fields = TYPE_FIELDS (type);
6634 if (format == OBJC_ENCODE_INLINE_DEFS
6635 || generating_instance_variables)
6637 obstack_1grow (&util_obstack, left);
6638 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6639 obstack_grow (&util_obstack,
6640 IDENTIFIER_POINTER (name),
6641 strlen (IDENTIFIER_POINTER (name)));
6642 else
6643 obstack_1grow (&util_obstack, '?');
6645 obstack_1grow (&util_obstack, '=');
6647 for (; fields; fields = TREE_CHAIN (fields))
6649 if (generating_instance_variables)
6651 tree fname = DECL_NAME (fields);
6653 obstack_1grow (&util_obstack, '"');
6654 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6656 obstack_grow (&util_obstack,
6657 IDENTIFIER_POINTER (fname),
6658 strlen (IDENTIFIER_POINTER (fname)));
6661 obstack_1grow (&util_obstack, '"');
6664 encode_field_decl (fields, curtype, format);
6667 obstack_1grow (&util_obstack, right);
6670 else
6672 obstack_1grow (&util_obstack, left);
6673 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6674 obstack_grow (&util_obstack,
6675 IDENTIFIER_POINTER (name),
6676 strlen (IDENTIFIER_POINTER (name)));
6677 else
6678 /* We have an untagged structure or a typedef. */
6679 obstack_1grow (&util_obstack, '?');
6681 obstack_1grow (&util_obstack, right);
6686 static void
6687 encode_aggregate (type, curtype, format)
6688 tree type;
6689 int curtype;
6690 int format;
6692 enum tree_code code = TREE_CODE (type);
6694 switch (code)
6696 case RECORD_TYPE:
6698 encode_aggregate_within(type, curtype, format, '{', '}');
6699 break;
6701 case UNION_TYPE:
6703 encode_aggregate_within(type, curtype, format, '(', ')');
6704 break;
6707 case ENUMERAL_TYPE:
6708 obstack_1grow (&util_obstack, 'i');
6709 break;
6711 default:
6712 break;
6716 /* Support bitfields. The current version of Objective-C does not support
6717 them. The string will consist of one or more "b:n"'s where n is an
6718 integer describing the width of the bitfield. Currently, classes in
6719 the kit implement a method "-(char *)describeBitfieldStruct:" that
6720 simulates this. If they do not implement this method, the archiver
6721 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6722 according to the GNU compiler. After looking at the "kit", it appears
6723 that all classes currently rely on this default behavior, rather than
6724 hand generating this string (which is tedious). */
6726 static void
6727 encode_bitfield (width, format)
6728 int width;
6729 int format;
6731 char buffer[40];
6732 sprintf (buffer, "b%d", width);
6733 obstack_grow (&util_obstack, buffer, strlen (buffer));
6736 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6738 static void
6739 encode_type (type, curtype, format)
6740 tree type;
6741 int curtype;
6742 int format;
6744 enum tree_code code = TREE_CODE (type);
6746 if (code == INTEGER_TYPE)
6748 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6749 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6751 /* Unsigned integer types. */
6753 if (TYPE_MODE (type) == QImode)
6754 obstack_1grow (&util_obstack, 'C');
6755 else if (TYPE_MODE (type) == HImode)
6756 obstack_1grow (&util_obstack, 'S');
6757 else if (TYPE_MODE (type) == SImode)
6759 if (type == long_unsigned_type_node)
6760 obstack_1grow (&util_obstack, 'L');
6761 else
6762 obstack_1grow (&util_obstack, 'I');
6764 else if (TYPE_MODE (type) == DImode)
6765 obstack_1grow (&util_obstack, 'Q');
6768 else
6769 /* Signed integer types. */
6771 if (TYPE_MODE (type) == QImode)
6772 obstack_1grow (&util_obstack, 'c');
6773 else if (TYPE_MODE (type) == HImode)
6774 obstack_1grow (&util_obstack, 's');
6775 else if (TYPE_MODE (type) == SImode)
6777 if (type == long_integer_type_node)
6778 obstack_1grow (&util_obstack, 'l');
6779 else
6780 obstack_1grow (&util_obstack, 'i');
6783 else if (TYPE_MODE (type) == DImode)
6784 obstack_1grow (&util_obstack, 'q');
6788 else if (code == REAL_TYPE)
6790 /* Floating point types. */
6792 if (TYPE_MODE (type) == SFmode)
6793 obstack_1grow (&util_obstack, 'f');
6794 else if (TYPE_MODE (type) == DFmode
6795 || TYPE_MODE (type) == TFmode)
6796 obstack_1grow (&util_obstack, 'd');
6799 else if (code == VOID_TYPE)
6800 obstack_1grow (&util_obstack, 'v');
6802 else if (code == ARRAY_TYPE)
6803 encode_array (type, curtype, format);
6805 else if (code == POINTER_TYPE)
6806 encode_pointer (type, curtype, format);
6808 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6809 encode_aggregate (type, curtype, format);
6811 else if (code == FUNCTION_TYPE) /* '?' */
6812 obstack_1grow (&util_obstack, '?');
6815 static void
6816 encode_field_decl (field_decl, curtype, format)
6817 tree field_decl;
6818 int curtype;
6819 int format;
6821 tree type;
6823 /* If this field is obviously a bitfield, or is a bitfield that has been
6824 clobbered to look like a ordinary integer mode, go ahead and generate
6825 the bitfield typing information. */
6826 type = TREE_TYPE (field_decl);
6827 if (DECL_BIT_FIELD (field_decl))
6828 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6829 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6830 && DECL_FIELD_SIZE (field_decl)
6831 && TYPE_MODE (type) > DECL_MODE (field_decl))
6832 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6833 else
6834 encode_type (TREE_TYPE (field_decl), curtype, format);
6837 static tree
6838 expr_last (complex_expr)
6839 tree complex_expr;
6841 tree next;
6843 if (complex_expr)
6844 while ((next = TREE_OPERAND (complex_expr, 0)))
6845 complex_expr = next;
6847 return complex_expr;
6850 /* The selector of the current method,
6851 or NULL if we aren't compiling a method. */
6853 tree
6854 maybe_objc_method_name (decl)
6855 tree decl;
6857 if (method_context)
6858 return METHOD_SEL_NAME (method_context);
6859 else
6860 return 0;
6863 /* Transform a method definition into a function definition as follows:
6864 - synthesize the first two arguments, "self" and "_cmd". */
6866 void
6867 start_method_def (method)
6868 tree method;
6870 tree decl_specs;
6872 /* Required to implement _msgSuper. */
6873 method_context = method;
6874 UOBJC_SUPER_decl = NULL_TREE;
6876 /* Must be called BEFORE start_function. */
6877 pushlevel (0);
6879 /* Generate prototype declarations for arguments..."new-style". */
6881 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
6882 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6883 else
6884 /* Really a `struct objc_class *'. However, we allow people to
6885 assign to self, which changes its type midstream. */
6886 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6888 push_parm_decl (build_tree_list
6889 (build_tree_list (decl_specs,
6890 build1 (INDIRECT_REF, NULL_TREE, self_id)),
6891 build_tree_list (unused_list, NULL_TREE)));
6893 #ifdef OBJC_INT_SELECTORS
6894 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
6895 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
6896 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
6897 build_tree_list (unused_list, NULL_TREE)));
6898 #else /* not OBJC_INT_SELECTORS */
6899 decl_specs = build_tree_list (NULL_TREE,
6900 xref_tag (RECORD_TYPE,
6901 get_identifier (TAG_SELECTOR)));
6902 push_parm_decl (build_tree_list
6903 (build_tree_list (decl_specs,
6904 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6905 build_tree_list (unused_list, NULL_TREE)));
6906 #endif /* not OBJC_INT_SELECTORS */
6908 /* Generate argument declarations if a keyword_decl. */
6909 if (METHOD_SEL_ARGS (method))
6911 tree arglist = METHOD_SEL_ARGS (method);
6914 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6915 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6917 if (arg_decl)
6919 tree last_expr = expr_last (arg_decl);
6921 /* Unite the abstract decl with its name. */
6922 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6923 push_parm_decl (build_tree_list
6924 (build_tree_list (arg_spec, arg_decl),
6925 build_tree_list (NULL_TREE, NULL_TREE)));
6927 /* Unhook: restore the abstract declarator. */
6928 TREE_OPERAND (last_expr, 0) = NULL_TREE;
6931 else
6932 push_parm_decl (build_tree_list
6933 (build_tree_list (arg_spec,
6934 KEYWORD_ARG_NAME (arglist)),
6935 build_tree_list (NULL_TREE, NULL_TREE)));
6937 arglist = TREE_CHAIN (arglist);
6939 while (arglist);
6942 if (METHOD_ADD_ARGS (method) > (tree)1)
6944 /* We have a variable length selector - in "prototype" format. */
6945 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6946 while (akey)
6948 /* This must be done prior to calling pushdecl. pushdecl is
6949 going to change our chain on us. */
6950 tree nextkey = TREE_CHAIN (akey);
6951 pushdecl (akey);
6952 akey = nextkey;
6957 static void
6958 warn_with_method (message, mtype, method)
6959 char *message;
6960 int mtype;
6961 tree method;
6963 if (count_error (1) == 0)
6964 return;
6966 report_error_function (DECL_SOURCE_FILE (method));
6968 fprintf (stderr, "%s:%d: warning: ",
6969 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
6970 bzero (errbuf, BUFSIZE);
6971 fprintf (stderr, "%s `%c%s'\n",
6972 message, mtype, gen_method_decl (method, errbuf));
6975 /* Return 1 if METHOD is consistent with PROTO. */
6977 static int
6978 comp_method_with_proto (method, proto)
6979 tree method, proto;
6981 static tree function_type = 0;
6983 /* Create a function_type node once. */
6984 if (!function_type)
6986 push_obstacks_nochange ();
6987 end_temporary_allocation ();
6988 function_type = make_node (FUNCTION_TYPE);
6989 pop_obstacks ();
6992 /* Install argument types - normally set by build_function_type. */
6993 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
6995 /* install return type */
6996 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
6998 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
7001 /* Return 1 if PROTO1 is consistent with PROTO2. */
7003 static int
7004 comp_proto_with_proto (proto1, proto2)
7005 tree proto1, proto2;
7007 static tree function_type1 = 0, function_type2 = 0;
7009 /* Create a couple function_type node's once. */
7010 if (!function_type1)
7012 push_obstacks_nochange ();
7013 end_temporary_allocation ();
7014 function_type1 = make_node (FUNCTION_TYPE);
7015 function_type2 = make_node (FUNCTION_TYPE);
7016 pop_obstacks ();
7019 /* Install argument types; normally set by build_function_type. */
7020 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
7021 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
7023 /* Install return type. */
7024 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
7025 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
7027 return comptypes (function_type1, function_type2);
7030 /* - Generate an identifier for the function. the format is "_n_cls",
7031 where 1 <= n <= nMethods, and cls is the name the implementation we
7032 are processing.
7033 - Install the return type from the method declaration.
7034 - If we have a prototype, check for type consistency. */
7036 static void
7037 really_start_method (method, parmlist)
7038 tree method, parmlist;
7040 tree sc_spec, ret_spec, ret_decl, decl_specs;
7041 tree method_decl, method_id;
7042 char *buf, *sel_name, *class_name, *cat_name;
7044 /* Synth the storage class & assemble the return type. */
7045 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7046 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7047 decl_specs = chainon (sc_spec, ret_spec);
7049 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7050 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
7051 cat_name = ((TREE_CODE (implementation_context)
7052 == CLASS_IMPLEMENTATION_TYPE)
7053 ? NULL
7054 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
7055 method_slot++;
7057 /* Make sure this is big enough for any plausible method label. */
7058 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7059 + (cat_name ? strlen (cat_name) : 0));
7061 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7062 class_name, cat_name, sel_name, method_slot);
7064 method_id = get_identifier (buf);
7066 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7068 /* Check the declarator portion of the return type for the method. */
7069 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7071 /* Unite the complex decl (specified in the abstract decl) with the
7072 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7073 tree save_expr = expr_last (ret_decl);
7075 TREE_OPERAND (save_expr, 0) = method_decl;
7076 method_decl = ret_decl;
7078 /* Fool the parser into thinking it is starting a function. */
7079 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7081 /* Unhook: this has the effect of restoring the abstract declarator. */
7082 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7085 else
7087 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7089 /* Fool the parser into thinking it is starting a function. */
7090 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7092 /* Unhook: this has the effect of restoring the abstract declarator. */
7093 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7096 METHOD_DEFINITION (method) = current_function_decl;
7098 if (implementation_template != implementation_context)
7100 tree proto;
7102 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7103 proto = lookup_instance_method_static (implementation_template,
7104 METHOD_SEL_NAME (method));
7105 else
7106 proto = lookup_class_method_static (implementation_template,
7107 METHOD_SEL_NAME (method));
7109 if (proto && ! comp_method_with_proto (method, proto))
7111 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7113 warn_with_method ("conflicting types for", type, method);
7114 warn_with_method ("previous declaration of", type, proto);
7119 /* The following routine is always called...this "architecture" is to
7120 accommodate "old-style" variable length selectors.
7122 - a:a b:b // prototype ; id c; id d; // old-style. */
7124 void
7125 continue_method_def ()
7127 tree parmlist;
7129 if (METHOD_ADD_ARGS (method_context) == (tree)1)
7130 /* We have a `, ...' immediately following the selector. */
7131 parmlist = get_parm_info (0);
7132 else
7133 parmlist = get_parm_info (1); /* place a `void_at_end' */
7135 /* Set self_decl from the first argument...this global is used by
7136 build_ivar_reference calling build_indirect_ref. */
7137 self_decl = TREE_PURPOSE (parmlist);
7139 poplevel (0, 0, 0);
7140 really_start_method (method_context, parmlist);
7141 store_parm_decls ();
7144 /* Called by the parser, from the `pushlevel' production. */
7146 void
7147 add_objc_decls ()
7149 if (!UOBJC_SUPER_decl)
7151 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7152 build_tree_list (NULL_TREE,
7153 objc_super_template),
7154 0, NULL_TREE, NULL_TREE);
7156 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7158 /* This prevents `unused variable' warnings when compiling with -Wall. */
7159 TREE_USED (UOBJC_SUPER_decl) = 1;
7160 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7164 /* _n_Method (id self, SEL sel, ...)
7166 struct objc_super _S;
7167 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7168 } */
7170 tree
7171 get_super_receiver ()
7173 if (method_context)
7175 tree super_expr, super_expr_list;
7177 /* Set receiver to self. */
7178 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7179 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7180 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7182 /* Set class to begin searching. */
7183 super_expr = build_component_ref (UOBJC_SUPER_decl,
7184 get_identifier ("class"));
7186 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7188 /* [_cls, __cls]Super are "pre-built" in
7189 synth_forward_declarations. */
7191 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7192 ((TREE_CODE (method_context)
7193 == INSTANCE_METHOD_DECL)
7194 ? ucls_super_ref
7195 : uucls_super_ref));
7198 else
7199 /* We have a category. */
7201 tree super_name = CLASS_SUPER_NAME (implementation_template);
7202 tree super_class;
7204 if (!super_name)
7206 error ("no super class declared in interface for `%s'",
7207 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7208 return error_mark_node;
7211 if (flag_next_runtime)
7213 super_class = get_class_reference (super_name);
7214 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7215 super_class
7216 = build_component_ref (build_indirect_ref (super_class, "->"),
7217 get_identifier ("isa"));
7219 else
7221 add_class_reference (super_name);
7222 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7223 ? objc_get_class_decl : objc_get_meta_class_decl);
7224 assemble_external (super_class);
7225 super_class
7226 = build_function_call
7227 (super_class,
7228 build_tree_list
7229 (NULL_TREE,
7230 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7231 IDENTIFIER_POINTER (super_name))));
7234 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7235 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7238 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7240 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7241 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7243 return build_compound_expr (super_expr_list);
7245 else
7247 error ("[super ...] must appear in a method context");
7248 return error_mark_node;
7252 static tree
7253 encode_method_def (func_decl)
7254 tree func_decl;
7256 tree parms;
7257 int stack_size;
7258 int max_parm_end = 0;
7259 char buffer[40];
7260 tree result;
7262 /* Return type. */
7263 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7264 obstack_object_size (&util_obstack),
7265 OBJC_ENCODE_INLINE_DEFS);
7267 /* Stack size. */
7268 for (parms = DECL_ARGUMENTS (func_decl); parms;
7269 parms = TREE_CHAIN (parms))
7271 int parm_end = (forwarding_offset (parms)
7272 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
7273 / BITS_PER_UNIT));
7275 if (!offset_is_register && parm_end > max_parm_end)
7276 max_parm_end = parm_end;
7279 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7281 sprintf (buffer, "%d", stack_size);
7282 obstack_grow (&util_obstack, buffer, strlen (buffer));
7284 /* Argument types. */
7285 for (parms = DECL_ARGUMENTS (func_decl); parms;
7286 parms = TREE_CHAIN (parms))
7288 /* Type. */
7289 encode_type (TREE_TYPE (parms),
7290 obstack_object_size (&util_obstack),
7291 OBJC_ENCODE_INLINE_DEFS);
7293 /* Compute offset. */
7294 sprintf (buffer, "%d", forwarding_offset (parms));
7296 /* Indicate register. */
7297 if (offset_is_register)
7298 obstack_1grow (&util_obstack, '+');
7300 obstack_grow (&util_obstack, buffer, strlen (buffer));
7303 obstack_1grow (&util_obstack, 0);
7304 result = get_identifier (obstack_finish (&util_obstack));
7305 obstack_free (&util_obstack, util_firstobj);
7306 return result;
7309 void
7310 finish_method_def ()
7312 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7314 finish_function (0);
7316 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7317 since the optimizer may find "may be used before set" errors. */
7318 method_context = NULL_TREE;
7321 #if 0
7323 lang_report_error_function (decl)
7324 tree decl;
7326 if (method_context)
7328 fprintf (stderr, "In method `%s'\n",
7329 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7330 return 1;
7333 else
7334 return 0;
7336 #endif
7338 static int
7339 is_complex_decl (type)
7340 tree type;
7342 return (TREE_CODE (type) == ARRAY_TYPE
7343 || TREE_CODE (type) == FUNCTION_TYPE
7344 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7348 /* Code to convert a decl node into text for a declaration in C. */
7350 static char tmpbuf[256];
7352 static void
7353 adorn_decl (decl, str)
7354 tree decl;
7355 char *str;
7357 enum tree_code code = TREE_CODE (decl);
7359 if (code == ARRAY_REF)
7361 tree an_int_cst = TREE_OPERAND (decl, 1);
7363 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7364 sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst));
7365 else
7366 strcat (str, "[]");
7369 else if (code == ARRAY_TYPE)
7371 tree an_int_cst = TYPE_SIZE (decl);
7372 tree array_of = TREE_TYPE (decl);
7374 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7375 sprintf (str + strlen (str), "[%d]",
7376 (TREE_INT_CST_LOW (an_int_cst)
7377 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7378 else
7379 strcat (str, "[]");
7382 else if (code == CALL_EXPR)
7384 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7386 strcat (str, "(");
7387 while (chain)
7389 gen_declaration (chain, str);
7390 chain = TREE_CHAIN (chain);
7391 if (chain)
7392 strcat (str, ", ");
7394 strcat (str, ")");
7397 else if (code == FUNCTION_TYPE)
7399 tree chain = TYPE_ARG_TYPES (decl);
7401 strcat (str, "(");
7402 while (chain && TREE_VALUE (chain) != void_type_node)
7404 gen_declaration (TREE_VALUE (chain), str);
7405 chain = TREE_CHAIN (chain);
7406 if (chain && TREE_VALUE (chain) != void_type_node)
7407 strcat (str, ", ");
7409 strcat (str, ")");
7412 else if (code == INDIRECT_REF)
7414 strcpy (tmpbuf, "*");
7415 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7417 tree chain;
7419 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7420 chain;
7421 chain = TREE_CHAIN (chain))
7423 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7425 strcat (tmpbuf, " ");
7426 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7429 if (str[0])
7430 strcat (tmpbuf, " ");
7432 strcat (tmpbuf, str);
7433 strcpy (str, tmpbuf);
7436 else if (code == POINTER_TYPE)
7438 strcpy (tmpbuf, "*");
7439 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7441 if (TREE_READONLY (decl))
7442 strcat (tmpbuf, " const");
7443 if (TYPE_VOLATILE (decl))
7444 strcat (tmpbuf, " volatile");
7445 if (str[0])
7446 strcat (tmpbuf, " ");
7448 strcat (tmpbuf, str);
7449 strcpy (str, tmpbuf);
7453 static char *
7454 gen_declarator (decl, buf, name)
7455 tree decl;
7456 char *buf;
7457 char *name;
7459 if (decl)
7461 enum tree_code code = TREE_CODE (decl);
7462 char *str;
7463 tree op;
7464 int wrap = 0;
7466 switch (code)
7468 case ARRAY_REF:
7469 case INDIRECT_REF:
7470 case CALL_EXPR:
7471 op = TREE_OPERAND (decl, 0);
7473 /* We have a pointer to a function or array...(*)(), (*)[] */
7474 if ((code == ARRAY_REF || code == CALL_EXPR)
7475 && op && TREE_CODE (op) == INDIRECT_REF)
7476 wrap = 1;
7478 str = gen_declarator (op, buf, name);
7480 if (wrap)
7482 strcpy (tmpbuf, "(");
7483 strcat (tmpbuf, str);
7484 strcat (tmpbuf, ")");
7485 strcpy (str, tmpbuf);
7488 adorn_decl (decl, str);
7489 break;
7491 case ARRAY_TYPE:
7492 case FUNCTION_TYPE:
7493 case POINTER_TYPE:
7494 strcpy (buf, name);
7495 str = buf;
7497 /* This clause is done iteratively rather than recursively. */
7500 op = (is_complex_decl (TREE_TYPE (decl))
7501 ? TREE_TYPE (decl) : NULL_TREE);
7503 adorn_decl (decl, str);
7505 /* We have a pointer to a function or array...(*)(), (*)[] */
7506 if (code == POINTER_TYPE
7507 && op && (TREE_CODE (op) == FUNCTION_TYPE
7508 || TREE_CODE (op) == ARRAY_TYPE))
7510 strcpy (tmpbuf, "(");
7511 strcat (tmpbuf, str);
7512 strcat (tmpbuf, ")");
7513 strcpy (str, tmpbuf);
7516 decl = (is_complex_decl (TREE_TYPE (decl))
7517 ? TREE_TYPE (decl) : NULL_TREE);
7520 while (decl && (code = TREE_CODE (decl)))
7523 break;
7525 case IDENTIFIER_NODE:
7526 /* Will only happen if we are processing a "raw" expr-decl. */
7527 strcpy (buf, IDENTIFIER_POINTER (decl));
7528 return buf;
7530 default:
7531 break;
7534 return str;
7537 else
7538 /* We have an abstract declarator or a _DECL node. */
7540 strcpy (buf, name);
7541 return buf;
7545 static void
7546 gen_declspecs (declspecs, buf, raw)
7547 tree declspecs;
7548 char *buf;
7549 int raw;
7551 if (raw)
7553 tree chain;
7555 for (chain = nreverse (copy_list (declspecs));
7556 chain; chain = TREE_CHAIN (chain))
7558 tree aspec = TREE_VALUE (chain);
7560 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7561 strcat (buf, IDENTIFIER_POINTER (aspec));
7562 else if (TREE_CODE (aspec) == RECORD_TYPE)
7564 if (TYPE_NAME (aspec))
7566 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7568 if (! TREE_STATIC_TEMPLATE (aspec))
7569 strcat (buf, "struct ");
7570 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7572 /* NEW!!! */
7573 if (protocol_list)
7575 tree chain = protocol_list;
7577 strcat (buf, " <");
7578 while (chain)
7580 strcat (buf,
7581 IDENTIFIER_POINTER
7582 (PROTOCOL_NAME (TREE_VALUE (chain))));
7583 chain = TREE_CHAIN (chain);
7584 if (chain)
7585 strcat (buf, ", ");
7587 strcat (buf, ">");
7591 else
7592 strcat (buf, "untagged struct");
7595 else if (TREE_CODE (aspec) == UNION_TYPE)
7597 if (TYPE_NAME (aspec))
7599 if (! TREE_STATIC_TEMPLATE (aspec))
7600 strcat (buf, "union ");
7601 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7603 else
7604 strcat (buf, "untagged union");
7607 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7609 if (TYPE_NAME (aspec))
7611 if (! TREE_STATIC_TEMPLATE (aspec))
7612 strcat (buf, "enum ");
7613 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7615 else
7616 strcat (buf, "untagged enum");
7619 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7620 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7622 else if (IS_ID (aspec))
7624 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7626 strcat (buf, "id");
7627 if (protocol_list)
7629 tree chain = protocol_list;
7631 strcat (buf, " <");
7632 while (chain)
7634 strcat (buf,
7635 IDENTIFIER_POINTER
7636 (PROTOCOL_NAME (TREE_VALUE (chain))));
7637 chain = TREE_CHAIN (chain);
7638 if (chain)
7639 strcat (buf, ", ");
7641 strcat (buf, ">");
7644 if (TREE_CHAIN (chain))
7645 strcat (buf, " ");
7648 else
7650 /* Type qualifiers. */
7651 if (TREE_READONLY (declspecs))
7652 strcat (buf, "const ");
7653 if (TYPE_VOLATILE (declspecs))
7654 strcat (buf, "volatile ");
7656 switch (TREE_CODE (declspecs))
7658 /* Type specifiers. */
7660 case INTEGER_TYPE:
7661 declspecs = TYPE_MAIN_VARIANT (declspecs);
7663 /* Signed integer types. */
7665 if (declspecs == short_integer_type_node)
7666 strcat (buf, "short int ");
7667 else if (declspecs == integer_type_node)
7668 strcat (buf, "int ");
7669 else if (declspecs == long_integer_type_node)
7670 strcat (buf, "long int ");
7671 else if (declspecs == long_long_integer_type_node)
7672 strcat (buf, "long long int ");
7673 else if (declspecs == signed_char_type_node
7674 || declspecs == char_type_node)
7675 strcat (buf, "char ");
7677 /* Unsigned integer types. */
7679 else if (declspecs == short_unsigned_type_node)
7680 strcat (buf, "unsigned short ");
7681 else if (declspecs == unsigned_type_node)
7682 strcat (buf, "unsigned int ");
7683 else if (declspecs == long_unsigned_type_node)
7684 strcat (buf, "unsigned long ");
7685 else if (declspecs == long_long_unsigned_type_node)
7686 strcat (buf, "unsigned long long ");
7687 else if (declspecs == unsigned_char_type_node)
7688 strcat (buf, "unsigned char ");
7689 break;
7691 case REAL_TYPE:
7692 declspecs = TYPE_MAIN_VARIANT (declspecs);
7694 if (declspecs == float_type_node)
7695 strcat (buf, "float ");
7696 else if (declspecs == double_type_node)
7697 strcat (buf, "double ");
7698 else if (declspecs == long_double_type_node)
7699 strcat (buf, "long double ");
7700 break;
7702 case RECORD_TYPE:
7703 if (TYPE_NAME (declspecs)
7704 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7706 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7708 if (! TREE_STATIC_TEMPLATE (declspecs))
7709 strcat (buf, "struct ");
7710 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7712 if (protocol_list)
7714 tree chain = protocol_list;
7716 strcat (buf, " <");
7717 while (chain)
7719 strcat (buf,
7720 IDENTIFIER_POINTER
7721 (PROTOCOL_NAME (TREE_VALUE (chain))));
7722 chain = TREE_CHAIN (chain);
7723 if (chain)
7724 strcat (buf, ", ");
7726 strcat (buf, ">");
7730 else
7731 strcat (buf, "untagged struct");
7733 strcat (buf, " ");
7734 break;
7736 case UNION_TYPE:
7737 if (TYPE_NAME (declspecs)
7738 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7740 strcat (buf, "union ");
7741 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7742 strcat (buf, " ");
7745 else
7746 strcat (buf, "untagged union ");
7747 break;
7749 case ENUMERAL_TYPE:
7750 if (TYPE_NAME (declspecs)
7751 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7753 strcat (buf, "enum ");
7754 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7755 strcat (buf, " ");
7758 else
7759 strcat (buf, "untagged enum ");
7760 break;
7762 case VOID_TYPE:
7763 strcat (buf, "void ");
7764 break;
7766 case POINTER_TYPE:
7768 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7770 strcat (buf, "id");
7771 if (protocol_list)
7773 tree chain = protocol_list;
7775 strcat (buf, " <");
7776 while (chain)
7778 strcat (buf,
7779 IDENTIFIER_POINTER
7780 (PROTOCOL_NAME (TREE_VALUE (chain))));
7781 chain = TREE_CHAIN (chain);
7782 if (chain)
7783 strcat (buf, ", ");
7786 strcat (buf, ">");
7789 break;
7791 default:
7792 break;
7797 static char *
7798 gen_declaration (atype_or_adecl, buf)
7799 tree atype_or_adecl;
7800 char *buf;
7802 char declbuf[256];
7804 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7806 tree declspecs; /* "identifier_node", "record_type" */
7807 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7809 /* We have a "raw", abstract declarator (typename). */
7810 declarator = TREE_VALUE (atype_or_adecl);
7811 declspecs = TREE_PURPOSE (atype_or_adecl);
7813 gen_declspecs (declspecs, buf, 1);
7814 if (declarator)
7816 strcat (buf, " ");
7817 strcat (buf, gen_declarator (declarator, declbuf, ""));
7821 else
7823 tree atype;
7824 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7825 tree declarator; /* "array_type", "function_type", "pointer_type". */
7827 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7828 || TREE_CODE (atype_or_adecl) == PARM_DECL
7829 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7830 atype = TREE_TYPE (atype_or_adecl);
7831 else
7832 /* Assume we have a *_type node. */
7833 atype = atype_or_adecl;
7835 if (is_complex_decl (atype))
7837 tree chain;
7839 /* Get the declaration specifier; it is at the end of the list. */
7840 declarator = chain = atype;
7842 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7843 while (is_complex_decl (chain));
7844 declspecs = chain;
7847 else
7849 declspecs = atype;
7850 declarator = NULL_TREE;
7853 gen_declspecs (declspecs, buf, 0);
7855 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7856 || TREE_CODE (atype_or_adecl) == PARM_DECL
7857 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7859 char *decl_name = (DECL_NAME (atype_or_adecl)
7860 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
7861 : "");
7863 if (declarator)
7865 strcat (buf, " ");
7866 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7869 else if (decl_name[0])
7871 strcat (buf, " ");
7872 strcat (buf, decl_name);
7875 else if (declarator)
7877 strcat (buf, " ");
7878 strcat (buf, gen_declarator (declarator, declbuf, ""));
7882 return buf;
7885 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7887 static char *
7888 gen_method_decl (method, buf)
7889 tree method;
7890 char *buf;
7892 tree chain;
7894 if (RAW_TYPESPEC (method) != objc_object_reference)
7896 strcpy (buf, "(");
7897 gen_declaration (TREE_TYPE (method), buf);
7898 strcat (buf, ")");
7901 chain = METHOD_SEL_ARGS (method);
7902 if (chain)
7904 /* We have a chain of keyword_decls. */
7907 if (KEYWORD_KEY_NAME (chain))
7908 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7910 strcat (buf, ":");
7911 if (RAW_TYPESPEC (chain) != objc_object_reference)
7913 strcat (buf, "(");
7914 gen_declaration (TREE_TYPE (chain), buf);
7915 strcat (buf, ")");
7918 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7919 if ((chain = TREE_CHAIN (chain)))
7920 strcat (buf, " ");
7922 while (chain);
7924 if (METHOD_ADD_ARGS (method) == (tree)1)
7925 strcat (buf, ", ...");
7926 else if (METHOD_ADD_ARGS (method))
7928 /* We have a tree list node as generate by get_parm_info. */
7929 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7931 /* Know we have a chain of parm_decls. */
7932 while (chain)
7934 strcat (buf, ", ");
7935 gen_declaration (chain, buf);
7936 chain = TREE_CHAIN (chain);
7941 else
7942 /* We have a unary selector. */
7943 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7945 return buf;
7948 /* Debug info. */
7950 static void
7951 dump_interface (fp, chain)
7952 FILE *fp;
7953 tree chain;
7955 char *buf = (char *)xmalloc (256);
7956 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7957 tree ivar_decls = CLASS_RAW_IVARS (chain);
7958 tree nst_methods = CLASS_NST_METHODS (chain);
7959 tree cls_methods = CLASS_CLS_METHODS (chain);
7961 fprintf (fp, "\n@interface %s", my_name);
7963 if (CLASS_SUPER_NAME (chain))
7965 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7966 fprintf (fp, " : %s\n", super_name);
7968 else
7969 fprintf (fp, "\n");
7971 if (ivar_decls)
7973 fprintf (fp, "{\n");
7976 bzero (buf, 256);
7977 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7978 ivar_decls = TREE_CHAIN (ivar_decls);
7980 while (ivar_decls);
7981 fprintf (fp, "}\n");
7984 while (nst_methods)
7986 bzero (buf, 256);
7987 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7988 nst_methods = TREE_CHAIN (nst_methods);
7991 while (cls_methods)
7993 bzero (buf, 256);
7994 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7995 cls_methods = TREE_CHAIN (cls_methods);
7997 fprintf (fp, "\n@end");
8000 /* Demangle function for Objective-C */
8001 static const char *
8002 objc_demangle (mangled)
8003 const char *mangled;
8005 char *demangled, *cp;
8007 if (mangled[0] == '_' &&
8008 (mangled[1] == 'i' || mangled[1] == 'c') &&
8009 mangled[2] == '_')
8011 cp = demangled = xmalloc(strlen(mangled) + 2);
8012 if (mangled[1] == 'i')
8013 *cp++ = '-'; /* for instance method */
8014 else
8015 *cp++ = '+'; /* for class method */
8016 *cp++ = '['; /* opening left brace */
8017 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8018 while (*cp && *cp == '_')
8019 cp++; /* skip any initial underbars in class name */
8020 cp = strchr(cp, '_'); /* find first non-initial underbar */
8021 if (cp == NULL)
8023 free(demangled); /* not mangled name */
8024 return mangled;
8026 if (cp[1] == '_') /* easy case: no category name */
8028 *cp++ = ' '; /* replace two '_' with one ' ' */
8029 strcpy(cp, mangled + (cp - demangled) + 2);
8031 else
8033 *cp++ = '('; /* less easy case: category name */
8034 cp = strchr(cp, '_');
8035 if (cp == 0)
8037 free(demangled); /* not mangled name */
8038 return mangled;
8040 *cp++ = ')';
8041 *cp++ = ' '; /* overwriting 1st char of method name... */
8042 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8044 while (*cp && *cp == '_')
8045 cp++; /* skip any initial underbars in method name */
8046 for (; *cp; cp++)
8047 if (*cp == '_')
8048 *cp = ':'; /* replace remaining '_' with ':' */
8049 *cp++ = ']'; /* closing right brace */
8050 *cp++ = 0; /* string terminator */
8051 return demangled;
8053 else
8054 return mangled; /* not an objc mangled name */
8057 static const char *
8058 objc_printable_name (decl, kind)
8059 tree decl;
8060 char **kind;
8062 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8065 static void
8066 init_objc ()
8068 /* Add the special tree codes of Objective C to the tables. */
8070 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
8072 gcc_obstack_init (&util_obstack);
8073 util_firstobj = (char *) obstack_finish (&util_obstack);
8075 bcopy (objc_tree_code_type,
8076 tree_code_type + (int) LAST_CODE,
8077 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
8078 bcopy ((char *) objc_tree_code_length,
8079 (char *) (tree_code_length + (int) LAST_CODE),
8080 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8081 * sizeof (int)));
8082 bcopy ((char *) objc_tree_code_name,
8083 (char *) (tree_code_name + (int) LAST_CODE),
8084 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8085 * sizeof (char *)));
8087 errbuf = (char *)xmalloc (BUFSIZE);
8088 hash_init ();
8089 synth_module_prologue ();
8091 /* Change the default error function */
8092 decl_printable_name = (char* (*)()) objc_printable_name;
8095 static void
8096 finish_objc ()
8098 struct imp_entry *impent;
8099 tree chain;
8100 /* The internally generated initializers appear to have missing braces.
8101 Don't warn about this. */
8102 int save_warn_missing_braces = warn_missing_braces;
8103 warn_missing_braces = 0;
8105 generate_forward_declaration_to_string_table ();
8107 #ifdef OBJC_PROLOGUE
8108 OBJC_PROLOGUE;
8109 #endif
8111 /* Process the static instances here because initialization of objc_symtab
8112 depends on them. */
8113 if (objc_static_instances)
8114 generate_static_references ();
8116 if (implementation_context || class_names_chain
8117 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8118 generate_objc_symtab_decl ();
8120 for (impent = imp_list; impent; impent = impent->next)
8122 implementation_context = impent->imp_context;
8123 implementation_template = impent->imp_template;
8125 UOBJC_CLASS_decl = impent->class_decl;
8126 UOBJC_METACLASS_decl = impent->meta_decl;
8128 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8130 /* all of the following reference the string pool... */
8131 generate_ivar_lists ();
8132 generate_dispatch_tables ();
8133 generate_shared_structures ();
8135 else
8137 generate_dispatch_tables ();
8138 generate_category (implementation_context);
8142 /* If we are using an array of selectors, we must always
8143 finish up the array decl even if no selectors were used. */
8144 if (! flag_next_runtime || sel_ref_chain)
8145 build_selector_translation_table ();
8147 if (protocol_chain)
8148 generate_protocols ();
8150 if (implementation_context || class_names_chain || objc_static_instances
8151 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8153 /* Arrange for Objc data structures to be initialized at run time. */
8154 char *init_name = build_module_descriptor ();
8155 if (init_name)
8156 assemble_constructor (init_name);
8159 /* Dump the class references. This forces the appropriate classes
8160 to be linked into the executable image, preserving unix archive
8161 semantics. This can be removed when we move to a more dynamically
8162 linked environment. */
8164 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8166 handle_class_ref (chain);
8167 if (TREE_PURPOSE (chain))
8168 generate_classref_translation_entry (chain);
8171 for (impent = imp_list; impent; impent = impent->next)
8172 handle_impent (impent);
8174 /* Dump the string table last. */
8176 generate_strings ();
8178 if (flag_gen_declaration)
8180 add_class (implementation_context);
8181 dump_interface (gen_declaration_file, implementation_context);
8184 if (warn_selector)
8186 int slot;
8187 hash hsh;
8189 /* Run through the selector hash tables and print a warning for any
8190 selector which has multiple methods. */
8192 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8193 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8194 if (hsh->list)
8196 tree meth = hsh->key;
8197 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8198 ? '-' : '+');
8199 attr loop;
8201 warning ("potential selector conflict for method `%s'",
8202 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8203 warn_with_method ("found", type, meth);
8204 for (loop = hsh->list; loop; loop = loop->next)
8205 warn_with_method ("found", type, loop->value);
8208 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8209 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8210 if (hsh->list)
8212 tree meth = hsh->key;
8213 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8214 ? '-' : '+');
8215 attr loop;
8217 warning ("potential selector conflict for method `%s'",
8218 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8219 warn_with_method ("found", type, meth);
8220 for (loop = hsh->list; loop; loop = loop->next)
8221 warn_with_method ("found", type, loop->value);
8225 warn_missing_braces = save_warn_missing_braces;
8228 /* Subroutines of finish_objc. */
8230 static void
8231 generate_classref_translation_entry (chain)
8232 tree chain;
8234 tree expr, name, decl_specs, decl, sc_spec;
8235 tree type;
8237 type = TREE_TYPE (TREE_PURPOSE (chain));
8239 expr = add_objc_string (TREE_VALUE (chain), class_names);
8240 expr = build_c_cast (type, expr); /* cast! */
8242 name = DECL_NAME (TREE_PURPOSE (chain));
8244 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8246 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8247 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8249 /* The decl that is returned from start_decl is the one that we
8250 forward declared in build_class_reference. */
8251 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8252 finish_decl (decl, expr, NULL_TREE);
8253 return;
8256 static void
8257 handle_class_ref (chain)
8258 tree chain;
8260 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8261 if (! flag_next_runtime)
8263 tree decl;
8264 char *string = (char *) alloca (strlen (name) + 30);
8265 tree exp;
8267 sprintf (string, "%sobjc_class_name_%s",
8268 (flag_next_runtime ? "." : "__"), name);
8270 /* Make a decl for this name, so we can use its address in a tree. */
8271 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8272 DECL_EXTERNAL (decl) = 1;
8273 TREE_PUBLIC (decl) = 1;
8275 pushdecl (decl);
8276 rest_of_decl_compilation (decl, 0, 0, 0);
8278 /* Make following constant read-only (why not)? */
8279 readonly_data_section ();
8281 exp = build1 (ADDR_EXPR, string_type_node, decl);
8283 /* Align the section properly. */
8284 assemble_constant_align (exp);
8286 /* Inform the assembler about this new external thing. */
8287 assemble_external (decl);
8289 /* Output a constant to reference this address. */
8290 output_constant (exp, int_size_in_bytes (string_type_node));
8292 else
8294 /* This overreliance on our assembler (i.e. lack of portability)
8295 should be dealt with at some point. The GNU strategy (above)
8296 won't work either, but it is a start. */
8297 char *string = (char *) alloca (strlen (name) + 30);
8298 sprintf (string, ".reference .objc_class_name_%s", name);
8299 assemble_asm (my_build_string (strlen (string) + 1, string));
8303 static void
8304 handle_impent (impent)
8305 struct imp_entry *impent;
8307 implementation_context = impent->imp_context;
8308 implementation_template = impent->imp_template;
8310 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8312 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8313 char *string = (char *) alloca (strlen (class_name) + 30);
8315 if (flag_next_runtime)
8317 /* Grossly unportable.
8318 People should know better than to assume
8319 such things about assembler syntax! */
8320 sprintf (string, ".objc_class_name_%s=0", class_name);
8321 assemble_asm (my_build_string (strlen (string) + 1, string));
8323 sprintf (string, ".globl .objc_class_name_%s", class_name);
8324 assemble_asm (my_build_string (strlen (string) + 1, string));
8327 else
8329 sprintf (string, "%sobjc_class_name_%s",
8330 (flag_next_runtime ? "." : "__"), class_name);
8331 assemble_global (string);
8332 assemble_label (string);
8336 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8338 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8339 char *class_super_name
8340 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8341 char *string = (char *) alloca (strlen (class_name)
8342 + strlen (class_super_name) + 30);
8344 /* Do the same for categories. Even though no references to these
8345 symbols are generated automatically by the compiler, it gives
8346 you a handle to pull them into an archive by hand. */
8347 if (flag_next_runtime)
8349 /* Grossly unportable. */
8350 sprintf (string, ".objc_category_name_%s_%s=0",
8351 class_name, class_super_name);
8352 assemble_asm (my_build_string (strlen (string) + 1, string));
8354 sprintf (string, ".globl .objc_category_name_%s_%s",
8355 class_name, class_super_name);
8356 assemble_asm (my_build_string (strlen (string) + 1, string));
8359 else
8361 sprintf (string, "%sobjc_category_name_%s_%s",
8362 (flag_next_runtime ? "." : "__"),
8363 class_name, class_super_name);
8364 assemble_global (string);
8365 assemble_label (string);
8370 #ifdef DEBUG
8372 static void
8373 objc_debug (fp)
8374 FILE *fp;
8376 char *buf = (char *)xmalloc (256);
8378 { /* dump function prototypes */
8379 tree loop = UOBJC_MODULES_decl;
8381 fprintf (fp, "\n\nfunction prototypes:\n");
8382 while (loop)
8384 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8386 /* We have a function definition: generate prototype. */
8387 bzero (errbuf, BUFSIZE);
8388 gen_declaration (loop, errbuf);
8389 fprintf (fp, "%s;\n", errbuf);
8391 loop = TREE_CHAIN (loop);
8395 /* Dump global chains. */
8396 tree loop;
8397 int i, index = 0, offset = 0;
8398 hash hashlist;
8400 for (i = 0; i < SIZEHASHTABLE; i++)
8402 if (hashlist = nst_method_hash_list[i])
8404 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8407 bzero (buf, 256);
8408 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8409 hashlist = hashlist->next;
8411 while (hashlist);
8415 for (i = 0; i < SIZEHASHTABLE; i++)
8417 if (hashlist = cls_method_hash_list[i])
8419 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8422 bzero (buf, 256);
8423 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8424 hashlist = hashlist->next;
8426 while (hashlist);
8430 fprintf (fp, "\nsel_refdef_chain:\n");
8431 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8433 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8434 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8435 index++;
8436 /* add one for the '\0' character */
8437 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8440 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8443 #endif
8445 void
8446 print_lang_statistics ()