* fold-const.c (tree_expr_nonnegative_p): Reformat checks for
[official-gcc.git] / gcc / objc / objc-act.c
blob1d76cc4d98959392f8019c4eed4f4116fbf59bdd
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003 Free Software Foundation, Inc.
4 Contributed by Steve Naroff.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* Purpose: This module implements the Objective-C 4.0 language.
25 compatibility issues (with the Stepstone translator):
27 - does not recognize the following 3.3 constructs.
28 @requires, @classes, @messages, = (...)
29 - methods with variable arguments must conform to ANSI standard.
30 - tagged structure definitions that appear in BOTH the interface
31 and implementation are not allowed.
32 - public/private: all instance variables are public within the
33 context of the implementation...I consider this to be a bug in
34 the translator.
35 - statically allocated objects are not supported. the user will
36 receive an error if this service is requested.
38 code generation `options':
42 #include "config.h"
43 #include "system.h"
44 #include "coretypes.h"
45 #include "tm.h"
46 #include "tree.h"
47 #include "rtl.h"
48 #include "tm_p.h"
49 #include "expr.h"
50 #include "c-tree.h"
51 #include "c-common.h"
52 #include "flags.h"
53 #include "langhooks.h"
54 #include "objc-act.h"
55 #include "input.h"
56 #include "except.h"
57 #include "function.h"
58 #include "output.h"
59 #include "toplev.h"
60 #include "ggc.h"
61 #include "varray.h"
62 #include "debug.h"
63 #include "target.h"
64 #include "diagnostic.h"
65 #include "cgraph.h"
67 #define OBJC_VOID_AT_END build_tree_list (NULL_TREE, void_type_node)
69 /* This is the default way of generating a method name. */
70 /* I am not sure it is really correct.
71 Perhaps there's a danger that it will make name conflicts
72 if method names contain underscores. -- rms. */
73 #ifndef OBJC_GEN_METHOD_LABEL
74 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
75 do { \
76 char *temp; \
77 sprintf ((BUF), "_%s_%s_%s_%s", \
78 ((IS_INST) ? "i" : "c"), \
79 (CLASS_NAME), \
80 ((CAT_NAME)? (CAT_NAME) : ""), \
81 (SEL_NAME)); \
82 for (temp = (BUF); *temp; temp++) \
83 if (*temp == ':') *temp = '_'; \
84 } while (0)
85 #endif
87 /* These need specifying. */
88 #ifndef OBJC_FORWARDING_STACK_OFFSET
89 #define OBJC_FORWARDING_STACK_OFFSET 0
90 #endif
92 #ifndef OBJC_FORWARDING_MIN_OFFSET
93 #define OBJC_FORWARDING_MIN_OFFSET 0
94 #endif
96 /* Set up for use of obstacks. */
98 #include "obstack.h"
100 /* This obstack is used to accumulate the encoding of a data type. */
101 static struct obstack util_obstack;
103 /* This points to the beginning of obstack contents, so we can free
104 the whole contents. */
105 char *util_firstobj;
107 /* The version identifies which language generation and runtime
108 the module (file) was compiled for, and is recorded in the
109 module descriptor. */
111 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
112 #define PROTOCOL_VERSION 2
114 /* (Decide if these can ever be validly changed.) */
115 #define OBJC_ENCODE_INLINE_DEFS 0
116 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
118 /*** Private Interface (procedures) ***/
120 /* Used by compile_file. */
122 static void init_objc (void);
123 static void finish_objc (void);
125 /* Code generation. */
127 static void synth_module_prologue (void);
128 static tree objc_build_constructor (tree, tree);
129 static rtx build_module_descriptor (void);
130 static tree init_module_descriptor (tree);
131 static tree build_objc_method_call (int, tree, tree, tree, tree);
132 static void generate_strings (void);
133 static tree get_proto_encoding (tree);
134 static void build_selector_translation_table (void);
136 static tree objc_add_static_instance (tree, tree);
138 static void build_objc_exception_stuff (void);
139 static tree objc_declare_variable (enum rid, tree, tree, tree);
140 static tree objc_enter_block (void);
141 static tree objc_exit_block (void);
142 static void objc_build_try_enter_fragment (void);
143 static void objc_build_try_exit_fragment (void);
144 static void objc_build_extract_fragment (void);
145 static tree objc_build_extract_expr (void);
147 static tree build_ivar_template (void);
148 static tree build_method_template (void);
149 static tree build_private_template (tree);
150 static void build_class_template (void);
151 static void build_selector_template (void);
152 static void build_category_template (void);
153 static tree lookup_method_in_hash_lists (tree, int);
154 static void build_super_template (void);
155 static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
156 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
157 static void synth_forward_declarations (void);
158 static int ivar_list_length (tree);
159 static tree get_class_ivars (tree, int);
160 static void generate_ivar_lists (void);
161 static void generate_dispatch_tables (void);
162 static void generate_shared_structures (void);
163 static tree generate_protocol_list (tree);
164 static void generate_forward_declaration_to_string_table (void);
165 static void build_protocol_reference (tree);
167 static tree build_keyword_selector (tree);
168 static tree synth_id_with_class_suffix (const char *, tree);
170 static void generate_static_references (void);
171 static int check_methods_accessible (tree, tree, int);
172 static void encode_aggregate_within (tree, int, int, int, int);
173 static const char *objc_demangle (const char *);
174 static void objc_expand_function_end (void);
176 /* Hash tables to manage the global pool of method prototypes. */
178 hash *nst_method_hash_list = 0;
179 hash *cls_method_hash_list = 0;
181 static size_t hash_func (tree);
182 static void hash_init (void);
183 static void hash_enter (hash *, tree);
184 static hash hash_lookup (hash *, tree);
185 static void hash_add_attr (hash, tree);
186 static tree lookup_method (tree, tree);
187 static tree lookup_method_static (tree, tree, int);
188 static void add_method_to_hash_list (hash *, tree);
189 static tree add_class (tree);
190 static void add_category (tree, tree);
191 static inline tree lookup_category (tree, tree);
193 enum string_section
195 class_names, /* class, category, protocol, module names */
196 meth_var_names, /* method and variable names */
197 meth_var_types /* method and variable type descriptors */
200 static tree add_objc_string (tree, enum string_section);
201 static tree get_objc_string_decl (tree, enum string_section);
202 static tree build_objc_string_decl (enum string_section);
203 static tree build_selector_reference_decl (void);
205 /* Protocol additions. */
207 static tree add_protocol (tree);
208 static tree lookup_protocol (tree);
209 static void check_protocol_recursively (tree, tree);
210 static tree lookup_and_install_protocols (tree);
212 /* Type encoding. */
214 static void encode_type_qualifiers (tree);
215 static void encode_pointer (tree, int, int);
216 static void encode_array (tree, int, int);
217 static void encode_aggregate (tree, int, int);
218 static void encode_next_bitfield (int);
219 static void encode_gnu_bitfield (int, tree, int);
220 static void encode_type (tree, int, int);
221 static void encode_field_decl (tree, int, int);
223 static void really_start_method (tree, tree);
224 static int comp_method_with_proto (tree, tree);
225 static int objc_types_are_equivalent (tree, tree);
226 static int comp_proto_with_proto (tree, tree);
227 static tree get_arg_type_list (tree, int, int);
228 static tree objc_expr_last (tree);
229 static void synth_self_and_ucmd_args (void);
231 /* Utilities for debugging and error diagnostics. */
233 static void warn_with_method (const char *, int, tree);
234 static void error_with_ivar (const char *, tree, tree);
235 static char *gen_method_decl (tree, char *);
236 static char *gen_declaration (tree, char *);
237 static void gen_declaration_1 (tree, char *);
238 static char *gen_declarator (tree, char *, const char *);
239 static int is_complex_decl (tree);
240 static void adorn_decl (tree, char *);
241 static void dump_interface (FILE *, tree);
243 /* Everything else. */
245 static tree define_decl (tree, tree);
246 static tree lookup_method_in_protocol_list (tree, tree, int);
247 static tree lookup_protocol_in_reflist (tree, tree);
248 static tree create_builtin_decl (enum tree_code, tree, const char *);
249 static void setup_string_decl (void);
250 static int check_string_class_template (void);
251 static tree my_build_string (int, const char *);
252 static void build_objc_symtab_template (void);
253 static tree init_def_list (tree);
254 static tree init_objc_symtab (tree);
255 static tree build_metadata_decl (const char *, tree);
256 static void forward_declare_categories (void);
257 static void generate_objc_symtab_decl (void);
258 static tree build_selector (tree);
259 static tree build_typed_selector_reference (tree, tree);
260 static tree build_selector_reference (tree);
261 static tree build_class_reference_decl (void);
262 static void add_class_reference (tree);
263 static tree build_protocol_template (void);
264 static tree build_descriptor_table_initializer (tree, tree);
265 static tree build_method_prototype_list_template (tree, int);
266 static tree build_method_prototype_template (void);
267 static tree objc_method_parm_type (tree);
268 static int objc_encoded_type_size (tree);
269 static tree encode_method_prototype (tree);
270 static tree generate_descriptor_table (tree, const char *, int, tree, tree);
271 static void generate_method_descriptors (tree);
272 static void generate_protocol_references (tree);
273 static void generate_protocols (void);
274 static void check_ivars (tree, tree);
275 static tree build_ivar_list_template (tree, int);
276 static tree build_method_list_template (tree, int);
277 static tree build_ivar_list_initializer (tree, tree);
278 static tree generate_ivars_list (tree, const char *, int, tree);
279 static tree build_dispatch_table_initializer (tree, tree);
280 static tree generate_dispatch_table (tree, const char *, int, tree);
281 static tree build_shared_structure_initializer (tree, tree, tree, tree,
282 tree, int, tree, tree, tree);
283 static void generate_category (tree);
284 static int is_objc_type_qualifier (tree);
285 static tree adjust_type_for_id_default (tree);
286 static tree check_duplicates (hash, int, int);
287 static tree receiver_is_class_object (tree, int, int);
288 static int check_methods (tree, tree, int);
289 static int conforms_to_protocol (tree, tree);
290 static void check_protocol (tree, const char *, const char *);
291 static void check_protocols (tree, const char *, const char *);
292 static void gen_declspecs (tree, char *, int);
293 static void generate_classref_translation_entry (tree);
294 static void handle_class_ref (tree);
295 static void generate_struct_by_value_array (void)
296 ATTRIBUTE_NORETURN;
297 static void mark_referenced_methods (void);
298 static void generate_objc_image_info (void);
300 /*** Private Interface (data) ***/
302 /* Reserved tag definitions. */
304 #define TYPE_ID "id"
305 #define TAG_OBJECT "objc_object"
306 #define TAG_CLASS "objc_class"
307 #define TAG_SUPER "objc_super"
308 #define TAG_SELECTOR "objc_selector"
310 #define UTAG_CLASS "_objc_class"
311 #define UTAG_IVAR "_objc_ivar"
312 #define UTAG_IVAR_LIST "_objc_ivar_list"
313 #define UTAG_METHOD "_objc_method"
314 #define UTAG_METHOD_LIST "_objc_method_list"
315 #define UTAG_CATEGORY "_objc_category"
316 #define UTAG_MODULE "_objc_module"
317 #define UTAG_SYMTAB "_objc_symtab"
318 #define UTAG_SUPER "_objc_super"
319 #define UTAG_SELECTOR "_objc_selector"
321 #define UTAG_PROTOCOL "_objc_protocol"
322 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
323 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
325 /* Note that the string object global name is only needed for the
326 NeXT runtime. */
327 #define STRING_OBJECT_GLOBAL_FORMAT "_%sClassReference"
329 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
331 static const char *TAG_GETCLASS;
332 static const char *TAG_GETMETACLASS;
333 static const char *TAG_MSGSEND;
334 static const char *TAG_MSGSENDSUPER;
335 /* The NeXT Objective-C messenger may have two extra entry points, for use
336 when returning a structure. */
337 static const char *TAG_MSGSEND_STRET;
338 static const char *TAG_MSGSENDSUPER_STRET;
339 static const char *TAG_EXECCLASS;
340 static const char *default_constant_string_class_name;
342 /* Runtime metadata flags. */
343 #define CLS_FACTORY 0x0001L
344 #define CLS_META 0x0002L
346 #define OBJC_MODIFIER_STATIC 0x00000001
347 #define OBJC_MODIFIER_FINAL 0x00000002
348 #define OBJC_MODIFIER_PUBLIC 0x00000004
349 #define OBJC_MODIFIER_PRIVATE 0x00000008
350 #define OBJC_MODIFIER_PROTECTED 0x00000010
351 #define OBJC_MODIFIER_NATIVE 0x00000020
352 #define OBJC_MODIFIER_SYNCHRONIZED 0x00000040
353 #define OBJC_MODIFIER_ABSTRACT 0x00000080
354 #define OBJC_MODIFIER_VOLATILE 0x00000100
355 #define OBJC_MODIFIER_TRANSIENT 0x00000200
356 #define OBJC_MODIFIER_NONE_SPECIFIED 0x80000000
358 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
359 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
360 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
361 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
362 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
363 #define TAG_EXCEPTIONMATCH "objc_exception_match"
364 #define TAG_EXCEPTIONTHROW "objc_exception_throw"
365 #define TAG_SYNCENTER "objc_sync_enter"
366 #define TAG_SYNCEXIT "objc_sync_exit"
367 #define TAG_SETJMP "_setjmp"
368 #define TAG_RETURN_STRUCT "objc_return_struct"
370 #define UTAG_EXCDATA "_objc_exception_data"
371 #define UTAG_EXCDATA_VAR "_stackExceptionData"
372 #define UTAG_CAUGHTEXC_VAR "_caughtException"
373 #define UTAG_RETHROWEXC_VAR "_rethrowException"
374 #define UTAG_EVALONCE_VAR "_eval_once"
376 struct val_stack {
377 long val;
378 struct val_stack *next;
380 static struct val_stack *catch_count_stack, *exc_binding_stack;
382 /* useful for debugging */
383 static int if_nesting_count;
384 static int blk_nesting_count;
386 static void val_stack_push (struct val_stack **, long);
387 static void val_stack_pop (struct val_stack **);
389 /* The OCTI_... enumeration itself is in objc/objc-act.h. */
390 tree objc_global_trees[OCTI_MAX];
392 static void handle_impent (struct imp_entry *);
394 struct imp_entry *imp_list = 0;
395 int imp_count = 0; /* `@implementation' */
396 int cat_count = 0; /* `@category' */
398 /* Use to generate method labels. */
399 static int method_slot = 0;
401 #define BUFSIZE 1024
403 static char *errbuf; /* Buffer for error diagnostics */
405 /* Data imported from tree.c. */
407 extern enum debug_info_type write_symbols;
409 /* Data imported from toplev.c. */
411 extern const char *dump_base_name;
413 static int flag_typed_selectors;
415 FILE *gen_declaration_file;
417 /* Tells "encode_pointer/encode_aggregate" whether we are generating
418 type descriptors for instance variables (as opposed to methods).
419 Type descriptors for instance variables contain more information
420 than methods (for static typing and embedded structures). */
422 static int generating_instance_variables = 0;
424 /* Some platforms pass small structures through registers versus
425 through an invisible pointer. Determine at what size structure is
426 the transition point between the two possibilities. */
428 static void
429 generate_struct_by_value_array (void)
431 tree type;
432 tree field_decl, field_decl_chain;
433 int i, j;
434 int aggregate_in_mem[32];
435 int found = 0;
437 /* Presumably no platform passes 32 byte structures in a register. */
438 for (i = 1; i < 32; i++)
440 char buffer[5];
442 /* Create an unnamed struct that has `i' character components */
443 type = start_struct (RECORD_TYPE, NULL_TREE);
445 strcpy (buffer, "c1");
446 field_decl = create_builtin_decl (FIELD_DECL,
447 char_type_node,
448 buffer);
449 field_decl_chain = field_decl;
451 for (j = 1; j < i; j++)
453 sprintf (buffer, "c%d", j + 1);
454 field_decl = create_builtin_decl (FIELD_DECL,
455 char_type_node,
456 buffer);
457 chainon (field_decl_chain, field_decl);
459 finish_struct (type, field_decl_chain, NULL_TREE);
461 aggregate_in_mem[i] = aggregate_value_p (type, 0);
462 if (!aggregate_in_mem[i])
463 found = 1;
466 /* We found some structures that are returned in registers instead of memory
467 so output the necessary data. */
468 if (found)
470 for (i = 31; i >= 0; i--)
471 if (!aggregate_in_mem[i])
472 break;
473 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
475 /* The first member of the structure is always 0 because we don't handle
476 structures with 0 members */
477 printf ("static int struct_forward_array[] = {\n 0");
479 for (j = 1; j <= i; j++)
480 printf (", %d", aggregate_in_mem[j]);
481 printf ("\n};\n");
484 exit (0);
487 bool
488 objc_init (void)
490 if (c_objc_common_init () == false)
491 return false;
493 /* Force the line number back to 0; check_newline will have
494 raised it to 1, which will make the builtin functions appear
495 not to be built in. */
496 input_line = 0;
498 /* If gen_declaration desired, open the output file. */
499 if (flag_gen_declaration)
501 register char * const dumpname = concat (dump_base_name, ".decl", NULL);
502 gen_declaration_file = fopen (dumpname, "w");
503 if (gen_declaration_file == 0)
504 fatal_error ("can't open %s: %m", dumpname);
505 free (dumpname);
508 if (flag_next_runtime)
510 TAG_GETCLASS = "objc_getClass";
511 TAG_GETMETACLASS = "objc_getMetaClass";
512 TAG_MSGSEND = "objc_msgSend";
513 TAG_MSGSENDSUPER = "objc_msgSendSuper";
514 TAG_MSGSEND_STRET = "objc_msgSend_stret";
515 TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
516 TAG_EXECCLASS = "__objc_execClass";
517 default_constant_string_class_name = "NSConstantString";
519 else
521 TAG_GETCLASS = "objc_get_class";
522 TAG_GETMETACLASS = "objc_get_meta_class";
523 TAG_MSGSEND = "objc_msg_lookup";
524 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
525 /* GNU runtime does not provide special functions to support
526 structure-returning methods. */
527 TAG_EXECCLASS = "__objc_exec_class";
528 default_constant_string_class_name = "NXConstantString";
529 flag_typed_selectors = 1;
532 objc_ellipsis_node = make_node (ERROR_MARK);
534 init_objc ();
536 if (print_struct_values)
537 generate_struct_by_value_array ();
539 return true;
542 void
543 finish_file (void)
545 mark_referenced_methods ();
546 c_objc_common_finish_file ();
548 /* Finalize Objective-C runtime data. No need to generate tables
549 and code if only checking syntax. */
550 if (!flag_syntax_only)
551 finish_objc ();
553 if (gen_declaration_file)
554 fclose (gen_declaration_file);
557 static tree
558 define_decl (tree declarator, tree declspecs)
560 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
561 finish_decl (decl, NULL_TREE, NULL_TREE);
562 return decl;
565 static tree
566 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
567 int class_meth)
569 tree rproto, p;
570 tree fnd = 0;
572 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
574 p = TREE_VALUE (rproto);
576 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
578 if ((fnd = lookup_method (class_meth
579 ? PROTOCOL_CLS_METHODS (p)
580 : PROTOCOL_NST_METHODS (p), sel_name)))
582 else if (PROTOCOL_LIST (p))
583 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
584 sel_name, class_meth);
586 else
588 ; /* An identifier...if we could not find a protocol. */
591 if (fnd)
592 return fnd;
595 return 0;
598 static tree
599 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
601 tree rproto, p;
603 /* Make sure the protocol is supported by the object on the rhs. */
604 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
606 tree fnd = 0;
607 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
609 p = TREE_VALUE (rproto);
611 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
613 if (lproto == p)
614 fnd = lproto;
616 else if (PROTOCOL_LIST (p))
617 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
620 if (fnd)
621 return fnd;
624 else
626 ; /* An identifier...if we could not find a protocol. */
629 return 0;
632 /* Return 1 if LHS and RHS are compatible types for assignment or
633 various other operations. Return 0 if they are incompatible, and
634 return -1 if we choose to not decide (because the types are really
635 just C types, not ObjC specific ones). When the operation is
636 REFLEXIVE (typically comparisons), check for compatibility in
637 either direction; when it's not (typically assignments), don't.
639 This function is called in two cases: when both lhs and rhs are
640 pointers to records (in which case we check protocols too), and
641 when both lhs and rhs are records (in which case we check class
642 inheritance only).
644 Warnings about classes/protocols not implementing a protocol are
645 emitted here (multiple of those warnings might be emitted for a
646 single line!); generic warnings about incompatible assignments and
647 lacks of casts in comparisons are/must be emitted by the caller if
648 we return 0.
652 objc_comptypes (tree lhs, tree rhs, int reflexive)
654 /* New clause for protocols. */
656 /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE. We only
657 manage the ObjC ones, and leave the rest to the C code. */
658 if (TREE_CODE (lhs) == POINTER_TYPE
659 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
660 && TREE_CODE (rhs) == POINTER_TYPE
661 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
663 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
664 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
666 if (lhs_is_proto)
668 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
669 tree rproto, rproto_list;
670 tree p;
672 /* <Protocol> = <Protocol> */
673 if (rhs_is_proto)
675 rproto_list = TYPE_PROTOCOL_LIST (rhs);
677 if (!reflexive)
679 /* An assignment between objects of type 'id
680 <Protocol>'; make sure the protocol on the lhs is
681 supported by the object on the rhs. */
682 for (lproto = lproto_list; lproto;
683 lproto = TREE_CHAIN (lproto))
685 p = TREE_VALUE (lproto);
686 rproto = lookup_protocol_in_reflist (rproto_list, p);
688 if (!rproto)
689 warning
690 ("object does not conform to the `%s' protocol",
691 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
693 return 1;
695 else
697 /* Obscure case - a comparison between two objects
698 of type 'id <Protocol>'. Check that either the
699 protocol on the lhs is supported by the object on
700 the rhs, or viceversa. */
702 /* Check if the protocol on the lhs is supported by the
703 object on the rhs. */
704 for (lproto = lproto_list; lproto;
705 lproto = TREE_CHAIN (lproto))
707 p = TREE_VALUE (lproto);
708 rproto = lookup_protocol_in_reflist (rproto_list, p);
710 if (!rproto)
712 /* Check failed - check if the protocol on the rhs
713 is supported by the object on the lhs. */
714 for (rproto = rproto_list; rproto;
715 rproto = TREE_CHAIN (rproto))
717 p = TREE_VALUE (rproto);
718 lproto = lookup_protocol_in_reflist (lproto_list,
721 if (!lproto)
723 /* This check failed too: incompatible */
724 return 0;
727 return 1;
730 return 1;
733 /* <Protocol> = <class> * */
734 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
736 tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
737 tree rinter;
739 /* Make sure the protocol is supported by the object on
740 the rhs. */
741 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
743 p = TREE_VALUE (lproto);
744 rproto = 0;
745 rinter = lookup_interface (rname);
747 while (rinter && !rproto)
749 tree cat;
751 rproto_list = CLASS_PROTOCOL_LIST (rinter);
752 rproto = lookup_protocol_in_reflist (rproto_list, p);
753 /* If the underlying ObjC class does not have
754 the protocol we're looking for, check for "one-off"
755 protocols (e.g., `NSObject<MyProt> *foo;') attached
756 to the rhs. */
757 if (!rproto)
759 rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
760 rproto = lookup_protocol_in_reflist (rproto_list, p);
763 /* Check for protocols adopted by categories. */
764 cat = CLASS_CATEGORY_LIST (rinter);
765 while (cat && !rproto)
767 rproto_list = CLASS_PROTOCOL_LIST (cat);
768 rproto = lookup_protocol_in_reflist (rproto_list, p);
769 cat = CLASS_CATEGORY_LIST (cat);
772 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
775 if (!rproto)
776 warning ("class `%s' does not implement the `%s' protocol",
777 IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
778 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
780 return 1;
782 /* <Protocol> = id */
783 else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
785 return 1;
787 /* <Protocol> = Class */
788 else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
790 return 0;
792 /* <Protocol> = ?? : let comptypes decide. */
793 return -1;
795 else if (rhs_is_proto)
797 /* <class> * = <Protocol> */
798 if (TYPED_OBJECT (TREE_TYPE (lhs)))
800 if (reflexive)
802 tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
803 tree rinter;
804 tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
806 /* Make sure the protocol is supported by the object on
807 the lhs. */
808 for (rproto = rproto_list; rproto;
809 rproto = TREE_CHAIN (rproto))
811 tree p = TREE_VALUE (rproto);
812 tree lproto = 0;
813 rinter = lookup_interface (rname);
815 while (rinter && !lproto)
817 tree cat;
819 tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
820 lproto = lookup_protocol_in_reflist (lproto_list, p);
821 /* If the underlying ObjC class does not
822 have the protocol we're looking for,
823 check for "one-off" protocols (e.g.,
824 `NSObject<MyProt> *foo;') attached to the
825 lhs. */
826 if (!lproto)
828 lproto_list = TYPE_PROTOCOL_LIST
829 (TREE_TYPE (lhs));
830 lproto = lookup_protocol_in_reflist
831 (lproto_list, p);
834 /* Check for protocols adopted by categories. */
835 cat = CLASS_CATEGORY_LIST (rinter);
836 while (cat && !lproto)
838 lproto_list = CLASS_PROTOCOL_LIST (cat);
839 lproto = lookup_protocol_in_reflist (lproto_list,
841 cat = CLASS_CATEGORY_LIST (cat);
844 rinter = lookup_interface (CLASS_SUPER_NAME
845 (rinter));
848 if (!lproto)
849 warning ("class `%s' does not implement the `%s' protocol",
850 IDENTIFIER_POINTER (OBJC_TYPE_NAME
851 (TREE_TYPE (lhs))),
852 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
854 return 1;
856 else
857 return 0;
859 /* id = <Protocol> */
860 else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
862 return 1;
864 /* Class = <Protocol> */
865 else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
867 return 0;
869 /* ??? = <Protocol> : let comptypes decide */
870 else
872 return -1;
875 else
877 /* Attention: we shouldn't defer to comptypes here. One bad
878 side effect would be that we might loose the REFLEXIVE
879 information.
881 lhs = TREE_TYPE (lhs);
882 rhs = TREE_TYPE (rhs);
886 if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
888 /* Nothing to do with ObjC - let immediately comptypes take
889 responsibility for checking. */
890 return -1;
893 /* `id' = `<class> *' `<class> *' = `id': always allow it.
894 Please note that
895 'Object *o = [[Object alloc] init]; falls
896 in the case <class> * = `id'.
898 if ((OBJC_TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
899 || (OBJC_TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
900 return 1;
902 /* `id' = `Class', `Class' = `id' */
904 else if ((OBJC_TYPE_NAME (lhs) == objc_object_id
905 && OBJC_TYPE_NAME (rhs) == objc_class_id)
906 || (OBJC_TYPE_NAME (lhs) == objc_class_id
907 && OBJC_TYPE_NAME (rhs) == objc_object_id))
908 return 1;
910 /* `<class> *' = `<class> *' */
912 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
914 tree lname = OBJC_TYPE_NAME (lhs);
915 tree rname = OBJC_TYPE_NAME (rhs);
916 tree inter;
918 if (lname == rname)
919 return 1;
921 /* If the left hand side is a super class of the right hand side,
922 allow it. */
923 for (inter = lookup_interface (rname); inter;
924 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
925 if (lname == CLASS_SUPER_NAME (inter))
926 return 1;
928 /* Allow the reverse when reflexive. */
929 if (reflexive)
930 for (inter = lookup_interface (lname); inter;
931 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
932 if (rname == CLASS_SUPER_NAME (inter))
933 return 1;
935 return 0;
937 else
938 /* Not an ObjC type - let comptypes do the check. */
939 return -1;
942 /* Called from finish_decl. */
944 void
945 objc_check_decl (tree decl)
947 tree type = TREE_TYPE (decl);
949 if (TREE_CODE (type) != RECORD_TYPE)
950 return;
951 if (TYPE_NAME (type) && (type = is_class_name (TYPE_NAME (type))))
952 error ("statically allocated instance of Objective-C class `%s'",
953 IDENTIFIER_POINTER (type));
956 /* Implement static typing. At this point, we know we have an interface. */
958 tree
959 get_static_reference (tree interface, tree protocols)
961 tree type = xref_tag (RECORD_TYPE, interface);
963 if (protocols)
965 tree t, m = TYPE_MAIN_VARIANT (type);
967 t = copy_node (type);
969 /* Add this type to the chain of variants of TYPE. */
970 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
971 TYPE_NEXT_VARIANT (m) = t;
973 /* Look up protocols and install in lang specific list. Note
974 that the protocol list can have a different lifetime than T! */
975 SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
977 /* This forces a new pointer type to be created later
978 (in build_pointer_type)...so that the new template
979 we just created will actually be used...what a hack! */
980 if (TYPE_POINTER_TO (t))
981 TYPE_POINTER_TO (t) = NULL_TREE;
983 type = t;
986 return type;
989 tree
990 get_object_reference (tree protocols)
992 tree type_decl = lookup_name (objc_id_id);
993 tree type;
995 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
997 type = TREE_TYPE (type_decl);
998 if (TYPE_MAIN_VARIANT (type) != id_type)
999 warning ("unexpected type for `id' (%s)",
1000 gen_declaration (type, errbuf));
1002 else
1004 error ("undefined type `id', please import <objc/objc.h>");
1005 return error_mark_node;
1008 /* This clause creates a new pointer type that is qualified with
1009 the protocol specification...this info is used later to do more
1010 elaborate type checking. */
1012 if (protocols)
1014 tree t, m = TYPE_MAIN_VARIANT (type);
1016 t = copy_node (type);
1018 /* Add this type to the chain of variants of TYPE. */
1019 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1020 TYPE_NEXT_VARIANT (m) = t;
1022 /* Look up protocols...and install in lang specific list */
1023 SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
1025 /* This forces a new pointer type to be created later
1026 (in build_pointer_type)...so that the new template
1027 we just created will actually be used...what a hack! */
1028 if (TYPE_POINTER_TO (t))
1029 TYPE_POINTER_TO (t) = NULL_TREE;
1031 type = t;
1033 return type;
1036 /* Check for circular dependencies in protocols. The arguments are
1037 PROTO, the protocol to check, and LIST, a list of protocol it
1038 conforms to. */
1040 static void
1041 check_protocol_recursively (tree proto, tree list)
1043 tree p;
1045 for (p = list; p; p = TREE_CHAIN (p))
1047 tree pp = TREE_VALUE (p);
1049 if (TREE_CODE (pp) == IDENTIFIER_NODE)
1050 pp = lookup_protocol (pp);
1052 if (pp == proto)
1053 fatal_error ("protocol `%s' has circular dependency",
1054 IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1055 if (pp)
1056 check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1060 /* Look up PROTOCOLS, and return a list of those that are found.
1061 If none are found, return NULL. */
1063 static tree
1064 lookup_and_install_protocols (tree protocols)
1066 tree proto;
1067 tree return_value = NULL_TREE;
1069 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1071 tree ident = TREE_VALUE (proto);
1072 tree p = lookup_protocol (ident);
1074 if (!p)
1075 error ("cannot find protocol declaration for `%s'",
1076 IDENTIFIER_POINTER (ident));
1077 else
1078 return_value = chainon (return_value,
1079 build_tree_list (NULL_TREE, p));
1082 return return_value;
1085 /* Create and push a decl for a built-in external variable or field NAME.
1086 CODE says which.
1087 TYPE is its data type. */
1089 static tree
1090 create_builtin_decl (enum tree_code code, tree type, const char *name)
1092 tree decl = build_decl (code, get_identifier (name), type);
1094 if (code == VAR_DECL)
1096 TREE_STATIC (decl) = 1;
1097 make_decl_rtl (decl, 0);
1098 pushdecl (decl);
1099 DECL_ARTIFICIAL (decl) = 1;
1102 return decl;
1105 /* Find the decl for the constant string class. */
1107 static void
1108 setup_string_decl (void)
1110 if (!string_class_decl)
1112 if (!constant_string_global_id)
1114 char *name;
1115 size_t length;
1116 /* %s in format will provide room for terminating null */
1117 length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1118 + strlen (constant_string_class_name);
1119 name = xmalloc (length);
1120 sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1121 constant_string_class_name);
1122 constant_string_global_id = get_identifier (name);
1124 string_class_decl = lookup_name (constant_string_global_id);
1128 /* Purpose: "play" parser, creating/installing representations
1129 of the declarations that are required by Objective-C.
1131 Model:
1133 type_spec--------->sc_spec
1134 (tree_list) (tree_list)
1137 identifier_node identifier_node */
1139 static void
1140 synth_module_prologue (void)
1142 tree temp_type;
1144 /* Defined in `objc.h' */
1145 objc_object_id = get_identifier (TAG_OBJECT);
1147 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1149 id_type = build_pointer_type (objc_object_reference);
1151 objc_id_id = get_identifier (TYPE_ID);
1152 objc_class_id = get_identifier (TAG_CLASS);
1154 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1155 temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1156 objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
1157 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1158 temp_type));
1160 /* Declare type of selector-objects that represent an operation name. */
1162 if (flag_next_runtime)
1163 /* `struct objc_selector *' */
1164 selector_type
1165 = build_pointer_type (xref_tag (RECORD_TYPE,
1166 get_identifier (TAG_SELECTOR)));
1167 else
1168 /* `const struct objc_selector *' */
1169 selector_type
1170 = build_pointer_type
1171 (build_qualified_type (xref_tag (RECORD_TYPE,
1172 get_identifier (TAG_SELECTOR)),
1173 TYPE_QUAL_CONST));
1175 /* Declare receiver type used for dispatching messages to 'super'. */
1177 /* `struct objc_super *' */
1178 super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1179 get_identifier (TAG_SUPER)));
1181 if (flag_next_runtime)
1183 /* NB: In order to call one of the ..._stret (struct-returning)
1184 functions, the function *MUST* first be cast to a signature that
1185 corresponds to the actual ObjC method being invoked. This is
1186 what is done by the build_objc_method_call() routine below. */
1188 /* id objc_msgSend (id, SEL, ...); */
1189 /* id objc_msgSendNonNil (id, SEL, ...); */
1190 /* id objc_msgSend_stret (id, SEL, ...); */
1191 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1192 temp_type
1193 = build_function_type (id_type,
1194 tree_cons (NULL_TREE, id_type,
1195 tree_cons (NULL_TREE, selector_type,
1196 NULL_TREE)));
1197 umsg_decl = builtin_function (TAG_MSGSEND,
1198 temp_type, 0, NOT_BUILT_IN,
1199 NULL, NULL_TREE);
1200 umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1201 temp_type, 0, NOT_BUILT_IN,
1202 NULL, NULL_TREE);
1203 umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1204 temp_type, 0, NOT_BUILT_IN,
1205 NULL, NULL_TREE);
1206 umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1207 temp_type, 0, NOT_BUILT_IN,
1208 NULL, NULL_TREE);
1210 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1211 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1212 temp_type
1213 = build_function_type (id_type,
1214 tree_cons (NULL_TREE, super_type,
1215 tree_cons (NULL_TREE, selector_type,
1216 NULL_TREE)));
1217 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1218 temp_type, 0, NOT_BUILT_IN,
1219 NULL, NULL_TREE);
1220 umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1221 temp_type, 0, NOT_BUILT_IN, 0,
1222 NULL_TREE);
1224 else
1226 /* GNU runtime messenger entry points. */
1228 /* typedef id (*IMP)(id, SEL, ...); */
1229 tree IMP_type
1230 = build_pointer_type
1231 (build_function_type (id_type,
1232 tree_cons (NULL_TREE, id_type,
1233 tree_cons (NULL_TREE, selector_type,
1234 NULL_TREE))));
1236 /* IMP objc_msg_lookup (id, SEL); */
1237 temp_type
1238 = build_function_type (IMP_type,
1239 tree_cons (NULL_TREE, id_type,
1240 tree_cons (NULL_TREE, selector_type,
1241 OBJC_VOID_AT_END)));
1242 umsg_decl = builtin_function (TAG_MSGSEND,
1243 temp_type, 0, NOT_BUILT_IN,
1244 NULL, NULL_TREE);
1246 /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1247 temp_type
1248 = build_function_type (IMP_type,
1249 tree_cons (NULL_TREE, super_type,
1250 tree_cons (NULL_TREE, selector_type,
1251 OBJC_VOID_AT_END)));
1252 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1253 temp_type, 0, NOT_BUILT_IN,
1254 NULL, NULL_TREE);
1257 /* id objc_getClass (const char *); */
1259 temp_type = build_function_type (id_type,
1260 tree_cons (NULL_TREE,
1261 const_string_type_node,
1262 OBJC_VOID_AT_END));
1264 objc_get_class_decl
1265 = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
1266 NULL, NULL_TREE);
1268 /* id objc_getMetaClass (const char *); */
1270 objc_get_meta_class_decl
1271 = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1273 build_super_template ();
1274 if (flag_next_runtime)
1275 build_objc_exception_stuff ();
1277 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1279 if (! flag_next_runtime)
1281 if (flag_typed_selectors)
1283 /* Suppress outputting debug symbols, because
1284 dbxout_init hasn'r been called yet. */
1285 enum debug_info_type save_write_symbols = write_symbols;
1286 const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1287 write_symbols = NO_DEBUG;
1288 debug_hooks = &do_nothing_debug_hooks;
1290 build_selector_template ();
1291 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1293 write_symbols = save_write_symbols;
1294 debug_hooks = save_hooks;
1296 else
1297 temp_type = build_array_type (selector_type, NULL_TREE);
1299 layout_type (temp_type);
1300 UOBJC_SELECTOR_TABLE_decl
1301 = create_builtin_decl (VAR_DECL, temp_type,
1302 "_OBJC_SELECTOR_TABLE");
1304 /* Avoid warning when not sending messages. */
1305 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1308 generate_forward_declaration_to_string_table ();
1310 /* Forward declare constant_string_id and constant_string_type. */
1311 if (!constant_string_class_name)
1312 constant_string_class_name = default_constant_string_class_name;
1314 constant_string_id = get_identifier (constant_string_class_name);
1315 objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1317 /* Pre-build the following entities - for speed/convenience. */
1318 self_id = get_identifier ("self");
1319 ucmd_id = get_identifier ("_cmd");
1320 #ifndef OBJCPLUS
1321 /* The C++ front-end does not appear to grok __attribute__((__unused__)). */
1322 unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1323 #endif
1326 /* Ensure that the ivar list for NSConstantString/NXConstantString
1327 (or whatever was specified via `-fconstant-string-class')
1328 contains fields at least as large as the following three, so that
1329 the runtime can stomp on them with confidence:
1331 struct STRING_OBJECT_CLASS_NAME
1333 Object isa;
1334 char *cString;
1335 unsigned int length;
1336 }; */
1338 static int
1339 check_string_class_template (void)
1341 tree field_decl = TYPE_FIELDS (constant_string_type);
1343 #define AT_LEAST_AS_LARGE_AS(F, T) \
1344 (F && TREE_CODE (F) == FIELD_DECL \
1345 && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1346 >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1348 if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1349 return 0;
1351 field_decl = TREE_CHAIN (field_decl);
1352 if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1353 return 0;
1355 field_decl = TREE_CHAIN (field_decl);
1356 return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1358 #undef AT_LEAST_AS_LARGE_AS
1361 /* Avoid calling `check_string_class_template ()' more than once. */
1362 static GTY(()) int string_layout_checked;
1364 /* Custom build_string which sets TREE_TYPE! */
1366 static tree
1367 my_build_string (int len, const char *str)
1369 return fix_string_type (build_string (len, str));
1372 /* Given a chain of STRING_CST's, build a static instance of
1373 NXConstantString which points at the concatenation of those
1374 strings. We place the string object in the __string_objects
1375 section of the __OBJC segment. The Objective-C runtime will
1376 initialize the isa pointers of the string objects to point at the
1377 NXConstantString class object. */
1379 tree
1380 build_objc_string_object (tree string)
1382 tree initlist, constructor, constant_string_class;
1383 int length;
1385 string = fix_string_type (string);
1387 constant_string_class = lookup_interface (constant_string_id);
1388 if (!constant_string_class
1389 || !(constant_string_type
1390 = CLASS_STATIC_TEMPLATE (constant_string_class)))
1392 error ("cannot find interface declaration for `%s'",
1393 IDENTIFIER_POINTER (constant_string_id));
1394 return error_mark_node;
1397 /* Call to 'combine_strings' has been moved above. */
1398 TREE_SET_CODE (string, STRING_CST);
1399 length = TREE_STRING_LENGTH (string) - 1;
1401 if (!string_layout_checked)
1403 /* The NSConstantString/NXConstantString ivar layout is now
1404 known. */
1405 if (!check_string_class_template ())
1407 error ("interface `%s' does not have valid constant string layout",
1408 IDENTIFIER_POINTER (constant_string_id));
1409 return error_mark_node;
1411 add_class_reference (constant_string_id);
1414 /* & ((NXConstantString) { NULL, string, length }) */
1416 if (flag_next_runtime)
1418 /* For the NeXT runtime, we can generate a literal reference
1419 to the string class, don't need to run a constructor. */
1420 setup_string_decl ();
1421 if (string_class_decl == NULL_TREE)
1423 error ("cannot find reference tag for class `%s'",
1424 IDENTIFIER_POINTER (constant_string_id));
1425 return error_mark_node;
1427 initlist = build_tree_list
1428 (NULL_TREE,
1429 copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
1431 else
1433 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1436 initlist
1437 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1438 initlist);
1439 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1440 constructor = objc_build_constructor (constant_string_type,
1441 nreverse (initlist));
1443 if (!flag_next_runtime)
1445 constructor
1446 = objc_add_static_instance (constructor, constant_string_type);
1449 return (build_unary_op (ADDR_EXPR, constructor, 1));
1452 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1454 static GTY(()) int num_static_inst;
1456 static tree
1457 objc_add_static_instance (tree constructor, tree class_decl)
1459 tree *chain, decl;
1460 char buf[256];
1462 /* Find the list of static instances for the CLASS_DECL. Create one if
1463 not found. */
1464 for (chain = &objc_static_instances;
1465 *chain && TREE_VALUE (*chain) != class_decl;
1466 chain = &TREE_CHAIN (*chain));
1467 if (!*chain)
1469 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1470 add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1473 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1474 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1475 DECL_COMMON (decl) = 1;
1476 TREE_STATIC (decl) = 1;
1477 DECL_ARTIFICIAL (decl) = 1;
1478 DECL_INITIAL (decl) = constructor;
1480 /* We may be writing something else just now.
1481 Postpone till end of input. */
1482 DECL_DEFER_OUTPUT (decl) = 1;
1483 pushdecl_top_level (decl);
1484 rest_of_decl_compilation (decl, 0, 1, 0);
1486 /* Add the DECL to the head of this CLASS' list. */
1487 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1489 return decl;
1492 /* Build a static constant CONSTRUCTOR
1493 with type TYPE and elements ELTS. */
1495 static tree
1496 objc_build_constructor (tree type, tree elts)
1498 tree constructor, f, e;
1500 /* ??? Most of the places that we build constructors, we don't fill in
1501 the type of integers properly. Convert them all en masse. */
1502 if (TREE_CODE (type) == ARRAY_TYPE)
1504 f = TREE_TYPE (type);
1505 if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
1506 for (e = elts; e ; e = TREE_CHAIN (e))
1507 TREE_VALUE (e) = convert (f, TREE_VALUE (e));
1509 else
1511 f = TYPE_FIELDS (type);
1512 for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
1513 if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
1514 || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
1515 TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
1518 constructor = build_constructor (type, elts);
1519 TREE_CONSTANT (constructor) = 1;
1520 TREE_STATIC (constructor) = 1;
1521 TREE_READONLY (constructor) = 1;
1523 #ifdef OBJCPLUS
1524 /* zlaski 2001-Apr-02: mark this as a call to a constructor, as required by
1525 build_unary_op (wasn't true in 2.7.2.1 days) */
1526 TREE_HAS_CONSTRUCTOR (constructor) = 1;
1527 #endif
1528 return constructor;
1531 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1533 /* Predefine the following data type:
1535 struct _objc_symtab
1537 long sel_ref_cnt;
1538 SEL *refs;
1539 short cls_def_cnt;
1540 short cat_def_cnt;
1541 void *defs[cls_def_cnt + cat_def_cnt];
1542 }; */
1544 static void
1545 build_objc_symtab_template (void)
1547 tree field_decl, field_decl_chain;
1549 objc_symtab_template
1550 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1552 /* long sel_ref_cnt; */
1554 field_decl = create_builtin_decl (FIELD_DECL,
1555 long_integer_type_node,
1556 "sel_ref_cnt");
1557 field_decl_chain = field_decl;
1559 /* SEL *refs; */
1561 field_decl = create_builtin_decl (FIELD_DECL,
1562 build_pointer_type (selector_type),
1563 "refs");
1564 chainon (field_decl_chain, field_decl);
1566 /* short cls_def_cnt; */
1568 field_decl = create_builtin_decl (FIELD_DECL,
1569 short_integer_type_node,
1570 "cls_def_cnt");
1571 chainon (field_decl_chain, field_decl);
1573 /* short cat_def_cnt; */
1575 field_decl = create_builtin_decl (FIELD_DECL,
1576 short_integer_type_node,
1577 "cat_def_cnt");
1578 chainon (field_decl_chain, field_decl);
1580 if (imp_count || cat_count || !flag_next_runtime)
1582 /* void *defs[imp_count + cat_count (+ 1)]; */
1583 /* NB: The index is one less than the size of the array. */
1584 int index = imp_count + cat_count
1585 + (flag_next_runtime? -1: 0);
1586 field_decl = create_builtin_decl
1587 (FIELD_DECL,
1588 build_array_type
1589 (ptr_type_node,
1590 build_index_type (build_int_2 (index, 0))),
1591 "defs");
1592 chainon (field_decl_chain, field_decl);
1595 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1598 /* Create the initial value for the `defs' field of _objc_symtab.
1599 This is a CONSTRUCTOR. */
1601 static tree
1602 init_def_list (tree type)
1604 tree expr, initlist = NULL_TREE;
1605 struct imp_entry *impent;
1607 if (imp_count)
1608 for (impent = imp_list; impent; impent = impent->next)
1610 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1612 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1613 initlist = tree_cons (NULL_TREE, expr, initlist);
1617 if (cat_count)
1618 for (impent = imp_list; impent; impent = impent->next)
1620 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1622 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1623 initlist = tree_cons (NULL_TREE, expr, initlist);
1627 if (!flag_next_runtime)
1629 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1630 tree expr;
1632 if (static_instances_decl)
1633 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1634 else
1635 expr = build_int_2 (0, 0);
1637 initlist = tree_cons (NULL_TREE, expr, initlist);
1640 return objc_build_constructor (type, nreverse (initlist));
1643 /* Construct the initial value for all of _objc_symtab. */
1645 static tree
1646 init_objc_symtab (tree type)
1648 tree initlist;
1650 /* sel_ref_cnt = { ..., 5, ... } */
1652 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1654 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1656 if (flag_next_runtime || ! sel_ref_chain)
1657 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1658 else
1659 initlist = tree_cons (NULL_TREE,
1660 build_unary_op (ADDR_EXPR,
1661 UOBJC_SELECTOR_TABLE_decl, 1),
1662 initlist);
1664 /* cls_def_cnt = { ..., 5, ... } */
1666 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1668 /* cat_def_cnt = { ..., 5, ... } */
1670 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1672 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1674 if (imp_count || cat_count || !flag_next_runtime)
1677 tree field = TYPE_FIELDS (type);
1678 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1680 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1681 initlist);
1684 return objc_build_constructor (type, nreverse (initlist));
1687 /* Generate forward declarations for metadata such as
1688 'OBJC_CLASS_...'. */
1690 static tree
1691 build_metadata_decl (const char *name, tree type)
1693 tree decl, decl_specs;
1694 /* extern struct TYPE NAME_<name>; */
1695 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
1696 decl_specs = tree_cons (NULL_TREE, type, decl_specs);
1697 decl = define_decl (synth_id_with_class_suffix
1698 (name,
1699 objc_implementation_context),
1700 decl_specs);
1701 TREE_USED (decl) = 1;
1702 DECL_ARTIFICIAL (decl) = 1;
1703 TREE_PUBLIC (decl) = 0;
1704 return decl;
1707 /* Push forward-declarations of all the categories so that
1708 init_def_list can use them in a CONSTRUCTOR. */
1710 static void
1711 forward_declare_categories (void)
1713 struct imp_entry *impent;
1714 tree sav = objc_implementation_context;
1716 for (impent = imp_list; impent; impent = impent->next)
1718 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1720 /* Set an invisible arg to synth_id_with_class_suffix. */
1721 objc_implementation_context = impent->imp_context;
1722 /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1723 impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1724 objc_category_template);
1727 objc_implementation_context = sav;
1730 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1731 and initialized appropriately. */
1733 static void
1734 generate_objc_symtab_decl (void)
1736 tree sc_spec;
1738 if (!objc_category_template)
1739 build_category_template ();
1741 /* forward declare categories */
1742 if (cat_count)
1743 forward_declare_categories ();
1745 if (!objc_symtab_template)
1746 build_objc_symtab_template ();
1748 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1750 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1751 tree_cons (NULL_TREE,
1752 objc_symtab_template, sc_spec),
1754 NULL_TREE);
1756 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1757 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1758 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1759 finish_decl (UOBJC_SYMBOLS_decl,
1760 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1761 NULL_TREE);
1764 static tree
1765 init_module_descriptor (tree type)
1767 tree initlist, expr;
1769 /* version = { 1, ... } */
1771 expr = build_int_2 (OBJC_VERSION, 0);
1772 initlist = build_tree_list (NULL_TREE, expr);
1774 /* size = { ..., sizeof (struct objc_module), ... } */
1776 expr = size_in_bytes (objc_module_template);
1777 initlist = tree_cons (NULL_TREE, expr, initlist);
1779 /* name = { ..., "foo.m", ... } */
1781 expr = add_objc_string (get_identifier (input_filename), class_names);
1782 initlist = tree_cons (NULL_TREE, expr, initlist);
1784 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1786 if (UOBJC_SYMBOLS_decl)
1787 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1788 else
1789 expr = build_int_2 (0, 0);
1790 initlist = tree_cons (NULL_TREE, expr, initlist);
1792 return objc_build_constructor (type, nreverse (initlist));
1795 /* Write out the data structures to describe Objective C classes defined.
1796 If appropriate, compile and output a setup function to initialize them.
1797 Return a symbol_ref to the function to call to initialize the Objective C
1798 data structures for this file (and perhaps for other files also).
1800 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1802 static rtx
1803 build_module_descriptor (void)
1805 tree decl_specs, field_decl, field_decl_chain;
1807 objc_module_template
1808 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1810 /* Long version; */
1812 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1813 field_decl = get_identifier ("version");
1814 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1815 field_decl_chain = field_decl;
1817 /* long size; */
1819 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1820 field_decl = get_identifier ("size");
1821 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1822 chainon (field_decl_chain, field_decl);
1824 /* char *name; */
1826 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1827 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1828 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1829 chainon (field_decl_chain, field_decl);
1831 /* struct objc_symtab *symtab; */
1833 decl_specs = get_identifier (UTAG_SYMTAB);
1834 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1835 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1836 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1837 chainon (field_decl_chain, field_decl);
1839 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1841 /* Create an instance of "objc_module". */
1843 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1844 build_tree_list (NULL_TREE,
1845 ridpointers[(int) RID_STATIC]));
1847 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1848 decl_specs, 1, NULL_TREE);
1850 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1851 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1852 DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
1854 finish_decl (UOBJC_MODULES_decl,
1855 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1856 NULL_TREE);
1858 /* Mark the decl to avoid "defined but not used" warning. */
1859 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1861 /* Generate a constructor call for the module descriptor.
1862 This code was generated by reading the grammar rules
1863 of c-parse.in; Therefore, it may not be the most efficient
1864 way of generating the requisite code. */
1866 if (flag_next_runtime)
1867 return NULL_RTX;
1870 tree parms, execclass_decl, decelerator, void_list_node_1;
1871 tree init_function_name, init_function_decl;
1873 /* Declare void __objc_execClass (void *); */
1875 void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1876 execclass_decl = build_decl (FUNCTION_DECL,
1877 get_identifier (TAG_EXECCLASS),
1878 build_function_type (void_type_node,
1879 tree_cons (NULL_TREE, ptr_type_node,
1880 OBJC_VOID_AT_END)));
1882 DECL_EXTERNAL (execclass_decl) = 1;
1883 DECL_ARTIFICIAL (execclass_decl) = 1;
1884 TREE_PUBLIC (execclass_decl) = 1;
1885 pushdecl (execclass_decl);
1886 rest_of_decl_compilation (execclass_decl, 0, 0, 0);
1887 assemble_external (execclass_decl);
1889 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1891 init_function_name = get_file_function_name ('I');
1892 start_function (void_list_node_1,
1893 build_nt (CALL_EXPR, init_function_name,
1894 tree_cons (NULL_TREE, NULL_TREE,
1895 OBJC_VOID_AT_END),
1896 NULL_TREE),
1897 NULL_TREE);
1898 store_parm_decls ();
1900 init_function_decl = current_function_decl;
1901 TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
1902 TREE_USED (init_function_decl) = 1;
1903 /* Don't let this one be deferred. */
1904 DECL_INLINE (init_function_decl) = 0;
1905 DECL_UNINLINABLE (init_function_decl) = 1;
1906 current_function_cannot_inline
1907 = "static constructors and destructors cannot be inlined";
1909 parms
1910 = build_tree_list (NULL_TREE,
1911 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1912 decelerator = build_function_call (execclass_decl, parms);
1914 c_expand_expr_stmt (decelerator);
1916 finish_function ();
1918 return XEXP (DECL_RTL (init_function_decl), 0);
1922 /* extern const char _OBJC_STRINGS[]; */
1924 static void
1925 generate_forward_declaration_to_string_table (void)
1927 tree sc_spec, decl_specs, expr_decl;
1929 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1930 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1932 expr_decl
1933 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1935 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1938 /* Return the DECL of the string IDENT in the SECTION. */
1940 static tree
1941 get_objc_string_decl (tree ident, enum string_section section)
1943 tree chain;
1945 if (section == class_names)
1946 chain = class_names_chain;
1947 else if (section == meth_var_names)
1948 chain = meth_var_names_chain;
1949 else if (section == meth_var_types)
1950 chain = meth_var_types_chain;
1951 else
1952 abort ();
1954 for (; chain != 0; chain = TREE_CHAIN (chain))
1955 if (TREE_VALUE (chain) == ident)
1956 return (TREE_PURPOSE (chain));
1958 abort ();
1959 return NULL_TREE;
1962 /* Output references to all statically allocated objects. Return the DECL
1963 for the array built. */
1965 static void
1966 generate_static_references (void)
1968 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1969 tree class_name, class, decl, initlist;
1970 tree cl_chain, in_chain, type;
1971 int num_inst, num_class;
1972 char buf[256];
1974 if (flag_next_runtime)
1975 abort ();
1977 for (cl_chain = objc_static_instances, num_class = 0;
1978 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1980 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1981 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1983 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1984 ident = get_identifier (buf);
1986 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1987 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1988 build_tree_list (NULL_TREE,
1989 ridpointers[(int) RID_STATIC]));
1990 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
1991 DECL_CONTEXT (decl) = 0;
1992 DECL_ARTIFICIAL (decl) = 1;
1994 /* Output {class_name, ...}. */
1995 class = TREE_VALUE (cl_chain);
1996 class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
1997 initlist = build_tree_list (NULL_TREE,
1998 build_unary_op (ADDR_EXPR, class_name, 1));
2000 /* Output {..., instance, ...}. */
2001 for (in_chain = TREE_PURPOSE (cl_chain);
2002 in_chain; in_chain = TREE_CHAIN (in_chain))
2004 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2005 initlist = tree_cons (NULL_TREE, expr, initlist);
2008 /* Output {..., NULL}. */
2009 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2011 expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2012 finish_decl (decl, expr, NULL_TREE);
2013 TREE_USED (decl) = 1;
2015 type = build_array_type (build_pointer_type (void_type_node), 0);
2016 decl = build_decl (VAR_DECL, ident, type);
2017 TREE_USED (decl) = 1;
2018 TREE_STATIC (decl) = 1;
2019 decls
2020 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2023 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
2024 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
2025 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
2026 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
2027 build_tree_list (NULL_TREE,
2028 ridpointers[(int) RID_STATIC]));
2029 static_instances_decl
2030 = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
2031 TREE_USED (static_instances_decl) = 1;
2032 DECL_CONTEXT (static_instances_decl) = 0;
2033 DECL_ARTIFICIAL (static_instances_decl) = 1;
2034 expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
2035 nreverse (decls));
2036 finish_decl (static_instances_decl, expr, NULL_TREE);
2039 /* Output all strings. */
2041 static void
2042 generate_strings (void)
2044 tree sc_spec, decl_specs, expr_decl;
2045 tree chain, string_expr;
2046 tree string, decl;
2048 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2050 string = TREE_VALUE (chain);
2051 decl = TREE_PURPOSE (chain);
2052 sc_spec
2053 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2054 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2055 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2056 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2057 DECL_CONTEXT (decl) = NULL_TREE;
2058 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2059 IDENTIFIER_POINTER (string));
2060 finish_decl (decl, string_expr, NULL_TREE);
2063 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2065 string = TREE_VALUE (chain);
2066 decl = TREE_PURPOSE (chain);
2067 sc_spec
2068 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2069 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2070 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2071 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2072 DECL_CONTEXT (decl) = NULL_TREE;
2073 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2074 IDENTIFIER_POINTER (string));
2075 finish_decl (decl, string_expr, NULL_TREE);
2078 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2080 string = TREE_VALUE (chain);
2081 decl = TREE_PURPOSE (chain);
2082 sc_spec
2083 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2084 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2085 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2086 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2087 DECL_CONTEXT (decl) = NULL_TREE;
2088 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2089 IDENTIFIER_POINTER (string));
2090 finish_decl (decl, string_expr, NULL_TREE);
2094 static GTY(()) int selector_reference_idx;
2096 static tree
2097 build_selector_reference_decl (void)
2099 tree decl, ident;
2100 char buf[256];
2102 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2104 ident = get_identifier (buf);
2106 decl = build_decl (VAR_DECL, ident, selector_type);
2107 DECL_EXTERNAL (decl) = 1;
2108 TREE_PUBLIC (decl) = 0;
2109 TREE_USED (decl) = 1;
2110 DECL_ARTIFICIAL (decl) = 1;
2111 DECL_CONTEXT (decl) = 0;
2113 make_decl_rtl (decl, 0);
2114 pushdecl_top_level (decl);
2116 return decl;
2119 /* Just a handy wrapper for add_objc_string. */
2121 static tree
2122 build_selector (tree ident)
2124 tree expr = add_objc_string (ident, meth_var_names);
2125 if (flag_typed_selectors)
2126 return expr;
2127 else
2128 return build_c_cast (selector_type, expr); /* cast! */
2131 static void
2132 build_selector_translation_table (void)
2134 tree sc_spec, decl_specs;
2135 tree chain, initlist = NULL_TREE;
2136 int offset = 0;
2137 tree decl = NULL_TREE, var_decl, name;
2139 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2141 tree expr;
2143 if (warn_selector && objc_implementation_context)
2145 tree method_chain;
2146 bool found = false;
2147 for (method_chain = meth_var_names_chain;
2148 method_chain;
2149 method_chain = TREE_CHAIN (method_chain))
2151 if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2153 found = true;
2154 break;
2157 if (!found)
2159 /* Adjust line number for warning message. */
2160 int save_lineno = input_line;
2161 if (flag_next_runtime && TREE_PURPOSE (chain))
2162 input_line = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
2163 warning ("creating selector for non existant method %s",
2164 IDENTIFIER_POINTER (TREE_VALUE (chain)));
2165 input_line = save_lineno;
2169 expr = build_selector (TREE_VALUE (chain));
2171 if (flag_next_runtime)
2173 name = DECL_NAME (TREE_PURPOSE (chain));
2175 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2177 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2178 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2180 var_decl = name;
2182 /* The `decl' that is returned from start_decl is the one that we
2183 forward declared in `build_selector_reference' */
2184 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
2187 /* add one for the '\0' character */
2188 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2190 if (flag_next_runtime)
2191 finish_decl (decl, expr, NULL_TREE);
2192 else
2194 if (flag_typed_selectors)
2196 tree eltlist = NULL_TREE;
2197 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2198 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2199 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2200 expr = objc_build_constructor (objc_selector_template,
2201 nreverse (eltlist));
2203 initlist = tree_cons (NULL_TREE, expr, initlist);
2208 if (! flag_next_runtime)
2210 /* Cause the variable and its initial value to be actually output. */
2211 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2212 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2213 /* NULL terminate the list and fix the decl for output. */
2214 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2215 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
2216 initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2217 nreverse (initlist));
2218 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2219 current_function_decl = NULL_TREE;
2223 static tree
2224 get_proto_encoding (tree proto)
2226 tree encoding;
2227 if (proto)
2229 if (! METHOD_ENCODING (proto))
2231 encoding = encode_method_prototype (proto);
2232 METHOD_ENCODING (proto) = encoding;
2234 else
2235 encoding = METHOD_ENCODING (proto);
2237 return add_objc_string (encoding, meth_var_types);
2239 else
2240 return build_int_2 (0, 0);
2243 /* sel_ref_chain is a list whose "value" fields will be instances of
2244 identifier_node that represent the selector. */
2246 static tree
2247 build_typed_selector_reference (tree ident, tree prototype)
2249 tree *chain = &sel_ref_chain;
2250 tree expr;
2251 int index = 0;
2253 while (*chain)
2255 if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2256 goto return_at_index;
2258 index++;
2259 chain = &TREE_CHAIN (*chain);
2262 *chain = tree_cons (prototype, ident, NULL_TREE);
2264 return_at_index:
2265 expr = build_unary_op (ADDR_EXPR,
2266 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2267 build_int_2 (index, 0)),
2269 return build_c_cast (selector_type, expr);
2272 static tree
2273 build_selector_reference (tree ident)
2275 tree *chain = &sel_ref_chain;
2276 tree expr;
2277 int index = 0;
2279 while (*chain)
2281 if (TREE_VALUE (*chain) == ident)
2282 return (flag_next_runtime
2283 ? TREE_PURPOSE (*chain)
2284 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2285 build_int_2 (index, 0)));
2287 index++;
2288 chain = &TREE_CHAIN (*chain);
2291 expr = build_selector_reference_decl ();
2293 *chain = tree_cons (expr, ident, NULL_TREE);
2295 return (flag_next_runtime
2296 ? expr
2297 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2298 build_int_2 (index, 0)));
2301 static GTY(()) int class_reference_idx;
2303 static tree
2304 build_class_reference_decl (void)
2306 tree decl, ident;
2307 char buf[256];
2309 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2311 ident = get_identifier (buf);
2313 decl = build_decl (VAR_DECL, ident, objc_class_type);
2314 DECL_EXTERNAL (decl) = 1;
2315 TREE_PUBLIC (decl) = 0;
2316 TREE_USED (decl) = 1;
2317 DECL_CONTEXT (decl) = 0;
2318 DECL_ARTIFICIAL (decl) = 1;
2320 make_decl_rtl (decl, 0);
2321 pushdecl_top_level (decl);
2323 return decl;
2326 /* Create a class reference, but don't create a variable to reference
2327 it. */
2329 static void
2330 add_class_reference (tree ident)
2332 tree chain;
2334 if ((chain = cls_ref_chain))
2336 tree tail;
2339 if (ident == TREE_VALUE (chain))
2340 return;
2342 tail = chain;
2343 chain = TREE_CHAIN (chain);
2345 while (chain);
2347 /* Append to the end of the list */
2348 TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2350 else
2351 cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2354 /* Get a class reference, creating it if necessary. Also create the
2355 reference variable. */
2357 tree
2358 get_class_reference (tree ident)
2360 tree orig_ident;
2362 #ifdef OBJCPLUS
2363 if (processing_template_decl)
2364 /* Must wait until template instantiation time. */
2365 return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2366 if (TREE_CODE (ident) == TYPE_DECL)
2367 ident = DECL_NAME (ident);
2368 #endif
2369 orig_ident = ident;
2371 if (!(ident = is_class_name (ident)))
2373 error ("`%s' is not an Objective-C class name or alias",
2374 IDENTIFIER_POINTER (orig_ident));
2375 return error_mark_node;
2378 if (flag_next_runtime && !flag_zero_link)
2380 tree *chain;
2381 tree decl;
2383 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2384 if (TREE_VALUE (*chain) == ident)
2386 if (! TREE_PURPOSE (*chain))
2387 TREE_PURPOSE (*chain) = build_class_reference_decl ();
2389 return TREE_PURPOSE (*chain);
2392 decl = build_class_reference_decl ();
2393 *chain = tree_cons (decl, ident, NULL_TREE);
2394 return decl;
2396 else
2398 tree params;
2400 add_class_reference (ident);
2402 params = build_tree_list (NULL_TREE,
2403 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2404 IDENTIFIER_POINTER (ident)));
2406 assemble_external (objc_get_class_decl);
2407 return build_function_call (objc_get_class_decl, params);
2411 /* For each string section we have a chain which maps identifier nodes
2412 to decls for the strings. */
2414 static tree
2415 add_objc_string (tree ident, enum string_section section)
2417 tree *chain, decl;
2419 if (section == class_names)
2420 chain = &class_names_chain;
2421 else if (section == meth_var_names)
2422 chain = &meth_var_names_chain;
2423 else if (section == meth_var_types)
2424 chain = &meth_var_types_chain;
2425 else
2426 abort ();
2428 while (*chain)
2430 if (TREE_VALUE (*chain) == ident)
2431 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2433 chain = &TREE_CHAIN (*chain);
2436 decl = build_objc_string_decl (section);
2438 *chain = tree_cons (decl, ident, NULL_TREE);
2440 return build_unary_op (ADDR_EXPR, decl, 1);
2443 static GTY(()) int class_names_idx;
2444 static GTY(()) int meth_var_names_idx;
2445 static GTY(()) int meth_var_types_idx;
2447 static tree
2448 build_objc_string_decl (enum string_section section)
2450 tree decl, ident;
2451 char buf[256];
2453 if (section == class_names)
2454 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2455 else if (section == meth_var_names)
2456 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2457 else if (section == meth_var_types)
2458 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2460 ident = get_identifier (buf);
2462 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2463 DECL_EXTERNAL (decl) = 1;
2464 TREE_PUBLIC (decl) = 0;
2465 TREE_USED (decl) = 1;
2466 TREE_CONSTANT (decl) = 1;
2467 DECL_CONTEXT (decl) = 0;
2468 DECL_ARTIFICIAL (decl) = 1;
2470 make_decl_rtl (decl, 0);
2471 pushdecl_top_level (decl);
2473 return decl;
2477 void
2478 objc_declare_alias (tree alias_ident, tree class_ident)
2480 tree underlying_class;
2482 #ifdef OBJCPLUS
2483 if (current_namespace != global_namespace) {
2484 error ("Objective-C declarations may only appear in global scope");
2486 #endif /* OBJCPLUS */
2488 if (!(underlying_class = is_class_name (class_ident)))
2489 warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2490 else if (is_class_name (alias_ident))
2491 warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2492 else
2493 alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2496 void
2497 objc_declare_class (tree ident_list)
2499 tree list;
2500 #ifdef OBJCPLUS
2501 if (current_namespace != global_namespace) {
2502 error ("Objective-C declarations may only appear in global scope");
2504 #endif /* OBJCPLUS */
2506 for (list = ident_list; list; list = TREE_CHAIN (list))
2508 tree ident = TREE_VALUE (list);
2510 if (! is_class_name (ident))
2512 tree record = lookup_name (ident);
2514 if (record && ! TREE_STATIC_TEMPLATE (record))
2516 error ("`%s' redeclared as different kind of symbol",
2517 IDENTIFIER_POINTER (ident));
2518 error ("%Jprevious declaration of '%D'",
2519 record, record);
2522 record = xref_tag (RECORD_TYPE, ident);
2523 TREE_STATIC_TEMPLATE (record) = 1;
2524 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2529 tree
2530 is_class_name (tree ident)
2532 tree chain;
2534 if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2535 && identifier_global_value (ident))
2536 ident = identifier_global_value (ident);
2537 while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2538 ident = TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2540 #ifdef OBJCPLUS
2541 if (ident && TREE_CODE (ident) == RECORD_TYPE)
2542 ident = TYPE_NAME (ident);
2543 if (ident && TREE_CODE (ident) == TYPE_DECL)
2544 ident = DECL_NAME (ident);
2545 #endif
2546 if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2547 return NULL_TREE;
2549 if (lookup_interface (ident))
2550 return ident;
2552 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2554 if (ident == TREE_VALUE (chain))
2555 return ident;
2558 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2560 if (ident == TREE_VALUE (chain))
2561 return TREE_PURPOSE (chain);
2564 return 0;
2567 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
2568 class instance. This is needed by other parts of the compiler to
2569 handle ObjC types gracefully. */
2571 tree
2572 objc_is_object_ptr (tree type)
2574 type = TYPE_MAIN_VARIANT (type);
2575 if (!type || TREE_CODE (type) != POINTER_TYPE)
2576 return 0;
2577 /* NB: This function may be called before the ObjC front-end has
2578 been initialized, in which case ID_TYPE will be NULL. */
2579 if (id_type && type && TYPE_P (type)
2580 && (IS_ID (type)
2581 || TREE_TYPE (type) == TREE_TYPE (objc_class_type)))
2582 return type;
2583 return is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
2586 tree
2587 lookup_interface (tree ident)
2589 tree chain;
2591 #ifdef OBJCPLUS
2592 if (ident && TREE_CODE (ident) == TYPE_DECL)
2593 ident = DECL_NAME (ident);
2594 #endif
2595 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2597 if (ident == CLASS_NAME (chain))
2598 return chain;
2600 return NULL_TREE;
2603 /* Implement @defs (<classname>) within struct bodies. */
2605 tree
2606 get_class_ivars_from_name (tree class_name)
2608 tree interface = lookup_interface (class_name);
2609 tree field, fields = NULL_TREE;
2611 if (interface)
2613 tree raw_ivar = get_class_ivars (interface, 1);
2615 /* Regenerate the FIELD_DECLs for the enclosing struct. */
2616 for (; raw_ivar; raw_ivar = TREE_CHAIN (raw_ivar))
2618 field = grokfield (TREE_PURPOSE (TREE_VALUE (raw_ivar)),
2619 TREE_PURPOSE (raw_ivar),
2620 TREE_VALUE (TREE_VALUE (raw_ivar)));
2621 #ifdef OBJCPLUS
2622 finish_member_declaration (field);
2623 #else
2624 fields = chainon (fields, field);
2625 #endif
2628 else
2629 error ("cannot find interface declaration for `%s'",
2630 IDENTIFIER_POINTER (class_name));
2632 return fields;
2635 /* Used by: build_private_template, continue_class,
2636 and for @defs constructs. */
2638 static tree
2639 get_class_ivars (tree interface, int raw)
2641 tree my_name, super_name, ivar_chain;
2643 my_name = CLASS_NAME (interface);
2644 super_name = CLASS_SUPER_NAME (interface);
2645 if (raw)
2646 ivar_chain = CLASS_RAW_IVARS (interface);
2647 else
2649 ivar_chain = CLASS_IVARS (interface);
2650 /* Save off a pristine copy of the leaf ivars (i.e, those not
2651 inherited from a super class). */
2652 if (!CLASS_OWN_IVARS (interface))
2653 CLASS_OWN_IVARS (interface) = copy_list (ivar_chain);
2656 while (super_name)
2658 tree op1;
2659 tree super_interface = lookup_interface (super_name);
2661 if (!super_interface)
2663 /* fatal did not work with 2 args...should fix */
2664 error ("cannot find interface declaration for `%s', superclass of `%s'",
2665 IDENTIFIER_POINTER (super_name),
2666 IDENTIFIER_POINTER (my_name));
2667 exit (FATAL_EXIT_CODE);
2670 if (super_interface == interface)
2671 fatal_error ("circular inheritance in interface declaration for `%s'",
2672 IDENTIFIER_POINTER (super_name));
2674 interface = super_interface;
2675 my_name = CLASS_NAME (interface);
2676 super_name = CLASS_SUPER_NAME (interface);
2678 op1 = (raw ? CLASS_RAW_IVARS (interface) : CLASS_OWN_IVARS (interface));
2679 if (op1)
2681 tree head = copy_list (op1);
2683 /* Prepend super class ivars...make a copy of the list, we
2684 do not want to alter the original. */
2685 chainon (head, ivar_chain);
2686 ivar_chain = head;
2690 return ivar_chain;
2693 static tree
2694 objc_enter_block (void)
2696 tree block;
2698 #ifdef OBJCPLUS
2699 block = begin_compound_stmt (0);
2700 #else
2701 block = c_begin_compound_stmt ();
2702 pushlevel (0);
2703 clear_last_expr ();
2704 add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
2705 #endif
2707 objc_exception_block_stack = tree_cons (NULL_TREE, block,
2708 objc_exception_block_stack);
2710 blk_nesting_count++;
2711 return block;
2714 static tree
2715 objc_exit_block (void)
2717 tree block = TREE_VALUE (objc_exception_block_stack);
2718 #ifndef OBJCPLUS
2719 tree scope_stmt, inner;
2720 #endif
2722 objc_clear_super_receiver ();
2723 #ifdef OBJCPLUS
2724 finish_compound_stmt (0, block);
2725 #else
2726 scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
2727 inner = poplevel (KEEP_MAYBE, 1, 0);
2729 SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
2730 = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
2731 = inner;
2732 RECHAIN_STMTS (block, COMPOUND_BODY (block));
2733 #endif
2734 last_expr_type = NULL_TREE;
2735 objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack);
2737 blk_nesting_count--;
2738 return block;
2741 static tree
2742 objc_declare_variable (enum rid scspec, tree name, tree type, tree init)
2744 tree decl;
2746 type = tree_cons (NULL_TREE, type,
2747 tree_cons (NULL_TREE, ridpointers[(int) scspec],
2748 NULL_TREE));
2749 TREE_STATIC (type) = 1;
2750 decl = start_decl (name, type, (init != NULL_TREE), NULL_TREE);
2751 finish_decl (decl, init, NULL_TREE);
2752 /* This prevents `unused variable' warnings when compiling with -Wall. */
2753 TREE_USED (decl) = 1;
2754 DECL_ARTIFICIAL (decl) = 1;
2755 return decl;
2758 tree
2759 objc_build_throw_stmt (tree throw_expr)
2761 tree func_params;
2763 if (!flag_objc_exceptions)
2764 fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
2766 if (!throw_expr && objc_caught_exception)
2767 throw_expr = TREE_VALUE (objc_caught_exception);
2769 if (!throw_expr)
2771 error ("`@throw;' (rethrow) used outside of a `@catch' block");
2772 return error_mark_node;
2775 func_params = tree_cons (NULL_TREE, throw_expr, NULL_TREE);
2777 assemble_external (objc_exception_throw_decl);
2778 return c_expand_expr_stmt (build_function_call (objc_exception_throw_decl,
2779 func_params));
2782 static void
2783 val_stack_push (struct val_stack **nc, long val)
2785 struct val_stack *new_elem = xmalloc (sizeof (struct val_stack));
2786 new_elem->val = val;
2787 new_elem->next = *nc;
2788 *nc = new_elem;
2791 static void
2792 val_stack_pop (struct val_stack **nc)
2794 struct val_stack *old_elem = *nc;
2795 *nc = old_elem->next;
2796 free (old_elem);
2799 static void
2800 objc_build_try_enter_fragment (void)
2802 /* objc_exception_try_enter(&_stackExceptionData);
2803 if (!_setjmp(&_stackExceptionData.buf)) { */
2805 tree func_params, if_stmt, cond;
2807 func_params
2808 = tree_cons (NULL_TREE,
2809 build_unary_op (ADDR_EXPR,
2810 TREE_VALUE (objc_stack_exception_data),
2812 NULL_TREE);
2814 assemble_external (objc_exception_try_enter_decl);
2815 c_expand_expr_stmt (build_function_call
2816 (objc_exception_try_enter_decl, func_params));
2818 if_stmt = c_begin_if_stmt ();
2819 if_nesting_count++;
2820 /* If <setjmp.h> has been included, the _setjmp prototype has
2821 acquired a real, breathing type for its parameter. Cast our
2822 argument to that type. */
2823 func_params
2824 = tree_cons (NULL_TREE,
2825 build_c_cast (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))
2826 ? TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
2827 : ptr_type_node,
2828 build_unary_op
2829 (ADDR_EXPR,
2830 build_component_ref (TREE_VALUE (objc_stack_exception_data),
2831 get_identifier ("buf")), 0)),
2832 NULL_TREE);
2833 assemble_external (objc_setjmp_decl);
2834 cond = build_unary_op (TRUTH_NOT_EXPR,
2835 build_function_call (objc_setjmp_decl, func_params),
2837 c_expand_start_cond ((*lang_hooks.truthvalue_conversion) (cond),
2838 0, if_stmt);
2839 objc_enter_block ();
2842 static tree
2843 objc_build_extract_expr (void)
2845 /* ... = objc_exception_extract(&_stackExceptionData); */
2847 tree func_params
2848 = tree_cons (NULL_TREE,
2849 build_unary_op (ADDR_EXPR,
2850 TREE_VALUE (objc_stack_exception_data), 0),
2851 NULL_TREE);
2853 assemble_external (objc_exception_extract_decl);
2854 return build_function_call (objc_exception_extract_decl, func_params);
2857 static void
2858 objc_build_try_exit_fragment (void)
2860 /* objc_exception_try_exit(&_stackExceptionData); */
2862 tree func_params
2863 = tree_cons (NULL_TREE,
2864 build_unary_op (ADDR_EXPR,
2865 TREE_VALUE (objc_stack_exception_data), 0),
2866 NULL_TREE);
2868 assemble_external (objc_exception_try_exit_decl);
2869 c_expand_expr_stmt (build_function_call (objc_exception_try_exit_decl,
2870 func_params));
2873 static void
2874 objc_build_extract_fragment (void)
2876 /* } else {
2877 _rethrowException = objc_exception_extract(&_stackExceptionData);
2878 } */
2880 objc_exit_block ();
2881 c_finish_then ();
2883 c_expand_start_else ();
2884 objc_enter_block ();
2885 c_expand_expr_stmt (build_modify_expr
2886 (TREE_VALUE (objc_rethrow_exception),
2887 NOP_EXPR,
2888 objc_build_extract_expr ()));
2889 objc_exit_block ();
2890 c_finish_else ();
2891 c_expand_end_cond ();
2892 if_nesting_count--;
2895 tree
2896 objc_build_try_prologue (void)
2898 /* { // new scope
2899 struct _objc_exception_data _stackExceptionData;
2900 volatile id _rethrowException = nil;
2901 { // begin TRY-CATCH scope
2902 objc_exception_try_enter(&_stackExceptionData);
2903 if (!_setjmp(&_stackExceptionData.buf)) { */
2905 tree try_catch_block;
2907 if (!flag_objc_exceptions)
2908 fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
2910 objc_mark_locals_volatile ((void *)(exc_binding_stack
2911 ? exc_binding_stack->val
2912 : 0));
2913 objc_enter_block ();
2914 objc_stack_exception_data
2915 = tree_cons (NULL_TREE,
2916 objc_declare_variable (RID_AUTO,
2917 get_identifier (UTAG_EXCDATA_VAR),
2918 xref_tag (RECORD_TYPE,
2919 get_identifier (UTAG_EXCDATA)),
2920 NULL_TREE),
2921 objc_stack_exception_data);
2922 objc_rethrow_exception = tree_cons (NULL_TREE,
2923 objc_declare_variable (RID_VOLATILE,
2924 get_identifier (UTAG_RETHROWEXC_VAR),
2925 id_type,
2926 build_int_2 (0, 0)),
2927 objc_rethrow_exception);
2929 try_catch_block = objc_enter_block ();
2930 val_stack_push (&exc_binding_stack, (long) get_current_scope ());
2931 objc_build_try_enter_fragment ();
2933 return try_catch_block;
2936 void
2937 objc_build_try_epilogue (int also_catch_prologue)
2939 if (also_catch_prologue)
2941 /* } else {
2942 register id _caughtException = objc_exception_extract( &_stackExceptionData);
2943 objc_exception_try_enter(&_stackExceptionData);
2944 if(!_setjmp(&_stackExceptionData.buf)) {
2945 if (0) { */
2947 tree if_stmt;
2949 objc_exit_block ();
2950 c_finish_then ();
2952 c_expand_start_else ();
2953 objc_enter_block ();
2954 objc_caught_exception
2955 = tree_cons (NULL_TREE,
2956 objc_declare_variable (RID_REGISTER,
2957 get_identifier (UTAG_CAUGHTEXC_VAR),
2958 id_type,
2959 objc_build_extract_expr ()),
2960 objc_caught_exception);
2961 objc_build_try_enter_fragment ();
2962 val_stack_push (&catch_count_stack, 1);
2963 if_stmt = c_begin_if_stmt ();
2964 if_nesting_count++;
2965 c_expand_start_cond ((*lang_hooks.truthvalue_conversion) (boolean_false_node),
2966 0, if_stmt);
2967 objc_enter_block ();
2969 /* Start a new chain of @catch statements for this @try. */
2970 objc_catch_type = tree_cons (objc_catch_type, NULL_TREE, NULL_TREE);
2972 else
2973 { /* !also_catch_prologue */
2975 /* } else {
2976 _rethrowException = objc_exception_extract( &_stackExceptionData);
2978 } */
2979 objc_build_extract_fragment ();
2980 objc_exit_block ();
2984 void
2985 objc_build_catch_stmt (tree catch_expr)
2987 /* } else if (objc_exception_match(objc_get_class("SomeClass"), _caughtException)) {
2988 register SomeClass *e = _caughtException; */
2990 tree if_stmt, cond, func_params, prev_catch, var_name, var_type;
2991 int catch_id;
2993 #ifndef OBJCPLUS
2994 /* Yet another C/C++ impedance mismatch. */
2995 catch_expr = TREE_PURPOSE (catch_expr);
2996 #endif
2998 var_name = TREE_VALUE (catch_expr);
2999 var_type = TREE_VALUE (TREE_PURPOSE (catch_expr));
3000 if (TREE_CODE (var_name) == INDIRECT_REF)
3001 var_name = TREE_OPERAND (var_name, 0);
3002 if (TREE_CODE (var_type) == TYPE_DECL
3003 || TREE_CODE (var_type) == POINTER_TYPE)
3004 var_type = TREE_TYPE (var_type);
3005 catch_id = (var_type == TREE_TYPE (id_type));
3007 if (!flag_objc_exceptions)
3008 fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3010 if (!(catch_id || TYPED_OBJECT (var_type)))
3011 fatal_error ("`@catch' parameter is not a known Objective-C class type");
3013 /* Examine previous @catch clauses for the current @try block for
3014 superclasses of the 'var_type' class. */
3015 for (prev_catch = objc_catch_type; TREE_VALUE (prev_catch);
3016 prev_catch = TREE_CHAIN (prev_catch))
3018 if (TREE_VALUE (prev_catch) == TREE_TYPE (id_type))
3020 warning ("Exception already handled by preceding `@catch(id)'");
3021 break;
3023 else if (!catch_id
3024 && objc_comptypes (TREE_VALUE (prev_catch), var_type, 0) == 1)
3025 warning ("Exception of type `%s *' already handled by `@catch (%s *)'",
3026 IDENTIFIER_POINTER (OBJC_TYPE_NAME (var_type)),
3027 IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_VALUE (prev_catch))));
3030 objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
3032 objc_exit_block ();
3033 c_finish_then ();
3035 c_expand_start_else ();
3036 catch_count_stack->val++;
3037 if_stmt = c_begin_if_stmt ();
3038 if_nesting_count++;
3040 if (catch_id)
3041 cond = integer_one_node;
3042 else
3044 cond = get_class_reference (OBJC_TYPE_NAME (var_type));
3046 func_params
3047 = tree_cons (NULL_TREE, cond,
3048 tree_cons (NULL_TREE,
3049 TREE_VALUE (objc_caught_exception),
3050 NULL_TREE));
3051 assemble_external (objc_exception_match_decl);
3052 cond = build_function_call (objc_exception_match_decl, func_params);
3055 c_expand_start_cond ((*lang_hooks.truthvalue_conversion) (cond),
3056 0, if_stmt);
3057 objc_enter_block ();
3058 objc_declare_variable (RID_REGISTER, var_name,
3059 build_pointer_type (var_type),
3060 TREE_VALUE (objc_caught_exception));
3063 void
3064 objc_build_catch_epilogue (void)
3066 /* } else {
3067 _rethrowException = _caughtException;
3068 objc_exception_try_exit(&_stackExceptionData);
3070 } else {
3071 _rethrowException = objc_exception_extract(&_stackExceptionData);
3074 } // end TRY-CATCH scope
3077 objc_exit_block ();
3078 c_finish_then ();
3080 c_expand_start_else ();
3081 objc_enter_block ();
3082 c_expand_expr_stmt
3083 (build_modify_expr
3084 (TREE_VALUE (objc_rethrow_exception),
3085 NOP_EXPR,
3086 TREE_VALUE (objc_caught_exception)));
3087 objc_build_try_exit_fragment ();
3088 objc_exit_block ();
3089 while (catch_count_stack->val--)
3091 c_finish_else (); /* close off all the nested ifs ! */
3092 c_expand_end_cond ();
3093 if_nesting_count--;
3095 val_stack_pop (&catch_count_stack);
3096 objc_caught_exception = TREE_CHAIN (objc_caught_exception);
3098 objc_build_extract_fragment ();
3100 objc_exit_block ();
3101 c_finish_else ();
3102 c_expand_end_cond ();
3103 if_nesting_count--;
3104 objc_exit_block ();
3106 /* Return to enclosing chain of @catch statements (if any). */
3107 while (TREE_VALUE (objc_catch_type))
3108 objc_catch_type = TREE_CHAIN (objc_catch_type);
3109 objc_catch_type = TREE_PURPOSE (objc_catch_type);
3112 tree
3113 objc_build_finally_prologue (void)
3115 /* { // begin FINALLY scope
3116 if (!_rethrowException) {
3117 objc_exception_try_exit(&_stackExceptionData);
3118 } */
3120 tree blk = objc_enter_block ();
3122 tree if_stmt = c_begin_if_stmt ();
3123 if_nesting_count++;
3125 c_expand_start_cond ((*lang_hooks.truthvalue_conversion)
3126 (build_unary_op
3127 (TRUTH_NOT_EXPR,
3128 TREE_VALUE (objc_rethrow_exception), 0)),
3129 0, if_stmt);
3130 objc_enter_block ();
3131 objc_build_try_exit_fragment ();
3132 objc_exit_block ();
3133 c_finish_then ();
3134 c_expand_end_cond ();
3135 if_nesting_count--;
3137 return blk;
3140 tree
3141 objc_build_finally_epilogue (void)
3143 /* if (_rethrowException) {
3144 objc_exception_throw(_rethrowException);
3146 } // end FINALLY scope
3147 } */
3149 tree if_stmt = c_begin_if_stmt ();
3150 if_nesting_count++;
3152 c_expand_start_cond
3153 ((*lang_hooks.truthvalue_conversion) (TREE_VALUE (objc_rethrow_exception)),
3154 0, if_stmt);
3155 objc_enter_block ();
3156 objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
3157 objc_exit_block ();
3158 c_finish_then ();
3159 c_expand_end_cond ();
3160 if_nesting_count--;
3162 objc_exit_block ();
3163 objc_rethrow_exception = TREE_CHAIN (objc_rethrow_exception);
3164 objc_stack_exception_data = TREE_CHAIN (objc_stack_exception_data);
3166 val_stack_pop (&exc_binding_stack);
3167 return objc_exit_block ();
3170 tree
3171 objc_build_try_catch_finally_stmt (int has_catch, int has_finally)
3173 /* NB: The operative assumption here is that TRY_FINALLY_EXPR will
3174 deal with all exits from 'try_catch_blk' and route them through
3175 'finally_blk'. */
3176 tree outer_blk = objc_build_finally_epilogue ();
3177 tree prec_stmt = TREE_CHAIN (TREE_CHAIN (COMPOUND_BODY (outer_blk)));
3178 tree try_catch_blk = TREE_CHAIN (prec_stmt), try_catch_expr;
3179 tree finally_blk = TREE_CHAIN (try_catch_blk), finally_expr;
3180 tree succ_stmt = TREE_CHAIN (finally_blk);
3181 tree try_finally_stmt, try_finally_expr;
3183 if (!flag_objc_exceptions)
3184 fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3186 /* It is an error to have a @try block without a @catch and/or @finally
3187 (even though sensible code can be generated nonetheless). */
3189 if (!has_catch && !has_finally)
3190 error ("`@try' without `@catch' or `@finally'");
3192 /* We shall now do something truly disgusting. We shall remove the
3193 'try_catch_blk' and 'finally_blk' from the 'outer_blk' statement
3194 chain, and replace them with a TRY_FINALLY_EXPR statement! If
3195 this doesn't work, we will have to learn (from Per/gcj) how to
3196 construct the 'outer_blk' lazily. */
3198 TREE_CHAIN (try_catch_blk) = TREE_CHAIN (finally_blk) = NULL_TREE;
3199 try_catch_expr = build1 (STMT_EXPR, void_type_node, try_catch_blk);
3200 TREE_SIDE_EFFECTS (try_catch_expr) = 1;
3201 finally_expr = build1 (STMT_EXPR, void_type_node, finally_blk);
3202 TREE_SIDE_EFFECTS (finally_expr) = 1;
3203 try_finally_expr = build (TRY_FINALLY_EXPR, void_type_node, try_catch_expr,
3204 finally_expr);
3205 TREE_SIDE_EFFECTS (try_finally_expr) = 1;
3206 try_finally_stmt = build_stmt (EXPR_STMT, try_finally_expr);
3207 TREE_CHAIN (prec_stmt) = try_finally_stmt;
3208 TREE_CHAIN (try_finally_stmt) = succ_stmt;
3210 return outer_blk; /* the whole enchilada */
3213 void
3214 objc_build_synchronized_prologue (tree sync_expr)
3216 /* {
3217 id _eval_once = <sync_expr>;
3218 @try {
3219 objc_sync_enter( _eval_once ); */
3221 tree func_params;
3223 if (!flag_objc_exceptions)
3224 fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
3226 objc_enter_block ();
3227 objc_eval_once
3228 = tree_cons (NULL_TREE,
3229 objc_declare_variable (RID_AUTO,
3230 get_identifier (UTAG_EVALONCE_VAR),
3231 id_type,
3232 sync_expr),
3233 objc_eval_once);
3234 objc_build_try_prologue ();
3235 objc_enter_block ();
3236 func_params = tree_cons (NULL_TREE,
3237 TREE_VALUE (objc_eval_once),
3238 NULL_TREE);
3240 assemble_external (objc_sync_enter_decl);
3241 c_expand_expr_stmt (build_function_call
3242 (objc_sync_enter_decl, func_params));
3245 tree
3246 objc_build_synchronized_epilogue (void)
3248 /* }
3249 @finally {
3250 objc_sync_exit( _eval_once );
3252 } */
3254 tree func_params;
3256 objc_exit_block ();
3257 objc_build_try_epilogue (0);
3258 objc_build_finally_prologue ();
3259 func_params = tree_cons (NULL_TREE, TREE_VALUE (objc_eval_once),
3260 NULL_TREE);
3262 assemble_external (objc_sync_exit_decl);
3263 c_expand_expr_stmt (build_function_call (objc_sync_exit_decl,
3264 func_params));
3265 objc_build_try_catch_finally_stmt (0, 1);
3267 return objc_exit_block ();
3270 /* Predefine the following data type:
3272 struct _objc_exception_data
3274 int buf[_JBLEN];
3275 void *pointers[4];
3276 }; */
3278 /* The following yuckiness should prevent users from having to #include
3279 <setjmp.h> in their code... */
3281 #ifdef TARGET_POWERPC
3282 /* snarfed from /usr/include/ppc/setjmp.h */
3283 #define _JBLEN (26 + 36 + 129 + 1)
3284 #else
3285 /* snarfed from /usr/include/i386/{setjmp,signal}.h */
3286 #define _JBLEN 18
3287 #endif
3289 static void
3290 build_objc_exception_stuff (void)
3292 tree field_decl, field_decl_chain, index, temp_type;
3294 /* Suppress outputting debug symbols, because
3295 dbxout_init hasn't been called yet. */
3296 enum debug_info_type save_write_symbols = write_symbols;
3297 const struct gcc_debug_hooks *save_hooks = debug_hooks;
3299 write_symbols = NO_DEBUG;
3300 debug_hooks = &do_nothing_debug_hooks;
3301 objc_exception_data_template
3302 = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3304 /* int buf[_JBLEN]; */
3306 index = build_index_type (build_int_2 (_JBLEN - 1, 0));
3307 field_decl = create_builtin_decl (FIELD_DECL,
3308 build_array_type (integer_type_node, index),
3309 "buf");
3310 field_decl_chain = field_decl;
3312 /* void *pointers[4]; */
3314 index = build_index_type (build_int_2 (4 - 1, 0));
3315 field_decl = create_builtin_decl (FIELD_DECL,
3316 build_array_type (ptr_type_node, index),
3317 "pointers");
3318 chainon (field_decl_chain, field_decl);
3320 finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3322 /* int _setjmp(...); */
3323 /* If the user includes <setjmp.h>, this shall be superceded by
3324 'int _setjmp(jmp_buf);' */
3325 temp_type = build_function_type (integer_type_node, NULL_TREE);
3326 objc_setjmp_decl
3327 = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3329 /* id objc_exception_extract(struct _objc_exception_data *); */
3330 temp_type
3331 = build_function_type (id_type,
3332 tree_cons (NULL_TREE,
3333 build_pointer_type (objc_exception_data_template),
3334 OBJC_VOID_AT_END));
3335 objc_exception_extract_decl
3336 = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3337 /* void objc_exception_try_enter(struct _objc_exception_data *); */
3338 /* void objc_exception_try_exit(struct _objc_exception_data *); */
3339 temp_type
3340 = build_function_type (void_type_node,
3341 tree_cons (NULL_TREE,
3342 build_pointer_type (objc_exception_data_template),
3343 OBJC_VOID_AT_END));
3344 objc_exception_try_enter_decl
3345 = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3346 objc_exception_try_exit_decl
3347 = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3348 /* void objc_exception_throw(id) __attribute__((noreturn)); */
3349 /* void objc_sync_enter(id); */
3350 /* void objc_sync_exit(id); */
3351 temp_type = build_function_type (void_type_node,
3352 tree_cons (NULL_TREE, id_type,
3353 OBJC_VOID_AT_END));
3354 objc_exception_throw_decl
3355 = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3356 DECL_ATTRIBUTES (objc_exception_throw_decl)
3357 = tree_cons (get_identifier ("noreturn"), NULL_TREE, NULL_TREE);
3358 objc_sync_enter_decl
3359 = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3360 objc_sync_exit_decl
3361 = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3362 /* int objc_exception_match(id, id); */
3363 temp_type = build_function_type (integer_type_node,
3364 tree_cons (NULL_TREE, id_type,
3365 tree_cons (NULL_TREE, id_type,
3366 OBJC_VOID_AT_END)));
3367 objc_exception_match_decl
3368 = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3370 write_symbols = save_write_symbols;
3371 debug_hooks = save_hooks;
3374 /* struct <classname> {
3375 struct objc_class *isa;
3377 }; */
3379 static tree
3380 build_private_template (tree class)
3382 tree ivar_context;
3384 if (CLASS_STATIC_TEMPLATE (class))
3386 uprivate_record = CLASS_STATIC_TEMPLATE (class);
3387 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3389 else
3391 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3392 ivar_context = get_class_ivars (class, 0);
3394 finish_struct (uprivate_record, ivar_context, NULL_TREE);
3396 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3398 /* mark this record as class template - for class type checking */
3399 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3402 instance_type
3403 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3404 uprivate_record),
3405 build1 (INDIRECT_REF, NULL_TREE,
3406 NULL_TREE)));
3408 return ivar_context;
3411 /* Begin code generation for protocols... */
3413 /* struct objc_protocol {
3414 char *protocol_name;
3415 struct objc_protocol **protocol_list;
3416 struct objc_method_desc *instance_methods;
3417 struct objc_method_desc *class_methods;
3418 }; */
3420 static tree
3421 build_protocol_template (void)
3423 tree decl_specs, field_decl, field_decl_chain;
3424 tree template;
3426 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
3428 /* struct objc_class *isa; */
3430 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3431 get_identifier (UTAG_CLASS)));
3432 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3433 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3434 field_decl_chain = field_decl;
3436 /* char *protocol_name; */
3438 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3439 field_decl
3440 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
3441 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3442 chainon (field_decl_chain, field_decl);
3444 /* struct objc_protocol **protocol_list; */
3446 decl_specs = build_tree_list (NULL_TREE, template);
3447 field_decl
3448 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3449 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3450 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3451 chainon (field_decl_chain, field_decl);
3453 /* struct objc_method_list *instance_methods; */
3455 decl_specs
3456 = build_tree_list (NULL_TREE,
3457 xref_tag (RECORD_TYPE,
3458 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3459 field_decl
3460 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3461 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3462 chainon (field_decl_chain, field_decl);
3464 /* struct objc_method_list *class_methods; */
3466 decl_specs
3467 = build_tree_list (NULL_TREE,
3468 xref_tag (RECORD_TYPE,
3469 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3470 field_decl
3471 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3472 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3473 chainon (field_decl_chain, field_decl);
3475 return finish_struct (template, field_decl_chain, NULL_TREE);
3478 static tree
3479 build_descriptor_table_initializer (tree type, tree entries)
3481 tree initlist = NULL_TREE;
3485 tree eltlist = NULL_TREE;
3487 eltlist
3488 = tree_cons (NULL_TREE,
3489 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3490 eltlist
3491 = tree_cons (NULL_TREE,
3492 add_objc_string (METHOD_ENCODING (entries),
3493 meth_var_types),
3494 eltlist);
3496 initlist
3497 = tree_cons (NULL_TREE,
3498 objc_build_constructor (type, nreverse (eltlist)),
3499 initlist);
3501 entries = TREE_CHAIN (entries);
3503 while (entries);
3505 return objc_build_constructor (build_array_type (type, 0),
3506 nreverse (initlist));
3509 /* struct objc_method_prototype_list {
3510 int count;
3511 struct objc_method_prototype {
3512 SEL name;
3513 char *types;
3514 } list[1];
3515 }; */
3517 static tree
3518 build_method_prototype_list_template (tree list_type, int size)
3520 tree objc_ivar_list_record;
3521 tree decl_specs, field_decl, field_decl_chain;
3523 /* Generate an unnamed struct definition. */
3525 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3527 /* int method_count; */
3529 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3530 field_decl = get_identifier ("method_count");
3531 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3532 field_decl_chain = field_decl;
3534 /* struct objc_method method_list[]; */
3536 decl_specs = build_tree_list (NULL_TREE, list_type);
3537 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3538 build_int_2 (size, 0));
3539 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3540 chainon (field_decl_chain, field_decl);
3542 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3544 return objc_ivar_list_record;
3547 static tree
3548 build_method_prototype_template (void)
3550 tree proto_record;
3551 tree decl_specs, field_decl, field_decl_chain;
3553 proto_record
3554 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
3556 /* struct objc_selector *_cmd; */
3557 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
3558 get_identifier (TAG_SELECTOR)), NULL_TREE);
3559 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3560 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3561 field_decl_chain = field_decl;
3563 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3564 field_decl
3565 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
3566 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3567 chainon (field_decl_chain, field_decl);
3569 finish_struct (proto_record, field_decl_chain, NULL_TREE);
3571 return proto_record;
3574 static tree
3575 objc_method_parm_type (tree type)
3577 type = groktypename (TREE_TYPE (type));
3578 if (TREE_CODE (type) == TYPE_DECL)
3579 type = TREE_TYPE (type);
3580 return TYPE_MAIN_VARIANT (type);
3583 static int
3584 objc_encoded_type_size (tree type)
3586 int sz = int_size_in_bytes (type);
3588 /* Make all integer and enum types at least as large
3589 as an int. */
3590 if (sz > 0 && (TREE_CODE (type) == INTEGER_TYPE
3591 || TREE_CODE (type) == BOOLEAN_TYPE
3592 || TREE_CODE (type) == ENUMERAL_TYPE))
3593 sz = MAX (sz, int_size_in_bytes (integer_type_node));
3594 /* Treat arrays as pointers, since that's how they're
3595 passed in. */
3596 else if (TREE_CODE (type) == ARRAY_TYPE)
3597 sz = int_size_in_bytes (ptr_type_node);
3598 return sz;
3601 static tree
3602 encode_method_prototype (tree method_decl)
3604 tree parms;
3605 int parm_offset, i;
3606 char buf[40];
3607 tree result;
3609 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
3610 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
3612 /* Encode return type. */
3613 encode_type (objc_method_parm_type (method_decl),
3614 obstack_object_size (&util_obstack),
3615 OBJC_ENCODE_INLINE_DEFS);
3617 /* Stack size. */
3618 /* The first two arguments (self and _cmd) are pointers; account for
3619 their size. */
3620 i = int_size_in_bytes (ptr_type_node);
3621 parm_offset = 2 * i;
3622 for (parms = METHOD_SEL_ARGS (method_decl); parms;
3623 parms = TREE_CHAIN (parms))
3625 tree type = objc_method_parm_type (parms);
3626 int sz = objc_encoded_type_size (type);
3628 /* If a type size is not known, bail out. */
3629 if (sz < 0)
3631 error ("%Jtype '%D' does not have a known size",
3632 type, type);
3633 /* Pretend that the encoding succeeded; the compilation will
3634 fail nevertheless. */
3635 goto finish_encoding;
3637 parm_offset += sz;
3640 sprintf (buf, "%d@0:%d", parm_offset, i);
3641 obstack_grow (&util_obstack, buf, strlen (buf));
3643 /* Argument types. */
3644 parm_offset = 2 * i;
3645 for (parms = METHOD_SEL_ARGS (method_decl); parms;
3646 parms = TREE_CHAIN (parms))
3648 tree type = objc_method_parm_type (parms);
3650 /* Process argument qualifiers for user supplied arguments. */
3651 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
3653 /* Type. */
3654 encode_type (type, obstack_object_size (&util_obstack),
3655 OBJC_ENCODE_INLINE_DEFS);
3657 /* Compute offset. */
3658 sprintf (buf, "%d", parm_offset);
3659 parm_offset += objc_encoded_type_size (type);
3661 obstack_grow (&util_obstack, buf, strlen (buf));
3664 finish_encoding:
3665 obstack_1grow (&util_obstack, '\0');
3666 result = get_identifier (obstack_finish (&util_obstack));
3667 obstack_free (&util_obstack, util_firstobj);
3668 return result;
3671 static tree
3672 generate_descriptor_table (tree type, const char *name, int size, tree list,
3673 tree proto)
3675 tree sc_spec, decl_specs, decl, initlist;
3677 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3678 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3680 decl = start_decl (synth_id_with_class_suffix (name, proto),
3681 decl_specs, 1, NULL_TREE);
3682 DECL_CONTEXT (decl) = NULL_TREE;
3684 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3685 initlist = tree_cons (NULL_TREE, list, initlist);
3687 finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
3688 NULL_TREE);
3690 return decl;
3693 static void
3694 generate_method_descriptors (tree protocol)
3696 tree initlist, chain, method_list_template;
3697 tree cast, variable_length_type;
3698 int size;
3700 if (!objc_method_prototype_template)
3701 objc_method_prototype_template = build_method_prototype_template ();
3703 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3704 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
3705 NULL_TREE);
3706 variable_length_type = groktypename (cast);
3708 chain = PROTOCOL_CLS_METHODS (protocol);
3709 if (chain)
3711 size = list_length (chain);
3713 method_list_template
3714 = build_method_prototype_list_template (objc_method_prototype_template,
3715 size);
3717 initlist
3718 = build_descriptor_table_initializer (objc_method_prototype_template,
3719 chain);
3721 UOBJC_CLASS_METHODS_decl
3722 = generate_descriptor_table (method_list_template,
3723 "_OBJC_PROTOCOL_CLASS_METHODS",
3724 size, initlist, protocol);
3725 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3727 else
3728 UOBJC_CLASS_METHODS_decl = 0;
3730 chain = PROTOCOL_NST_METHODS (protocol);
3731 if (chain)
3733 size = list_length (chain);
3735 method_list_template
3736 = build_method_prototype_list_template (objc_method_prototype_template,
3737 size);
3738 initlist
3739 = build_descriptor_table_initializer (objc_method_prototype_template,
3740 chain);
3742 UOBJC_INSTANCE_METHODS_decl
3743 = generate_descriptor_table (method_list_template,
3744 "_OBJC_PROTOCOL_INSTANCE_METHODS",
3745 size, initlist, protocol);
3746 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3748 else
3749 UOBJC_INSTANCE_METHODS_decl = 0;
3752 static void
3753 generate_protocol_references (tree plist)
3755 tree lproto;
3757 /* Forward declare protocols referenced. */
3758 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3760 tree proto = TREE_VALUE (lproto);
3762 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3763 && PROTOCOL_NAME (proto))
3765 if (! PROTOCOL_FORWARD_DECL (proto))
3766 build_protocol_reference (proto);
3768 if (PROTOCOL_LIST (proto))
3769 generate_protocol_references (PROTOCOL_LIST (proto));
3774 /* For each protocol which was referenced either from a @protocol()
3775 expression, or because a class/category implements it (then a
3776 pointer to the protocol is stored in the struct describing the
3777 class/category), we create a statically allocated instance of the
3778 Protocol class. The code is written in such a way as to generate
3779 as few Protocol objects as possible; we generate a unique Protocol
3780 instance for each protocol, and we don't generate a Protocol
3781 instance if the protocol is never referenced (either from a
3782 @protocol() or from a class/category implementation). These
3783 statically allocated objects can be referred to via the static
3784 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3786 The statically allocated Protocol objects that we generate here
3787 need to be fixed up at runtime in order to be used: the 'isa'
3788 pointer of the objects need to be set up to point to the 'Protocol'
3789 class, as known at runtime.
3791 The NeXT runtime fixes up all protocols at program startup time,
3792 before main() is entered. It uses a low-level trick to look up all
3793 those symbols, then loops on them and fixes them up.
3795 The GNU runtime as well fixes up all protocols before user code
3796 from the module is executed; it requires pointers to those symbols
3797 to be put in the objc_symtab (which is then passed as argument to
3798 the function __objc_exec_class() which the compiler sets up to be
3799 executed automatically when the module is loaded); setup of those
3800 Protocol objects happen in two ways in the GNU runtime: all
3801 Protocol objects referred to by a class or category implementation
3802 are fixed up when the class/category is loaded; all Protocol
3803 objects referred to by a @protocol() expression are added by the
3804 compiler to the list of statically allocated instances to fixup
3805 (the same list holding the statically allocated constant string
3806 objects). Because, as explained above, the compiler generates as
3807 few Protocol objects as possible, some Protocol object might end up
3808 being referenced multiple times when compiled with the GNU runtime,
3809 and end up being fixed up multiple times at runtime inizialization.
3810 But that doesn't hurt, it's just a little inefficient. */
3812 static void
3813 generate_protocols (void)
3815 tree p, encoding;
3816 tree sc_spec, decl_specs, decl;
3817 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3818 tree cast_type2;
3820 if (! objc_protocol_template)
3821 objc_protocol_template = build_protocol_template ();
3823 /* If a protocol was directly referenced, pull in indirect references. */
3824 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3825 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3826 generate_protocol_references (PROTOCOL_LIST (p));
3828 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3830 tree nst_methods = PROTOCOL_NST_METHODS (p);
3831 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3833 /* If protocol wasn't referenced, don't generate any code. */
3834 if (! PROTOCOL_FORWARD_DECL (p))
3835 continue;
3837 /* Make sure we link in the Protocol class. */
3838 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3840 while (nst_methods)
3842 if (! METHOD_ENCODING (nst_methods))
3844 encoding = encode_method_prototype (nst_methods);
3845 METHOD_ENCODING (nst_methods) = encoding;
3847 nst_methods = TREE_CHAIN (nst_methods);
3850 while (cls_methods)
3852 if (! METHOD_ENCODING (cls_methods))
3854 encoding = encode_method_prototype (cls_methods);
3855 METHOD_ENCODING (cls_methods) = encoding;
3858 cls_methods = TREE_CHAIN (cls_methods);
3860 generate_method_descriptors (p);
3862 if (PROTOCOL_LIST (p))
3863 refs_decl = generate_protocol_list (p);
3864 else
3865 refs_decl = 0;
3867 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3869 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3870 NULL_TREE);
3871 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3873 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3874 decl_specs, 1, NULL_TREE);
3876 DECL_CONTEXT (decl) = NULL_TREE;
3878 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3880 if (refs_decl)
3882 cast_type2
3883 = groktypename
3884 (build_tree_list (build_tree_list (NULL_TREE,
3885 objc_protocol_template),
3886 build1 (INDIRECT_REF, NULL_TREE,
3887 build1 (INDIRECT_REF, NULL_TREE,
3888 NULL_TREE))));
3890 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3891 TREE_TYPE (refs_expr) = cast_type2;
3893 else
3894 refs_expr = build_int_2 (0, 0);
3896 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3897 by generate_method_descriptors, which is called above. */
3898 initlist = build_protocol_initializer (TREE_TYPE (decl),
3899 protocol_name_expr, refs_expr,
3900 UOBJC_INSTANCE_METHODS_decl,
3901 UOBJC_CLASS_METHODS_decl);
3902 finish_decl (decl, initlist, NULL_TREE);
3904 /* Mark the decl as used to avoid "defined but not used" warning. */
3905 TREE_USED (decl) = 1;
3909 static tree
3910 build_protocol_initializer (tree type, tree protocol_name,
3911 tree protocol_list, tree instance_methods,
3912 tree class_methods)
3914 tree initlist = NULL_TREE, expr;
3915 tree cast_type;
3917 cast_type = groktypename
3918 (build_tree_list
3919 (build_tree_list (NULL_TREE,
3920 xref_tag (RECORD_TYPE,
3921 get_identifier (UTAG_CLASS))),
3922 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3924 /* Filling the "isa" in with one allows the runtime system to
3925 detect that the version change...should remove before final release. */
3927 expr = build_int_2 (PROTOCOL_VERSION, 0);
3928 TREE_TYPE (expr) = cast_type;
3929 initlist = tree_cons (NULL_TREE, expr, initlist);
3930 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3931 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3933 if (!instance_methods)
3934 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3935 else
3937 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3938 initlist = tree_cons (NULL_TREE, expr, initlist);
3941 if (!class_methods)
3942 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3943 else
3945 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3946 initlist = tree_cons (NULL_TREE, expr, initlist);
3949 return objc_build_constructor (type, nreverse (initlist));
3952 /* struct objc_category {
3953 char *category_name;
3954 char *class_name;
3955 struct objc_method_list *instance_methods;
3956 struct objc_method_list *class_methods;
3957 struct objc_protocol_list *protocols;
3958 }; */
3960 static void
3961 build_category_template (void)
3963 tree decl_specs, field_decl, field_decl_chain;
3965 objc_category_template = start_struct (RECORD_TYPE,
3966 get_identifier (UTAG_CATEGORY));
3967 /* char *category_name; */
3969 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3970 field_decl
3971 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3972 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3973 field_decl_chain = field_decl;
3975 /* char *class_name; */
3977 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3978 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3979 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3980 chainon (field_decl_chain, field_decl);
3982 /* struct objc_method_list *instance_methods; */
3984 decl_specs = build_tree_list (NULL_TREE,
3985 xref_tag (RECORD_TYPE,
3986 get_identifier (UTAG_METHOD_LIST)));
3987 field_decl
3988 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3989 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3990 chainon (field_decl_chain, field_decl);
3992 /* struct objc_method_list *class_methods; */
3994 decl_specs = build_tree_list (NULL_TREE,
3995 xref_tag (RECORD_TYPE,
3996 get_identifier (UTAG_METHOD_LIST)));
3997 field_decl
3998 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3999 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4000 chainon (field_decl_chain, field_decl);
4002 /* struct objc_protocol **protocol_list; */
4004 decl_specs = build_tree_list (NULL_TREE,
4005 xref_tag (RECORD_TYPE,
4006 get_identifier (UTAG_PROTOCOL)));
4007 field_decl
4008 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4009 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4010 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4011 chainon (field_decl_chain, field_decl);
4013 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4016 /* struct objc_selector {
4017 void *sel_id;
4018 char *sel_type;
4019 }; */
4021 static void
4022 build_selector_template (void)
4025 tree decl_specs, field_decl, field_decl_chain;
4027 objc_selector_template
4028 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4030 /* void *sel_id; */
4032 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4033 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4034 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4035 field_decl_chain = field_decl;
4037 /* char *sel_type; */
4039 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4040 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
4041 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4042 chainon (field_decl_chain, field_decl);
4044 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4047 /* struct objc_class {
4048 struct objc_class *isa;
4049 struct objc_class *super_class;
4050 char *name;
4051 long version;
4052 long info;
4053 long instance_size;
4054 struct objc_ivar_list *ivars;
4055 struct objc_method_list *methods;
4056 if (flag_next_runtime)
4057 struct objc_cache *cache;
4058 else {
4059 struct sarray *dtable;
4060 struct objc_class *subclass_list;
4061 struct objc_class *sibling_class;
4063 struct objc_protocol_list *protocols;
4064 if (flag_next_runtime)
4065 void *sel_id;
4066 void *gc_object_type;
4067 }; */
4069 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4070 the NeXT/Apple runtime; still, the compiler must generate them to
4071 maintain backward binary compatibility (and to allow for future
4072 expansion). */
4074 static void
4075 build_class_template (void)
4077 tree decl_specs, field_decl, field_decl_chain;
4079 objc_class_template
4080 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4082 /* struct objc_class *isa; */
4084 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4085 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
4086 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4087 field_decl_chain = field_decl;
4089 /* struct objc_class *super_class; */
4091 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4092 field_decl
4093 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4094 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4095 chainon (field_decl_chain, field_decl);
4097 /* char *name; */
4099 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4100 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
4101 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4102 chainon (field_decl_chain, field_decl);
4104 /* long version; */
4106 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4107 field_decl = get_identifier ("version");
4108 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4109 chainon (field_decl_chain, field_decl);
4111 /* long info; */
4113 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4114 field_decl = get_identifier ("info");
4115 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4116 chainon (field_decl_chain, field_decl);
4118 /* long instance_size; */
4120 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
4121 field_decl = get_identifier ("instance_size");
4122 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4123 chainon (field_decl_chain, field_decl);
4125 /* struct objc_ivar_list *ivars; */
4127 decl_specs = build_tree_list (NULL_TREE,
4128 xref_tag (RECORD_TYPE,
4129 get_identifier (UTAG_IVAR_LIST)));
4130 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
4131 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4132 chainon (field_decl_chain, field_decl);
4134 /* struct objc_method_list *methods; */
4136 decl_specs = build_tree_list (NULL_TREE,
4137 xref_tag (RECORD_TYPE,
4138 get_identifier (UTAG_METHOD_LIST)));
4139 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
4140 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4141 chainon (field_decl_chain, field_decl);
4143 if (flag_next_runtime)
4145 /* struct objc_cache *cache; */
4147 decl_specs = build_tree_list (NULL_TREE,
4148 xref_tag (RECORD_TYPE,
4149 get_identifier ("objc_cache")));
4150 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
4151 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4152 chainon (field_decl_chain, field_decl);
4154 else
4156 /* struct sarray *dtable; */
4158 decl_specs = build_tree_list (NULL_TREE,
4159 xref_tag (RECORD_TYPE,
4160 get_identifier ("sarray")));
4161 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
4162 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4163 chainon (field_decl_chain, field_decl);
4165 /* struct objc_class *subclass_list; */
4167 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4168 field_decl
4169 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
4170 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4171 chainon (field_decl_chain, field_decl);
4173 /* struct objc_class *sibling_class; */
4175 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
4176 field_decl
4177 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
4178 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4179 chainon (field_decl_chain, field_decl);
4182 /* struct objc_protocol **protocol_list; */
4184 decl_specs = build_tree_list (NULL_TREE,
4185 xref_tag (RECORD_TYPE,
4186 get_identifier (UTAG_PROTOCOL)));
4187 field_decl
4188 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
4189 field_decl
4190 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4191 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4192 chainon (field_decl_chain, field_decl);
4194 if (flag_next_runtime)
4196 /* void *sel_id; */
4198 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4199 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
4200 field_decl
4201 = grokfield (field_decl, decl_specs, NULL_TREE);
4202 chainon (field_decl_chain, field_decl);
4205 /* void *gc_object_type; */
4207 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
4208 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
4209 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4210 chainon (field_decl_chain, field_decl);
4212 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
4215 /* Generate appropriate forward declarations for an implementation. */
4217 static void
4218 synth_forward_declarations (void)
4220 tree an_id;
4222 /* static struct objc_class _OBJC_CLASS_<my_name>; */
4223 UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
4224 objc_class_template);
4226 /* static struct objc_class _OBJC_METACLASS_<my_name>; */
4227 UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
4228 objc_class_template);
4230 /* Pre-build the following entities - for speed/convenience. */
4232 an_id = get_identifier ("super_class");
4233 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
4234 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
4237 static void
4238 error_with_ivar (const char *message, tree decl, tree rawdecl)
4240 error ("%J%s `%s'", decl,
4241 message, gen_declaration (rawdecl, errbuf));
4245 static void
4246 check_ivars (tree inter, tree imp)
4248 tree intdecls = CLASS_IVARS (inter);
4249 tree impdecls = CLASS_IVARS (imp);
4250 tree rawintdecls = CLASS_RAW_IVARS (inter);
4251 tree rawimpdecls = CLASS_RAW_IVARS (imp);
4253 while (1)
4255 tree t1, t2;
4257 #ifdef OBJCPLUS
4258 if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4259 intdecls = TREE_CHAIN (intdecls);
4260 #endif
4261 if (intdecls == 0 && impdecls == 0)
4262 break;
4263 if (intdecls == 0 || impdecls == 0)
4265 error ("inconsistent instance variable specification");
4266 break;
4269 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4271 if (!comptypes (t1, t2, false)
4272 || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
4273 TREE_VALUE (TREE_VALUE (rawimpdecls))))
4275 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4277 error_with_ivar ("conflicting instance variable type",
4278 impdecls, rawimpdecls);
4279 error_with_ivar ("previous declaration of",
4280 intdecls, rawintdecls);
4282 else /* both the type and the name don't match */
4284 error ("inconsistent instance variable specification");
4285 break;
4289 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4291 error_with_ivar ("conflicting instance variable name",
4292 impdecls, rawimpdecls);
4293 error_with_ivar ("previous declaration of",
4294 intdecls, rawintdecls);
4297 intdecls = TREE_CHAIN (intdecls);
4298 impdecls = TREE_CHAIN (impdecls);
4299 rawintdecls = TREE_CHAIN (rawintdecls);
4300 rawimpdecls = TREE_CHAIN (rawimpdecls);
4304 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
4305 This needs to be done just once per compilation. */
4307 static void
4308 build_super_template (void)
4310 tree decl_specs, field_decl, field_decl_chain;
4312 /* Suppress outputting debug symbols, because
4313 dbxout_init hasn't been called yet. */
4314 enum debug_info_type save_write_symbols = write_symbols;
4315 const struct gcc_debug_hooks *save_hooks = debug_hooks;
4317 write_symbols = NO_DEBUG;
4318 debug_hooks = &do_nothing_debug_hooks;
4320 objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
4322 /* struct objc_object *self; */
4324 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
4325 field_decl = get_identifier ("self");
4326 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
4327 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4328 field_decl_chain = field_decl;
4330 #ifdef OBJCPLUS
4331 /* struct objc_class *super_class; */
4332 #else
4333 /* struct objc_class *class; */
4334 #endif
4336 decl_specs = get_identifier (UTAG_CLASS);
4337 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
4338 #ifdef OBJCPLUS
4339 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
4340 #else
4341 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
4342 #endif
4344 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4345 chainon (field_decl_chain, field_decl);
4347 finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
4349 write_symbols = save_write_symbols;
4350 debug_hooks = save_hooks;
4353 /* struct objc_ivar {
4354 char *ivar_name;
4355 char *ivar_type;
4356 int ivar_offset;
4357 }; */
4359 static tree
4360 build_ivar_template (void)
4362 tree objc_ivar_id, objc_ivar_record;
4363 tree decl_specs, field_decl, field_decl_chain;
4365 objc_ivar_id = get_identifier (UTAG_IVAR);
4366 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
4368 /* char *ivar_name; */
4370 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4371 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
4373 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4374 field_decl_chain = field_decl;
4376 /* char *ivar_type; */
4378 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
4379 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
4381 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4382 chainon (field_decl_chain, field_decl);
4384 /* int ivar_offset; */
4386 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4387 field_decl = get_identifier ("ivar_offset");
4389 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4390 chainon (field_decl_chain, field_decl);
4392 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
4394 return objc_ivar_record;
4397 /* struct {
4398 int ivar_count;
4399 struct objc_ivar ivar_list[ivar_count];
4400 }; */
4402 static tree
4403 build_ivar_list_template (tree list_type, int size)
4405 tree objc_ivar_list_record;
4406 tree decl_specs, field_decl, field_decl_chain;
4408 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4410 /* int ivar_count; */
4412 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4413 field_decl = get_identifier ("ivar_count");
4415 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4416 field_decl_chain = field_decl;
4418 /* struct objc_ivar ivar_list[]; */
4420 decl_specs = build_tree_list (NULL_TREE, list_type);
4421 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
4422 build_int_2 (size, 0));
4424 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4425 chainon (field_decl_chain, field_decl);
4427 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4429 return objc_ivar_list_record;
4432 /* struct {
4433 int method_next;
4434 int method_count;
4435 struct objc_method method_list[method_count];
4436 }; */
4438 static tree
4439 build_method_list_template (tree list_type, int size)
4441 tree objc_ivar_list_record;
4442 tree decl_specs, field_decl, field_decl_chain;
4444 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4446 /* int method_next; */
4448 decl_specs
4449 = build_tree_list
4450 (NULL_TREE,
4451 xref_tag (RECORD_TYPE,
4452 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
4453 field_decl
4454 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
4455 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4456 field_decl_chain = field_decl;
4458 /* int method_count; */
4460 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
4461 field_decl = get_identifier ("method_count");
4463 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4464 chainon (field_decl_chain, field_decl);
4466 /* struct objc_method method_list[]; */
4468 decl_specs = build_tree_list (NULL_TREE, list_type);
4469 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
4470 build_int_2 (size, 0));
4472 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4473 chainon (field_decl_chain, field_decl);
4475 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4477 return objc_ivar_list_record;
4480 static tree
4481 build_ivar_list_initializer (tree type, tree field_decl)
4483 tree initlist = NULL_TREE;
4487 tree ivar = NULL_TREE;
4489 /* Set name. */
4490 if (DECL_NAME (field_decl))
4491 ivar = tree_cons (NULL_TREE,
4492 add_objc_string (DECL_NAME (field_decl),
4493 meth_var_names),
4494 ivar);
4495 else
4496 /* Unnamed bit-field ivar (yuck). */
4497 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
4499 /* Set type. */
4500 encode_field_decl (field_decl,
4501 obstack_object_size (&util_obstack),
4502 OBJC_ENCODE_DONT_INLINE_DEFS);
4504 /* Null terminate string. */
4505 obstack_1grow (&util_obstack, 0);
4506 ivar
4507 = tree_cons
4508 (NULL_TREE,
4509 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
4510 meth_var_types),
4511 ivar);
4512 obstack_free (&util_obstack, util_firstobj);
4514 /* Set offset. */
4515 ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
4516 initlist = tree_cons (NULL_TREE,
4517 objc_build_constructor (type, nreverse (ivar)),
4518 initlist);
4520 field_decl = TREE_CHAIN (field_decl);
4521 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
4523 while (field_decl);
4525 return objc_build_constructor (build_array_type (type, 0),
4526 nreverse (initlist));
4529 static tree
4530 generate_ivars_list (tree type, const char *name, int size, tree list)
4532 tree sc_spec, decl_specs, decl, initlist;
4534 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4535 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4537 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4538 decl_specs, 1, NULL_TREE);
4540 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
4541 initlist = tree_cons (NULL_TREE, list, initlist);
4543 finish_decl (decl,
4544 objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4545 NULL_TREE);
4547 return decl;
4550 /* Count only the fields occurring in T. */
4551 static int
4552 ivar_list_length (tree t)
4554 int count = 0;
4556 for (; t; t = TREE_CHAIN (t))
4557 if (TREE_CODE (t) == FIELD_DECL)
4558 ++count;
4560 return count;
4563 static void
4564 generate_ivar_lists (void)
4566 tree initlist, ivar_list_template, chain;
4567 tree cast, variable_length_type;
4568 int size;
4570 generating_instance_variables = 1;
4572 if (!objc_ivar_template)
4573 objc_ivar_template = build_ivar_template ();
4575 cast
4576 = build_tree_list
4577 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
4578 get_identifier (UTAG_IVAR_LIST))),
4579 NULL_TREE);
4580 variable_length_type = groktypename (cast);
4582 /* Only generate class variables for the root of the inheritance
4583 hierarchy since these will be the same for every class. */
4585 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
4586 && (chain = TYPE_FIELDS (objc_class_template)))
4588 size = ivar_list_length (chain);
4590 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4591 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4593 UOBJC_CLASS_VARIABLES_decl
4594 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
4595 size, initlist);
4596 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
4598 else
4599 UOBJC_CLASS_VARIABLES_decl = 0;
4601 chain = CLASS_IVARS (implementation_template);
4602 if (chain)
4604 size = ivar_list_length (chain);
4605 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4606 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4608 UOBJC_INSTANCE_VARIABLES_decl
4609 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
4610 size, initlist);
4611 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
4613 else
4614 UOBJC_INSTANCE_VARIABLES_decl = 0;
4616 generating_instance_variables = 0;
4619 static tree
4620 build_dispatch_table_initializer (tree type, tree entries)
4622 tree initlist = NULL_TREE;
4626 tree elemlist = NULL_TREE;
4628 elemlist = tree_cons (NULL_TREE,
4629 build_selector (METHOD_SEL_NAME (entries)),
4630 NULL_TREE);
4632 /* Generate the method encoding if we don't have one already. */
4633 if (! METHOD_ENCODING (entries))
4634 METHOD_ENCODING (entries) =
4635 encode_method_prototype (entries);
4637 elemlist = tree_cons (NULL_TREE,
4638 add_objc_string (METHOD_ENCODING (entries),
4639 meth_var_types),
4640 elemlist);
4642 elemlist = tree_cons (NULL_TREE,
4643 build_unary_op (ADDR_EXPR,
4644 METHOD_DEFINITION (entries), 1),
4645 elemlist);
4647 initlist = tree_cons (NULL_TREE,
4648 objc_build_constructor (type, nreverse (elemlist)),
4649 initlist);
4651 entries = TREE_CHAIN (entries);
4653 while (entries);
4655 return objc_build_constructor (build_array_type (type, 0),
4656 nreverse (initlist));
4659 /* To accomplish method prototyping without generating all kinds of
4660 inane warnings, the definition of the dispatch table entries were
4661 changed from:
4663 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4665 struct objc_method { SEL _cmd; ...; void *_imp; }; */
4667 static tree
4668 build_method_template (void)
4670 tree _SLT_record;
4671 tree decl_specs, field_decl, field_decl_chain;
4673 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4675 /* struct objc_selector *_cmd; */
4676 decl_specs = tree_cons (NULL_TREE,
4677 xref_tag (RECORD_TYPE,
4678 get_identifier (TAG_SELECTOR)),
4679 NULL_TREE);
4680 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4682 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4683 field_decl_chain = field_decl;
4685 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4686 field_decl = build1 (INDIRECT_REF, NULL_TREE,
4687 get_identifier ("method_types"));
4688 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4689 chainon (field_decl_chain, field_decl);
4691 /* void *_imp; */
4693 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4694 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4695 field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
4696 chainon (field_decl_chain, field_decl);
4698 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4700 return _SLT_record;
4704 static tree
4705 generate_dispatch_table (tree type, const char *name, int size, tree list)
4707 tree sc_spec, decl_specs, decl, initlist;
4709 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4710 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4712 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
4713 decl_specs, 1, NULL_TREE);
4715 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4716 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4717 initlist = tree_cons (NULL_TREE, list, initlist);
4719 finish_decl (decl,
4720 objc_build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4721 NULL_TREE);
4723 return decl;
4726 static void
4727 mark_referenced_methods (void)
4729 struct imp_entry *impent;
4730 tree chain;
4732 for (impent = imp_list; impent; impent = impent->next)
4734 chain = CLASS_CLS_METHODS (impent->imp_context);
4735 while (chain)
4737 cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4738 chain = TREE_CHAIN (chain);
4741 chain = CLASS_NST_METHODS (impent->imp_context);
4742 while (chain)
4744 cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4745 chain = TREE_CHAIN (chain);
4750 static void
4751 generate_dispatch_tables (void)
4753 tree initlist, chain, method_list_template;
4754 tree cast, variable_length_type;
4755 int size;
4757 if (!objc_method_template)
4758 objc_method_template = build_method_template ();
4760 cast
4761 = build_tree_list
4762 (build_tree_list (NULL_TREE,
4763 xref_tag (RECORD_TYPE,
4764 get_identifier (UTAG_METHOD_LIST))),
4765 NULL_TREE);
4767 variable_length_type = groktypename (cast);
4769 chain = CLASS_CLS_METHODS (objc_implementation_context);
4770 if (chain)
4772 size = list_length (chain);
4774 method_list_template
4775 = build_method_list_template (objc_method_template, size);
4776 initlist
4777 = build_dispatch_table_initializer (objc_method_template, chain);
4779 UOBJC_CLASS_METHODS_decl
4780 = generate_dispatch_table (method_list_template,
4781 ((TREE_CODE (objc_implementation_context)
4782 == CLASS_IMPLEMENTATION_TYPE)
4783 ? "_OBJC_CLASS_METHODS"
4784 : "_OBJC_CATEGORY_CLASS_METHODS"),
4785 size, initlist);
4786 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4788 else
4789 UOBJC_CLASS_METHODS_decl = 0;
4791 chain = CLASS_NST_METHODS (objc_implementation_context);
4792 if (chain)
4794 size = list_length (chain);
4796 method_list_template
4797 = build_method_list_template (objc_method_template, size);
4798 initlist
4799 = build_dispatch_table_initializer (objc_method_template, chain);
4801 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4802 UOBJC_INSTANCE_METHODS_decl
4803 = generate_dispatch_table (method_list_template,
4804 "_OBJC_INSTANCE_METHODS",
4805 size, initlist);
4806 else
4807 /* We have a category. */
4808 UOBJC_INSTANCE_METHODS_decl
4809 = generate_dispatch_table (method_list_template,
4810 "_OBJC_CATEGORY_INSTANCE_METHODS",
4811 size, initlist);
4812 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4814 else
4815 UOBJC_INSTANCE_METHODS_decl = 0;
4818 static tree
4819 generate_protocol_list (tree i_or_p)
4821 tree initlist, decl_specs, sc_spec;
4822 tree refs_decl, expr_decl, lproto, e, plist;
4823 tree cast_type;
4824 int size = 0;
4826 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4827 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4828 plist = CLASS_PROTOCOL_LIST (i_or_p);
4829 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4830 plist = PROTOCOL_LIST (i_or_p);
4831 else
4832 abort ();
4834 cast_type = groktypename
4835 (build_tree_list
4836 (build_tree_list (NULL_TREE,
4837 xref_tag (RECORD_TYPE,
4838 get_identifier (UTAG_PROTOCOL))),
4839 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4841 /* Compute size. */
4842 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4843 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4844 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4845 size++;
4847 /* Build initializer. */
4848 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4850 e = build_int_2 (size, 0);
4851 TREE_TYPE (e) = cast_type;
4852 initlist = tree_cons (NULL_TREE, e, initlist);
4854 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4856 tree pval = TREE_VALUE (lproto);
4858 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4859 && PROTOCOL_FORWARD_DECL (pval))
4861 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4862 initlist = tree_cons (NULL_TREE, e, initlist);
4866 /* static struct objc_protocol *refs[n]; */
4868 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4869 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4870 get_identifier (UTAG_PROTOCOL)),
4871 sc_spec);
4873 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4874 expr_decl = build_nt (ARRAY_REF,
4875 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4876 i_or_p),
4877 build_int_2 (size + 2, 0));
4878 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4879 expr_decl = build_nt (ARRAY_REF,
4880 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4881 i_or_p),
4882 build_int_2 (size + 2, 0));
4883 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4884 expr_decl
4885 = build_nt (ARRAY_REF,
4886 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4887 i_or_p),
4888 build_int_2 (size + 2, 0));
4889 else
4890 abort ();
4892 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4894 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
4895 DECL_CONTEXT (refs_decl) = NULL_TREE;
4897 finish_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4898 nreverse (initlist)),
4899 NULL_TREE);
4901 return refs_decl;
4904 static tree
4905 build_category_initializer (tree type, tree cat_name, tree class_name,
4906 tree instance_methods, tree class_methods,
4907 tree protocol_list)
4909 tree initlist = NULL_TREE, expr;
4911 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4912 initlist = tree_cons (NULL_TREE, class_name, initlist);
4914 if (!instance_methods)
4915 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4916 else
4918 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4919 initlist = tree_cons (NULL_TREE, expr, initlist);
4921 if (!class_methods)
4922 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4923 else
4925 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4926 initlist = tree_cons (NULL_TREE, expr, initlist);
4929 /* protocol_list = */
4930 if (!protocol_list)
4931 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4932 else
4934 tree cast_type2 = groktypename
4935 (build_tree_list
4936 (build_tree_list (NULL_TREE,
4937 xref_tag (RECORD_TYPE,
4938 get_identifier (UTAG_PROTOCOL))),
4939 build1 (INDIRECT_REF, NULL_TREE,
4940 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4942 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4943 TREE_TYPE (expr) = cast_type2;
4944 initlist = tree_cons (NULL_TREE, expr, initlist);
4947 return objc_build_constructor (type, nreverse (initlist));
4950 /* struct objc_class {
4951 struct objc_class *isa;
4952 struct objc_class *super_class;
4953 char *name;
4954 long version;
4955 long info;
4956 long instance_size;
4957 struct objc_ivar_list *ivars;
4958 struct objc_method_list *methods;
4959 if (flag_next_runtime)
4960 struct objc_cache *cache;
4961 else {
4962 struct sarray *dtable;
4963 struct objc_class *subclass_list;
4964 struct objc_class *sibling_class;
4966 struct objc_protocol_list *protocols;
4967 if (flag_next_runtime)
4968 void *sel_id;
4969 void *gc_object_type;
4970 }; */
4972 static tree
4973 build_shared_structure_initializer (tree type, tree isa, tree super,
4974 tree name, tree size, int status,
4975 tree dispatch_table, tree ivar_list,
4976 tree protocol_list)
4978 tree initlist = NULL_TREE, expr;
4980 /* isa = */
4981 initlist = tree_cons (NULL_TREE, isa, initlist);
4983 /* super_class = */
4984 initlist = tree_cons (NULL_TREE, super, initlist);
4986 /* name = */
4987 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4989 /* version = */
4990 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4992 /* info = */
4993 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4995 /* instance_size = */
4996 initlist = tree_cons (NULL_TREE, size, initlist);
4998 /* objc_ivar_list = */
4999 if (!ivar_list)
5000 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5001 else
5003 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
5004 initlist = tree_cons (NULL_TREE, expr, initlist);
5007 /* objc_method_list = */
5008 if (!dispatch_table)
5009 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5010 else
5012 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
5013 initlist = tree_cons (NULL_TREE, expr, initlist);
5016 if (flag_next_runtime)
5017 /* method_cache = */
5018 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5019 else
5021 /* dtable = */
5022 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5024 /* subclass_list = */
5025 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5027 /* sibling_class = */
5028 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5031 /* protocol_list = */
5032 if (! protocol_list)
5033 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5034 else
5036 tree cast_type2
5037 = groktypename
5038 (build_tree_list
5039 (build_tree_list (NULL_TREE,
5040 xref_tag (RECORD_TYPE,
5041 get_identifier (UTAG_PROTOCOL))),
5042 build1 (INDIRECT_REF, NULL_TREE,
5043 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
5045 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
5046 TREE_TYPE (expr) = cast_type2;
5047 initlist = tree_cons (NULL_TREE, expr, initlist);
5050 if (flag_next_runtime)
5051 /* sel_id = NULL */
5052 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5054 /* gc_object_type = NULL */
5055 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
5057 return objc_build_constructor (type, nreverse (initlist));
5060 /* Retrieve category interface CAT_NAME (if any) associated with CLASS. */
5062 static inline tree
5063 lookup_category (tree class, tree cat_name)
5065 tree category = CLASS_CATEGORY_LIST (class);
5067 while (category && CLASS_SUPER_NAME (category) != cat_name)
5068 category = CLASS_CATEGORY_LIST (category);
5069 return category;
5072 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
5074 static void
5075 generate_category (tree cat)
5077 tree sc_spec, decl_specs, decl;
5078 tree initlist, cat_name_expr, class_name_expr;
5079 tree protocol_decl, category;
5081 add_class_reference (CLASS_NAME (cat));
5082 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
5084 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
5086 category = lookup_category (implementation_template,
5087 CLASS_SUPER_NAME (cat));
5089 if (category && CLASS_PROTOCOL_LIST (category))
5091 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
5092 protocol_decl = generate_protocol_list (category);
5094 else
5095 protocol_decl = 0;
5097 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
5098 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
5100 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
5101 objc_implementation_context),
5102 decl_specs, 1, NULL_TREE);
5104 initlist = build_category_initializer (TREE_TYPE (decl),
5105 cat_name_expr, class_name_expr,
5106 UOBJC_INSTANCE_METHODS_decl,
5107 UOBJC_CLASS_METHODS_decl,
5108 protocol_decl);
5110 finish_decl (decl, initlist, NULL_TREE);
5113 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
5114 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5116 static void
5117 generate_shared_structures (void)
5119 tree sc_spec, decl_specs, decl;
5120 tree name_expr, super_expr, root_expr;
5121 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5122 tree cast_type, initlist, protocol_decl;
5124 my_super_id = CLASS_SUPER_NAME (implementation_template);
5125 if (my_super_id)
5127 add_class_reference (my_super_id);
5129 /* Compute "my_root_id" - this is required for code generation.
5130 the "isa" for all meta class structures points to the root of
5131 the inheritance hierarchy (e.g. "__Object")... */
5132 my_root_id = my_super_id;
5135 tree my_root_int = lookup_interface (my_root_id);
5137 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5138 my_root_id = CLASS_SUPER_NAME (my_root_int);
5139 else
5140 break;
5142 while (1);
5144 else
5145 /* No super class. */
5146 my_root_id = CLASS_NAME (implementation_template);
5148 cast_type
5149 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5150 objc_class_template),
5151 build1 (INDIRECT_REF,
5152 NULL_TREE, NULL_TREE)));
5154 name_expr = add_objc_string (CLASS_NAME (implementation_template),
5155 class_names);
5157 /* Install class `isa' and `super' pointers at runtime. */
5158 if (my_super_id)
5160 super_expr = add_objc_string (my_super_id, class_names);
5161 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5163 else
5164 super_expr = build_int_2 (0, 0);
5166 root_expr = add_objc_string (my_root_id, class_names);
5167 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5169 if (CLASS_PROTOCOL_LIST (implementation_template))
5171 generate_protocol_references
5172 (CLASS_PROTOCOL_LIST (implementation_template));
5173 protocol_decl = generate_protocol_list (implementation_template);
5175 else
5176 protocol_decl = 0;
5178 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5180 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5181 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5183 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
5184 NULL_TREE);
5186 initlist
5187 = build_shared_structure_initializer
5188 (TREE_TYPE (decl),
5189 root_expr, super_expr, name_expr,
5190 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5191 2 /*CLS_META*/,
5192 UOBJC_CLASS_METHODS_decl,
5193 UOBJC_CLASS_VARIABLES_decl,
5194 protocol_decl);
5196 finish_decl (decl, initlist, NULL_TREE);
5198 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5200 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
5201 NULL_TREE);
5203 initlist
5204 = build_shared_structure_initializer
5205 (TREE_TYPE (decl),
5206 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5207 super_expr, name_expr,
5208 convert (integer_type_node,
5209 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5210 (implementation_template))),
5211 1 /*CLS_FACTORY*/,
5212 UOBJC_INSTANCE_METHODS_decl,
5213 UOBJC_INSTANCE_VARIABLES_decl,
5214 protocol_decl);
5216 finish_decl (decl, initlist, NULL_TREE);
5219 static tree
5220 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5222 char *string;
5223 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5224 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5226 const char *const class_name
5227 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5228 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
5229 sprintf (string, "%s_%s", preamble,
5230 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5232 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5233 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5235 /* We have a category. */
5236 const char *const class_name
5237 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5238 const char *const class_super_name
5239 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5240 string = (char *) alloca (strlen (preamble)
5241 + strlen (class_name)
5242 + strlen (class_super_name)
5243 + 3);
5244 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5246 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5248 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5249 string
5250 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
5251 sprintf (string, "%s_%s", preamble, protocol_name);
5253 else
5254 abort ();
5256 return get_identifier (string);
5259 static int
5260 is_objc_type_qualifier (tree node)
5262 return (TREE_CODE (node) == IDENTIFIER_NODE
5263 && (node == ridpointers [(int) RID_CONST]
5264 || node == ridpointers [(int) RID_VOLATILE]
5265 || node == ridpointers [(int) RID_IN]
5266 || node == ridpointers [(int) RID_OUT]
5267 || node == ridpointers [(int) RID_INOUT]
5268 || node == ridpointers [(int) RID_BYCOPY]
5269 || node == ridpointers [(int) RID_BYREF]
5270 || node == ridpointers [(int) RID_ONEWAY]));
5273 /* If type is empty or only type qualifiers are present, add default
5274 type of id (otherwise grokdeclarator will default to int). */
5276 static tree
5277 adjust_type_for_id_default (tree type)
5279 tree declspecs, chain;
5281 if (!type)
5282 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
5283 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5285 declspecs = TREE_PURPOSE (type);
5287 /* Determine if a typespec is present. */
5288 for (chain = declspecs;
5289 chain;
5290 chain = TREE_CHAIN (chain))
5292 if (TYPED_OBJECT (TREE_VALUE (chain))
5293 && !(TREE_VALUE (type)
5294 && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
5295 error ("can not use an object as parameter to a method\n");
5296 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
5297 return type;
5300 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
5301 declspecs),
5302 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
5305 /* Usage:
5306 keyworddecl:
5307 selector ':' '(' typename ')' identifier
5309 Purpose:
5310 Transform an Objective-C keyword argument into
5311 the C equivalent parameter declarator.
5313 In: key_name, an "identifier_node" (optional).
5314 arg_type, a "tree_list" (optional).
5315 arg_name, an "identifier_node".
5317 Note: It would be really nice to strongly type the preceding
5318 arguments in the function prototype; however, then I
5319 could not use the "accessor" macros defined in "tree.h".
5321 Out: an instance of "keyword_decl". */
5323 tree
5324 build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5326 tree keyword_decl;
5328 /* If no type is specified, default to "id". */
5329 arg_type = adjust_type_for_id_default (arg_type);
5331 keyword_decl = make_node (KEYWORD_DECL);
5333 TREE_TYPE (keyword_decl) = arg_type;
5334 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5335 KEYWORD_KEY_NAME (keyword_decl) = key_name;
5337 return keyword_decl;
5340 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
5342 static tree
5343 build_keyword_selector (tree selector)
5345 int len = 0;
5346 tree key_chain, key_name;
5347 char *buf;
5349 /* Scan the selector to see how much space we'll need. */
5350 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5352 if (TREE_CODE (selector) == KEYWORD_DECL)
5353 key_name = KEYWORD_KEY_NAME (key_chain);
5354 else if (TREE_CODE (selector) == TREE_LIST)
5355 key_name = TREE_PURPOSE (key_chain);
5356 else
5357 abort ();
5359 if (key_name)
5360 len += IDENTIFIER_LENGTH (key_name) + 1;
5361 else
5362 /* Just a ':' arg. */
5363 len++;
5366 buf = (char *) alloca (len + 1);
5367 /* Start the buffer out as an empty string. */
5368 buf[0] = '\0';
5370 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5372 if (TREE_CODE (selector) == KEYWORD_DECL)
5373 key_name = KEYWORD_KEY_NAME (key_chain);
5374 else if (TREE_CODE (selector) == TREE_LIST)
5376 key_name = TREE_PURPOSE (key_chain);
5377 /* The keyword decl chain will later be used as a function argument
5378 chain. Unhook the selector itself so as to not confuse other
5379 parts of the compiler. */
5380 TREE_PURPOSE (key_chain) = NULL_TREE;
5382 else
5383 abort ();
5385 if (key_name)
5386 strcat (buf, IDENTIFIER_POINTER (key_name));
5387 strcat (buf, ":");
5390 return get_identifier (buf);
5393 /* Used for declarations and definitions. */
5395 tree
5396 build_method_decl (enum tree_code code, tree ret_type, tree selector,
5397 tree add_args)
5399 tree method_decl;
5401 /* If no type is specified, default to "id". */
5402 ret_type = adjust_type_for_id_default (ret_type);
5404 method_decl = make_node (code);
5405 TREE_TYPE (method_decl) = ret_type;
5407 /* If we have a keyword selector, create an identifier_node that
5408 represents the full selector name (`:' included)... */
5409 if (TREE_CODE (selector) == KEYWORD_DECL)
5411 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5412 METHOD_SEL_ARGS (method_decl) = selector;
5413 METHOD_ADD_ARGS (method_decl) = add_args;
5415 else
5417 METHOD_SEL_NAME (method_decl) = selector;
5418 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5419 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5422 return method_decl;
5425 #define METHOD_DEF 0
5426 #define METHOD_REF 1
5428 /* Used by `build_objc_method_call' and `comp_proto_with_proto'. Return
5429 an argument list for method METH. CONTEXT is either METHOD_DEF or
5430 METHOD_REF, saying whether we are trying to define a method or call
5431 one. SUPERFLAG says this is for a send to super; this makes a
5432 difference for the NeXT calling sequence in which the lookup and
5433 the method call are done together. If METH is null, user-defined
5434 arguments (i.e., beyond self and _cmd) shall be represented by `...'. */
5436 static tree
5437 get_arg_type_list (tree meth, int context, int superflag)
5439 tree arglist, akey;
5441 /* Receiver type. */
5442 if (flag_next_runtime && superflag)
5443 arglist = build_tree_list (NULL_TREE, super_type);
5444 else if (context == METHOD_DEF)
5445 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
5446 else
5447 arglist = build_tree_list (NULL_TREE, id_type);
5449 /* Selector type - will eventually change to `int'. */
5450 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
5452 /* No actual method prototype given -- assume that remaining arguments
5453 are `...'. */
5454 if (!meth)
5455 return arglist;
5457 /* Build a list of argument types. */
5458 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
5460 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
5461 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
5464 if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
5465 /* We have a `, ...' immediately following the selector,
5466 finalize the arglist...simulate get_parm_info (0). */
5468 else if (METHOD_ADD_ARGS (meth))
5470 /* we have a variable length selector */
5471 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
5472 chainon (arglist, add_arg_list);
5474 else
5475 /* finalize the arglist...simulate get_parm_info (1) */
5476 chainon (arglist, OBJC_VOID_AT_END);
5478 return arglist;
5481 static tree
5482 check_duplicates (hash hsh, int methods, int is_class)
5484 tree meth = NULL_TREE;
5486 if (hsh)
5488 meth = hsh->key;
5490 if (hsh->list)
5492 /* We have two or more methods with the same name but
5493 different types. */
5494 attr loop;
5496 warning ("multiple %s named `%c%s' found",
5497 methods ? "methods" : "selectors",
5498 (is_class ? '+' : '-'),
5499 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5501 warn_with_method (methods ? "using" : "found",
5502 ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5503 ? '-'
5504 : '+'),
5505 meth);
5506 for (loop = hsh->list; loop; loop = loop->next)
5507 warn_with_method ("also found",
5508 ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
5509 ? '-'
5510 : '+'),
5511 loop->value);
5514 return meth;
5517 /* If RECEIVER is a class reference, return the identifier node for
5518 the referenced class. RECEIVER is created by get_class_reference,
5519 so we check the exact form created depending on which runtimes are
5520 used. */
5522 static tree
5523 receiver_is_class_object (tree receiver, int self, int super)
5525 tree chain, exp, arg;
5527 /* The receiver is 'self' or 'super' in the context of a class method. */
5528 if (objc_method_context
5529 && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
5530 && (self || super))
5531 return (super
5532 ? CLASS_SUPER_NAME (implementation_template)
5533 : CLASS_NAME (implementation_template));
5535 if (flag_next_runtime)
5537 /* The receiver is a variable created by
5538 build_class_reference_decl. */
5539 if (TREE_CODE (receiver) == VAR_DECL
5540 && TREE_TYPE (TREE_TYPE (receiver)) == TREE_TYPE (objc_class_type))
5541 /* Look up the identifier. */
5542 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5543 if (TREE_PURPOSE (chain) == receiver)
5544 return TREE_VALUE (chain);
5547 /* The receiver is a function call that returns an id. Check if
5548 it is a call to objc_getClass, if so, pick up the class name. */
5549 if (TREE_CODE (receiver) == CALL_EXPR
5550 && (exp = TREE_OPERAND (receiver, 0))
5551 && TREE_CODE (exp) == ADDR_EXPR
5552 && (exp = TREE_OPERAND (exp, 0))
5553 && TREE_CODE (exp) == FUNCTION_DECL
5554 /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
5555 prototypes for objc_get_class(). Thankfuly, they seem to share the
5556 same function type. */
5557 && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
5558 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
5559 /* We have a call to objc_get_class/objc_getClass! */
5560 && (arg = TREE_OPERAND (receiver, 1))
5561 && TREE_CODE (arg) == TREE_LIST
5562 && (arg = TREE_VALUE (arg)))
5564 STRIP_NOPS (arg);
5565 if (TREE_CODE (arg) == ADDR_EXPR
5566 && (arg = TREE_OPERAND (arg, 0))
5567 && TREE_CODE (arg) == STRING_CST)
5568 /* Finally, we have the class name. */
5569 return get_identifier (TREE_STRING_POINTER (arg));
5571 return 0;
5574 /* If we are currently building a message expr, this holds
5575 the identifier of the selector of the message. This is
5576 used when printing warnings about argument mismatches. */
5578 static tree current_objc_message_selector = 0;
5580 tree
5581 objc_message_selector (void)
5583 return current_objc_message_selector;
5586 /* Construct an expression for sending a message.
5587 MESS has the object to send to in TREE_PURPOSE
5588 and the argument list (including selector) in TREE_VALUE.
5590 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
5591 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
5593 tree
5594 build_message_expr (tree mess)
5596 tree receiver = TREE_PURPOSE (mess);
5597 tree sel_name;
5598 tree args = TREE_VALUE (mess);
5599 tree method_params = NULL_TREE;
5601 if (TREE_CODE (receiver) == ERROR_MARK)
5602 return error_mark_node;
5604 /* Obtain the full selector name. */
5605 if (TREE_CODE (args) == IDENTIFIER_NODE)
5606 /* A unary selector. */
5607 sel_name = args;
5608 else if (TREE_CODE (args) == TREE_LIST)
5609 sel_name = build_keyword_selector (args);
5610 else
5611 abort ();
5613 /* Build the parameter list to give to the method. */
5614 if (TREE_CODE (args) == TREE_LIST)
5616 tree chain = args, prev = NULL_TREE;
5618 /* We have a keyword selector--check for comma expressions. */
5619 while (chain)
5621 tree element = TREE_VALUE (chain);
5623 /* We have a comma expression, must collapse... */
5624 if (TREE_CODE (element) == TREE_LIST)
5626 if (prev)
5627 TREE_CHAIN (prev) = element;
5628 else
5629 args = element;
5631 prev = chain;
5632 chain = TREE_CHAIN (chain);
5634 method_params = args;
5637 #ifdef OBJCPLUS
5638 if (processing_template_decl)
5639 /* Must wait until template instantiation time. */
5640 return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
5641 method_params);
5642 #endif
5644 return finish_message_expr (receiver, sel_name, method_params);
5647 /* Look up method SEL_NAME that would be suitable for receiver
5648 of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
5649 nonzero), and report on any duplicates. */
5651 static tree
5652 lookup_method_in_hash_lists (tree sel_name, int is_class)
5654 hash method_prototype = NULL;
5656 if (!is_class)
5657 method_prototype = hash_lookup (nst_method_hash_list,
5658 sel_name);
5660 if (!method_prototype)
5662 method_prototype = hash_lookup (cls_method_hash_list,
5663 sel_name);
5664 is_class = 1;
5667 return check_duplicates (method_prototype, 1, is_class);
5670 /* The 'finish_message_expr' routine is called from within
5671 'build_message_expr' for non-template functions. In the case of
5672 C++ template functions, it is called from 'build_expr_from_tree'
5673 (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */
5675 tree
5676 finish_message_expr (tree receiver, tree sel_name, tree method_params)
5678 tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
5679 tree selector, retval, is_class;
5680 int self, super, have_cast;
5682 /* Extract the receiver of the message, as well as its type
5683 (where the latter may take the form of a cast or be inferred
5684 from the implementation context). */
5685 rtype = receiver;
5686 while (TREE_CODE (rtype) == COMPOUND_EXPR
5687 || TREE_CODE (rtype) == MODIFY_EXPR
5688 || TREE_CODE (rtype) == NOP_EXPR
5689 || TREE_CODE (rtype) == COMPONENT_REF)
5690 rtype = TREE_OPERAND (rtype, 0);
5691 self = (rtype == self_decl);
5692 super = (rtype == UOBJC_SUPER_decl);
5693 rtype = TREE_TYPE (receiver);
5694 have_cast = (TREE_CODE (receiver) == NOP_EXPR
5695 || (TREE_CODE (receiver) == COMPOUND_EXPR
5696 && !IS_SUPER (rtype)));
5698 /* If the receiver is a class object, retrieve the corresponding
5699 @interface, if one exists. */
5700 is_class = receiver_is_class_object (receiver, self, super);
5702 /* Now determine the receiver type (if an explicit cast has not been
5703 provided). */
5704 if (!have_cast)
5706 if (is_class)
5707 rtype = lookup_interface (is_class);
5708 /* Handle `self' and `super'. */
5709 else if (super)
5711 if (!CLASS_SUPER_NAME (implementation_template))
5713 error ("no super class declared in @interface for `%s'",
5714 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5715 return error_mark_node;
5717 rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5719 else if (self)
5720 rtype = lookup_interface (CLASS_NAME (implementation_template));
5723 /* If receiver is of type `id' or `Class' (or if the @interface for a
5724 class is not visible), we shall be satisfied with the existence of
5725 any instance or class method. */
5726 if (!rtype || IS_ID (rtype)
5727 || TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
5729 if (!rtype)
5730 rtype = xref_tag (RECORD_TYPE, is_class);
5731 else if (IS_ID (rtype))
5733 rprotos = TYPE_PROTOCOL_LIST (rtype);
5734 rtype = NULL_TREE;
5736 else
5737 is_class = TYPE_NAME (rtype) = get_identifier ("Class");
5739 if (rprotos)
5740 method_prototype
5741 = lookup_method_in_protocol_list (rprotos, sel_name,
5742 is_class != NULL_TREE);
5743 if (!method_prototype && !rprotos)
5744 method_prototype
5745 = lookup_method_in_hash_lists (sel_name,
5746 is_class != NULL_TREE);
5748 else
5750 tree orig_rtype = rtype, saved_rtype;
5752 if (TREE_CODE (rtype) == POINTER_TYPE)
5753 rtype = TREE_TYPE (rtype);
5754 /* Traverse typedef aliases */
5755 while (TREE_CODE (rtype) == RECORD_TYPE && TYPE_NAME (rtype)
5756 && TREE_CODE (TYPE_NAME (rtype)) == TYPE_DECL
5757 && DECL_ORIGINAL_TYPE (TYPE_NAME (rtype)))
5758 rtype = DECL_ORIGINAL_TYPE (TYPE_NAME (rtype));
5759 saved_rtype = rtype;
5760 if (TYPED_OBJECT (rtype))
5762 rprotos = TYPE_PROTOCOL_LIST (rtype);
5763 rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
5765 /* If we could not find an @interface declaration, we must have
5766 only seen a @class declaration; so, we cannot say anything
5767 more intelligent about which methods the receiver will
5768 understand. */
5769 if (!rtype)
5770 rtype = saved_rtype;
5771 else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
5772 || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
5774 /* We have a valid ObjC class name. Look up the method name
5775 in the published @interface for the class (and its
5776 superclasses). */
5777 method_prototype
5778 = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
5780 /* If the method was not found in the @interface, it may still
5781 exist locally as part of the @implementation. */
5782 if (!method_prototype && objc_implementation_context
5783 && CLASS_NAME (objc_implementation_context)
5784 == OBJC_TYPE_NAME (rtype))
5785 method_prototype
5786 = lookup_method
5787 ((is_class
5788 ? CLASS_CLS_METHODS (objc_implementation_context)
5789 : CLASS_NST_METHODS (objc_implementation_context)),
5790 sel_name);
5792 /* If we haven't found a candidate method by now, try looking for
5793 it in the protocol list. */
5794 if (!method_prototype && rprotos)
5795 method_prototype
5796 = lookup_method_in_protocol_list (rprotos, sel_name,
5797 is_class != NULL_TREE);
5799 else
5801 warning ("invalid receiver type `%s'",
5802 gen_declaration (orig_rtype, errbuf));
5803 rtype = rprotos = NULL_TREE;
5807 if (!method_prototype)
5809 static bool warn_missing_methods = false;
5811 if (rtype)
5812 warning ("`%s' may not respond to `%c%s'",
5813 IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
5814 (is_class ? '+' : '-'),
5815 IDENTIFIER_POINTER (sel_name));
5816 if (rprotos)
5817 warning ("`%c%s' not implemented by protocol(s)",
5818 (is_class ? '+' : '-'),
5819 IDENTIFIER_POINTER (sel_name));
5820 if (!warn_missing_methods)
5822 warning ("(Messages without a matching method signature");
5823 warning ("will be assumed to return `id' and accept");
5824 warning ("`...' as arguments.)");
5825 warn_missing_methods = true;
5829 /* Save the selector name for printing error messages. */
5830 current_objc_message_selector = sel_name;
5832 /* Build the parameters list for looking up the method.
5833 These are the object itself and the selector. */
5835 if (flag_typed_selectors)
5836 selector = build_typed_selector_reference (sel_name, method_prototype);
5837 else
5838 selector = build_selector_reference (sel_name);
5840 retval = build_objc_method_call (super, method_prototype,
5841 receiver,
5842 selector, method_params);
5844 current_objc_message_selector = 0;
5846 return retval;
5849 /* Build a tree expression to send OBJECT the operation SELECTOR,
5850 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5851 assuming the method has prototype METHOD_PROTOTYPE.
5852 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5853 Use METHOD_PARAMS as list of args to pass to the method.
5854 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5856 static tree
5857 build_objc_method_call (int super_flag, tree method_prototype,
5858 tree lookup_object, tree selector,
5859 tree method_params)
5861 tree sender = (super_flag ? umsg_super_decl :
5862 (!flag_next_runtime || flag_nil_receivers
5863 ? umsg_decl
5864 : umsg_nonnil_decl));
5865 tree rcv_p = (super_flag ? super_type : id_type);
5867 /* If a prototype for the method to be called exists, then cast
5868 the sender's return type and arguments to match that of the method.
5869 Otherwise, leave sender as is. */
5870 tree ret_type
5871 = (method_prototype
5872 ? groktypename (TREE_TYPE (method_prototype))
5873 : id_type);
5874 tree sender_cast
5875 = build_pointer_type
5876 (build_function_type
5877 (ret_type,
5878 get_arg_type_list
5879 (method_prototype, METHOD_REF, super_flag)));
5881 lookup_object = build_c_cast (rcv_p, lookup_object);
5883 if (flag_next_runtime)
5885 /* If we are returning a struct in memory, and the address
5886 of that memory location is passed as a hidden first
5887 argument, then change which messenger entry point this
5888 expr will call. NB: Note that sender_cast remains
5889 unchanged (it already has a struct return type). */
5890 if (!targetm.calls.struct_value_rtx (0, 0)
5891 && (TREE_CODE (ret_type) == RECORD_TYPE
5892 || TREE_CODE (ret_type) == UNION_TYPE)
5893 && targetm.calls.return_in_memory (ret_type, 0))
5894 sender = (super_flag ? umsg_super_stret_decl :
5895 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
5897 method_params = tree_cons (NULL_TREE, lookup_object,
5898 tree_cons (NULL_TREE, selector,
5899 method_params));
5900 TREE_USED (sender) = 1;
5901 assemble_external (sender);
5902 /* We want to cast the sender, not convert it. */
5903 return build_function_call (build_c_cast (sender_cast, sender),
5904 method_params);
5906 else
5908 /* This is the portable (GNU) way. */
5909 tree method, object;
5911 /* First, call the lookup function to get a pointer to the method,
5912 then cast the pointer, then call it with the method arguments.
5913 Use SAVE_EXPR to avoid evaluating the receiver twice. */
5914 lookup_object = save_expr (lookup_object);
5915 object = (super_flag ? self_decl : lookup_object);
5916 TREE_USED (sender) = 1;
5917 assemble_external (sender);
5918 method
5919 = build_function_call (sender,
5920 tree_cons (NULL_TREE, lookup_object,
5921 tree_cons (NULL_TREE, selector,
5922 NULL_TREE)));
5924 /* Pass the object to the method. */
5925 TREE_USED (method) = 1;
5926 assemble_external (method);
5927 return build_function_call
5928 (build_c_cast (sender_cast, method),
5929 tree_cons (NULL_TREE, object,
5930 tree_cons (NULL_TREE, selector, method_params)));
5934 static void
5935 build_protocol_reference (tree p)
5937 tree decl, ident, ptype;
5939 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5941 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5942 ptype
5943 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5944 objc_protocol_template),
5945 NULL_TREE));
5947 if (identifier_global_value (ident))
5948 decl = identifier_global_value (ident); /* Set by pushdecl. */
5949 else
5951 decl = build_decl (VAR_DECL, ident, ptype);
5952 DECL_EXTERNAL (decl) = 1;
5953 TREE_PUBLIC (decl) = 0;
5954 TREE_USED (decl) = 1;
5955 DECL_ARTIFICIAL (decl) = 1;
5957 make_decl_rtl (decl, 0);
5958 pushdecl_top_level (decl);
5961 PROTOCOL_FORWARD_DECL (p) = decl;
5964 /* This function is called by the parser when (and only when) a
5965 @protocol() expression is found, in order to compile it. */
5966 tree
5967 build_protocol_expr (tree protoname)
5969 tree expr;
5970 tree p = lookup_protocol (protoname);
5972 if (!p)
5974 error ("cannot find protocol declaration for `%s'",
5975 IDENTIFIER_POINTER (protoname));
5976 return error_mark_node;
5979 if (!PROTOCOL_FORWARD_DECL (p))
5980 build_protocol_reference (p);
5982 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5984 TREE_TYPE (expr) = protocol_type;
5986 /* The @protocol() expression is being compiled into a pointer to a
5987 statically allocated instance of the Protocol class. To become
5988 usable at runtime, the 'isa' pointer of the instance need to be
5989 fixed up at runtime by the runtime library, to point to the
5990 actual 'Protocol' class. */
5992 /* For the GNU runtime, put the static Protocol instance in the list
5993 of statically allocated instances, so that we make sure that its
5994 'isa' pointer is fixed up at runtime by the GNU runtime library
5995 to point to the Protocol class (at runtime, when loading the
5996 module, the GNU runtime library loops on the statically allocated
5997 instances (as found in the defs field in objc_symtab) and fixups
5998 all the 'isa' pointers of those objects). */
5999 if (! flag_next_runtime)
6001 /* This type is a struct containing the fields of a Protocol
6002 object. (Cfr. protocol_type instead is the type of a pointer
6003 to such a struct). */
6004 tree protocol_struct_type = xref_tag
6005 (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
6006 tree *chain;
6008 /* Look for the list of Protocol statically allocated instances
6009 to fixup at runtime. Create a new list to hold Protocol
6010 statically allocated instances, if the list is not found. At
6011 present there is only another list, holding NSConstantString
6012 static instances to be fixed up at runtime. */
6013 for (chain = &objc_static_instances;
6014 *chain && TREE_VALUE (*chain) != protocol_struct_type;
6015 chain = &TREE_CHAIN (*chain));
6016 if (!*chain)
6018 *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
6019 add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
6020 class_names);
6023 /* Add this statically allocated instance to the Protocol list. */
6024 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
6025 PROTOCOL_FORWARD_DECL (p),
6026 TREE_PURPOSE (*chain));
6030 return expr;
6033 /* This function is called by the parser when a @selector() expression
6034 is found, in order to compile it. It is only called by the parser
6035 and only to compile a @selector(). */
6036 tree
6037 build_selector_expr (tree selnamelist)
6039 tree selname;
6041 /* Obtain the full selector name. */
6042 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
6043 /* A unary selector. */
6044 selname = selnamelist;
6045 else if (TREE_CODE (selnamelist) == TREE_LIST)
6046 selname = build_keyword_selector (selnamelist);
6047 else
6048 abort ();
6050 /* If we are required to check @selector() expressions as they
6051 are found, check that the selector has been declared. */
6052 if (warn_undeclared_selector)
6054 /* Look the selector up in the list of all known class and
6055 instance methods (up to this line) to check that the selector
6056 exists. */
6057 hash hsh;
6059 /* First try with instance methods. */
6060 hsh = hash_lookup (nst_method_hash_list, selname);
6062 /* If not found, try with class methods. */
6063 if (!hsh)
6065 hsh = hash_lookup (cls_method_hash_list, selname);
6068 /* If still not found, print out a warning. */
6069 if (!hsh)
6071 warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
6076 if (flag_typed_selectors)
6077 return build_typed_selector_reference (selname, 0);
6078 else
6079 return build_selector_reference (selname);
6082 tree
6083 build_encode_expr (tree type)
6085 tree result;
6086 const char *string;
6088 encode_type (type, obstack_object_size (&util_obstack),
6089 OBJC_ENCODE_INLINE_DEFS);
6090 obstack_1grow (&util_obstack, 0); /* null terminate string */
6091 string = obstack_finish (&util_obstack);
6093 /* Synthesize a string that represents the encoded struct/union. */
6094 result = my_build_string (strlen (string) + 1, string);
6095 obstack_free (&util_obstack, util_firstobj);
6096 return result;
6099 tree
6100 build_ivar_reference (tree id)
6102 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
6104 /* Historically, a class method that produced objects (factory
6105 method) would assign `self' to the instance that it
6106 allocated. This would effectively turn the class method into
6107 an instance method. Following this assignment, the instance
6108 variables could be accessed. That practice, while safe,
6109 violates the simple rule that a class method should not refer
6110 to an instance variable. It's better to catch the cases
6111 where this is done unknowingly than to support the above
6112 paradigm. */
6113 warning ("instance variable `%s' accessed in class method",
6114 IDENTIFIER_POINTER (id));
6115 TREE_TYPE (self_decl) = instance_type; /* cast */
6118 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
6121 /* Compute a hash value for a given method SEL_NAME. */
6123 static size_t
6124 hash_func (tree sel_name)
6126 const unsigned char *s
6127 = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6128 size_t h = 0;
6130 while (*s)
6131 h = h * 67 + *s++ - 113;
6132 return h;
6135 static void
6136 hash_init (void)
6138 nst_method_hash_list
6139 = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6140 cls_method_hash_list
6141 = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6144 /* WARNING!!!! hash_enter is called with a method, and will peek
6145 inside to find its selector! But hash_lookup is given a selector
6146 directly, and looks for the selector that's inside the found
6147 entry's key (method) for comparison. */
6149 static void
6150 hash_enter (hash *hashlist, tree method)
6152 hash obj;
6153 int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6155 obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6156 obj->list = 0;
6157 obj->next = hashlist[slot];
6158 obj->key = method;
6160 hashlist[slot] = obj; /* append to front */
6163 static hash
6164 hash_lookup (hash *hashlist, tree sel_name)
6166 hash target;
6168 target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6170 while (target)
6172 if (sel_name == METHOD_SEL_NAME (target->key))
6173 return target;
6175 target = target->next;
6177 return 0;
6180 static void
6181 hash_add_attr (hash entry, tree value)
6183 attr obj;
6185 obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6186 obj->next = entry->list;
6187 obj->value = value;
6189 entry->list = obj; /* append to front */
6192 static tree
6193 lookup_method (tree mchain, tree method)
6195 tree key;
6197 if (TREE_CODE (method) == IDENTIFIER_NODE)
6198 key = method;
6199 else
6200 key = METHOD_SEL_NAME (method);
6202 while (mchain)
6204 if (METHOD_SEL_NAME (mchain) == key)
6205 return mchain;
6207 mchain = TREE_CHAIN (mchain);
6209 return NULL_TREE;
6212 static tree
6213 lookup_method_static (tree interface, tree ident, int is_class)
6215 tree meth = NULL_TREE, root_inter = NULL_TREE;
6216 tree inter = interface;
6218 while (inter)
6220 tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6221 tree category = inter;
6223 /* First, look up the method in the class itself. */
6224 if ((meth = lookup_method (chain, ident)))
6225 return meth;
6227 /* Failing that, look for the method in each category of the class. */
6228 while ((category = CLASS_CATEGORY_LIST (category)))
6230 chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6232 /* Check directly in each category. */
6233 if ((meth = lookup_method (chain, ident)))
6234 return meth;
6236 /* Failing that, check in each category's protocols. */
6237 if (CLASS_PROTOCOL_LIST (category))
6239 if ((meth = (lookup_method_in_protocol_list
6240 (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6241 return meth;
6245 /* If not found in categories, check in protocols of the main class. */
6246 if (CLASS_PROTOCOL_LIST (inter))
6248 if ((meth = (lookup_method_in_protocol_list
6249 (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6250 return meth;
6253 /* Failing that, climb up the inheritance hierarchy. */
6254 root_inter = inter;
6255 inter = lookup_interface (CLASS_SUPER_NAME (inter));
6257 while (inter);
6259 /* If no class (factory) method was found, check if an _instance_
6260 method of the same name exists in the root class. This is what
6261 the Objective-C runtime will do. If an instance method was not
6262 found, return 0. */
6263 return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6266 /* Add the method to the hash list if it doesn't contain an identical
6267 method already. */
6268 static void
6269 add_method_to_hash_list (hash *hash_list, tree method)
6271 hash hsh;
6273 if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6275 /* Install on a global chain. */
6276 hash_enter (hash_list, method);
6278 else
6280 /* Check types against those; if different, add to a list. */
6281 attr loop;
6282 int already_there = comp_proto_with_proto (method, hsh->key);
6283 for (loop = hsh->list; !already_there && loop; loop = loop->next)
6284 already_there |= comp_proto_with_proto (method, loop->value);
6285 if (!already_there)
6286 hash_add_attr (hsh, method);
6290 tree
6291 objc_add_method (tree class, tree method, int is_class)
6293 tree mth;
6295 if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
6297 /* put method on list in reverse order */
6298 if (is_class)
6300 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6301 CLASS_CLS_METHODS (class) = method;
6303 else
6305 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6306 CLASS_NST_METHODS (class) = method;
6309 else
6311 /* When processing an @interface for a class or category, give hard
6312 errors on methods with identical selectors but differing argument
6313 and/or return types. We do not do this for @implementations, because
6314 C/C++ will do it for us (i.e., there will be duplicate function
6315 definition errors). */
6316 if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6317 || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6318 && !comp_proto_with_proto (method, mth))
6319 error ("duplicate declaration of method `%c%s'",
6320 is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6323 if (is_class)
6324 add_method_to_hash_list (cls_method_hash_list, method);
6325 else
6327 add_method_to_hash_list (nst_method_hash_list, method);
6329 /* Instance methods in root classes (and categories thereof)
6330 may acts as class methods as a last resort. */
6331 if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6332 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6333 class = lookup_interface (CLASS_NAME (class));
6335 if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
6336 && !CLASS_SUPER_NAME (class))
6337 add_method_to_hash_list (cls_method_hash_list, method);
6340 return method;
6343 static tree
6344 add_class (tree class)
6346 /* Put interfaces on list in reverse order. */
6347 TREE_CHAIN (class) = interface_chain;
6348 interface_chain = class;
6349 return interface_chain;
6352 static void
6353 add_category (tree class, tree category)
6355 /* Put categories on list in reverse order. */
6356 tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
6358 if (cat)
6360 warning ("duplicate interface declaration for category `%s(%s)'",
6361 IDENTIFIER_POINTER (CLASS_NAME (class)),
6362 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
6364 else
6366 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
6367 CLASS_CATEGORY_LIST (class) = category;
6371 /* Called after parsing each instance variable declaration. Necessary to
6372 preserve typedefs and implement public/private...
6374 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
6376 tree
6377 add_instance_variable (tree class, int public, tree declarator,
6378 tree declspecs, tree width)
6380 tree field_decl = grokfield (declarator, declspecs, width);
6381 tree field_type = TREE_TYPE (field_decl);
6382 const char *ivar_name = DECL_NAME (field_decl)
6383 ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
6384 : "<unnamed>";
6385 tree raw_decl;
6387 #ifdef OBJCPLUS
6388 if (TREE_CODE (field_type) == REFERENCE_TYPE)
6390 error ("illegal reference type specified for instance variable `%s'",
6391 ivar_name);
6392 /* Return class as is without adding this ivar. */
6393 return class;
6395 #endif
6397 if (field_type == error_mark_node || !TYPE_SIZE (field_type)
6398 || TYPE_SIZE (field_type) == error_mark_node
6399 /* 'type[0]' is allowed, but 'type[]' is not! */
6400 #ifdef OBJCPLUS
6401 || (TYPE_SIZE (field_type) == bitsize_zero_node
6402 && !TREE_OPERAND (declarator, 1))
6403 #endif
6406 error ("instance variable `%s' has unknown size", ivar_name);
6407 /* Return class as is without adding this ivar. */
6408 return class;
6411 #ifdef OBJCPLUS
6412 /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
6413 cannot be ivars; ditto for classes with vtables. */
6414 if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
6415 || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
6417 const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
6418 if(TYPE_POLYMORPHIC_P (field_type)) {
6419 /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
6420 error ("type `%s' has virtual member functions", type_name);
6421 error ("illegal aggregate type `%s' specified for instance variable `%s'",
6422 type_name, ivar_name);
6423 /* Return class as is without adding this ivar. */
6424 return class;
6426 /* user-defined constructors and destructors are not known to Obj-C and
6427 hence will not be called. This may or may not be a problem. */
6428 if (TYPE_NEEDS_CONSTRUCTING (field_type))
6429 warning ("type `%s' has a user-defined constructor", type_name);
6430 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
6431 warning ("type `%s' has a user-defined destructor", type_name);
6432 warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
6434 #endif
6436 /* Overload the public attribute, it is not used for FIELD_DECLs. */
6437 switch (public)
6439 case 0:
6440 TREE_PUBLIC (field_decl) = 0;
6441 TREE_PRIVATE (field_decl) = 0;
6442 TREE_PROTECTED (field_decl) = 1;
6443 break;
6445 case 1:
6446 TREE_PUBLIC (field_decl) = 1;
6447 TREE_PRIVATE (field_decl) = 0;
6448 TREE_PROTECTED (field_decl) = 0;
6449 break;
6451 case 2:
6452 TREE_PUBLIC (field_decl) = 0;
6453 TREE_PRIVATE (field_decl) = 1;
6454 TREE_PROTECTED (field_decl) = 0;
6455 break;
6459 raw_decl = build_tree_list (declspecs, build_tree_list (declarator, width));
6460 CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), raw_decl);
6461 CLASS_IVARS (class) = chainon (CLASS_IVARS (class), field_decl);
6462 return class;
6465 tree
6466 is_ivar (tree decl_chain, tree ident)
6468 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
6469 if (DECL_NAME (decl_chain) == ident)
6470 return decl_chain;
6471 return NULL_TREE;
6474 /* True if the ivar is private and we are not in its implementation. */
6477 is_private (tree decl)
6479 if (TREE_PRIVATE (decl)
6480 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
6482 error ("instance variable `%s' is declared private",
6483 IDENTIFIER_POINTER (DECL_NAME (decl)));
6484 return 1;
6486 else
6487 return 0;
6490 /* We have an instance variable reference;, check to see if it is public. */
6493 is_public (tree expr, tree identifier)
6495 tree basetype = TREE_TYPE (expr);
6496 enum tree_code code = TREE_CODE (basetype);
6497 tree decl;
6499 if (code == RECORD_TYPE)
6501 if (TREE_STATIC_TEMPLATE (basetype))
6503 if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6505 error ("cannot find interface declaration for `%s'",
6506 IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6507 return 0;
6510 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6512 if (TREE_PUBLIC (decl))
6513 return 1;
6515 /* Important difference between the Stepstone translator:
6516 all instance variables should be public within the context
6517 of the implementation. */
6518 if (objc_implementation_context
6519 && (((TREE_CODE (objc_implementation_context)
6520 == CLASS_IMPLEMENTATION_TYPE)
6521 || (TREE_CODE (objc_implementation_context)
6522 == CATEGORY_IMPLEMENTATION_TYPE))
6523 && (CLASS_NAME (objc_implementation_context)
6524 == OBJC_TYPE_NAME (basetype))))
6525 return ! is_private (decl);
6527 /* The 2.95.2 compiler sometimes allowed C functions to access
6528 non-@public ivars. We will let this slide for now... */
6529 if (!objc_method_context)
6531 warning ("instance variable `%s' is %s; "
6532 "this will be a hard error in the future",
6533 IDENTIFIER_POINTER (identifier),
6534 TREE_PRIVATE (decl) ? "@private" : "@protected");
6535 return 1;
6538 error ("instance variable `%s' is declared %s",
6539 IDENTIFIER_POINTER (identifier),
6540 TREE_PRIVATE (decl) ? "private" : "protected");
6541 return 0;
6545 else if (objc_implementation_context && (basetype == objc_object_reference))
6547 TREE_TYPE (expr) = uprivate_record;
6548 warning ("static access to object of type `id'");
6552 return 1;
6555 /* Make sure all entries in CHAIN are also in LIST. */
6557 static int
6558 check_methods (tree chain, tree list, int mtype)
6560 int first = 1;
6562 while (chain)
6564 if (!lookup_method (list, chain))
6566 if (first)
6568 if (TREE_CODE (objc_implementation_context)
6569 == CLASS_IMPLEMENTATION_TYPE)
6570 warning ("incomplete implementation of class `%s'",
6571 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6572 else if (TREE_CODE (objc_implementation_context)
6573 == CATEGORY_IMPLEMENTATION_TYPE)
6574 warning ("incomplete implementation of category `%s'",
6575 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6576 first = 0;
6579 warning ("method definition for `%c%s' not found",
6580 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6583 chain = TREE_CHAIN (chain);
6586 return first;
6589 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */
6591 static int
6592 conforms_to_protocol (tree class, tree protocol)
6594 if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6596 tree p = CLASS_PROTOCOL_LIST (class);
6597 while (p && TREE_VALUE (p) != protocol)
6598 p = TREE_CHAIN (p);
6600 if (!p)
6602 tree super = (CLASS_SUPER_NAME (class)
6603 ? lookup_interface (CLASS_SUPER_NAME (class))
6604 : NULL_TREE);
6605 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6606 if (!tmp)
6607 return 0;
6611 return 1;
6614 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6615 CONTEXT. This is one of two mechanisms to check protocol integrity. */
6617 static int
6618 check_methods_accessible (tree chain, tree context, int mtype)
6620 int first = 1;
6621 tree list;
6622 tree base_context = context;
6624 while (chain)
6626 context = base_context;
6627 while (context)
6629 if (mtype == '+')
6630 list = CLASS_CLS_METHODS (context);
6631 else
6632 list = CLASS_NST_METHODS (context);
6634 if (lookup_method (list, chain))
6635 break;
6637 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6638 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6639 context = (CLASS_SUPER_NAME (context)
6640 ? lookup_interface (CLASS_SUPER_NAME (context))
6641 : NULL_TREE);
6643 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6644 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6645 context = (CLASS_NAME (context)
6646 ? lookup_interface (CLASS_NAME (context))
6647 : NULL_TREE);
6648 else
6649 abort ();
6652 if (context == NULL_TREE)
6654 if (first)
6656 if (TREE_CODE (objc_implementation_context)
6657 == CLASS_IMPLEMENTATION_TYPE)
6658 warning ("incomplete implementation of class `%s'",
6659 IDENTIFIER_POINTER
6660 (CLASS_NAME (objc_implementation_context)));
6661 else if (TREE_CODE (objc_implementation_context)
6662 == CATEGORY_IMPLEMENTATION_TYPE)
6663 warning ("incomplete implementation of category `%s'",
6664 IDENTIFIER_POINTER
6665 (CLASS_SUPER_NAME (objc_implementation_context)));
6666 first = 0;
6668 warning ("method definition for `%c%s' not found",
6669 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6672 chain = TREE_CHAIN (chain); /* next method... */
6674 return first;
6677 /* Check whether the current interface (accessible via
6678 'objc_implementation_context') actually implements protocol P, along
6679 with any protocols that P inherits. */
6681 static void
6682 check_protocol (tree p, const char *type, const char *name)
6684 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6686 int f1, f2;
6688 /* Ensure that all protocols have bodies! */
6689 if (warn_protocol)
6691 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6692 CLASS_CLS_METHODS (objc_implementation_context),
6693 '+');
6694 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6695 CLASS_NST_METHODS (objc_implementation_context),
6696 '-');
6698 else
6700 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6701 objc_implementation_context,
6702 '+');
6703 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6704 objc_implementation_context,
6705 '-');
6708 if (!f1 || !f2)
6709 warning ("%s `%s' does not fully implement the `%s' protocol",
6710 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6713 /* Check protocols recursively. */
6714 if (PROTOCOL_LIST (p))
6716 tree subs = PROTOCOL_LIST (p);
6717 tree super_class =
6718 lookup_interface (CLASS_SUPER_NAME (implementation_template));
6720 while (subs)
6722 tree sub = TREE_VALUE (subs);
6724 /* If the superclass does not conform to the protocols
6725 inherited by P, then we must! */
6726 if (!super_class || !conforms_to_protocol (super_class, sub))
6727 check_protocol (sub, type, name);
6728 subs = TREE_CHAIN (subs);
6733 /* Check whether the current interface (accessible via
6734 'objc_implementation_context') actually implements the protocols listed
6735 in PROTO_LIST. */
6737 static void
6738 check_protocols (tree proto_list, const char *type, const char *name)
6740 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6742 tree p = TREE_VALUE (proto_list);
6744 check_protocol (p, type, name);
6748 /* Make sure that the class CLASS_NAME is defined
6749 CODE says which kind of thing CLASS_NAME ought to be.
6750 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6751 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
6753 tree
6754 start_class (enum tree_code code, tree class_name, tree super_name,
6755 tree protocol_list)
6757 tree class, decl;
6759 #ifdef OBJCPLUS
6760 if (current_namespace != global_namespace) {
6761 error ("Objective-C declarations may only appear in global scope");
6763 #endif /* OBJCPLUS */
6765 if (objc_implementation_context)
6767 warning ("`@end' missing in implementation context");
6768 finish_class (objc_implementation_context);
6769 objc_ivar_chain = NULL_TREE;
6770 objc_implementation_context = NULL_TREE;
6773 class = make_node (code);
6774 TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
6776 CLASS_NAME (class) = class_name;
6777 CLASS_SUPER_NAME (class) = super_name;
6778 CLASS_CLS_METHODS (class) = NULL_TREE;
6780 if (! is_class_name (class_name)
6781 && (decl = lookup_name (class_name)))
6783 error ("`%s' redeclared as different kind of symbol",
6784 IDENTIFIER_POINTER (class_name));
6785 error ("%Jprevious declaration of '%D'",
6786 decl, decl);
6789 if (code == CLASS_IMPLEMENTATION_TYPE)
6792 tree chain;
6794 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6795 if (TREE_VALUE (chain) == class_name)
6797 error ("reimplementation of class `%s'",
6798 IDENTIFIER_POINTER (class_name));
6799 return error_mark_node;
6801 implemented_classes = tree_cons (NULL_TREE, class_name,
6802 implemented_classes);
6805 /* Reset for multiple classes per file. */
6806 method_slot = 0;
6808 objc_implementation_context = class;
6810 /* Lookup the interface for this implementation. */
6812 if (!(implementation_template = lookup_interface (class_name)))
6814 warning ("cannot find interface declaration for `%s'",
6815 IDENTIFIER_POINTER (class_name));
6816 add_class (implementation_template = objc_implementation_context);
6819 /* If a super class has been specified in the implementation,
6820 insure it conforms to the one specified in the interface. */
6822 if (super_name
6823 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6825 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6826 const char *const name =
6827 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6828 error ("conflicting super class name `%s'",
6829 IDENTIFIER_POINTER (super_name));
6830 error ("previous declaration of `%s'", name);
6833 else if (! super_name)
6835 CLASS_SUPER_NAME (objc_implementation_context)
6836 = CLASS_SUPER_NAME (implementation_template);
6840 else if (code == CLASS_INTERFACE_TYPE)
6842 if (lookup_interface (class_name))
6843 #ifdef OBJCPLUS
6844 error ("duplicate interface declaration for class `%s'",
6845 #else
6846 warning ("duplicate interface declaration for class `%s'",
6847 #endif
6848 IDENTIFIER_POINTER (class_name));
6849 else
6850 add_class (class);
6852 if (protocol_list)
6853 CLASS_PROTOCOL_LIST (class)
6854 = lookup_and_install_protocols (protocol_list);
6857 else if (code == CATEGORY_INTERFACE_TYPE)
6859 tree class_category_is_assoc_with;
6861 /* For a category, class_name is really the name of the class that
6862 the following set of methods will be associated with. We must
6863 find the interface so that can derive the objects template. */
6865 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6867 error ("cannot find interface declaration for `%s'",
6868 IDENTIFIER_POINTER (class_name));
6869 exit (FATAL_EXIT_CODE);
6871 else
6872 add_category (class_category_is_assoc_with, class);
6874 if (protocol_list)
6875 CLASS_PROTOCOL_LIST (class)
6876 = lookup_and_install_protocols (protocol_list);
6879 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6881 /* Reset for multiple classes per file. */
6882 method_slot = 0;
6884 objc_implementation_context = class;
6886 /* For a category, class_name is really the name of the class that
6887 the following set of methods will be associated with. We must
6888 find the interface so that can derive the objects template. */
6890 if (!(implementation_template = lookup_interface (class_name)))
6892 error ("cannot find interface declaration for `%s'",
6893 IDENTIFIER_POINTER (class_name));
6894 exit (FATAL_EXIT_CODE);
6897 return class;
6900 tree
6901 continue_class (tree class)
6903 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6904 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6906 struct imp_entry *imp_entry;
6907 tree ivar_context;
6909 /* Check consistency of the instance variables. */
6911 if (CLASS_IVARS (class))
6912 check_ivars (implementation_template, class);
6914 /* code generation */
6916 ivar_context = build_private_template (implementation_template);
6918 if (!objc_class_template)
6919 build_class_template ();
6921 imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6923 imp_entry->next = imp_list;
6924 imp_entry->imp_context = class;
6925 imp_entry->imp_template = implementation_template;
6927 synth_forward_declarations ();
6928 imp_entry->class_decl = UOBJC_CLASS_decl;
6929 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6931 /* Append to front and increment count. */
6932 imp_list = imp_entry;
6933 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6934 imp_count++;
6935 else
6936 cat_count++;
6938 return ivar_context;
6941 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6943 if (!CLASS_STATIC_TEMPLATE (class))
6945 tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6946 finish_struct (record, get_class_ivars (class, 0), NULL_TREE);
6947 CLASS_STATIC_TEMPLATE (class) = record;
6949 /* Mark this record as a class template for static typing. */
6950 TREE_STATIC_TEMPLATE (record) = 1;
6953 return NULL_TREE;
6956 else
6957 return error_mark_node;
6960 /* This is called once we see the "@end" in an interface/implementation. */
6962 void
6963 finish_class (tree class)
6965 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6967 /* All code generation is done in finish_objc. */
6969 if (implementation_template != objc_implementation_context)
6971 /* Ensure that all method listed in the interface contain bodies. */
6972 check_methods (CLASS_CLS_METHODS (implementation_template),
6973 CLASS_CLS_METHODS (objc_implementation_context), '+');
6974 check_methods (CLASS_NST_METHODS (implementation_template),
6975 CLASS_NST_METHODS (objc_implementation_context), '-');
6977 if (CLASS_PROTOCOL_LIST (implementation_template))
6978 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6979 "class",
6980 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6984 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6986 tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6988 if (category)
6990 /* Ensure all method listed in the interface contain bodies. */
6991 check_methods (CLASS_CLS_METHODS (category),
6992 CLASS_CLS_METHODS (objc_implementation_context), '+');
6993 check_methods (CLASS_NST_METHODS (category),
6994 CLASS_NST_METHODS (objc_implementation_context), '-');
6996 if (CLASS_PROTOCOL_LIST (category))
6997 check_protocols (CLASS_PROTOCOL_LIST (category),
6998 "category",
6999 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7003 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
7005 tree decl_specs;
7006 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
7007 char *string = (char *) alloca (strlen (class_name) + 3);
7009 /* extern struct objc_object *_<my_name>; */
7011 sprintf (string, "_%s", class_name);
7013 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
7014 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
7015 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
7016 decl_specs);
7020 static tree
7021 add_protocol (tree protocol)
7023 /* Put protocol on list in reverse order. */
7024 TREE_CHAIN (protocol) = protocol_chain;
7025 protocol_chain = protocol;
7026 return protocol_chain;
7029 static tree
7030 lookup_protocol (tree ident)
7032 tree chain;
7034 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
7035 if (ident == PROTOCOL_NAME (chain))
7036 return chain;
7038 return NULL_TREE;
7041 /* This function forward declares the protocols named by NAMES. If
7042 they are already declared or defined, the function has no effect. */
7044 void
7045 objc_declare_protocols (tree names)
7047 tree list;
7049 #ifdef OBJCPLUS
7050 if (current_namespace != global_namespace) {
7051 error ("Objective-C declarations may only appear in global scope");
7053 #endif /* OBJCPLUS */
7055 for (list = names; list; list = TREE_CHAIN (list))
7057 tree name = TREE_VALUE (list);
7059 if (lookup_protocol (name) == NULL_TREE)
7061 tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
7063 TYPE_BINFO (protocol) = make_tree_vec (2);
7064 PROTOCOL_NAME (protocol) = name;
7065 PROTOCOL_LIST (protocol) = NULL_TREE;
7066 add_protocol (protocol);
7067 PROTOCOL_DEFINED (protocol) = 0;
7068 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7073 tree
7074 start_protocol (enum tree_code code, tree name, tree list)
7076 tree protocol;
7078 #ifdef OBJCPLUS
7079 if (current_namespace != global_namespace) {
7080 error ("Objective-C declarations may only appear in global scope");
7082 #endif /* OBJCPLUS */
7084 /* This is as good a place as any. Need to invoke
7085 push_tag_toplevel. */
7086 if (!objc_protocol_template)
7087 objc_protocol_template = build_protocol_template ();
7089 protocol = lookup_protocol (name);
7091 if (!protocol)
7093 protocol = make_node (code);
7094 TYPE_BINFO (protocol) = make_tree_vec (2);
7096 PROTOCOL_NAME (protocol) = name;
7097 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7098 add_protocol (protocol);
7099 PROTOCOL_DEFINED (protocol) = 1;
7100 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
7102 check_protocol_recursively (protocol, list);
7104 else if (! PROTOCOL_DEFINED (protocol))
7106 PROTOCOL_DEFINED (protocol) = 1;
7107 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7109 check_protocol_recursively (protocol, list);
7111 else
7113 warning ("duplicate declaration for protocol `%s'",
7114 IDENTIFIER_POINTER (name));
7116 return protocol;
7119 void
7120 finish_protocol (tree protocol ATTRIBUTE_UNUSED)
7125 /* "Encode" a data type into a string, which grows in util_obstack.
7126 ??? What is the FORMAT? Someone please document this! */
7128 static void
7129 encode_type_qualifiers (tree declspecs)
7131 tree spec;
7133 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7135 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
7136 obstack_1grow (&util_obstack, 'r');
7137 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7138 obstack_1grow (&util_obstack, 'n');
7139 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7140 obstack_1grow (&util_obstack, 'N');
7141 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7142 obstack_1grow (&util_obstack, 'o');
7143 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7144 obstack_1grow (&util_obstack, 'O');
7145 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7146 obstack_1grow (&util_obstack, 'R');
7147 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7148 obstack_1grow (&util_obstack, 'V');
7152 /* Encode a pointer type. */
7154 static void
7155 encode_pointer (tree type, int curtype, int format)
7157 tree pointer_to = TREE_TYPE (type);
7159 if (TREE_CODE (pointer_to) == RECORD_TYPE)
7161 if (OBJC_TYPE_NAME (pointer_to)
7162 && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7164 const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7166 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7168 obstack_1grow (&util_obstack, '@');
7169 return;
7171 else if (TREE_STATIC_TEMPLATE (pointer_to))
7173 if (generating_instance_variables)
7175 obstack_1grow (&util_obstack, '@');
7176 obstack_1grow (&util_obstack, '"');
7177 obstack_grow (&util_obstack, name, strlen (name));
7178 obstack_1grow (&util_obstack, '"');
7179 return;
7181 else
7183 obstack_1grow (&util_obstack, '@');
7184 return;
7187 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7189 obstack_1grow (&util_obstack, '#');
7190 return;
7192 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7194 obstack_1grow (&util_obstack, ':');
7195 return;
7199 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7200 && TYPE_MODE (pointer_to) == QImode)
7202 tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7203 ? OBJC_TYPE_NAME (pointer_to)
7204 : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7206 if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7208 obstack_1grow (&util_obstack, '*');
7209 return;
7213 /* We have a type that does not get special treatment. */
7215 /* NeXT extension */
7216 obstack_1grow (&util_obstack, '^');
7217 encode_type (pointer_to, curtype, format);
7220 static void
7221 encode_array (tree type, int curtype, int format)
7223 tree an_int_cst = TYPE_SIZE (type);
7224 tree array_of = TREE_TYPE (type);
7225 char buffer[40];
7227 /* An incomplete array is treated like a pointer. */
7228 if (an_int_cst == NULL)
7230 encode_pointer (type, curtype, format);
7231 return;
7234 sprintf (buffer, "[%ld",
7235 (long) (TREE_INT_CST_LOW (an_int_cst)
7236 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7238 obstack_grow (&util_obstack, buffer, strlen (buffer));
7239 encode_type (array_of, curtype, format);
7240 obstack_1grow (&util_obstack, ']');
7241 return;
7244 static void
7245 encode_aggregate_within (tree type, int curtype, int format, int left,
7246 int right)
7248 tree name;
7249 /* NB: aggregates that are pointed to have slightly different encoding
7250 rules in that you never encode the names of instance variables. */
7251 int pointed_to
7252 = (obstack_object_size (&util_obstack) > 0
7253 && *(obstack_next_free (&util_obstack) - 1) == '^');
7254 int inline_contents
7255 = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7256 && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7258 /* Traverse struct aliases; it is important to get the
7259 original struct and its tag name (if any). */
7260 type = TYPE_MAIN_VARIANT (type);
7261 name = OBJC_TYPE_NAME (type);
7262 /* Open parenth/bracket. */
7263 obstack_1grow (&util_obstack, left);
7265 /* Encode the struct/union tag name, or '?' if a tag was
7266 not provided. Typedef aliases do not qualify. */
7267 if (name && TREE_CODE (name) == IDENTIFIER_NODE
7268 #ifdef OBJCPLUS
7269 /* Did this struct have a tag? */
7270 && !TYPE_WAS_ANONYMOUS (type)
7271 #endif
7273 obstack_grow (&util_obstack,
7274 IDENTIFIER_POINTER (name),
7275 strlen (IDENTIFIER_POINTER (name)));
7276 else
7277 obstack_1grow (&util_obstack, '?');
7279 /* Encode the types (and possibly names) of the inner fields,
7280 if required. */
7281 if (inline_contents)
7283 tree fields = TYPE_FIELDS (type);
7285 obstack_1grow (&util_obstack, '=');
7286 for (; fields; fields = TREE_CHAIN (fields))
7288 #ifdef OBJCPLUS
7289 /* C++ static members, and things that are not fields at all,
7290 should not appear in the encoding. */
7291 if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7292 continue;
7293 #endif
7294 if (generating_instance_variables && !pointed_to)
7296 tree fname = DECL_NAME (fields);
7298 obstack_1grow (&util_obstack, '"');
7299 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7300 obstack_grow (&util_obstack,
7301 IDENTIFIER_POINTER (fname),
7302 strlen (IDENTIFIER_POINTER (fname)));
7303 obstack_1grow (&util_obstack, '"');
7305 encode_field_decl (fields, curtype, format);
7308 /* Close parenth/bracket. */
7309 obstack_1grow (&util_obstack, right);
7312 static void
7313 encode_aggregate (tree type, int curtype, int format)
7315 enum tree_code code = TREE_CODE (type);
7317 switch (code)
7319 case RECORD_TYPE:
7321 encode_aggregate_within (type, curtype, format, '{', '}');
7322 break;
7324 case UNION_TYPE:
7326 encode_aggregate_within (type, curtype, format, '(', ')');
7327 break;
7330 case ENUMERAL_TYPE:
7331 obstack_1grow (&util_obstack, 'i');
7332 break;
7334 default:
7335 break;
7339 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7340 field type. */
7342 static void
7343 encode_next_bitfield (int width)
7345 char buffer[40];
7346 sprintf (buffer, "b%d", width);
7347 obstack_grow (&util_obstack, buffer, strlen (buffer));
7350 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
7351 static void
7352 encode_type (tree type, int curtype, int format)
7354 enum tree_code code = TREE_CODE (type);
7355 char c;
7357 if (code == INTEGER_TYPE)
7359 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7361 case 8: c = TREE_UNSIGNED (type) ? 'C' : 'c'; break;
7362 case 16: c = TREE_UNSIGNED (type) ? 'S' : 's'; break;
7363 case 32:
7364 if (type == long_unsigned_type_node
7365 || type == long_integer_type_node)
7366 c = TREE_UNSIGNED (type) ? 'L' : 'l';
7367 else
7368 c = TREE_UNSIGNED (type) ? 'I' : 'i';
7369 break;
7370 case 64: c = TREE_UNSIGNED (type) ? 'Q' : 'q'; break;
7371 default: abort ();
7373 obstack_1grow (&util_obstack, c);
7376 else if (code == REAL_TYPE)
7378 /* Floating point types. */
7379 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7381 case 32: c = 'f'; break;
7382 case 64:
7383 case 128: c = 'd'; break;
7384 default: abort ();
7386 obstack_1grow (&util_obstack, c);
7389 else if (code == VOID_TYPE)
7390 obstack_1grow (&util_obstack, 'v');
7392 else if (code == BOOLEAN_TYPE)
7393 obstack_1grow (&util_obstack, 'B');
7395 else if (code == ARRAY_TYPE)
7396 encode_array (type, curtype, format);
7398 else if (code == POINTER_TYPE)
7399 encode_pointer (type, curtype, format);
7401 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7402 encode_aggregate (type, curtype, format);
7404 else if (code == FUNCTION_TYPE) /* '?' */
7405 obstack_1grow (&util_obstack, '?');
7408 static void
7409 encode_gnu_bitfield (int position, tree type, int size)
7411 enum tree_code code = TREE_CODE (type);
7412 char buffer[40];
7413 char charType = '?';
7415 if (code == INTEGER_TYPE)
7417 if (integer_zerop (TYPE_MIN_VALUE (type)))
7419 /* Unsigned integer types. */
7421 if (TYPE_MODE (type) == QImode)
7422 charType = 'C';
7423 else if (TYPE_MODE (type) == HImode)
7424 charType = 'S';
7425 else if (TYPE_MODE (type) == SImode)
7427 if (type == long_unsigned_type_node)
7428 charType = 'L';
7429 else
7430 charType = 'I';
7432 else if (TYPE_MODE (type) == DImode)
7433 charType = 'Q';
7436 else
7437 /* Signed integer types. */
7439 if (TYPE_MODE (type) == QImode)
7440 charType = 'c';
7441 else if (TYPE_MODE (type) == HImode)
7442 charType = 's';
7443 else if (TYPE_MODE (type) == SImode)
7445 if (type == long_integer_type_node)
7446 charType = 'l';
7447 else
7448 charType = 'i';
7451 else if (TYPE_MODE (type) == DImode)
7452 charType = 'q';
7455 else if (code == ENUMERAL_TYPE)
7456 charType = 'i';
7457 else
7458 abort ();
7460 sprintf (buffer, "b%d%c%d", position, charType, size);
7461 obstack_grow (&util_obstack, buffer, strlen (buffer));
7464 static void
7465 encode_field_decl (tree field_decl, int curtype, int format)
7467 tree type;
7469 #ifdef OBJCPLUS
7470 /* C++ static members, and things that are not fields at all,
7471 should not appear in the encoding. */
7472 if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7473 return;
7474 #endif
7476 type = TREE_TYPE (field_decl);
7478 /* Generate the bitfield typing information, if needed. Note the difference
7479 between GNU and NeXT runtimes. */
7480 if (DECL_BIT_FIELD_TYPE (field_decl))
7482 int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7484 if (flag_next_runtime)
7485 encode_next_bitfield (size);
7486 else
7487 encode_gnu_bitfield (int_bit_position (field_decl),
7488 DECL_BIT_FIELD_TYPE (field_decl), size);
7490 else
7491 encode_type (TREE_TYPE (field_decl), curtype, format);
7494 static tree
7495 objc_expr_last (tree complex_expr)
7497 tree next;
7499 if (complex_expr)
7500 while ((next = TREE_OPERAND (complex_expr, 0)))
7501 complex_expr = next;
7503 return complex_expr;
7506 static void
7507 synth_self_and_ucmd_args (void)
7509 tree decl_specs;
7511 if (objc_method_context
7512 && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7513 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7514 else
7515 /* Really a `struct objc_class *'. However, we allow people to
7516 assign to self, which changes its type midstream. */
7517 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7519 push_parm_decl (build_tree_list
7520 (build_tree_list (decl_specs,
7521 build1 (INDIRECT_REF, NULL_TREE, self_id)),
7522 unused_list));
7524 decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (selector_type));
7525 push_parm_decl (build_tree_list
7526 (build_tree_list (decl_specs,
7527 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7528 unused_list));
7531 /* Transform a method definition into a function definition as follows:
7532 - synthesize the first two arguments, "self" and "_cmd". */
7534 void
7535 start_method_def (tree method)
7537 /* Required to implement _msgSuper. */
7538 objc_method_context = method;
7539 UOBJC_SUPER_decl = NULL_TREE;
7541 /* Must be called BEFORE start_function. */
7542 pushlevel (0);
7544 /* Generate prototype declarations for arguments..."new-style". */
7545 synth_self_and_ucmd_args ();
7547 /* Generate argument declarations if a keyword_decl. */
7548 if (METHOD_SEL_ARGS (method))
7550 tree arglist = METHOD_SEL_ARGS (method);
7553 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7554 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7556 if (arg_decl)
7558 tree last_expr = objc_expr_last (arg_decl);
7560 /* Unite the abstract decl with its name. */
7561 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7562 push_parm_decl (build_tree_list
7563 (build_tree_list (arg_spec, arg_decl),
7564 NULL_TREE));
7566 #ifndef OBJCPLUS
7567 /* Unhook: restore the abstract declarator. */
7568 TREE_OPERAND (last_expr, 0) = NULL_TREE;
7569 #endif
7572 else
7573 push_parm_decl (build_tree_list
7574 (build_tree_list (arg_spec,
7575 KEYWORD_ARG_NAME (arglist)),
7576 NULL_TREE));
7578 arglist = TREE_CHAIN (arglist);
7580 while (arglist);
7583 if (METHOD_ADD_ARGS (method) != NULL_TREE
7584 && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7586 /* We have a variable length selector - in "prototype" format. */
7587 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7588 while (akey)
7590 /* This must be done prior to calling pushdecl. pushdecl is
7591 going to change our chain on us. */
7592 tree nextkey = TREE_CHAIN (akey);
7593 pushdecl (akey);
7594 akey = nextkey;
7599 static void
7600 warn_with_method (const char *message, int mtype, tree method)
7602 /* Add a readable method name to the warning. */
7603 warning ("%J%s `%c%s'", method,
7604 message, mtype, gen_method_decl (method, errbuf));
7607 /* Return 1 if METHOD is consistent with PROTO. */
7609 static int
7610 comp_method_with_proto (tree method, tree proto)
7612 /* Create a function template node at most once. */
7613 if (!function1_template)
7614 function1_template = make_node (FUNCTION_TYPE);
7616 /* Install argument types - normally set by build_function_type. */
7617 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7619 /* install return type */
7620 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7622 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
7623 false);
7626 /* Return 1 if TYPE1 is equivalent to TYPE2. */
7628 static int
7629 objc_types_are_equivalent (tree type1, tree type2)
7631 if (type1 == type2)
7632 return 1;
7633 if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7634 return 0;
7635 type1 = TYPE_PROTOCOL_LIST (type1);
7636 type2 = TYPE_PROTOCOL_LIST (type2);
7637 if (list_length (type1) == list_length (type2))
7639 for (; type2; type2 = TREE_CHAIN (type2))
7640 if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7641 return 0;
7642 return 1;
7644 return 0;
7647 /* Return 1 if PROTO1 is equivalent to PROTO2. */
7649 static int
7650 comp_proto_with_proto (tree proto1, tree proto2)
7652 tree type1, type2;
7654 /* The following test is needed in case there are hashing
7655 collisions. */
7656 if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7657 return 0;
7659 /* Compare return types. */
7660 type1 = groktypename (TREE_TYPE (proto1));
7661 type2 = groktypename (TREE_TYPE (proto2));
7663 if (!objc_types_are_equivalent (type1, type2))
7664 return 0;
7666 /* Compare argument types. */
7667 for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7668 type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7669 type1 && type2;
7670 type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7672 if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7673 return 0;
7676 return (!type1 && !type2);
7679 /* - Generate an identifier for the function. the format is "_n_cls",
7680 where 1 <= n <= nMethods, and cls is the name the implementation we
7681 are processing.
7682 - Install the return type from the method declaration.
7683 - If we have a prototype, check for type consistency. */
7685 static void
7686 really_start_method (tree method, tree parmlist)
7688 tree sc_spec, ret_spec, ret_decl, decl_specs;
7689 tree method_decl, method_id;
7690 const char *sel_name, *class_name, *cat_name;
7691 char *buf;
7693 /* Synth the storage class & assemble the return type. */
7694 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7695 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7696 decl_specs = chainon (sc_spec, ret_spec);
7698 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7699 class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7700 cat_name = ((TREE_CODE (objc_implementation_context)
7701 == CLASS_IMPLEMENTATION_TYPE)
7702 ? NULL
7703 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7704 method_slot++;
7706 /* Make sure this is big enough for any plausible method label. */
7707 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7708 + (cat_name ? strlen (cat_name) : 0));
7710 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7711 class_name, cat_name, sel_name, method_slot);
7713 method_id = get_identifier (buf);
7715 #ifdef OBJCPLUS
7716 /* Objective-C methods cannot be overloaded, so we don't need
7717 the type encoding appended. It looks bad anyway... */
7718 push_lang_context (lang_name_c);
7719 #endif
7721 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7723 /* Check the declarator portion of the return type for the method. */
7724 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7726 /* Unite the complex decl (specified in the abstract decl) with the
7727 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7728 tree save_expr = objc_expr_last (ret_decl);
7730 TREE_OPERAND (save_expr, 0) = method_decl;
7731 method_decl = ret_decl;
7733 /* Fool the parser into thinking it is starting a function. */
7734 start_function (decl_specs, method_decl, NULL_TREE);
7736 /* Unhook: this has the effect of restoring the abstract declarator. */
7737 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7740 else
7742 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7744 /* Fool the parser into thinking it is starting a function. */
7745 start_function (decl_specs, method_decl, NULL_TREE);
7747 /* Unhook: this has the effect of restoring the abstract declarator. */
7748 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7751 #ifdef OBJCPLUS
7752 /* set self_decl from the first argument...this global is used by
7753 * build_ivar_reference().build_indirect_ref().
7755 self_decl = DECL_ARGUMENTS (current_function_decl);
7757 /* snaroff (3/28/96): when compiling with -Wall, this suppresses
7758 * the following: warning:unused parameter `struct objc_selector * _cmd'
7760 TREE_USED (self_decl) = 1;
7761 TREE_USED (TREE_CHAIN (self_decl)) = 1;
7762 /* Ditto for the underlying (static) C function. */
7763 TREE_USED (current_function_decl) = 1;
7764 pop_lang_context ();
7765 #endif
7767 METHOD_DEFINITION (method) = current_function_decl;
7769 /* Check consistency...start_function, pushdecl, duplicate_decls. */
7771 if (implementation_template != objc_implementation_context)
7773 tree proto
7774 = lookup_method_static (implementation_template,
7775 METHOD_SEL_NAME (method),
7776 TREE_CODE (method) == CLASS_METHOD_DECL);
7778 if (proto)
7780 if (!comp_method_with_proto (method, proto))
7782 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7784 warn_with_method ("conflicting types for", type, method);
7785 warn_with_method ("previous declaration of", type, proto);
7788 else
7790 /* We have a method @implementation even though we did not
7791 see a corresponding @interface declaration (which is allowed
7792 by Objective-C rules). Go ahead and place the method in
7793 the @interface anyway, so that message dispatch lookups
7794 will see it. */
7795 tree interface = implementation_template;
7797 if (TREE_CODE (objc_implementation_context)
7798 == CATEGORY_IMPLEMENTATION_TYPE)
7799 interface = lookup_category
7800 (interface,
7801 CLASS_SUPER_NAME (objc_implementation_context));
7803 if (interface)
7804 objc_add_method (interface, copy_node (method),
7805 TREE_CODE (method) == CLASS_METHOD_DECL);
7810 /* The following routine is always called...this "architecture" is to
7811 accommodate "old-style" variable length selectors.
7813 - a:a b:b // prototype ; id c; id d; // old-style. */
7815 void
7816 continue_method_def (void)
7818 tree parmlist;
7820 if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7821 /* We have a `, ...' immediately following the selector. */
7822 parmlist = get_parm_info (0);
7823 else
7824 parmlist = get_parm_info (1); /* place a `void_at_end' */
7826 #ifndef OBJCPLUS
7827 /* Set self_decl from the first argument...this global is used by
7828 build_ivar_reference calling build_indirect_ref. */
7829 self_decl = TREE_PURPOSE (parmlist);
7830 #endif /* !OBJCPLUS */
7832 poplevel (0, 0, 0);
7833 really_start_method (objc_method_context, parmlist);
7834 store_parm_decls ();
7837 static void *UOBJC_SUPER_scope = 0;
7839 /* _n_Method (id self, SEL sel, ...)
7841 struct objc_super _S;
7842 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7843 } */
7845 tree
7846 get_super_receiver (void)
7848 if (objc_method_context)
7850 tree super_expr, super_expr_list;
7852 if (!UOBJC_SUPER_decl)
7854 UOBJC_SUPER_decl = start_decl (get_identifier (TAG_SUPER),
7855 build_tree_list (NULL_TREE,
7856 objc_super_template),
7857 0, NULL_TREE);
7859 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7861 /* This prevents `unused variable' warnings when compiling with -Wall. */
7862 TREE_USED (UOBJC_SUPER_decl) = 1;
7863 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7865 UOBJC_SUPER_scope = get_current_scope ();
7868 /* Set receiver to self. */
7869 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7870 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7871 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7873 /* Set class to begin searching. */
7874 #ifdef OBJCPLUS
7875 super_expr = build_component_ref (UOBJC_SUPER_decl,
7876 get_identifier ("super_class"));
7877 #else
7878 super_expr = build_component_ref (UOBJC_SUPER_decl,
7879 get_identifier ("class"));
7880 #endif
7882 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7884 /* [_cls, __cls]Super are "pre-built" in
7885 synth_forward_declarations. */
7887 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7888 ((TREE_CODE (objc_method_context)
7889 == INSTANCE_METHOD_DECL)
7890 ? ucls_super_ref
7891 : uucls_super_ref));
7894 else
7895 /* We have a category. */
7897 tree super_name = CLASS_SUPER_NAME (implementation_template);
7898 tree super_class;
7900 /* Barf if super used in a category of Object. */
7901 if (!super_name)
7903 error ("no super class declared in interface for `%s'",
7904 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7905 return error_mark_node;
7908 if (flag_next_runtime && !flag_zero_link)
7910 super_class = get_class_reference (super_name);
7911 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7912 /* If we are in a class method, we must retrieve the
7913 _metaclass_ for the current class, pointed at by
7914 the class's "isa" pointer. The following assumes that
7915 "isa" is the first ivar in a class (which it must be). */
7916 super_class
7917 = build_indirect_ref
7918 (build_c_cast (build_pointer_type (objc_class_type),
7919 super_class), "unary *");
7921 else
7923 add_class_reference (super_name);
7924 super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7925 ? objc_get_class_decl : objc_get_meta_class_decl);
7926 assemble_external (super_class);
7927 super_class
7928 = build_function_call
7929 (super_class,
7930 build_tree_list
7931 (NULL_TREE,
7932 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7933 IDENTIFIER_POINTER (super_name))));
7936 super_expr
7937 = build_modify_expr (super_expr, NOP_EXPR,
7938 build_c_cast (TREE_TYPE (super_expr),
7939 super_class));
7942 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7944 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7945 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7947 return build_compound_expr (super_expr_list);
7949 else
7951 error ("[super ...] must appear in a method context");
7952 return error_mark_node;
7956 /* When exiting a scope, sever links to a 'super' declaration (if any)
7957 therein contained. */
7959 void
7960 objc_clear_super_receiver (void)
7962 if (objc_method_context
7963 && UOBJC_SUPER_scope == get_current_scope ()) {
7964 UOBJC_SUPER_decl = 0;
7965 UOBJC_SUPER_scope = 0;
7969 static void
7970 objc_expand_function_end (void)
7972 /* This routine may also get called for C functions, including those
7973 nested within ObjC methods. In such cases, method encoding is
7974 meaningless. */
7975 if (objc_method_context == NULL_TREE
7976 || DECL_INITIAL (objc_method_context) != current_function_decl)
7977 return;
7979 METHOD_ENCODING (objc_method_context)
7980 = encode_method_prototype (objc_method_context);
7983 void
7984 finish_method_def (void)
7986 lang_expand_function_end = objc_expand_function_end;
7987 /* We cannot validly inline ObjC methods, at least not without a language
7988 extension to declare that a method need not be dynamically
7989 dispatched, so suppress all thoughts of doing so. */
7990 DECL_INLINE (current_function_decl) = 0;
7991 DECL_UNINLINABLE (current_function_decl) = 1;
7992 current_function_cannot_inline = "methods cannot be inlined";
7994 finish_function ();
7995 lang_expand_function_end = NULL;
7997 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7998 since the optimizer may find "may be used before set" errors. */
7999 objc_method_context = NULL_TREE;
8002 #if 0
8004 lang_report_error_function (tree decl)
8006 if (objc_method_context)
8008 fprintf (stderr, "In method `%s'\n",
8009 IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
8010 return 1;
8013 else
8014 return 0;
8016 #endif
8018 static int
8019 is_complex_decl (tree type)
8021 return (TREE_CODE (type) == ARRAY_TYPE
8022 || TREE_CODE (type) == FUNCTION_TYPE
8023 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
8027 /* Code to convert a decl node into text for a declaration in C. */
8029 static char tmpbuf[256];
8031 static void
8032 adorn_decl (tree decl, char *str)
8034 enum tree_code code = TREE_CODE (decl);
8036 if (code == ARRAY_REF)
8038 tree an_int_cst = TREE_OPERAND (decl, 1);
8040 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
8041 sprintf (str + strlen (str), "[%ld]",
8042 (long) TREE_INT_CST_LOW (an_int_cst));
8043 else
8044 strcat (str, "[]");
8047 else if (code == ARRAY_TYPE)
8049 tree an_int_cst = TYPE_SIZE (decl);
8050 tree array_of = TREE_TYPE (decl);
8052 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
8053 sprintf (str + strlen (str), "[%ld]",
8054 (long) (TREE_INT_CST_LOW (an_int_cst)
8055 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
8056 else
8057 strcat (str, "[]");
8060 else if (code == CALL_EXPR)
8062 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
8064 strcat (str, "(");
8065 while (chain)
8067 gen_declaration_1 (chain, str);
8068 chain = TREE_CHAIN (chain);
8069 if (chain)
8070 strcat (str, ", ");
8072 strcat (str, ")");
8075 else if (code == FUNCTION_TYPE)
8077 tree chain = TYPE_ARG_TYPES (decl);
8079 strcat (str, "(");
8080 while (chain && TREE_VALUE (chain) != void_type_node)
8082 gen_declaration_1 (TREE_VALUE (chain), str);
8083 chain = TREE_CHAIN (chain);
8084 if (chain && TREE_VALUE (chain) != void_type_node)
8085 strcat (str, ", ");
8087 strcat (str, ")");
8090 else if (code == INDIRECT_REF)
8092 strcpy (tmpbuf, "*");
8093 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
8095 tree chain;
8097 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
8098 chain;
8099 chain = TREE_CHAIN (chain))
8101 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
8103 strcat (tmpbuf, " ");
8104 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
8107 if (str[0])
8108 strcat (tmpbuf, " ");
8110 strcat (tmpbuf, str);
8111 strcpy (str, tmpbuf);
8114 else if (code == POINTER_TYPE)
8116 strcpy (tmpbuf, "*");
8117 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
8119 if (TREE_READONLY (decl))
8120 strcat (tmpbuf, " const");
8121 if (TYPE_VOLATILE (decl))
8122 strcat (tmpbuf, " volatile");
8123 if (str[0])
8124 strcat (tmpbuf, " ");
8126 strcat (tmpbuf, str);
8127 strcpy (str, tmpbuf);
8131 static char *
8132 gen_declarator (tree decl, char *buf, const char *name)
8134 if (decl)
8136 enum tree_code code = TREE_CODE (decl);
8137 char *str;
8138 tree op;
8139 int wrap = 0;
8141 switch (code)
8143 case ARRAY_REF:
8144 case INDIRECT_REF:
8145 case CALL_EXPR:
8146 op = TREE_OPERAND (decl, 0);
8148 /* We have a pointer to a function or array...(*)(), (*)[] */
8149 if ((code == ARRAY_REF || code == CALL_EXPR)
8150 && op && TREE_CODE (op) == INDIRECT_REF)
8151 wrap = 1;
8153 str = gen_declarator (op, buf, name);
8155 if (wrap)
8157 strcpy (tmpbuf, "(");
8158 strcat (tmpbuf, str);
8159 strcat (tmpbuf, ")");
8160 strcpy (str, tmpbuf);
8163 adorn_decl (decl, str);
8164 break;
8166 case ARRAY_TYPE:
8167 case FUNCTION_TYPE:
8168 case POINTER_TYPE:
8169 strcpy (buf, name);
8170 str = buf;
8172 /* This clause is done iteratively rather than recursively. */
8175 op = (is_complex_decl (TREE_TYPE (decl))
8176 ? TREE_TYPE (decl) : NULL_TREE);
8178 adorn_decl (decl, str);
8180 /* We have a pointer to a function or array...(*)(), (*)[] */
8181 if (code == POINTER_TYPE
8182 && op && (TREE_CODE (op) == FUNCTION_TYPE
8183 || TREE_CODE (op) == ARRAY_TYPE))
8185 strcpy (tmpbuf, "(");
8186 strcat (tmpbuf, str);
8187 strcat (tmpbuf, ")");
8188 strcpy (str, tmpbuf);
8191 decl = (is_complex_decl (TREE_TYPE (decl))
8192 ? TREE_TYPE (decl) : NULL_TREE);
8195 while (decl && (code = TREE_CODE (decl)))
8198 break;
8200 case IDENTIFIER_NODE:
8201 /* Will only happen if we are processing a "raw" expr-decl. */
8202 strcpy (buf, IDENTIFIER_POINTER (decl));
8203 return buf;
8205 default:
8206 abort ();
8209 return str;
8212 else
8213 /* We have an abstract declarator or a _DECL node. */
8215 strcpy (buf, name);
8216 return buf;
8220 static void
8221 gen_declspecs (tree declspecs, char *buf, int raw)
8223 if (raw)
8225 tree chain;
8227 for (chain = nreverse (copy_list (declspecs));
8228 chain; chain = TREE_CHAIN (chain))
8230 tree aspec = TREE_VALUE (chain);
8232 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
8233 strcat (buf, IDENTIFIER_POINTER (aspec));
8234 else if (TREE_CODE (aspec) == RECORD_TYPE)
8236 if (OBJC_TYPE_NAME (aspec))
8238 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8240 if (! TREE_STATIC_TEMPLATE (aspec))
8241 strcat (buf, "struct ");
8242 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8244 /* NEW!!! */
8245 if (protocol_list)
8247 tree chain = protocol_list;
8249 strcat (buf, " <");
8250 while (chain)
8252 strcat (buf,
8253 IDENTIFIER_POINTER
8254 (PROTOCOL_NAME (TREE_VALUE (chain))));
8255 chain = TREE_CHAIN (chain);
8256 if (chain)
8257 strcat (buf, ", ");
8259 strcat (buf, ">");
8263 else
8264 strcat (buf, "untagged struct");
8267 else if (TREE_CODE (aspec) == UNION_TYPE)
8269 if (OBJC_TYPE_NAME (aspec))
8271 if (! TREE_STATIC_TEMPLATE (aspec))
8272 strcat (buf, "union ");
8273 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8275 else
8276 strcat (buf, "untagged union");
8279 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
8281 if (OBJC_TYPE_NAME (aspec))
8283 if (! TREE_STATIC_TEMPLATE (aspec))
8284 strcat (buf, "enum ");
8285 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (aspec)));
8287 else
8288 strcat (buf, "untagged enum");
8291 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
8292 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
8294 else if (IS_ID (aspec))
8296 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
8298 strcat (buf, "id");
8299 if (protocol_list)
8301 tree chain = protocol_list;
8303 strcat (buf, " <");
8304 while (chain)
8306 strcat (buf,
8307 IDENTIFIER_POINTER
8308 (PROTOCOL_NAME (TREE_VALUE (chain))));
8309 chain = TREE_CHAIN (chain);
8310 if (chain)
8311 strcat (buf, ", ");
8313 strcat (buf, ">");
8316 if (TREE_CHAIN (chain))
8317 strcat (buf, " ");
8320 else
8322 /* Type qualifiers. */
8323 if (TREE_READONLY (declspecs))
8324 strcat (buf, "const ");
8325 if (TYPE_VOLATILE (declspecs))
8326 strcat (buf, "volatile ");
8328 switch (TREE_CODE (declspecs))
8330 /* Type specifiers. */
8332 case INTEGER_TYPE:
8333 declspecs = TYPE_MAIN_VARIANT (declspecs);
8335 /* Signed integer types. */
8337 if (declspecs == short_integer_type_node)
8338 strcat (buf, "short int ");
8339 else if (declspecs == integer_type_node)
8340 strcat (buf, "int ");
8341 else if (declspecs == long_integer_type_node)
8342 strcat (buf, "long int ");
8343 else if (declspecs == long_long_integer_type_node)
8344 strcat (buf, "long long int ");
8345 else if (declspecs == signed_char_type_node
8346 || declspecs == char_type_node)
8347 strcat (buf, "char ");
8349 /* Unsigned integer types. */
8351 else if (declspecs == short_unsigned_type_node)
8352 strcat (buf, "unsigned short ");
8353 else if (declspecs == unsigned_type_node)
8354 strcat (buf, "unsigned int ");
8355 else if (declspecs == long_unsigned_type_node)
8356 strcat (buf, "unsigned long ");
8357 else if (declspecs == long_long_unsigned_type_node)
8358 strcat (buf, "unsigned long long ");
8359 else if (declspecs == unsigned_char_type_node)
8360 strcat (buf, "unsigned char ");
8361 break;
8363 case REAL_TYPE:
8364 declspecs = TYPE_MAIN_VARIANT (declspecs);
8366 if (declspecs == float_type_node)
8367 strcat (buf, "float ");
8368 else if (declspecs == double_type_node)
8369 strcat (buf, "double ");
8370 else if (declspecs == long_double_type_node)
8371 strcat (buf, "long double ");
8372 break;
8374 case RECORD_TYPE:
8375 if (OBJC_TYPE_NAME (declspecs)
8376 && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8378 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8380 if (! TREE_STATIC_TEMPLATE (declspecs))
8381 strcat (buf, "struct ");
8382 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8384 if (protocol_list)
8386 tree chain = protocol_list;
8388 strcat (buf, " <");
8389 while (chain)
8391 strcat (buf,
8392 IDENTIFIER_POINTER
8393 (PROTOCOL_NAME (TREE_VALUE (chain))));
8394 chain = TREE_CHAIN (chain);
8395 if (chain)
8396 strcat (buf, ", ");
8398 strcat (buf, ">");
8402 else
8403 strcat (buf, "untagged struct");
8405 strcat (buf, " ");
8406 break;
8408 case UNION_TYPE:
8409 if (OBJC_TYPE_NAME (declspecs)
8410 && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8412 strcat (buf, "union ");
8413 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8414 strcat (buf, " ");
8417 else
8418 strcat (buf, "untagged union ");
8419 break;
8421 case ENUMERAL_TYPE:
8422 if (OBJC_TYPE_NAME (declspecs)
8423 && TREE_CODE (OBJC_TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
8425 strcat (buf, "enum ");
8426 strcat (buf, IDENTIFIER_POINTER (OBJC_TYPE_NAME (declspecs)));
8427 strcat (buf, " ");
8430 else
8431 strcat (buf, "untagged enum ");
8432 break;
8434 case VOID_TYPE:
8435 strcat (buf, "void ");
8436 break;
8438 case POINTER_TYPE:
8440 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
8442 strcat (buf, "id");
8443 if (protocol_list)
8445 tree chain = protocol_list;
8447 strcat (buf, " <");
8448 while (chain)
8450 strcat (buf,
8451 IDENTIFIER_POINTER
8452 (PROTOCOL_NAME (TREE_VALUE (chain))));
8453 chain = TREE_CHAIN (chain);
8454 if (chain)
8455 strcat (buf, ", ");
8458 strcat (buf, ">");
8461 break;
8463 default:
8464 break;
8469 /* Given a tree node, produce a printable description of it in the given
8470 buffer, overwriting the buffer. */
8472 static char *
8473 gen_declaration (tree atype_or_adecl, char *buf)
8475 buf[0] = '\0';
8476 gen_declaration_1 (atype_or_adecl, buf);
8477 return buf;
8480 /* Given a tree node, append a printable description to the end of the
8481 given buffer. */
8483 static void
8484 gen_declaration_1 (tree atype_or_adecl, char *buf)
8486 char declbuf[256];
8488 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
8490 tree declspecs; /* "identifier_node", "record_type" */
8491 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
8492 tree width = NULL_TREE; /* for bitfields */
8494 /* We have a "raw", abstract declarator (typename). */
8495 declarator = TREE_VALUE (atype_or_adecl);
8496 /* In the case of raw ivars, the declarator itself is a list,
8497 and contains bitfield widths. */
8498 if (declarator && TREE_CODE (declarator) == TREE_LIST)
8500 width = TREE_VALUE (declarator);
8501 declarator = TREE_PURPOSE (declarator);
8503 declspecs = TREE_PURPOSE (atype_or_adecl);
8505 gen_declspecs (declspecs, buf, 1);
8506 if (declarator)
8508 strcat (buf, " ");
8509 strcat (buf, gen_declarator (declarator, declbuf, ""));
8511 if (width)
8512 sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED,
8513 TREE_INT_CST_LOW (width));
8516 else
8518 tree atype;
8519 tree declspecs; /* "integer_type", "real_type", "record_type"... */
8520 tree declarator; /* "array_type", "function_type", "pointer_type". */
8522 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8523 || TREE_CODE (atype_or_adecl) == PARM_DECL
8524 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8525 atype = TREE_TYPE (atype_or_adecl);
8526 else
8527 /* Assume we have a *_type node. */
8528 atype = atype_or_adecl;
8530 if (is_complex_decl (atype))
8532 tree chain;
8534 /* Get the declaration specifier; it is at the end of the list. */
8535 declarator = chain = atype;
8537 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
8538 while (is_complex_decl (chain));
8539 declspecs = chain;
8542 else
8544 declspecs = atype;
8545 declarator = NULL_TREE;
8548 gen_declspecs (declspecs, buf, 0);
8550 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
8551 || TREE_CODE (atype_or_adecl) == PARM_DECL
8552 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
8554 const char *const decl_name =
8555 (DECL_NAME (atype_or_adecl)
8556 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8558 if (declarator)
8560 strcat (buf, " ");
8561 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8564 else if (decl_name[0])
8566 strcat (buf, " ");
8567 strcat (buf, decl_name);
8570 else if (declarator)
8572 strcat (buf, " ");
8573 strcat (buf, gen_declarator (declarator, declbuf, ""));
8578 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8580 /* Given a method tree, put a printable description into the given
8581 buffer (overwriting) and return a pointer to the buffer. */
8583 static char *
8584 gen_method_decl (tree method, char *buf)
8586 tree chain;
8588 buf[0] = '\0';
8589 if (RAW_TYPESPEC (method) != objc_object_reference)
8591 strcat (buf, "(");
8592 gen_declaration_1 (TREE_TYPE (method), buf);
8593 strcat (buf, ")");
8596 chain = METHOD_SEL_ARGS (method);
8597 if (chain)
8599 /* We have a chain of keyword_decls. */
8602 if (KEYWORD_KEY_NAME (chain))
8603 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8605 strcat (buf, ":");
8606 if (RAW_TYPESPEC (chain) != objc_object_reference)
8608 strcat (buf, "(");
8609 gen_declaration_1 (TREE_TYPE (chain), buf);
8610 strcat (buf, ")");
8613 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8614 if ((chain = TREE_CHAIN (chain)))
8615 strcat (buf, " ");
8617 while (chain);
8619 if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8620 strcat (buf, ", ...");
8621 else if (METHOD_ADD_ARGS (method))
8623 /* We have a tree list node as generate by get_parm_info. */
8624 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8626 /* Know we have a chain of parm_decls. */
8627 while (chain)
8629 strcat (buf, ", ");
8630 gen_declaration_1 (chain, buf);
8631 chain = TREE_CHAIN (chain);
8636 else
8637 /* We have a unary selector. */
8638 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8640 return buf;
8643 /* Debug info. */
8646 /* Dump an @interface declaration of the supplied class CHAIN to the
8647 supplied file FP. Used to implement the -gen-decls option (which
8648 prints out an @interface declaration of all classes compiled in
8649 this run); potentially useful for debugging the compiler too. */
8650 static void
8651 dump_interface (FILE *fp, tree chain)
8653 /* FIXME: A heap overflow here whenever a method (or ivar)
8654 declaration is so long that it doesn't fit in the buffer. The
8655 code and all the related functions should be rewritten to avoid
8656 using fixed size buffers. */
8657 char *buf = (char *) xmalloc (1024 * 10);
8658 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8659 tree ivar_decls = CLASS_RAW_IVARS (chain);
8660 tree nst_methods = CLASS_NST_METHODS (chain);
8661 tree cls_methods = CLASS_CLS_METHODS (chain);
8663 fprintf (fp, "\n@interface %s", my_name);
8665 /* CLASS_SUPER_NAME is used to store the superclass name for
8666 classes, and the category name for categories. */
8667 if (CLASS_SUPER_NAME (chain))
8669 const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8671 if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8672 || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8674 fprintf (fp, " (%s)\n", name);
8676 else
8678 fprintf (fp, " : %s\n", name);
8681 else
8682 fprintf (fp, "\n");
8684 /* FIXME - the following doesn't seem to work at the moment. */
8685 if (ivar_decls)
8687 fprintf (fp, "{\n");
8690 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8691 ivar_decls = TREE_CHAIN (ivar_decls);
8693 while (ivar_decls);
8694 fprintf (fp, "}\n");
8697 while (nst_methods)
8699 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8700 nst_methods = TREE_CHAIN (nst_methods);
8703 while (cls_methods)
8705 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8706 cls_methods = TREE_CHAIN (cls_methods);
8709 fprintf (fp, "@end\n");
8712 /* Demangle function for Objective-C */
8713 static const char *
8714 objc_demangle (const char *mangled)
8716 char *demangled, *cp;
8718 if (mangled[0] == '_' &&
8719 (mangled[1] == 'i' || mangled[1] == 'c') &&
8720 mangled[2] == '_')
8722 cp = demangled = xmalloc(strlen(mangled) + 2);
8723 if (mangled[1] == 'i')
8724 *cp++ = '-'; /* for instance method */
8725 else
8726 *cp++ = '+'; /* for class method */
8727 *cp++ = '['; /* opening left brace */
8728 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8729 while (*cp && *cp == '_')
8730 cp++; /* skip any initial underbars in class name */
8731 cp = strchr(cp, '_'); /* find first non-initial underbar */
8732 if (cp == NULL)
8734 free(demangled); /* not mangled name */
8735 return mangled;
8737 if (cp[1] == '_') /* easy case: no category name */
8739 *cp++ = ' '; /* replace two '_' with one ' ' */
8740 strcpy(cp, mangled + (cp - demangled) + 2);
8742 else
8744 *cp++ = '('; /* less easy case: category name */
8745 cp = strchr(cp, '_');
8746 if (cp == 0)
8748 free(demangled); /* not mangled name */
8749 return mangled;
8751 *cp++ = ')';
8752 *cp++ = ' '; /* overwriting 1st char of method name... */
8753 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8755 while (*cp && *cp == '_')
8756 cp++; /* skip any initial underbars in method name */
8757 for (; *cp; cp++)
8758 if (*cp == '_')
8759 *cp = ':'; /* replace remaining '_' with ':' */
8760 *cp++ = ']'; /* closing right brace */
8761 *cp++ = 0; /* string terminator */
8762 return demangled;
8764 else
8765 return mangled; /* not an objc mangled name */
8768 const char *
8769 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8771 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8774 static void
8775 init_objc (void)
8777 gcc_obstack_init (&util_obstack);
8778 util_firstobj = (char *) obstack_finish (&util_obstack);
8780 errbuf = (char *) xmalloc (BUFSIZE);
8781 hash_init ();
8782 synth_module_prologue ();
8785 static void
8786 finish_objc (void)
8788 struct imp_entry *impent;
8789 tree chain;
8790 /* The internally generated initializers appear to have missing braces.
8791 Don't warn about this. */
8792 int save_warn_missing_braces = warn_missing_braces;
8793 warn_missing_braces = 0;
8795 /* A missing @end may not be detected by the parser. */
8796 if (objc_implementation_context)
8798 warning ("`@end' missing in implementation context");
8799 finish_class (objc_implementation_context);
8800 objc_ivar_chain = NULL_TREE;
8801 objc_implementation_context = NULL_TREE;
8804 generate_forward_declaration_to_string_table ();
8806 /* Process the static instances here because initialization of objc_symtab
8807 depends on them. */
8808 if (objc_static_instances)
8809 generate_static_references ();
8811 if (imp_list || class_names_chain
8812 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8813 generate_objc_symtab_decl ();
8815 for (impent = imp_list; impent; impent = impent->next)
8817 objc_implementation_context = impent->imp_context;
8818 implementation_template = impent->imp_template;
8820 UOBJC_CLASS_decl = impent->class_decl;
8821 UOBJC_METACLASS_decl = impent->meta_decl;
8823 /* Dump the @interface of each class as we compile it, if the
8824 -gen-decls option is in use. TODO: Dump the classes in the
8825 order they were found, rather than in reverse order as we
8826 are doing now. */
8827 if (flag_gen_declaration)
8829 dump_interface (gen_declaration_file, objc_implementation_context);
8832 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8834 /* all of the following reference the string pool... */
8835 generate_ivar_lists ();
8836 generate_dispatch_tables ();
8837 generate_shared_structures ();
8839 else
8841 generate_dispatch_tables ();
8842 generate_category (objc_implementation_context);
8846 /* If we are using an array of selectors, we must always
8847 finish up the array decl even if no selectors were used. */
8848 if (! flag_next_runtime || sel_ref_chain)
8849 build_selector_translation_table ();
8851 if (protocol_chain)
8852 generate_protocols ();
8854 if (flag_replace_objc_classes && imp_list)
8855 generate_objc_image_info ();
8857 if (objc_implementation_context || class_names_chain || objc_static_instances
8858 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8860 /* Arrange for ObjC data structures to be initialized at run time. */
8861 rtx init_sym = build_module_descriptor ();
8862 if (init_sym && targetm.have_ctors_dtors)
8863 (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8866 /* Dump the class references. This forces the appropriate classes
8867 to be linked into the executable image, preserving unix archive
8868 semantics. This can be removed when we move to a more dynamically
8869 linked environment. */
8871 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8873 handle_class_ref (chain);
8874 if (TREE_PURPOSE (chain))
8875 generate_classref_translation_entry (chain);
8878 for (impent = imp_list; impent; impent = impent->next)
8879 handle_impent (impent);
8881 /* Dump the string table last. */
8883 generate_strings ();
8885 if (warn_selector)
8887 int slot;
8888 hash hsh;
8890 /* Run through the selector hash tables and print a warning for any
8891 selector which has multiple methods. */
8893 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8895 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8896 check_duplicates (hsh, 0, 1);
8897 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8898 check_duplicates (hsh, 0, 1);
8902 warn_missing_braces = save_warn_missing_braces;
8905 /* Subroutines of finish_objc. */
8907 static void
8908 generate_classref_translation_entry (tree chain)
8910 tree expr, name, decl_specs, decl, sc_spec;
8911 tree type;
8913 type = TREE_TYPE (TREE_PURPOSE (chain));
8915 expr = add_objc_string (TREE_VALUE (chain), class_names);
8916 expr = build_c_cast (type, expr); /* cast! */
8918 name = DECL_NAME (TREE_PURPOSE (chain));
8920 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8922 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8923 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8925 /* The decl that is returned from start_decl is the one that we
8926 forward declared in build_class_reference. */
8927 decl = start_decl (name, decl_specs, 1, NULL_TREE);
8928 DECL_CONTEXT (decl) = NULL_TREE;
8929 finish_decl (decl, expr, NULL_TREE);
8930 return;
8933 static void
8934 handle_class_ref (tree chain)
8936 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8937 char *string = (char *) alloca (strlen (name) + 30);
8938 tree decl;
8939 tree exp;
8941 sprintf (string, "%sobjc_class_name_%s",
8942 (flag_next_runtime ? "." : "__"), name);
8944 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8945 if (flag_next_runtime)
8947 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8948 return;
8950 #endif
8952 /* Make a decl for this name, so we can use its address in a tree. */
8953 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8954 DECL_EXTERNAL (decl) = 1;
8955 TREE_PUBLIC (decl) = 1;
8957 pushdecl (decl);
8958 rest_of_decl_compilation (decl, 0, 0, 0);
8960 /* Make a decl for the address. */
8961 sprintf (string, "%sobjc_class_ref_%s",
8962 (flag_next_runtime ? "." : "__"), name);
8963 exp = build1 (ADDR_EXPR, string_type_node, decl);
8964 decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8965 DECL_INITIAL (decl) = exp;
8966 TREE_STATIC (decl) = 1;
8967 TREE_USED (decl) = 1;
8969 pushdecl (decl);
8970 rest_of_decl_compilation (decl, 0, 0, 0);
8973 static void
8974 handle_impent (struct imp_entry *impent)
8976 char *string;
8978 objc_implementation_context = impent->imp_context;
8979 implementation_template = impent->imp_template;
8981 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8983 const char *const class_name =
8984 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8986 string = (char *) alloca (strlen (class_name) + 30);
8988 sprintf (string, "%sobjc_class_name_%s",
8989 (flag_next_runtime ? "." : "__"), class_name);
8991 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8993 const char *const class_name =
8994 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8995 const char *const class_super_name =
8996 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8998 string = (char *) alloca (strlen (class_name)
8999 + strlen (class_super_name) + 30);
9001 /* Do the same for categories. Even though no references to
9002 these symbols are generated automatically by the compiler, it
9003 gives you a handle to pull them into an archive by hand. */
9004 sprintf (string, "*%sobjc_category_name_%s_%s",
9005 (flag_next_runtime ? "." : "__"), class_name, class_super_name);
9007 else
9008 return;
9010 #ifdef ASM_DECLARE_CLASS_REFERENCE
9011 if (flag_next_runtime)
9013 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
9014 return;
9016 else
9017 #endif
9019 tree decl, init;
9021 init = build_int_2 (0, 0);
9022 TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
9023 decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
9024 TREE_PUBLIC (decl) = 1;
9025 TREE_READONLY (decl) = 1;
9026 TREE_USED (decl) = 1;
9027 TREE_CONSTANT (decl) = 1;
9028 DECL_CONTEXT (decl) = 0;
9029 DECL_ARTIFICIAL (decl) = 1;
9030 DECL_INITIAL (decl) = init;
9031 assemble_variable (decl, 1, 0, 0);
9035 /* The Fix-and-Countinue functionality available in Mac OS X 10.3 and
9036 later requires that ObjC translation units participating in F&C be
9037 specially marked. The following routine accomplishes this. */
9039 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
9041 static void
9042 generate_objc_image_info (void)
9044 tree sc_spec, decl, initlist;
9046 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
9047 decl
9048 = start_decl (get_identifier ("_OBJC_IMAGE_INFO"),
9049 tree_cons (NULL_TREE,
9050 build_array_type
9051 (integer_type_node,
9052 build_index_type (build_int_2 (1, 0))),
9053 sc_spec),
9055 NULL_TREE);
9057 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
9058 initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
9059 initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
9061 TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
9062 TREE_CONSTANT (initlist) = TREE_STATIC (initlist) = 1;
9063 finish_decl (decl, initlist, NULL_TREE);
9066 /* Look up ID as an instance variable. */
9068 tree
9069 lookup_objc_ivar (tree id)
9071 tree decl;
9073 if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
9074 /* We have a message to super. */
9075 return get_super_receiver ();
9076 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
9078 if (is_private (decl))
9079 return error_mark_node;
9080 else
9081 return build_ivar_reference (id);
9083 else
9084 return 0;
9087 #include "gt-objc-objc-act.h"
9088 #include "gtype-objc.h"