c-common.h: Remove RID_ID.
[official-gcc.git] / gcc / objc / objc-act.c
blob21b279d5397b79bda13c1a5989e116e011495307
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004 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"
51 #ifdef OBJCPLUS
52 #include "cp-tree.h"
53 #else
54 #include "c-tree.h"
55 #endif
57 #include "c-common.h"
58 #include "flags.h"
59 #include "langhooks.h"
60 #include "objc-act.h"
61 #include "input.h"
62 #include "except.h"
63 #include "function.h"
64 #include "output.h"
65 #include "toplev.h"
66 #include "ggc.h"
67 #include "varray.h"
68 #include "debug.h"
69 #include "target.h"
70 #include "diagnostic.h"
71 #include "cgraph.h"
72 #include "tree-iterator.h"
73 #include "libfuncs.h"
74 #include "hashtab.h"
76 #define OBJC_VOID_AT_END void_list_node
78 /* When building Objective-C++, we are not linking against the C front-end
79 and so need to replicate the C tree-construction functions in some way. */
80 #ifdef OBJCPLUS
81 #define OBJCP_REMAP_FUNCTIONS
82 #include "objcp-decl.h"
83 #endif /* OBJCPLUS */
85 /* This is the default way of generating a method name. */
86 /* I am not sure it is really correct.
87 Perhaps there's a danger that it will make name conflicts
88 if method names contain underscores. -- rms. */
89 #ifndef OBJC_GEN_METHOD_LABEL
90 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
91 do { \
92 char *temp; \
93 sprintf ((BUF), "_%s_%s_%s_%s", \
94 ((IS_INST) ? "i" : "c"), \
95 (CLASS_NAME), \
96 ((CAT_NAME)? (CAT_NAME) : ""), \
97 (SEL_NAME)); \
98 for (temp = (BUF); *temp; temp++) \
99 if (*temp == ':') *temp = '_'; \
100 } while (0)
101 #endif
103 /* These need specifying. */
104 #ifndef OBJC_FORWARDING_STACK_OFFSET
105 #define OBJC_FORWARDING_STACK_OFFSET 0
106 #endif
108 #ifndef OBJC_FORWARDING_MIN_OFFSET
109 #define OBJC_FORWARDING_MIN_OFFSET 0
110 #endif
112 /* Set up for use of obstacks. */
114 #include "obstack.h"
116 /* This obstack is used to accumulate the encoding of a data type. */
117 static struct obstack util_obstack;
119 /* This points to the beginning of obstack contents, so we can free
120 the whole contents. */
121 char *util_firstobj;
123 /* The version identifies which language generation and runtime
124 the module (file) was compiled for, and is recorded in the
125 module descriptor. */
127 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
128 #define PROTOCOL_VERSION 2
130 /* (Decide if these can ever be validly changed.) */
131 #define OBJC_ENCODE_INLINE_DEFS 0
132 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
134 /*** Private Interface (procedures) ***/
136 /* Used by compile_file. */
138 static void init_objc (void);
139 static void finish_objc (void);
141 /* Code generation. */
143 static void synth_module_prologue (void);
144 static tree objc_build_constructor (tree, tree);
145 static void build_module_descriptor (void);
146 static void build_module_initializer_routine (void);
147 static tree init_module_descriptor (tree);
148 static tree build_objc_method_call (int, tree, tree, tree, tree);
149 static void generate_strings (void);
150 static tree get_proto_encoding (tree);
151 static void build_selector_translation_table (void);
152 static tree lookup_interface (tree);
153 static tree objc_add_static_instance (tree, tree);
155 static tree start_class (enum tree_code, tree, tree, tree);
156 static tree continue_class (tree);
157 static void finish_class (tree);
158 static void start_method_def (tree);
159 #ifdef OBJCPLUS
160 static void objc_start_function (tree, tree, tree, tree);
161 #else
162 static void objc_start_function (tree, tree, tree, struct c_arg_info *);
163 #endif
164 static tree start_protocol (enum tree_code, tree, tree);
165 static tree build_method_decl (enum tree_code, tree, tree, tree);
166 static tree objc_add_method (tree, tree, int);
167 static tree add_instance_variable (tree, int, tree);
168 static tree build_ivar_reference (tree);
169 static tree is_ivar (tree, tree);
170 static int is_private (tree);
171 static tree get_super_receiver (void);
173 static void build_objc_exception_stuff (void);
174 static void build_next_objc_exception_stuff (void);
176 static tree build_ivar_template (void);
177 static tree build_method_template (void);
178 static tree build_private_template (tree);
179 static void build_class_template (void);
180 static void build_selector_template (void);
181 static void build_category_template (void);
182 static tree lookup_method_in_hash_lists (tree, int);
183 static void build_super_template (void);
184 static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
185 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
186 static void synth_forward_declarations (void);
187 static int ivar_list_length (tree);
188 static tree get_class_ivars (tree);
189 static void generate_ivar_lists (void);
190 static void generate_dispatch_tables (void);
191 static void generate_shared_structures (void);
192 static tree generate_protocol_list (tree);
193 static void build_protocol_reference (tree);
195 static tree build_keyword_selector (tree);
196 static const char *synth_id_with_class_suffix (const char *, tree);
198 static void generate_static_references (void);
199 static int check_methods_accessible (tree, tree, int);
200 static void encode_aggregate_within (tree, int, int, int, int);
201 static const char *objc_demangle (const char *);
203 /* Hash tables to manage the global pool of method prototypes. */
205 hash *nst_method_hash_list = 0;
206 hash *cls_method_hash_list = 0;
208 static size_t hash_func (tree);
209 static void hash_init (void);
210 static void hash_enter (hash *, tree);
211 static hash hash_lookup (hash *, tree);
212 static void hash_add_attr (hash, tree);
213 static tree lookup_method (tree, tree);
214 static tree lookup_method_static (tree, tree, int);
215 static void add_method_to_hash_list (hash *, tree);
216 static tree add_class (tree);
217 static void add_category (tree, tree);
218 static inline tree lookup_category (tree, tree);
220 enum string_section
222 class_names, /* class, category, protocol, module names */
223 meth_var_names, /* method and variable names */
224 meth_var_types /* method and variable type descriptors */
227 static tree add_objc_string (tree, enum string_section);
228 static tree get_objc_string_decl (tree, enum string_section);
229 static tree build_objc_string_decl (enum string_section);
230 static tree build_selector_reference_decl (void);
231 static void build_selector_table_decl (void);
233 /* Protocol additions. */
235 static tree add_protocol (tree);
236 static tree lookup_protocol (tree);
237 static void check_protocol_recursively (tree, tree);
238 static tree lookup_and_install_protocols (tree);
240 /* Type encoding. */
242 static void encode_type_qualifiers (tree);
243 static void encode_pointer (tree, int, int);
244 static void encode_array (tree, int, int);
245 static void encode_aggregate (tree, int, int);
246 static void encode_next_bitfield (int);
247 static void encode_gnu_bitfield (int, tree, int);
248 static void encode_type (tree, int, int);
249 static void encode_field_decl (tree, int, int);
251 #ifdef OBJCPLUS
252 static void really_start_method (tree, tree);
253 #else
254 static void really_start_method (tree, struct c_arg_info *);
255 #endif
256 static int objc_types_are_equivalent (tree, tree);
257 static int comp_proto_with_proto (tree, tree);
258 static tree get_arg_type_list (tree, int, int);
259 static void objc_push_parm (tree);
260 #ifdef OBJCPLUS
261 static tree objc_get_parm_info (int);
262 #else
263 static struct c_arg_info *objc_get_parm_info (int);
264 #endif
265 static void synth_self_and_ucmd_args (void);
267 /* Utilities for debugging and error diagnostics. */
269 static void warn_with_method (const char *, int, tree);
270 static void error_with_ivar (const char *, tree);
271 static char *gen_type_name (tree);
272 static char *gen_type_name_0 (tree);
273 static char *gen_method_decl (tree);
274 static char *gen_declaration (tree);
275 static void dump_interface (FILE *, tree);
277 /* Everything else. */
279 static tree lookup_method_in_protocol_list (tree, tree, int);
280 static tree lookup_protocol_in_reflist (tree, tree);
281 static tree start_var_decl (tree, const char *);
282 static void finish_var_decl (tree, tree);
283 static tree create_field_decl (tree, const char *);
284 static tree setup_string_decl (void);
285 static int check_string_class_template (void);
286 static tree my_build_string (int, const char *);
287 static void build_objc_symtab_template (void);
288 static tree init_def_list (tree);
289 static tree init_objc_symtab (tree);
290 static tree build_metadata_decl (const char *, tree);
291 static void forward_declare_categories (void);
292 static void generate_objc_symtab_decl (void);
293 static tree build_selector (tree);
294 static tree build_typed_selector_reference (tree, tree);
295 static tree build_selector_reference (tree);
296 static tree build_class_reference_decl (void);
297 static void add_class_reference (tree);
298 static void build_protocol_template (void);
299 static tree build_descriptor_table_initializer (tree, tree);
300 static tree build_method_prototype_list_template (tree, int);
301 static tree build_method_prototype_template (void);
302 static tree objc_method_parm_type (tree);
303 static int objc_encoded_type_size (tree);
304 static tree encode_method_prototype (tree);
305 static tree generate_descriptor_table (tree, const char *, int, tree, tree);
306 static void generate_method_descriptors (tree);
307 static void generate_protocol_references (tree);
308 static void generate_protocols (void);
309 static void check_ivars (tree, tree);
310 static tree build_ivar_list_template (tree, int);
311 static tree build_method_list_template (tree, int);
312 static tree build_ivar_list_initializer (tree, tree);
313 static tree generate_ivars_list (tree, const char *, int, tree);
314 static tree build_dispatch_table_initializer (tree, tree);
315 static tree generate_dispatch_table (tree, const char *, int, tree);
316 static tree build_shared_structure_initializer (tree, tree, tree, tree,
317 tree, int, tree, tree, tree);
318 static void generate_category (tree);
319 static tree adjust_type_for_id_default (tree);
320 static tree check_duplicates (hash, int, int);
321 static tree receiver_is_class_object (tree, int, int);
322 static int check_methods (tree, tree, int);
323 static int conforms_to_protocol (tree, tree);
324 static void check_protocol (tree, const char *, const char *);
325 static void check_protocols (tree, const char *, const char *);
326 static void generate_classref_translation_entry (tree);
327 static void handle_class_ref (tree);
328 static void generate_struct_by_value_array (void)
329 ATTRIBUTE_NORETURN;
330 static void mark_referenced_methods (void);
331 static void generate_objc_image_info (void);
333 /*** Private Interface (data) ***/
335 /* Reserved tag definitions. */
337 #define OBJECT_TYPEDEF_NAME "id"
338 #define CLASS_TYPEDEF_NAME "Class"
340 #define TAG_OBJECT "objc_object"
341 #define TAG_CLASS "objc_class"
342 #define TAG_SUPER "objc_super"
343 #define TAG_SELECTOR "objc_selector"
345 #define UTAG_CLASS "_objc_class"
346 #define UTAG_IVAR "_objc_ivar"
347 #define UTAG_IVAR_LIST "_objc_ivar_list"
348 #define UTAG_METHOD "_objc_method"
349 #define UTAG_METHOD_LIST "_objc_method_list"
350 #define UTAG_CATEGORY "_objc_category"
351 #define UTAG_MODULE "_objc_module"
352 #define UTAG_SYMTAB "_objc_symtab"
353 #define UTAG_SUPER "_objc_super"
354 #define UTAG_SELECTOR "_objc_selector"
356 #define UTAG_PROTOCOL "_objc_protocol"
357 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
358 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
360 /* Note that the string object global name is only needed for the
361 NeXT runtime. */
362 #define STRING_OBJECT_GLOBAL_FORMAT "_%sClassReference"
364 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
366 static const char *TAG_GETCLASS;
367 static const char *TAG_GETMETACLASS;
368 static const char *TAG_MSGSEND;
369 static const char *TAG_MSGSENDSUPER;
370 /* The NeXT Objective-C messenger may have two extra entry points, for use
371 when returning a structure. */
372 static const char *TAG_MSGSEND_STRET;
373 static const char *TAG_MSGSENDSUPER_STRET;
374 static const char *default_constant_string_class_name;
376 /* Runtime metadata flags. */
377 #define CLS_FACTORY 0x0001L
378 #define CLS_META 0x0002L
380 #define OBJC_MODIFIER_STATIC 0x00000001
381 #define OBJC_MODIFIER_FINAL 0x00000002
382 #define OBJC_MODIFIER_PUBLIC 0x00000004
383 #define OBJC_MODIFIER_PRIVATE 0x00000008
384 #define OBJC_MODIFIER_PROTECTED 0x00000010
385 #define OBJC_MODIFIER_NATIVE 0x00000020
386 #define OBJC_MODIFIER_SYNCHRONIZED 0x00000040
387 #define OBJC_MODIFIER_ABSTRACT 0x00000080
388 #define OBJC_MODIFIER_VOLATILE 0x00000100
389 #define OBJC_MODIFIER_TRANSIENT 0x00000200
390 #define OBJC_MODIFIER_NONE_SPECIFIED 0x80000000
392 /* NeXT-specific tags. */
394 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
395 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
396 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
397 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
398 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
399 #define TAG_EXCEPTIONMATCH "objc_exception_match"
400 #define TAG_EXCEPTIONTHROW "objc_exception_throw"
401 #define TAG_SYNCENTER "objc_sync_enter"
402 #define TAG_SYNCEXIT "objc_sync_exit"
403 #define TAG_SETJMP "_setjmp"
404 #define UTAG_EXCDATA "_objc_exception_data"
406 /* GNU-specific tags. */
408 #define TAG_EXECCLASS "__objc_exec_class"
409 #define TAG_GNUINIT "__objc_gnu_init"
411 /* The OCTI_... enumeration itself is in objc/objc-act.h. */
412 tree objc_global_trees[OCTI_MAX];
414 static void handle_impent (struct imp_entry *);
416 struct imp_entry *imp_list = 0;
417 int imp_count = 0; /* `@implementation' */
418 int cat_count = 0; /* `@category' */
420 enum tree_code objc_inherit_code;
421 int objc_public_flag;
423 /* Use to generate method labels. */
424 static int method_slot = 0;
426 #define BUFSIZE 1024
428 static char *errbuf; /* Buffer for error diagnostics */
430 /* Data imported from tree.c. */
432 extern enum debug_info_type write_symbols;
434 /* Data imported from toplev.c. */
436 extern const char *dump_base_name;
438 static int flag_typed_selectors;
440 /* Store all constructed constant strings in a hash table so that
441 they get uniqued properly. */
443 struct string_descriptor GTY(())
445 /* The literal argument . */
446 tree literal;
448 /* The resulting constant string. */
449 tree constructor;
452 static GTY((param_is (struct string_descriptor))) htab_t string_htab;
454 static hashval_t string_hash (const void *);
455 static int string_eq (const void *, const void *);
457 FILE *gen_declaration_file;
459 /* Tells "encode_pointer/encode_aggregate" whether we are generating
460 type descriptors for instance variables (as opposed to methods).
461 Type descriptors for instance variables contain more information
462 than methods (for static typing and embedded structures). */
464 static int generating_instance_variables = 0;
466 /* Some platforms pass small structures through registers versus
467 through an invisible pointer. Determine at what size structure is
468 the transition point between the two possibilities. */
470 static void
471 generate_struct_by_value_array (void)
473 tree type;
474 tree field_decl, field_decl_chain;
475 int i, j;
476 int aggregate_in_mem[32];
477 int found = 0;
479 /* Presumably no platform passes 32 byte structures in a register. */
480 for (i = 1; i < 32; i++)
482 char buffer[5];
484 /* Create an unnamed struct that has `i' character components */
485 type = start_struct (RECORD_TYPE, NULL_TREE);
487 strcpy (buffer, "c1");
488 field_decl = create_field_decl (char_type_node,
489 buffer);
490 field_decl_chain = field_decl;
492 for (j = 1; j < i; j++)
494 sprintf (buffer, "c%d", j + 1);
495 field_decl = create_field_decl (char_type_node,
496 buffer);
497 chainon (field_decl_chain, field_decl);
499 finish_struct (type, field_decl_chain, NULL_TREE);
501 aggregate_in_mem[i] = aggregate_value_p (type, 0);
502 if (!aggregate_in_mem[i])
503 found = 1;
506 /* We found some structures that are returned in registers instead of memory
507 so output the necessary data. */
508 if (found)
510 for (i = 31; i >= 0; i--)
511 if (!aggregate_in_mem[i])
512 break;
513 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
515 /* The first member of the structure is always 0 because we don't handle
516 structures with 0 members */
517 printf ("static int struct_forward_array[] = {\n 0");
519 for (j = 1; j <= i; j++)
520 printf (", %d", aggregate_in_mem[j]);
521 printf ("\n};\n");
524 exit (0);
527 bool
528 objc_init (void)
530 #ifdef OBJCPLUS
531 if (cxx_init () == false)
532 #else
533 if (c_objc_common_init () == false)
534 #endif
535 return false;
537 #ifndef USE_MAPPED_LOCATION
538 /* Force the line number back to 0; check_newline will have
539 raised it to 1, which will make the builtin functions appear
540 not to be built in. */
541 input_line = 0;
542 #endif
544 /* If gen_declaration desired, open the output file. */
545 if (flag_gen_declaration)
547 register char * const dumpname = concat (dump_base_name, ".decl", NULL);
548 gen_declaration_file = fopen (dumpname, "w");
549 if (gen_declaration_file == 0)
550 fatal_error ("can't open %s: %m", dumpname);
551 free (dumpname);
554 if (flag_next_runtime)
556 TAG_GETCLASS = "objc_getClass";
557 TAG_GETMETACLASS = "objc_getMetaClass";
558 TAG_MSGSEND = "objc_msgSend";
559 TAG_MSGSENDSUPER = "objc_msgSendSuper";
560 TAG_MSGSEND_STRET = "objc_msgSend_stret";
561 TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
562 default_constant_string_class_name = "NSConstantString";
564 else
566 TAG_GETCLASS = "objc_get_class";
567 TAG_GETMETACLASS = "objc_get_meta_class";
568 TAG_MSGSEND = "objc_msg_lookup";
569 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
570 /* GNU runtime does not provide special functions to support
571 structure-returning methods. */
572 default_constant_string_class_name = "NXConstantString";
573 flag_typed_selectors = 1;
576 init_objc ();
578 if (print_struct_values)
579 generate_struct_by_value_array ();
581 return true;
584 void
585 objc_finish_file (void)
587 mark_referenced_methods ();
589 #ifdef OBJCPLUS
590 /* We need to instantiate templates _before_ we emit ObjC metadata;
591 if we do not, some metadata (such as selectors) may go missing. */
592 instantiate_pending_templates (0);
593 #endif
595 /* Finalize Objective-C runtime data. No need to generate tables
596 and code if only checking syntax. */
597 if (!flag_syntax_only)
598 finish_objc ();
600 if (gen_declaration_file)
601 fclose (gen_declaration_file);
603 #ifdef OBJCPLUS
604 cp_finish_file ();
605 #endif
608 /* Return the first occurrence of a method declaration corresponding
609 to sel_name in rproto_list. Search rproto_list recursively.
610 If is_class is 0, search for instance methods, otherwise for class
611 methods. */
612 static tree
613 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
614 int is_class)
616 tree rproto, p;
617 tree fnd = 0;
619 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
621 p = TREE_VALUE (rproto);
623 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
625 if ((fnd = lookup_method (is_class
626 ? PROTOCOL_CLS_METHODS (p)
627 : PROTOCOL_NST_METHODS (p), sel_name)))
629 else if (PROTOCOL_LIST (p))
630 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
631 sel_name, is_class);
633 else
635 ; /* An identifier...if we could not find a protocol. */
638 if (fnd)
639 return fnd;
642 return 0;
645 static tree
646 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
648 tree rproto, p;
650 /* Make sure the protocol is supported by the object on the rhs. */
651 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
653 tree fnd = 0;
654 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
656 p = TREE_VALUE (rproto);
658 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
660 if (lproto == p)
661 fnd = lproto;
663 else if (PROTOCOL_LIST (p))
664 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
667 if (fnd)
668 return fnd;
671 else
673 ; /* An identifier...if we could not find a protocol. */
676 return 0;
679 void
680 objc_start_class_interface (tree class, tree super_class, tree protos)
682 objc_interface_context
683 = objc_ivar_context
684 = start_class (CLASS_INTERFACE_TYPE, class, super_class, protos);
685 objc_public_flag = 0;
688 void
689 objc_start_category_interface (tree class, tree categ, tree protos)
691 objc_interface_context
692 = start_class (CATEGORY_INTERFACE_TYPE, class, categ, protos);
693 objc_ivar_chain
694 = continue_class (objc_interface_context);
697 void
698 objc_start_protocol (tree name, tree protos)
700 objc_interface_context
701 = start_protocol (PROTOCOL_INTERFACE_TYPE, name, protos);
704 void
705 objc_continue_interface (void)
707 objc_ivar_chain
708 = continue_class (objc_interface_context);
711 void
712 objc_finish_interface (void)
714 finish_class (objc_interface_context);
715 objc_interface_context = NULL_TREE;
718 void
719 objc_start_class_implementation (tree class, tree super_class)
721 objc_implementation_context
722 = objc_ivar_context
723 = start_class (CLASS_IMPLEMENTATION_TYPE, class, super_class, NULL_TREE);
724 objc_public_flag = 0;
727 void
728 objc_start_category_implementation (tree class, tree categ)
730 objc_implementation_context
731 = start_class (CATEGORY_IMPLEMENTATION_TYPE, class, categ, NULL_TREE);
732 objc_ivar_chain
733 = continue_class (objc_implementation_context);
736 void
737 objc_continue_implementation (void)
739 objc_ivar_chain
740 = continue_class (objc_implementation_context);
743 void
744 objc_finish_implementation (void)
746 if (objc_implementation_context)
748 finish_class (objc_implementation_context);
749 objc_ivar_chain = NULL_TREE;
750 objc_implementation_context = NULL_TREE;
752 else
753 warning ("`@end' must appear in an @implementation context");
756 void
757 objc_set_visibility (int visibility)
759 objc_public_flag = visibility;
762 void
763 objc_set_method_type (enum tree_code type)
765 objc_inherit_code = (type == PLUS_EXPR
766 ? CLASS_METHOD_DECL
767 : INSTANCE_METHOD_DECL);
770 tree
771 objc_build_method_signature (tree rettype, tree selector, tree optparms)
773 return build_method_decl (objc_inherit_code, rettype, selector, optparms);
776 void
777 objc_add_method_declaration (tree decl)
779 if (!objc_interface_context)
780 fatal_error ("method declaration not in @interface context");
782 objc_add_method (objc_interface_context,
783 decl,
784 objc_inherit_code == CLASS_METHOD_DECL);
787 void
788 objc_start_method_definition (tree decl)
790 if (!objc_implementation_context)
791 fatal_error ("method definition not in @implementation context");
793 objc_add_method (objc_implementation_context,
794 decl,
795 objc_inherit_code == CLASS_METHOD_DECL);
796 start_method_def (decl);
799 void
800 objc_add_instance_variable (tree decl)
802 (void) add_instance_variable (objc_ivar_context,
803 objc_public_flag,
804 decl);
807 /* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
808 an '@'. */
811 objc_is_reserved_word (tree ident)
813 unsigned char code = C_RID_CODE (ident);
815 return (OBJC_IS_AT_KEYWORD (code)
816 #ifdef OBJCPLUS
817 || code == RID_CLASS || code == RID_PUBLIC
818 || code == RID_PROTECTED || code == RID_PRIVATE
819 || code == RID_TRY || code == RID_THROW || code == RID_CATCH
820 #endif
824 /* Return true if TYPE is 'id'. */
826 static bool
827 objc_is_object_id (tree type)
829 return OBJC_TYPE_NAME (type) == objc_object_id;
832 static bool
833 objc_is_class_id (tree type)
835 return OBJC_TYPE_NAME (type) == objc_class_id;
838 /* Return 1 if LHS and RHS are compatible types for assignment or
839 various other operations. Return 0 if they are incompatible, and
840 return -1 if we choose to not decide (because the types are really
841 just C types, not ObjC specific ones). When the operation is
842 REFLEXIVE (typically comparisons), check for compatibility in
843 either direction; when it's not (typically assignments), don't.
845 This function is called in two cases: when both lhs and rhs are
846 pointers to records (in which case we check protocols too), and
847 when both lhs and rhs are records (in which case we check class
848 inheritance only).
850 Warnings about classes/protocols not implementing a protocol are
851 emitted here (multiple of those warnings might be emitted for a
852 single line!); generic warnings about incompatible assignments and
853 lacks of casts in comparisons are/must be emitted by the caller if
854 we return 0.
858 objc_comptypes (tree lhs, tree rhs, int reflexive)
860 /* New clause for protocols. */
862 /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE. We only
863 manage the ObjC ones, and leave the rest to the C code. */
864 if (TREE_CODE (lhs) == POINTER_TYPE
865 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
866 && TREE_CODE (rhs) == POINTER_TYPE
867 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
869 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (lhs);
870 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (rhs);
872 if (lhs_is_proto)
874 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
875 tree rproto, rproto_list;
876 tree p;
878 /* <Protocol> = <Protocol> */
879 if (rhs_is_proto)
881 /* Class <Protocol> != id <Protocol>;
882 id <Protocol> != Class <Protocol> */
883 if (IS_ID (lhs) != IS_ID (rhs))
884 return 0;
886 rproto_list = TYPE_PROTOCOL_LIST (rhs);
888 if (!reflexive)
890 /* An assignment between objects of type 'id
891 <Protocol>'; make sure the protocol on the lhs is
892 supported by the object on the rhs. */
893 for (lproto = lproto_list; lproto;
894 lproto = TREE_CHAIN (lproto))
896 p = TREE_VALUE (lproto);
897 rproto = lookup_protocol_in_reflist (rproto_list, p);
899 if (!rproto)
900 warning
901 ("object does not conform to the `%s' protocol",
902 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
904 return 1;
906 else
908 /* Obscure case - a comparison between two objects
909 of type 'id <Protocol>'. Check that either the
910 protocol on the lhs is supported by the object on
911 the rhs, or viceversa. */
913 /* Check if the protocol on the lhs is supported by the
914 object on the rhs. */
915 for (lproto = lproto_list; lproto;
916 lproto = TREE_CHAIN (lproto))
918 p = TREE_VALUE (lproto);
919 rproto = lookup_protocol_in_reflist (rproto_list, p);
921 if (!rproto)
923 /* Check failed - check if the protocol on the rhs
924 is supported by the object on the lhs. */
925 for (rproto = rproto_list; rproto;
926 rproto = TREE_CHAIN (rproto))
928 p = TREE_VALUE (rproto);
929 lproto = lookup_protocol_in_reflist (lproto_list,
932 if (!lproto)
934 /* This check failed too: incompatible */
935 return 0;
938 return 1;
941 return 1;
944 /* <Protocol> = <class> * */
945 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
947 tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
948 tree rinter;
950 /* Class <Protocol> != <class> * */
951 if (IS_CLASS (lhs))
952 return 0;
954 /* Make sure the protocol is supported by the object on
955 the rhs. */
956 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
958 p = TREE_VALUE (lproto);
959 rproto = 0;
960 rinter = lookup_interface (rname);
962 while (rinter && !rproto)
964 tree cat;
966 rproto_list = CLASS_PROTOCOL_LIST (rinter);
967 rproto = lookup_protocol_in_reflist (rproto_list, p);
968 /* If the underlying ObjC class does not have
969 the protocol we're looking for, check for "one-off"
970 protocols (e.g., `NSObject<MyProt> *foo;') attached
971 to the rhs. */
972 if (!rproto)
974 rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
975 rproto = lookup_protocol_in_reflist (rproto_list, p);
978 /* Check for protocols adopted by categories. */
979 cat = CLASS_CATEGORY_LIST (rinter);
980 while (cat && !rproto)
982 rproto_list = CLASS_PROTOCOL_LIST (cat);
983 rproto = lookup_protocol_in_reflist (rproto_list, p);
984 cat = CLASS_CATEGORY_LIST (cat);
987 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
990 if (!rproto)
991 warning ("class `%s' does not implement the `%s' protocol",
992 IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
993 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
995 return 1;
997 /* id <Protocol> = id; Class <Protocol> = id */
998 else if (objc_is_object_id (TREE_TYPE (rhs)))
1000 return 1;
1002 /* id <Protocol> != Class; Class <Protocol> = Class */
1003 else if (objc_is_class_id (TREE_TYPE (rhs)))
1005 return IS_CLASS (lhs);
1007 /* <Protocol> = ?? : let comptypes decide. */
1008 return -1;
1010 else if (rhs_is_proto)
1012 /* <class> * = <Protocol> */
1013 if (TYPED_OBJECT (TREE_TYPE (lhs)))
1015 /* <class> * != Class <Protocol> */
1016 if (IS_CLASS (rhs))
1017 return 0;
1019 if (reflexive)
1021 tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
1022 tree rinter;
1023 tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
1025 /* Make sure the protocol is supported by the object on
1026 the lhs. */
1027 for (rproto = rproto_list; rproto;
1028 rproto = TREE_CHAIN (rproto))
1030 tree p = TREE_VALUE (rproto);
1031 tree lproto = 0;
1032 rinter = lookup_interface (rname);
1034 while (rinter && !lproto)
1036 tree cat;
1038 tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
1039 lproto = lookup_protocol_in_reflist (lproto_list, p);
1040 /* If the underlying ObjC class does not
1041 have the protocol we're looking for,
1042 check for "one-off" protocols (e.g.,
1043 `NSObject<MyProt> *foo;') attached to the
1044 lhs. */
1045 if (!lproto)
1047 lproto_list = TYPE_PROTOCOL_LIST
1048 (TREE_TYPE (lhs));
1049 lproto = lookup_protocol_in_reflist
1050 (lproto_list, p);
1053 /* Check for protocols adopted by categories. */
1054 cat = CLASS_CATEGORY_LIST (rinter);
1055 while (cat && !lproto)
1057 lproto_list = CLASS_PROTOCOL_LIST (cat);
1058 lproto = lookup_protocol_in_reflist (lproto_list,
1060 cat = CLASS_CATEGORY_LIST (cat);
1063 rinter = lookup_interface (CLASS_SUPER_NAME
1064 (rinter));
1067 if (!lproto)
1068 warning ("class `%s' does not implement the `%s' protocol",
1069 IDENTIFIER_POINTER (OBJC_TYPE_NAME
1070 (TREE_TYPE (lhs))),
1071 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1073 return 1;
1075 else
1076 return 0;
1078 /* id = id <Protocol>; id = Class <Protocol> */
1079 else if (objc_is_object_id (TREE_TYPE (lhs)))
1081 return 1;
1083 /* Class != id <Protocol>; Class = Class <Protocol> */
1084 else if (objc_is_class_id (TREE_TYPE (lhs)))
1086 return IS_CLASS (rhs);
1088 /* ??? = <Protocol> : let comptypes decide */
1089 else
1091 return -1;
1094 else
1096 /* Attention: we shouldn't defer to comptypes here. One bad
1097 side effect would be that we might loose the REFLEXIVE
1098 information.
1100 lhs = TREE_TYPE (lhs);
1101 rhs = TREE_TYPE (rhs);
1105 if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
1107 /* Nothing to do with ObjC - let immediately comptypes take
1108 responsibility for checking. */
1109 return -1;
1112 /* `id' = `<class> *' `<class> *' = `id': always allow it.
1113 Please note that
1114 'Object *o = [[Object alloc] init]; falls
1115 in the case <class> * = `id'.
1117 if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
1118 || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
1119 return 1;
1121 /* `id' = `Class', `Class' = `id' */
1123 else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
1124 || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
1125 return 1;
1127 /* `Class' != `<class> *' && `<class> *' != `Class'! */
1128 else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
1129 || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
1130 return 0;
1132 /* `<class> *' = `<class> *' */
1134 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
1136 tree lname = OBJC_TYPE_NAME (lhs);
1137 tree rname = OBJC_TYPE_NAME (rhs);
1138 tree inter;
1140 if (lname == rname)
1141 return 1;
1143 /* If the left hand side is a super class of the right hand side,
1144 allow it. */
1145 for (inter = lookup_interface (rname); inter;
1146 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1147 if (lname == CLASS_SUPER_NAME (inter))
1148 return 1;
1150 /* Allow the reverse when reflexive. */
1151 if (reflexive)
1152 for (inter = lookup_interface (lname); inter;
1153 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1154 if (rname == CLASS_SUPER_NAME (inter))
1155 return 1;
1157 return 0;
1159 else
1160 /* Not an ObjC type - let comptypes do the check. */
1161 return -1;
1164 /* Called from finish_decl. */
1166 void
1167 objc_check_decl (tree decl)
1169 tree type = TREE_TYPE (decl);
1171 if (TREE_CODE (type) != RECORD_TYPE)
1172 return;
1173 if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
1174 error ("statically allocated instance of Objective-C class `%s'",
1175 IDENTIFIER_POINTER (type));
1178 /* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
1179 either name an Objective-C class, or refer to the special 'id' or 'Class'
1180 types. If INTERFACE is not a valid ObjC type, just return it unchanged. */
1182 tree
1183 objc_get_protocol_qualified_type (tree interface, tree protocols)
1185 tree type;
1187 if (!interface)
1188 type = objc_object_type;
1189 else if (!(type = objc_is_id (interface)))
1191 type = objc_is_class_name (interface);
1193 if (type)
1194 type = xref_tag (RECORD_TYPE, type);
1195 else
1196 return interface;
1199 if (protocols)
1201 type = build_variant_type_copy (type);
1202 /* Look up protocols and install in lang specific list. Note
1203 that the protocol list can have a different lifetime than T! */
1204 SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
1206 /* Establish the ObjC-ness of this record. */
1207 if (TREE_CODE (type) == RECORD_TYPE)
1208 TREE_STATIC_TEMPLATE (type) = 1;
1211 return type;
1214 /* Check for circular dependencies in protocols. The arguments are
1215 PROTO, the protocol to check, and LIST, a list of protocol it
1216 conforms to. */
1218 static void
1219 check_protocol_recursively (tree proto, tree list)
1221 tree p;
1223 for (p = list; p; p = TREE_CHAIN (p))
1225 tree pp = TREE_VALUE (p);
1227 if (TREE_CODE (pp) == IDENTIFIER_NODE)
1228 pp = lookup_protocol (pp);
1230 if (pp == proto)
1231 fatal_error ("protocol `%s' has circular dependency",
1232 IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1233 if (pp)
1234 check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1238 /* Look up PROTOCOLS, and return a list of those that are found.
1239 If none are found, return NULL. */
1241 static tree
1242 lookup_and_install_protocols (tree protocols)
1244 tree proto;
1245 tree return_value = NULL_TREE;
1247 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1249 tree ident = TREE_VALUE (proto);
1250 tree p = lookup_protocol (ident);
1252 if (!p)
1253 error ("cannot find protocol declaration for `%s'",
1254 IDENTIFIER_POINTER (ident));
1255 else
1256 return_value = chainon (return_value,
1257 build_tree_list (NULL_TREE, p));
1260 return return_value;
1263 /* Create a declaration for field NAME of a given TYPE. */
1265 static tree
1266 create_field_decl (tree type, const char *name)
1268 return build_decl (FIELD_DECL, get_identifier (name), type);
1271 /* Create a global, static declaration for variable NAME of a given TYPE. The
1272 finish_var_decl() routine will need to be called on it afterwards. */
1274 static tree
1275 start_var_decl (tree type, const char *name)
1277 tree var = build_decl (VAR_DECL, get_identifier (name), type);
1279 TREE_STATIC (var) = 1;
1280 DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */
1281 DECL_IGNORED_P (var) = 1;
1282 DECL_ARTIFICIAL (var) = 1;
1283 DECL_CONTEXT (var) = NULL_TREE;
1284 #ifdef OBJCPLUS
1285 DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
1286 #endif
1288 return var;
1291 /* Finish off the variable declaration created by start_var_decl(). */
1293 static void
1294 finish_var_decl (tree var, tree initializer)
1296 finish_decl (var, initializer, NULL_TREE);
1297 /* Ensure that the variable actually gets output. */
1298 mark_decl_referenced (var);
1299 /* Mark the decl to avoid "defined but not used" warning. */
1300 TREE_USED (var) = 1;
1303 /* Find the decl for the constant string class reference. This is only
1304 used for the NeXT runtime. */
1306 static tree
1307 setup_string_decl (void)
1309 char *name;
1310 size_t length;
1312 /* %s in format will provide room for terminating null */
1313 length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1314 + strlen (constant_string_class_name);
1315 name = xmalloc (length);
1316 sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1317 constant_string_class_name);
1318 constant_string_global_id = get_identifier (name);
1319 string_class_decl = lookup_name (constant_string_global_id);
1321 return string_class_decl;
1324 /* Purpose: "play" parser, creating/installing representations
1325 of the declarations that are required by Objective-C.
1327 Model:
1329 type_spec--------->sc_spec
1330 (tree_list) (tree_list)
1333 identifier_node identifier_node */
1335 static void
1336 synth_module_prologue (void)
1338 tree type;
1339 enum debug_info_type save_write_symbols = write_symbols;
1340 const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1342 /* Suppress outputting debug symbols, because
1343 dbxout_init hasn'r been called yet. */
1344 write_symbols = NO_DEBUG;
1345 debug_hooks = &do_nothing_debug_hooks;
1347 #ifdef OBJCPLUS
1348 push_lang_context (lang_name_c); /* extern "C" */
1349 #endif
1351 /* The following are also defined in <objc/objc.h> and friends. */
1353 objc_object_id = get_identifier (TAG_OBJECT);
1354 objc_class_id = get_identifier (TAG_CLASS);
1356 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1357 objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
1359 objc_object_type = build_pointer_type (objc_object_reference);
1360 objc_class_type = build_pointer_type (objc_class_reference);
1362 objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
1363 objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
1365 /* Declare the 'id' and 'Class' typedefs. */
1367 type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1368 objc_object_name,
1369 objc_object_type));
1370 DECL_IN_SYSTEM_HEADER (type) = 1;
1371 type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
1372 objc_class_name,
1373 objc_class_type));
1374 DECL_IN_SYSTEM_HEADER (type) = 1;
1376 /* Forward-declare '@interface Protocol'. */
1378 type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1379 objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
1380 objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1381 type));
1383 /* Declare type of selector-objects that represent an operation name. */
1385 if (flag_next_runtime)
1386 /* `struct objc_selector *' */
1387 objc_selector_type
1388 = build_pointer_type (xref_tag (RECORD_TYPE,
1389 get_identifier (TAG_SELECTOR)));
1390 else
1391 /* `const struct objc_selector *' */
1392 objc_selector_type
1393 = build_pointer_type
1394 (build_qualified_type (xref_tag (RECORD_TYPE,
1395 get_identifier (TAG_SELECTOR)),
1396 TYPE_QUAL_CONST));
1398 /* Declare receiver type used for dispatching messages to 'super'. */
1400 /* `struct objc_super *' */
1401 objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1402 get_identifier (TAG_SUPER)));
1404 if (flag_next_runtime)
1406 /* NB: In order to call one of the ..._stret (struct-returning)
1407 functions, the function *MUST* first be cast to a signature that
1408 corresponds to the actual ObjC method being invoked. This is
1409 what is done by the build_objc_method_call() routine below. */
1411 /* id objc_msgSend (id, SEL, ...); */
1412 /* id objc_msgSendNonNil (id, SEL, ...); */
1413 /* id objc_msgSend_stret (id, SEL, ...); */
1414 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1415 type
1416 = build_function_type (objc_object_type,
1417 tree_cons (NULL_TREE, objc_object_type,
1418 tree_cons (NULL_TREE, objc_selector_type,
1419 NULL_TREE)));
1420 umsg_decl = builtin_function (TAG_MSGSEND,
1421 type, 0, NOT_BUILT_IN,
1422 NULL, NULL_TREE);
1423 umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1424 type, 0, NOT_BUILT_IN,
1425 NULL, NULL_TREE);
1426 umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1427 type, 0, NOT_BUILT_IN,
1428 NULL, NULL_TREE);
1429 umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1430 type, 0, NOT_BUILT_IN,
1431 NULL, NULL_TREE);
1433 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1434 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1435 type
1436 = build_function_type (objc_object_type,
1437 tree_cons (NULL_TREE, objc_super_type,
1438 tree_cons (NULL_TREE, objc_selector_type,
1439 NULL_TREE)));
1440 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1441 type, 0, NOT_BUILT_IN,
1442 NULL, NULL_TREE);
1443 umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1444 type, 0, NOT_BUILT_IN, 0,
1445 NULL_TREE);
1447 else
1449 /* GNU runtime messenger entry points. */
1451 /* typedef id (*IMP)(id, SEL, ...); */
1452 tree IMP_type
1453 = build_pointer_type
1454 (build_function_type (objc_object_type,
1455 tree_cons (NULL_TREE, objc_object_type,
1456 tree_cons (NULL_TREE, objc_selector_type,
1457 NULL_TREE))));
1459 /* IMP objc_msg_lookup (id, SEL); */
1460 type
1461 = build_function_type (IMP_type,
1462 tree_cons (NULL_TREE, objc_object_type,
1463 tree_cons (NULL_TREE, objc_selector_type,
1464 OBJC_VOID_AT_END)));
1465 umsg_decl = builtin_function (TAG_MSGSEND,
1466 type, 0, NOT_BUILT_IN,
1467 NULL, NULL_TREE);
1469 /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1470 type
1471 = build_function_type (IMP_type,
1472 tree_cons (NULL_TREE, objc_super_type,
1473 tree_cons (NULL_TREE, objc_selector_type,
1474 OBJC_VOID_AT_END)));
1475 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1476 type, 0, NOT_BUILT_IN,
1477 NULL, NULL_TREE);
1479 /* The following GNU runtime entry point is called to initialize
1480 each module:
1482 __objc_exec_class (void *); */
1483 type
1484 = build_function_type (void_type_node,
1485 tree_cons (NULL_TREE, ptr_type_node,
1486 OBJC_VOID_AT_END));
1487 execclass_decl = builtin_function (TAG_EXECCLASS,
1488 type, 0, NOT_BUILT_IN,
1489 NULL, NULL_TREE);
1492 /* id objc_getClass (const char *); */
1494 type = build_function_type (objc_object_type,
1495 tree_cons (NULL_TREE,
1496 const_string_type_node,
1497 OBJC_VOID_AT_END));
1499 objc_get_class_decl
1500 = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
1501 NULL, NULL_TREE);
1503 /* id objc_getMetaClass (const char *); */
1505 objc_get_meta_class_decl
1506 = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1508 build_class_template ();
1509 build_super_template ();
1510 build_protocol_template ();
1511 build_category_template ();
1512 build_objc_exception_stuff ();
1514 if (flag_next_runtime)
1515 build_next_objc_exception_stuff ();
1517 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1519 if (! flag_next_runtime)
1520 build_selector_table_decl ();
1522 /* Forward declare constant_string_id and constant_string_type. */
1523 if (!constant_string_class_name)
1524 constant_string_class_name = default_constant_string_class_name;
1526 constant_string_id = get_identifier (constant_string_class_name);
1527 objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1529 /* Pre-build the following entities - for speed/convenience. */
1530 self_id = get_identifier ("self");
1531 ucmd_id = get_identifier ("_cmd");
1532 #ifndef OBJCPLUS
1533 /* The C++ front-end does not appear to grok __attribute__((__unused__)). */
1534 unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1535 #endif
1537 #ifdef OBJCPLUS
1538 pop_lang_context ();
1539 #endif
1541 write_symbols = save_write_symbols;
1542 debug_hooks = save_hooks;
1545 /* Ensure that the ivar list for NSConstantString/NXConstantString
1546 (or whatever was specified via `-fconstant-string-class')
1547 contains fields at least as large as the following three, so that
1548 the runtime can stomp on them with confidence:
1550 struct STRING_OBJECT_CLASS_NAME
1552 Object isa;
1553 char *cString;
1554 unsigned int length;
1555 }; */
1557 static int
1558 check_string_class_template (void)
1560 tree field_decl = TYPE_FIELDS (constant_string_type);
1562 #define AT_LEAST_AS_LARGE_AS(F, T) \
1563 (F && TREE_CODE (F) == FIELD_DECL \
1564 && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1565 >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1567 if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1568 return 0;
1570 field_decl = TREE_CHAIN (field_decl);
1571 if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1572 return 0;
1574 field_decl = TREE_CHAIN (field_decl);
1575 return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1577 #undef AT_LEAST_AS_LARGE_AS
1580 /* Avoid calling `check_string_class_template ()' more than once. */
1581 static GTY(()) int string_layout_checked;
1583 /* Custom build_string which sets TREE_TYPE! */
1585 static tree
1586 my_build_string (int len, const char *str)
1588 return fix_string_type (build_string (len, str));
1592 static hashval_t
1593 string_hash (const void *ptr)
1595 tree str = ((struct string_descriptor *)ptr)->literal;
1596 const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
1597 int i, len = TREE_STRING_LENGTH (str);
1598 hashval_t h = len;
1600 for (i = 0; i < len; i++)
1601 h = ((h * 613) + p[i]);
1603 return h;
1606 static int
1607 string_eq (const void *ptr1, const void *ptr2)
1609 tree str1 = ((struct string_descriptor *)ptr1)->literal;
1610 tree str2 = ((struct string_descriptor *)ptr2)->literal;
1611 int len1 = TREE_STRING_LENGTH (str1);
1613 return (len1 == TREE_STRING_LENGTH (str2)
1614 && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
1615 len1));
1618 /* Given a chain of STRING_CST's, build a static instance of
1619 NXConstantString which points at the concatenation of those
1620 strings. We place the string object in the __string_objects
1621 section of the __OBJC segment. The Objective-C runtime will
1622 initialize the isa pointers of the string objects to point at the
1623 NXConstantString class object. */
1625 tree
1626 objc_build_string_object (tree string)
1628 tree initlist, constructor, constant_string_class;
1629 int length;
1630 tree fields, addr;
1631 struct string_descriptor *desc, key;
1632 void **loc;
1634 /* Prep the string argument. */
1635 string = fix_string_type (string);
1636 TREE_SET_CODE (string, STRING_CST);
1637 length = TREE_STRING_LENGTH (string) - 1;
1639 /* Check whether the string class being used actually exists and has the
1640 correct ivar layout. */
1641 if (!string_layout_checked)
1643 string_layout_checked = -1;
1644 constant_string_class = lookup_interface (constant_string_id);
1646 if (!constant_string_class
1647 || !(constant_string_type
1648 = CLASS_STATIC_TEMPLATE (constant_string_class)))
1649 error ("cannot find interface declaration for `%s'",
1650 IDENTIFIER_POINTER (constant_string_id));
1651 /* The NSConstantString/NXConstantString ivar layout is now known. */
1652 else if (!check_string_class_template ())
1653 error ("interface `%s' does not have valid constant string layout",
1654 IDENTIFIER_POINTER (constant_string_id));
1655 /* For the NeXT runtime, we can generate a literal reference
1656 to the string class, don't need to run a constructor. */
1657 else if (flag_next_runtime && !setup_string_decl ())
1658 error ("cannot find reference tag for class `%s'",
1659 IDENTIFIER_POINTER (constant_string_id));
1660 else
1662 string_layout_checked = 1; /* Success! */
1663 add_class_reference (constant_string_id);
1667 if (string_layout_checked == -1)
1668 return error_mark_node;
1670 /* Perhaps we already constructed a constant string just like this one? */
1671 key.literal = string;
1672 loc = htab_find_slot (string_htab, &key, INSERT);
1673 desc = *loc;
1675 if (!desc)
1677 tree var;
1678 *loc = desc = ggc_alloc (sizeof (*desc));
1679 desc->literal = string;
1681 /* GNU: & ((NXConstantString) { NULL, string, length }) */
1682 /* NeXT: & ((NSConstantString) { isa, string, length }) */
1683 fields = TYPE_FIELDS (constant_string_type);
1684 initlist
1685 = build_tree_list (fields,
1686 flag_next_runtime
1687 ? build_unary_op (ADDR_EXPR, string_class_decl, 0)
1688 : build_int_cst (NULL_TREE, 0));
1689 fields = TREE_CHAIN (fields);
1690 initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1),
1691 initlist);
1692 fields = TREE_CHAIN (fields);
1693 initlist = tree_cons (fields, build_int_cst (NULL_TREE, length),
1694 initlist);
1695 constructor = objc_build_constructor (constant_string_type,
1696 nreverse (initlist));
1697 TREE_INVARIANT (constructor) = true;
1699 if (!flag_next_runtime)
1700 constructor
1701 = objc_add_static_instance (constructor, constant_string_type);
1702 else
1704 var = build_decl (CONST_DECL, NULL, TREE_TYPE (constructor));
1705 DECL_INITIAL (var) = constructor;
1706 TREE_STATIC (var) = 1;
1707 pushdecl_top_level (var);
1708 constructor = var;
1710 desc->constructor = constructor;
1713 addr = build_unary_op (ADDR_EXPR, desc->constructor, 1);
1715 return addr;
1718 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1720 static GTY(()) int num_static_inst;
1722 static tree
1723 objc_add_static_instance (tree constructor, tree class_decl)
1725 tree *chain, decl;
1726 char buf[256];
1728 /* Find the list of static instances for the CLASS_DECL. Create one if
1729 not found. */
1730 for (chain = &objc_static_instances;
1731 *chain && TREE_VALUE (*chain) != class_decl;
1732 chain = &TREE_CHAIN (*chain));
1733 if (!*chain)
1735 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1736 add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1739 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1740 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1741 DECL_COMMON (decl) = 1;
1742 TREE_STATIC (decl) = 1;
1743 DECL_ARTIFICIAL (decl) = 1;
1744 DECL_INITIAL (decl) = constructor;
1746 /* We may be writing something else just now.
1747 Postpone till end of input. */
1748 DECL_DEFER_OUTPUT (decl) = 1;
1749 pushdecl_top_level (decl);
1750 rest_of_decl_compilation (decl, 1, 0);
1752 /* Add the DECL to the head of this CLASS' list. */
1753 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1755 return decl;
1758 /* Build a static constant CONSTRUCTOR
1759 with type TYPE and elements ELTS. */
1761 static tree
1762 objc_build_constructor (tree type, tree elts)
1764 tree constructor = build_constructor (type, elts);
1766 TREE_CONSTANT (constructor) = 1;
1767 TREE_STATIC (constructor) = 1;
1768 TREE_READONLY (constructor) = 1;
1770 #ifdef OBJCPLUS
1771 /* Adjust for impedance mismatch. We should figure out how to build
1772 CONSTRUCTORs that consistently please both the C and C++ gods. */
1773 if (!TREE_PURPOSE (elts))
1774 TREE_TYPE (constructor) = NULL_TREE;
1775 TREE_HAS_CONSTRUCTOR (constructor) = 1;
1776 #endif
1778 return constructor;
1781 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1783 /* Predefine the following data type:
1785 struct _objc_symtab
1787 long sel_ref_cnt;
1788 SEL *refs;
1789 short cls_def_cnt;
1790 short cat_def_cnt;
1791 void *defs[cls_def_cnt + cat_def_cnt];
1792 }; */
1794 static void
1795 build_objc_symtab_template (void)
1797 tree field_decl, field_decl_chain;
1799 objc_symtab_template
1800 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1802 /* long sel_ref_cnt; */
1803 field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt");
1804 field_decl_chain = field_decl;
1806 /* SEL *refs; */
1807 field_decl = create_field_decl (build_pointer_type (objc_selector_type),
1808 "refs");
1809 chainon (field_decl_chain, field_decl);
1811 /* short cls_def_cnt; */
1812 field_decl = create_field_decl (short_integer_type_node, "cls_def_cnt");
1813 chainon (field_decl_chain, field_decl);
1815 /* short cat_def_cnt; */
1816 field_decl = create_field_decl (short_integer_type_node,
1817 "cat_def_cnt");
1818 chainon (field_decl_chain, field_decl);
1820 if (imp_count || cat_count || !flag_next_runtime)
1822 /* void *defs[imp_count + cat_count (+ 1)]; */
1823 /* NB: The index is one less than the size of the array. */
1824 int index = imp_count + cat_count
1825 + (flag_next_runtime? -1: 0);
1826 field_decl = create_field_decl
1827 (build_array_type
1828 (ptr_type_node,
1829 build_index_type (build_int_cst (NULL_TREE, index))),
1830 "defs");
1831 chainon (field_decl_chain, field_decl);
1834 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1837 /* Create the initial value for the `defs' field of _objc_symtab.
1838 This is a CONSTRUCTOR. */
1840 static tree
1841 init_def_list (tree type)
1843 tree expr, initlist = NULL_TREE;
1844 struct imp_entry *impent;
1846 if (imp_count)
1847 for (impent = imp_list; impent; impent = impent->next)
1849 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1851 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1852 initlist = tree_cons (NULL_TREE, expr, initlist);
1856 if (cat_count)
1857 for (impent = imp_list; impent; impent = impent->next)
1859 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1861 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1862 initlist = tree_cons (NULL_TREE, expr, initlist);
1866 if (!flag_next_runtime)
1868 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1869 tree expr;
1871 if (static_instances_decl)
1872 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1873 else
1874 expr = build_int_cst (NULL_TREE, 0);
1876 initlist = tree_cons (NULL_TREE, expr, initlist);
1879 return objc_build_constructor (type, nreverse (initlist));
1882 /* Construct the initial value for all of _objc_symtab. */
1884 static tree
1885 init_objc_symtab (tree type)
1887 tree initlist;
1889 /* sel_ref_cnt = { ..., 5, ... } */
1891 initlist = build_tree_list (NULL_TREE,
1892 build_int_cst (long_integer_type_node, 0));
1894 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1896 if (flag_next_runtime || ! sel_ref_chain)
1897 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
1898 else
1899 initlist
1900 = tree_cons (NULL_TREE,
1901 convert (build_pointer_type (objc_selector_type),
1902 build_unary_op (ADDR_EXPR,
1903 UOBJC_SELECTOR_TABLE_decl, 1)),
1904 initlist);
1906 /* cls_def_cnt = { ..., 5, ... } */
1908 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
1910 /* cat_def_cnt = { ..., 5, ... } */
1912 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
1914 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1916 if (imp_count || cat_count || !flag_next_runtime)
1919 tree field = TYPE_FIELDS (type);
1920 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1922 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1923 initlist);
1926 return objc_build_constructor (type, nreverse (initlist));
1929 /* Generate forward declarations for metadata such as
1930 'OBJC_CLASS_...'. */
1932 static tree
1933 build_metadata_decl (const char *name, tree type)
1935 tree decl;
1937 /* struct TYPE NAME_<name>; */
1938 decl = start_var_decl (type, synth_id_with_class_suffix
1939 (name,
1940 objc_implementation_context));
1942 return decl;
1945 /* Push forward-declarations of all the categories so that
1946 init_def_list can use them in a CONSTRUCTOR. */
1948 static void
1949 forward_declare_categories (void)
1951 struct imp_entry *impent;
1952 tree sav = objc_implementation_context;
1954 for (impent = imp_list; impent; impent = impent->next)
1956 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1958 /* Set an invisible arg to synth_id_with_class_suffix. */
1959 objc_implementation_context = impent->imp_context;
1960 /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1961 impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1962 objc_category_template);
1965 objc_implementation_context = sav;
1968 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1969 and initialized appropriately. */
1971 static void
1972 generate_objc_symtab_decl (void)
1974 /* forward declare categories */
1975 if (cat_count)
1976 forward_declare_categories ();
1978 build_objc_symtab_template ();
1979 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
1980 finish_var_decl (UOBJC_SYMBOLS_decl,
1981 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
1984 static tree
1985 init_module_descriptor (tree type)
1987 tree initlist, expr;
1989 /* version = { 1, ... } */
1991 expr = build_int_cst (long_integer_type_node, OBJC_VERSION);
1992 initlist = build_tree_list (NULL_TREE, expr);
1994 /* size = { ..., sizeof (struct _objc_module), ... } */
1996 expr = convert (long_integer_type_node,
1997 size_in_bytes (objc_module_template));
1998 initlist = tree_cons (NULL_TREE, expr, initlist);
2000 /* name = { ..., "foo.m", ... } */
2002 expr = add_objc_string (get_identifier (input_filename), class_names);
2003 initlist = tree_cons (NULL_TREE, expr, initlist);
2005 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
2007 if (UOBJC_SYMBOLS_decl)
2008 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
2009 else
2010 expr = build_int_cst (NULL_TREE, 0);
2011 initlist = tree_cons (NULL_TREE, expr, initlist);
2013 return objc_build_constructor (type, nreverse (initlist));
2016 /* Write out the data structures to describe Objective C classes defined.
2018 struct _objc_module { ... } _OBJC_MODULE = { ... }; */
2020 static void
2021 build_module_descriptor (void)
2023 tree field_decl, field_decl_chain;
2025 #ifdef OBJCPLUS
2026 push_lang_context (lang_name_c); /* extern "C" */
2027 #endif
2029 objc_module_template
2030 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
2032 /* long version; */
2033 field_decl = create_field_decl (long_integer_type_node, "version");
2034 field_decl_chain = field_decl;
2036 /* long size; */
2037 field_decl = create_field_decl (long_integer_type_node, "size");
2038 chainon (field_decl_chain, field_decl);
2040 /* char *name; */
2041 field_decl = create_field_decl (string_type_node, "name");
2042 chainon (field_decl_chain, field_decl);
2044 /* struct _objc_symtab *symtab; */
2045 field_decl
2046 = create_field_decl (build_pointer_type
2047 (xref_tag (RECORD_TYPE,
2048 get_identifier (UTAG_SYMTAB))),
2049 "symtab");
2050 chainon (field_decl_chain, field_decl);
2052 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
2054 /* Create an instance of "_objc_module". */
2055 UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
2056 finish_var_decl (UOBJC_MODULES_decl,
2057 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
2059 #ifdef OBJCPLUS
2060 pop_lang_context ();
2061 #endif
2064 /* The GNU runtime requires us to provide a static initializer function
2065 for each module:
2067 static void __objc_gnu_init (void) {
2068 __objc_exec_class (&L_OBJC_MODULES);
2069 } */
2071 static void
2072 build_module_initializer_routine (void)
2074 tree body;
2076 #ifdef OBJCPLUS
2077 push_lang_context (lang_name_c); /* extern "C" */
2078 #endif
2080 objc_push_parm (build_decl (PARM_DECL, NULL_TREE, void_type_node));
2081 objc_start_function (get_identifier (TAG_GNUINIT),
2082 build_function_type (void_type_node,
2083 OBJC_VOID_AT_END),
2084 NULL_TREE, objc_get_parm_info (0));
2086 body = c_begin_compound_stmt (true);
2087 add_stmt (build_function_call
2088 (execclass_decl,
2089 build_tree_list
2090 (NULL_TREE,
2091 build_unary_op (ADDR_EXPR,
2092 UOBJC_MODULES_decl, 0))));
2093 add_stmt (c_end_compound_stmt (body, true));
2095 TREE_PUBLIC (current_function_decl) = 0;
2097 #ifndef OBJCPLUS
2098 /* For Objective-C++, we will need to call __objc_gnu_init
2099 from objc_generate_static_init_call() below. */
2100 DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
2101 #endif
2103 GNU_INIT_decl = current_function_decl;
2104 finish_function ();
2106 #ifdef OBJCPLUS
2107 pop_lang_context ();
2108 #endif
2111 #ifdef OBJCPLUS
2112 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
2113 to be called by the module initializer routine. */
2116 objc_static_init_needed_p (void)
2118 return (GNU_INIT_decl != NULL_TREE);
2121 /* Generate a call to the __objc_gnu_init initializer function. */
2123 tree
2124 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
2126 add_stmt (build_stmt (EXPR_STMT,
2127 build_function_call (GNU_INIT_decl, NULL_TREE)));
2129 return ctors;
2131 #endif /* OBJCPLUS */
2133 /* Return the DECL of the string IDENT in the SECTION. */
2135 static tree
2136 get_objc_string_decl (tree ident, enum string_section section)
2138 tree chain;
2140 if (section == class_names)
2141 chain = class_names_chain;
2142 else if (section == meth_var_names)
2143 chain = meth_var_names_chain;
2144 else if (section == meth_var_types)
2145 chain = meth_var_types_chain;
2146 else
2147 abort ();
2149 for (; chain != 0; chain = TREE_CHAIN (chain))
2150 if (TREE_VALUE (chain) == ident)
2151 return (TREE_PURPOSE (chain));
2153 abort ();
2154 return NULL_TREE;
2157 /* Output references to all statically allocated objects. Return the DECL
2158 for the array built. */
2160 static void
2161 generate_static_references (void)
2163 tree decls = NULL_TREE, expr = NULL_TREE;
2164 tree class_name, class, decl, initlist;
2165 tree cl_chain, in_chain, type
2166 = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
2167 int num_inst, num_class;
2168 char buf[256];
2170 if (flag_next_runtime)
2171 abort ();
2173 for (cl_chain = objc_static_instances, num_class = 0;
2174 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
2176 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
2177 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
2179 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
2180 decl = start_var_decl (type, buf);
2182 /* Output {class_name, ...}. */
2183 class = TREE_VALUE (cl_chain);
2184 class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
2185 initlist = build_tree_list (NULL_TREE,
2186 build_unary_op (ADDR_EXPR, class_name, 1));
2188 /* Output {..., instance, ...}. */
2189 for (in_chain = TREE_PURPOSE (cl_chain);
2190 in_chain; in_chain = TREE_CHAIN (in_chain))
2192 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
2193 initlist = tree_cons (NULL_TREE, expr, initlist);
2196 /* Output {..., NULL}. */
2197 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
2199 expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
2200 finish_var_decl (decl, expr);
2201 decls
2202 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2205 decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
2206 expr = objc_build_constructor (type, nreverse (decls));
2207 static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
2208 finish_var_decl (static_instances_decl, expr);
2211 /* Output all strings. */
2213 static void
2214 generate_strings (void)
2216 tree chain, string_expr;
2217 tree string, decl, type;
2219 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2221 string = TREE_VALUE (chain);
2222 decl = TREE_PURPOSE (chain);
2223 type = build_array_type
2224 (char_type_node,
2225 build_index_type
2226 (build_int_cst (NULL_TREE,
2227 IDENTIFIER_LENGTH (string))));
2228 decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2229 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2230 IDENTIFIER_POINTER (string));
2231 finish_var_decl (decl, string_expr);
2234 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2236 string = TREE_VALUE (chain);
2237 decl = TREE_PURPOSE (chain);
2238 type = build_array_type
2239 (char_type_node,
2240 build_index_type
2241 (build_int_cst (NULL_TREE,
2242 IDENTIFIER_LENGTH (string))));
2243 decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2244 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2245 IDENTIFIER_POINTER (string));
2246 finish_var_decl (decl, string_expr);
2249 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2251 string = TREE_VALUE (chain);
2252 decl = TREE_PURPOSE (chain);
2253 type = build_array_type
2254 (char_type_node,
2255 build_index_type
2256 (build_int_cst (NULL_TREE,
2257 IDENTIFIER_LENGTH (string))));
2258 decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl)));
2259 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2260 IDENTIFIER_POINTER (string));
2261 finish_var_decl (decl, string_expr);
2265 static GTY(()) int selector_reference_idx;
2267 static tree
2268 build_selector_reference_decl (void)
2270 tree decl;
2271 char buf[256];
2273 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
2274 decl = start_var_decl (objc_selector_type, buf);
2276 return decl;
2279 static void
2280 build_selector_table_decl (void)
2282 tree temp;
2284 if (flag_typed_selectors)
2286 build_selector_template ();
2287 temp = build_array_type (objc_selector_template, NULL_TREE);
2289 else
2290 temp = build_array_type (objc_selector_type, NULL_TREE);
2292 UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
2295 /* Just a handy wrapper for add_objc_string. */
2297 static tree
2298 build_selector (tree ident)
2300 return convert (objc_selector_type,
2301 add_objc_string (ident, meth_var_names));
2304 static void
2305 build_selector_translation_table (void)
2307 tree chain, initlist = NULL_TREE;
2308 int offset = 0;
2309 tree decl = NULL_TREE;
2311 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2313 tree expr;
2315 if (warn_selector && objc_implementation_context)
2317 tree method_chain;
2318 bool found = false;
2319 for (method_chain = meth_var_names_chain;
2320 method_chain;
2321 method_chain = TREE_CHAIN (method_chain))
2323 if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
2325 found = true;
2326 break;
2329 if (!found)
2330 warning ("%Jcreating selector for nonexistent method %qE",
2331 TREE_PURPOSE (chain), TREE_VALUE (chain));
2334 expr = build_selector (TREE_VALUE (chain));
2335 /* add one for the '\0' character */
2336 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2338 if (flag_next_runtime)
2340 decl = TREE_PURPOSE (chain);
2341 finish_var_decl (decl, expr);
2343 else
2345 if (flag_typed_selectors)
2347 tree eltlist = NULL_TREE;
2348 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2349 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2350 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2351 expr = objc_build_constructor (objc_selector_template,
2352 nreverse (eltlist));
2355 initlist = tree_cons (NULL_TREE, expr, initlist);
2359 if (! flag_next_runtime)
2361 /* Cause the selector table (previously forward-declared)
2362 to be actually output. */
2363 initlist = tree_cons (NULL_TREE,
2364 flag_typed_selectors
2365 ? objc_build_constructor
2366 (objc_selector_template,
2367 tree_cons (NULL_TREE,
2368 build_int_cst (NULL_TREE, 0),
2369 tree_cons (NULL_TREE,
2370 build_int_cst (NULL_TREE, 0),
2371 NULL_TREE)))
2372 : build_int_cst (NULL_TREE, 0), initlist);
2373 initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2374 nreverse (initlist));
2375 finish_var_decl (UOBJC_SELECTOR_TABLE_decl, initlist);
2379 static tree
2380 get_proto_encoding (tree proto)
2382 tree encoding;
2383 if (proto)
2385 if (! METHOD_ENCODING (proto))
2387 encoding = encode_method_prototype (proto);
2388 METHOD_ENCODING (proto) = encoding;
2390 else
2391 encoding = METHOD_ENCODING (proto);
2393 return add_objc_string (encoding, meth_var_types);
2395 else
2396 return build_int_cst (NULL_TREE, 0);
2399 /* sel_ref_chain is a list whose "value" fields will be instances of
2400 identifier_node that represent the selector. */
2402 static tree
2403 build_typed_selector_reference (tree ident, tree prototype)
2405 tree *chain = &sel_ref_chain;
2406 tree expr;
2407 int index = 0;
2409 while (*chain)
2411 if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
2412 goto return_at_index;
2414 index++;
2415 chain = &TREE_CHAIN (*chain);
2418 *chain = tree_cons (prototype, ident, NULL_TREE);
2420 return_at_index:
2421 expr = build_unary_op (ADDR_EXPR,
2422 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2423 build_int_cst (NULL_TREE, index)),
2425 return convert (objc_selector_type, expr);
2428 static tree
2429 build_selector_reference (tree ident)
2431 tree *chain = &sel_ref_chain;
2432 tree expr;
2433 int index = 0;
2435 while (*chain)
2437 if (TREE_VALUE (*chain) == ident)
2438 return (flag_next_runtime
2439 ? TREE_PURPOSE (*chain)
2440 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2441 build_int_cst (NULL_TREE, index)));
2443 index++;
2444 chain = &TREE_CHAIN (*chain);
2447 expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
2449 *chain = tree_cons (expr, ident, NULL_TREE);
2451 return (flag_next_runtime
2452 ? expr
2453 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2454 build_int_cst (NULL_TREE, index)));
2457 static GTY(()) int class_reference_idx;
2459 static tree
2460 build_class_reference_decl (void)
2462 tree decl;
2463 char buf[256];
2465 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
2466 decl = start_var_decl (objc_class_type, buf);
2468 return decl;
2471 /* Create a class reference, but don't create a variable to reference
2472 it. */
2474 static void
2475 add_class_reference (tree ident)
2477 tree chain;
2479 if ((chain = cls_ref_chain))
2481 tree tail;
2484 if (ident == TREE_VALUE (chain))
2485 return;
2487 tail = chain;
2488 chain = TREE_CHAIN (chain);
2490 while (chain);
2492 /* Append to the end of the list */
2493 TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2495 else
2496 cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2499 /* Get a class reference, creating it if necessary. Also create the
2500 reference variable. */
2502 tree
2503 objc_get_class_reference (tree ident)
2505 tree orig_ident;
2507 #ifdef OBJCPLUS
2508 if (processing_template_decl)
2509 /* Must wait until template instantiation time. */
2510 return build_min_nt (CLASS_REFERENCE_EXPR, ident);
2511 if (TREE_CODE (ident) == TYPE_DECL)
2512 ident = DECL_NAME (ident);
2513 #endif
2514 orig_ident = ident;
2516 if (!(ident = objc_is_class_name (ident)))
2518 error ("`%s' is not an Objective-C class name or alias",
2519 IDENTIFIER_POINTER (orig_ident));
2520 return error_mark_node;
2523 if (flag_next_runtime && !flag_zero_link)
2525 tree *chain;
2526 tree decl;
2528 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2529 if (TREE_VALUE (*chain) == ident)
2531 if (! TREE_PURPOSE (*chain))
2532 TREE_PURPOSE (*chain) = build_class_reference_decl ();
2534 return TREE_PURPOSE (*chain);
2537 decl = build_class_reference_decl ();
2538 *chain = tree_cons (decl, ident, NULL_TREE);
2539 return decl;
2541 else
2543 tree params;
2545 add_class_reference (ident);
2547 params = build_tree_list (NULL_TREE,
2548 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2549 IDENTIFIER_POINTER (ident)));
2551 assemble_external (objc_get_class_decl);
2552 return build_function_call (objc_get_class_decl, params);
2556 /* For each string section we have a chain which maps identifier nodes
2557 to decls for the strings. */
2559 static tree
2560 add_objc_string (tree ident, enum string_section section)
2562 tree *chain, decl;
2564 if (section == class_names)
2565 chain = &class_names_chain;
2566 else if (section == meth_var_names)
2567 chain = &meth_var_names_chain;
2568 else if (section == meth_var_types)
2569 chain = &meth_var_types_chain;
2570 else
2571 abort ();
2573 while (*chain)
2575 if (TREE_VALUE (*chain) == ident)
2576 return convert (string_type_node,
2577 build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1));
2579 chain = &TREE_CHAIN (*chain);
2582 decl = build_objc_string_decl (section);
2584 *chain = tree_cons (decl, ident, NULL_TREE);
2586 return convert (string_type_node, build_unary_op (ADDR_EXPR, decl, 1));
2589 static GTY(()) int class_names_idx;
2590 static GTY(()) int meth_var_names_idx;
2591 static GTY(()) int meth_var_types_idx;
2593 static tree
2594 build_objc_string_decl (enum string_section section)
2596 tree decl, ident;
2597 char buf[256];
2599 if (section == class_names)
2600 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2601 else if (section == meth_var_names)
2602 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2603 else if (section == meth_var_types)
2604 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2606 ident = get_identifier (buf);
2608 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2609 DECL_EXTERNAL (decl) = 1;
2610 TREE_PUBLIC (decl) = 0;
2611 TREE_USED (decl) = 1;
2612 TREE_CONSTANT (decl) = 1;
2613 DECL_CONTEXT (decl) = 0;
2614 DECL_ARTIFICIAL (decl) = 1;
2615 #ifdef OBJCPLUS
2616 DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */
2617 #endif
2619 make_decl_rtl (decl);
2620 pushdecl_top_level (decl);
2622 return decl;
2626 void
2627 objc_declare_alias (tree alias_ident, tree class_ident)
2629 tree underlying_class;
2631 #ifdef OBJCPLUS
2632 if (current_namespace != global_namespace) {
2633 error ("Objective-C declarations may only appear in global scope");
2635 #endif /* OBJCPLUS */
2637 if (!(underlying_class = objc_is_class_name (class_ident)))
2638 warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2639 else if (objc_is_class_name (alias_ident))
2640 warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2641 else
2642 alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
2645 void
2646 objc_declare_class (tree ident_list)
2648 tree list;
2649 #ifdef OBJCPLUS
2650 if (current_namespace != global_namespace) {
2651 error ("Objective-C declarations may only appear in global scope");
2653 #endif /* OBJCPLUS */
2655 for (list = ident_list; list; list = TREE_CHAIN (list))
2657 tree ident = TREE_VALUE (list);
2659 if (! objc_is_class_name (ident))
2661 tree record = lookup_name (ident);
2663 if (record && ! TREE_STATIC_TEMPLATE (record))
2665 error ("`%s' redeclared as different kind of symbol",
2666 IDENTIFIER_POINTER (ident));
2667 error ("%Jprevious declaration of '%D'",
2668 record, record);
2671 record = xref_tag (RECORD_TYPE, ident);
2672 TREE_STATIC_TEMPLATE (record) = 1;
2673 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2678 tree
2679 objc_is_class_name (tree ident)
2681 tree chain;
2683 if (ident && TREE_CODE (ident) == IDENTIFIER_NODE
2684 && identifier_global_value (ident))
2685 ident = identifier_global_value (ident);
2686 while (ident && TREE_CODE (ident) == TYPE_DECL && DECL_ORIGINAL_TYPE (ident))
2687 ident = OBJC_TYPE_NAME (DECL_ORIGINAL_TYPE (ident));
2689 if (ident && TREE_CODE (ident) == RECORD_TYPE)
2690 ident = OBJC_TYPE_NAME (ident);
2691 #ifdef OBJCPLUS
2692 if (ident && TREE_CODE (ident) == TYPE_DECL)
2693 ident = DECL_NAME (ident);
2694 #endif
2695 if (!ident || TREE_CODE (ident) != IDENTIFIER_NODE)
2696 return NULL_TREE;
2698 if (lookup_interface (ident))
2699 return ident;
2701 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2703 if (ident == TREE_VALUE (chain))
2704 return ident;
2707 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2709 if (ident == TREE_VALUE (chain))
2710 return TREE_PURPOSE (chain);
2713 return 0;
2716 /* Check whether TYPE is either 'id' or 'Class'. */
2718 tree
2719 objc_is_id (tree type)
2721 if (type && TREE_CODE (type) == IDENTIFIER_NODE
2722 && identifier_global_value (type))
2723 type = identifier_global_value (type);
2725 if (type && TREE_CODE (type) == TYPE_DECL)
2726 type = TREE_TYPE (type);
2728 /* NB: This function may be called before the ObjC front-end has
2729 been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL. */
2730 return (objc_object_type && type
2731 && (IS_ID (type) || IS_CLASS (type) || IS_SUPER (type))
2732 ? type
2733 : NULL_TREE);
2736 /* Check whether TYPE is either 'id', 'Class', or a pointer to an ObjC
2737 class instance. This is needed by other parts of the compiler to
2738 handle ObjC types gracefully. */
2740 tree
2741 objc_is_object_ptr (tree type)
2743 tree ret;
2745 type = TYPE_MAIN_VARIANT (type);
2746 if (!POINTER_TYPE_P (type))
2747 return 0;
2749 ret = objc_is_id (type);
2750 if (!ret)
2751 ret = objc_is_class_name (TREE_TYPE (type));
2753 return ret;
2756 static tree
2757 lookup_interface (tree ident)
2759 tree chain;
2761 #ifdef OBJCPLUS
2762 if (ident && TREE_CODE (ident) == TYPE_DECL)
2763 ident = DECL_NAME (ident);
2764 #endif
2765 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2767 if (ident == CLASS_NAME (chain))
2768 return chain;
2770 return NULL_TREE;
2773 /* Implement @defs (<classname>) within struct bodies. */
2775 tree
2776 objc_get_class_ivars (tree class_name)
2778 tree interface = lookup_interface (class_name);
2780 if (interface)
2781 return get_class_ivars (interface);
2783 error ("cannot find interface declaration for `%s'",
2784 IDENTIFIER_POINTER (class_name));
2786 return error_mark_node;
2789 /* Used by: build_private_template, continue_class,
2790 and for @defs constructs. */
2792 static tree
2793 get_class_ivars (tree interface)
2795 tree ivar_chain = copy_list (CLASS_RAW_IVARS (interface));
2797 /* Both CLASS_RAW_IVARS and CLASS_IVARS contain a list of ivars declared
2798 by the current class (i.e., they do not include super-class ivars).
2799 However, the CLASS_IVARS list will be side-effected by a call to
2800 finish_struct(), which will fill in field offsets. */
2801 if (!CLASS_IVARS (interface))
2802 CLASS_IVARS (interface) = ivar_chain;
2804 while (CLASS_SUPER_NAME (interface))
2806 /* Prepend super-class ivars. */
2807 interface = lookup_interface (CLASS_SUPER_NAME (interface));
2808 ivar_chain = chainon (copy_list (CLASS_RAW_IVARS (interface)),
2809 ivar_chain);
2812 return ivar_chain;
2815 static tree
2816 objc_create_temporary_var (tree type)
2818 tree decl;
2820 decl = build_decl (VAR_DECL, NULL_TREE, type);
2821 TREE_USED (decl) = 1;
2822 DECL_ARTIFICIAL (decl) = 1;
2823 DECL_IGNORED_P (decl) = 1;
2824 DECL_CONTEXT (decl) = current_function_decl;
2826 return decl;
2829 /* Exception handling constructs. We begin by having the parser do most
2830 of the work and passing us blocks. What we do next depends on whether
2831 we're doing "native" exception handling or legacy Darwin setjmp exceptions.
2832 We abstract all of this in a handful of appropriately named routines. */
2834 /* Stack of open try blocks. */
2836 struct objc_try_context
2838 struct objc_try_context *outer;
2840 /* Statements (or statement lists) as processed by the parser. */
2841 tree try_body;
2842 tree finally_body;
2844 /* Some file position locations. */
2845 location_t try_locus;
2846 location_t end_try_locus;
2847 location_t end_catch_locus;
2848 location_t finally_locus;
2849 location_t end_finally_locus;
2851 /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
2852 of a TRY_CATCH_EXPR. Even when doing Darwin setjmp. */
2853 tree catch_list;
2855 /* The CATCH_EXPR of an open @catch clause. */
2856 tree current_catch;
2858 /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR. */
2859 tree caught_decl;
2860 tree stack_decl;
2861 tree rethrow_decl;
2864 static struct objc_try_context *cur_try_context;
2866 /* This hook, called via lang_eh_runtime_type, generates a runtime object
2867 that represents TYPE. For Objective-C, this is just the class name. */
2868 /* ??? Isn't there a class object or some such? Is it easy to get? */
2870 #ifndef OBJCPLUS
2871 static tree
2872 objc_eh_runtime_type (tree type)
2874 return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
2876 #endif
2878 /* Initialize exception handling. */
2880 static void
2881 objc_init_exceptions (void)
2883 static bool done = false;
2884 if (done)
2885 return;
2886 done = true;
2888 if (flag_objc_sjlj_exceptions)
2890 /* On Darwin, ObjC exceptions require a sufficiently recent
2891 version of the runtime, so the user must ask for them explicitly. */
2892 if (!flag_objc_exceptions)
2893 warning ("use %<-fobjc-exceptions%> to enable Objective-C "
2894 "exception syntax");
2896 #ifndef OBJCPLUS
2897 else
2899 c_eh_initialized_p = true;
2900 eh_personality_libfunc
2901 = init_one_libfunc (USING_SJLJ_EXCEPTIONS
2902 ? "__gnu_objc_personality_sj0"
2903 : "__gnu_objc_personality_v0");
2904 using_eh_for_cleanups ();
2905 lang_eh_runtime_type = objc_eh_runtime_type;
2907 #endif
2910 /* Build an EXC_PTR_EXPR, or the moral equivalent. In the case of Darwin,
2911 we'll arrange for it to be initialized (and associated with a binding)
2912 later. */
2914 static tree
2915 objc_build_exc_ptr (void)
2917 if (flag_objc_sjlj_exceptions)
2919 tree var = cur_try_context->caught_decl;
2920 if (!var)
2922 var = objc_create_temporary_var (objc_object_type);
2923 cur_try_context->caught_decl = var;
2925 return var;
2927 else
2928 return build (EXC_PTR_EXPR, objc_object_type);
2931 /* Build "objc_exception_try_exit(&_stack)". */
2933 static tree
2934 next_sjlj_build_try_exit (void)
2936 tree t;
2937 t = build_fold_addr_expr (cur_try_context->stack_decl);
2938 t = tree_cons (NULL, t, NULL);
2939 t = build_function_call (objc_exception_try_exit_decl, t);
2940 return t;
2943 /* Build
2944 objc_exception_try_enter (&_stack);
2945 if (_setjmp(&_stack.buf))
2947 else
2949 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2950 empty, ready for the caller to fill them in. */
2952 static tree
2953 next_sjlj_build_enter_and_setjmp (void)
2955 tree t, enter, sj, cond;
2957 t = build_fold_addr_expr (cur_try_context->stack_decl);
2958 t = tree_cons (NULL, t, NULL);
2959 enter = build_function_call (objc_exception_try_enter_decl, t);
2961 t = build_component_ref (cur_try_context->stack_decl,
2962 get_identifier ("buf"));
2963 t = build_fold_addr_expr (t);
2964 t = convert (ptr_type_node, t);
2965 t = tree_cons (NULL, t, NULL);
2966 sj = build_function_call (objc_setjmp_decl, t);
2968 cond = build (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2969 cond = lang_hooks.truthvalue_conversion (cond);
2971 return build (COND_EXPR, void_type_node, cond, NULL, NULL);
2974 /* Build
2975 DECL = objc_exception_extract(&_stack);
2978 static tree
2979 next_sjlj_build_exc_extract (tree decl)
2981 tree t;
2983 t = build_fold_addr_expr (cur_try_context->stack_decl);
2984 t = tree_cons (NULL, t, NULL);
2985 t = build_function_call (objc_exception_extract_decl, t);
2986 t = convert (TREE_TYPE (decl), t);
2987 t = build (MODIFY_EXPR, void_type_node, decl, t);
2989 return t;
2992 /* Build
2993 if (objc_exception_match(obj_get_class(TYPE), _caught)
2994 BODY
2995 else if (...)
2997 else
2999 _rethrow = _caught;
3000 objc_exception_try_exit(&_stack);
3002 from the sequence of CATCH_EXPRs in the current try context. */
3004 static tree
3005 next_sjlj_build_catch_list (void)
3007 tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3008 tree catch_seq, t;
3009 tree *last = &catch_seq;
3010 bool saw_id = false;
3012 for (; !tsi_end_p (i); tsi_next (&i))
3014 tree stmt = tsi_stmt (i);
3015 tree type = CATCH_TYPES (stmt);
3016 tree body = CATCH_BODY (stmt);
3018 if (type == NULL)
3020 *last = body;
3021 saw_id = true;
3022 break;
3024 else
3026 tree args, cond;
3028 if (type == error_mark_node)
3029 cond = error_mark_node;
3030 else
3032 args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
3033 t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
3034 args = tree_cons (NULL, t, args);
3035 t = build_function_call (objc_exception_match_decl, args);
3036 cond = lang_hooks.truthvalue_conversion (t);
3038 t = build (COND_EXPR, void_type_node, cond, body, NULL);
3039 SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
3041 *last = t;
3042 last = &COND_EXPR_ELSE (t);
3046 if (!saw_id)
3048 t = build (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
3049 cur_try_context->caught_decl);
3050 SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3051 append_to_statement_list (t, last);
3053 t = next_sjlj_build_try_exit ();
3054 SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
3055 append_to_statement_list (t, last);
3058 return catch_seq;
3061 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
3062 exception handling. We aim to build:
3065 struct _objc_exception_data _stack;
3066 id volatile _rethrow = 0;
3069 objc_exception_try_enter (&_stack);
3070 if (_setjmp(&_stack.buf))
3072 id _caught = objc_exception_extract(&_stack);
3073 objc_exception_try_enter (&_stack);
3074 if (_setjmp(&_stack.buf))
3075 _rethrow = objc_exception_extract(&_stack);
3076 else
3077 CATCH-LIST
3079 else
3080 TRY-BLOCK
3082 finally
3084 if (!_rethrow)
3085 objc_exception_try_exit(&_stack);
3086 FINALLY-BLOCK
3087 if (_rethrow)
3088 objc_exception_throw(_rethrow);
3092 If CATCH-LIST is empty, we can omit all of the block containing
3093 "_caught" except for the setting of _rethrow. Note the use of
3094 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
3095 but handles goto and other exits from the block. */
3097 static tree
3098 next_sjlj_build_try_catch_finally (void)
3100 tree rethrow_decl, stack_decl, t;
3101 tree catch_seq, try_fin, bind;
3103 /* Create the declarations involved. */
3104 t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3105 stack_decl = objc_create_temporary_var (t);
3106 cur_try_context->stack_decl = stack_decl;
3108 rethrow_decl = objc_create_temporary_var (objc_object_type);
3109 cur_try_context->rethrow_decl = rethrow_decl;
3110 TREE_THIS_VOLATILE (rethrow_decl) = 1;
3111 TREE_CHAIN (rethrow_decl) = stack_decl;
3113 /* Build the outermost variable binding level. */
3114 bind = build (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
3115 SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
3116 TREE_SIDE_EFFECTS (bind) = 1;
3118 /* Initialize rethrow_decl. */
3119 t = build (MODIFY_EXPR, void_type_node, rethrow_decl,
3120 convert (objc_object_type, null_pointer_node));
3121 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3122 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3124 /* Build the outermost TRY_FINALLY_EXPR. */
3125 try_fin = build (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
3126 SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
3127 TREE_SIDE_EFFECTS (try_fin) = 1;
3128 append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
3130 /* Create the complete catch sequence. */
3131 if (cur_try_context->catch_list)
3133 tree caught_decl = objc_build_exc_ptr ();
3134 catch_seq = build_stmt (BIND_EXPR, caught_decl, NULL, NULL);
3136 t = next_sjlj_build_exc_extract (caught_decl);
3137 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3139 t = next_sjlj_build_enter_and_setjmp ();
3140 COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
3141 COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
3142 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
3144 else
3145 catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
3146 SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
3148 /* Build the main register-and-try if statement. */
3149 t = next_sjlj_build_enter_and_setjmp ();
3150 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
3151 COND_EXPR_THEN (t) = catch_seq;
3152 COND_EXPR_ELSE (t) = cur_try_context->try_body;
3153 TREE_OPERAND (try_fin, 0) = t;
3155 /* Build the complete FINALLY statement list. */
3156 t = next_sjlj_build_try_exit ();
3157 t = build_stmt (COND_EXPR,
3158 lang_hooks.truthvalue_conversion (rethrow_decl),
3159 NULL, t);
3160 SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
3161 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3163 append_to_statement_list (cur_try_context->finally_body,
3164 &TREE_OPERAND (try_fin, 1));
3166 t = tree_cons (NULL, rethrow_decl, NULL);
3167 t = build_function_call (objc_exception_throw_decl, t);
3168 t = build_stmt (COND_EXPR,
3169 lang_hooks.truthvalue_conversion (rethrow_decl),
3170 t, NULL);
3171 SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
3172 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
3174 return bind;
3177 /* Called just after parsing the @try and its associated BODY. We now
3178 must prepare for the tricky bits -- handling the catches and finally. */
3180 void
3181 objc_begin_try_stmt (location_t try_locus, tree body)
3183 struct objc_try_context *c = xcalloc (1, sizeof (*c));
3184 c->outer = cur_try_context;
3185 c->try_body = body;
3186 c->try_locus = try_locus;
3187 c->end_try_locus = input_location;
3188 cur_try_context = c;
3190 objc_init_exceptions ();
3193 /* Called just after parsing "@catch (parm)". Open a binding level,
3194 enter DECL into the binding level, and initialize it. Leave the
3195 binding level open while the body of the compound statement is parsed. */
3197 void
3198 objc_begin_catch_clause (tree decl)
3200 tree compound, type, t;
3202 /* Begin a new scope that the entire catch clause will live in. */
3203 compound = c_begin_compound_stmt (true);
3205 /* The parser passed in a PARM_DECL, but what we really want is a VAR_DECL. */
3206 decl = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
3207 lang_hooks.decls.pushdecl (decl);
3209 /* Since a decl is required here by syntax, don't warn if its unused. */
3210 /* ??? As opposed to __attribute__((unused))? Anyway, this appears to
3211 be what the previous objc implementation did. */
3212 TREE_USED (decl) = 1;
3214 /* Verify that the type of the catch is valid. It must be a pointer
3215 to an Objective-C class, or "id" (which is catch-all). */
3216 type = TREE_TYPE (decl);
3218 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3219 type = NULL;
3220 else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3222 error ("@catch parameter is not a known Objective-C class type");
3223 type = error_mark_node;
3225 else if (cur_try_context->catch_list)
3227 /* Examine previous @catch clauses and see if we've already
3228 caught the type in question. */
3229 tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
3230 for (; !tsi_end_p (i); tsi_next (&i))
3232 tree stmt = tsi_stmt (i);
3233 t = CATCH_TYPES (stmt);
3234 if (t == error_mark_node)
3235 continue;
3236 if (!t || objc_comptypes (TREE_TYPE (t), TREE_TYPE (type), 0) == 1)
3238 warning ("exception of type %<%T%> will be caught",
3239 TREE_TYPE (type));
3240 warning ("%H by earlier handler for %<%T%>",
3241 EXPR_LOCUS (stmt), TREE_TYPE (t ? t : objc_object_type));
3242 break;
3247 /* Record the data for the catch in the try context so that we can
3248 finalize it later. */
3249 t = build_stmt (CATCH_EXPR, type, compound);
3250 cur_try_context->current_catch = t;
3252 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3253 t = objc_build_exc_ptr ();
3254 t = convert (TREE_TYPE (decl), t);
3255 t = build (MODIFY_EXPR, void_type_node, decl, t);
3256 add_stmt (t);
3259 /* Called just after parsing the closing brace of a @catch clause. Close
3260 the open binding level, and record a CATCH_EXPR for it. */
3262 void
3263 objc_finish_catch_clause (void)
3265 tree c = cur_try_context->current_catch;
3266 cur_try_context->current_catch = NULL;
3267 cur_try_context->end_catch_locus = input_location;
3269 CATCH_BODY (c) = c_end_compound_stmt (CATCH_BODY (c), 1);
3270 append_to_statement_list (c, &cur_try_context->catch_list);
3273 /* Called after parsing a @finally clause and its associated BODY.
3274 Record the body for later placement. */
3276 void
3277 objc_build_finally_clause (location_t finally_locus, tree body)
3279 cur_try_context->finally_body = body;
3280 cur_try_context->finally_locus = finally_locus;
3281 cur_try_context->end_finally_locus = input_location;
3284 /* Called to finalize a @try construct. */
3286 void
3287 objc_finish_try_stmt (void)
3289 struct objc_try_context *c = cur_try_context;
3290 tree stmt;
3292 if (c->catch_list == NULL && c->finally_body == NULL)
3293 error ("`@try' without `@catch' or `@finally'");
3295 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
3296 if (flag_objc_sjlj_exceptions)
3298 if (!cur_try_context->finally_body)
3300 cur_try_context->finally_locus = input_location;
3301 cur_try_context->end_finally_locus = input_location;
3303 stmt = next_sjlj_build_try_catch_finally ();
3305 else
3307 /* Otherwise, nest the CATCH inside a FINALLY. */
3308 stmt = c->try_body;
3309 if (c->catch_list)
3311 stmt = build_stmt (TRY_CATCH_EXPR, stmt, c->catch_list);
3312 SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3314 if (c->finally_body)
3316 stmt = build_stmt (TRY_FINALLY_EXPR, stmt, c->finally_body);
3317 SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
3320 add_stmt (stmt);
3322 cur_try_context = c->outer;
3323 free (c);
3326 tree
3327 objc_build_throw_stmt (tree throw_expr)
3329 tree args;
3331 objc_init_exceptions ();
3333 if (throw_expr == NULL)
3335 /* If we're not inside a @catch block, there is no "current
3336 exception" to be rethrown. */
3337 if (cur_try_context == NULL
3338 || cur_try_context->current_catch == NULL)
3340 error ("%<@throw%> (rethrow) used outside of a @catch block");
3341 return NULL_TREE;
3344 /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3345 value that we get from the runtime. */
3346 throw_expr = objc_build_exc_ptr ();
3349 /* A throw is just a call to the runtime throw function with the
3350 object as a parameter. */
3351 args = tree_cons (NULL, throw_expr, NULL);
3352 return add_stmt (build_function_call (objc_exception_throw_decl, args));
3355 void
3356 objc_build_synchronized (location_t start_locus, tree mutex, tree body)
3358 tree args, call;
3360 /* First lock the mutex. */
3361 mutex = save_expr (mutex);
3362 args = tree_cons (NULL, mutex, NULL);
3363 call = build_function_call (objc_sync_enter_decl, args);
3364 SET_EXPR_LOCATION (call, start_locus);
3365 add_stmt (call);
3367 /* Build the mutex unlock. */
3368 args = tree_cons (NULL, mutex, NULL);
3369 call = build_function_call (objc_sync_exit_decl, args);
3370 SET_EXPR_LOCATION (call, input_location);
3372 /* Put the that and the body in a TRY_FINALLY. */
3373 objc_begin_try_stmt (start_locus, body);
3374 objc_build_finally_clause (input_location, call);
3375 objc_finish_try_stmt ();
3379 /* Predefine the following data type:
3381 struct _objc_exception_data
3383 int buf[_JBLEN];
3384 void *pointers[4];
3385 }; */
3387 /* The following yuckiness should prevent users from having to #include
3388 <setjmp.h> in their code... */
3390 #ifdef TARGET_POWERPC
3391 /* snarfed from /usr/include/ppc/setjmp.h */
3392 #define _JBLEN (26 + 36 + 129 + 1)
3393 #else
3394 /* snarfed from /usr/include/i386/{setjmp,signal}.h */
3395 #define _JBLEN 18
3396 #endif
3398 static void
3399 build_next_objc_exception_stuff (void)
3401 tree field_decl, field_decl_chain, index, temp_type;
3403 objc_exception_data_template
3404 = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
3406 /* int buf[_JBLEN]; */
3408 index = build_index_type (build_int_cst (NULL_TREE, _JBLEN - 1));
3409 field_decl = create_field_decl (build_array_type (integer_type_node, index),
3410 "buf");
3411 field_decl_chain = field_decl;
3413 /* void *pointers[4]; */
3415 index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
3416 field_decl = create_field_decl (build_array_type (ptr_type_node, index),
3417 "pointers");
3418 chainon (field_decl_chain, field_decl);
3420 finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
3422 /* int _setjmp(...); */
3423 /* If the user includes <setjmp.h>, this shall be superseded by
3424 'int _setjmp(jmp_buf);' */
3425 temp_type = build_function_type (integer_type_node, NULL_TREE);
3426 objc_setjmp_decl
3427 = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3429 /* id objc_exception_extract(struct _objc_exception_data *); */
3430 temp_type
3431 = build_function_type (objc_object_type,
3432 tree_cons (NULL_TREE,
3433 build_pointer_type (objc_exception_data_template),
3434 OBJC_VOID_AT_END));
3435 objc_exception_extract_decl
3436 = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3437 /* void objc_exception_try_enter(struct _objc_exception_data *); */
3438 /* void objc_exception_try_exit(struct _objc_exception_data *); */
3439 temp_type
3440 = build_function_type (void_type_node,
3441 tree_cons (NULL_TREE,
3442 build_pointer_type (objc_exception_data_template),
3443 OBJC_VOID_AT_END));
3444 objc_exception_try_enter_decl
3445 = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3446 objc_exception_try_exit_decl
3447 = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3449 /* int objc_exception_match(id, id); */
3450 temp_type
3451 = build_function_type (integer_type_node,
3452 tree_cons (NULL_TREE, objc_object_type,
3453 tree_cons (NULL_TREE, objc_object_type,
3454 OBJC_VOID_AT_END)));
3455 objc_exception_match_decl
3456 = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3459 static void
3460 build_objc_exception_stuff (void)
3462 tree noreturn_list, nothrow_list, temp_type;
3464 noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
3465 nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
3467 /* void objc_exception_throw(id) __attribute__((noreturn)); */
3468 /* void objc_sync_enter(id); */
3469 /* void objc_sync_exit(id); */
3470 temp_type = build_function_type (void_type_node,
3471 tree_cons (NULL_TREE, objc_object_type,
3472 OBJC_VOID_AT_END));
3473 objc_exception_throw_decl
3474 = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
3475 noreturn_list);
3476 objc_sync_enter_decl
3477 = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
3478 NULL, nothrow_list);
3479 objc_sync_exit_decl
3480 = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
3481 NULL, nothrow_list);
3485 /* struct <classname> {
3486 struct _objc_class *isa;
3488 }; */
3490 static tree
3491 build_private_template (tree class)
3493 tree ivar_context;
3495 if (CLASS_STATIC_TEMPLATE (class))
3497 uprivate_record = CLASS_STATIC_TEMPLATE (class);
3498 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3500 else
3502 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3503 ivar_context = get_class_ivars (class);
3505 finish_struct (uprivate_record, ivar_context, NULL_TREE);
3507 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3509 /* mark this record as class template - for class type checking */
3510 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3513 objc_instance_type = build_pointer_type (uprivate_record);
3515 return ivar_context;
3518 /* Begin code generation for protocols... */
3520 /* struct _objc_protocol {
3521 struct _objc_class *isa;
3522 char *protocol_name;
3523 struct _objc_protocol **protocol_list;
3524 struct _objc__method_prototype_list *instance_methods;
3525 struct _objc__method_prototype_list *class_methods;
3526 }; */
3528 static void
3529 build_protocol_template (void)
3531 tree field_decl, field_decl_chain;
3533 objc_protocol_template = start_struct (RECORD_TYPE,
3534 get_identifier (UTAG_PROTOCOL));
3536 /* struct _objc_class *isa; */
3537 field_decl = create_field_decl (build_pointer_type
3538 (xref_tag (RECORD_TYPE,
3539 get_identifier (UTAG_CLASS))),
3540 "isa");
3541 field_decl_chain = field_decl;
3543 /* char *protocol_name; */
3544 field_decl = create_field_decl (string_type_node, "protocol_name");
3545 chainon (field_decl_chain, field_decl);
3547 /* struct _objc_protocol **protocol_list; */
3548 field_decl = create_field_decl (build_pointer_type
3549 (build_pointer_type
3550 (objc_protocol_template)),
3551 "protocol_list");
3552 chainon (field_decl_chain, field_decl);
3554 /* struct objc_method_list *instance_methods; */
3555 field_decl = create_field_decl (build_pointer_type
3556 (xref_tag (RECORD_TYPE,
3557 get_identifier
3558 (UTAG_METHOD_PROTOTYPE_LIST))),
3559 "instance_methods");
3560 chainon (field_decl_chain, field_decl);
3562 /* struct objc_method_list *class_methods; */
3563 field_decl = create_field_decl (build_pointer_type
3564 (xref_tag (RECORD_TYPE,
3565 get_identifier
3566 (UTAG_METHOD_PROTOTYPE_LIST))),
3567 "class_methods");
3568 chainon (field_decl_chain, field_decl);
3570 finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
3573 static tree
3574 build_descriptor_table_initializer (tree type, tree entries)
3576 tree initlist = NULL_TREE;
3580 tree eltlist = NULL_TREE;
3582 eltlist
3583 = tree_cons (NULL_TREE,
3584 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3585 eltlist
3586 = tree_cons (NULL_TREE,
3587 add_objc_string (METHOD_ENCODING (entries),
3588 meth_var_types),
3589 eltlist);
3591 initlist
3592 = tree_cons (NULL_TREE,
3593 objc_build_constructor (type, nreverse (eltlist)),
3594 initlist);
3596 entries = TREE_CHAIN (entries);
3598 while (entries);
3600 return objc_build_constructor (build_array_type (type, 0),
3601 nreverse (initlist));
3604 /* struct objc_method_prototype_list {
3605 int count;
3606 struct objc_method_prototype {
3607 SEL name;
3608 char *types;
3609 } list[1];
3610 }; */
3612 static tree
3613 build_method_prototype_list_template (tree list_type, int size)
3615 tree objc_ivar_list_record;
3616 tree field_decl, field_decl_chain;
3618 /* Generate an unnamed struct definition. */
3620 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3622 /* int method_count; */
3623 field_decl = create_field_decl (integer_type_node, "method_count");
3624 field_decl_chain = field_decl;
3626 /* struct objc_method method_list[]; */
3627 field_decl = create_field_decl (build_array_type
3628 (list_type,
3629 build_index_type
3630 (build_int_cst (NULL_TREE, size - 1))),
3631 "method_list");
3632 chainon (field_decl_chain, field_decl);
3634 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3636 return objc_ivar_list_record;
3639 static tree
3640 build_method_prototype_template (void)
3642 tree proto_record;
3643 tree field_decl, field_decl_chain;
3645 proto_record
3646 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
3648 /* SEL _cmd; */
3649 field_decl = create_field_decl (objc_selector_type, "_cmd");
3650 field_decl_chain = field_decl;
3652 /* char *method_types; */
3653 field_decl = create_field_decl (string_type_node, "method_types");
3654 chainon (field_decl_chain, field_decl);
3656 finish_struct (proto_record, field_decl_chain, NULL_TREE);
3658 return proto_record;
3661 static tree
3662 objc_method_parm_type (tree type)
3664 type = TREE_VALUE (TREE_TYPE (type));
3665 if (TREE_CODE (type) == TYPE_DECL)
3666 type = TREE_TYPE (type);
3667 return TYPE_MAIN_VARIANT (type);
3670 static int
3671 objc_encoded_type_size (tree type)
3673 int sz = int_size_in_bytes (type);
3675 /* Make all integer and enum types at least as large
3676 as an int. */
3677 if (sz > 0 && INTEGRAL_TYPE_P (type))
3678 sz = MAX (sz, int_size_in_bytes (integer_type_node));
3679 /* Treat arrays as pointers, since that's how they're
3680 passed in. */
3681 else if (TREE_CODE (type) == ARRAY_TYPE)
3682 sz = int_size_in_bytes (ptr_type_node);
3683 return sz;
3686 static tree
3687 encode_method_prototype (tree method_decl)
3689 tree parms;
3690 int parm_offset, i;
3691 char buf[40];
3692 tree result;
3694 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
3695 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
3697 /* Encode return type. */
3698 encode_type (objc_method_parm_type (method_decl),
3699 obstack_object_size (&util_obstack),
3700 OBJC_ENCODE_INLINE_DEFS);
3702 /* Stack size. */
3703 /* The first two arguments (self and _cmd) are pointers; account for
3704 their size. */
3705 i = int_size_in_bytes (ptr_type_node);
3706 parm_offset = 2 * i;
3707 for (parms = METHOD_SEL_ARGS (method_decl); parms;
3708 parms = TREE_CHAIN (parms))
3710 tree type = objc_method_parm_type (parms);
3711 int sz = objc_encoded_type_size (type);
3713 /* If a type size is not known, bail out. */
3714 if (sz < 0)
3716 error ("%Jtype '%D' does not have a known size",
3717 type, type);
3718 /* Pretend that the encoding succeeded; the compilation will
3719 fail nevertheless. */
3720 goto finish_encoding;
3722 parm_offset += sz;
3725 sprintf (buf, "%d@0:%d", parm_offset, i);
3726 obstack_grow (&util_obstack, buf, strlen (buf));
3728 /* Argument types. */
3729 parm_offset = 2 * i;
3730 for (parms = METHOD_SEL_ARGS (method_decl); parms;
3731 parms = TREE_CHAIN (parms))
3733 tree type = objc_method_parm_type (parms);
3735 /* Process argument qualifiers for user supplied arguments. */
3736 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
3738 /* Type. */
3739 encode_type (type, obstack_object_size (&util_obstack),
3740 OBJC_ENCODE_INLINE_DEFS);
3742 /* Compute offset. */
3743 sprintf (buf, "%d", parm_offset);
3744 parm_offset += objc_encoded_type_size (type);
3746 obstack_grow (&util_obstack, buf, strlen (buf));
3749 finish_encoding:
3750 obstack_1grow (&util_obstack, '\0');
3751 result = get_identifier (obstack_finish (&util_obstack));
3752 obstack_free (&util_obstack, util_firstobj);
3753 return result;
3756 static tree
3757 generate_descriptor_table (tree type, const char *name, int size, tree list,
3758 tree proto)
3760 tree decl, initlist;
3762 decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
3764 initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
3765 initlist = tree_cons (NULL_TREE, list, initlist);
3767 finish_var_decl (decl, objc_build_constructor (type, nreverse (initlist)));
3769 return decl;
3772 static void
3773 generate_method_descriptors (tree protocol)
3775 tree initlist, chain, method_list_template;
3776 tree variable_length_type
3777 = xref_tag (RECORD_TYPE,
3778 get_identifier (UTAG_METHOD_PROTOTYPE_LIST));
3779 int size;
3781 if (!objc_method_prototype_template)
3782 objc_method_prototype_template = build_method_prototype_template ();
3784 chain = PROTOCOL_CLS_METHODS (protocol);
3785 if (chain)
3787 size = list_length (chain);
3789 method_list_template
3790 = build_method_prototype_list_template (objc_method_prototype_template,
3791 size);
3793 initlist
3794 = build_descriptor_table_initializer (objc_method_prototype_template,
3795 chain);
3797 UOBJC_CLASS_METHODS_decl
3798 = generate_descriptor_table (method_list_template,
3799 "_OBJC_PROTOCOL_CLASS_METHODS",
3800 size, initlist, protocol);
3801 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3803 else
3804 UOBJC_CLASS_METHODS_decl = 0;
3806 chain = PROTOCOL_NST_METHODS (protocol);
3807 if (chain)
3809 size = list_length (chain);
3811 method_list_template
3812 = build_method_prototype_list_template (objc_method_prototype_template,
3813 size);
3814 initlist
3815 = build_descriptor_table_initializer (objc_method_prototype_template,
3816 chain);
3818 UOBJC_INSTANCE_METHODS_decl
3819 = generate_descriptor_table (method_list_template,
3820 "_OBJC_PROTOCOL_INSTANCE_METHODS",
3821 size, initlist, protocol);
3822 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3824 else
3825 UOBJC_INSTANCE_METHODS_decl = 0;
3828 static void
3829 generate_protocol_references (tree plist)
3831 tree lproto;
3833 /* Forward declare protocols referenced. */
3834 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3836 tree proto = TREE_VALUE (lproto);
3838 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3839 && PROTOCOL_NAME (proto))
3841 if (! PROTOCOL_FORWARD_DECL (proto))
3842 build_protocol_reference (proto);
3844 if (PROTOCOL_LIST (proto))
3845 generate_protocol_references (PROTOCOL_LIST (proto));
3850 /* For each protocol which was referenced either from a @protocol()
3851 expression, or because a class/category implements it (then a
3852 pointer to the protocol is stored in the struct describing the
3853 class/category), we create a statically allocated instance of the
3854 Protocol class. The code is written in such a way as to generate
3855 as few Protocol objects as possible; we generate a unique Protocol
3856 instance for each protocol, and we don't generate a Protocol
3857 instance if the protocol is never referenced (either from a
3858 @protocol() or from a class/category implementation). These
3859 statically allocated objects can be referred to via the static
3860 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
3862 The statically allocated Protocol objects that we generate here
3863 need to be fixed up at runtime in order to be used: the 'isa'
3864 pointer of the objects need to be set up to point to the 'Protocol'
3865 class, as known at runtime.
3867 The NeXT runtime fixes up all protocols at program startup time,
3868 before main() is entered. It uses a low-level trick to look up all
3869 those symbols, then loops on them and fixes them up.
3871 The GNU runtime as well fixes up all protocols before user code
3872 from the module is executed; it requires pointers to those symbols
3873 to be put in the objc_symtab (which is then passed as argument to
3874 the function __objc_exec_class() which the compiler sets up to be
3875 executed automatically when the module is loaded); setup of those
3876 Protocol objects happen in two ways in the GNU runtime: all
3877 Protocol objects referred to by a class or category implementation
3878 are fixed up when the class/category is loaded; all Protocol
3879 objects referred to by a @protocol() expression are added by the
3880 compiler to the list of statically allocated instances to fixup
3881 (the same list holding the statically allocated constant string
3882 objects). Because, as explained above, the compiler generates as
3883 few Protocol objects as possible, some Protocol object might end up
3884 being referenced multiple times when compiled with the GNU runtime,
3885 and end up being fixed up multiple times at runtime initialization.
3886 But that doesn't hurt, it's just a little inefficient. */
3888 static void
3889 generate_protocols (void)
3891 tree p, encoding;
3892 tree decl;
3893 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3895 /* If a protocol was directly referenced, pull in indirect references. */
3896 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3897 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3898 generate_protocol_references (PROTOCOL_LIST (p));
3900 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3902 tree nst_methods = PROTOCOL_NST_METHODS (p);
3903 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3905 /* If protocol wasn't referenced, don't generate any code. */
3906 decl = PROTOCOL_FORWARD_DECL (p);
3908 if (!decl)
3909 continue;
3911 /* Make sure we link in the Protocol class. */
3912 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3914 while (nst_methods)
3916 if (! METHOD_ENCODING (nst_methods))
3918 encoding = encode_method_prototype (nst_methods);
3919 METHOD_ENCODING (nst_methods) = encoding;
3921 nst_methods = TREE_CHAIN (nst_methods);
3924 while (cls_methods)
3926 if (! METHOD_ENCODING (cls_methods))
3928 encoding = encode_method_prototype (cls_methods);
3929 METHOD_ENCODING (cls_methods) = encoding;
3932 cls_methods = TREE_CHAIN (cls_methods);
3934 generate_method_descriptors (p);
3936 if (PROTOCOL_LIST (p))
3937 refs_decl = generate_protocol_list (p);
3938 else
3939 refs_decl = 0;
3941 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3942 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3944 if (refs_decl)
3945 refs_expr = convert (build_pointer_type (build_pointer_type
3946 (objc_protocol_template)),
3947 build_unary_op (ADDR_EXPR, refs_decl, 0));
3948 else
3949 refs_expr = build_int_cst (NULL_TREE, 0);
3951 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3952 by generate_method_descriptors, which is called above. */
3953 initlist = build_protocol_initializer (TREE_TYPE (decl),
3954 protocol_name_expr, refs_expr,
3955 UOBJC_INSTANCE_METHODS_decl,
3956 UOBJC_CLASS_METHODS_decl);
3957 finish_var_decl (decl, initlist);
3961 static tree
3962 build_protocol_initializer (tree type, tree protocol_name,
3963 tree protocol_list, tree instance_methods,
3964 tree class_methods)
3966 tree initlist = NULL_TREE, expr;
3967 tree cast_type = build_pointer_type
3968 (xref_tag (RECORD_TYPE,
3969 get_identifier (UTAG_CLASS)));
3971 /* Filling the "isa" in with one allows the runtime system to
3972 detect that the version change...should remove before final release. */
3974 expr = build_int_cst (cast_type, PROTOCOL_VERSION);
3975 initlist = tree_cons (NULL_TREE, expr, initlist);
3976 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3977 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3979 if (!instance_methods)
3980 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
3981 else
3983 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3984 initlist = tree_cons (NULL_TREE, expr, initlist);
3987 if (!class_methods)
3988 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
3989 else
3991 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3992 initlist = tree_cons (NULL_TREE, expr, initlist);
3995 return objc_build_constructor (type, nreverse (initlist));
3998 /* struct _objc_category {
3999 char *category_name;
4000 char *class_name;
4001 struct _objc_method_list *instance_methods;
4002 struct _objc_method_list *class_methods;
4003 struct _objc_protocol_list *protocols;
4004 }; */
4006 static void
4007 build_category_template (void)
4009 tree field_decl, field_decl_chain;
4011 objc_category_template = start_struct (RECORD_TYPE,
4012 get_identifier (UTAG_CATEGORY));
4014 /* char *category_name; */
4015 field_decl = create_field_decl (string_type_node, "category_name");
4016 field_decl_chain = field_decl;
4018 /* char *class_name; */
4019 field_decl = create_field_decl (string_type_node, "class_name");
4020 chainon (field_decl_chain, field_decl);
4022 /* struct _objc_method_list *instance_methods; */
4023 field_decl = create_field_decl (build_pointer_type
4024 (xref_tag (RECORD_TYPE,
4025 get_identifier
4026 (UTAG_METHOD_LIST))),
4027 "instance_methods");
4028 chainon (field_decl_chain, field_decl);
4030 /* struct _objc_method_list *class_methods; */
4031 field_decl = create_field_decl (build_pointer_type
4032 (xref_tag (RECORD_TYPE,
4033 get_identifier
4034 (UTAG_METHOD_LIST))),
4035 "class_methods");
4036 chainon (field_decl_chain, field_decl);
4038 /* struct _objc_protocol **protocol_list; */
4039 field_decl = create_field_decl (build_pointer_type
4040 (build_pointer_type
4041 (objc_protocol_template)),
4042 "protocol_list");
4043 chainon (field_decl_chain, field_decl);
4045 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
4048 /* struct _objc_selector {
4049 SEL sel_id;
4050 char *sel_type;
4051 }; */
4053 static void
4054 build_selector_template (void)
4057 tree field_decl, field_decl_chain;
4059 objc_selector_template
4060 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
4062 /* SEL sel_id; */
4063 field_decl = create_field_decl (objc_selector_type, "sel_id");
4064 field_decl_chain = field_decl;
4066 /* char *sel_type; */
4067 field_decl = create_field_decl (string_type_node, "sel_type");
4068 chainon (field_decl_chain, field_decl);
4070 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
4073 /* struct _objc_class {
4074 struct _objc_class *isa;
4075 struct _objc_class *super_class;
4076 char *name;
4077 long version;
4078 long info;
4079 long instance_size;
4080 struct _objc_ivar_list *ivars;
4081 struct _objc_method_list *methods;
4082 #ifdef __NEXT_RUNTIME__
4083 struct objc_cache *cache;
4084 #else
4085 struct sarray *dtable;
4086 struct _objc_class *subclass_list;
4087 struct _objc_class *sibling_class;
4088 #endif
4089 struct _objc_protocol_list *protocols;
4090 #ifdef __NEXT_RUNTIME__
4091 void *sel_id;
4092 #endif
4093 void *gc_object_type;
4094 }; */
4096 /* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
4097 the NeXT/Apple runtime; still, the compiler must generate them to
4098 maintain backward binary compatibility (and to allow for future
4099 expansion). */
4101 static void
4102 build_class_template (void)
4104 tree field_decl, field_decl_chain;
4106 objc_class_template
4107 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
4109 /* struct _objc_class *isa; */
4110 field_decl = create_field_decl (build_pointer_type (objc_class_template),
4111 "isa");
4112 field_decl_chain = field_decl;
4114 /* struct _objc_class *super_class; */
4115 field_decl = create_field_decl (build_pointer_type (objc_class_template),
4116 "super_class");
4117 chainon (field_decl_chain, field_decl);
4119 /* char *name; */
4120 field_decl = create_field_decl (string_type_node, "name");
4121 chainon (field_decl_chain, field_decl);
4123 /* long version; */
4124 field_decl = create_field_decl (long_integer_type_node, "version");
4125 chainon (field_decl_chain, field_decl);
4127 /* long info; */
4128 field_decl = create_field_decl (long_integer_type_node, "info");
4129 chainon (field_decl_chain, field_decl);
4131 /* long instance_size; */
4132 field_decl = create_field_decl (long_integer_type_node, "instance_size");
4133 chainon (field_decl_chain, field_decl);
4135 /* struct _objc_ivar_list *ivars; */
4136 field_decl = create_field_decl (build_pointer_type
4137 (xref_tag (RECORD_TYPE,
4138 get_identifier
4139 (UTAG_IVAR_LIST))),
4140 "ivars");
4141 chainon (field_decl_chain, field_decl);
4143 /* struct _objc_method_list *methods; */
4144 field_decl = create_field_decl (build_pointer_type
4145 (xref_tag (RECORD_TYPE,
4146 get_identifier
4147 (UTAG_METHOD_LIST))),
4148 "methods");
4149 chainon (field_decl_chain, field_decl);
4151 if (flag_next_runtime)
4153 /* struct objc_cache *cache; */
4154 field_decl = create_field_decl (build_pointer_type
4155 (xref_tag (RECORD_TYPE,
4156 get_identifier
4157 ("objc_cache"))),
4158 "cache");
4159 chainon (field_decl_chain, field_decl);
4161 else
4163 /* struct sarray *dtable; */
4164 field_decl = create_field_decl (build_pointer_type
4165 (xref_tag (RECORD_TYPE,
4166 get_identifier
4167 ("sarray"))),
4168 "dtable");
4169 chainon (field_decl_chain, field_decl);
4171 /* struct objc_class *subclass_list; */
4172 field_decl = create_field_decl (build_pointer_type
4173 (objc_class_template),
4174 "subclass_list");
4175 chainon (field_decl_chain, field_decl);
4177 /* struct objc_class *sibling_class; */
4178 field_decl = create_field_decl (build_pointer_type
4179 (objc_class_template),
4180 "sibling_class");
4181 chainon (field_decl_chain, field_decl);
4184 /* struct _objc_protocol **protocol_list; */
4185 field_decl = create_field_decl (build_pointer_type
4186 (build_pointer_type
4187 (xref_tag (RECORD_TYPE,
4188 get_identifier
4189 (UTAG_PROTOCOL)))),
4190 "protocol_list");
4191 chainon (field_decl_chain, field_decl);
4193 if (flag_next_runtime)
4195 /* void *sel_id; */
4196 field_decl = create_field_decl (build_pointer_type (void_type_node),
4197 "sel_id");
4198 chainon (field_decl_chain, field_decl);
4201 /* void *gc_object_type; */
4202 field_decl = create_field_decl (build_pointer_type (void_type_node),
4203 "gc_object_type");
4204 chainon (field_decl_chain, field_decl);
4206 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
4209 /* Generate appropriate forward declarations for an implementation. */
4211 static void
4212 synth_forward_declarations (void)
4214 tree an_id;
4216 /* static struct objc_class _OBJC_CLASS_<my_name>; */
4217 UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
4218 objc_class_template);
4220 /* static struct objc_class _OBJC_METACLASS_<my_name>; */
4221 UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
4222 objc_class_template);
4224 /* Pre-build the following entities - for speed/convenience. */
4226 an_id = get_identifier ("super_class");
4227 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
4228 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
4231 static void
4232 error_with_ivar (const char *message, tree decl)
4234 error ("%J%s `%s'", decl,
4235 message, gen_declaration (decl));
4239 static void
4240 check_ivars (tree inter, tree imp)
4242 tree intdecls = CLASS_RAW_IVARS (inter);
4243 tree impdecls = CLASS_RAW_IVARS (imp);
4245 while (1)
4247 tree t1, t2;
4249 #ifdef OBJCPLUS
4250 if (intdecls && TREE_CODE (intdecls) == TYPE_DECL)
4251 intdecls = TREE_CHAIN (intdecls);
4252 #endif
4253 if (intdecls == 0 && impdecls == 0)
4254 break;
4255 if (intdecls == 0 || impdecls == 0)
4257 error ("inconsistent instance variable specification");
4258 break;
4261 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
4263 if (!comptypes (t1, t2)
4264 || !tree_int_cst_equal (DECL_INITIAL (intdecls),
4265 DECL_INITIAL (impdecls)))
4267 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
4269 error_with_ivar ("conflicting instance variable type",
4270 impdecls);
4271 error_with_ivar ("previous declaration of",
4272 intdecls);
4274 else /* both the type and the name don't match */
4276 error ("inconsistent instance variable specification");
4277 break;
4281 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
4283 error_with_ivar ("conflicting instance variable name",
4284 impdecls);
4285 error_with_ivar ("previous declaration of",
4286 intdecls);
4289 intdecls = TREE_CHAIN (intdecls);
4290 impdecls = TREE_CHAIN (impdecls);
4294 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
4295 This needs to be done just once per compilation. */
4297 /* struct _objc_super {
4298 struct _objc_object *self;
4299 struct _objc_class *super_class;
4300 }; */
4302 static void
4303 build_super_template (void)
4305 tree field_decl, field_decl_chain;
4307 objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
4309 /* struct _objc_object *self; */
4310 field_decl = create_field_decl (objc_object_type, "self");
4311 field_decl_chain = field_decl;
4313 /* struct _objc_class *super_class; */
4314 field_decl = create_field_decl (build_pointer_type (objc_class_template),
4315 "super_class");
4316 chainon (field_decl_chain, field_decl);
4318 finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
4321 /* struct _objc_ivar {
4322 char *ivar_name;
4323 char *ivar_type;
4324 int ivar_offset;
4325 }; */
4327 static tree
4328 build_ivar_template (void)
4330 tree objc_ivar_id, objc_ivar_record;
4331 tree field_decl, field_decl_chain;
4333 objc_ivar_id = get_identifier (UTAG_IVAR);
4334 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
4336 /* char *ivar_name; */
4337 field_decl = create_field_decl (string_type_node, "ivar_name");
4338 field_decl_chain = field_decl;
4340 /* char *ivar_type; */
4341 field_decl = create_field_decl (string_type_node, "ivar_type");
4342 chainon (field_decl_chain, field_decl);
4344 /* int ivar_offset; */
4345 field_decl = create_field_decl (integer_type_node, "ivar_offset");
4346 chainon (field_decl_chain, field_decl);
4348 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
4350 return objc_ivar_record;
4353 /* struct {
4354 int ivar_count;
4355 struct objc_ivar ivar_list[ivar_count];
4356 }; */
4358 static tree
4359 build_ivar_list_template (tree list_type, int size)
4361 tree objc_ivar_list_record;
4362 tree field_decl, field_decl_chain;
4364 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4366 /* int ivar_count; */
4367 field_decl = create_field_decl (integer_type_node, "ivar_count");
4368 field_decl_chain = field_decl;
4370 /* struct objc_ivar ivar_list[]; */
4371 field_decl = create_field_decl (build_array_type
4372 (list_type,
4373 build_index_type
4374 (build_int_cst (NULL_TREE, size - 1))),
4375 "ivar_list");
4376 chainon (field_decl_chain, field_decl);
4378 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4380 return objc_ivar_list_record;
4383 /* struct {
4384 struct _objc__method_prototype_list *method_next;
4385 int method_count;
4386 struct objc_method method_list[method_count];
4387 }; */
4389 static tree
4390 build_method_list_template (tree list_type, int size)
4392 tree objc_ivar_list_record;
4393 tree field_decl, field_decl_chain;
4395 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
4397 /* struct _objc__method_prototype_list *method_next; */
4398 field_decl = create_field_decl (build_pointer_type
4399 (xref_tag (RECORD_TYPE,
4400 get_identifier
4401 (UTAG_METHOD_PROTOTYPE_LIST))),
4402 "method_next");
4403 field_decl_chain = field_decl;
4405 /* int method_count; */
4406 field_decl = create_field_decl (integer_type_node, "method_count");
4407 chainon (field_decl_chain, field_decl);
4409 /* struct objc_method method_list[]; */
4410 field_decl = create_field_decl (build_array_type
4411 (list_type,
4412 build_index_type
4413 (build_int_cst (NULL_TREE, size - 1))),
4414 "method_list");
4415 chainon (field_decl_chain, field_decl);
4417 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
4419 return objc_ivar_list_record;
4422 static tree
4423 build_ivar_list_initializer (tree type, tree field_decl)
4425 tree initlist = NULL_TREE;
4429 tree ivar = NULL_TREE;
4431 /* Set name. */
4432 if (DECL_NAME (field_decl))
4433 ivar = tree_cons (NULL_TREE,
4434 add_objc_string (DECL_NAME (field_decl),
4435 meth_var_names),
4436 ivar);
4437 else
4438 /* Unnamed bit-field ivar (yuck). */
4439 ivar = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), ivar);
4441 /* Set type. */
4442 encode_field_decl (field_decl,
4443 obstack_object_size (&util_obstack),
4444 OBJC_ENCODE_DONT_INLINE_DEFS);
4446 /* Null terminate string. */
4447 obstack_1grow (&util_obstack, 0);
4448 ivar
4449 = tree_cons
4450 (NULL_TREE,
4451 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
4452 meth_var_types),
4453 ivar);
4454 obstack_free (&util_obstack, util_firstobj);
4456 /* Set offset. */
4457 ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
4458 initlist = tree_cons (NULL_TREE,
4459 objc_build_constructor (type, nreverse (ivar)),
4460 initlist);
4462 field_decl = TREE_CHAIN (field_decl);
4463 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
4465 while (field_decl);
4467 return objc_build_constructor (build_array_type (type, 0),
4468 nreverse (initlist));
4471 static tree
4472 generate_ivars_list (tree type, const char *name, int size, tree list)
4474 tree decl, initlist;
4476 decl = start_var_decl (type, synth_id_with_class_suffix
4477 (name, objc_implementation_context));
4479 initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
4480 initlist = tree_cons (NULL_TREE, list, initlist);
4482 finish_var_decl (decl,
4483 objc_build_constructor (TREE_TYPE (decl),
4484 nreverse (initlist)));
4486 return decl;
4489 /* Count only the fields occurring in T. */
4490 static int
4491 ivar_list_length (tree t)
4493 int count = 0;
4495 for (; t; t = TREE_CHAIN (t))
4496 if (TREE_CODE (t) == FIELD_DECL)
4497 ++count;
4499 return count;
4502 static void
4503 generate_ivar_lists (void)
4505 tree initlist, ivar_list_template, chain;
4506 tree variable_length_type
4507 = xref_tag (RECORD_TYPE, get_identifier (UTAG_IVAR_LIST));
4508 int size;
4510 generating_instance_variables = 1;
4512 if (!objc_ivar_template)
4513 objc_ivar_template = build_ivar_template ();
4515 /* Only generate class variables for the root of the inheritance
4516 hierarchy since these will be the same for every class. */
4518 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
4519 && (chain = TYPE_FIELDS (objc_class_template)))
4521 size = ivar_list_length (chain);
4523 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4524 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4526 UOBJC_CLASS_VARIABLES_decl
4527 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
4528 size, initlist);
4529 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
4531 else
4532 UOBJC_CLASS_VARIABLES_decl = 0;
4534 chain = CLASS_IVARS (implementation_template);
4535 if (chain)
4537 size = ivar_list_length (chain);
4538 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
4539 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
4541 UOBJC_INSTANCE_VARIABLES_decl
4542 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
4543 size, initlist);
4544 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
4546 else
4547 UOBJC_INSTANCE_VARIABLES_decl = 0;
4549 generating_instance_variables = 0;
4552 static tree
4553 build_dispatch_table_initializer (tree type, tree entries)
4555 tree initlist = NULL_TREE;
4559 tree elemlist = NULL_TREE;
4561 elemlist = tree_cons (NULL_TREE,
4562 build_selector (METHOD_SEL_NAME (entries)),
4563 NULL_TREE);
4565 /* Generate the method encoding if we don't have one already. */
4566 if (! METHOD_ENCODING (entries))
4567 METHOD_ENCODING (entries) =
4568 encode_method_prototype (entries);
4570 elemlist = tree_cons (NULL_TREE,
4571 add_objc_string (METHOD_ENCODING (entries),
4572 meth_var_types),
4573 elemlist);
4575 elemlist
4576 = tree_cons (NULL_TREE,
4577 convert (ptr_type_node,
4578 build_unary_op (ADDR_EXPR,
4579 METHOD_DEFINITION (entries), 1)),
4580 elemlist);
4582 initlist = tree_cons (NULL_TREE,
4583 objc_build_constructor (type, nreverse (elemlist)),
4584 initlist);
4586 entries = TREE_CHAIN (entries);
4588 while (entries);
4590 return objc_build_constructor (build_array_type (type, 0),
4591 nreverse (initlist));
4594 /* To accomplish method prototyping without generating all kinds of
4595 inane warnings, the definition of the dispatch table entries were
4596 changed from:
4598 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4600 struct objc_method { SEL _cmd; ...; void *_imp; }; */
4602 static tree
4603 build_method_template (void)
4605 tree _SLT_record;
4606 tree field_decl, field_decl_chain;
4608 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4610 /* SEL _cmd; */
4611 field_decl = create_field_decl (objc_selector_type, "_cmd");
4612 field_decl_chain = field_decl;
4614 /* char *method_types; */
4615 field_decl = create_field_decl (string_type_node, "method_types");
4616 chainon (field_decl_chain, field_decl);
4618 /* void *_imp; */
4619 field_decl = create_field_decl (build_pointer_type (void_type_node),
4620 "_imp");
4621 chainon (field_decl_chain, field_decl);
4623 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4625 return _SLT_record;
4629 static tree
4630 generate_dispatch_table (tree type, const char *name, int size, tree list)
4632 tree decl, initlist;
4634 decl = start_var_decl (type, synth_id_with_class_suffix
4635 (name, objc_implementation_context));
4637 initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
4638 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
4639 initlist = tree_cons (NULL_TREE, list, initlist);
4641 finish_var_decl (decl,
4642 objc_build_constructor (TREE_TYPE (decl),
4643 nreverse (initlist)));
4645 return decl;
4648 static void
4649 mark_referenced_methods (void)
4651 struct imp_entry *impent;
4652 tree chain;
4654 for (impent = imp_list; impent; impent = impent->next)
4656 chain = CLASS_CLS_METHODS (impent->imp_context);
4657 while (chain)
4659 cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4660 chain = TREE_CHAIN (chain);
4663 chain = CLASS_NST_METHODS (impent->imp_context);
4664 while (chain)
4666 cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
4667 chain = TREE_CHAIN (chain);
4672 static void
4673 generate_dispatch_tables (void)
4675 tree initlist, chain, method_list_template;
4676 tree variable_length_type
4677 = xref_tag (RECORD_TYPE, get_identifier (UTAG_METHOD_LIST));
4678 int size;
4680 if (!objc_method_template)
4681 objc_method_template = build_method_template ();
4683 chain = CLASS_CLS_METHODS (objc_implementation_context);
4684 if (chain)
4686 size = list_length (chain);
4688 method_list_template
4689 = build_method_list_template (objc_method_template, size);
4690 initlist
4691 = build_dispatch_table_initializer (objc_method_template, chain);
4693 UOBJC_CLASS_METHODS_decl
4694 = generate_dispatch_table (method_list_template,
4695 ((TREE_CODE (objc_implementation_context)
4696 == CLASS_IMPLEMENTATION_TYPE)
4697 ? "_OBJC_CLASS_METHODS"
4698 : "_OBJC_CATEGORY_CLASS_METHODS"),
4699 size, initlist);
4700 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4702 else
4703 UOBJC_CLASS_METHODS_decl = 0;
4705 chain = CLASS_NST_METHODS (objc_implementation_context);
4706 if (chain)
4708 size = list_length (chain);
4710 method_list_template
4711 = build_method_list_template (objc_method_template, size);
4712 initlist
4713 = build_dispatch_table_initializer (objc_method_template, chain);
4715 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4716 UOBJC_INSTANCE_METHODS_decl
4717 = generate_dispatch_table (method_list_template,
4718 "_OBJC_INSTANCE_METHODS",
4719 size, initlist);
4720 else
4721 /* We have a category. */
4722 UOBJC_INSTANCE_METHODS_decl
4723 = generate_dispatch_table (method_list_template,
4724 "_OBJC_CATEGORY_INSTANCE_METHODS",
4725 size, initlist);
4726 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4728 else
4729 UOBJC_INSTANCE_METHODS_decl = 0;
4732 static tree
4733 generate_protocol_list (tree i_or_p)
4735 tree initlist;
4736 tree refs_decl, lproto, e, plist;
4737 int size = 0;
4738 const char *ref_name;
4740 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4741 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4742 plist = CLASS_PROTOCOL_LIST (i_or_p);
4743 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4744 plist = PROTOCOL_LIST (i_or_p);
4745 else
4746 abort ();
4748 /* Compute size. */
4749 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4750 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4751 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4752 size++;
4754 /* Build initializer. */
4755 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), NULL_TREE);
4756 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
4757 initlist = tree_cons (NULL_TREE, e, initlist);
4759 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4761 tree pval = TREE_VALUE (lproto);
4763 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4764 && PROTOCOL_FORWARD_DECL (pval))
4766 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4767 initlist = tree_cons (NULL_TREE, e, initlist);
4771 /* static struct objc_protocol *refs[n]; */
4773 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4774 ref_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p);
4775 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4776 ref_name = synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p);
4777 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4778 ref_name = synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p);
4779 else
4780 abort ();
4782 refs_decl = start_var_decl
4783 (build_array_type
4784 (build_pointer_type (objc_protocol_template),
4785 build_index_type (build_int_cst (NULL_TREE, size + 2))),
4786 ref_name);
4788 finish_var_decl (refs_decl, objc_build_constructor (TREE_TYPE (refs_decl),
4789 nreverse (initlist)));
4791 return refs_decl;
4794 static tree
4795 build_category_initializer (tree type, tree cat_name, tree class_name,
4796 tree instance_methods, tree class_methods,
4797 tree protocol_list)
4799 tree initlist = NULL_TREE, expr;
4801 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4802 initlist = tree_cons (NULL_TREE, class_name, initlist);
4804 if (!instance_methods)
4805 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4806 else
4808 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4809 initlist = tree_cons (NULL_TREE, expr, initlist);
4811 if (!class_methods)
4812 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4813 else
4815 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4816 initlist = tree_cons (NULL_TREE, expr, initlist);
4819 /* protocol_list = */
4820 if (!protocol_list)
4821 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4822 else
4824 expr = convert (build_pointer_type
4825 (build_pointer_type
4826 (objc_protocol_template)),
4827 build_unary_op (ADDR_EXPR, protocol_list, 0));
4828 initlist = tree_cons (NULL_TREE, expr, initlist);
4831 return objc_build_constructor (type, nreverse (initlist));
4834 /* struct _objc_class {
4835 struct objc_class *isa;
4836 struct objc_class *super_class;
4837 char *name;
4838 long version;
4839 long info;
4840 long instance_size;
4841 struct objc_ivar_list *ivars;
4842 struct objc_method_list *methods;
4843 if (flag_next_runtime)
4844 struct objc_cache *cache;
4845 else {
4846 struct sarray *dtable;
4847 struct objc_class *subclass_list;
4848 struct objc_class *sibling_class;
4850 struct objc_protocol_list *protocols;
4851 if (flag_next_runtime)
4852 void *sel_id;
4853 void *gc_object_type;
4854 }; */
4856 static tree
4857 build_shared_structure_initializer (tree type, tree isa, tree super,
4858 tree name, tree size, int status,
4859 tree dispatch_table, tree ivar_list,
4860 tree protocol_list)
4862 tree initlist = NULL_TREE, expr;
4864 /* isa = */
4865 initlist = tree_cons (NULL_TREE, isa, initlist);
4867 /* super_class = */
4868 initlist = tree_cons (NULL_TREE, super, initlist);
4870 /* name = */
4871 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4873 /* version = */
4874 initlist = tree_cons (NULL_TREE, build_int_cst (long_integer_type_node, 0),
4875 initlist);
4877 /* info = */
4878 initlist = tree_cons (NULL_TREE,
4879 build_int_cst (long_integer_type_node, status),
4880 initlist);
4882 /* instance_size = */
4883 initlist = tree_cons (NULL_TREE, convert (long_integer_type_node, size),
4884 initlist);
4886 /* objc_ivar_list = */
4887 if (!ivar_list)
4888 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4889 else
4891 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4892 initlist = tree_cons (NULL_TREE, expr, initlist);
4895 /* objc_method_list = */
4896 if (!dispatch_table)
4897 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4898 else
4900 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4901 initlist = tree_cons (NULL_TREE, expr, initlist);
4904 if (flag_next_runtime)
4905 /* method_cache = */
4906 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4907 else
4909 /* dtable = */
4910 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4912 /* subclass_list = */
4913 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4915 /* sibling_class = */
4916 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4919 /* protocol_list = */
4920 if (! protocol_list)
4921 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4922 else
4924 expr = convert (build_pointer_type
4925 (build_pointer_type
4926 (objc_protocol_template)),
4927 build_unary_op (ADDR_EXPR, protocol_list, 0));
4928 initlist = tree_cons (NULL_TREE, expr, initlist);
4931 if (flag_next_runtime)
4932 /* sel_id = NULL */
4933 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4935 /* gc_object_type = NULL */
4936 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
4938 return objc_build_constructor (type, nreverse (initlist));
4941 /* Retrieve category interface CAT_NAME (if any) associated with CLASS. */
4943 static inline tree
4944 lookup_category (tree class, tree cat_name)
4946 tree category = CLASS_CATEGORY_LIST (class);
4948 while (category && CLASS_SUPER_NAME (category) != cat_name)
4949 category = CLASS_CATEGORY_LIST (category);
4950 return category;
4953 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4955 static void
4956 generate_category (tree cat)
4958 tree decl;
4959 tree initlist, cat_name_expr, class_name_expr;
4960 tree protocol_decl, category;
4962 add_class_reference (CLASS_NAME (cat));
4963 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4965 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4967 category = lookup_category (implementation_template,
4968 CLASS_SUPER_NAME (cat));
4970 if (category && CLASS_PROTOCOL_LIST (category))
4972 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4973 protocol_decl = generate_protocol_list (category);
4975 else
4976 protocol_decl = 0;
4978 decl = start_var_decl (objc_category_template,
4979 synth_id_with_class_suffix
4980 ("_OBJC_CATEGORY", objc_implementation_context));
4982 initlist = build_category_initializer (TREE_TYPE (decl),
4983 cat_name_expr, class_name_expr,
4984 UOBJC_INSTANCE_METHODS_decl,
4985 UOBJC_CLASS_METHODS_decl,
4986 protocol_decl);
4988 finish_var_decl (decl, initlist);
4991 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4992 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4994 static void
4995 generate_shared_structures (void)
4997 tree sc_spec, decl_specs, decl;
4998 tree name_expr, super_expr, root_expr;
4999 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
5000 tree cast_type, initlist, protocol_decl;
5002 my_super_id = CLASS_SUPER_NAME (implementation_template);
5003 if (my_super_id)
5005 add_class_reference (my_super_id);
5007 /* Compute "my_root_id" - this is required for code generation.
5008 the "isa" for all meta class structures points to the root of
5009 the inheritance hierarchy (e.g. "__Object")... */
5010 my_root_id = my_super_id;
5013 tree my_root_int = lookup_interface (my_root_id);
5015 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
5016 my_root_id = CLASS_SUPER_NAME (my_root_int);
5017 else
5018 break;
5020 while (1);
5022 else
5023 /* No super class. */
5024 my_root_id = CLASS_NAME (implementation_template);
5026 cast_type = build_pointer_type (objc_class_template);
5027 name_expr = add_objc_string (CLASS_NAME (implementation_template),
5028 class_names);
5030 /* Install class `isa' and `super' pointers at runtime. */
5031 if (my_super_id)
5033 super_expr = add_objc_string (my_super_id, class_names);
5034 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
5036 else
5037 super_expr = build_int_cst (NULL_TREE, 0);
5039 root_expr = add_objc_string (my_root_id, class_names);
5040 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
5042 if (CLASS_PROTOCOL_LIST (implementation_template))
5044 generate_protocol_references
5045 (CLASS_PROTOCOL_LIST (implementation_template));
5046 protocol_decl = generate_protocol_list (implementation_template);
5048 else
5049 protocol_decl = 0;
5051 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
5053 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
5054 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
5056 decl = start_var_decl (objc_class_template,
5057 IDENTIFIER_POINTER
5058 (DECL_NAME (UOBJC_METACLASS_decl)));
5060 initlist
5061 = build_shared_structure_initializer
5062 (TREE_TYPE (decl),
5063 root_expr, super_expr, name_expr,
5064 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
5065 2 /*CLS_META*/,
5066 UOBJC_CLASS_METHODS_decl,
5067 UOBJC_CLASS_VARIABLES_decl,
5068 protocol_decl);
5070 finish_var_decl (decl, initlist);
5072 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
5074 decl = start_var_decl (objc_class_template,
5075 IDENTIFIER_POINTER
5076 (DECL_NAME (UOBJC_CLASS_decl)));
5078 initlist
5079 = build_shared_structure_initializer
5080 (TREE_TYPE (decl),
5081 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
5082 super_expr, name_expr,
5083 convert (integer_type_node,
5084 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
5085 (implementation_template))),
5086 1 /*CLS_FACTORY*/,
5087 UOBJC_INSTANCE_METHODS_decl,
5088 UOBJC_INSTANCE_VARIABLES_decl,
5089 protocol_decl);
5091 finish_var_decl (decl, initlist);
5095 static const char *
5096 synth_id_with_class_suffix (const char *preamble, tree ctxt)
5098 static char string[BUFSIZE];
5100 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
5101 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
5103 sprintf (string, "%s_%s", preamble,
5104 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
5106 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
5107 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
5109 /* We have a category. */
5110 const char *const class_name
5111 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
5112 const char *const class_super_name
5113 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
5114 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
5116 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
5118 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
5119 sprintf (string, "%s_%s", preamble, protocol_name);
5121 else
5122 abort ();
5124 return string;
5127 /* If type is empty or only type qualifiers are present, add default
5128 type of id (otherwise grokdeclarator will default to int). */
5130 static tree
5131 adjust_type_for_id_default (tree type)
5133 if (!type)
5134 type = make_node (TREE_LIST);
5136 if (!TREE_VALUE (type))
5137 TREE_VALUE (type) = objc_object_type;
5138 else if (TREE_CODE (TREE_VALUE (type)) == RECORD_TYPE
5139 && TYPED_OBJECT (TREE_VALUE (type)))
5140 error ("can not use an object as parameter to a method");
5142 return type;
5145 /* Usage:
5146 keyworddecl:
5147 selector ':' '(' typename ')' identifier
5149 Purpose:
5150 Transform an Objective-C keyword argument into
5151 the C equivalent parameter declarator.
5153 In: key_name, an "identifier_node" (optional).
5154 arg_type, a "tree_list" (optional).
5155 arg_name, an "identifier_node".
5157 Note: It would be really nice to strongly type the preceding
5158 arguments in the function prototype; however, then I
5159 could not use the "accessor" macros defined in "tree.h".
5161 Out: an instance of "keyword_decl". */
5163 tree
5164 objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
5166 tree keyword_decl;
5168 /* If no type is specified, default to "id". */
5169 arg_type = adjust_type_for_id_default (arg_type);
5171 keyword_decl = make_node (KEYWORD_DECL);
5173 TREE_TYPE (keyword_decl) = arg_type;
5174 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
5175 KEYWORD_KEY_NAME (keyword_decl) = key_name;
5177 return keyword_decl;
5180 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
5182 static tree
5183 build_keyword_selector (tree selector)
5185 int len = 0;
5186 tree key_chain, key_name;
5187 char *buf;
5189 /* Scan the selector to see how much space we'll need. */
5190 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5192 if (TREE_CODE (selector) == KEYWORD_DECL)
5193 key_name = KEYWORD_KEY_NAME (key_chain);
5194 else if (TREE_CODE (selector) == TREE_LIST)
5195 key_name = TREE_PURPOSE (key_chain);
5196 else
5197 abort ();
5199 if (key_name)
5200 len += IDENTIFIER_LENGTH (key_name) + 1;
5201 else
5202 /* Just a ':' arg. */
5203 len++;
5206 buf = (char *) alloca (len + 1);
5207 /* Start the buffer out as an empty string. */
5208 buf[0] = '\0';
5210 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
5212 if (TREE_CODE (selector) == KEYWORD_DECL)
5213 key_name = KEYWORD_KEY_NAME (key_chain);
5214 else if (TREE_CODE (selector) == TREE_LIST)
5216 key_name = TREE_PURPOSE (key_chain);
5217 /* The keyword decl chain will later be used as a function argument
5218 chain. Unhook the selector itself so as to not confuse other
5219 parts of the compiler. */
5220 TREE_PURPOSE (key_chain) = NULL_TREE;
5222 else
5223 abort ();
5225 if (key_name)
5226 strcat (buf, IDENTIFIER_POINTER (key_name));
5227 strcat (buf, ":");
5230 return get_identifier (buf);
5233 /* Used for declarations and definitions. */
5235 static tree
5236 build_method_decl (enum tree_code code, tree ret_type, tree selector,
5237 tree add_args)
5239 tree method_decl;
5241 /* If no type is specified, default to "id". */
5242 ret_type = adjust_type_for_id_default (ret_type);
5244 method_decl = make_node (code);
5245 TREE_TYPE (method_decl) = ret_type;
5247 /* If we have a keyword selector, create an identifier_node that
5248 represents the full selector name (`:' included)... */
5249 if (TREE_CODE (selector) == KEYWORD_DECL)
5251 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
5252 METHOD_SEL_ARGS (method_decl) = selector;
5253 METHOD_ADD_ARGS (method_decl) = add_args;
5255 else
5257 METHOD_SEL_NAME (method_decl) = selector;
5258 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
5259 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
5262 return method_decl;
5265 #define METHOD_DEF 0
5266 #define METHOD_REF 1
5268 /* Used by `build_objc_method_call' and `comp_proto_with_proto'. Return
5269 an argument list for method METH. CONTEXT is either METHOD_DEF or
5270 METHOD_REF, saying whether we are trying to define a method or call
5271 one. SUPERFLAG says this is for a send to super; this makes a
5272 difference for the NeXT calling sequence in which the lookup and
5273 the method call are done together. If METH is null, user-defined
5274 arguments (i.e., beyond self and _cmd) shall be represented by `...'. */
5276 static tree
5277 get_arg_type_list (tree meth, int context, int superflag)
5279 tree arglist, akey;
5281 /* Receiver type. */
5282 if (flag_next_runtime && superflag)
5283 arglist = build_tree_list (NULL_TREE, objc_super_type);
5284 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5285 arglist = build_tree_list (NULL_TREE, objc_instance_type);
5286 else
5287 arglist = build_tree_list (NULL_TREE, objc_object_type);
5289 /* Selector type - will eventually change to `int'. */
5290 chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
5292 /* No actual method prototype given -- assume that remaining arguments
5293 are `...'. */
5294 if (!meth)
5295 return arglist;
5297 /* Build a list of argument types. */
5298 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
5300 tree arg_type = TREE_VALUE (TREE_TYPE (akey));
5302 chainon (arglist, build_tree_list (NULL_TREE, arg_type));
5305 if (METHOD_ADD_ARGS (meth))
5307 for (akey = TREE_CHAIN (METHOD_ADD_ARGS (meth));
5308 akey; akey = TREE_CHAIN (akey))
5310 tree arg_type = TREE_TYPE (TREE_VALUE (akey));
5312 chainon (arglist, build_tree_list (NULL_TREE, arg_type));
5315 if (!TREE_OVERFLOW (METHOD_ADD_ARGS (meth)))
5316 goto lack_of_ellipsis;
5318 else
5320 lack_of_ellipsis:
5321 chainon (arglist, OBJC_VOID_AT_END);
5324 return arglist;
5327 static tree
5328 check_duplicates (hash hsh, int methods, int is_class)
5330 tree meth = NULL_TREE;
5332 if (hsh)
5334 meth = hsh->key;
5336 if (hsh->list)
5338 /* We have two or more methods with the same name but
5339 different types. */
5340 attr loop;
5342 warning ("multiple %s named `%c%s' found",
5343 methods ? "methods" : "selectors",
5344 (is_class ? '+' : '-'),
5345 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5347 warn_with_method (methods ? "using" : "found",
5348 ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5349 ? '-'
5350 : '+'),
5351 meth);
5352 for (loop = hsh->list; loop; loop = loop->next)
5353 warn_with_method ("also found",
5354 ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
5355 ? '-'
5356 : '+'),
5357 loop->value);
5360 return meth;
5363 /* If RECEIVER is a class reference, return the identifier node for
5364 the referenced class. RECEIVER is created by objc_get_class_reference,
5365 so we check the exact form created depending on which runtimes are
5366 used. */
5368 static tree
5369 receiver_is_class_object (tree receiver, int self, int super)
5371 tree chain, exp, arg;
5373 /* The receiver is 'self' or 'super' in the context of a class method. */
5374 if (objc_method_context
5375 && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL
5376 && (self || super))
5377 return (super
5378 ? CLASS_SUPER_NAME (implementation_template)
5379 : CLASS_NAME (implementation_template));
5381 if (flag_next_runtime)
5383 /* The receiver is a variable created by
5384 build_class_reference_decl. */
5385 if (TREE_CODE (receiver) == VAR_DECL && IS_CLASS (TREE_TYPE (receiver)))
5386 /* Look up the identifier. */
5387 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
5388 if (TREE_PURPOSE (chain) == receiver)
5389 return TREE_VALUE (chain);
5392 /* The receiver is a function call that returns an id. Check if
5393 it is a call to objc_getClass, if so, pick up the class name. */
5394 if (TREE_CODE (receiver) == CALL_EXPR
5395 && (exp = TREE_OPERAND (receiver, 0))
5396 && TREE_CODE (exp) == ADDR_EXPR
5397 && (exp = TREE_OPERAND (exp, 0))
5398 && TREE_CODE (exp) == FUNCTION_DECL
5399 /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
5400 prototypes for objc_get_class(). Thankfully, they seem to share the
5401 same function type. */
5402 && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
5403 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
5404 /* We have a call to objc_get_class/objc_getClass! */
5405 && (arg = TREE_OPERAND (receiver, 1))
5406 && TREE_CODE (arg) == TREE_LIST
5407 && (arg = TREE_VALUE (arg)))
5409 STRIP_NOPS (arg);
5410 if (TREE_CODE (arg) == ADDR_EXPR
5411 && (arg = TREE_OPERAND (arg, 0))
5412 && TREE_CODE (arg) == STRING_CST)
5413 /* Finally, we have the class name. */
5414 return get_identifier (TREE_STRING_POINTER (arg));
5416 return 0;
5419 /* If we are currently building a message expr, this holds
5420 the identifier of the selector of the message. This is
5421 used when printing warnings about argument mismatches. */
5423 static tree current_objc_message_selector = 0;
5425 tree
5426 objc_message_selector (void)
5428 return current_objc_message_selector;
5431 /* Construct an expression for sending a message.
5432 MESS has the object to send to in TREE_PURPOSE
5433 and the argument list (including selector) in TREE_VALUE.
5435 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
5436 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
5438 tree
5439 objc_build_message_expr (tree mess)
5441 tree receiver = TREE_PURPOSE (mess);
5442 tree sel_name;
5443 #ifdef OBJCPLUS
5444 tree args = TREE_PURPOSE (TREE_VALUE (mess));
5445 #else
5446 tree args = TREE_VALUE (mess);
5447 #endif
5448 tree method_params = NULL_TREE;
5450 if (TREE_CODE (receiver) == ERROR_MARK)
5451 return error_mark_node;
5453 /* Obtain the full selector name. */
5454 if (TREE_CODE (args) == IDENTIFIER_NODE)
5455 /* A unary selector. */
5456 sel_name = args;
5457 else if (TREE_CODE (args) == TREE_LIST)
5458 sel_name = build_keyword_selector (args);
5459 else
5460 abort ();
5462 /* Build the parameter list to give to the method. */
5463 if (TREE_CODE (args) == TREE_LIST)
5464 #ifdef OBJCPLUS
5465 method_params = chainon (args, TREE_VALUE (TREE_VALUE (mess)));
5466 #else
5468 tree chain = args, prev = NULL_TREE;
5470 /* We have a keyword selector--check for comma expressions. */
5471 while (chain)
5473 tree element = TREE_VALUE (chain);
5475 /* We have a comma expression, must collapse... */
5476 if (TREE_CODE (element) == TREE_LIST)
5478 if (prev)
5479 TREE_CHAIN (prev) = element;
5480 else
5481 args = element;
5483 prev = chain;
5484 chain = TREE_CHAIN (chain);
5486 method_params = args;
5488 #endif
5490 #ifdef OBJCPLUS
5491 if (processing_template_decl)
5492 /* Must wait until template instantiation time. */
5493 return build_min_nt (MESSAGE_SEND_EXPR, receiver, sel_name,
5494 method_params);
5495 #endif
5497 return objc_finish_message_expr (receiver, sel_name, method_params);
5500 /* Look up method SEL_NAME that would be suitable for receiver
5501 of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
5502 nonzero), and report on any duplicates. */
5504 static tree
5505 lookup_method_in_hash_lists (tree sel_name, int is_class)
5507 hash method_prototype = NULL;
5509 if (!is_class)
5510 method_prototype = hash_lookup (nst_method_hash_list,
5511 sel_name);
5513 if (!method_prototype)
5515 method_prototype = hash_lookup (cls_method_hash_list,
5516 sel_name);
5517 is_class = 1;
5520 return check_duplicates (method_prototype, 1, is_class);
5523 /* The 'objc_finish_message_expr' routine is called from within
5524 'objc_build_message_expr' for non-template functions. In the case of
5525 C++ template functions, it is called from 'build_expr_from_tree'
5526 (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */
5528 tree
5529 objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
5531 tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
5532 tree selector, retval, class_tree;
5533 int self, super, have_cast;
5535 /* Extract the receiver of the message, as well as its type
5536 (where the latter may take the form of a cast or be inferred
5537 from the implementation context). */
5538 rtype = receiver;
5539 while (TREE_CODE (rtype) == COMPOUND_EXPR
5540 || TREE_CODE (rtype) == MODIFY_EXPR
5541 || TREE_CODE (rtype) == NOP_EXPR
5542 || TREE_CODE (rtype) == CONVERT_EXPR
5543 || TREE_CODE (rtype) == COMPONENT_REF)
5544 rtype = TREE_OPERAND (rtype, 0);
5545 self = (rtype == self_decl);
5546 super = (rtype == UOBJC_SUPER_decl);
5547 rtype = TREE_TYPE (receiver);
5548 have_cast = (TREE_CODE (receiver) == NOP_EXPR
5549 || (TREE_CODE (receiver) == COMPOUND_EXPR
5550 && !IS_SUPER (rtype)));
5552 /* If the receiver is a class object, retrieve the corresponding
5553 @interface, if one exists. */
5554 class_tree = receiver_is_class_object (receiver, self, super);
5556 /* Now determine the receiver type (if an explicit cast has not been
5557 provided). */
5558 if (!have_cast)
5560 if (class_tree)
5561 rtype = lookup_interface (class_tree);
5562 /* Handle `self' and `super'. */
5563 else if (super)
5565 if (!CLASS_SUPER_NAME (implementation_template))
5567 error ("no super class declared in @interface for `%s'",
5568 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5569 return error_mark_node;
5571 rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5573 else if (self)
5574 rtype = lookup_interface (CLASS_NAME (implementation_template));
5577 /* If receiver is of type `id' or `Class' (or if the @interface for a
5578 class is not visible), we shall be satisfied with the existence of
5579 any instance or class method. */
5580 if (!rtype || objc_is_id (rtype))
5582 if (!rtype)
5583 rtype = xref_tag (RECORD_TYPE, class_tree);
5584 else
5586 class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE);
5587 rprotos = TYPE_PROTOCOL_LIST (rtype);
5588 rtype = NULL_TREE;
5591 if (rprotos)
5593 /* If messaging 'id <Protos>' or 'Class <Proto>', first search
5594 in protocols themselves for the method prototype. */
5595 method_prototype
5596 = lookup_method_in_protocol_list (rprotos, sel_name,
5597 class_tree != NULL_TREE);
5599 /* If messaging 'Class <Proto>' but did not find a class method
5600 prototype, search for an instance method instead, and warn
5601 about having done so. */
5602 if (!method_prototype && !rtype && class_tree != NULL_TREE)
5604 method_prototype
5605 = lookup_method_in_protocol_list (rprotos, sel_name, 0);
5607 if (method_prototype)
5608 warning ("found `-%s' instead of `+%s' in protocol(s)",
5609 IDENTIFIER_POINTER (sel_name),
5610 IDENTIFIER_POINTER (sel_name));
5614 else
5616 tree orig_rtype = rtype, saved_rtype;
5618 if (TREE_CODE (rtype) == POINTER_TYPE)
5619 rtype = TREE_TYPE (rtype);
5620 /* Traverse typedef aliases */
5621 while (TREE_CODE (rtype) == RECORD_TYPE && OBJC_TYPE_NAME (rtype)
5622 && TREE_CODE (OBJC_TYPE_NAME (rtype)) == TYPE_DECL
5623 && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype)))
5624 rtype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (rtype));
5625 saved_rtype = rtype;
5626 if (TYPED_OBJECT (rtype))
5628 rprotos = TYPE_PROTOCOL_LIST (rtype);
5629 rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
5631 /* If we could not find an @interface declaration, we must have
5632 only seen a @class declaration; so, we cannot say anything
5633 more intelligent about which methods the receiver will
5634 understand. */
5635 if (!rtype)
5636 rtype = saved_rtype;
5637 else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
5638 || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
5640 /* We have a valid ObjC class name. Look up the method name
5641 in the published @interface for the class (and its
5642 superclasses). */
5643 method_prototype
5644 = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
5646 /* If the method was not found in the @interface, it may still
5647 exist locally as part of the @implementation. */
5648 if (!method_prototype && objc_implementation_context
5649 && CLASS_NAME (objc_implementation_context)
5650 == OBJC_TYPE_NAME (rtype))
5651 method_prototype
5652 = lookup_method
5653 ((class_tree
5654 ? CLASS_CLS_METHODS (objc_implementation_context)
5655 : CLASS_NST_METHODS (objc_implementation_context)),
5656 sel_name);
5658 /* If we haven't found a candidate method by now, try looking for
5659 it in the protocol list. */
5660 if (!method_prototype && rprotos)
5661 method_prototype
5662 = lookup_method_in_protocol_list (rprotos, sel_name,
5663 class_tree != NULL_TREE);
5665 else
5667 warning ("invalid receiver type `%s'",
5668 gen_type_name (orig_rtype));
5669 /* After issuing the "invalid receiver" warning, perform method
5670 lookup as if we were messaging 'id'. */
5671 rtype = rprotos = NULL_TREE;
5676 /* For 'id' or 'Class' receivers, search in the global hash table
5677 as a last resort. For all receivers, warn if protocol searches
5678 have failed. */
5679 if (!method_prototype)
5681 if (rprotos)
5682 warning ("`%c%s' not found in protocol(s)",
5683 (class_tree ? '+' : '-'),
5684 IDENTIFIER_POINTER (sel_name));
5686 if (!rtype)
5687 method_prototype
5688 = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
5691 if (!method_prototype)
5693 static bool warn_missing_methods = false;
5695 if (rtype)
5696 warning ("`%s' may not respond to `%c%s'",
5697 IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
5698 (class_tree ? '+' : '-'),
5699 IDENTIFIER_POINTER (sel_name));
5700 /* If we are messaging an 'id' or 'Class' object and made it here,
5701 then we have failed to find _any_ instance or class method,
5702 respectively. */
5703 else
5704 warning ("no `%c%s' method found",
5705 (class_tree ? '+' : '-'),
5706 IDENTIFIER_POINTER (sel_name));
5708 if (!warn_missing_methods)
5710 warning ("(Messages without a matching method signature");
5711 warning ("will be assumed to return `id' and accept");
5712 warning ("`...' as arguments.)");
5713 warn_missing_methods = true;
5717 /* Save the selector name for printing error messages. */
5718 current_objc_message_selector = sel_name;
5720 /* Build the parameters list for looking up the method.
5721 These are the object itself and the selector. */
5723 if (flag_typed_selectors)
5724 selector = build_typed_selector_reference (sel_name, method_prototype);
5725 else
5726 selector = build_selector_reference (sel_name);
5728 retval = build_objc_method_call (super, method_prototype,
5729 receiver,
5730 selector, method_params);
5732 current_objc_message_selector = 0;
5734 return retval;
5737 /* Build a tree expression to send OBJECT the operation SELECTOR,
5738 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5739 assuming the method has prototype METHOD_PROTOTYPE.
5740 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5741 Use METHOD_PARAMS as list of args to pass to the method.
5742 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5744 static tree
5745 build_objc_method_call (int super_flag, tree method_prototype,
5746 tree lookup_object, tree selector,
5747 tree method_params)
5749 tree sender = (super_flag ? umsg_super_decl :
5750 (!flag_next_runtime || flag_nil_receivers
5751 ? umsg_decl
5752 : umsg_nonnil_decl));
5753 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
5755 /* If a prototype for the method to be called exists, then cast
5756 the sender's return type and arguments to match that of the method.
5757 Otherwise, leave sender as is. */
5758 tree ret_type
5759 = (method_prototype
5760 ? TREE_VALUE (TREE_TYPE (method_prototype))
5761 : objc_object_type);
5762 tree sender_cast
5763 = build_pointer_type
5764 (build_function_type
5765 (ret_type,
5766 get_arg_type_list
5767 (method_prototype, METHOD_REF, super_flag)));
5768 tree method, t;
5770 lookup_object = build_c_cast (rcv_p, lookup_object);
5772 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
5773 lookup_object = save_expr (lookup_object);
5775 if (flag_next_runtime)
5777 /* If we are returning a struct in memory, and the address
5778 of that memory location is passed as a hidden first
5779 argument, then change which messenger entry point this
5780 expr will call. NB: Note that sender_cast remains
5781 unchanged (it already has a struct return type). */
5782 if (!targetm.calls.struct_value_rtx (0, 0)
5783 && (TREE_CODE (ret_type) == RECORD_TYPE
5784 || TREE_CODE (ret_type) == UNION_TYPE)
5785 && targetm.calls.return_in_memory (ret_type, 0))
5786 sender = (super_flag ? umsg_super_stret_decl :
5787 flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
5789 method_params = tree_cons (NULL_TREE, lookup_object,
5790 tree_cons (NULL_TREE, selector,
5791 method_params));
5792 method = build_fold_addr_expr (sender);
5794 else
5796 /* This is the portable (GNU) way. */
5797 tree object;
5799 /* First, call the lookup function to get a pointer to the method,
5800 then cast the pointer, then call it with the method arguments. */
5802 object = (super_flag ? self_decl : lookup_object);
5804 t = tree_cons (NULL_TREE, selector, NULL_TREE);
5805 t = tree_cons (NULL_TREE, lookup_object, t);
5806 method = build_function_call (sender, t);
5808 /* Pass the object to the method. */
5809 method_params = tree_cons (NULL_TREE, object,
5810 tree_cons (NULL_TREE, selector,
5811 method_params));
5814 /* ??? Selector is not at this point something we can use inside
5815 the compiler itself. Set it to garbage for the nonce. */
5816 t = build (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
5817 return build_function_call (t, method_params);
5820 static void
5821 build_protocol_reference (tree p)
5823 tree decl;
5824 const char *proto_name;
5826 /* static struct _objc_protocol _OBJC_PROTOCOL_<mumble>; */
5828 proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5829 decl = start_var_decl (objc_protocol_template, proto_name);
5831 PROTOCOL_FORWARD_DECL (p) = decl;
5834 /* This function is called by the parser when (and only when) a
5835 @protocol() expression is found, in order to compile it. */
5836 tree
5837 objc_build_protocol_expr (tree protoname)
5839 tree expr;
5840 tree p = lookup_protocol (protoname);
5842 if (!p)
5844 error ("cannot find protocol declaration for `%s'",
5845 IDENTIFIER_POINTER (protoname));
5846 return error_mark_node;
5849 if (!PROTOCOL_FORWARD_DECL (p))
5850 build_protocol_reference (p);
5852 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5854 /* ??? Ideally we'd build the reference with objc_protocol_type directly,
5855 if we have it, rather than converting it here. */
5856 expr = convert (objc_protocol_type, expr);
5858 /* The @protocol() expression is being compiled into a pointer to a
5859 statically allocated instance of the Protocol class. To become
5860 usable at runtime, the 'isa' pointer of the instance need to be
5861 fixed up at runtime by the runtime library, to point to the
5862 actual 'Protocol' class. */
5864 /* For the GNU runtime, put the static Protocol instance in the list
5865 of statically allocated instances, so that we make sure that its
5866 'isa' pointer is fixed up at runtime by the GNU runtime library
5867 to point to the Protocol class (at runtime, when loading the
5868 module, the GNU runtime library loops on the statically allocated
5869 instances (as found in the defs field in objc_symtab) and fixups
5870 all the 'isa' pointers of those objects). */
5871 if (! flag_next_runtime)
5873 /* This type is a struct containing the fields of a Protocol
5874 object. (Cfr. objc_protocol_type instead is the type of a pointer
5875 to such a struct). */
5876 tree protocol_struct_type = xref_tag
5877 (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
5878 tree *chain;
5880 /* Look for the list of Protocol statically allocated instances
5881 to fixup at runtime. Create a new list to hold Protocol
5882 statically allocated instances, if the list is not found. At
5883 present there is only another list, holding NSConstantString
5884 static instances to be fixed up at runtime. */
5885 for (chain = &objc_static_instances;
5886 *chain && TREE_VALUE (*chain) != protocol_struct_type;
5887 chain = &TREE_CHAIN (*chain));
5888 if (!*chain)
5890 *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
5891 add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
5892 class_names);
5895 /* Add this statically allocated instance to the Protocol list. */
5896 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
5897 PROTOCOL_FORWARD_DECL (p),
5898 TREE_PURPOSE (*chain));
5902 return expr;
5905 /* This function is called by the parser when a @selector() expression
5906 is found, in order to compile it. It is only called by the parser
5907 and only to compile a @selector(). */
5908 tree
5909 objc_build_selector_expr (tree selnamelist)
5911 tree selname;
5913 /* Obtain the full selector name. */
5914 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5915 /* A unary selector. */
5916 selname = selnamelist;
5917 else if (TREE_CODE (selnamelist) == TREE_LIST)
5918 selname = build_keyword_selector (selnamelist);
5919 else
5920 abort ();
5922 /* If we are required to check @selector() expressions as they
5923 are found, check that the selector has been declared. */
5924 if (warn_undeclared_selector)
5926 /* Look the selector up in the list of all known class and
5927 instance methods (up to this line) to check that the selector
5928 exists. */
5929 hash hsh;
5931 /* First try with instance methods. */
5932 hsh = hash_lookup (nst_method_hash_list, selname);
5934 /* If not found, try with class methods. */
5935 if (!hsh)
5937 hsh = hash_lookup (cls_method_hash_list, selname);
5940 /* If still not found, print out a warning. */
5941 if (!hsh)
5943 warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
5948 if (flag_typed_selectors)
5949 return build_typed_selector_reference (selname, 0);
5950 else
5951 return build_selector_reference (selname);
5954 tree
5955 objc_build_encode_expr (tree type)
5957 tree result;
5958 const char *string;
5960 encode_type (type, obstack_object_size (&util_obstack),
5961 OBJC_ENCODE_INLINE_DEFS);
5962 obstack_1grow (&util_obstack, 0); /* null terminate string */
5963 string = obstack_finish (&util_obstack);
5965 /* Synthesize a string that represents the encoded struct/union. */
5966 result = my_build_string (strlen (string) + 1, string);
5967 obstack_free (&util_obstack, util_firstobj);
5968 return result;
5971 static tree
5972 build_ivar_reference (tree id)
5974 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
5976 /* Historically, a class method that produced objects (factory
5977 method) would assign `self' to the instance that it
5978 allocated. This would effectively turn the class method into
5979 an instance method. Following this assignment, the instance
5980 variables could be accessed. That practice, while safe,
5981 violates the simple rule that a class method should not refer
5982 to an instance variable. It's better to catch the cases
5983 where this is done unknowingly than to support the above
5984 paradigm. */
5985 warning ("instance variable `%s' accessed in class method",
5986 IDENTIFIER_POINTER (id));
5987 self_decl = convert (objc_instance_type, self_decl); /* cast */
5990 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5993 /* Compute a hash value for a given method SEL_NAME. */
5995 static size_t
5996 hash_func (tree sel_name)
5998 const unsigned char *s
5999 = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
6000 size_t h = 0;
6002 while (*s)
6003 h = h * 67 + *s++ - 113;
6004 return h;
6007 static void
6008 hash_init (void)
6010 nst_method_hash_list
6011 = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6012 cls_method_hash_list
6013 = (hash *) ggc_alloc_cleared (SIZEHASHTABLE * sizeof (hash));
6015 /* Initialize the hash table used to hold the constant string objects. */
6016 string_htab = htab_create_ggc (31, string_hash,
6017 string_eq, NULL);
6020 /* WARNING!!!! hash_enter is called with a method, and will peek
6021 inside to find its selector! But hash_lookup is given a selector
6022 directly, and looks for the selector that's inside the found
6023 entry's key (method) for comparison. */
6025 static void
6026 hash_enter (hash *hashlist, tree method)
6028 hash obj;
6029 int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
6031 obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
6032 obj->list = 0;
6033 obj->next = hashlist[slot];
6034 obj->key = method;
6036 hashlist[slot] = obj; /* append to front */
6039 static hash
6040 hash_lookup (hash *hashlist, tree sel_name)
6042 hash target;
6044 target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
6046 while (target)
6048 if (sel_name == METHOD_SEL_NAME (target->key))
6049 return target;
6051 target = target->next;
6053 return 0;
6056 static void
6057 hash_add_attr (hash entry, tree value)
6059 attr obj;
6061 obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
6062 obj->next = entry->list;
6063 obj->value = value;
6065 entry->list = obj; /* append to front */
6068 static tree
6069 lookup_method (tree mchain, tree method)
6071 tree key;
6073 if (TREE_CODE (method) == IDENTIFIER_NODE)
6074 key = method;
6075 else
6076 key = METHOD_SEL_NAME (method);
6078 while (mchain)
6080 if (METHOD_SEL_NAME (mchain) == key)
6081 return mchain;
6083 mchain = TREE_CHAIN (mchain);
6085 return NULL_TREE;
6088 static tree
6089 lookup_method_static (tree interface, tree ident, int is_class)
6091 tree meth = NULL_TREE, root_inter = NULL_TREE;
6092 tree inter = interface;
6094 while (inter)
6096 tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
6097 tree category = inter;
6099 /* First, look up the method in the class itself. */
6100 if ((meth = lookup_method (chain, ident)))
6101 return meth;
6103 /* Failing that, look for the method in each category of the class. */
6104 while ((category = CLASS_CATEGORY_LIST (category)))
6106 chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
6108 /* Check directly in each category. */
6109 if ((meth = lookup_method (chain, ident)))
6110 return meth;
6112 /* Failing that, check in each category's protocols. */
6113 if (CLASS_PROTOCOL_LIST (category))
6115 if ((meth = (lookup_method_in_protocol_list
6116 (CLASS_PROTOCOL_LIST (category), ident, is_class))))
6117 return meth;
6121 /* If not found in categories, check in protocols of the main class. */
6122 if (CLASS_PROTOCOL_LIST (inter))
6124 if ((meth = (lookup_method_in_protocol_list
6125 (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
6126 return meth;
6129 /* Failing that, climb up the inheritance hierarchy. */
6130 root_inter = inter;
6131 inter = lookup_interface (CLASS_SUPER_NAME (inter));
6133 while (inter);
6135 /* If no class (factory) method was found, check if an _instance_
6136 method of the same name exists in the root class. This is what
6137 the Objective-C runtime will do. If an instance method was not
6138 found, return 0. */
6139 return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
6142 /* Add the method to the hash list if it doesn't contain an identical
6143 method already. */
6144 static void
6145 add_method_to_hash_list (hash *hash_list, tree method)
6147 hash hsh;
6149 if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
6151 /* Install on a global chain. */
6152 hash_enter (hash_list, method);
6154 else
6156 /* Check types against those; if different, add to a list. */
6157 attr loop;
6158 int already_there = comp_proto_with_proto (method, hsh->key);
6159 for (loop = hsh->list; !already_there && loop; loop = loop->next)
6160 already_there |= comp_proto_with_proto (method, loop->value);
6161 if (!already_there)
6162 hash_add_attr (hsh, method);
6166 static tree
6167 objc_add_method (tree class, tree method, int is_class)
6169 tree mth;
6171 if (!(mth = lookup_method (is_class
6172 ? CLASS_CLS_METHODS (class)
6173 : CLASS_NST_METHODS (class), method)))
6175 /* put method on list in reverse order */
6176 if (is_class)
6178 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
6179 CLASS_CLS_METHODS (class) = method;
6181 else
6183 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
6184 CLASS_NST_METHODS (class) = method;
6187 else
6189 /* When processing an @interface for a class or category, give hard
6190 errors on methods with identical selectors but differing argument
6191 and/or return types. We do not do this for @implementations, because
6192 C/C++ will do it for us (i.e., there will be duplicate function
6193 definition errors). */
6194 if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
6195 || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
6196 && !comp_proto_with_proto (method, mth))
6197 error ("duplicate declaration of method `%c%s'",
6198 is_class ? '+' : '-',
6199 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
6202 if (is_class)
6203 add_method_to_hash_list (cls_method_hash_list, method);
6204 else
6206 add_method_to_hash_list (nst_method_hash_list, method);
6208 /* Instance methods in root classes (and categories thereof)
6209 may act as class methods as a last resort. We also add
6210 instance methods listed in @protocol declarations to
6211 the class hash table, on the assumption that @protocols
6212 may be adopted by root classes or categories. */
6213 if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
6214 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6215 class = lookup_interface (CLASS_NAME (class));
6217 if (TREE_CODE (class) == PROTOCOL_INTERFACE_TYPE
6218 || !CLASS_SUPER_NAME (class))
6219 add_method_to_hash_list (cls_method_hash_list, method);
6222 return method;
6225 static tree
6226 add_class (tree class)
6228 /* Put interfaces on list in reverse order. */
6229 TREE_CHAIN (class) = interface_chain;
6230 interface_chain = class;
6231 return interface_chain;
6234 static void
6235 add_category (tree class, tree category)
6237 /* Put categories on list in reverse order. */
6238 tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
6240 if (cat)
6242 warning ("duplicate interface declaration for category `%s(%s)'",
6243 IDENTIFIER_POINTER (CLASS_NAME (class)),
6244 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
6246 else
6248 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
6249 CLASS_CATEGORY_LIST (class) = category;
6253 /* Called after parsing each instance variable declaration. Necessary to
6254 preserve typedefs and implement public/private...
6256 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
6258 static tree
6259 add_instance_variable (tree class, int public, tree field_decl)
6261 tree field_type = TREE_TYPE (field_decl);
6262 const char *ivar_name = DECL_NAME (field_decl)
6263 ? IDENTIFIER_POINTER (DECL_NAME (field_decl))
6264 : "<unnamed>";
6266 #ifdef OBJCPLUS
6267 if (TREE_CODE (field_type) == REFERENCE_TYPE)
6269 error ("illegal reference type specified for instance variable `%s'",
6270 ivar_name);
6271 /* Return class as is without adding this ivar. */
6272 return class;
6274 #endif
6276 if (field_type == error_mark_node || !TYPE_SIZE (field_type)
6277 || TYPE_SIZE (field_type) == error_mark_node)
6278 /* 'type[0]' is allowed, but 'type[]' is not! */
6280 error ("instance variable `%s' has unknown size", ivar_name);
6281 /* Return class as is without adding this ivar. */
6282 return class;
6285 #ifdef OBJCPLUS
6286 /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
6287 cannot be ivars; ditto for classes with vtables. */
6288 if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
6289 || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
6291 const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
6292 if(TYPE_POLYMORPHIC_P (field_type)) {
6293 /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
6294 error ("type `%s' has virtual member functions", type_name);
6295 error ("illegal aggregate type `%s' specified for instance variable `%s'",
6296 type_name, ivar_name);
6297 /* Return class as is without adding this ivar. */
6298 return class;
6300 /* user-defined constructors and destructors are not known to Obj-C and
6301 hence will not be called. This may or may not be a problem. */
6302 if (TYPE_NEEDS_CONSTRUCTING (field_type))
6303 warning ("type `%s' has a user-defined constructor", type_name);
6304 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
6305 warning ("type `%s' has a user-defined destructor", type_name);
6306 warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
6308 #endif
6310 /* Overload the public attribute, it is not used for FIELD_DECLs. */
6311 switch (public)
6313 case 0:
6314 TREE_PUBLIC (field_decl) = 0;
6315 TREE_PRIVATE (field_decl) = 0;
6316 TREE_PROTECTED (field_decl) = 1;
6317 break;
6319 case 1:
6320 TREE_PUBLIC (field_decl) = 1;
6321 TREE_PRIVATE (field_decl) = 0;
6322 TREE_PROTECTED (field_decl) = 0;
6323 break;
6325 case 2:
6326 TREE_PUBLIC (field_decl) = 0;
6327 TREE_PRIVATE (field_decl) = 1;
6328 TREE_PROTECTED (field_decl) = 0;
6329 break;
6333 CLASS_RAW_IVARS (class) = chainon (CLASS_RAW_IVARS (class), field_decl);
6335 return class;
6338 static tree
6339 is_ivar (tree decl_chain, tree ident)
6341 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
6342 if (DECL_NAME (decl_chain) == ident)
6343 return decl_chain;
6344 return NULL_TREE;
6347 /* True if the ivar is private and we are not in its implementation. */
6349 static int
6350 is_private (tree decl)
6352 return (TREE_PRIVATE (decl)
6353 && ! is_ivar (CLASS_IVARS (implementation_template),
6354 DECL_NAME (decl)));
6357 /* We have an instance variable reference;, check to see if it is public. */
6360 objc_is_public (tree expr, tree identifier)
6362 tree basetype = TREE_TYPE (expr);
6363 enum tree_code code = TREE_CODE (basetype);
6364 tree decl;
6366 if (code == RECORD_TYPE)
6368 if (TREE_STATIC_TEMPLATE (basetype))
6370 if (!lookup_interface (OBJC_TYPE_NAME (basetype)))
6372 error ("cannot find interface declaration for `%s'",
6373 IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
6374 return 0;
6377 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
6379 if (TREE_PUBLIC (decl))
6380 return 1;
6382 /* Important difference between the Stepstone translator:
6383 all instance variables should be public within the context
6384 of the implementation. */
6385 if (objc_implementation_context
6386 && (((TREE_CODE (objc_implementation_context)
6387 == CLASS_IMPLEMENTATION_TYPE)
6388 || (TREE_CODE (objc_implementation_context)
6389 == CATEGORY_IMPLEMENTATION_TYPE))
6390 && (CLASS_NAME (objc_implementation_context)
6391 == OBJC_TYPE_NAME (basetype))))
6393 int private = is_private (decl);
6395 if (private)
6396 error ("instance variable `%s' is declared private",
6397 IDENTIFIER_POINTER (DECL_NAME (decl)));
6398 return !private;
6401 /* The 2.95.2 compiler sometimes allowed C functions to access
6402 non-@public ivars. We will let this slide for now... */
6403 if (!objc_method_context)
6405 warning ("instance variable `%s' is %s; "
6406 "this will be a hard error in the future",
6407 IDENTIFIER_POINTER (identifier),
6408 TREE_PRIVATE (decl) ? "@private" : "@protected");
6409 return 1;
6412 error ("instance variable `%s' is declared %s",
6413 IDENTIFIER_POINTER (identifier),
6414 TREE_PRIVATE (decl) ? "private" : "protected");
6415 return 0;
6419 else if (objc_implementation_context && (basetype == objc_object_reference))
6421 expr = convert (uprivate_record, expr);
6422 warning ("static access to object of type `id'");
6426 return 1;
6429 /* Make sure all entries in CHAIN are also in LIST. */
6431 static int
6432 check_methods (tree chain, tree list, int mtype)
6434 int first = 1;
6436 while (chain)
6438 if (!lookup_method (list, chain))
6440 if (first)
6442 if (TREE_CODE (objc_implementation_context)
6443 == CLASS_IMPLEMENTATION_TYPE)
6444 warning ("incomplete implementation of class `%s'",
6445 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6446 else if (TREE_CODE (objc_implementation_context)
6447 == CATEGORY_IMPLEMENTATION_TYPE)
6448 warning ("incomplete implementation of category `%s'",
6449 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6450 first = 0;
6453 warning ("method definition for `%c%s' not found",
6454 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6457 chain = TREE_CHAIN (chain);
6460 return first;
6463 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */
6465 static int
6466 conforms_to_protocol (tree class, tree protocol)
6468 if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
6470 tree p = CLASS_PROTOCOL_LIST (class);
6471 while (p && TREE_VALUE (p) != protocol)
6472 p = TREE_CHAIN (p);
6474 if (!p)
6476 tree super = (CLASS_SUPER_NAME (class)
6477 ? lookup_interface (CLASS_SUPER_NAME (class))
6478 : NULL_TREE);
6479 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
6480 if (!tmp)
6481 return 0;
6485 return 1;
6488 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
6489 CONTEXT. This is one of two mechanisms to check protocol integrity. */
6491 static int
6492 check_methods_accessible (tree chain, tree context, int mtype)
6494 int first = 1;
6495 tree list;
6496 tree base_context = context;
6498 while (chain)
6500 context = base_context;
6501 while (context)
6503 if (mtype == '+')
6504 list = CLASS_CLS_METHODS (context);
6505 else
6506 list = CLASS_NST_METHODS (context);
6508 if (lookup_method (list, chain))
6509 break;
6511 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6512 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6513 context = (CLASS_SUPER_NAME (context)
6514 ? lookup_interface (CLASS_SUPER_NAME (context))
6515 : NULL_TREE);
6517 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6518 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6519 context = (CLASS_NAME (context)
6520 ? lookup_interface (CLASS_NAME (context))
6521 : NULL_TREE);
6522 else
6523 abort ();
6526 if (context == NULL_TREE)
6528 if (first)
6530 if (TREE_CODE (objc_implementation_context)
6531 == CLASS_IMPLEMENTATION_TYPE)
6532 warning ("incomplete implementation of class `%s'",
6533 IDENTIFIER_POINTER
6534 (CLASS_NAME (objc_implementation_context)));
6535 else if (TREE_CODE (objc_implementation_context)
6536 == CATEGORY_IMPLEMENTATION_TYPE)
6537 warning ("incomplete implementation of category `%s'",
6538 IDENTIFIER_POINTER
6539 (CLASS_SUPER_NAME (objc_implementation_context)));
6540 first = 0;
6542 warning ("method definition for `%c%s' not found",
6543 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6546 chain = TREE_CHAIN (chain); /* next method... */
6548 return first;
6551 /* Check whether the current interface (accessible via
6552 'objc_implementation_context') actually implements protocol P, along
6553 with any protocols that P inherits. */
6555 static void
6556 check_protocol (tree p, const char *type, const char *name)
6558 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6560 int f1, f2;
6562 /* Ensure that all protocols have bodies! */
6563 if (warn_protocol)
6565 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6566 CLASS_CLS_METHODS (objc_implementation_context),
6567 '+');
6568 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6569 CLASS_NST_METHODS (objc_implementation_context),
6570 '-');
6572 else
6574 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6575 objc_implementation_context,
6576 '+');
6577 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6578 objc_implementation_context,
6579 '-');
6582 if (!f1 || !f2)
6583 warning ("%s `%s' does not fully implement the `%s' protocol",
6584 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6587 /* Check protocols recursively. */
6588 if (PROTOCOL_LIST (p))
6590 tree subs = PROTOCOL_LIST (p);
6591 tree super_class =
6592 lookup_interface (CLASS_SUPER_NAME (implementation_template));
6594 while (subs)
6596 tree sub = TREE_VALUE (subs);
6598 /* If the superclass does not conform to the protocols
6599 inherited by P, then we must! */
6600 if (!super_class || !conforms_to_protocol (super_class, sub))
6601 check_protocol (sub, type, name);
6602 subs = TREE_CHAIN (subs);
6607 /* Check whether the current interface (accessible via
6608 'objc_implementation_context') actually implements the protocols listed
6609 in PROTO_LIST. */
6611 static void
6612 check_protocols (tree proto_list, const char *type, const char *name)
6614 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6616 tree p = TREE_VALUE (proto_list);
6618 check_protocol (p, type, name);
6622 /* Make sure that the class CLASS_NAME is defined
6623 CODE says which kind of thing CLASS_NAME ought to be.
6624 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6625 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
6627 static tree
6628 start_class (enum tree_code code, tree class_name, tree super_name,
6629 tree protocol_list)
6631 tree class, decl;
6633 #ifdef OBJCPLUS
6634 if (current_namespace != global_namespace) {
6635 error ("Objective-C declarations may only appear in global scope");
6637 #endif /* OBJCPLUS */
6639 if (objc_implementation_context)
6641 warning ("`@end' missing in implementation context");
6642 finish_class (objc_implementation_context);
6643 objc_ivar_chain = NULL_TREE;
6644 objc_implementation_context = NULL_TREE;
6647 class = make_node (code);
6648 TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
6650 /* Check for existence of the super class, if one was specified. */
6651 if ((code == CLASS_INTERFACE_TYPE || code == CLASS_IMPLEMENTATION_TYPE)
6652 && super_name && !objc_is_class_name (super_name))
6654 error ("cannot find interface declaration for `%s', superclass of `%s'",
6655 IDENTIFIER_POINTER (super_name),
6656 IDENTIFIER_POINTER (class_name));
6657 super_name = NULL_TREE;
6660 CLASS_NAME (class) = class_name;
6661 CLASS_SUPER_NAME (class) = super_name;
6662 CLASS_CLS_METHODS (class) = NULL_TREE;
6664 if (! objc_is_class_name (class_name)
6665 && (decl = lookup_name (class_name)))
6667 error ("`%s' redeclared as different kind of symbol",
6668 IDENTIFIER_POINTER (class_name));
6669 error ("%Jprevious declaration of '%D'",
6670 decl, decl);
6673 if (code == CLASS_IMPLEMENTATION_TYPE)
6676 tree chain;
6678 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6679 if (TREE_VALUE (chain) == class_name)
6681 error ("reimplementation of class `%s'",
6682 IDENTIFIER_POINTER (class_name));
6683 return error_mark_node;
6685 implemented_classes = tree_cons (NULL_TREE, class_name,
6686 implemented_classes);
6689 /* Reset for multiple classes per file. */
6690 method_slot = 0;
6692 objc_implementation_context = class;
6694 /* Lookup the interface for this implementation. */
6696 if (!(implementation_template = lookup_interface (class_name)))
6698 warning ("cannot find interface declaration for `%s'",
6699 IDENTIFIER_POINTER (class_name));
6700 add_class (implementation_template = objc_implementation_context);
6703 /* If a super class has been specified in the implementation,
6704 insure it conforms to the one specified in the interface. */
6706 if (super_name
6707 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6709 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6710 const char *const name =
6711 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6712 error ("conflicting super class name `%s'",
6713 IDENTIFIER_POINTER (super_name));
6714 error ("previous declaration of `%s'", name);
6717 else if (! super_name)
6719 CLASS_SUPER_NAME (objc_implementation_context)
6720 = CLASS_SUPER_NAME (implementation_template);
6724 else if (code == CLASS_INTERFACE_TYPE)
6726 if (lookup_interface (class_name))
6727 #ifdef OBJCPLUS
6728 error ("duplicate interface declaration for class `%s'",
6729 #else
6730 warning ("duplicate interface declaration for class `%s'",
6731 #endif
6732 IDENTIFIER_POINTER (class_name));
6733 else
6734 add_class (class);
6736 if (protocol_list)
6737 CLASS_PROTOCOL_LIST (class)
6738 = lookup_and_install_protocols (protocol_list);
6741 else if (code == CATEGORY_INTERFACE_TYPE)
6743 tree class_category_is_assoc_with;
6745 /* For a category, class_name is really the name of the class that
6746 the following set of methods will be associated with. We must
6747 find the interface so that can derive the objects template. */
6749 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6751 error ("cannot find interface declaration for `%s'",
6752 IDENTIFIER_POINTER (class_name));
6753 exit (FATAL_EXIT_CODE);
6755 else
6756 add_category (class_category_is_assoc_with, class);
6758 if (protocol_list)
6759 CLASS_PROTOCOL_LIST (class)
6760 = lookup_and_install_protocols (protocol_list);
6763 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6765 /* Reset for multiple classes per file. */
6766 method_slot = 0;
6768 objc_implementation_context = class;
6770 /* For a category, class_name is really the name of the class that
6771 the following set of methods will be associated with. We must
6772 find the interface so that can derive the objects template. */
6774 if (!(implementation_template = lookup_interface (class_name)))
6776 error ("cannot find interface declaration for `%s'",
6777 IDENTIFIER_POINTER (class_name));
6778 exit (FATAL_EXIT_CODE);
6781 return class;
6784 static tree
6785 continue_class (tree class)
6787 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6788 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6790 struct imp_entry *imp_entry;
6791 tree ivar_context;
6793 /* Check consistency of the instance variables. */
6795 if (CLASS_RAW_IVARS (class))
6796 check_ivars (implementation_template, class);
6798 /* code generation */
6800 #ifdef OBJCPLUS
6801 push_lang_context (lang_name_c);
6802 #endif
6804 ivar_context = build_private_template (implementation_template);
6806 imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6808 imp_entry->next = imp_list;
6809 imp_entry->imp_context = class;
6810 imp_entry->imp_template = implementation_template;
6812 synth_forward_declarations ();
6813 imp_entry->class_decl = UOBJC_CLASS_decl;
6814 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6816 /* Append to front and increment count. */
6817 imp_list = imp_entry;
6818 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6819 imp_count++;
6820 else
6821 cat_count++;
6823 #ifdef OBJCPLUS
6824 pop_lang_context ();
6825 #endif /* OBJCPLUS */
6827 return ivar_context;
6830 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6832 #ifdef OBJCPLUS
6833 push_lang_context (lang_name_c);
6834 #endif /* OBJCPLUS */
6836 if (!CLASS_STATIC_TEMPLATE (class))
6838 tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
6839 finish_struct (record, get_class_ivars (class), NULL_TREE);
6840 CLASS_STATIC_TEMPLATE (class) = record;
6842 /* Mark this record as a class template for static typing. */
6843 TREE_STATIC_TEMPLATE (record) = 1;
6846 #ifdef OBJCPLUS
6847 pop_lang_context ();
6848 #endif /* OBJCPLUS */
6850 return NULL_TREE;
6853 else
6854 return error_mark_node;
6857 /* This is called once we see the "@end" in an interface/implementation. */
6859 static void
6860 finish_class (tree class)
6862 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6864 /* All code generation is done in finish_objc. */
6866 if (implementation_template != objc_implementation_context)
6868 /* Ensure that all method listed in the interface contain bodies. */
6869 check_methods (CLASS_CLS_METHODS (implementation_template),
6870 CLASS_CLS_METHODS (objc_implementation_context), '+');
6871 check_methods (CLASS_NST_METHODS (implementation_template),
6872 CLASS_NST_METHODS (objc_implementation_context), '-');
6874 if (CLASS_PROTOCOL_LIST (implementation_template))
6875 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6876 "class",
6877 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6881 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6883 tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
6885 if (category)
6887 /* Ensure all method listed in the interface contain bodies. */
6888 check_methods (CLASS_CLS_METHODS (category),
6889 CLASS_CLS_METHODS (objc_implementation_context), '+');
6890 check_methods (CLASS_NST_METHODS (category),
6891 CLASS_NST_METHODS (objc_implementation_context), '-');
6893 if (CLASS_PROTOCOL_LIST (category))
6894 check_protocols (CLASS_PROTOCOL_LIST (category),
6895 "category",
6896 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6900 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6902 tree decl;
6903 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6904 char *string = (char *) alloca (strlen (class_name) + 3);
6906 /* extern struct objc_object *_<my_name>; */
6908 sprintf (string, "_%s", class_name);
6910 decl = build_decl (VAR_DECL, get_identifier (string),
6911 build_pointer_type (objc_object_reference));
6912 DECL_EXTERNAL (decl) = 1;
6913 lang_hooks.decls.pushdecl (decl);
6914 finish_decl (decl, NULL_TREE, NULL_TREE);
6918 static tree
6919 add_protocol (tree protocol)
6921 /* Put protocol on list in reverse order. */
6922 TREE_CHAIN (protocol) = protocol_chain;
6923 protocol_chain = protocol;
6924 return protocol_chain;
6927 static tree
6928 lookup_protocol (tree ident)
6930 tree chain;
6932 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6933 if (ident == PROTOCOL_NAME (chain))
6934 return chain;
6936 return NULL_TREE;
6939 /* This function forward declares the protocols named by NAMES. If
6940 they are already declared or defined, the function has no effect. */
6942 void
6943 objc_declare_protocols (tree names)
6945 tree list;
6947 #ifdef OBJCPLUS
6948 if (current_namespace != global_namespace) {
6949 error ("Objective-C declarations may only appear in global scope");
6951 #endif /* OBJCPLUS */
6953 for (list = names; list; list = TREE_CHAIN (list))
6955 tree name = TREE_VALUE (list);
6957 if (lookup_protocol (name) == NULL_TREE)
6959 tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6961 TYPE_LANG_SLOT_1 (protocol)
6962 = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
6963 PROTOCOL_NAME (protocol) = name;
6964 PROTOCOL_LIST (protocol) = NULL_TREE;
6965 add_protocol (protocol);
6966 PROTOCOL_DEFINED (protocol) = 0;
6967 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6972 static tree
6973 start_protocol (enum tree_code code, tree name, tree list)
6975 tree protocol;
6977 #ifdef OBJCPLUS
6978 if (current_namespace != global_namespace) {
6979 error ("Objective-C declarations may only appear in global scope");
6981 #endif /* OBJCPLUS */
6983 protocol = lookup_protocol (name);
6985 if (!protocol)
6987 protocol = make_node (code);
6988 TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
6990 PROTOCOL_NAME (protocol) = name;
6991 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6992 add_protocol (protocol);
6993 PROTOCOL_DEFINED (protocol) = 1;
6994 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6996 check_protocol_recursively (protocol, list);
6998 else if (! PROTOCOL_DEFINED (protocol))
7000 PROTOCOL_DEFINED (protocol) = 1;
7001 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
7003 check_protocol_recursively (protocol, list);
7005 else
7007 warning ("duplicate declaration for protocol `%s'",
7008 IDENTIFIER_POINTER (name));
7010 return protocol;
7014 /* "Encode" a data type into a string, which grows in util_obstack.
7015 ??? What is the FORMAT? Someone please document this! */
7017 static void
7018 encode_type_qualifiers (tree declspecs)
7020 tree spec;
7022 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
7024 if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
7025 obstack_1grow (&util_obstack, 'n');
7026 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
7027 obstack_1grow (&util_obstack, 'N');
7028 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
7029 obstack_1grow (&util_obstack, 'o');
7030 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
7031 obstack_1grow (&util_obstack, 'O');
7032 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
7033 obstack_1grow (&util_obstack, 'R');
7034 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
7035 obstack_1grow (&util_obstack, 'V');
7039 /* Encode a pointer type. */
7041 static void
7042 encode_pointer (tree type, int curtype, int format)
7044 tree pointer_to = TREE_TYPE (type);
7046 if (TREE_CODE (pointer_to) == RECORD_TYPE)
7048 if (OBJC_TYPE_NAME (pointer_to)
7049 && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
7051 const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
7053 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
7055 obstack_1grow (&util_obstack, '@');
7056 return;
7058 else if (TREE_STATIC_TEMPLATE (pointer_to))
7060 if (generating_instance_variables)
7062 obstack_1grow (&util_obstack, '@');
7063 obstack_1grow (&util_obstack, '"');
7064 obstack_grow (&util_obstack, name, strlen (name));
7065 obstack_1grow (&util_obstack, '"');
7066 return;
7068 else
7070 obstack_1grow (&util_obstack, '@');
7071 return;
7074 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
7076 obstack_1grow (&util_obstack, '#');
7077 return;
7079 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
7081 obstack_1grow (&util_obstack, ':');
7082 return;
7086 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
7087 && TYPE_MODE (pointer_to) == QImode)
7089 tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
7090 ? OBJC_TYPE_NAME (pointer_to)
7091 : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
7093 if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
7095 /* It appears that "r*" means "const char *" rather than
7096 "char *const". */
7097 if (TYPE_READONLY (pointer_to))
7098 obstack_1grow (&util_obstack, 'r');
7100 obstack_1grow (&util_obstack, '*');
7101 return;
7105 /* We have a type that does not get special treatment. */
7107 /* NeXT extension */
7108 obstack_1grow (&util_obstack, '^');
7109 encode_type (pointer_to, curtype, format);
7112 static void
7113 encode_array (tree type, int curtype, int format)
7115 tree an_int_cst = TYPE_SIZE (type);
7116 tree array_of = TREE_TYPE (type);
7117 char buffer[40];
7119 /* An incomplete array is treated like a pointer. */
7120 if (an_int_cst == NULL)
7122 encode_pointer (type, curtype, format);
7123 return;
7126 sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
7127 (TREE_INT_CST_LOW (an_int_cst)
7128 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7130 obstack_grow (&util_obstack, buffer, strlen (buffer));
7131 encode_type (array_of, curtype, format);
7132 obstack_1grow (&util_obstack, ']');
7133 return;
7136 static void
7137 encode_aggregate_within (tree type, int curtype, int format, int left,
7138 int right)
7140 tree name;
7141 /* NB: aggregates that are pointed to have slightly different encoding
7142 rules in that you never encode the names of instance variables. */
7143 int pointed_to
7144 = (obstack_object_size (&util_obstack) > 0
7145 && *(obstack_next_free (&util_obstack) - 1) == '^');
7146 int inline_contents
7147 = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
7148 && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
7150 /* Traverse struct aliases; it is important to get the
7151 original struct and its tag name (if any). */
7152 type = TYPE_MAIN_VARIANT (type);
7153 name = OBJC_TYPE_NAME (type);
7154 /* Open parenth/bracket. */
7155 obstack_1grow (&util_obstack, left);
7157 /* Encode the struct/union tag name, or '?' if a tag was
7158 not provided. Typedef aliases do not qualify. */
7159 if (name && TREE_CODE (name) == IDENTIFIER_NODE
7160 #ifdef OBJCPLUS
7161 /* Did this struct have a tag? */
7162 && !TYPE_WAS_ANONYMOUS (type)
7163 #endif
7165 obstack_grow (&util_obstack,
7166 IDENTIFIER_POINTER (name),
7167 strlen (IDENTIFIER_POINTER (name)));
7168 else
7169 obstack_1grow (&util_obstack, '?');
7171 /* Encode the types (and possibly names) of the inner fields,
7172 if required. */
7173 if (inline_contents)
7175 tree fields = TYPE_FIELDS (type);
7177 obstack_1grow (&util_obstack, '=');
7178 for (; fields; fields = TREE_CHAIN (fields))
7180 #ifdef OBJCPLUS
7181 /* C++ static members, and things that are not fields at all,
7182 should not appear in the encoding. */
7183 if (TREE_CODE (fields) != FIELD_DECL || TREE_STATIC (fields))
7184 continue;
7185 #endif
7186 if (generating_instance_variables && !pointed_to)
7188 tree fname = DECL_NAME (fields);
7190 obstack_1grow (&util_obstack, '"');
7191 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
7192 obstack_grow (&util_obstack,
7193 IDENTIFIER_POINTER (fname),
7194 strlen (IDENTIFIER_POINTER (fname)));
7195 obstack_1grow (&util_obstack, '"');
7197 encode_field_decl (fields, curtype, format);
7200 /* Close parenth/bracket. */
7201 obstack_1grow (&util_obstack, right);
7204 static void
7205 encode_aggregate (tree type, int curtype, int format)
7207 enum tree_code code = TREE_CODE (type);
7209 switch (code)
7211 case RECORD_TYPE:
7213 encode_aggregate_within (type, curtype, format, '{', '}');
7214 break;
7216 case UNION_TYPE:
7218 encode_aggregate_within (type, curtype, format, '(', ')');
7219 break;
7222 case ENUMERAL_TYPE:
7223 obstack_1grow (&util_obstack, 'i');
7224 break;
7226 default:
7227 break;
7231 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
7232 field type. */
7234 static void
7235 encode_next_bitfield (int width)
7237 char buffer[40];
7238 sprintf (buffer, "b%d", width);
7239 obstack_grow (&util_obstack, buffer, strlen (buffer));
7242 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
7243 static void
7244 encode_type (tree type, int curtype, int format)
7246 enum tree_code code = TREE_CODE (type);
7247 char c;
7249 if (TYPE_READONLY (type))
7250 obstack_1grow (&util_obstack, 'r');
7252 if (code == INTEGER_TYPE)
7254 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7256 case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
7257 case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
7258 case 32:
7259 if (type == long_unsigned_type_node
7260 || type == long_integer_type_node)
7261 c = TYPE_UNSIGNED (type) ? 'L' : 'l';
7262 else
7263 c = TYPE_UNSIGNED (type) ? 'I' : 'i';
7264 break;
7265 case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
7266 default: abort ();
7268 obstack_1grow (&util_obstack, c);
7271 else if (code == REAL_TYPE)
7273 /* Floating point types. */
7274 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
7276 case 32: c = 'f'; break;
7277 case 64:
7278 case 128: c = 'd'; break;
7279 default: abort ();
7281 obstack_1grow (&util_obstack, c);
7284 else if (code == VOID_TYPE)
7285 obstack_1grow (&util_obstack, 'v');
7287 else if (code == BOOLEAN_TYPE)
7288 obstack_1grow (&util_obstack, 'B');
7290 else if (code == ARRAY_TYPE)
7291 encode_array (type, curtype, format);
7293 else if (code == POINTER_TYPE)
7294 encode_pointer (type, curtype, format);
7296 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
7297 encode_aggregate (type, curtype, format);
7299 else if (code == FUNCTION_TYPE) /* '?' */
7300 obstack_1grow (&util_obstack, '?');
7303 static void
7304 encode_gnu_bitfield (int position, tree type, int size)
7306 enum tree_code code = TREE_CODE (type);
7307 char buffer[40];
7308 char charType = '?';
7310 if (code == INTEGER_TYPE)
7312 if (integer_zerop (TYPE_MIN_VALUE (type)))
7314 /* Unsigned integer types. */
7316 if (TYPE_MODE (type) == QImode)
7317 charType = 'C';
7318 else if (TYPE_MODE (type) == HImode)
7319 charType = 'S';
7320 else if (TYPE_MODE (type) == SImode)
7322 if (type == long_unsigned_type_node)
7323 charType = 'L';
7324 else
7325 charType = 'I';
7327 else if (TYPE_MODE (type) == DImode)
7328 charType = 'Q';
7331 else
7332 /* Signed integer types. */
7334 if (TYPE_MODE (type) == QImode)
7335 charType = 'c';
7336 else if (TYPE_MODE (type) == HImode)
7337 charType = 's';
7338 else if (TYPE_MODE (type) == SImode)
7340 if (type == long_integer_type_node)
7341 charType = 'l';
7342 else
7343 charType = 'i';
7346 else if (TYPE_MODE (type) == DImode)
7347 charType = 'q';
7350 else if (code == ENUMERAL_TYPE)
7351 charType = 'i';
7352 else
7353 abort ();
7355 sprintf (buffer, "b%d%c%d", position, charType, size);
7356 obstack_grow (&util_obstack, buffer, strlen (buffer));
7359 static void
7360 encode_field_decl (tree field_decl, int curtype, int format)
7362 tree type;
7364 #ifdef OBJCPLUS
7365 /* C++ static members, and things that are not fields at all,
7366 should not appear in the encoding. */
7367 if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
7368 return;
7369 #endif
7371 type = TREE_TYPE (field_decl);
7373 /* Generate the bitfield typing information, if needed. Note the difference
7374 between GNU and NeXT runtimes. */
7375 if (DECL_BIT_FIELD_TYPE (field_decl))
7377 int size = tree_low_cst (DECL_SIZE (field_decl), 1);
7379 if (flag_next_runtime)
7380 encode_next_bitfield (size);
7381 else
7382 encode_gnu_bitfield (int_bit_position (field_decl),
7383 DECL_BIT_FIELD_TYPE (field_decl), size);
7385 else
7386 encode_type (TREE_TYPE (field_decl), curtype, format);
7389 static GTY(()) tree objc_parmlist = NULL_TREE;
7391 /* Append PARM to a list of formal parameters of a method, making a necessary
7392 array-to-pointer adjustment along the way. */
7394 static void
7395 objc_push_parm (tree parm)
7397 /* Convert array parameters of unknown size into pointers. */
7398 if (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE
7399 && !TYPE_SIZE (TREE_TYPE (parm)))
7400 TREE_TYPE (parm) = build_pointer_type (TREE_TYPE (TREE_TYPE (parm)));
7402 objc_parmlist = chainon (objc_parmlist, parm);
7405 /* Retrieve the formal parameter list constructed via preceding calls to
7406 objc_push_parm(). */
7408 #ifdef OBJCPLUS
7409 static tree
7410 objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
7411 #else
7412 static struct c_arg_info *
7413 objc_get_parm_info (int have_ellipsis)
7414 #endif
7416 #ifdef OBJCPLUS
7417 tree parm_info = objc_parmlist;
7418 objc_parmlist = NULL_TREE;
7420 return parm_info;
7421 #else
7422 tree parm_info = objc_parmlist;
7423 struct c_arg_info *arg_info;
7424 /* The C front-end requires an elaborate song and dance at
7425 this point. */
7426 push_scope ();
7427 declare_parm_level ();
7428 while (parm_info)
7430 tree next = TREE_CHAIN (parm_info);
7432 TREE_CHAIN (parm_info) = NULL_TREE;
7433 pushdecl (parm_info);
7434 parm_info = next;
7436 arg_info = get_parm_info (have_ellipsis);
7437 pop_scope ();
7438 objc_parmlist = NULL_TREE;
7439 return arg_info;
7440 #endif
7443 /* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
7444 method definitions. In the case of instance methods, we can be more
7445 specific as to the type of 'self'. */
7447 static void
7448 synth_self_and_ucmd_args (void)
7450 tree self_type;
7452 if (objc_method_context
7453 && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7454 self_type = objc_instance_type;
7455 else
7456 /* Really a `struct objc_class *'. However, we allow people to
7457 assign to self, which changes its type midstream. */
7458 self_type = objc_object_type;
7460 /* id self; */
7461 objc_push_parm (build_decl (PARM_DECL, self_id, self_type));
7463 /* SEL _cmd; */
7464 objc_push_parm (build_decl (PARM_DECL, ucmd_id, objc_selector_type));
7467 /* Transform an Objective-C method definition into a static C function
7468 definition, synthesizing the first two arguments, "self" and "_cmd",
7469 in the process. */
7471 static void
7472 start_method_def (tree method)
7474 tree parmlist;
7475 #ifdef OBJCPLUS
7476 tree parm_info;
7477 #else
7478 struct c_arg_info *parm_info;
7479 #endif
7480 int have_ellipsis = 0;
7482 /* Required to implement _msgSuper. */
7483 objc_method_context = method;
7484 UOBJC_SUPER_decl = NULL_TREE;
7486 /* Generate prototype declarations for arguments..."new-style". */
7487 synth_self_and_ucmd_args ();
7489 /* Generate argument declarations if a keyword_decl. */
7490 parmlist = METHOD_SEL_ARGS (method);
7491 while (parmlist)
7493 tree parm = build_decl (PARM_DECL, KEYWORD_ARG_NAME (parmlist),
7494 TREE_VALUE (TREE_TYPE (parmlist)));
7496 objc_push_parm (parm);
7497 parmlist = TREE_CHAIN (parmlist);
7500 if (METHOD_ADD_ARGS (method))
7502 tree akey;
7504 for (akey = TREE_CHAIN (METHOD_ADD_ARGS (method));
7505 akey; akey = TREE_CHAIN (akey))
7507 objc_push_parm (TREE_VALUE (akey));
7510 if (TREE_OVERFLOW (METHOD_ADD_ARGS (method)))
7511 have_ellipsis = 1;
7514 parm_info = objc_get_parm_info (have_ellipsis);
7516 really_start_method (objc_method_context, parm_info);
7519 static void
7520 warn_with_method (const char *message, int mtype, tree method)
7522 /* Add a readable method name to the warning. */
7523 warning ("%J%s `%c%s'", method,
7524 message, mtype, gen_method_decl (method));
7527 /* Return 1 if TYPE1 is equivalent to TYPE2
7528 for purposes of method overloading. */
7530 static int
7531 objc_types_are_equivalent (tree type1, tree type2)
7533 if (type1 == type2)
7534 return 1;
7536 /* Strip away indirections. */
7537 while ((TREE_CODE (type1) == ARRAY_TYPE || TREE_CODE (type1) == POINTER_TYPE)
7538 && (TREE_CODE (type1) == TREE_CODE (type2)))
7539 type1 = TREE_TYPE (type1), type2 = TREE_TYPE (type2);
7540 if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
7541 return 0;
7543 type1 = TYPE_PROTOCOL_LIST (type1);
7544 type2 = TYPE_PROTOCOL_LIST (type2);
7545 if (list_length (type1) == list_length (type2))
7547 for (; type2; type2 = TREE_CHAIN (type2))
7548 if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
7549 return 0;
7550 return 1;
7552 return 0;
7555 /* Return 1 if PROTO1 is equivalent to PROTO2
7556 for purposes of method overloading. */
7558 static int
7559 comp_proto_with_proto (tree proto1, tree proto2)
7561 tree type1, type2;
7563 /* The following test is needed in case there are hashing
7564 collisions. */
7565 if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
7566 return 0;
7568 /* Compare return types. */
7569 type1 = TREE_VALUE (TREE_TYPE (proto1));
7570 type2 = TREE_VALUE (TREE_TYPE (proto2));
7572 if (!objc_types_are_equivalent (type1, type2))
7573 return 0;
7575 /* Compare argument types. */
7576 for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
7577 type2 = get_arg_type_list (proto2, METHOD_REF, 0);
7578 type1 && type2;
7579 type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
7581 if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
7582 return 0;
7585 return (!type1 && !type2);
7588 /* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
7589 this occurs. ObjC method dispatches are _not_ like C++ virtual
7590 member function dispatches, and we account for the difference here. */
7591 tree
7592 #ifdef OBJCPLUS
7593 objc_fold_obj_type_ref (tree ref, tree known_type)
7594 #else
7595 objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
7596 tree known_type ATTRIBUTE_UNUSED)
7597 #endif
7599 #ifdef OBJCPLUS
7600 tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
7602 /* If the receiver does not have virtual member functions, there
7603 is nothing we can (or need to) do here. */
7604 if (!v)
7605 return NULL_TREE;
7607 /* Let C++ handle C++ virtual functions. */
7608 return cp_fold_obj_type_ref (ref, known_type);
7609 #else
7610 /* For plain ObjC, we currently do not need to do anything. */
7611 return NULL_TREE;
7612 #endif
7615 static void
7616 objc_start_function (tree name, tree type, tree attrs,
7617 #ifdef OBJCPLUS
7618 tree params
7619 #else
7620 struct c_arg_info *params
7621 #endif
7624 tree fndecl = build_decl (FUNCTION_DECL, name, type);
7626 #ifdef OBJCPLUS
7627 DECL_ARGUMENTS (fndecl) = params;
7628 #endif
7629 DECL_INITIAL (fndecl) = error_mark_node;
7630 DECL_EXTERNAL (fndecl) = 0;
7631 TREE_STATIC (fndecl) = 1;
7633 #ifdef OBJCPLUS
7634 retrofit_lang_decl (fndecl);
7635 cplus_decl_attributes (&fndecl, attrs, 0);
7636 start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
7637 #else
7638 decl_attributes (&fndecl, attrs, 0);
7639 announce_function (fndecl);
7640 current_function_decl = pushdecl (fndecl);
7641 push_scope ();
7642 declare_parm_level ();
7643 DECL_RESULT (current_function_decl)
7644 = build_decl (RESULT_DECL, NULL_TREE,
7645 TREE_TYPE (TREE_TYPE (current_function_decl)));
7646 start_fname_decls ();
7647 store_parm_decls_from (params);
7648 #endif
7650 TREE_USED (current_function_decl) = 1;
7653 /* - Generate an identifier for the function. the format is "_n_cls",
7654 where 1 <= n <= nMethods, and cls is the name the implementation we
7655 are processing.
7656 - Install the return type from the method declaration.
7657 - If we have a prototype, check for type consistency. */
7659 static void
7660 really_start_method (tree method,
7661 #ifdef OBJCPLUS
7662 tree parmlist
7663 #else
7664 struct c_arg_info *parmlist
7665 #endif
7668 tree ret_type, meth_type;
7669 tree method_id;
7670 const char *sel_name, *class_name, *cat_name;
7671 char *buf;
7673 /* Synth the storage class & assemble the return type. */
7674 ret_type = TREE_VALUE (TREE_TYPE (method));
7676 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7677 class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7678 cat_name = ((TREE_CODE (objc_implementation_context)
7679 == CLASS_IMPLEMENTATION_TYPE)
7680 ? NULL
7681 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7682 method_slot++;
7684 /* Make sure this is big enough for any plausible method label. */
7685 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7686 + (cat_name ? strlen (cat_name) : 0));
7688 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7689 class_name, cat_name, sel_name, method_slot);
7691 method_id = get_identifier (buf);
7693 #ifdef OBJCPLUS
7694 /* Objective-C methods cannot be overloaded, so we don't need
7695 the type encoding appended. It looks bad anyway... */
7696 push_lang_context (lang_name_c);
7697 #endif
7699 meth_type
7700 = build_function_type (ret_type,
7701 get_arg_type_list (method, METHOD_DEF, 0));
7702 objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
7704 /* Set self_decl from the first argument. */
7705 self_decl = DECL_ARGUMENTS (current_function_decl);
7707 /* Suppress unused warnings. */
7708 TREE_USED (self_decl) = 1;
7709 TREE_USED (TREE_CHAIN (self_decl)) = 1;
7710 #ifdef OBJCPLUS
7711 pop_lang_context ();
7712 #endif
7714 METHOD_DEFINITION (method) = current_function_decl;
7716 /* Check consistency...start_function, pushdecl, duplicate_decls. */
7718 if (implementation_template != objc_implementation_context)
7720 tree proto
7721 = lookup_method_static (implementation_template,
7722 METHOD_SEL_NAME (method),
7723 TREE_CODE (method) == CLASS_METHOD_DECL);
7725 if (proto)
7727 if (!comp_proto_with_proto (method, proto))
7729 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7731 warn_with_method ("conflicting types for", type, method);
7732 warn_with_method ("previous declaration of", type, proto);
7735 else
7737 /* We have a method @implementation even though we did not
7738 see a corresponding @interface declaration (which is allowed
7739 by Objective-C rules). Go ahead and place the method in
7740 the @interface anyway, so that message dispatch lookups
7741 will see it. */
7742 tree interface = implementation_template;
7744 if (TREE_CODE (objc_implementation_context)
7745 == CATEGORY_IMPLEMENTATION_TYPE)
7746 interface = lookup_category
7747 (interface,
7748 CLASS_SUPER_NAME (objc_implementation_context));
7750 if (interface)
7751 objc_add_method (interface, copy_node (method),
7752 TREE_CODE (method) == CLASS_METHOD_DECL);
7757 static void *UOBJC_SUPER_scope = 0;
7759 /* _n_Method (id self, SEL sel, ...)
7761 struct objc_super _S;
7762 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7763 } */
7765 static tree
7766 get_super_receiver (void)
7768 if (objc_method_context)
7770 tree super_expr, super_expr_list;
7772 if (!UOBJC_SUPER_decl)
7774 UOBJC_SUPER_decl = build_decl (VAR_DECL, get_identifier (TAG_SUPER),
7775 objc_super_template);
7776 /* This prevents `unused variable' warnings when compiling with -Wall. */
7777 TREE_USED (UOBJC_SUPER_decl) = 1;
7778 lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
7779 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7780 UOBJC_SUPER_scope = objc_get_current_scope ();
7783 /* Set receiver to self. */
7784 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7785 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7786 super_expr_list = super_expr;
7788 /* Set class to begin searching. */
7789 super_expr = build_component_ref (UOBJC_SUPER_decl,
7790 get_identifier ("super_class"));
7792 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7794 /* [_cls, __cls]Super are "pre-built" in
7795 synth_forward_declarations. */
7797 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7798 ((TREE_CODE (objc_method_context)
7799 == INSTANCE_METHOD_DECL)
7800 ? ucls_super_ref
7801 : uucls_super_ref));
7804 else
7805 /* We have a category. */
7807 tree super_name = CLASS_SUPER_NAME (implementation_template);
7808 tree super_class;
7810 /* Barf if super used in a category of Object. */
7811 if (!super_name)
7813 error ("no super class declared in interface for `%s'",
7814 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7815 return error_mark_node;
7818 if (flag_next_runtime && !flag_zero_link)
7820 super_class = objc_get_class_reference (super_name);
7821 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7822 /* If we are in a class method, we must retrieve the
7823 _metaclass_ for the current class, pointed at by
7824 the class's "isa" pointer. The following assumes that
7825 "isa" is the first ivar in a class (which it must be). */
7826 super_class
7827 = build_indirect_ref
7828 (build_c_cast (build_pointer_type (objc_class_type),
7829 super_class), "unary *");
7831 else
7833 add_class_reference (super_name);
7834 super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7835 ? objc_get_class_decl : objc_get_meta_class_decl);
7836 assemble_external (super_class);
7837 super_class
7838 = build_function_call
7839 (super_class,
7840 build_tree_list
7841 (NULL_TREE,
7842 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7843 IDENTIFIER_POINTER (super_name))));
7846 super_expr
7847 = build_modify_expr (super_expr, NOP_EXPR,
7848 build_c_cast (TREE_TYPE (super_expr),
7849 super_class));
7852 super_expr_list = build_compound_expr (super_expr_list, super_expr);
7854 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7855 super_expr_list = build_compound_expr (super_expr_list, super_expr);
7857 return super_expr_list;
7859 else
7861 error ("[super ...] must appear in a method context");
7862 return error_mark_node;
7866 /* When exiting a scope, sever links to a 'super' declaration (if any)
7867 therein contained. */
7869 void
7870 objc_clear_super_receiver (void)
7872 if (objc_method_context
7873 && UOBJC_SUPER_scope == objc_get_current_scope ()) {
7874 UOBJC_SUPER_decl = 0;
7875 UOBJC_SUPER_scope = 0;
7879 void
7880 objc_finish_method_definition (tree fndecl)
7882 /* We cannot validly inline ObjC methods, at least not without a language
7883 extension to declare that a method need not be dynamically
7884 dispatched, so suppress all thoughts of doing so. */
7885 DECL_INLINE (fndecl) = 0;
7886 DECL_UNINLINABLE (fndecl) = 1;
7888 #ifndef OBJCPLUS
7889 /* The C++ front-end will have called finish_function() for us. */
7890 finish_function ();
7891 #endif
7893 METHOD_ENCODING (objc_method_context)
7894 = encode_method_prototype (objc_method_context);
7896 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7897 since the optimizer may find "may be used before set" errors. */
7898 objc_method_context = NULL_TREE;
7901 #if 0
7903 lang_report_error_function (tree decl)
7905 if (objc_method_context)
7907 fprintf (stderr, "In method `%s'\n",
7908 IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7909 return 1;
7912 else
7913 return 0;
7915 #endif
7917 /* Given a tree DECL node, produce a printable description of it in the given
7918 buffer, overwriting the buffer. */
7920 static char *
7921 gen_declaration (tree decl)
7923 errbuf[0] = '\0';
7925 if (DECL_P (decl))
7927 gen_type_name_0 (TREE_TYPE (decl));
7929 if (DECL_NAME (decl))
7931 if (!POINTER_TYPE_P (TREE_TYPE (decl)))
7932 strcat (errbuf, " ");
7934 strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
7937 if (DECL_INITIAL (decl)
7938 && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
7939 sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
7940 TREE_INT_CST_LOW (DECL_INITIAL (decl)));
7943 return errbuf;
7946 /* Given a tree TYPE node, produce a printable description of it in the given
7947 buffer, overwriting the buffer. */
7949 static char *
7950 gen_type_name_0 (tree type)
7952 tree orig = type, proto;
7954 if (TYPE_P (type) && TYPE_NAME (type))
7955 type = TYPE_NAME (type);
7956 else if (POINTER_TYPE_P (type))
7958 gen_type_name_0 (TREE_TYPE (type));
7960 if (!POINTER_TYPE_P (TREE_TYPE (type)))
7961 strcat (errbuf, " ");
7963 strcat (errbuf, "*");
7964 goto exit_function;
7967 if (TREE_CODE (type) == TYPE_DECL && DECL_NAME (type))
7968 type = DECL_NAME (type);
7970 strcat (errbuf, IDENTIFIER_POINTER (type));
7971 proto = TYPE_PROTOCOL_LIST (orig);
7973 if (proto)
7975 strcat (errbuf, " <");
7977 while (proto) {
7978 strcat (errbuf,
7979 IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (proto))));
7980 proto = TREE_CHAIN (proto);
7981 strcat (errbuf, proto ? ", " : ">");
7985 exit_function:
7986 return errbuf;
7989 static char *
7990 gen_type_name (tree type)
7992 errbuf[0] = '\0';
7994 return gen_type_name_0 (type);
7997 /* Given a method tree, put a printable description into the given
7998 buffer (overwriting) and return a pointer to the buffer. */
8000 static char *
8001 gen_method_decl (tree method)
8003 tree chain;
8005 strcpy (errbuf, "("); /* NB: Do _not_ call strcat() here. */
8006 gen_type_name_0 (TREE_VALUE (TREE_TYPE (method)));
8007 strcat (errbuf, ")");
8008 chain = METHOD_SEL_ARGS (method);
8010 if (chain)
8012 /* We have a chain of keyword_decls. */
8015 if (KEYWORD_KEY_NAME (chain))
8016 strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8018 strcat (errbuf, ":(");
8019 gen_type_name_0 (TREE_VALUE (TREE_TYPE (chain)));
8020 strcat (errbuf, ")");
8022 strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8023 if ((chain = TREE_CHAIN (chain)))
8024 strcat (errbuf, " ");
8026 while (chain);
8028 if (METHOD_ADD_ARGS (method))
8030 chain = TREE_CHAIN (METHOD_ADD_ARGS (method));
8032 /* Know we have a chain of parm_decls. */
8033 while (chain)
8035 strcat (errbuf, ", ");
8036 gen_type_name_0 (TREE_TYPE (TREE_VALUE (chain)));
8037 chain = TREE_CHAIN (chain);
8040 if (TREE_OVERFLOW (METHOD_ADD_ARGS (method)))
8041 strcat (errbuf, ", ...");
8045 else
8046 /* We have a unary selector. */
8047 strcat (errbuf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8049 return errbuf;
8052 /* Debug info. */
8055 /* Dump an @interface declaration of the supplied class CHAIN to the
8056 supplied file FP. Used to implement the -gen-decls option (which
8057 prints out an @interface declaration of all classes compiled in
8058 this run); potentially useful for debugging the compiler too. */
8059 static void
8060 dump_interface (FILE *fp, tree chain)
8062 /* FIXME: A heap overflow here whenever a method (or ivar)
8063 declaration is so long that it doesn't fit in the buffer. The
8064 code and all the related functions should be rewritten to avoid
8065 using fixed size buffers. */
8066 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8067 tree ivar_decls = CLASS_RAW_IVARS (chain);
8068 tree nst_methods = CLASS_NST_METHODS (chain);
8069 tree cls_methods = CLASS_CLS_METHODS (chain);
8071 fprintf (fp, "\n@interface %s", my_name);
8073 /* CLASS_SUPER_NAME is used to store the superclass name for
8074 classes, and the category name for categories. */
8075 if (CLASS_SUPER_NAME (chain))
8077 const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8079 if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8080 || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8082 fprintf (fp, " (%s)\n", name);
8084 else
8086 fprintf (fp, " : %s\n", name);
8089 else
8090 fprintf (fp, "\n");
8092 /* FIXME - the following doesn't seem to work at the moment. */
8093 if (ivar_decls)
8095 fprintf (fp, "{\n");
8098 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls));
8099 ivar_decls = TREE_CHAIN (ivar_decls);
8101 while (ivar_decls);
8102 fprintf (fp, "}\n");
8105 while (nst_methods)
8107 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods));
8108 nst_methods = TREE_CHAIN (nst_methods);
8111 while (cls_methods)
8113 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods));
8114 cls_methods = TREE_CHAIN (cls_methods);
8117 fprintf (fp, "@end\n");
8120 /* Demangle function for Objective-C */
8121 static const char *
8122 objc_demangle (const char *mangled)
8124 char *demangled, *cp;
8126 if (mangled[0] == '_' &&
8127 (mangled[1] == 'i' || mangled[1] == 'c') &&
8128 mangled[2] == '_')
8130 cp = demangled = xmalloc(strlen(mangled) + 2);
8131 if (mangled[1] == 'i')
8132 *cp++ = '-'; /* for instance method */
8133 else
8134 *cp++ = '+'; /* for class method */
8135 *cp++ = '['; /* opening left brace */
8136 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8137 while (*cp && *cp == '_')
8138 cp++; /* skip any initial underbars in class name */
8139 cp = strchr(cp, '_'); /* find first non-initial underbar */
8140 if (cp == NULL)
8142 free(demangled); /* not mangled name */
8143 return mangled;
8145 if (cp[1] == '_') /* easy case: no category name */
8147 *cp++ = ' '; /* replace two '_' with one ' ' */
8148 strcpy(cp, mangled + (cp - demangled) + 2);
8150 else
8152 *cp++ = '('; /* less easy case: category name */
8153 cp = strchr(cp, '_');
8154 if (cp == 0)
8156 free(demangled); /* not mangled name */
8157 return mangled;
8159 *cp++ = ')';
8160 *cp++ = ' '; /* overwriting 1st char of method name... */
8161 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8163 while (*cp && *cp == '_')
8164 cp++; /* skip any initial underbars in method name */
8165 for (; *cp; cp++)
8166 if (*cp == '_')
8167 *cp = ':'; /* replace remaining '_' with ':' */
8168 *cp++ = ']'; /* closing right brace */
8169 *cp++ = 0; /* string terminator */
8170 return demangled;
8172 else
8173 return mangled; /* not an objc mangled name */
8176 const char *
8177 objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
8179 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8182 static void
8183 init_objc (void)
8185 gcc_obstack_init (&util_obstack);
8186 util_firstobj = (char *) obstack_finish (&util_obstack);
8188 errbuf = (char *) xmalloc (1024 * 10);
8189 hash_init ();
8190 synth_module_prologue ();
8193 static void
8194 finish_objc (void)
8196 struct imp_entry *impent;
8197 tree chain;
8198 /* The internally generated initializers appear to have missing braces.
8199 Don't warn about this. */
8200 int save_warn_missing_braces = warn_missing_braces;
8201 warn_missing_braces = 0;
8203 /* A missing @end may not be detected by the parser. */
8204 if (objc_implementation_context)
8206 warning ("`@end' missing in implementation context");
8207 finish_class (objc_implementation_context);
8208 objc_ivar_chain = NULL_TREE;
8209 objc_implementation_context = NULL_TREE;
8212 /* Process the static instances here because initialization of objc_symtab
8213 depends on them. */
8214 if (objc_static_instances)
8215 generate_static_references ();
8217 if (imp_list || class_names_chain
8218 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8219 generate_objc_symtab_decl ();
8221 for (impent = imp_list; impent; impent = impent->next)
8223 objc_implementation_context = impent->imp_context;
8224 implementation_template = impent->imp_template;
8226 UOBJC_CLASS_decl = impent->class_decl;
8227 UOBJC_METACLASS_decl = impent->meta_decl;
8229 /* Dump the @interface of each class as we compile it, if the
8230 -gen-decls option is in use. TODO: Dump the classes in the
8231 order they were found, rather than in reverse order as we
8232 are doing now. */
8233 if (flag_gen_declaration)
8235 dump_interface (gen_declaration_file, objc_implementation_context);
8238 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8240 /* all of the following reference the string pool... */
8241 generate_ivar_lists ();
8242 generate_dispatch_tables ();
8243 generate_shared_structures ();
8245 else
8247 generate_dispatch_tables ();
8248 generate_category (objc_implementation_context);
8252 /* If we are using an array of selectors, we must always
8253 finish up the array decl even if no selectors were used. */
8254 if (! flag_next_runtime || sel_ref_chain)
8255 build_selector_translation_table ();
8257 if (protocol_chain)
8258 generate_protocols ();
8260 if (flag_replace_objc_classes && imp_list)
8261 generate_objc_image_info ();
8263 /* Arrange for ObjC data structures to be initialized at run time. */
8264 if (objc_implementation_context || class_names_chain || objc_static_instances
8265 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8267 build_module_descriptor ();
8269 if (!flag_next_runtime)
8270 build_module_initializer_routine ();
8273 /* Dump the class references. This forces the appropriate classes
8274 to be linked into the executable image, preserving unix archive
8275 semantics. This can be removed when we move to a more dynamically
8276 linked environment. */
8278 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8280 handle_class_ref (chain);
8281 if (TREE_PURPOSE (chain))
8282 generate_classref_translation_entry (chain);
8285 for (impent = imp_list; impent; impent = impent->next)
8286 handle_impent (impent);
8288 /* Dump the string table last. */
8290 generate_strings ();
8292 if (warn_selector)
8294 int slot;
8295 hash hsh;
8297 /* Run through the selector hash tables and print a warning for any
8298 selector which has multiple methods. */
8300 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8302 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8303 check_duplicates (hsh, 0, 1);
8304 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8305 check_duplicates (hsh, 0, 1);
8309 warn_missing_braces = save_warn_missing_braces;
8312 /* Subroutines of finish_objc. */
8314 static void
8315 generate_classref_translation_entry (tree chain)
8317 tree expr, decl, type;
8319 decl = TREE_PURPOSE (chain);
8320 type = TREE_TYPE (decl);
8322 expr = add_objc_string (TREE_VALUE (chain), class_names);
8323 expr = convert (type, expr); /* cast! */
8325 /* The decl that is the one that we
8326 forward declared in build_class_reference. */
8327 finish_var_decl (decl, expr);
8328 return;
8331 static void
8332 handle_class_ref (tree chain)
8334 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8335 char *string = (char *) alloca (strlen (name) + 30);
8336 tree decl;
8337 tree exp;
8339 sprintf (string, "%sobjc_class_name_%s",
8340 (flag_next_runtime ? "." : "__"), name);
8342 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8343 if (flag_next_runtime)
8345 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8346 return;
8348 #endif
8350 /* Make a decl for this name, so we can use its address in a tree. */
8351 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8352 DECL_EXTERNAL (decl) = 1;
8353 TREE_PUBLIC (decl) = 1;
8355 pushdecl (decl);
8356 rest_of_decl_compilation (decl, 0, 0);
8358 /* Make a decl for the address. */
8359 sprintf (string, "%sobjc_class_ref_%s",
8360 (flag_next_runtime ? "." : "__"), name);
8361 exp = build1 (ADDR_EXPR, string_type_node, decl);
8362 decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8363 DECL_INITIAL (decl) = exp;
8364 TREE_STATIC (decl) = 1;
8365 TREE_USED (decl) = 1;
8367 pushdecl (decl);
8368 rest_of_decl_compilation (decl, 0, 0);
8371 static void
8372 handle_impent (struct imp_entry *impent)
8374 char *string;
8376 objc_implementation_context = impent->imp_context;
8377 implementation_template = impent->imp_template;
8379 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8381 const char *const class_name =
8382 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8384 string = (char *) alloca (strlen (class_name) + 30);
8386 sprintf (string, "%sobjc_class_name_%s",
8387 (flag_next_runtime ? "." : "__"), class_name);
8389 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8391 const char *const class_name =
8392 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8393 const char *const class_super_name =
8394 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8396 string = (char *) alloca (strlen (class_name)
8397 + strlen (class_super_name) + 30);
8399 /* Do the same for categories. Even though no references to
8400 these symbols are generated automatically by the compiler, it
8401 gives you a handle to pull them into an archive by hand. */
8402 sprintf (string, "*%sobjc_category_name_%s_%s",
8403 (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8405 else
8406 return;
8408 #ifdef ASM_DECLARE_CLASS_REFERENCE
8409 if (flag_next_runtime)
8411 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8412 return;
8414 else
8415 #endif
8417 tree decl, init;
8419 init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0);
8420 decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
8421 TREE_PUBLIC (decl) = 1;
8422 TREE_READONLY (decl) = 1;
8423 TREE_USED (decl) = 1;
8424 TREE_CONSTANT (decl) = 1;
8425 DECL_CONTEXT (decl) = 0;
8426 DECL_ARTIFICIAL (decl) = 1;
8427 DECL_INITIAL (decl) = init;
8428 assemble_variable (decl, 1, 0, 0);
8432 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
8433 later requires that ObjC translation units participating in F&C be
8434 specially marked. The following routine accomplishes this. */
8436 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
8438 static void
8439 generate_objc_image_info (void)
8441 tree decl, initlist;
8443 decl = start_var_decl (build_array_type
8444 (integer_type_node,
8445 build_index_type (build_int_cst (NULL_TREE, 2 - 1))),
8446 "_OBJC_IMAGE_INFO");
8448 initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
8449 initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 1), initlist);
8450 initlist = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
8452 finish_var_decl (decl, initlist);
8455 /* Look up ID as an instance variable. */
8457 tree
8458 objc_lookup_ivar (tree id)
8460 tree decl;
8462 if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8463 /* We have a message to super. */
8464 return get_super_receiver ();
8465 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8467 if (is_private (decl))
8468 return 0;
8469 else
8470 return build_ivar_reference (id);
8472 else
8473 return 0;
8476 #include "gt-objc-objc-act.h"