]> gcc.gnu.org Git - gcc.git/blob - gcc/objc/objc-act.c
objc-act.c (lang_init, [...]): Remove redundant code, assuming doing_objc_thang is...
[gcc.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
4 Contributed by Steve Naroff.
5
6 This file is part of GNU CC.
7
8 GNU CC 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.
12
13 GNU CC 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.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Purpose: This module implements the Objective-C 4.0 language.
24
25 compatibility issues (with the Stepstone translator):
26
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.
37
38 code generation `options':
39
40 - OBJC_INT_SELECTORS */
41
42 #include "config.h"
43 #include "system.h"
44 #include "tree.h"
45 #include "rtl.h"
46 #include "expr.h"
47 #include "c-tree.h"
48 #include "c-lex.h"
49 #include "c-common.h"
50 #include "flags.h"
51 #include "objc-act.h"
52 #include "input.h"
53 #include "except.h"
54 #include "function.h"
55 #include "output.h"
56 #include "toplev.h"
57 #include "ggc.h"
58 #include "cpplib.h"
59
60 /* This is the default way of generating a method name. */
61 /* I am not sure it is really correct.
62 Perhaps there's a danger that it will make name conflicts
63 if method names contain underscores. -- rms. */
64 #ifndef OBJC_GEN_METHOD_LABEL
65 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
66 do { \
67 char *temp; \
68 sprintf ((BUF), "_%s_%s_%s_%s", \
69 ((IS_INST) ? "i" : "c"), \
70 (CLASS_NAME), \
71 ((CAT_NAME)? (CAT_NAME) : ""), \
72 (SEL_NAME)); \
73 for (temp = (BUF); *temp; temp++) \
74 if (*temp == ':') *temp = '_'; \
75 } while (0)
76 #endif
77
78 /* These need specifying. */
79 #ifndef OBJC_FORWARDING_STACK_OFFSET
80 #define OBJC_FORWARDING_STACK_OFFSET 0
81 #endif
82
83 #ifndef OBJC_FORWARDING_MIN_OFFSET
84 #define OBJC_FORWARDING_MIN_OFFSET 0
85 #endif
86 \f
87 /* Define the special tree codes that we use. */
88
89 /* Table indexed by tree code giving a string containing a character
90 classifying the tree code. Possibilities are
91 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
92
93 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
94
95 static const char objc_tree_code_type[] = {
96 'x',
97 #include "objc-tree.def"
98 };
99 #undef DEFTREECODE
100
101 /* Table indexed by tree code giving number of expression
102 operands beyond the fixed part of the node structure.
103 Not used for types or decls. */
104
105 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
106
107 static const int objc_tree_code_length[] = {
108 0,
109 #include "objc-tree.def"
110 };
111 #undef DEFTREECODE
112
113 /* Names of tree components.
114 Used for printing out the tree and error messages. */
115 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
116
117 static const char * const objc_tree_code_name[] = {
118 "@@dummy",
119 #include "objc-tree.def"
120 };
121 #undef DEFTREECODE
122 \f
123 /* Set up for use of obstacks. */
124
125 #include "obstack.h"
126
127 #define obstack_chunk_alloc xmalloc
128 #define obstack_chunk_free free
129
130 /* This obstack is used to accumulate the encoding of a data type. */
131 static struct obstack util_obstack;
132 /* This points to the beginning of obstack contents,
133 so we can free the whole contents. */
134 char *util_firstobj;
135
136 /* for encode_method_def */
137 #include "rtl.h"
138
139 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
140 #define PROTOCOL_VERSION 2
141
142 #define OBJC_ENCODE_INLINE_DEFS 0
143 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
144
145 /*** Private Interface (procedures) ***/
146
147 /* Used by compile_file. */
148
149 static void init_objc PARAMS ((void));
150 static void finish_objc PARAMS ((void));
151
152 /* Code generation. */
153
154 static void synth_module_prologue PARAMS ((void));
155 static tree build_constructor PARAMS ((tree, tree));
156 static const char *build_module_descriptor PARAMS ((void));
157 static tree init_module_descriptor PARAMS ((tree));
158 static tree build_objc_method_call PARAMS ((int, tree, tree,
159 tree, tree, tree));
160 static void generate_strings PARAMS ((void));
161 static tree get_proto_encoding PARAMS ((tree));
162 static void build_selector_translation_table PARAMS ((void));
163 static tree build_ivar_chain PARAMS ((tree, int));
164
165 static tree objc_add_static_instance PARAMS ((tree, tree));
166
167 static tree build_ivar_template PARAMS ((void));
168 static tree build_method_template PARAMS ((void));
169 static tree build_private_template PARAMS ((tree));
170 static void build_class_template PARAMS ((void));
171 static void build_selector_template PARAMS ((void));
172 static void build_category_template PARAMS ((void));
173 static tree build_super_template PARAMS ((void));
174 static tree build_category_initializer PARAMS ((tree, tree, tree,
175 tree, tree, tree));
176 static tree build_protocol_initializer PARAMS ((tree, tree, tree,
177 tree, tree));
178
179 static void synth_forward_declarations PARAMS ((void));
180 static void generate_ivar_lists PARAMS ((void));
181 static void generate_dispatch_tables PARAMS ((void));
182 static void generate_shared_structures PARAMS ((void));
183 static tree generate_protocol_list PARAMS ((tree));
184 static void generate_forward_declaration_to_string_table PARAMS ((void));
185 static void build_protocol_reference PARAMS ((tree));
186
187 #if 0
188 static tree init_selector PARAMS ((int));
189 #endif
190 static tree build_keyword_selector PARAMS ((tree));
191 static tree synth_id_with_class_suffix PARAMS ((const char *, tree));
192
193 static void generate_static_references PARAMS ((void));
194 static int check_methods_accessible PARAMS ((tree, tree,
195 int));
196 static void encode_aggregate_within PARAMS ((tree, int, int,
197 int, int));
198 static const char *objc_demangle PARAMS ((const char *));
199 static const char *objc_printable_name PARAMS ((tree, int));
200 static void objc_expand_function_end PARAMS ((void));
201
202 /* Misc. bookkeeping */
203
204 typedef struct hashed_entry *hash;
205 typedef struct hashed_attribute *attr;
206
207 struct hashed_attribute
208 {
209 attr next;
210 tree value;
211 };
212 struct hashed_entry
213 {
214 attr list;
215 hash next;
216 tree key;
217 };
218
219 static void hash_init PARAMS ((void));
220 static void hash_enter PARAMS ((hash *, tree));
221 static hash hash_lookup PARAMS ((hash *, tree));
222 static void hash_add_attr PARAMS ((hash, tree));
223 static tree lookup_method PARAMS ((tree, tree));
224 static tree lookup_instance_method_static PARAMS ((tree, tree));
225 static tree lookup_class_method_static PARAMS ((tree, tree));
226 static tree add_class PARAMS ((tree));
227 static void add_category PARAMS ((tree, tree));
228
229 enum string_section
230 {
231 class_names, /* class, category, protocol, module names */
232 meth_var_names, /* method and variable names */
233 meth_var_types /* method and variable type descriptors */
234 };
235
236 static tree add_objc_string PARAMS ((tree,
237 enum string_section));
238 static tree get_objc_string_decl PARAMS ((tree,
239 enum string_section));
240 static tree build_objc_string_decl PARAMS ((enum string_section));
241 static tree build_selector_reference_decl PARAMS ((void));
242
243 /* Protocol additions. */
244
245 static tree add_protocol PARAMS ((tree));
246 static tree lookup_protocol PARAMS ((tree));
247 static tree lookup_and_install_protocols PARAMS ((tree));
248
249 /* Type encoding. */
250
251 static void encode_type_qualifiers PARAMS ((tree));
252 static void encode_pointer PARAMS ((tree, int, int));
253 static void encode_array PARAMS ((tree, int, int));
254 static void encode_aggregate PARAMS ((tree, int, int));
255 static void encode_bitfield PARAMS ((int));
256 static void encode_type PARAMS ((tree, int, int));
257 static void encode_field_decl PARAMS ((tree, int, int));
258
259 static void really_start_method PARAMS ((tree, tree));
260 static int comp_method_with_proto PARAMS ((tree, tree));
261 static int comp_proto_with_proto PARAMS ((tree, tree));
262 static tree get_arg_type_list PARAMS ((tree, int, int));
263 static tree expr_last PARAMS ((tree));
264
265 /* Utilities for debugging and error diagnostics. */
266
267 static void warn_with_method PARAMS ((const char *, int, tree));
268 static void error_with_ivar PARAMS ((const char *, tree, tree));
269 static char *gen_method_decl PARAMS ((tree, char *));
270 static char *gen_declaration PARAMS ((tree, char *));
271 static char *gen_declarator PARAMS ((tree, char *,
272 const char *));
273 static int is_complex_decl PARAMS ((tree));
274 static void adorn_decl PARAMS ((tree, char *));
275 static void dump_interface PARAMS ((FILE *, tree));
276
277 /* Everything else. */
278
279 static void objc_fatal PARAMS ((void))
280 ATTRIBUTE_NORETURN;
281 static tree define_decl PARAMS ((tree, tree));
282 static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int));
283 static tree lookup_protocol_in_reflist PARAMS ((tree, tree));
284 static tree create_builtin_decl PARAMS ((enum tree_code,
285 tree, const char *));
286 static tree my_build_string PARAMS ((int, const char *));
287 static void build_objc_symtab_template PARAMS ((void));
288 static tree init_def_list PARAMS ((tree));
289 static tree init_objc_symtab PARAMS ((tree));
290 static void forward_declare_categories PARAMS ((void));
291 static void generate_objc_symtab_decl PARAMS ((void));
292 static tree build_selector PARAMS ((tree));
293 #if 0
294 static tree build_msg_pool_reference PARAMS ((int));
295 #endif
296 static tree build_typed_selector_reference PARAMS ((tree, tree));
297 static tree build_selector_reference PARAMS ((tree));
298 static tree build_class_reference_decl PARAMS ((void));
299 static void add_class_reference PARAMS ((tree));
300 static tree objc_copy_list PARAMS ((tree, tree *));
301 static tree build_protocol_template PARAMS ((void));
302 static tree build_descriptor_table_initializer PARAMS ((tree, tree));
303 static tree build_method_prototype_list_template PARAMS ((tree, int));
304 static tree build_method_prototype_template PARAMS ((void));
305 static int forwarding_offset PARAMS ((tree));
306 static tree encode_method_prototype PARAMS ((tree, tree));
307 static tree generate_descriptor_table PARAMS ((tree, const char *,
308 int, tree, tree));
309 static void generate_method_descriptors PARAMS ((tree));
310 static tree build_tmp_function_decl PARAMS ((void));
311 static void hack_method_prototype PARAMS ((tree, tree));
312 static void generate_protocol_references PARAMS ((tree));
313 static void generate_protocols PARAMS ((void));
314 static void check_ivars PARAMS ((tree, tree));
315 static tree build_ivar_list_template PARAMS ((tree, int));
316 static tree build_method_list_template PARAMS ((tree, int));
317 static tree build_ivar_list_initializer PARAMS ((tree, tree));
318 static tree generate_ivars_list PARAMS ((tree, const char *,
319 int, tree));
320 static tree build_dispatch_table_initializer PARAMS ((tree, tree));
321 static tree generate_dispatch_table PARAMS ((tree, const char *,
322 int, tree));
323 static tree build_shared_structure_initializer PARAMS ((tree, tree, tree, tree,
324 tree, int, tree, tree,
325 tree));
326 static void generate_category PARAMS ((tree));
327 static int is_objc_type_qualifier PARAMS ((tree));
328 static tree adjust_type_for_id_default PARAMS ((tree));
329 static tree check_duplicates PARAMS ((hash));
330 static tree receiver_is_class_object PARAMS ((tree));
331 static int check_methods PARAMS ((tree, tree, int));
332 static int conforms_to_protocol PARAMS ((tree, tree));
333 static void check_protocols PARAMS ((tree, const char *,
334 const char *));
335 static tree encode_method_def PARAMS ((tree));
336 static void gen_declspecs PARAMS ((tree, char *, int));
337 static void generate_classref_translation_entry PARAMS ((tree));
338 static void handle_class_ref PARAMS ((tree));
339 static void generate_struct_by_value_array PARAMS ((void))
340 ATTRIBUTE_NORETURN;
341 static void objc_act_parse_init PARAMS ((void));
342 static void ggc_mark_imp_list PARAMS ((void *));
343 static void ggc_mark_hash_table PARAMS ((void *));
344
345 /*** Private Interface (data) ***/
346
347 /* Reserved tag definitions. */
348
349 #define TYPE_ID "id"
350 #define TAG_OBJECT "objc_object"
351 #define TAG_CLASS "objc_class"
352 #define TAG_SUPER "objc_super"
353 #define TAG_SELECTOR "objc_selector"
354
355 #define UTAG_CLASS "_objc_class"
356 #define UTAG_IVAR "_objc_ivar"
357 #define UTAG_IVAR_LIST "_objc_ivar_list"
358 #define UTAG_METHOD "_objc_method"
359 #define UTAG_METHOD_LIST "_objc_method_list"
360 #define UTAG_CATEGORY "_objc_category"
361 #define UTAG_MODULE "_objc_module"
362 #define UTAG_STATICS "_objc_statics"
363 #define UTAG_SYMTAB "_objc_symtab"
364 #define UTAG_SUPER "_objc_super"
365 #define UTAG_SELECTOR "_objc_selector"
366
367 #define UTAG_PROTOCOL "_objc_protocol"
368 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
369 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
370 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
371
372 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
373 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
374
375 static const char *constant_string_class_name = NULL;
376
377 static const char *TAG_GETCLASS;
378 static const char *TAG_GETMETACLASS;
379 static const char *TAG_MSGSEND;
380 static const char *TAG_MSGSENDSUPER;
381 static const char *TAG_EXECCLASS;
382
383 /* Set by `continue_class' and checked by `is_public'. */
384
385 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
386 #define TYPED_OBJECT(type) \
387 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
388
389 tree objc_ellipsis_node;
390
391 enum objc_tree_index
392 {
393 OCTI_STATIC_NST,
394 OCTI_STATIC_NST_DECL,
395 OCTI_SELF_ID,
396 OCTI_UCMD_ID,
397 OCTI_UNUSED_LIST,
398 OCTI_SELF_DECL,
399 OCTI_UMSG_DECL,
400 OCTI_UMSG_SUPER_DECL,
401 OCTI_GET_CLASS_DECL,
402 OCTI_GET_MCLASS_DECL,
403 OCTI_SUPER_TYPE,
404 OCTI_SEL_TYPE,
405 OCTI_ID_TYPE,
406 OCTI_CLS_TYPE,
407 OCTI_NST_TYPE,
408 OCTI_PROTO_TYPE,
409
410 OCTI_CLS_CHAIN,
411 OCTI_ALIAS_CHAIN,
412 OCTI_INTF_CHAIN,
413 OCTI_PROTO_CHAIN,
414 OCTI_CLS_REF_CHAIN,
415 OCTI_SEL_REF_CHAIN,
416 OCTI_CLS_NAMES_CHAIN,
417 OCTI_METH_VAR_NAMES_CHAIN,
418 OCTI_METH_VAR_TYPES_CHAIN,
419
420 OCTI_SYMBOLS_DECL,
421 OCTI_NST_VAR_DECL,
422 OCTI_CLS_VAR_DECL,
423 OCTI_NST_METH_DECL,
424 OCTI_CLS_METH_DECL,
425 OCTI_CLS_DECL,
426 OCTI_MCLS_DECL,
427 OCTI_SEL_TABLE_DECL,
428 OCTI_MODULES_DECL,
429 OCTI_STRG_DECL,
430
431 OCTI_IMPL_CTX,
432 OCTI_IMPL_TEMPL,
433
434 OCTI_CLS_TEMPL,
435 OCTI_CAT_TEMPL,
436 OCTI_UPRIV_REC,
437 OCTI_PROTO_TEMPL,
438 OCTI_SEL_TEMPL,
439 OCTI_UCLS_SUPER_REF,
440 OCTI_UUCLS_SUPER_REF,
441 OCTI_METH_TEMPL,
442 OCTI_IVAR_TEMPL,
443 OCTI_SYMTAB_TEMPL,
444 OCTI_MODULE_TEMPL,
445 OCTI_SUPER_TEMPL,
446 OCTI_OBJ_REF,
447 OCTI_OBJ_ID,
448 OCTI_CLS_ID,
449 OCTI_ID_ID,
450 OCTI_CNST_STR_ID,
451 OCTI_CNST_STR_TYPE,
452 OCTI_SUPER_DECL,
453 OCTI_METH_CTX,
454
455 OCTI_MAX
456 };
457
458 static tree objc_global_trees[OCTI_MAX];
459
460 /* List of classes with list of their static instances. */
461 #define objc_static_instances objc_global_trees[OCTI_STATIC_NST]
462
463 /* The declaration of the array administrating the static instances. */
464 #define static_instances_decl objc_global_trees[OCTI_STATIC_NST_DECL]
465
466 /* Some commonly used instances of "identifier_node". */
467
468 #define self_id objc_global_trees[OCTI_SELF_ID]
469 #define ucmd_id objc_global_trees[OCTI_UCMD_ID]
470 #define unused_list objc_global_trees[OCTI_UNUSED_LIST]
471
472 #define self_decl objc_global_trees[OCTI_SELF_DECL]
473 #define umsg_decl objc_global_trees[OCTI_UMSG_DECL]
474 #define umsg_super_decl objc_global_trees[OCTI_UMSG_SUPER_DECL]
475 #define objc_get_class_decl objc_global_trees[OCTI_GET_CLASS_DECL]
476 #define objc_get_meta_class_decl \
477 objc_global_trees[OCTI_GET_MCLASS_DECL]
478
479 #define super_type objc_global_trees[OCTI_SUPER_TYPE]
480 #define selector_type objc_global_trees[OCTI_SEL_TYPE]
481 #define id_type objc_global_trees[OCTI_ID_TYPE]
482 #define objc_class_type objc_global_trees[OCTI_CLS_TYPE]
483 #define instance_type objc_global_trees[OCTI_NST_TYPE]
484 #define protocol_type objc_global_trees[OCTI_PROTO_TYPE]
485
486 /* Type checking macros. */
487
488 #define IS_ID(TYPE) \
489 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
490 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
491 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
492 #define IS_SUPER(TYPE) \
493 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
494
495 #define class_chain objc_global_trees[OCTI_CLS_CHAIN]
496 #define alias_chain objc_global_trees[OCTI_ALIAS_CHAIN]
497 #define interface_chain objc_global_trees[OCTI_INTF_CHAIN]
498 #define protocol_chain objc_global_trees[OCTI_PROTO_CHAIN]
499
500 /* Chains to manage selectors that are referenced and defined in the
501 module. */
502
503 #define cls_ref_chain objc_global_trees[OCTI_CLS_REF_CHAIN] /* Classes referenced. */
504 #define sel_ref_chain objc_global_trees[OCTI_SEL_REF_CHAIN] /* Selectors referenced. */
505
506 /* Chains to manage uniquing of strings. */
507
508 #define class_names_chain objc_global_trees[OCTI_CLS_NAMES_CHAIN]
509 #define meth_var_names_chain objc_global_trees[OCTI_METH_VAR_NAMES_CHAIN]
510 #define meth_var_types_chain objc_global_trees[OCTI_METH_VAR_TYPES_CHAIN]
511
512 /* Hash tables to manage the global pool of method prototypes. */
513
514 static hash *nst_method_hash_list = 0;
515 static hash *cls_method_hash_list = 0;
516
517 /* Backend data declarations. */
518
519 #define UOBJC_SYMBOLS_decl objc_global_trees[OCTI_SYMBOLS_DECL]
520 #define UOBJC_INSTANCE_VARIABLES_decl objc_global_trees[OCTI_NST_VAR_DECL]
521 #define UOBJC_CLASS_VARIABLES_decl objc_global_trees[OCTI_CLS_VAR_DECL]
522 #define UOBJC_INSTANCE_METHODS_decl objc_global_trees[OCTI_NST_METH_DECL]
523 #define UOBJC_CLASS_METHODS_decl objc_global_trees[OCTI_CLS_METH_DECL]
524 #define UOBJC_CLASS_decl objc_global_trees[OCTI_CLS_DECL]
525 #define UOBJC_METACLASS_decl objc_global_trees[OCTI_MCLS_DECL]
526 #define UOBJC_SELECTOR_TABLE_decl objc_global_trees[OCTI_SEL_TABLE_DECL]
527 #define UOBJC_MODULES_decl objc_global_trees[OCTI_MODULES_DECL]
528 #define UOBJC_STRINGS_decl objc_global_trees[OCTI_STRG_DECL]
529
530 /* The following are used when compiling a class implementation.
531 implementation_template will normally be an interface, however if
532 none exists this will be equal to implementation_context...it is
533 set in start_class. */
534
535 #define implementation_context objc_global_trees[OCTI_IMPL_CTX]
536 #define implementation_template objc_global_trees[OCTI_IMPL_TEMPL]
537
538 struct imp_entry
539 {
540 struct imp_entry *next;
541 tree imp_context;
542 tree imp_template;
543 tree class_decl; /* _OBJC_CLASS_<my_name>; */
544 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
545 };
546
547 static void handle_impent PARAMS ((struct imp_entry *));
548
549 static struct imp_entry *imp_list = 0;
550 static int imp_count = 0; /* `@implementation' */
551 static int cat_count = 0; /* `@category' */
552
553 #define objc_class_template objc_global_trees[OCTI_CLS_TEMPL]
554 #define objc_category_template objc_global_trees[OCTI_CAT_TEMPL]
555 #define uprivate_record objc_global_trees[OCTI_UPRIV_REC]
556 #define objc_protocol_template objc_global_trees[OCTI_PROTO_TEMPL]
557 #define objc_selector_template objc_global_trees[OCTI_SEL_TEMPL]
558 #define ucls_super_ref objc_global_trees[OCTI_UCLS_SUPER_REF]
559 #define uucls_super_ref objc_global_trees[OCTI_UUCLS_SUPER_REF]
560
561 #define objc_method_template objc_global_trees[OCTI_METH_TEMPL]
562 #define objc_ivar_template objc_global_trees[OCTI_IVAR_TEMPL]
563 #define objc_symtab_template objc_global_trees[OCTI_SYMTAB_TEMPL]
564 #define objc_module_template objc_global_trees[OCTI_MODULE_TEMPL]
565 #define objc_super_template objc_global_trees[OCTI_SUPER_TEMPL]
566 #define objc_object_reference objc_global_trees[OCTI_OBJ_REF]
567
568 #define objc_object_id objc_global_trees[OCTI_OBJ_ID]
569 #define objc_class_id objc_global_trees[OCTI_CLS_ID]
570 #define objc_id_id objc_global_trees[OCTI_ID_ID]
571 #define constant_string_id objc_global_trees[OCTI_CNST_STR_ID]
572 #define constant_string_type objc_global_trees[OCTI_CNST_STR_TYPE]
573 #define UOBJC_SUPER_decl objc_global_trees[OCTI_SUPER_DECL]
574
575 #define method_context objc_global_trees[OCTI_METH_CTX]
576 static int method_slot = 0; /* Used by start_method_def, */
577
578 #define BUFSIZE 1024
579
580 static char *errbuf; /* Buffer for error diagnostics */
581
582 /* Data imported from tree.c. */
583
584 extern enum debug_info_type write_symbols;
585
586 /* Data imported from toplev.c. */
587
588 extern const char *dump_base_name;
589 \f
590 /* Generate code for GNU or NeXT runtime environment. */
591
592 #ifdef NEXT_OBJC_RUNTIME
593 int flag_next_runtime = 1;
594 #else
595 int flag_next_runtime = 0;
596 #endif
597
598 int flag_typed_selectors;
599
600 /* Open and close the file for outputting class declarations, if requested. */
601
602 int flag_gen_declaration = 0;
603
604 FILE *gen_declaration_file;
605
606 /* Warn if multiple methods are seen for the same selector, but with
607 different argument types. */
608
609 int warn_selector = 0;
610
611 /* Warn if methods required by a protocol are not implemented in the
612 class adopting it. When turned off, methods inherited to that
613 class are also considered implemented */
614
615 int flag_warn_protocol = 1;
616
617 /* Tells "encode_pointer/encode_aggregate" whether we are generating
618 type descriptors for instance variables (as opposed to methods).
619 Type descriptors for instance variables contain more information
620 than methods (for static typing and embedded structures). This
621 was added to support features being planned for dbkit2. */
622
623 static int generating_instance_variables = 0;
624
625 /* Tells the compiler that this is a special run. Do not perform
626 any compiling, instead we are to test some platform dependent
627 features and output a C header file with appropriate definitions. */
628
629 static int print_struct_values = 0;
630
631 /* Some platforms pass small structures through registers versus through
632 an invisible pointer. Determine at what size structure is the
633 transition point between the two possibilities. */
634
635 static void
636 generate_struct_by_value_array ()
637 {
638 tree type;
639 tree field_decl, field_decl_chain;
640 int i, j;
641 int aggregate_in_mem[32];
642 int found = 0;
643
644 /* Presumbaly no platform passes 32 byte structures in a register. */
645 for (i = 1; i < 32; i++)
646 {
647 char buffer[5];
648
649 /* Create an unnamed struct that has `i' character components */
650 type = start_struct (RECORD_TYPE, NULL_TREE);
651
652 strcpy (buffer, "c1");
653 field_decl = create_builtin_decl (FIELD_DECL,
654 char_type_node,
655 buffer);
656 field_decl_chain = field_decl;
657
658 for (j = 1; j < i; j++)
659 {
660 sprintf (buffer, "c%d", j + 1);
661 field_decl = create_builtin_decl (FIELD_DECL,
662 char_type_node,
663 buffer);
664 chainon (field_decl_chain, field_decl);
665 }
666 finish_struct (type, field_decl_chain, NULL_TREE);
667
668 aggregate_in_mem[i] = aggregate_value_p (type);
669 if (!aggregate_in_mem[i])
670 found = 1;
671 }
672
673 /* We found some structures that are returned in registers instead of memory
674 so output the necessary data. */
675 if (found)
676 {
677 for (i = 31; i >= 0; i--)
678 if (!aggregate_in_mem[i])
679 break;
680 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
681
682 /* The first member of the structure is always 0 because we don't handle
683 structures with 0 members */
684 printf ("static int struct_forward_array[] = {\n 0");
685
686 for (j = 1; j <= i; j++)
687 printf (", %d", aggregate_in_mem[j]);
688 printf ("\n};\n");
689 }
690
691 exit (0);
692 }
693
694 void
695 lang_init_options ()
696 {
697 parse_in = cpp_create_reader (CLK_OBJC);
698 c_language = clk_objective_c;
699 }
700
701 void
702 lang_init ()
703 {
704 /* Force the line number back to 0; check_newline will have
705 raised it to 1, which will make the builtin functions appear
706 not to be built in. */
707 lineno = 0;
708
709 /* If gen_declaration desired, open the output file. */
710 if (flag_gen_declaration)
711 {
712 register char * const dumpname = concat (dumpname, ".decl", NULL);
713 gen_declaration_file = fopen (dumpname, "w");
714 if (gen_declaration_file == 0)
715 pfatal_with_name (dumpname);
716 free (dumpname);
717 }
718
719 if (flag_next_runtime)
720 {
721 TAG_GETCLASS = "objc_getClass";
722 TAG_GETMETACLASS = "objc_getMetaClass";
723 TAG_MSGSEND = "objc_msgSend";
724 TAG_MSGSENDSUPER = "objc_msgSendSuper";
725 TAG_EXECCLASS = "__objc_execClass";
726 }
727 else
728 {
729 TAG_GETCLASS = "objc_get_class";
730 TAG_GETMETACLASS = "objc_get_meta_class";
731 TAG_MSGSEND = "objc_msg_lookup";
732 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
733 TAG_EXECCLASS = "__objc_exec_class";
734 flag_typed_selectors = 1;
735 }
736
737 objc_ellipsis_node = make_node (ERROR_MARK);
738
739 init_objc ();
740
741 if (print_struct_values)
742 generate_struct_by_value_array ();
743
744 objc_act_parse_init ();
745 c_parse_init ();
746 }
747
748 static void
749 objc_fatal ()
750 {
751 fatal ("Objective-C text in C source file");
752 }
753
754 void
755 finish_file ()
756 {
757 finish_objc (); /* Objective-C finalization */
758
759 if (gen_declaration_file)
760 fclose (gen_declaration_file);
761 }
762
763 void
764 lang_finish ()
765 {
766 }
767
768 const char *
769 lang_identify ()
770 {
771 return "objc";
772 }
773
774 int
775 lang_decode_option (argc, argv)
776 int argc;
777 char **argv;
778 {
779 const char *p = argv[0];
780
781 if (!strcmp (p, "-gen-decls"))
782 flag_gen_declaration = 1;
783 else if (!strcmp (p, "-Wselector"))
784 warn_selector = 1;
785 else if (!strcmp (p, "-Wno-selector"))
786 warn_selector = 0;
787 else if (!strcmp (p, "-Wprotocol"))
788 flag_warn_protocol = 1;
789 else if (!strcmp (p, "-Wno-protocol"))
790 flag_warn_protocol = 0;
791 else if (!strcmp (p, "-fgnu-runtime"))
792 flag_next_runtime = 0;
793 else if (!strcmp (p, "-fno-next-runtime"))
794 flag_next_runtime = 0;
795 else if (!strcmp (p, "-fno-gnu-runtime"))
796 flag_next_runtime = 1;
797 else if (!strcmp (p, "-fnext-runtime"))
798 flag_next_runtime = 1;
799 else if (!strcmp (p, "-print-objc-runtime-info"))
800 print_struct_values = 1;
801 #define CSTSTRCLASS "-fconstant-string-class="
802 else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
803 if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
804 error ("no class name specified as argument to -fconstant-string-class");
805 constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
806 }
807 #undef CSTSTRCLASS
808 else
809 return c_decode_option (argc, argv);
810
811 return 1;
812 }
813
814 /* used by print-tree.c */
815
816 void
817 lang_print_xnode (file, node, indent)
818 FILE *file ATTRIBUTE_UNUSED;
819 tree node ATTRIBUTE_UNUSED;
820 int indent ATTRIBUTE_UNUSED;
821 {
822 }
823
824 \f
825 static tree
826 define_decl (declarator, declspecs)
827 tree declarator;
828 tree declspecs;
829 {
830 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
831 finish_decl (decl, NULL_TREE, NULL_TREE);
832 return decl;
833 }
834
835 /* Return 1 if LHS and RHS are compatible types for assignment or
836 various other operations. Return 0 if they are incompatible, and
837 return -1 if we choose to not decide. When the operation is
838 REFLEXIVE, check for compatibility in either direction.
839
840 For statically typed objects, an assignment of the form `a' = `b'
841 is permitted if:
842
843 `a' is of type "id",
844 `a' and `b' are the same class type, or
845 `a' and `b' are of class types A and B such that B is a descendant of A. */
846
847 int
848 maybe_objc_comptypes (lhs, rhs, reflexive)
849 tree lhs, rhs;
850 int reflexive;
851 {
852 return objc_comptypes (lhs, rhs, reflexive);
853 }
854
855 static tree
856 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
857 tree rproto_list;
858 tree sel_name;
859 int class_meth;
860 {
861 tree rproto, p;
862 tree fnd = 0;
863
864 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
865 {
866 p = TREE_VALUE (rproto);
867
868 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
869 {
870 if ((fnd = lookup_method (class_meth
871 ? PROTOCOL_CLS_METHODS (p)
872 : PROTOCOL_NST_METHODS (p), sel_name)))
873 ;
874 else if (PROTOCOL_LIST (p))
875 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
876 sel_name, class_meth);
877 }
878 else
879 {
880 ; /* An identifier...if we could not find a protocol. */
881 }
882
883 if (fnd)
884 return fnd;
885 }
886
887 return 0;
888 }
889
890 static tree
891 lookup_protocol_in_reflist (rproto_list, lproto)
892 tree rproto_list;
893 tree lproto;
894 {
895 tree rproto, p;
896
897 /* Make sure the protocol is support by the object on the rhs. */
898 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
899 {
900 tree fnd = 0;
901 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
902 {
903 p = TREE_VALUE (rproto);
904
905 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
906 {
907 if (lproto == p)
908 fnd = lproto;
909
910 else if (PROTOCOL_LIST (p))
911 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
912 }
913
914 if (fnd)
915 return fnd;
916 }
917 }
918 else
919 {
920 ; /* An identifier...if we could not find a protocol. */
921 }
922
923 return 0;
924 }
925
926 /* Return 1 if LHS and RHS are compatible types for assignment
927 or various other operations. Return 0 if they are incompatible,
928 and return -1 if we choose to not decide. When the operation
929 is REFLEXIVE, check for compatibility in either direction. */
930
931 int
932 objc_comptypes (lhs, rhs, reflexive)
933 tree lhs;
934 tree rhs;
935 int reflexive;
936 {
937 /* New clause for protocols. */
938
939 if (TREE_CODE (lhs) == POINTER_TYPE
940 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
941 && TREE_CODE (rhs) == POINTER_TYPE
942 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
943 {
944 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
945 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
946
947 if (lhs_is_proto)
948 {
949 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
950 tree rproto, rproto_list;
951 tree p;
952
953 if (rhs_is_proto)
954 {
955 rproto_list = TYPE_PROTOCOL_LIST (rhs);
956
957 /* Make sure the protocol is supported by the object
958 on the rhs. */
959 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
960 {
961 p = TREE_VALUE (lproto);
962 rproto = lookup_protocol_in_reflist (rproto_list, p);
963
964 if (!rproto)
965 warning ("object does not conform to the `%s' protocol",
966 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
967 }
968 }
969 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
970 {
971 tree rname = TYPE_NAME (TREE_TYPE (rhs));
972 tree rinter;
973
974 /* Make sure the protocol is supported by the object
975 on the rhs. */
976 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
977 {
978 p = TREE_VALUE (lproto);
979 rproto = 0;
980 rinter = lookup_interface (rname);
981
982 while (rinter && !rproto)
983 {
984 tree cat;
985
986 rproto_list = CLASS_PROTOCOL_LIST (rinter);
987 rproto = lookup_protocol_in_reflist (rproto_list, p);
988
989 /* Check for protocols adopted by categories. */
990 cat = CLASS_CATEGORY_LIST (rinter);
991 while (cat && !rproto)
992 {
993 rproto_list = CLASS_PROTOCOL_LIST (cat);
994 rproto = lookup_protocol_in_reflist (rproto_list, p);
995
996 cat = CLASS_CATEGORY_LIST (cat);
997 }
998
999 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
1000 }
1001
1002 if (!rproto)
1003 warning ("class `%s' does not implement the `%s' protocol",
1004 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
1005 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1006 }
1007 }
1008
1009 /* May change...based on whether there was any mismatch */
1010 return 1;
1011 }
1012 else if (rhs_is_proto)
1013 /* Lhs is not a protocol...warn if it is statically typed */
1014 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
1015
1016 else
1017 /* Defer to comptypes .*/
1018 return -1;
1019 }
1020
1021 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
1022 ; /* Fall thru. This is the case we have been handling all along */
1023 else
1024 /* Defer to comptypes. */
1025 return -1;
1026
1027 /* `id' = `<class> *', `<class> *' = `id' */
1028
1029 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
1030 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
1031 return 1;
1032
1033 /* `id' = `Class', `Class' = `id' */
1034
1035 else if ((TYPE_NAME (lhs) == objc_object_id
1036 && TYPE_NAME (rhs) == objc_class_id)
1037 || (TYPE_NAME (lhs) == objc_class_id
1038 && TYPE_NAME (rhs) == objc_object_id))
1039 return 1;
1040
1041 /* `<class> *' = `<class> *' */
1042
1043 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
1044 {
1045 tree lname = TYPE_NAME (lhs);
1046 tree rname = TYPE_NAME (rhs);
1047 tree inter;
1048
1049 if (lname == rname)
1050 return 1;
1051
1052 /* If the left hand side is a super class of the right hand side,
1053 allow it. */
1054 for (inter = lookup_interface (rname); inter;
1055 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1056 if (lname == CLASS_SUPER_NAME (inter))
1057 return 1;
1058
1059 /* Allow the reverse when reflexive. */
1060 if (reflexive)
1061 for (inter = lookup_interface (lname); inter;
1062 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
1063 if (rname == CLASS_SUPER_NAME (inter))
1064 return 1;
1065
1066 return 0;
1067 }
1068 else
1069 /* Defer to comptypes. */
1070 return -1;
1071 }
1072
1073 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
1074
1075 void
1076 objc_check_decl (decl)
1077 tree decl;
1078 {
1079 tree type = TREE_TYPE (decl);
1080
1081 if (TREE_CODE (type) == RECORD_TYPE
1082 && TREE_STATIC_TEMPLATE (type)
1083 && type != constant_string_type)
1084 {
1085 error_with_decl (decl, "`%s' cannot be statically allocated");
1086 fatal ("statically allocated objects not supported");
1087 }
1088 }
1089
1090 void
1091 maybe_objc_check_decl (decl)
1092 tree decl;
1093 {
1094 objc_check_decl (decl);
1095 }
1096
1097 /* Implement static typing. At this point, we know we have an interface. */
1098
1099 tree
1100 get_static_reference (interface, protocols)
1101 tree interface;
1102 tree protocols;
1103 {
1104 tree type = xref_tag (RECORD_TYPE, interface);
1105
1106 if (protocols)
1107 {
1108 tree t, m = TYPE_MAIN_VARIANT (type);
1109
1110 t = copy_node (type);
1111 TYPE_BINFO (t) = make_tree_vec (2);
1112
1113 /* Add this type to the chain of variants of TYPE. */
1114 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1115 TYPE_NEXT_VARIANT (m) = t;
1116
1117 /* Look up protocols and install in lang specific list. */
1118 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1119
1120 /* This forces a new pointer type to be created later
1121 (in build_pointer_type)...so that the new template
1122 we just created will actually be used...what a hack! */
1123 if (TYPE_POINTER_TO (t))
1124 TYPE_POINTER_TO (t) = 0;
1125
1126 type = t;
1127 }
1128
1129 return type;
1130 }
1131
1132 tree
1133 get_object_reference (protocols)
1134 tree protocols;
1135 {
1136 tree type_decl = lookup_name (objc_id_id);
1137 tree type;
1138
1139 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1140 {
1141 type = TREE_TYPE (type_decl);
1142 if (TYPE_MAIN_VARIANT (type) != id_type)
1143 warning ("Unexpected type for `id' (%s)",
1144 gen_declaration (type, errbuf));
1145 }
1146 else
1147 fatal ("Undefined type `id', please import <objc/objc.h>");
1148
1149 /* This clause creates a new pointer type that is qualified with
1150 the protocol specification...this info is used later to do more
1151 elaborate type checking. */
1152
1153 if (protocols)
1154 {
1155 tree t, m = TYPE_MAIN_VARIANT (type);
1156
1157 t = copy_node (type);
1158 TYPE_BINFO (t) = make_tree_vec (2);
1159
1160 /* Add this type to the chain of variants of TYPE. */
1161 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1162 TYPE_NEXT_VARIANT (m) = t;
1163
1164 /* Look up protocols...and install in lang specific list */
1165 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1166
1167 /* This forces a new pointer type to be created later
1168 (in build_pointer_type)...so that the new template
1169 we just created will actually be used...what a hack! */
1170 if (TYPE_POINTER_TO (t))
1171 TYPE_POINTER_TO (t) = NULL;
1172
1173 type = t;
1174 }
1175 return type;
1176 }
1177
1178 static tree
1179 lookup_and_install_protocols (protocols)
1180 tree protocols;
1181 {
1182 tree proto;
1183 tree prev = NULL;
1184 tree return_value = protocols;
1185
1186 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1187 {
1188 tree ident = TREE_VALUE (proto);
1189 tree p = lookup_protocol (ident);
1190
1191 if (!p)
1192 {
1193 error ("Cannot find protocol declaration for `%s'",
1194 IDENTIFIER_POINTER (ident));
1195 if (prev)
1196 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1197 else
1198 return_value = TREE_CHAIN (proto);
1199 }
1200 else
1201 {
1202 /* Replace identifier with actual protocol node. */
1203 TREE_VALUE (proto) = p;
1204 prev = proto;
1205 }
1206 }
1207
1208 return return_value;
1209 }
1210
1211 /* Create and push a decl for a built-in external variable or field NAME.
1212 CODE says which.
1213 TYPE is its data type. */
1214
1215 static tree
1216 create_builtin_decl (code, type, name)
1217 enum tree_code code;
1218 tree type;
1219 const char *name;
1220 {
1221 tree decl = build_decl (code, get_identifier (name), type);
1222
1223 if (code == VAR_DECL)
1224 {
1225 TREE_STATIC (decl) = 1;
1226 make_decl_rtl (decl, 0, 1);
1227 pushdecl (decl);
1228 }
1229
1230 DECL_ARTIFICIAL (decl) = 1;
1231 return decl;
1232 }
1233
1234 /* Purpose: "play" parser, creating/installing representations
1235 of the declarations that are required by Objective-C.
1236
1237 Model:
1238
1239 type_spec--------->sc_spec
1240 (tree_list) (tree_list)
1241 | |
1242 | |
1243 identifier_node identifier_node */
1244
1245 static void
1246 synth_module_prologue ()
1247 {
1248 tree temp_type;
1249 tree super_p;
1250
1251 /* Defined in `objc.h' */
1252 objc_object_id = get_identifier (TAG_OBJECT);
1253
1254 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1255
1256 id_type = build_pointer_type (objc_object_reference);
1257
1258 objc_id_id = get_identifier (TYPE_ID);
1259 objc_class_id = get_identifier (TAG_CLASS);
1260
1261 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1262 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1263 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1264
1265 /* Declare type of selector-objects that represent an operation name. */
1266
1267 #ifdef OBJC_INT_SELECTORS
1268 /* `unsigned int' */
1269 selector_type = unsigned_type_node;
1270 #else
1271 /* `struct objc_selector *' */
1272 selector_type
1273 = build_pointer_type (xref_tag (RECORD_TYPE,
1274 get_identifier (TAG_SELECTOR)));
1275 #endif /* not OBJC_INT_SELECTORS */
1276
1277 /* Forward declare type, or else the prototype for msgSendSuper will
1278 complain. */
1279
1280 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1281 get_identifier (TAG_SUPER)));
1282
1283
1284 /* id objc_msgSend (id, SEL, ...); */
1285
1286 temp_type
1287 = build_function_type (id_type,
1288 tree_cons (NULL_TREE, id_type,
1289 tree_cons (NULL_TREE, selector_type,
1290 NULL_TREE)));
1291
1292 if (! flag_next_runtime)
1293 {
1294 umsg_decl = build_decl (FUNCTION_DECL,
1295 get_identifier (TAG_MSGSEND), temp_type);
1296 DECL_EXTERNAL (umsg_decl) = 1;
1297 TREE_PUBLIC (umsg_decl) = 1;
1298 DECL_INLINE (umsg_decl) = 1;
1299 DECL_ARTIFICIAL (umsg_decl) = 1;
1300
1301 if (flag_traditional && TAG_MSGSEND[0] != '_')
1302 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1303
1304 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1305 pushdecl (umsg_decl);
1306 }
1307 else
1308 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
1309
1310 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1311
1312 temp_type
1313 = build_function_type (id_type,
1314 tree_cons (NULL_TREE, super_p,
1315 tree_cons (NULL_TREE, selector_type,
1316 NULL_TREE)));
1317
1318 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1319 temp_type, 0, NOT_BUILT_IN, 0);
1320
1321 /* id objc_getClass (const char *); */
1322
1323 temp_type = build_function_type (id_type,
1324 tree_cons (NULL_TREE,
1325 const_string_type_node,
1326 tree_cons (NULL_TREE, void_type_node,
1327 NULL_TREE)));
1328
1329 objc_get_class_decl
1330 = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
1331
1332 /* id objc_getMetaClass (const char *); */
1333
1334 objc_get_meta_class_decl
1335 = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
1336
1337 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1338
1339 if (! flag_next_runtime)
1340 {
1341 if (flag_typed_selectors)
1342 {
1343 /* Suppress outputting debug symbols, because
1344 dbxout_init hasn'r been called yet. */
1345 enum debug_info_type save_write_symbols = write_symbols;
1346 write_symbols = NO_DEBUG;
1347
1348 build_selector_template ();
1349 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1350
1351 write_symbols = save_write_symbols;
1352 }
1353 else
1354 temp_type = build_array_type (selector_type, NULL_TREE);
1355
1356 layout_type (temp_type);
1357 UOBJC_SELECTOR_TABLE_decl
1358 = create_builtin_decl (VAR_DECL, temp_type,
1359 "_OBJC_SELECTOR_TABLE");
1360
1361 /* Avoid warning when not sending messages. */
1362 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1363 }
1364
1365 generate_forward_declaration_to_string_table ();
1366
1367 /* Forward declare constant_string_id and constant_string_type. */
1368 if (!constant_string_class_name)
1369 constant_string_class_name = STRING_OBJECT_CLASS_NAME;
1370
1371 constant_string_id = get_identifier (constant_string_class_name);
1372 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1373 }
1374
1375 /* Custom build_string which sets TREE_TYPE! */
1376
1377 static tree
1378 my_build_string (len, str)
1379 int len;
1380 const char *str;
1381 {
1382 int wide_flag = 0;
1383 tree a_string = build_string (len, str);
1384
1385 /* Some code from combine_strings, which is local to c-parse.y. */
1386 if (TREE_TYPE (a_string) == int_array_type_node)
1387 wide_flag = 1;
1388
1389 TREE_TYPE (a_string)
1390 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1391 build_index_type (build_int_2 (len - 1, 0)));
1392
1393 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1394 TREE_STATIC (a_string) = 1;
1395
1396 return a_string;
1397 }
1398
1399 /* Given a chain of STRING_CST's, build a static instance of
1400 NXConstanString which points at the concatenation of those strings.
1401 We place the string object in the __string_objects section of the
1402 __OBJC segment. The Objective-C runtime will initialize the isa
1403 pointers of the string objects to point at the NXConstandString class
1404 object. */
1405
1406 tree
1407 build_objc_string_object (strings)
1408 tree strings;
1409 {
1410 tree string, initlist, constructor;
1411 int length;
1412
1413 if (lookup_interface (constant_string_id) == NULL_TREE)
1414 {
1415 error ("Cannot find interface declaration for `%s'",
1416 IDENTIFIER_POINTER (constant_string_id));
1417 return error_mark_node;
1418 }
1419
1420 add_class_reference (constant_string_id);
1421
1422 string = combine_strings (strings);
1423 TREE_SET_CODE (string, STRING_CST);
1424 length = TREE_STRING_LENGTH (string) - 1;
1425
1426 /* & ((NXConstantString) {0, string, length}) */
1427
1428 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1429 initlist
1430 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1431 initlist);
1432 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1433 constructor = build_constructor (constant_string_type, nreverse (initlist));
1434
1435 if (!flag_next_runtime)
1436 {
1437 constructor
1438 = objc_add_static_instance (constructor, constant_string_type);
1439 }
1440
1441 return (build_unary_op (ADDR_EXPR, constructor, 1));
1442 }
1443
1444 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1445
1446 static tree
1447 objc_add_static_instance (constructor, class_decl)
1448 tree constructor, class_decl;
1449 {
1450 static int num_static_inst;
1451 tree *chain, decl;
1452 char buf[256];
1453
1454 /* Find the list of static instances for the CLASS_DECL. Create one if
1455 not found. */
1456 for (chain = &objc_static_instances;
1457 *chain && TREE_VALUE (*chain) != class_decl;
1458 chain = &TREE_CHAIN (*chain));
1459 if (!*chain)
1460 {
1461 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1462 add_objc_string (TYPE_NAME (class_decl), class_names);
1463 }
1464
1465 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1466 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1467 DECL_COMMON (decl) = 1;
1468 TREE_STATIC (decl) = 1;
1469 DECL_ARTIFICIAL (decl) = 1;
1470 pushdecl_top_level (decl);
1471 rest_of_decl_compilation (decl, 0, 1, 0);
1472
1473 /* Do this here so it gets output later instead of possibly
1474 inside something else we are writing. */
1475 DECL_INITIAL (decl) = constructor;
1476
1477 /* Add the DECL to the head of this CLASS' list. */
1478 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1479
1480 return decl;
1481 }
1482
1483 /* Build a static constant CONSTRUCTOR
1484 with type TYPE and elements ELTS. */
1485
1486 static tree
1487 build_constructor (type, elts)
1488 tree type, elts;
1489 {
1490 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1491
1492 TREE_CONSTANT (constructor) = 1;
1493 TREE_STATIC (constructor) = 1;
1494 TREE_READONLY (constructor) = 1;
1495
1496 return constructor;
1497 }
1498 \f
1499 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1500
1501 /* Predefine the following data type:
1502
1503 struct _objc_symtab
1504 {
1505 long sel_ref_cnt;
1506 SEL *refs;
1507 short cls_def_cnt;
1508 short cat_def_cnt;
1509 void *defs[cls_def_cnt + cat_def_cnt];
1510 }; */
1511
1512 static void
1513 build_objc_symtab_template ()
1514 {
1515 tree field_decl, field_decl_chain, index;
1516
1517 objc_symtab_template
1518 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1519
1520 /* long sel_ref_cnt; */
1521
1522 field_decl = create_builtin_decl (FIELD_DECL,
1523 long_integer_type_node,
1524 "sel_ref_cnt");
1525 field_decl_chain = field_decl;
1526
1527 /* SEL *refs; */
1528
1529 field_decl = create_builtin_decl (FIELD_DECL,
1530 build_pointer_type (selector_type),
1531 "refs");
1532 chainon (field_decl_chain, field_decl);
1533
1534 /* short cls_def_cnt; */
1535
1536 field_decl = create_builtin_decl (FIELD_DECL,
1537 short_integer_type_node,
1538 "cls_def_cnt");
1539 chainon (field_decl_chain, field_decl);
1540
1541 /* short cat_def_cnt; */
1542
1543 field_decl = create_builtin_decl (FIELD_DECL,
1544 short_integer_type_node,
1545 "cat_def_cnt");
1546 chainon (field_decl_chain, field_decl);
1547
1548 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1549
1550 if (!flag_next_runtime)
1551 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1552 else
1553 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1554 imp_count == 0 && cat_count == 0
1555 ? -1 : 0));
1556 field_decl = create_builtin_decl (FIELD_DECL,
1557 build_array_type (ptr_type_node, index),
1558 "defs");
1559 chainon (field_decl_chain, field_decl);
1560
1561 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1562 }
1563
1564 /* Create the initial value for the `defs' field of _objc_symtab.
1565 This is a CONSTRUCTOR. */
1566
1567 static tree
1568 init_def_list (type)
1569 tree type;
1570 {
1571 tree expr, initlist = NULL_TREE;
1572 struct imp_entry *impent;
1573
1574 if (imp_count)
1575 for (impent = imp_list; impent; impent = impent->next)
1576 {
1577 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1578 {
1579 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1580 initlist = tree_cons (NULL_TREE, expr, initlist);
1581 }
1582 }
1583
1584 if (cat_count)
1585 for (impent = imp_list; impent; impent = impent->next)
1586 {
1587 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1588 {
1589 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1590 initlist = tree_cons (NULL_TREE, expr, initlist);
1591 }
1592 }
1593
1594 if (!flag_next_runtime)
1595 {
1596 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1597 tree expr;
1598
1599 if (static_instances_decl)
1600 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1601 else
1602 expr = build_int_2 (0, 0);
1603
1604 initlist = tree_cons (NULL_TREE, expr, initlist);
1605 }
1606
1607 return build_constructor (type, nreverse (initlist));
1608 }
1609
1610 /* Construct the initial value for all of _objc_symtab. */
1611
1612 static tree
1613 init_objc_symtab (type)
1614 tree type;
1615 {
1616 tree initlist;
1617
1618 /* sel_ref_cnt = { ..., 5, ... } */
1619
1620 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1621
1622 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1623
1624 if (flag_next_runtime || ! sel_ref_chain)
1625 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1626 else
1627 initlist = tree_cons (NULL_TREE,
1628 build_unary_op (ADDR_EXPR,
1629 UOBJC_SELECTOR_TABLE_decl, 1),
1630 initlist);
1631
1632 /* cls_def_cnt = { ..., 5, ... } */
1633
1634 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1635
1636 /* cat_def_cnt = { ..., 5, ... } */
1637
1638 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1639
1640 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1641
1642 if (imp_count || cat_count || static_instances_decl)
1643 {
1644
1645 tree field = TYPE_FIELDS (type);
1646 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1647
1648 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1649 initlist);
1650 }
1651
1652 return build_constructor (type, nreverse (initlist));
1653 }
1654
1655 /* Push forward-declarations of all the categories
1656 so that init_def_list can use them in a CONSTRUCTOR. */
1657
1658 static void
1659 forward_declare_categories ()
1660 {
1661 struct imp_entry *impent;
1662 tree sav = implementation_context;
1663
1664 for (impent = imp_list; impent; impent = impent->next)
1665 {
1666 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1667 {
1668 /* Set an invisible arg to synth_id_with_class_suffix. */
1669 implementation_context = impent->imp_context;
1670 impent->class_decl
1671 = create_builtin_decl (VAR_DECL, objc_category_template,
1672 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1673 }
1674 }
1675 implementation_context = sav;
1676 }
1677
1678 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1679 and initialized appropriately. */
1680
1681 static void
1682 generate_objc_symtab_decl ()
1683 {
1684 tree sc_spec;
1685
1686 if (!objc_category_template)
1687 build_category_template ();
1688
1689 /* forward declare categories */
1690 if (cat_count)
1691 forward_declare_categories ();
1692
1693 if (!objc_symtab_template)
1694 build_objc_symtab_template ();
1695
1696 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1697
1698 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1699 tree_cons (NULL_TREE,
1700 objc_symtab_template, sc_spec),
1701 1,
1702 NULL_TREE, NULL_TREE);
1703
1704 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1705 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1706 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1707 finish_decl (UOBJC_SYMBOLS_decl,
1708 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1709 NULL_TREE);
1710 }
1711 \f
1712 static tree
1713 init_module_descriptor (type)
1714 tree type;
1715 {
1716 tree initlist, expr;
1717
1718 /* version = { 1, ... } */
1719
1720 expr = build_int_2 (OBJC_VERSION, 0);
1721 initlist = build_tree_list (NULL_TREE, expr);
1722
1723 /* size = { ..., sizeof (struct objc_module), ... } */
1724
1725 expr = size_in_bytes (objc_module_template);
1726 initlist = tree_cons (NULL_TREE, expr, initlist);
1727
1728 /* name = { ..., "foo.m", ... } */
1729
1730 expr = add_objc_string (get_identifier (input_filename), class_names);
1731 initlist = tree_cons (NULL_TREE, expr, initlist);
1732
1733 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1734
1735 if (UOBJC_SYMBOLS_decl)
1736 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1737 else
1738 expr = build_int_2 (0, 0);
1739 initlist = tree_cons (NULL_TREE, expr, initlist);
1740
1741 return build_constructor (type, nreverse (initlist));
1742 }
1743
1744 /* Write out the data structures to describe Objective C classes defined.
1745 If appropriate, compile and output a setup function to initialize them.
1746 Return a string which is the name of a function to call to initialize
1747 the Objective C data structures for this file (and perhaps for other files
1748 also).
1749
1750 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1751
1752 static const char *
1753 build_module_descriptor ()
1754 {
1755 tree decl_specs, field_decl, field_decl_chain;
1756
1757 objc_module_template
1758 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1759
1760 /* Long version; */
1761
1762 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1763 field_decl = get_identifier ("version");
1764 field_decl
1765 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1766 field_decl_chain = field_decl;
1767
1768 /* long size; */
1769
1770 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1771 field_decl = get_identifier ("size");
1772 field_decl
1773 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1774 chainon (field_decl_chain, field_decl);
1775
1776 /* char *name; */
1777
1778 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1779 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1780 field_decl
1781 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1782 chainon (field_decl_chain, field_decl);
1783
1784 /* struct objc_symtab *symtab; */
1785
1786 decl_specs = get_identifier (UTAG_SYMTAB);
1787 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1788 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1789 field_decl
1790 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1791 chainon (field_decl_chain, field_decl);
1792
1793 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1794
1795 /* Create an instance of "objc_module". */
1796
1797 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1798 build_tree_list (NULL_TREE,
1799 ridpointers[(int) RID_STATIC]));
1800
1801 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1802 decl_specs, 1, NULL_TREE, NULL_TREE);
1803
1804 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1805 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1806 finish_decl (UOBJC_MODULES_decl,
1807 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1808 NULL_TREE);
1809
1810 /* Mark the decl to avoid "defined but not used" warning. */
1811 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1812
1813 /* Generate a constructor call for the module descriptor.
1814 This code was generated by reading the grammar rules
1815 of c-parse.in; Therefore, it may not be the most efficient
1816 way of generating the requisite code. */
1817
1818 if (flag_next_runtime)
1819 return 0;
1820
1821 {
1822 tree parms, function_decl, decelerator, void_list_node_1;
1823 tree function_type;
1824 tree init_function_name = get_file_function_name ('I');
1825
1826 /* Declare void __objc_execClass (void *); */
1827
1828 void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1829 function_type
1830 = build_function_type (void_type_node,
1831 tree_cons (NULL_TREE, ptr_type_node,
1832 void_list_node_1));
1833 function_decl = build_decl (FUNCTION_DECL,
1834 get_identifier (TAG_EXECCLASS),
1835 function_type);
1836 DECL_EXTERNAL (function_decl) = 1;
1837 DECL_ARTIFICIAL (function_decl) = 1;
1838 TREE_PUBLIC (function_decl) = 1;
1839
1840 pushdecl (function_decl);
1841 rest_of_decl_compilation (function_decl, 0, 0, 0);
1842
1843 parms
1844 = build_tree_list (NULL_TREE,
1845 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1846 decelerator = build_function_call (function_decl, parms);
1847
1848 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1849
1850 start_function (void_list_node_1,
1851 build_parse_node (CALL_EXPR, init_function_name,
1852 /* This has the format of the output
1853 of get_parm_info. */
1854 tree_cons (NULL_TREE, NULL_TREE,
1855 void_list_node_1),
1856 NULL_TREE),
1857 NULL_TREE, NULL_TREE);
1858 #if 0 /* This should be turned back on later
1859 for the systems where collect is not needed. */
1860 /* Make these functions nonglobal
1861 so each file can use the same name. */
1862 TREE_PUBLIC (current_function_decl) = 0;
1863 #endif
1864 TREE_USED (current_function_decl) = 1;
1865 store_parm_decls ();
1866
1867 assemble_external (function_decl);
1868 c_expand_expr_stmt (decelerator);
1869
1870 TREE_PUBLIC (current_function_decl) = 1;
1871
1872 function_decl = current_function_decl;
1873 finish_function (0);
1874
1875 /* Return the name of the constructor function. */
1876 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1877 }
1878 }
1879
1880 /* extern const char _OBJC_STRINGS[]; */
1881
1882 static void
1883 generate_forward_declaration_to_string_table ()
1884 {
1885 tree sc_spec, decl_specs, expr_decl;
1886
1887 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1888 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1889
1890 expr_decl
1891 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1892
1893 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1894 }
1895
1896 /* Return the DECL of the string IDENT in the SECTION. */
1897
1898 static tree
1899 get_objc_string_decl (ident, section)
1900 tree ident;
1901 enum string_section section;
1902 {
1903 tree chain;
1904
1905 if (section == class_names)
1906 chain = class_names_chain;
1907 else if (section == meth_var_names)
1908 chain = meth_var_names_chain;
1909 else if (section == meth_var_types)
1910 chain = meth_var_types_chain;
1911 else
1912 abort ();
1913
1914 for (; chain != 0; chain = TREE_VALUE (chain))
1915 if (TREE_VALUE (chain) == ident)
1916 return (TREE_PURPOSE (chain));
1917
1918 abort ();
1919 return NULL_TREE;
1920 }
1921
1922 /* Output references to all statically allocated objects. Return the DECL
1923 for the array built. */
1924
1925 static void
1926 generate_static_references ()
1927 {
1928 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1929 tree class_name, class, decl, initlist;
1930 tree cl_chain, in_chain, type;
1931 int num_inst, num_class;
1932 char buf[256];
1933
1934 if (flag_next_runtime)
1935 abort ();
1936
1937 for (cl_chain = objc_static_instances, num_class = 0;
1938 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1939 {
1940 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1941 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1942
1943 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1944 ident = get_identifier (buf);
1945
1946 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1947 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1948 build_tree_list (NULL_TREE,
1949 ridpointers[(int) RID_STATIC]));
1950 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1951 DECL_CONTEXT (decl) = 0;
1952 DECL_ARTIFICIAL (decl) = 1;
1953
1954 /* Output {class_name, ...}. */
1955 class = TREE_VALUE (cl_chain);
1956 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1957 initlist = build_tree_list (NULL_TREE,
1958 build_unary_op (ADDR_EXPR, class_name, 1));
1959
1960 /* Output {..., instance, ...}. */
1961 for (in_chain = TREE_PURPOSE (cl_chain);
1962 in_chain; in_chain = TREE_CHAIN (in_chain))
1963 {
1964 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1965 initlist = tree_cons (NULL_TREE, expr, initlist);
1966 }
1967
1968 /* Output {..., NULL}. */
1969 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1970
1971 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1972 finish_decl (decl, expr, NULL_TREE);
1973 TREE_USED (decl) = 1;
1974
1975 type = build_array_type (build_pointer_type (void_type_node), 0);
1976 decl = build_decl (VAR_DECL, ident, type);
1977 make_decl_rtl (decl, 0, 1);
1978 TREE_USED (decl) = 1;
1979 decls
1980 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1981 }
1982
1983 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1984 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1985 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1986 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1987 build_tree_list (NULL_TREE,
1988 ridpointers[(int) RID_STATIC]));
1989 static_instances_decl
1990 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1991 TREE_USED (static_instances_decl) = 1;
1992 DECL_CONTEXT (static_instances_decl) = 0;
1993 DECL_ARTIFICIAL (static_instances_decl) = 1;
1994 expr = build_constructor (TREE_TYPE (static_instances_decl),
1995 nreverse (decls));
1996 finish_decl (static_instances_decl, expr, NULL_TREE);
1997 }
1998
1999 /* Output all strings. */
2000
2001 static void
2002 generate_strings ()
2003 {
2004 tree sc_spec, decl_specs, expr_decl;
2005 tree chain, string_expr;
2006 tree string, decl;
2007
2008 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2009 {
2010 string = TREE_VALUE (chain);
2011 decl = TREE_PURPOSE (chain);
2012 sc_spec
2013 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2014 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2015 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2016 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2017 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2018 IDENTIFIER_POINTER (string));
2019 finish_decl (decl, string_expr, NULL_TREE);
2020 }
2021
2022 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2023 {
2024 string = TREE_VALUE (chain);
2025 decl = TREE_PURPOSE (chain);
2026 sc_spec
2027 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2028 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2029 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2030 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2031 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2032 IDENTIFIER_POINTER (string));
2033 finish_decl (decl, string_expr, NULL_TREE);
2034 }
2035
2036 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2037 {
2038 string = TREE_VALUE (chain);
2039 decl = TREE_PURPOSE (chain);
2040 sc_spec
2041 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2042 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2043 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
2044 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2045 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2046 IDENTIFIER_POINTER (string));
2047 finish_decl (decl, string_expr, NULL_TREE);
2048 }
2049 }
2050
2051 static tree
2052 build_selector_reference_decl ()
2053 {
2054 tree decl, ident;
2055 char buf[256];
2056 static int idx = 0;
2057
2058 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
2059
2060 ident = get_identifier (buf);
2061
2062 decl = build_decl (VAR_DECL, ident, selector_type);
2063 DECL_EXTERNAL (decl) = 1;
2064 TREE_PUBLIC (decl) = 1;
2065 TREE_USED (decl) = 1;
2066 TREE_READONLY (decl) = 1;
2067 DECL_ARTIFICIAL (decl) = 1;
2068 DECL_CONTEXT (decl) = 0;
2069
2070 make_decl_rtl (decl, 0, 1);
2071 pushdecl_top_level (decl);
2072
2073 return decl;
2074 }
2075
2076 /* Just a handy wrapper for add_objc_string. */
2077
2078 static tree
2079 build_selector (ident)
2080 tree ident;
2081 {
2082 tree expr = add_objc_string (ident, meth_var_names);
2083 if (flag_typed_selectors)
2084 return expr;
2085 else
2086 return build_c_cast (selector_type, expr); /* cast! */
2087 }
2088
2089 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
2090 The cast stops the compiler from issuing the following message:
2091 grok.m: warning: initialization of non-const * pointer from const *
2092 grok.m: warning: initialization between incompatible pointer types. */
2093
2094 #if 0
2095 static tree
2096 build_msg_pool_reference (offset)
2097 int offset;
2098 {
2099 tree expr = build_int_2 (offset, 0);
2100 tree cast;
2101
2102 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
2103 expr = build_unary_op (ADDR_EXPR, expr, 0);
2104
2105 cast = build_tree_list (build_tree_list (NULL_TREE,
2106 ridpointers[(int) RID_CHAR]),
2107 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
2108 TREE_TYPE (expr) = groktypename (cast);
2109 return expr;
2110 }
2111
2112 static tree
2113 init_selector (offset)
2114 int offset;
2115 {
2116 tree expr = build_msg_pool_reference (offset);
2117 TREE_TYPE (expr) = selector_type;
2118 return expr;
2119 }
2120 #endif
2121
2122 static void
2123 build_selector_translation_table ()
2124 {
2125 tree sc_spec, decl_specs;
2126 tree chain, initlist = NULL_TREE;
2127 int offset = 0;
2128 tree decl = NULL_TREE, var_decl, name;
2129
2130 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2131 {
2132 tree expr;
2133
2134 expr = build_selector (TREE_VALUE (chain));
2135
2136 if (flag_next_runtime)
2137 {
2138 name = DECL_NAME (TREE_PURPOSE (chain));
2139
2140 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2141
2142 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2143 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2144
2145 var_decl = name;
2146
2147 /* The `decl' that is returned from start_decl is the one that we
2148 forward declared in `build_selector_reference' */
2149 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2150 }
2151
2152 /* add one for the '\0' character */
2153 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2154
2155 if (flag_next_runtime)
2156 finish_decl (decl, expr, NULL_TREE);
2157 else
2158 {
2159 if (flag_typed_selectors)
2160 {
2161 tree eltlist = NULL_TREE;
2162 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2163 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2164 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2165 expr = build_constructor (objc_selector_template,
2166 nreverse (eltlist));
2167 }
2168 initlist = tree_cons (NULL_TREE, expr, initlist);
2169
2170 }
2171 }
2172
2173 if (! flag_next_runtime)
2174 {
2175 /* Cause the variable and its initial value to be actually output. */
2176 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2177 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2178 /* NULL terminate the list and fix the decl for output. */
2179 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2180 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
2181 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2182 nreverse (initlist));
2183 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2184 current_function_decl = NULL_TREE;
2185 }
2186 }
2187
2188 static tree
2189 get_proto_encoding (proto)
2190 tree proto;
2191 {
2192 tree encoding;
2193 if (proto)
2194 {
2195 tree tmp_decl;
2196
2197 if (! METHOD_ENCODING (proto))
2198 {
2199 tmp_decl = build_tmp_function_decl ();
2200 hack_method_prototype (proto, tmp_decl);
2201 encoding = encode_method_prototype (proto, tmp_decl);
2202 METHOD_ENCODING (proto) = encoding;
2203 }
2204 else
2205 encoding = METHOD_ENCODING (proto);
2206
2207 return add_objc_string (encoding, meth_var_types);
2208 }
2209 else
2210 return build_int_2 (0, 0);
2211 }
2212
2213 /* sel_ref_chain is a list whose "value" fields will be instances of
2214 identifier_node that represent the selector. */
2215
2216 static tree
2217 build_typed_selector_reference (ident, proto)
2218 tree ident, proto;
2219 {
2220 tree *chain = &sel_ref_chain;
2221 tree expr;
2222 int index = 0;
2223
2224 while (*chain)
2225 {
2226 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2227 goto return_at_index;
2228
2229 index++;
2230 chain = &TREE_CHAIN (*chain);
2231 }
2232
2233 *chain = tree_cons (proto, ident, NULL_TREE);
2234
2235 return_at_index:
2236 expr = build_unary_op (ADDR_EXPR,
2237 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2238 build_int_2 (index, 0)),
2239 1);
2240 return build_c_cast (selector_type, expr);
2241 }
2242
2243 static tree
2244 build_selector_reference (ident)
2245 tree ident;
2246 {
2247 tree *chain = &sel_ref_chain;
2248 tree expr;
2249 int index = 0;
2250
2251 while (*chain)
2252 {
2253 if (TREE_VALUE (*chain) == ident)
2254 return (flag_next_runtime
2255 ? TREE_PURPOSE (*chain)
2256 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2257 build_int_2 (index, 0)));
2258
2259 index++;
2260 chain = &TREE_CHAIN (*chain);
2261 }
2262
2263 expr = build_selector_reference_decl ();
2264
2265 *chain = tree_cons (expr, ident, NULL_TREE);
2266
2267 return (flag_next_runtime
2268 ? expr
2269 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2270 build_int_2 (index, 0)));
2271 }
2272
2273 static tree
2274 build_class_reference_decl ()
2275 {
2276 tree decl, ident;
2277 char buf[256];
2278 static int idx = 0;
2279
2280 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2281
2282 ident = get_identifier (buf);
2283
2284 decl = build_decl (VAR_DECL, ident, objc_class_type);
2285 DECL_EXTERNAL (decl) = 1;
2286 TREE_PUBLIC (decl) = 1;
2287 TREE_USED (decl) = 1;
2288 TREE_READONLY (decl) = 1;
2289 DECL_CONTEXT (decl) = 0;
2290 DECL_ARTIFICIAL (decl) = 1;
2291
2292 make_decl_rtl (decl, 0, 1);
2293 pushdecl_top_level (decl);
2294
2295 return decl;
2296 }
2297
2298 /* Create a class reference, but don't create a variable to reference
2299 it. */
2300
2301 static void
2302 add_class_reference (ident)
2303 tree ident;
2304 {
2305 tree chain;
2306
2307 if ((chain = cls_ref_chain))
2308 {
2309 tree tail;
2310 do
2311 {
2312 if (ident == TREE_VALUE (chain))
2313 return;
2314
2315 tail = chain;
2316 chain = TREE_CHAIN (chain);
2317 }
2318 while (chain);
2319
2320 /* Append to the end of the list */
2321 TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
2322 }
2323 else
2324 cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
2325 }
2326
2327 /* Get a class reference, creating it if necessary. Also create the
2328 reference variable. */
2329
2330 tree
2331 get_class_reference (ident)
2332 tree ident;
2333 {
2334 if (flag_next_runtime)
2335 {
2336 tree *chain;
2337 tree decl;
2338
2339 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2340 if (TREE_VALUE (*chain) == ident)
2341 {
2342 if (! TREE_PURPOSE (*chain))
2343 TREE_PURPOSE (*chain) = build_class_reference_decl ();
2344
2345 return TREE_PURPOSE (*chain);
2346 }
2347
2348 decl = build_class_reference_decl ();
2349 *chain = tree_cons (decl, ident, NULL_TREE);
2350 return decl;
2351 }
2352 else
2353 {
2354 tree params;
2355
2356 add_class_reference (ident);
2357
2358 params = build_tree_list (NULL_TREE,
2359 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2360 IDENTIFIER_POINTER (ident)));
2361
2362 assemble_external (objc_get_class_decl);
2363 return build_function_call (objc_get_class_decl, params);
2364 }
2365 }
2366
2367 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2368 of identifier_node that represent the selector. It returns the
2369 offset of the selector from the beginning of the _OBJC_STRINGS
2370 pool. This offset is typically used by init_selector during code
2371 generation.
2372
2373 For each string section we have a chain which maps identifier nodes
2374 to decls for the strings. */
2375
2376 static tree
2377 add_objc_string (ident, section)
2378 tree ident;
2379 enum string_section section;
2380 {
2381 tree *chain, decl;
2382
2383 if (section == class_names)
2384 chain = &class_names_chain;
2385 else if (section == meth_var_names)
2386 chain = &meth_var_names_chain;
2387 else if (section == meth_var_types)
2388 chain = &meth_var_types_chain;
2389 else
2390 abort ();
2391
2392 while (*chain)
2393 {
2394 if (TREE_VALUE (*chain) == ident)
2395 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2396
2397 chain = &TREE_CHAIN (*chain);
2398 }
2399
2400 decl = build_objc_string_decl (section);
2401
2402 *chain = tree_cons (decl, ident, NULL_TREE);
2403
2404 return build_unary_op (ADDR_EXPR, decl, 1);
2405 }
2406
2407 static tree
2408 build_objc_string_decl (section)
2409 enum string_section section;
2410 {
2411 tree decl, ident;
2412 char buf[256];
2413 static int class_names_idx = 0;
2414 static int meth_var_names_idx = 0;
2415 static int meth_var_types_idx = 0;
2416
2417 if (section == class_names)
2418 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2419 else if (section == meth_var_names)
2420 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2421 else if (section == meth_var_types)
2422 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2423
2424 ident = get_identifier (buf);
2425
2426 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2427 DECL_EXTERNAL (decl) = 1;
2428 TREE_PUBLIC (decl) = 1;
2429 TREE_USED (decl) = 1;
2430 TREE_READONLY (decl) = 1;
2431 TREE_CONSTANT (decl) = 1;
2432 DECL_CONTEXT (decl) = 0;
2433 DECL_ARTIFICIAL (decl) = 1;
2434
2435 make_decl_rtl (decl, 0, 1);
2436 pushdecl_top_level (decl);
2437
2438 return decl;
2439 }
2440
2441
2442 void
2443 objc_declare_alias (alias_ident, class_ident)
2444 tree alias_ident;
2445 tree class_ident;
2446 {
2447 if (is_class_name (class_ident) != class_ident)
2448 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2449 else if (is_class_name (alias_ident))
2450 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2451 else
2452 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2453 }
2454
2455 void
2456 objc_declare_class (ident_list)
2457 tree ident_list;
2458 {
2459 tree list;
2460
2461 for (list = ident_list; list; list = TREE_CHAIN (list))
2462 {
2463 tree ident = TREE_VALUE (list);
2464 tree decl;
2465
2466 if ((decl = lookup_name (ident)))
2467 {
2468 error ("`%s' redeclared as different kind of symbol",
2469 IDENTIFIER_POINTER (ident));
2470 error_with_decl (decl, "previous declaration of `%s'");
2471 }
2472
2473 if (! is_class_name (ident))
2474 {
2475 tree record = xref_tag (RECORD_TYPE, ident);
2476 TREE_STATIC_TEMPLATE (record) = 1;
2477 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2478 }
2479 }
2480 }
2481
2482 tree
2483 is_class_name (ident)
2484 tree ident;
2485 {
2486 tree chain;
2487
2488 if (lookup_interface (ident))
2489 return ident;
2490
2491 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2492 {
2493 if (ident == TREE_VALUE (chain))
2494 return ident;
2495 }
2496
2497 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2498 {
2499 if (ident == TREE_VALUE (chain))
2500 return TREE_PURPOSE (chain);
2501 }
2502
2503 return 0;
2504 }
2505
2506 tree
2507 lookup_interface (ident)
2508 tree ident;
2509 {
2510 tree chain;
2511
2512 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2513 {
2514 if (ident == CLASS_NAME (chain))
2515 return chain;
2516 }
2517 return NULL_TREE;
2518 }
2519
2520 static tree
2521 objc_copy_list (list, head)
2522 tree list;
2523 tree *head;
2524 {
2525 tree newlist = NULL_TREE, tail = NULL_TREE;
2526
2527 while (list)
2528 {
2529 tail = copy_node (list);
2530
2531 /* The following statement fixes a bug when inheriting instance
2532 variables that are declared to be bitfields. finish_struct
2533 expects to find the width of the bitfield in DECL_INITIAL. */
2534 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2535 DECL_INITIAL (tail) = DECL_SIZE (tail);
2536
2537 newlist = chainon (newlist, tail);
2538 list = TREE_CHAIN (list);
2539 }
2540
2541 *head = newlist;
2542 return tail;
2543 }
2544
2545 /* Used by: build_private_template, get_class_ivars, and
2546 continue_class. COPY is 1 when called from @defs. In this case
2547 copy all fields. Otherwise don't copy leaf ivars since we rely on
2548 them being side-effected exactly once by finish_struct. */
2549
2550 static tree
2551 build_ivar_chain (interface, copy)
2552 tree interface;
2553 int copy;
2554 {
2555 tree my_name, super_name, ivar_chain;
2556
2557 my_name = CLASS_NAME (interface);
2558 super_name = CLASS_SUPER_NAME (interface);
2559
2560 /* Possibly copy leaf ivars. */
2561 if (copy)
2562 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2563 else
2564 ivar_chain = CLASS_IVARS (interface);
2565
2566 while (super_name)
2567 {
2568 tree op1;
2569 tree super_interface = lookup_interface (super_name);
2570
2571 if (!super_interface)
2572 {
2573 /* fatal did not work with 2 args...should fix */
2574 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2575 IDENTIFIER_POINTER (super_name),
2576 IDENTIFIER_POINTER (my_name));
2577 exit (FATAL_EXIT_CODE);
2578 }
2579
2580 if (super_interface == interface)
2581 {
2582 fatal ("Circular inheritance in interface declaration for `%s'",
2583 IDENTIFIER_POINTER (super_name));
2584 }
2585
2586 interface = super_interface;
2587 my_name = CLASS_NAME (interface);
2588 super_name = CLASS_SUPER_NAME (interface);
2589
2590 op1 = CLASS_IVARS (interface);
2591 if (op1)
2592 {
2593 tree head, tail = objc_copy_list (op1, &head);
2594
2595 /* Prepend super class ivars...make a copy of the list, we
2596 do not want to alter the original. */
2597 TREE_CHAIN (tail) = ivar_chain;
2598 ivar_chain = head;
2599 }
2600 }
2601 return ivar_chain;
2602 }
2603
2604 /* struct <classname> {
2605 struct objc_class *isa;
2606 ...
2607 }; */
2608
2609 static tree
2610 build_private_template (class)
2611 tree class;
2612 {
2613 tree ivar_context;
2614
2615 if (CLASS_STATIC_TEMPLATE (class))
2616 {
2617 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2618 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2619 }
2620 else
2621 {
2622 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2623
2624 ivar_context = build_ivar_chain (class, 0);
2625
2626 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2627
2628 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2629
2630 /* mark this record as class template - for class type checking */
2631 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2632 }
2633
2634 instance_type
2635 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2636 uprivate_record),
2637 build1 (INDIRECT_REF, NULL_TREE,
2638 NULL_TREE)));
2639
2640 return ivar_context;
2641 }
2642 \f
2643 /* Begin code generation for protocols... */
2644
2645 /* struct objc_protocol {
2646 char *protocol_name;
2647 struct objc_protocol **protocol_list;
2648 struct objc_method_desc *instance_methods;
2649 struct objc_method_desc *class_methods;
2650 }; */
2651
2652 static tree
2653 build_protocol_template ()
2654 {
2655 tree decl_specs, field_decl, field_decl_chain;
2656 tree template;
2657
2658 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2659
2660 /* struct objc_class *isa; */
2661
2662 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2663 get_identifier (UTAG_CLASS)));
2664 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2665 field_decl
2666 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2667 field_decl_chain = field_decl;
2668
2669 /* char *protocol_name; */
2670
2671 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2672 field_decl
2673 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2674 field_decl
2675 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2676 chainon (field_decl_chain, field_decl);
2677
2678 /* struct objc_protocol **protocol_list; */
2679
2680 decl_specs = build_tree_list (NULL_TREE, template);
2681 field_decl
2682 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2683 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2684 field_decl
2685 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2686 chainon (field_decl_chain, field_decl);
2687
2688 /* struct objc_method_list *instance_methods; */
2689
2690 decl_specs
2691 = build_tree_list (NULL_TREE,
2692 xref_tag (RECORD_TYPE,
2693 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2694 field_decl
2695 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2696 field_decl
2697 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2698 chainon (field_decl_chain, field_decl);
2699
2700 /* struct objc_method_list *class_methods; */
2701
2702 decl_specs
2703 = build_tree_list (NULL_TREE,
2704 xref_tag (RECORD_TYPE,
2705 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2706 field_decl
2707 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2708 field_decl
2709 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2710 chainon (field_decl_chain, field_decl);
2711
2712 return finish_struct (template, field_decl_chain, NULL_TREE);
2713 }
2714
2715 static tree
2716 build_descriptor_table_initializer (type, entries)
2717 tree type;
2718 tree entries;
2719 {
2720 tree initlist = NULL_TREE;
2721
2722 do
2723 {
2724 tree eltlist = NULL_TREE;
2725
2726 eltlist
2727 = tree_cons (NULL_TREE,
2728 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2729 eltlist
2730 = tree_cons (NULL_TREE,
2731 add_objc_string (METHOD_ENCODING (entries),
2732 meth_var_types),
2733 eltlist);
2734
2735 initlist
2736 = tree_cons (NULL_TREE,
2737 build_constructor (type, nreverse (eltlist)), initlist);
2738
2739 entries = TREE_CHAIN (entries);
2740 }
2741 while (entries);
2742
2743 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2744 }
2745
2746 /* struct objc_method_prototype_list {
2747 int count;
2748 struct objc_method_prototype {
2749 SEL name;
2750 char *types;
2751 } list[1];
2752 }; */
2753
2754 static tree
2755 build_method_prototype_list_template (list_type, size)
2756 tree list_type;
2757 int size;
2758 {
2759 tree objc_ivar_list_record;
2760 tree decl_specs, field_decl, field_decl_chain;
2761
2762 /* Generate an unnamed struct definition. */
2763
2764 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2765
2766 /* int method_count; */
2767
2768 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2769 field_decl = get_identifier ("method_count");
2770
2771 field_decl
2772 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2773 field_decl_chain = field_decl;
2774
2775 /* struct objc_method method_list[]; */
2776
2777 decl_specs = build_tree_list (NULL_TREE, list_type);
2778 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2779 build_int_2 (size, 0));
2780
2781 field_decl
2782 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2783 chainon (field_decl_chain, field_decl);
2784
2785 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2786
2787 return objc_ivar_list_record;
2788 }
2789
2790 static tree
2791 build_method_prototype_template ()
2792 {
2793 tree proto_record;
2794 tree decl_specs, field_decl, field_decl_chain;
2795
2796 proto_record
2797 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2798
2799 #ifdef OBJC_INT_SELECTORS
2800 /* unsigned int _cmd; */
2801 decl_specs
2802 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2803 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2804 field_decl = get_identifier ("_cmd");
2805 #else /* OBJC_INT_SELECTORS */
2806 /* struct objc_selector *_cmd; */
2807 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2808 get_identifier (TAG_SELECTOR)), NULL_TREE);
2809 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2810 #endif /* OBJC_INT_SELECTORS */
2811
2812 field_decl
2813 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2814 field_decl_chain = field_decl;
2815
2816 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2817 field_decl
2818 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2819 field_decl
2820 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2821 chainon (field_decl_chain, field_decl);
2822
2823 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2824
2825 return proto_record;
2826 }
2827
2828 /* True if last call to forwarding_offset yielded a register offset. */
2829 static int offset_is_register;
2830
2831 static int
2832 forwarding_offset (parm)
2833 tree parm;
2834 {
2835 int offset_in_bytes;
2836
2837 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2838 {
2839 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2840
2841 /* ??? Here we assume that the parm address is indexed
2842 off the frame pointer or arg pointer.
2843 If that is not true, we produce meaningless results,
2844 but do not crash. */
2845 if (GET_CODE (addr) == PLUS
2846 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2847 offset_in_bytes = INTVAL (XEXP (addr, 1));
2848 else
2849 offset_in_bytes = 0;
2850
2851 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2852 offset_is_register = 0;
2853 }
2854 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2855 {
2856 int regno = REGNO (DECL_INCOMING_RTL (parm));
2857 offset_in_bytes = apply_args_register_offset (regno);
2858 offset_is_register = 1;
2859 }
2860 else
2861 return 0;
2862
2863 /* This is the case where the parm is passed as an int or double
2864 and it is converted to a char, short or float and stored back
2865 in the parmlist. In this case, describe the parm
2866 with the variable's declared type, and adjust the address
2867 if the least significant bytes (which we are using) are not
2868 the first ones. */
2869 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2870 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2871 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2872
2873 return offset_in_bytes;
2874 }
2875
2876 static tree
2877 encode_method_prototype (method_decl, func_decl)
2878 tree method_decl;
2879 tree func_decl;
2880 {
2881 tree parms;
2882 int stack_size, i;
2883 tree user_args;
2884 HOST_WIDE_INT max_parm_end = 0;
2885 char buf[40];
2886 tree result;
2887
2888 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2889 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2890
2891 /* C type. */
2892 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2893 obstack_object_size (&util_obstack),
2894 OBJC_ENCODE_INLINE_DEFS);
2895
2896 /* Stack size. */
2897 for (parms = DECL_ARGUMENTS (func_decl); parms;
2898 parms = TREE_CHAIN (parms))
2899 {
2900 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
2901 + int_size_in_bytes (TREE_TYPE (parms)));
2902
2903 if (!offset_is_register && max_parm_end < parm_end)
2904 max_parm_end = parm_end;
2905 }
2906
2907 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2908
2909 sprintf (buf, "%d", stack_size);
2910 obstack_grow (&util_obstack, buf, strlen (buf));
2911
2912 user_args = METHOD_SEL_ARGS (method_decl);
2913
2914 /* Argument types. */
2915 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2916 parms = TREE_CHAIN (parms), i++)
2917 {
2918 /* Process argument qualifiers for user supplied arguments. */
2919 if (i > 1)
2920 {
2921 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2922 user_args = TREE_CHAIN (user_args);
2923 }
2924
2925 /* Type. */
2926 encode_type (TREE_TYPE (parms),
2927 obstack_object_size (&util_obstack),
2928 OBJC_ENCODE_INLINE_DEFS);
2929
2930 /* Compute offset. */
2931 sprintf (buf, "%d", forwarding_offset (parms));
2932
2933 /* Indicate register. */
2934 if (offset_is_register)
2935 obstack_1grow (&util_obstack, '+');
2936
2937 obstack_grow (&util_obstack, buf, strlen (buf));
2938 }
2939
2940 obstack_1grow (&util_obstack, '\0');
2941 result = get_identifier (obstack_finish (&util_obstack));
2942 obstack_free (&util_obstack, util_firstobj);
2943 return result;
2944 }
2945
2946 static tree
2947 generate_descriptor_table (type, name, size, list, proto)
2948 tree type;
2949 const char *name;
2950 int size;
2951 tree list;
2952 tree proto;
2953 {
2954 tree sc_spec, decl_specs, decl, initlist;
2955
2956 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2957 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2958
2959 decl = start_decl (synth_id_with_class_suffix (name, proto),
2960 decl_specs, 1, NULL_TREE, NULL_TREE);
2961
2962 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2963 initlist = tree_cons (NULL_TREE, list, initlist);
2964
2965 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2966 NULL_TREE);
2967
2968 return decl;
2969 }
2970
2971 static void
2972 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2973 tree protocol;
2974 {
2975 static tree objc_method_prototype_template;
2976 tree initlist, chain, method_list_template;
2977 tree cast, variable_length_type;
2978 int size;
2979
2980 if (!objc_method_prototype_template)
2981 {
2982 objc_method_prototype_template = build_method_prototype_template ();
2983 ggc_add_tree_root (&objc_method_prototype_template, 1);
2984 }
2985
2986 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2987 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2988 NULL_TREE);
2989 variable_length_type = groktypename (cast);
2990
2991 chain = PROTOCOL_CLS_METHODS (protocol);
2992 if (chain)
2993 {
2994 size = list_length (chain);
2995
2996 method_list_template
2997 = build_method_prototype_list_template (objc_method_prototype_template,
2998 size);
2999
3000 initlist
3001 = build_descriptor_table_initializer (objc_method_prototype_template,
3002 chain);
3003
3004 UOBJC_CLASS_METHODS_decl
3005 = generate_descriptor_table (method_list_template,
3006 "_OBJC_PROTOCOL_CLASS_METHODS",
3007 size, initlist, protocol);
3008 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3009 }
3010 else
3011 UOBJC_CLASS_METHODS_decl = 0;
3012
3013 chain = PROTOCOL_NST_METHODS (protocol);
3014 if (chain)
3015 {
3016 size = list_length (chain);
3017
3018 method_list_template
3019 = build_method_prototype_list_template (objc_method_prototype_template,
3020 size);
3021 initlist
3022 = build_descriptor_table_initializer (objc_method_prototype_template,
3023 chain);
3024
3025 UOBJC_INSTANCE_METHODS_decl
3026 = generate_descriptor_table (method_list_template,
3027 "_OBJC_PROTOCOL_INSTANCE_METHODS",
3028 size, initlist, protocol);
3029 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3030 }
3031 else
3032 UOBJC_INSTANCE_METHODS_decl = 0;
3033 }
3034
3035 static tree
3036 build_tmp_function_decl ()
3037 {
3038 tree decl_specs, expr_decl, parms;
3039 static int xxx = 0;
3040 char buffer[80];
3041
3042 /* struct objc_object *objc_xxx (id, SEL, ...); */
3043 pushlevel (0);
3044 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3045 push_parm_decl (build_tree_list
3046 (build_tree_list (decl_specs,
3047 build1 (INDIRECT_REF, NULL_TREE,
3048 NULL_TREE)),
3049 build_tree_list (NULL_TREE, NULL_TREE)));
3050
3051 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3052 get_identifier (TAG_SELECTOR)));
3053 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
3054
3055 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
3056 build_tree_list (NULL_TREE, NULL_TREE)));
3057 parms = get_parm_info (0);
3058 poplevel (0, 0, 0);
3059
3060 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3061 sprintf (buffer, "__objc_tmp_%x", xxx++);
3062 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
3063 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
3064
3065 return define_decl (expr_decl, decl_specs);
3066 }
3067
3068 static void
3069 hack_method_prototype (nst_methods, tmp_decl)
3070 tree nst_methods;
3071 tree tmp_decl;
3072 {
3073 tree parms;
3074 tree parm;
3075
3076 /* Hack to avoid problem with static typing of self arg. */
3077 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
3078 start_method_def (nst_methods);
3079 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
3080
3081 if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node)
3082 parms = get_parm_info (0); /* we have a `, ...' */
3083 else
3084 parms = get_parm_info (1); /* place a `void_at_end' */
3085
3086 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
3087
3088 /* Usually called from store_parm_decls -> init_function_start. */
3089
3090 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
3091 current_function_decl = tmp_decl;
3092
3093 {
3094 /* Code taken from start_function. */
3095 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3096 /* Promote the value to int before returning it. */
3097 if (TREE_CODE (restype) == INTEGER_TYPE
3098 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3099 restype = integer_type_node;
3100 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3101 }
3102
3103 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3104 DECL_CONTEXT (parm) = tmp_decl;
3105
3106 init_function_start (tmp_decl, "objc-act", 0);
3107
3108 /* Typically called from expand_function_start for function definitions. */
3109 assign_parms (tmp_decl);
3110
3111 /* install return type */
3112 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3113
3114 }
3115
3116 static void
3117 generate_protocol_references (plist)
3118 tree plist;
3119 {
3120 tree lproto;
3121
3122 /* Forward declare protocols referenced. */
3123 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3124 {
3125 tree proto = TREE_VALUE (lproto);
3126
3127 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3128 && PROTOCOL_NAME (proto))
3129 {
3130 if (! PROTOCOL_FORWARD_DECL (proto))
3131 build_protocol_reference (proto);
3132
3133 if (PROTOCOL_LIST (proto))
3134 generate_protocol_references (PROTOCOL_LIST (proto));
3135 }
3136 }
3137 }
3138
3139 static void
3140 generate_protocols ()
3141 {
3142 tree p, tmp_decl, encoding;
3143 tree sc_spec, decl_specs, decl;
3144 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3145 tree cast_type2;
3146
3147 tmp_decl = build_tmp_function_decl ();
3148
3149 if (! objc_protocol_template)
3150 objc_protocol_template = build_protocol_template ();
3151
3152 /* If a protocol was directly referenced, pull in indirect references. */
3153 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3154 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3155 generate_protocol_references (PROTOCOL_LIST (p));
3156
3157 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3158 {
3159 tree nst_methods = PROTOCOL_NST_METHODS (p);
3160 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3161
3162 /* If protocol wasn't referenced, don't generate any code. */
3163 if (! PROTOCOL_FORWARD_DECL (p))
3164 continue;
3165
3166 /* Make sure we link in the Protocol class. */
3167 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3168
3169 while (nst_methods)
3170 {
3171 if (! METHOD_ENCODING (nst_methods))
3172 {
3173 hack_method_prototype (nst_methods, tmp_decl);
3174 encoding = encode_method_prototype (nst_methods, tmp_decl);
3175 METHOD_ENCODING (nst_methods) = encoding;
3176 }
3177 nst_methods = TREE_CHAIN (nst_methods);
3178 }
3179
3180 while (cls_methods)
3181 {
3182 if (! METHOD_ENCODING (cls_methods))
3183 {
3184 hack_method_prototype (cls_methods, tmp_decl);
3185 encoding = encode_method_prototype (cls_methods, tmp_decl);
3186 METHOD_ENCODING (cls_methods) = encoding;
3187 }
3188
3189 cls_methods = TREE_CHAIN (cls_methods);
3190 }
3191 generate_method_descriptors (p);
3192
3193 if (PROTOCOL_LIST (p))
3194 refs_decl = generate_protocol_list (p);
3195 else
3196 refs_decl = 0;
3197
3198 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3199
3200 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3201 NULL_TREE);
3202 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3203
3204 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3205 decl_specs, 1, NULL_TREE, NULL_TREE);
3206
3207 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3208
3209 if (refs_decl)
3210 {
3211 cast_type2
3212 = groktypename
3213 (build_tree_list (build_tree_list (NULL_TREE,
3214 objc_protocol_template),
3215 build1 (INDIRECT_REF, NULL_TREE,
3216 build1 (INDIRECT_REF, NULL_TREE,
3217 NULL_TREE))));
3218
3219 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3220 TREE_TYPE (refs_expr) = cast_type2;
3221 }
3222 else
3223 refs_expr = build_int_2 (0, 0);
3224
3225 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3226 by generate_method_descriptors, which is called above. */
3227 initlist = build_protocol_initializer (TREE_TYPE (decl),
3228 protocol_name_expr, refs_expr,
3229 UOBJC_INSTANCE_METHODS_decl,
3230 UOBJC_CLASS_METHODS_decl);
3231 finish_decl (decl, initlist, NULL_TREE);
3232
3233 /* Mark the decl as used to avoid "defined but not used" warning. */
3234 TREE_USED (decl) = 1;
3235 }
3236 }
3237
3238 static tree
3239 build_protocol_initializer (type, protocol_name, protocol_list,
3240 instance_methods, class_methods)
3241 tree type;
3242 tree protocol_name;
3243 tree protocol_list;
3244 tree instance_methods;
3245 tree class_methods;
3246 {
3247 tree initlist = NULL_TREE, expr;
3248 tree cast_type;
3249
3250 cast_type = groktypename
3251 (build_tree_list
3252 (build_tree_list (NULL_TREE,
3253 xref_tag (RECORD_TYPE,
3254 get_identifier (UTAG_CLASS))),
3255 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3256
3257 /* Filling the "isa" in with one allows the runtime system to
3258 detect that the version change...should remove before final release. */
3259
3260 expr = build_int_2 (PROTOCOL_VERSION, 0);
3261 TREE_TYPE (expr) = cast_type;
3262 initlist = tree_cons (NULL_TREE, expr, initlist);
3263 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3264 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3265
3266 if (!instance_methods)
3267 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3268 else
3269 {
3270 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3271 initlist = tree_cons (NULL_TREE, expr, initlist);
3272 }
3273
3274 if (!class_methods)
3275 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3276 else
3277 {
3278 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3279 initlist = tree_cons (NULL_TREE, expr, initlist);
3280 }
3281
3282 return build_constructor (type, nreverse (initlist));
3283 }
3284 \f
3285 /* struct objc_category {
3286 char *category_name;
3287 char *class_name;
3288 struct objc_method_list *instance_methods;
3289 struct objc_method_list *class_methods;
3290 struct objc_protocol_list *protocols;
3291 }; */
3292
3293 static void
3294 build_category_template ()
3295 {
3296 tree decl_specs, field_decl, field_decl_chain;
3297
3298 objc_category_template = start_struct (RECORD_TYPE,
3299 get_identifier (UTAG_CATEGORY));
3300 /* char *category_name; */
3301
3302 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3303 field_decl
3304 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3305 field_decl
3306 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3307 field_decl_chain = field_decl;
3308
3309 /* char *class_name; */
3310
3311 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3312 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3313 field_decl
3314 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3315 chainon (field_decl_chain, field_decl);
3316
3317 /* struct objc_method_list *instance_methods; */
3318
3319 decl_specs = build_tree_list (NULL_TREE,
3320 xref_tag (RECORD_TYPE,
3321 get_identifier (UTAG_METHOD_LIST)));
3322 field_decl
3323 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3324 field_decl
3325 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3326 chainon (field_decl_chain, field_decl);
3327
3328 /* struct objc_method_list *class_methods; */
3329
3330 decl_specs = build_tree_list (NULL_TREE,
3331 xref_tag (RECORD_TYPE,
3332 get_identifier (UTAG_METHOD_LIST)));
3333 field_decl
3334 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3335 field_decl
3336 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3337 chainon (field_decl_chain, field_decl);
3338
3339 /* struct objc_protocol **protocol_list; */
3340
3341 decl_specs = build_tree_list (NULL_TREE,
3342 xref_tag (RECORD_TYPE,
3343 get_identifier (UTAG_PROTOCOL)));
3344 field_decl
3345 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3346 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3347 field_decl
3348 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3349 chainon (field_decl_chain, field_decl);
3350
3351 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3352 }
3353
3354 /* struct objc_selector {
3355 void *sel_id;
3356 char *sel_type;
3357 }; */
3358
3359 static void
3360 build_selector_template ()
3361 {
3362
3363 tree decl_specs, field_decl, field_decl_chain;
3364
3365 objc_selector_template
3366 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3367
3368 /* void *sel_id; */
3369
3370 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3371 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3372 field_decl
3373 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3374 field_decl_chain = field_decl;
3375
3376 /* char *sel_type; */
3377
3378 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3379 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3380 field_decl
3381 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3382 chainon (field_decl_chain, field_decl);
3383
3384 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3385 }
3386
3387 /* struct objc_class {
3388 struct objc_class *isa;
3389 struct objc_class *super_class;
3390 char *name;
3391 long version;
3392 long info;
3393 long instance_size;
3394 struct objc_ivar_list *ivars;
3395 struct objc_method_list *methods;
3396 if (flag_next_runtime)
3397 struct objc_cache *cache;
3398 else {
3399 struct sarray *dtable;
3400 struct objc_class *subclass_list;
3401 struct objc_class *sibling_class;
3402 }
3403 struct objc_protocol_list *protocols;
3404 void *gc_object_type;
3405 }; */
3406
3407 static void
3408 build_class_template ()
3409 {
3410 tree decl_specs, field_decl, field_decl_chain;
3411
3412 objc_class_template
3413 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3414
3415 /* struct objc_class *isa; */
3416
3417 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3418 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3419 field_decl
3420 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3421 field_decl_chain = field_decl;
3422
3423 /* struct objc_class *super_class; */
3424
3425 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3426 field_decl
3427 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3428 field_decl
3429 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3430 chainon (field_decl_chain, field_decl);
3431
3432 /* char *name; */
3433
3434 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3435 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3436 field_decl
3437 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3438 chainon (field_decl_chain, field_decl);
3439
3440 /* long version; */
3441
3442 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3443 field_decl = get_identifier ("version");
3444 field_decl
3445 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3446 chainon (field_decl_chain, field_decl);
3447
3448 /* long info; */
3449
3450 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3451 field_decl = get_identifier ("info");
3452 field_decl
3453 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3454 chainon (field_decl_chain, field_decl);
3455
3456 /* long instance_size; */
3457
3458 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3459 field_decl = get_identifier ("instance_size");
3460 field_decl
3461 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3462 chainon (field_decl_chain, field_decl);
3463
3464 /* struct objc_ivar_list *ivars; */
3465
3466 decl_specs = build_tree_list (NULL_TREE,
3467 xref_tag (RECORD_TYPE,
3468 get_identifier (UTAG_IVAR_LIST)));
3469 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3470 field_decl
3471 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3472 chainon (field_decl_chain, field_decl);
3473
3474 /* struct objc_method_list *methods; */
3475
3476 decl_specs = build_tree_list (NULL_TREE,
3477 xref_tag (RECORD_TYPE,
3478 get_identifier (UTAG_METHOD_LIST)));
3479 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3480 field_decl
3481 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3482 chainon (field_decl_chain, field_decl);
3483
3484 if (flag_next_runtime)
3485 {
3486 /* struct objc_cache *cache; */
3487
3488 decl_specs = build_tree_list (NULL_TREE,
3489 xref_tag (RECORD_TYPE,
3490 get_identifier ("objc_cache")));
3491 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3492 field_decl = grokfield (input_filename, lineno, field_decl,
3493 decl_specs, NULL_TREE);
3494 chainon (field_decl_chain, field_decl);
3495 }
3496 else
3497 {
3498 /* struct sarray *dtable; */
3499
3500 decl_specs = build_tree_list (NULL_TREE,
3501 xref_tag (RECORD_TYPE,
3502 get_identifier ("sarray")));
3503 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3504 field_decl = grokfield (input_filename, lineno, field_decl,
3505 decl_specs, NULL_TREE);
3506 chainon (field_decl_chain, field_decl);
3507
3508 /* struct objc_class *subclass_list; */
3509
3510 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3511 field_decl
3512 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3513 field_decl = grokfield (input_filename, lineno, field_decl,
3514 decl_specs, NULL_TREE);
3515 chainon (field_decl_chain, field_decl);
3516
3517 /* struct objc_class *sibling_class; */
3518
3519 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3520 field_decl
3521 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3522 field_decl = grokfield (input_filename, lineno, field_decl,
3523 decl_specs, NULL_TREE);
3524 chainon (field_decl_chain, field_decl);
3525 }
3526
3527 /* struct objc_protocol **protocol_list; */
3528
3529 decl_specs = build_tree_list (NULL_TREE,
3530 xref_tag (RECORD_TYPE,
3531 get_identifier (UTAG_PROTOCOL)));
3532 field_decl
3533 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3534 field_decl
3535 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3536 field_decl = grokfield (input_filename, lineno, field_decl,
3537 decl_specs, NULL_TREE);
3538 chainon (field_decl_chain, field_decl);
3539
3540 /* void *sel_id; */
3541
3542 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3543 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3544 field_decl
3545 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3546 chainon (field_decl_chain, field_decl);
3547
3548 /* void *gc_object_type; */
3549
3550 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3551 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
3552 field_decl
3553 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3554 chainon (field_decl_chain, field_decl);
3555
3556 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3557 }
3558
3559 /* Generate appropriate forward declarations for an implementation. */
3560
3561 static void
3562 synth_forward_declarations ()
3563 {
3564 tree sc_spec, decl_specs, an_id;
3565
3566 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3567
3568 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3569
3570 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3571 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3572 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3573 TREE_USED (UOBJC_CLASS_decl) = 1;
3574 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3575
3576 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3577
3578 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3579 implementation_context);
3580
3581 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3582 TREE_USED (UOBJC_METACLASS_decl) = 1;
3583 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3584
3585 /* Pre-build the following entities - for speed/convenience. */
3586
3587 an_id = get_identifier ("super_class");
3588 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3589 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3590 }
3591
3592 static void
3593 error_with_ivar (message, decl, rawdecl)
3594 const char *message;
3595 tree decl;
3596 tree rawdecl;
3597 {
3598 count_error (0);
3599
3600 report_error_function (DECL_SOURCE_FILE (decl));
3601
3602 fprintf (stderr, "%s:%d: ",
3603 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3604 memset (errbuf, 0, BUFSIZE);
3605 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3606 }
3607
3608 #define USERTYPE(t) \
3609 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3610 || TREE_CODE (t) == ENUMERAL_TYPE)
3611
3612 static void
3613 check_ivars (inter, imp)
3614 tree inter;
3615 tree imp;
3616 {
3617 tree intdecls = CLASS_IVARS (inter);
3618 tree impdecls = CLASS_IVARS (imp);
3619 tree rawintdecls = CLASS_RAW_IVARS (inter);
3620 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3621
3622 while (1)
3623 {
3624 tree t1, t2;
3625
3626 if (intdecls == 0 && impdecls == 0)
3627 break;
3628 if (intdecls == 0 || impdecls == 0)
3629 {
3630 error ("inconsistent instance variable specification");
3631 break;
3632 }
3633
3634 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3635
3636 if (!comptypes (t1, t2))
3637 {
3638 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3639 {
3640 error_with_ivar ("conflicting instance variable type",
3641 impdecls, rawimpdecls);
3642 error_with_ivar ("previous declaration of",
3643 intdecls, rawintdecls);
3644 }
3645 else /* both the type and the name don't match */
3646 {
3647 error ("inconsistent instance variable specification");
3648 break;
3649 }
3650 }
3651
3652 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3653 {
3654 error_with_ivar ("conflicting instance variable name",
3655 impdecls, rawimpdecls);
3656 error_with_ivar ("previous declaration of",
3657 intdecls, rawintdecls);
3658 }
3659
3660 intdecls = TREE_CHAIN (intdecls);
3661 impdecls = TREE_CHAIN (impdecls);
3662 rawintdecls = TREE_CHAIN (rawintdecls);
3663 rawimpdecls = TREE_CHAIN (rawimpdecls);
3664 }
3665 }
3666
3667 /* Set super_type to the data type node for struct objc_super *,
3668 first defining struct objc_super itself.
3669 This needs to be done just once per compilation. */
3670
3671 static tree
3672 build_super_template ()
3673 {
3674 tree record, decl_specs, field_decl, field_decl_chain;
3675
3676 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3677
3678 /* struct objc_object *self; */
3679
3680 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3681 field_decl = get_identifier ("self");
3682 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3683 field_decl = grokfield (input_filename, lineno,
3684 field_decl, decl_specs, NULL_TREE);
3685 field_decl_chain = field_decl;
3686
3687 /* struct objc_class *class; */
3688
3689 decl_specs = get_identifier (UTAG_CLASS);
3690 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3691 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3692
3693 field_decl = grokfield (input_filename, lineno,
3694 field_decl, decl_specs, NULL_TREE);
3695 chainon (field_decl_chain, field_decl);
3696
3697 finish_struct (record, field_decl_chain, NULL_TREE);
3698
3699 /* `struct objc_super *' */
3700 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3701 record),
3702 build1 (INDIRECT_REF,
3703 NULL_TREE, NULL_TREE)));
3704 return record;
3705 }
3706
3707 /* struct objc_ivar {
3708 char *ivar_name;
3709 char *ivar_type;
3710 int ivar_offset;
3711 }; */
3712
3713 static tree
3714 build_ivar_template ()
3715 {
3716 tree objc_ivar_id, objc_ivar_record;
3717 tree decl_specs, field_decl, field_decl_chain;
3718
3719 objc_ivar_id = get_identifier (UTAG_IVAR);
3720 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3721
3722 /* char *ivar_name; */
3723
3724 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3725 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3726
3727 field_decl = grokfield (input_filename, lineno, field_decl,
3728 decl_specs, NULL_TREE);
3729 field_decl_chain = field_decl;
3730
3731 /* char *ivar_type; */
3732
3733 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3734 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3735
3736 field_decl = grokfield (input_filename, lineno, field_decl,
3737 decl_specs, NULL_TREE);
3738 chainon (field_decl_chain, field_decl);
3739
3740 /* int ivar_offset; */
3741
3742 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3743 field_decl = get_identifier ("ivar_offset");
3744
3745 field_decl = grokfield (input_filename, lineno, field_decl,
3746 decl_specs, NULL_TREE);
3747 chainon (field_decl_chain, field_decl);
3748
3749 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3750
3751 return objc_ivar_record;
3752 }
3753
3754 /* struct {
3755 int ivar_count;
3756 struct objc_ivar ivar_list[ivar_count];
3757 }; */
3758
3759 static tree
3760 build_ivar_list_template (list_type, size)
3761 tree list_type;
3762 int size;
3763 {
3764 tree objc_ivar_list_record;
3765 tree decl_specs, field_decl, field_decl_chain;
3766
3767 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3768
3769 /* int ivar_count; */
3770
3771 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3772 field_decl = get_identifier ("ivar_count");
3773
3774 field_decl = grokfield (input_filename, lineno, field_decl,
3775 decl_specs, NULL_TREE);
3776 field_decl_chain = field_decl;
3777
3778 /* struct objc_ivar ivar_list[]; */
3779
3780 decl_specs = build_tree_list (NULL_TREE, list_type);
3781 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3782 build_int_2 (size, 0));
3783
3784 field_decl = grokfield (input_filename, lineno,
3785 field_decl, decl_specs, NULL_TREE);
3786 chainon (field_decl_chain, field_decl);
3787
3788 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3789
3790 return objc_ivar_list_record;
3791 }
3792
3793 /* struct {
3794 int method_next;
3795 int method_count;
3796 struct objc_method method_list[method_count];
3797 }; */
3798
3799 static tree
3800 build_method_list_template (list_type, size)
3801 tree list_type;
3802 int size;
3803 {
3804 tree objc_ivar_list_record;
3805 tree decl_specs, field_decl, field_decl_chain;
3806
3807 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3808
3809 /* int method_next; */
3810
3811 decl_specs
3812 = build_tree_list
3813 (NULL_TREE,
3814 xref_tag (RECORD_TYPE,
3815 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3816 field_decl
3817 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3818 field_decl = grokfield (input_filename, lineno, field_decl,
3819 decl_specs, NULL_TREE);
3820 field_decl_chain = field_decl;
3821
3822 /* int method_count; */
3823
3824 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3825 field_decl = get_identifier ("method_count");
3826
3827 field_decl = grokfield (input_filename, lineno,
3828 field_decl, decl_specs, NULL_TREE);
3829 chainon (field_decl_chain, field_decl);
3830
3831 /* struct objc_method method_list[]; */
3832
3833 decl_specs = build_tree_list (NULL_TREE, list_type);
3834 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3835 build_int_2 (size, 0));
3836
3837 field_decl = grokfield (input_filename, lineno,
3838 field_decl, decl_specs, NULL_TREE);
3839 chainon (field_decl_chain, field_decl);
3840
3841 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3842
3843 return objc_ivar_list_record;
3844 }
3845
3846 static tree
3847 build_ivar_list_initializer (type, field_decl)
3848 tree type;
3849 tree field_decl;
3850 {
3851 tree initlist = NULL_TREE;
3852
3853 do
3854 {
3855 tree ivar = NULL_TREE;
3856
3857 /* Set name. */
3858 if (DECL_NAME (field_decl))
3859 ivar = tree_cons (NULL_TREE,
3860 add_objc_string (DECL_NAME (field_decl),
3861 meth_var_names),
3862 ivar);
3863 else
3864 /* Unnamed bit-field ivar (yuck). */
3865 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3866
3867 /* Set type. */
3868 encode_field_decl (field_decl,
3869 obstack_object_size (&util_obstack),
3870 OBJC_ENCODE_DONT_INLINE_DEFS);
3871
3872 /* Null terminate string. */
3873 obstack_1grow (&util_obstack, 0);
3874 ivar
3875 = tree_cons
3876 (NULL_TREE,
3877 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3878 meth_var_types),
3879 ivar);
3880 obstack_free (&util_obstack, util_firstobj);
3881
3882 /* Set offset. */
3883 ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
3884 initlist = tree_cons (NULL_TREE,
3885 build_constructor (type, nreverse (ivar)),
3886 initlist);
3887
3888 field_decl = TREE_CHAIN (field_decl);
3889 }
3890 while (field_decl);
3891
3892 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3893 }
3894
3895 static tree
3896 generate_ivars_list (type, name, size, list)
3897 tree type;
3898 const char *name;
3899 int size;
3900 tree list;
3901 {
3902 tree sc_spec, decl_specs, decl, initlist;
3903
3904 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3905 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3906
3907 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3908 decl_specs, 1, NULL_TREE, NULL_TREE);
3909
3910 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3911 initlist = tree_cons (NULL_TREE, list, initlist);
3912
3913 finish_decl (decl,
3914 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3915 NULL_TREE);
3916
3917 return decl;
3918 }
3919
3920 static void
3921 generate_ivar_lists ()
3922 {
3923 tree initlist, ivar_list_template, chain;
3924 tree cast, variable_length_type;
3925 int size;
3926
3927 generating_instance_variables = 1;
3928
3929 if (!objc_ivar_template)
3930 objc_ivar_template = build_ivar_template ();
3931
3932 cast
3933 = build_tree_list
3934 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3935 get_identifier (UTAG_IVAR_LIST))),
3936 NULL_TREE);
3937 variable_length_type = groktypename (cast);
3938
3939 /* Only generate class variables for the root of the inheritance
3940 hierarchy since these will be the same for every class. */
3941
3942 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3943 && (chain = TYPE_FIELDS (objc_class_template)))
3944 {
3945 size = list_length (chain);
3946
3947 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3948 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3949
3950 UOBJC_CLASS_VARIABLES_decl
3951 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3952 size, initlist);
3953 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3954 }
3955 else
3956 UOBJC_CLASS_VARIABLES_decl = 0;
3957
3958 chain = CLASS_IVARS (implementation_template);
3959 if (chain)
3960 {
3961 size = list_length (chain);
3962 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3963 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3964
3965 UOBJC_INSTANCE_VARIABLES_decl
3966 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3967 size, initlist);
3968 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3969 }
3970 else
3971 UOBJC_INSTANCE_VARIABLES_decl = 0;
3972
3973 generating_instance_variables = 0;
3974 }
3975
3976 static tree
3977 build_dispatch_table_initializer (type, entries)
3978 tree type;
3979 tree entries;
3980 {
3981 tree initlist = NULL_TREE;
3982
3983 do
3984 {
3985 tree elemlist = NULL_TREE;
3986
3987 elemlist = tree_cons (NULL_TREE,
3988 build_selector (METHOD_SEL_NAME (entries)),
3989 NULL_TREE);
3990
3991 elemlist = tree_cons (NULL_TREE,
3992 add_objc_string (METHOD_ENCODING (entries),
3993 meth_var_types),
3994 elemlist);
3995
3996 elemlist = tree_cons (NULL_TREE,
3997 build_unary_op (ADDR_EXPR,
3998 METHOD_DEFINITION (entries), 1),
3999 elemlist);
4000
4001 initlist = tree_cons (NULL_TREE,
4002 build_constructor (type, nreverse (elemlist)),
4003 initlist);
4004
4005 entries = TREE_CHAIN (entries);
4006 }
4007 while (entries);
4008
4009 return build_constructor (build_array_type (type, 0), nreverse (initlist));
4010 }
4011
4012 /* To accomplish method prototyping without generating all kinds of
4013 inane warnings, the definition of the dispatch table entries were
4014 changed from:
4015
4016 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
4017 to:
4018 struct objc_method { SEL _cmd; ...; void *_imp; }; */
4019
4020 static tree
4021 build_method_template ()
4022 {
4023 tree _SLT_record;
4024 tree decl_specs, field_decl, field_decl_chain;
4025
4026 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
4027
4028 #ifdef OBJC_INT_SELECTORS
4029 /* unsigned int _cmd; */
4030 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
4031 NULL_TREE);
4032 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
4033 field_decl = get_identifier ("_cmd");
4034 #else /* not OBJC_INT_SELECTORS */
4035 /* struct objc_selector *_cmd; */
4036 decl_specs = tree_cons (NULL_TREE,
4037 xref_tag (RECORD_TYPE,
4038 get_identifier (TAG_SELECTOR)),
4039 NULL_TREE);
4040 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
4041 #endif /* not OBJC_INT_SELECTORS */
4042
4043 field_decl = grokfield (input_filename, lineno, field_decl,
4044 decl_specs, NULL_TREE);
4045 field_decl_chain = field_decl;
4046
4047 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
4048 field_decl = build1 (INDIRECT_REF, NULL_TREE,
4049 get_identifier ("method_types"));
4050 field_decl = grokfield (input_filename, lineno, field_decl,
4051 decl_specs, NULL_TREE);
4052 chainon (field_decl_chain, field_decl);
4053
4054 /* void *_imp; */
4055
4056 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4057 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4058 field_decl = grokfield (input_filename, lineno, field_decl,
4059 decl_specs, NULL_TREE);
4060 chainon (field_decl_chain, field_decl);
4061
4062 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4063
4064 return _SLT_record;
4065 }
4066
4067
4068 static tree
4069 generate_dispatch_table (type, name, size, list)
4070 tree type;
4071 const char *name;
4072 int size;
4073 tree list;
4074 {
4075 tree sc_spec, decl_specs, decl, initlist;
4076
4077 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4078 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4079
4080 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
4081 decl_specs, 1, NULL_TREE, NULL_TREE);
4082
4083 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4084 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4085 initlist = tree_cons (NULL_TREE, list, initlist);
4086
4087 finish_decl (decl,
4088 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4089 NULL_TREE);
4090
4091 return decl;
4092 }
4093
4094 static void
4095 generate_dispatch_tables ()
4096 {
4097 tree initlist, chain, method_list_template;
4098 tree cast, variable_length_type;
4099 int size;
4100
4101 if (!objc_method_template)
4102 objc_method_template = build_method_template ();
4103
4104 cast
4105 = build_tree_list
4106 (build_tree_list (NULL_TREE,
4107 xref_tag (RECORD_TYPE,
4108 get_identifier (UTAG_METHOD_LIST))),
4109 NULL_TREE);
4110
4111 variable_length_type = groktypename (cast);
4112
4113 chain = CLASS_CLS_METHODS (implementation_context);
4114 if (chain)
4115 {
4116 size = list_length (chain);
4117
4118 method_list_template
4119 = build_method_list_template (objc_method_template, size);
4120 initlist
4121 = build_dispatch_table_initializer (objc_method_template, chain);
4122
4123 UOBJC_CLASS_METHODS_decl
4124 = generate_dispatch_table (method_list_template,
4125 ((TREE_CODE (implementation_context)
4126 == CLASS_IMPLEMENTATION_TYPE)
4127 ? "_OBJC_CLASS_METHODS"
4128 : "_OBJC_CATEGORY_CLASS_METHODS"),
4129 size, initlist);
4130 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4131 }
4132 else
4133 UOBJC_CLASS_METHODS_decl = 0;
4134
4135 chain = CLASS_NST_METHODS (implementation_context);
4136 if (chain)
4137 {
4138 size = list_length (chain);
4139
4140 method_list_template
4141 = build_method_list_template (objc_method_template, size);
4142 initlist
4143 = build_dispatch_table_initializer (objc_method_template, chain);
4144
4145 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4146 UOBJC_INSTANCE_METHODS_decl
4147 = generate_dispatch_table (method_list_template,
4148 "_OBJC_INSTANCE_METHODS",
4149 size, initlist);
4150 else
4151 /* We have a category. */
4152 UOBJC_INSTANCE_METHODS_decl
4153 = generate_dispatch_table (method_list_template,
4154 "_OBJC_CATEGORY_INSTANCE_METHODS",
4155 size, initlist);
4156 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4157 }
4158 else
4159 UOBJC_INSTANCE_METHODS_decl = 0;
4160 }
4161
4162 static tree
4163 generate_protocol_list (i_or_p)
4164 tree i_or_p;
4165 {
4166 tree initlist, decl_specs, sc_spec;
4167 tree refs_decl, expr_decl, lproto, e, plist;
4168 tree cast_type;
4169 int size = 0;
4170
4171 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4172 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4173 plist = CLASS_PROTOCOL_LIST (i_or_p);
4174 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4175 plist = PROTOCOL_LIST (i_or_p);
4176 else
4177 abort ();
4178
4179 cast_type = groktypename
4180 (build_tree_list
4181 (build_tree_list (NULL_TREE,
4182 xref_tag (RECORD_TYPE,
4183 get_identifier (UTAG_PROTOCOL))),
4184 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4185
4186 /* Compute size. */
4187 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4188 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4189 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4190 size++;
4191
4192 /* Build initializer. */
4193 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4194
4195 e = build_int_2 (size, 0);
4196 TREE_TYPE (e) = cast_type;
4197 initlist = tree_cons (NULL_TREE, e, initlist);
4198
4199 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4200 {
4201 tree pval = TREE_VALUE (lproto);
4202
4203 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4204 && PROTOCOL_FORWARD_DECL (pval))
4205 {
4206 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4207 initlist = tree_cons (NULL_TREE, e, initlist);
4208 }
4209 }
4210
4211 /* static struct objc_protocol *refs[n]; */
4212
4213 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4214 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4215 get_identifier (UTAG_PROTOCOL)),
4216 sc_spec);
4217
4218 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4219 expr_decl = build_nt (ARRAY_REF,
4220 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4221 i_or_p),
4222 build_int_2 (size + 2, 0));
4223 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4224 expr_decl = build_nt (ARRAY_REF,
4225 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4226 i_or_p),
4227 build_int_2 (size + 2, 0));
4228 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4229 expr_decl
4230 = build_nt (ARRAY_REF,
4231 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4232 i_or_p),
4233 build_int_2 (size + 2, 0));
4234 else
4235 abort ();
4236
4237 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4238
4239 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4240
4241 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4242 nreverse (initlist)),
4243 NULL_TREE);
4244
4245 return refs_decl;
4246 }
4247
4248 static tree
4249 build_category_initializer (type, cat_name, class_name,
4250 instance_methods, class_methods, protocol_list)
4251 tree type;
4252 tree cat_name;
4253 tree class_name;
4254 tree instance_methods;
4255 tree class_methods;
4256 tree protocol_list;
4257 {
4258 tree initlist = NULL_TREE, expr;
4259
4260 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4261 initlist = tree_cons (NULL_TREE, class_name, initlist);
4262
4263 if (!instance_methods)
4264 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4265 else
4266 {
4267 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4268 initlist = tree_cons (NULL_TREE, expr, initlist);
4269 }
4270 if (!class_methods)
4271 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4272 else
4273 {
4274 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4275 initlist = tree_cons (NULL_TREE, expr, initlist);
4276 }
4277
4278 /* protocol_list = */
4279 if (!protocol_list)
4280 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4281 else
4282 {
4283 tree cast_type2 = groktypename
4284 (build_tree_list
4285 (build_tree_list (NULL_TREE,
4286 xref_tag (RECORD_TYPE,
4287 get_identifier (UTAG_PROTOCOL))),
4288 build1 (INDIRECT_REF, NULL_TREE,
4289 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4290
4291 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4292 TREE_TYPE (expr) = cast_type2;
4293 initlist = tree_cons (NULL_TREE, expr, initlist);
4294 }
4295
4296 return build_constructor (type, nreverse (initlist));
4297 }
4298
4299 /* struct objc_class {
4300 struct objc_class *isa;
4301 struct objc_class *super_class;
4302 char *name;
4303 long version;
4304 long info;
4305 long instance_size;
4306 struct objc_ivar_list *ivars;
4307 struct objc_method_list *methods;
4308 if (flag_next_runtime)
4309 struct objc_cache *cache;
4310 else {
4311 struct sarray *dtable;
4312 struct objc_class *subclass_list;
4313 struct objc_class *sibling_class;
4314 }
4315 struct objc_protocol_list *protocols;
4316 void *gc_object_type;
4317 }; */
4318
4319 static tree
4320 build_shared_structure_initializer (type, isa, super, name, size, status,
4321 dispatch_table, ivar_list, protocol_list)
4322 tree type;
4323 tree isa;
4324 tree super;
4325 tree name;
4326 tree size;
4327 int status;
4328 tree dispatch_table;
4329 tree ivar_list;
4330 tree protocol_list;
4331 {
4332 tree initlist = NULL_TREE, expr;
4333
4334 /* isa = */
4335 initlist = tree_cons (NULL_TREE, isa, initlist);
4336
4337 /* super_class = */
4338 initlist = tree_cons (NULL_TREE, super, initlist);
4339
4340 /* name = */
4341 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4342
4343 /* version = */
4344 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4345
4346 /* info = */
4347 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4348
4349 /* instance_size = */
4350 initlist = tree_cons (NULL_TREE, size, initlist);
4351
4352 /* objc_ivar_list = */
4353 if (!ivar_list)
4354 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4355 else
4356 {
4357 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4358 initlist = tree_cons (NULL_TREE, expr, initlist);
4359 }
4360
4361 /* objc_method_list = */
4362 if (!dispatch_table)
4363 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4364 else
4365 {
4366 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4367 initlist = tree_cons (NULL_TREE, expr, initlist);
4368 }
4369
4370 if (flag_next_runtime)
4371 /* method_cache = */
4372 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4373 else
4374 {
4375 /* dtable = */
4376 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4377
4378 /* subclass_list = */
4379 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4380
4381 /* sibling_class = */
4382 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4383 }
4384
4385 /* protocol_list = */
4386 if (! protocol_list)
4387 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4388 else
4389 {
4390 tree cast_type2
4391 = groktypename
4392 (build_tree_list
4393 (build_tree_list (NULL_TREE,
4394 xref_tag (RECORD_TYPE,
4395 get_identifier (UTAG_PROTOCOL))),
4396 build1 (INDIRECT_REF, NULL_TREE,
4397 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4398
4399 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4400 TREE_TYPE (expr) = cast_type2;
4401 initlist = tree_cons (NULL_TREE, expr, initlist);
4402 }
4403
4404 /* gc_object_type = NULL */
4405 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4406
4407 return build_constructor (type, nreverse (initlist));
4408 }
4409
4410 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4411
4412 static void
4413 generate_category (cat)
4414 tree cat;
4415 {
4416 tree sc_spec, decl_specs, decl;
4417 tree initlist, cat_name_expr, class_name_expr;
4418 tree protocol_decl, category;
4419
4420 add_class_reference (CLASS_NAME (cat));
4421 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4422
4423 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4424
4425 category = CLASS_CATEGORY_LIST (implementation_template);
4426
4427 /* find the category interface from the class it is associated with */
4428 while (category)
4429 {
4430 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4431 break;
4432 category = CLASS_CATEGORY_LIST (category);
4433 }
4434
4435 if (category && CLASS_PROTOCOL_LIST (category))
4436 {
4437 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4438 protocol_decl = generate_protocol_list (category);
4439 }
4440 else
4441 protocol_decl = 0;
4442
4443 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4444 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4445
4446 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4447 implementation_context),
4448 decl_specs, 1, NULL_TREE, NULL_TREE);
4449
4450 initlist = build_category_initializer (TREE_TYPE (decl),
4451 cat_name_expr, class_name_expr,
4452 UOBJC_INSTANCE_METHODS_decl,
4453 UOBJC_CLASS_METHODS_decl,
4454 protocol_decl);
4455
4456 TREE_USED (decl) = 1;
4457 finish_decl (decl, initlist, NULL_TREE);
4458 }
4459
4460 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4461 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4462
4463 static void
4464 generate_shared_structures ()
4465 {
4466 tree sc_spec, decl_specs, decl;
4467 tree name_expr, super_expr, root_expr;
4468 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4469 tree cast_type, initlist, protocol_decl;
4470
4471 my_super_id = CLASS_SUPER_NAME (implementation_template);
4472 if (my_super_id)
4473 {
4474 add_class_reference (my_super_id);
4475
4476 /* Compute "my_root_id" - this is required for code generation.
4477 the "isa" for all meta class structures points to the root of
4478 the inheritance hierarchy (e.g. "__Object")... */
4479 my_root_id = my_super_id;
4480 do
4481 {
4482 tree my_root_int = lookup_interface (my_root_id);
4483
4484 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4485 my_root_id = CLASS_SUPER_NAME (my_root_int);
4486 else
4487 break;
4488 }
4489 while (1);
4490 }
4491 else
4492 /* No super class. */
4493 my_root_id = CLASS_NAME (implementation_template);
4494
4495 cast_type
4496 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4497 objc_class_template),
4498 build1 (INDIRECT_REF,
4499 NULL_TREE, NULL_TREE)));
4500
4501 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4502 class_names);
4503
4504 /* Install class `isa' and `super' pointers at runtime. */
4505 if (my_super_id)
4506 {
4507 super_expr = add_objc_string (my_super_id, class_names);
4508 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4509 }
4510 else
4511 super_expr = build_int_2 (0, 0);
4512
4513 root_expr = add_objc_string (my_root_id, class_names);
4514 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4515
4516 if (CLASS_PROTOCOL_LIST (implementation_template))
4517 {
4518 generate_protocol_references
4519 (CLASS_PROTOCOL_LIST (implementation_template));
4520 protocol_decl = generate_protocol_list (implementation_template);
4521 }
4522 else
4523 protocol_decl = 0;
4524
4525 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4526
4527 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4528 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4529
4530 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4531 NULL_TREE, NULL_TREE);
4532
4533 initlist
4534 = build_shared_structure_initializer
4535 (TREE_TYPE (decl),
4536 root_expr, super_expr, name_expr,
4537 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
4538 2 /*CLS_META*/,
4539 UOBJC_CLASS_METHODS_decl,
4540 UOBJC_CLASS_VARIABLES_decl,
4541 protocol_decl);
4542
4543 finish_decl (decl, initlist, NULL_TREE);
4544
4545 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4546
4547 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4548 NULL_TREE, NULL_TREE);
4549
4550 initlist
4551 = build_shared_structure_initializer
4552 (TREE_TYPE (decl),
4553 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4554 super_expr, name_expr,
4555 convert (integer_type_node,
4556 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
4557 (implementation_template))),
4558 1 /*CLS_FACTORY*/,
4559 UOBJC_INSTANCE_METHODS_decl,
4560 UOBJC_INSTANCE_VARIABLES_decl,
4561 protocol_decl);
4562
4563 finish_decl (decl, initlist, NULL_TREE);
4564 }
4565
4566 static tree
4567 synth_id_with_class_suffix (preamble, ctxt)
4568 const char *preamble;
4569 tree ctxt;
4570 {
4571 char *string;
4572 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4573 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4574 {
4575 const char *class_name
4576 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4577 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4578 sprintf (string, "%s_%s", preamble,
4579 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4580 }
4581 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4582 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4583 {
4584 /* We have a category. */
4585 const char *class_name
4586 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4587 const char *class_super_name
4588 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4589 string = (char *) alloca (strlen (preamble)
4590 + strlen (class_name)
4591 + strlen (class_super_name)
4592 + 3);
4593 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4594 }
4595 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4596 {
4597 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4598 string
4599 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4600 sprintf (string, "%s_%s", preamble, protocol_name);
4601 }
4602 else
4603 abort ();
4604
4605 return get_identifier (string);
4606 }
4607
4608 static int
4609 is_objc_type_qualifier (node)
4610 tree node;
4611 {
4612 return (TREE_CODE (node) == IDENTIFIER_NODE
4613 && (node == ridpointers [(int) RID_CONST]
4614 || node == ridpointers [(int) RID_VOLATILE]
4615 || node == ridpointers [(int) RID_IN]
4616 || node == ridpointers [(int) RID_OUT]
4617 || node == ridpointers [(int) RID_INOUT]
4618 || node == ridpointers [(int) RID_BYCOPY]
4619 || node == ridpointers [(int) RID_BYREF]
4620 || node == ridpointers [(int) RID_ONEWAY]));
4621 }
4622
4623 /* If type is empty or only type qualifiers are present, add default
4624 type of id (otherwise grokdeclarator will default to int). */
4625
4626 static tree
4627 adjust_type_for_id_default (type)
4628 tree type;
4629 {
4630 tree declspecs, chain;
4631
4632 if (!type)
4633 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4634 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4635
4636 declspecs = TREE_PURPOSE (type);
4637
4638 /* Determine if a typespec is present. */
4639 for (chain = declspecs;
4640 chain;
4641 chain = TREE_CHAIN (chain))
4642 {
4643 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4644 return type;
4645 }
4646
4647 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4648 declspecs),
4649 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4650 }
4651
4652 /* Usage:
4653 keyworddecl:
4654 selector ':' '(' typename ')' identifier
4655
4656 Purpose:
4657 Transform an Objective-C keyword argument into
4658 the C equivalent parameter declarator.
4659
4660 In: key_name, an "identifier_node" (optional).
4661 arg_type, a "tree_list" (optional).
4662 arg_name, an "identifier_node".
4663
4664 Note: It would be really nice to strongly type the preceding
4665 arguments in the function prototype; however, then I
4666 could not use the "accessor" macros defined in "tree.h".
4667
4668 Out: an instance of "keyword_decl". */
4669
4670 tree
4671 build_keyword_decl (key_name, arg_type, arg_name)
4672 tree key_name;
4673 tree arg_type;
4674 tree arg_name;
4675 {
4676 tree keyword_decl;
4677
4678 /* If no type is specified, default to "id". */
4679 arg_type = adjust_type_for_id_default (arg_type);
4680
4681 keyword_decl = make_node (KEYWORD_DECL);
4682
4683 TREE_TYPE (keyword_decl) = arg_type;
4684 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4685 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4686
4687 return keyword_decl;
4688 }
4689
4690 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4691
4692 static tree
4693 build_keyword_selector (selector)
4694 tree selector;
4695 {
4696 int len = 0;
4697 tree key_chain, key_name;
4698 char *buf;
4699
4700 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4701 {
4702 if (TREE_CODE (selector) == KEYWORD_DECL)
4703 key_name = KEYWORD_KEY_NAME (key_chain);
4704 else if (TREE_CODE (selector) == TREE_LIST)
4705 key_name = TREE_PURPOSE (key_chain);
4706 else
4707 abort ();
4708
4709 if (key_name)
4710 len += IDENTIFIER_LENGTH (key_name) + 1;
4711 else
4712 /* Just a ':' arg. */
4713 len++;
4714 }
4715
4716 buf = (char *)alloca (len + 1);
4717 memset (buf, 0, len + 1);
4718
4719 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4720 {
4721 if (TREE_CODE (selector) == KEYWORD_DECL)
4722 key_name = KEYWORD_KEY_NAME (key_chain);
4723 else if (TREE_CODE (selector) == TREE_LIST)
4724 key_name = TREE_PURPOSE (key_chain);
4725 else
4726 abort ();
4727
4728 if (key_name)
4729 strcat (buf, IDENTIFIER_POINTER (key_name));
4730 strcat (buf, ":");
4731 }
4732
4733 return get_identifier (buf);
4734 }
4735
4736 /* Used for declarations and definitions. */
4737
4738 tree
4739 build_method_decl (code, ret_type, selector, add_args)
4740 enum tree_code code;
4741 tree ret_type;
4742 tree selector;
4743 tree add_args;
4744 {
4745 tree method_decl;
4746
4747 /* If no type is specified, default to "id". */
4748 ret_type = adjust_type_for_id_default (ret_type);
4749
4750 method_decl = make_node (code);
4751 TREE_TYPE (method_decl) = ret_type;
4752
4753 /* If we have a keyword selector, create an identifier_node that
4754 represents the full selector name (`:' included)... */
4755 if (TREE_CODE (selector) == KEYWORD_DECL)
4756 {
4757 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4758 METHOD_SEL_ARGS (method_decl) = selector;
4759 METHOD_ADD_ARGS (method_decl) = add_args;
4760 }
4761 else
4762 {
4763 METHOD_SEL_NAME (method_decl) = selector;
4764 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4765 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4766 }
4767
4768 return method_decl;
4769 }
4770
4771 #define METHOD_DEF 0
4772 #define METHOD_REF 1
4773
4774 /* Used by `build_message_expr' and `comp_method_types'. Return an
4775 argument list for method METH. CONTEXT is either METHOD_DEF or
4776 METHOD_REF, saying whether we are trying to define a method or call
4777 one. SUPERFLAG says this is for a send to super; this makes a
4778 difference for the NeXT calling sequence in which the lookup and
4779 the method call are done together. */
4780
4781 static tree
4782 get_arg_type_list (meth, context, superflag)
4783 tree meth;
4784 int context;
4785 int superflag;
4786 {
4787 tree arglist, akey;
4788
4789 /* Receiver type. */
4790 if (flag_next_runtime && superflag)
4791 arglist = build_tree_list (NULL_TREE, super_type);
4792 else if (context == METHOD_DEF)
4793 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4794 else
4795 arglist = build_tree_list (NULL_TREE, id_type);
4796
4797 /* Selector type - will eventually change to `int'. */
4798 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4799
4800 /* Build a list of argument types. */
4801 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4802 {
4803 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4804 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4805 }
4806
4807 if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
4808 /* We have a `, ...' immediately following the selector,
4809 finalize the arglist...simulate get_parm_info (0). */
4810 ;
4811 else if (METHOD_ADD_ARGS (meth))
4812 {
4813 /* we have a variable length selector */
4814 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4815 chainon (arglist, add_arg_list);
4816 }
4817 else
4818 /* finalize the arglist...simulate get_parm_info (1) */
4819 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4820
4821 return arglist;
4822 }
4823
4824 static tree
4825 check_duplicates (hsh)
4826 hash hsh;
4827 {
4828 tree meth = NULL_TREE;
4829
4830 if (hsh)
4831 {
4832 meth = hsh->key;
4833
4834 if (hsh->list)
4835 {
4836 /* We have two methods with the same name and different types. */
4837 attr loop;
4838 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4839
4840 warning ("multiple declarations for method `%s'",
4841 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4842
4843 warn_with_method ("using", type, meth);
4844 for (loop = hsh->list; loop; loop = loop->next)
4845 warn_with_method ("also found", type, loop->value);
4846 }
4847 }
4848 return meth;
4849 }
4850
4851 /* If RECEIVER is a class reference, return the identifier node for the
4852 referenced class. RECEIVER is created by get_class_reference, so we
4853 check the exact form created depending on which runtimes are used. */
4854
4855 static tree
4856 receiver_is_class_object (receiver)
4857 tree receiver;
4858 {
4859 tree chain, exp, arg;
4860 if (flag_next_runtime)
4861 {
4862 /* The receiver is a variable created by build_class_reference_decl. */
4863 if (TREE_CODE (receiver) == VAR_DECL
4864 && TREE_TYPE (receiver) == objc_class_type)
4865 /* Look up the identifier. */
4866 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4867 if (TREE_PURPOSE (chain) == receiver)
4868 return TREE_VALUE (chain);
4869 }
4870 else
4871 {
4872 /* The receiver is a function call that returns an id. Check if
4873 it is a call to objc_getClass, if so, pick up the class name. */
4874 if ((exp = TREE_OPERAND (receiver, 0))
4875 && TREE_CODE (exp) == ADDR_EXPR
4876 && (exp = TREE_OPERAND (exp, 0))
4877 && TREE_CODE (exp) == FUNCTION_DECL
4878 && exp == objc_get_class_decl
4879 /* we have a call to objc_getClass! */
4880 && (arg = TREE_OPERAND (receiver, 1))
4881 && TREE_CODE (arg) == TREE_LIST
4882 && (arg = TREE_VALUE (arg)))
4883 {
4884 STRIP_NOPS (arg);
4885 if (TREE_CODE (arg) == ADDR_EXPR
4886 && (arg = TREE_OPERAND (arg, 0))
4887 && TREE_CODE (arg) == STRING_CST)
4888 /* Finally, we have the class name. */
4889 return get_identifier (TREE_STRING_POINTER (arg));
4890 }
4891 }
4892 return 0;
4893 }
4894 \f
4895 /* If we are currently building a message expr, this holds
4896 the identifier of the selector of the message. This is
4897 used when printing warnings about argument mismatches. */
4898
4899 static tree building_objc_message_expr = 0;
4900
4901 tree
4902 maybe_building_objc_message_expr ()
4903 {
4904 return building_objc_message_expr;
4905 }
4906
4907 /* Construct an expression for sending a message.
4908 MESS has the object to send to in TREE_PURPOSE
4909 and the argument list (including selector) in TREE_VALUE.
4910
4911 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4912 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4913
4914 tree
4915 build_message_expr (mess)
4916 tree mess;
4917 {
4918 tree receiver = TREE_PURPOSE (mess);
4919 tree selector, self_object;
4920 tree rtype, sel_name;
4921 tree args = TREE_VALUE (mess);
4922 tree method_params = NULL_TREE;
4923 tree method_prototype = NULL_TREE;
4924 tree retval;
4925 int statically_typed = 0, statically_allocated = 0;
4926 tree class_ident = 0;
4927
4928 /* 1 if this is sending to the superclass. */
4929 int super;
4930
4931 if (TREE_CODE (receiver) == ERROR_MARK)
4932 return error_mark_node;
4933
4934 /* Determine receiver type. */
4935 rtype = TREE_TYPE (receiver);
4936 super = IS_SUPER (rtype);
4937
4938 if (! super)
4939 {
4940 if (TREE_STATIC_TEMPLATE (rtype))
4941 statically_allocated = 1;
4942 else if (TREE_CODE (rtype) == POINTER_TYPE
4943 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4944 statically_typed = 1;
4945 else if ((flag_next_runtime
4946 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4947 && (class_ident = receiver_is_class_object (receiver)))
4948 ;
4949 else if (! IS_ID (rtype)
4950 /* Allow any type that matches objc_class_type. */
4951 && ! comptypes (rtype, objc_class_type))
4952 {
4953 memset (errbuf, 0, BUFSIZE);
4954 warning ("invalid receiver type `%s'",
4955 gen_declaration (rtype, errbuf));
4956 }
4957
4958 if (statically_allocated)
4959 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4960
4961 /* Don't evaluate the receiver twice. */
4962 receiver = save_expr (receiver);
4963 self_object = receiver;
4964 }
4965 else
4966 /* If sending to `super', use current self as the object. */
4967 self_object = self_decl;
4968
4969 /* Obtain the full selector name. */
4970
4971 if (TREE_CODE (args) == IDENTIFIER_NODE)
4972 /* A unary selector. */
4973 sel_name = args;
4974 else if (TREE_CODE (args) == TREE_LIST)
4975 sel_name = build_keyword_selector (args);
4976 else
4977 abort ();
4978
4979 /* Build the parameter list to give to the method. */
4980
4981 method_params = NULL_TREE;
4982 if (TREE_CODE (args) == TREE_LIST)
4983 {
4984 tree chain = args, prev = NULL_TREE;
4985
4986 /* We have a keyword selector--check for comma expressions. */
4987 while (chain)
4988 {
4989 tree element = TREE_VALUE (chain);
4990
4991 /* We have a comma expression, must collapse... */
4992 if (TREE_CODE (element) == TREE_LIST)
4993 {
4994 if (prev)
4995 TREE_CHAIN (prev) = element;
4996 else
4997 args = element;
4998 }
4999 prev = chain;
5000 chain = TREE_CHAIN (chain);
5001 }
5002 method_params = args;
5003 }
5004
5005 /* Determine operation return type. */
5006
5007 if (IS_SUPER (rtype))
5008 {
5009 tree iface;
5010
5011 if (CLASS_SUPER_NAME (implementation_template))
5012 {
5013 iface
5014 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5015
5016 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
5017 method_prototype = lookup_instance_method_static (iface, sel_name);
5018 else
5019 method_prototype = lookup_class_method_static (iface, sel_name);
5020
5021 if (iface && !method_prototype)
5022 warning ("`%s' does not respond to `%s'",
5023 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
5024 IDENTIFIER_POINTER (sel_name));
5025 }
5026 else
5027 {
5028 error ("no super class declared in interface for `%s'",
5029 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
5030 return error_mark_node;
5031 }
5032
5033 }
5034 else if (statically_allocated)
5035 {
5036 tree ctype = TREE_TYPE (rtype);
5037 tree iface = lookup_interface (TYPE_NAME (rtype));
5038
5039 if (iface)
5040 method_prototype = lookup_instance_method_static (iface, sel_name);
5041
5042 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5043 method_prototype
5044 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5045 sel_name, 0);
5046
5047 if (!method_prototype)
5048 warning ("`%s' does not respond to `%s'",
5049 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
5050 IDENTIFIER_POINTER (sel_name));
5051 }
5052 else if (statically_typed)
5053 {
5054 tree ctype = TREE_TYPE (rtype);
5055
5056 /* `self' is now statically_typed. All methods should be visible
5057 within the context of the implementation. */
5058 if (implementation_context
5059 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
5060 {
5061 method_prototype
5062 = lookup_instance_method_static (implementation_template,
5063 sel_name);
5064
5065 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5066 method_prototype
5067 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5068 sel_name, 0);
5069
5070 if (! method_prototype
5071 && implementation_template != implementation_context)
5072 /* The method is not published in the interface. Check
5073 locally. */
5074 method_prototype
5075 = lookup_method (CLASS_NST_METHODS (implementation_context),
5076 sel_name);
5077 }
5078 else
5079 {
5080 tree iface;
5081
5082 if ((iface = lookup_interface (TYPE_NAME (ctype))))
5083 method_prototype = lookup_instance_method_static (iface, sel_name);
5084
5085 if (! method_prototype)
5086 {
5087 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5088 if (protocol_list)
5089 method_prototype
5090 = lookup_method_in_protocol_list (protocol_list,
5091 sel_name, 0);
5092 }
5093 }
5094
5095 if (!method_prototype)
5096 warning ("`%s' does not respond to `%s'",
5097 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5098 IDENTIFIER_POINTER (sel_name));
5099 }
5100 else if (class_ident)
5101 {
5102 if (implementation_context
5103 && CLASS_NAME (implementation_context) == class_ident)
5104 {
5105 method_prototype
5106 = lookup_class_method_static (implementation_template, sel_name);
5107
5108 if (!method_prototype
5109 && implementation_template != implementation_context)
5110 /* The method is not published in the interface. Check
5111 locally. */
5112 method_prototype
5113 = lookup_method (CLASS_CLS_METHODS (implementation_context),
5114 sel_name);
5115 }
5116 else
5117 {
5118 tree iface;
5119
5120 if ((iface = lookup_interface (class_ident)))
5121 method_prototype = lookup_class_method_static (iface, sel_name);
5122 }
5123
5124 if (!method_prototype)
5125 {
5126 warning ("cannot find class (factory) method.");
5127 warning ("return type for `%s' defaults to id",
5128 IDENTIFIER_POINTER (sel_name));
5129 }
5130 }
5131 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5132 {
5133 /* An anonymous object that has been qualified with a protocol. */
5134
5135 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5136
5137 method_prototype = lookup_method_in_protocol_list (protocol_list,
5138 sel_name, 0);
5139
5140 if (!method_prototype)
5141 {
5142 hash hsh;
5143
5144 warning ("method `%s' not implemented by protocol.",
5145 IDENTIFIER_POINTER (sel_name));
5146
5147 /* Try and find the method signature in the global pools. */
5148
5149 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5150 hsh = hash_lookup (cls_method_hash_list, sel_name);
5151
5152 if (!(method_prototype = check_duplicates (hsh)))
5153 warning ("return type defaults to id");
5154 }
5155 }
5156 else
5157 {
5158 hash hsh;
5159
5160 /* We think we have an instance...loophole: extern id Object; */
5161 hsh = hash_lookup (nst_method_hash_list, sel_name);
5162 if (!hsh)
5163 /* For various loopholes, like sending messages to self in a
5164 factory context. */
5165 hsh = hash_lookup (cls_method_hash_list, sel_name);
5166
5167 method_prototype = check_duplicates (hsh);
5168 if (!method_prototype)
5169 {
5170 warning ("cannot find method.");
5171 warning ("return type for `%s' defaults to id",
5172 IDENTIFIER_POINTER (sel_name));
5173 }
5174 }
5175
5176 /* Save the selector name for printing error messages. */
5177 building_objc_message_expr = sel_name;
5178
5179 /* Build the parameters list for looking up the method.
5180 These are the object itself and the selector. */
5181
5182 if (flag_typed_selectors)
5183 selector = build_typed_selector_reference (sel_name, method_prototype);
5184 else
5185 selector = build_selector_reference (sel_name);
5186
5187 retval = build_objc_method_call (super, method_prototype,
5188 receiver, self_object,
5189 selector, method_params);
5190
5191 building_objc_message_expr = 0;
5192
5193 return retval;
5194 }
5195 \f
5196 /* Build a tree expression to send OBJECT the operation SELECTOR,
5197 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5198 assuming the method has prototype METHOD_PROTOTYPE.
5199 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5200 Use METHOD_PARAMS as list of args to pass to the method.
5201 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5202
5203 static tree
5204 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5205 selector, method_params)
5206 int super_flag;
5207 tree method_prototype, lookup_object, object, selector, method_params;
5208 {
5209 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5210 tree rcv_p = (super_flag
5211 ? build_pointer_type (xref_tag (RECORD_TYPE,
5212 get_identifier (TAG_SUPER)))
5213 : id_type);
5214
5215 if (flag_next_runtime)
5216 {
5217 if (! method_prototype)
5218 {
5219 method_params = tree_cons (NULL_TREE, lookup_object,
5220 tree_cons (NULL_TREE, selector,
5221 method_params));
5222 assemble_external (sender);
5223 return build_function_call (sender, method_params);
5224 }
5225 else
5226 {
5227 /* This is a real kludge, but it is used only for the Next.
5228 Clobber the data type of SENDER temporarily to accept
5229 all the arguments for this operation, and to return
5230 whatever this operation returns. */
5231 tree arglist = NULL_TREE;
5232 tree retval;
5233
5234 /* Save the proper contents of SENDER's data type. */
5235 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5236 tree savret = TREE_TYPE (TREE_TYPE (sender));
5237
5238 /* Install this method's argument types. */
5239 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5240 super_flag);
5241 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5242
5243 /* Install this method's return type. */
5244 TREE_TYPE (TREE_TYPE (sender))
5245 = groktypename (TREE_TYPE (method_prototype));
5246
5247 /* Call SENDER with all the parameters. This will do type
5248 checking using the arg types for this method. */
5249 method_params = tree_cons (NULL_TREE, lookup_object,
5250 tree_cons (NULL_TREE, selector,
5251 method_params));
5252 assemble_external (sender);
5253 retval = build_function_call (sender, method_params);
5254
5255 /* Restore SENDER's return/argument types. */
5256 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5257 TREE_TYPE (TREE_TYPE (sender)) = savret;
5258 return retval;
5259 }
5260 }
5261 else
5262 {
5263 /* This is the portable way.
5264 First call the lookup function to get a pointer to the method,
5265 then cast the pointer, then call it with the method arguments. */
5266 tree method;
5267
5268 /* Avoid trouble since we may evaluate each of these twice. */
5269 object = save_expr (object);
5270 selector = save_expr (selector);
5271
5272 lookup_object = build_c_cast (rcv_p, lookup_object);
5273
5274 assemble_external (sender);
5275 method
5276 = build_function_call (sender,
5277 tree_cons (NULL_TREE, lookup_object,
5278 tree_cons (NULL_TREE, selector,
5279 NULL_TREE)));
5280
5281 /* If we have a method prototype, construct the data type this
5282 method needs, and cast what we got from SENDER into a pointer
5283 to that type. */
5284 if (method_prototype)
5285 {
5286 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5287 super_flag);
5288 tree valtype = groktypename (TREE_TYPE (method_prototype));
5289 tree fake_function_type = build_function_type (valtype, arglist);
5290 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5291 }
5292 else
5293 TREE_TYPE (method)
5294 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5295
5296 /* Pass the object to the method. */
5297 assemble_external (method);
5298 return build_function_call (method,
5299 tree_cons (NULL_TREE, object,
5300 tree_cons (NULL_TREE, selector,
5301 method_params)));
5302 }
5303 }
5304 \f
5305 static void
5306 build_protocol_reference (p)
5307 tree p;
5308 {
5309 tree decl, ident, ptype;
5310
5311 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5312
5313 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5314 ptype
5315 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5316 objc_protocol_template),
5317 NULL_TREE));
5318
5319 if (IDENTIFIER_GLOBAL_VALUE (ident))
5320 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5321 else
5322 {
5323 decl = build_decl (VAR_DECL, ident, ptype);
5324 DECL_EXTERNAL (decl) = 1;
5325 TREE_PUBLIC (decl) = 1;
5326 TREE_USED (decl) = 1;
5327 DECL_ARTIFICIAL (decl) = 1;
5328
5329 make_decl_rtl (decl, 0, 1);
5330 pushdecl_top_level (decl);
5331 }
5332
5333 PROTOCOL_FORWARD_DECL (p) = decl;
5334 }
5335
5336 tree
5337 build_protocol_expr (protoname)
5338 tree protoname;
5339 {
5340 tree expr;
5341 tree p = lookup_protocol (protoname);
5342
5343 if (!p)
5344 {
5345 error ("Cannot find protocol declaration for `%s'",
5346 IDENTIFIER_POINTER (protoname));
5347 return error_mark_node;
5348 }
5349
5350 if (!PROTOCOL_FORWARD_DECL (p))
5351 build_protocol_reference (p);
5352
5353 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5354
5355 TREE_TYPE (expr) = protocol_type;
5356
5357 return expr;
5358 }
5359
5360 tree
5361 build_selector_expr (selnamelist)
5362 tree selnamelist;
5363 {
5364 tree selname;
5365
5366 /* Obtain the full selector name. */
5367 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5368 /* A unary selector. */
5369 selname = selnamelist;
5370 else if (TREE_CODE (selnamelist) == TREE_LIST)
5371 selname = build_keyword_selector (selnamelist);
5372 else
5373 abort ();
5374
5375 if (flag_typed_selectors)
5376 return build_typed_selector_reference (selname, 0);
5377 else
5378 return build_selector_reference (selname);
5379 }
5380
5381 tree
5382 build_encode_expr (type)
5383 tree type;
5384 {
5385 tree result;
5386 const char *string;
5387
5388 encode_type (type, obstack_object_size (&util_obstack),
5389 OBJC_ENCODE_INLINE_DEFS);
5390 obstack_1grow (&util_obstack, 0); /* null terminate string */
5391 string = obstack_finish (&util_obstack);
5392
5393 /* Synthesize a string that represents the encoded struct/union. */
5394 result = my_build_string (strlen (string) + 1, string);
5395 obstack_free (&util_obstack, util_firstobj);
5396 return result;
5397 }
5398
5399 tree
5400 build_ivar_reference (id)
5401 tree id;
5402 {
5403 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5404 {
5405 /* Historically, a class method that produced objects (factory
5406 method) would assign `self' to the instance that it
5407 allocated. This would effectively turn the class method into
5408 an instance method. Following this assignment, the instance
5409 variables could be accessed. That practice, while safe,
5410 violates the simple rule that a class method should not refer
5411 to an instance variable. It's better to catch the cases
5412 where this is done unknowingly than to support the above
5413 paradigm. */
5414 warning ("instance variable `%s' accessed in class method",
5415 IDENTIFIER_POINTER (id));
5416 TREE_TYPE (self_decl) = instance_type; /* cast */
5417 }
5418
5419 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5420 }
5421 \f
5422 #define HASH_ALLOC_LIST_SIZE 170
5423 #define ATTR_ALLOC_LIST_SIZE 170
5424 #define SIZEHASHTABLE 257
5425
5426 /* make positive */
5427 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5428
5429 static void
5430 hash_init ()
5431 {
5432 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5433 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5434
5435 if (!nst_method_hash_list || !cls_method_hash_list)
5436 perror ("unable to allocate space in objc-tree.c");
5437 else
5438 {
5439 int i;
5440
5441 for (i = 0; i < SIZEHASHTABLE; i++)
5442 {
5443 nst_method_hash_list[i] = 0;
5444 cls_method_hash_list[i] = 0;
5445 }
5446 }
5447 }
5448
5449 static void
5450 hash_enter (hashlist, method)
5451 hash *hashlist;
5452 tree method;
5453 {
5454 static hash hash_alloc_list = 0;
5455 static int hash_alloc_index = 0;
5456 hash obj;
5457 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5458
5459 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5460 {
5461 hash_alloc_index = 0;
5462 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5463 * HASH_ALLOC_LIST_SIZE);
5464 if (! hash_alloc_list)
5465 perror ("unable to allocate in objc-tree.c");
5466 }
5467 obj = &hash_alloc_list[hash_alloc_index++];
5468 obj->list = 0;
5469 obj->next = hashlist[slot];
5470 obj->key = method;
5471
5472 hashlist[slot] = obj; /* append to front */
5473 }
5474
5475 static hash
5476 hash_lookup (hashlist, sel_name)
5477 hash *hashlist;
5478 tree sel_name;
5479 {
5480 hash target;
5481
5482 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5483
5484 while (target)
5485 {
5486 if (sel_name == METHOD_SEL_NAME (target->key))
5487 return target;
5488
5489 target = target->next;
5490 }
5491 return 0;
5492 }
5493
5494 static void
5495 hash_add_attr (entry, value)
5496 hash entry;
5497 tree value;
5498 {
5499 static attr attr_alloc_list = 0;
5500 static int attr_alloc_index = 0;
5501 attr obj;
5502
5503 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5504 {
5505 attr_alloc_index = 0;
5506 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5507 * ATTR_ALLOC_LIST_SIZE);
5508 if (! attr_alloc_list)
5509 perror ("unable to allocate in objc-tree.c");
5510 }
5511 obj = &attr_alloc_list[attr_alloc_index++];
5512 obj->next = entry->list;
5513 obj->value = value;
5514
5515 entry->list = obj; /* append to front */
5516 }
5517 \f
5518 static tree
5519 lookup_method (mchain, method)
5520 tree mchain;
5521 tree method;
5522 {
5523 tree key;
5524
5525 if (TREE_CODE (method) == IDENTIFIER_NODE)
5526 key = method;
5527 else
5528 key = METHOD_SEL_NAME (method);
5529
5530 while (mchain)
5531 {
5532 if (METHOD_SEL_NAME (mchain) == key)
5533 return mchain;
5534 mchain = TREE_CHAIN (mchain);
5535 }
5536 return NULL_TREE;
5537 }
5538
5539 static tree
5540 lookup_instance_method_static (interface, ident)
5541 tree interface;
5542 tree ident;
5543 {
5544 tree inter = interface;
5545 tree chain = CLASS_NST_METHODS (inter);
5546 tree meth = NULL_TREE;
5547
5548 do
5549 {
5550 if ((meth = lookup_method (chain, ident)))
5551 return meth;
5552
5553 if (CLASS_CATEGORY_LIST (inter))
5554 {
5555 tree category = CLASS_CATEGORY_LIST (inter);
5556 chain = CLASS_NST_METHODS (category);
5557
5558 do
5559 {
5560 if ((meth = lookup_method (chain, ident)))
5561 return meth;
5562
5563 /* Check for instance methods in protocols in categories. */
5564 if (CLASS_PROTOCOL_LIST (category))
5565 {
5566 if ((meth = (lookup_method_in_protocol_list
5567 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5568 return meth;
5569 }
5570
5571 if ((category = CLASS_CATEGORY_LIST (category)))
5572 chain = CLASS_NST_METHODS (category);
5573 }
5574 while (category);
5575 }
5576
5577 if (CLASS_PROTOCOL_LIST (inter))
5578 {
5579 if ((meth = (lookup_method_in_protocol_list
5580 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5581 return meth;
5582 }
5583
5584 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5585 chain = CLASS_NST_METHODS (inter);
5586 }
5587 while (inter);
5588
5589 return meth;
5590 }
5591
5592 static tree
5593 lookup_class_method_static (interface, ident)
5594 tree interface;
5595 tree ident;
5596 {
5597 tree inter = interface;
5598 tree chain = CLASS_CLS_METHODS (inter);
5599 tree meth = NULL_TREE;
5600 tree root_inter = NULL_TREE;
5601
5602 do
5603 {
5604 if ((meth = lookup_method (chain, ident)))
5605 return meth;
5606
5607 if (CLASS_CATEGORY_LIST (inter))
5608 {
5609 tree category = CLASS_CATEGORY_LIST (inter);
5610 chain = CLASS_CLS_METHODS (category);
5611
5612 do
5613 {
5614 if ((meth = lookup_method (chain, ident)))
5615 return meth;
5616
5617 /* Check for class methods in protocols in categories. */
5618 if (CLASS_PROTOCOL_LIST (category))
5619 {
5620 if ((meth = (lookup_method_in_protocol_list
5621 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5622 return meth;
5623 }
5624
5625 if ((category = CLASS_CATEGORY_LIST (category)))
5626 chain = CLASS_CLS_METHODS (category);
5627 }
5628 while (category);
5629 }
5630
5631 /* Check for class methods in protocols. */
5632 if (CLASS_PROTOCOL_LIST (inter))
5633 {
5634 if ((meth = (lookup_method_in_protocol_list
5635 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5636 return meth;
5637 }
5638
5639 root_inter = inter;
5640 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5641 chain = CLASS_CLS_METHODS (inter);
5642 }
5643 while (inter);
5644
5645 /* Simulate wrap around. */
5646 return lookup_instance_method_static (root_inter, ident);
5647 }
5648
5649 tree
5650 add_class_method (class, method)
5651 tree class;
5652 tree method;
5653 {
5654 tree mth;
5655 hash hsh;
5656
5657 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5658 {
5659 /* put method on list in reverse order */
5660 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5661 CLASS_CLS_METHODS (class) = method;
5662 }
5663 else
5664 {
5665 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5666 error ("duplicate definition of class method `%s'.",
5667 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5668 else
5669 {
5670 /* Check types; if different, complain. */
5671 if (!comp_proto_with_proto (method, mth))
5672 error ("duplicate declaration of class method `%s'.",
5673 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5674 }
5675 }
5676
5677 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5678 {
5679 /* Install on a global chain. */
5680 hash_enter (cls_method_hash_list, method);
5681 }
5682 else
5683 {
5684 /* Check types; if different, add to a list. */
5685 if (!comp_proto_with_proto (method, hsh->key))
5686 hash_add_attr (hsh, method);
5687 }
5688 return method;
5689 }
5690 \f
5691 tree
5692 add_instance_method (class, method)
5693 tree class;
5694 tree method;
5695 {
5696 tree mth;
5697 hash hsh;
5698
5699 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5700 {
5701 /* Put method on list in reverse order. */
5702 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5703 CLASS_NST_METHODS (class) = method;
5704 }
5705 else
5706 {
5707 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5708 error ("duplicate definition of instance method `%s'.",
5709 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5710 else
5711 {
5712 /* Check types; if different, complain. */
5713 if (!comp_proto_with_proto (method, mth))
5714 error ("duplicate declaration of instance method `%s'.",
5715 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5716 }
5717 }
5718
5719 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5720 {
5721 /* Install on a global chain. */
5722 hash_enter (nst_method_hash_list, method);
5723 }
5724 else
5725 {
5726 /* Check types; if different, add to a list. */
5727 if (!comp_proto_with_proto (method, hsh->key))
5728 hash_add_attr (hsh, method);
5729 }
5730 return method;
5731 }
5732
5733 static tree
5734 add_class (class)
5735 tree class;
5736 {
5737 /* Put interfaces on list in reverse order. */
5738 TREE_CHAIN (class) = interface_chain;
5739 interface_chain = class;
5740 return interface_chain;
5741 }
5742
5743 static void
5744 add_category (class, category)
5745 tree class;
5746 tree category;
5747 {
5748 /* Put categories on list in reverse order. */
5749 tree cat = CLASS_CATEGORY_LIST (class);
5750
5751 while (cat)
5752 {
5753 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5754 warning ("duplicate interface declaration for category `%s(%s)'",
5755 IDENTIFIER_POINTER (CLASS_NAME (class)),
5756 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5757 cat = CLASS_CATEGORY_LIST (cat);
5758 }
5759
5760 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5761 CLASS_CATEGORY_LIST (class) = category;
5762 }
5763
5764 /* Called after parsing each instance variable declaration. Necessary to
5765 preserve typedefs and implement public/private...
5766
5767 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5768
5769 tree
5770 add_instance_variable (class, public, declarator, declspecs, width)
5771 tree class;
5772 int public;
5773 tree declarator;
5774 tree declspecs;
5775 tree width;
5776 {
5777 tree field_decl, raw_decl;
5778
5779 raw_decl = build_tree_list (declspecs, declarator);
5780
5781 if (CLASS_RAW_IVARS (class))
5782 chainon (CLASS_RAW_IVARS (class), raw_decl);
5783 else
5784 CLASS_RAW_IVARS (class) = raw_decl;
5785
5786 field_decl = grokfield (input_filename, lineno,
5787 declarator, declspecs, width);
5788
5789 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5790 switch (public)
5791 {
5792 case 0:
5793 TREE_PUBLIC (field_decl) = 0;
5794 TREE_PRIVATE (field_decl) = 0;
5795 TREE_PROTECTED (field_decl) = 1;
5796 break;
5797
5798 case 1:
5799 TREE_PUBLIC (field_decl) = 1;
5800 TREE_PRIVATE (field_decl) = 0;
5801 TREE_PROTECTED (field_decl) = 0;
5802 break;
5803
5804 case 2:
5805 TREE_PUBLIC (field_decl) = 0;
5806 TREE_PRIVATE (field_decl) = 1;
5807 TREE_PROTECTED (field_decl) = 0;
5808 break;
5809
5810 }
5811
5812 if (CLASS_IVARS (class))
5813 chainon (CLASS_IVARS (class), field_decl);
5814 else
5815 CLASS_IVARS (class) = field_decl;
5816
5817 return class;
5818 }
5819 \f
5820 tree
5821 is_ivar (decl_chain, ident)
5822 tree decl_chain;
5823 tree ident;
5824 {
5825 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5826 if (DECL_NAME (decl_chain) == ident)
5827 return decl_chain;
5828 return NULL_TREE;
5829 }
5830
5831 /* True if the ivar is private and we are not in its implementation. */
5832
5833 int
5834 is_private (decl)
5835 tree decl;
5836 {
5837 if (TREE_PRIVATE (decl)
5838 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5839 {
5840 error ("instance variable `%s' is declared private",
5841 IDENTIFIER_POINTER (DECL_NAME (decl)));
5842 return 1;
5843 }
5844 else
5845 return 0;
5846 }
5847
5848 /* We have an instance variable reference;, check to see if it is public. */
5849
5850 int
5851 is_public (expr, identifier)
5852 tree expr;
5853 tree identifier;
5854 {
5855 tree basetype = TREE_TYPE (expr);
5856 enum tree_code code = TREE_CODE (basetype);
5857 tree decl;
5858
5859 if (code == RECORD_TYPE)
5860 {
5861 if (TREE_STATIC_TEMPLATE (basetype))
5862 {
5863 if (!lookup_interface (TYPE_NAME (basetype)))
5864 {
5865 error ("Cannot find interface declaration for `%s'",
5866 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5867 return 0;
5868 }
5869
5870 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5871 {
5872 if (TREE_PUBLIC (decl))
5873 return 1;
5874
5875 /* Important difference between the Stepstone translator:
5876 all instance variables should be public within the context
5877 of the implementation. */
5878 if (implementation_context
5879 && (((TREE_CODE (implementation_context)
5880 == CLASS_IMPLEMENTATION_TYPE)
5881 || (TREE_CODE (implementation_context)
5882 == CATEGORY_IMPLEMENTATION_TYPE))
5883 && (CLASS_NAME (implementation_context)
5884 == TYPE_NAME (basetype))))
5885 return ! is_private (decl);
5886
5887 error ("instance variable `%s' is declared %s",
5888 IDENTIFIER_POINTER (identifier),
5889 TREE_PRIVATE (decl) ? "private" : "protected");
5890 return 0;
5891 }
5892 }
5893
5894 else if (implementation_context && (basetype == objc_object_reference))
5895 {
5896 TREE_TYPE (expr) = uprivate_record;
5897 warning ("static access to object of type `id'");
5898 }
5899 }
5900
5901 return 1;
5902 }
5903
5904 /* Implement @defs (<classname>) within struct bodies. */
5905
5906 tree
5907 get_class_ivars (interface)
5908 tree interface;
5909 {
5910 return build_ivar_chain (interface, 1);
5911 }
5912 \f
5913 /* Make sure all entries in CHAIN are also in LIST. */
5914
5915 static int
5916 check_methods (chain, list, mtype)
5917 tree chain;
5918 tree list;
5919 int mtype;
5920 {
5921 int first = 1;
5922
5923 while (chain)
5924 {
5925 if (!lookup_method (list, chain))
5926 {
5927 if (first)
5928 {
5929 if (TREE_CODE (implementation_context)
5930 == CLASS_IMPLEMENTATION_TYPE)
5931 warning ("incomplete implementation of class `%s'",
5932 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5933 else if (TREE_CODE (implementation_context)
5934 == CATEGORY_IMPLEMENTATION_TYPE)
5935 warning ("incomplete implementation of category `%s'",
5936 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5937 first = 0;
5938 }
5939
5940 warning ("method definition for `%c%s' not found",
5941 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5942 }
5943
5944 chain = TREE_CHAIN (chain);
5945 }
5946
5947 return first;
5948 }
5949
5950 static int
5951 conforms_to_protocol (class, protocol)
5952 tree class;
5953 tree protocol;
5954 {
5955 while (protocol)
5956 {
5957 tree p = CLASS_PROTOCOL_LIST (class);
5958
5959 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5960 p = TREE_CHAIN (p);
5961
5962 if (!p)
5963 {
5964 tree super = (CLASS_SUPER_NAME (class)
5965 ? lookup_interface (CLASS_SUPER_NAME (class))
5966 : NULL_TREE);
5967 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5968 if (!tmp)
5969 return 0;
5970 }
5971
5972 protocol = TREE_CHAIN (protocol);
5973 }
5974
5975 return 1;
5976 }
5977
5978 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5979 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5980
5981 static int
5982 check_methods_accessible (chain, context, mtype)
5983 tree chain;
5984 tree context;
5985 int mtype;
5986 {
5987 int first = 1;
5988 tree list;
5989 tree base_context = context;
5990
5991 while (chain)
5992 {
5993 context = base_context;
5994 while (context)
5995 {
5996 if (mtype == '+')
5997 list = CLASS_CLS_METHODS (context);
5998 else
5999 list = CLASS_NST_METHODS (context);
6000
6001 if (lookup_method (list, chain))
6002 break;
6003
6004 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6005 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6006 context = (CLASS_SUPER_NAME (context)
6007 ? lookup_interface (CLASS_SUPER_NAME (context))
6008 : NULL_TREE);
6009
6010 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6011 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6012 context = (CLASS_NAME (context)
6013 ? lookup_interface (CLASS_NAME (context))
6014 : NULL_TREE);
6015 else
6016 abort ();
6017 }
6018
6019 if (context == NULL_TREE)
6020 {
6021 if (first)
6022 {
6023 if (TREE_CODE (implementation_context)
6024 == CLASS_IMPLEMENTATION_TYPE)
6025 warning ("incomplete implementation of class `%s'",
6026 IDENTIFIER_POINTER
6027 (CLASS_NAME (implementation_context)));
6028 else if (TREE_CODE (implementation_context)
6029 == CATEGORY_IMPLEMENTATION_TYPE)
6030 warning ("incomplete implementation of category `%s'",
6031 IDENTIFIER_POINTER
6032 (CLASS_SUPER_NAME (implementation_context)));
6033 first = 0;
6034 }
6035 warning ("method definition for `%c%s' not found",
6036 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6037 }
6038
6039 chain = TREE_CHAIN (chain); /* next method... */
6040 }
6041 return first;
6042 }
6043
6044 static void
6045 check_protocols (proto_list, type, name)
6046 tree proto_list;
6047 const char *type;
6048 const char *name;
6049 {
6050 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6051 {
6052 tree p = TREE_VALUE (proto_list);
6053
6054 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6055 {
6056 int f1, f2;
6057
6058 /* Ensure that all protocols have bodies. */
6059 if (flag_warn_protocol) {
6060 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6061 CLASS_CLS_METHODS (implementation_context),
6062 '+');
6063 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6064 CLASS_NST_METHODS (implementation_context),
6065 '-');
6066 } else {
6067 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6068 implementation_context,
6069 '+');
6070 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6071 implementation_context,
6072 '-');
6073 }
6074
6075 if (!f1 || !f2)
6076 warning ("%s `%s' does not fully implement the `%s' protocol",
6077 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6078
6079 }
6080 else
6081 {
6082 ; /* An identifier if we could not find a protocol. */
6083 }
6084
6085 /* Check protocols recursively. */
6086 if (PROTOCOL_LIST (p))
6087 {
6088 tree super_class
6089 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6090 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
6091 check_protocols (PROTOCOL_LIST (p), type, name);
6092 }
6093 }
6094 }
6095 \f
6096 /* Make sure that the class CLASS_NAME is defined
6097 CODE says which kind of thing CLASS_NAME ought to be.
6098 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6099 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
6100
6101 tree
6102 start_class (code, class_name, super_name, protocol_list)
6103 enum tree_code code;
6104 tree class_name;
6105 tree super_name;
6106 tree protocol_list;
6107 {
6108 tree class, decl;
6109
6110 class = make_node (code);
6111 TYPE_BINFO (class) = make_tree_vec (5);
6112
6113 CLASS_NAME (class) = class_name;
6114 CLASS_SUPER_NAME (class) = super_name;
6115 CLASS_CLS_METHODS (class) = NULL_TREE;
6116
6117 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6118 {
6119 error ("`%s' redeclared as different kind of symbol",
6120 IDENTIFIER_POINTER (class_name));
6121 error_with_decl (decl, "previous declaration of `%s'");
6122 }
6123
6124 if (code == CLASS_IMPLEMENTATION_TYPE)
6125 {
6126 {
6127 static tree implemented_classes = 0;
6128 tree chain = implemented_classes;
6129 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6130 if (TREE_VALUE (chain) == class_name)
6131 {
6132 error ("reimplementation of class `%s'",
6133 IDENTIFIER_POINTER (class_name));
6134 return error_mark_node;
6135 }
6136 implemented_classes = tree_cons (NULL_TREE, class_name,
6137 implemented_classes);
6138 }
6139
6140 /* Pre-build the following entities - for speed/convenience. */
6141 if (!self_id)
6142 self_id = get_identifier ("self");
6143 if (!ucmd_id)
6144 ucmd_id = get_identifier ("_cmd");
6145 if (!unused_list)
6146 unused_list
6147 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6148 if (!objc_super_template)
6149 objc_super_template = build_super_template ();
6150
6151 /* Reset for multiple classes per file. */
6152 method_slot = 0;
6153
6154 implementation_context = class;
6155
6156 /* Lookup the interface for this implementation. */
6157
6158 if (!(implementation_template = lookup_interface (class_name)))
6159 {
6160 warning ("Cannot find interface declaration for `%s'",
6161 IDENTIFIER_POINTER (class_name));
6162 add_class (implementation_template = implementation_context);
6163 }
6164
6165 /* If a super class has been specified in the implementation,
6166 insure it conforms to the one specified in the interface. */
6167
6168 if (super_name
6169 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6170 {
6171 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6172 const char *name =
6173 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6174 error ("conflicting super class name `%s'",
6175 IDENTIFIER_POINTER (super_name));
6176 error ("previous declaration of `%s'", name);
6177 }
6178
6179 else if (! super_name)
6180 {
6181 CLASS_SUPER_NAME (implementation_context)
6182 = CLASS_SUPER_NAME (implementation_template);
6183 }
6184 }
6185
6186 else if (code == CLASS_INTERFACE_TYPE)
6187 {
6188 if (lookup_interface (class_name))
6189 warning ("duplicate interface declaration for class `%s'",
6190 IDENTIFIER_POINTER (class_name));
6191 else
6192 add_class (class);
6193
6194 if (protocol_list)
6195 CLASS_PROTOCOL_LIST (class)
6196 = lookup_and_install_protocols (protocol_list);
6197 }
6198
6199 else if (code == CATEGORY_INTERFACE_TYPE)
6200 {
6201 tree class_category_is_assoc_with;
6202
6203 /* For a category, class_name is really the name of the class that
6204 the following set of methods will be associated with. We must
6205 find the interface so that can derive the objects template. */
6206
6207 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6208 {
6209 error ("Cannot find interface declaration for `%s'",
6210 IDENTIFIER_POINTER (class_name));
6211 exit (FATAL_EXIT_CODE);
6212 }
6213 else
6214 add_category (class_category_is_assoc_with, class);
6215
6216 if (protocol_list)
6217 CLASS_PROTOCOL_LIST (class)
6218 = lookup_and_install_protocols (protocol_list);
6219 }
6220
6221 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6222 {
6223 /* Pre-build the following entities for speed/convenience. */
6224 if (!self_id)
6225 self_id = get_identifier ("self");
6226 if (!ucmd_id)
6227 ucmd_id = get_identifier ("_cmd");
6228 if (!unused_list)
6229 unused_list
6230 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6231 if (!objc_super_template)
6232 objc_super_template = build_super_template ();
6233
6234 /* Reset for multiple classes per file. */
6235 method_slot = 0;
6236
6237 implementation_context = class;
6238
6239 /* For a category, class_name is really the name of the class that
6240 the following set of methods will be associated with. We must
6241 find the interface so that can derive the objects template. */
6242
6243 if (!(implementation_template = lookup_interface (class_name)))
6244 {
6245 error ("Cannot find interface declaration for `%s'",
6246 IDENTIFIER_POINTER (class_name));
6247 exit (FATAL_EXIT_CODE);
6248 }
6249 }
6250 return class;
6251 }
6252
6253 tree
6254 continue_class (class)
6255 tree class;
6256 {
6257 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6258 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6259 {
6260 struct imp_entry *imp_entry;
6261 tree ivar_context;
6262
6263 /* Check consistency of the instance variables. */
6264
6265 if (CLASS_IVARS (class))
6266 check_ivars (implementation_template, class);
6267
6268 /* code generation */
6269
6270 ivar_context = build_private_template (implementation_template);
6271
6272 if (!objc_class_template)
6273 build_class_template ();
6274
6275 if (!(imp_entry
6276 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6277 perror ("unable to allocate in objc-tree.c");
6278
6279 imp_entry->next = imp_list;
6280 imp_entry->imp_context = class;
6281 imp_entry->imp_template = implementation_template;
6282
6283 synth_forward_declarations ();
6284 imp_entry->class_decl = UOBJC_CLASS_decl;
6285 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6286
6287 /* Append to front and increment count. */
6288 imp_list = imp_entry;
6289 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6290 imp_count++;
6291 else
6292 cat_count++;
6293
6294 return ivar_context;
6295 }
6296
6297 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6298 {
6299 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6300
6301 if (!TYPE_FIELDS (record))
6302 {
6303 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6304 CLASS_STATIC_TEMPLATE (class) = record;
6305
6306 /* Mark this record as a class template for static typing. */
6307 TREE_STATIC_TEMPLATE (record) = 1;
6308 }
6309
6310 return NULL_TREE;
6311 }
6312
6313 else
6314 return error_mark_node;
6315 }
6316
6317 /* This is called once we see the "@end" in an interface/implementation. */
6318
6319 void
6320 finish_class (class)
6321 tree class;
6322 {
6323 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6324 {
6325 /* All code generation is done in finish_objc. */
6326
6327 if (implementation_template != implementation_context)
6328 {
6329 /* Ensure that all method listed in the interface contain bodies. */
6330 check_methods (CLASS_CLS_METHODS (implementation_template),
6331 CLASS_CLS_METHODS (implementation_context), '+');
6332 check_methods (CLASS_NST_METHODS (implementation_template),
6333 CLASS_NST_METHODS (implementation_context), '-');
6334
6335 if (CLASS_PROTOCOL_LIST (implementation_template))
6336 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6337 "class",
6338 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6339 }
6340 }
6341
6342 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6343 {
6344 tree category = CLASS_CATEGORY_LIST (implementation_template);
6345
6346 /* Find the category interface from the class it is associated with. */
6347 while (category)
6348 {
6349 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6350 break;
6351 category = CLASS_CATEGORY_LIST (category);
6352 }
6353
6354 if (category)
6355 {
6356 /* Ensure all method listed in the interface contain bodies. */
6357 check_methods (CLASS_CLS_METHODS (category),
6358 CLASS_CLS_METHODS (implementation_context), '+');
6359 check_methods (CLASS_NST_METHODS (category),
6360 CLASS_NST_METHODS (implementation_context), '-');
6361
6362 if (CLASS_PROTOCOL_LIST (category))
6363 check_protocols (CLASS_PROTOCOL_LIST (category),
6364 "category",
6365 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6366 }
6367 }
6368
6369 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6370 {
6371 tree decl_specs;
6372 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6373 char *string = (char *) alloca (strlen (class_name) + 3);
6374
6375 /* extern struct objc_object *_<my_name>; */
6376
6377 sprintf (string, "_%s", class_name);
6378
6379 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6380 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6381 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6382 decl_specs);
6383 }
6384 }
6385
6386 static tree
6387 add_protocol (protocol)
6388 tree protocol;
6389 {
6390 /* Put protocol on list in reverse order. */
6391 TREE_CHAIN (protocol) = protocol_chain;
6392 protocol_chain = protocol;
6393 return protocol_chain;
6394 }
6395
6396 static tree
6397 lookup_protocol (ident)
6398 tree ident;
6399 {
6400 tree chain;
6401
6402 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6403 {
6404 if (ident == PROTOCOL_NAME (chain))
6405 return chain;
6406 }
6407
6408 return NULL_TREE;
6409 }
6410
6411 tree
6412 start_protocol (code, name, list)
6413 enum tree_code code;
6414 tree name;
6415 tree list;
6416 {
6417 tree protocol;
6418
6419 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6420 if (!objc_protocol_template)
6421 objc_protocol_template = build_protocol_template ();
6422
6423 protocol = make_node (code);
6424 TYPE_BINFO (protocol) = make_tree_vec (2);
6425
6426 PROTOCOL_NAME (protocol) = name;
6427 PROTOCOL_LIST (protocol) = list;
6428
6429 lookup_and_install_protocols (list);
6430
6431 if (lookup_protocol (name))
6432 warning ("duplicate declaration for protocol `%s'",
6433 IDENTIFIER_POINTER (name));
6434 else
6435 add_protocol (protocol);
6436
6437 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6438
6439 return protocol;
6440 }
6441
6442 void
6443 finish_protocol (protocol)
6444 tree protocol ATTRIBUTE_UNUSED;
6445 {
6446 }
6447
6448 \f
6449 /* "Encode" a data type into a string, which grows in util_obstack.
6450 ??? What is the FORMAT? Someone please document this! */
6451
6452 static void
6453 encode_type_qualifiers (declspecs)
6454 tree declspecs;
6455 {
6456 tree spec;
6457
6458 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6459 {
6460 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6461 obstack_1grow (&util_obstack, 'r');
6462 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6463 obstack_1grow (&util_obstack, 'n');
6464 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6465 obstack_1grow (&util_obstack, 'N');
6466 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6467 obstack_1grow (&util_obstack, 'o');
6468 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6469 obstack_1grow (&util_obstack, 'O');
6470 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6471 obstack_1grow (&util_obstack, 'R');
6472 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6473 obstack_1grow (&util_obstack, 'V');
6474 }
6475 }
6476
6477 /* Encode a pointer type. */
6478
6479 static void
6480 encode_pointer (type, curtype, format)
6481 tree type;
6482 int curtype;
6483 int format;
6484 {
6485 tree pointer_to = TREE_TYPE (type);
6486
6487 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6488 {
6489 if (TYPE_NAME (pointer_to)
6490 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6491 {
6492 const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6493
6494 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6495 {
6496 obstack_1grow (&util_obstack, '@');
6497 return;
6498 }
6499 else if (TREE_STATIC_TEMPLATE (pointer_to))
6500 {
6501 if (generating_instance_variables)
6502 {
6503 obstack_1grow (&util_obstack, '@');
6504 obstack_1grow (&util_obstack, '"');
6505 obstack_grow (&util_obstack, name, strlen (name));
6506 obstack_1grow (&util_obstack, '"');
6507 return;
6508 }
6509 else
6510 {
6511 obstack_1grow (&util_obstack, '@');
6512 return;
6513 }
6514 }
6515 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6516 {
6517 obstack_1grow (&util_obstack, '#');
6518 return;
6519 }
6520 #ifndef OBJC_INT_SELECTORS
6521 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6522 {
6523 obstack_1grow (&util_obstack, ':');
6524 return;
6525 }
6526 #endif /* OBJC_INT_SELECTORS */
6527 }
6528 }
6529 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6530 && TYPE_MODE (pointer_to) == QImode)
6531 {
6532 obstack_1grow (&util_obstack, '*');
6533 return;
6534 }
6535
6536 /* We have a type that does not get special treatment. */
6537
6538 /* NeXT extension */
6539 obstack_1grow (&util_obstack, '^');
6540 encode_type (pointer_to, curtype, format);
6541 }
6542
6543 static void
6544 encode_array (type, curtype, format)
6545 tree type;
6546 int curtype;
6547 int format;
6548 {
6549 tree an_int_cst = TYPE_SIZE (type);
6550 tree array_of = TREE_TYPE (type);
6551 char buffer[40];
6552
6553 /* An incomplete array is treated like a pointer. */
6554 if (an_int_cst == NULL)
6555 {
6556 encode_pointer (type, curtype, format);
6557 return;
6558 }
6559
6560 sprintf (buffer, "[%ld",
6561 (long) (TREE_INT_CST_LOW (an_int_cst)
6562 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6563
6564 obstack_grow (&util_obstack, buffer, strlen (buffer));
6565 encode_type (array_of, curtype, format);
6566 obstack_1grow (&util_obstack, ']');
6567 return;
6568 }
6569 \f
6570 static void
6571 encode_aggregate_within (type, curtype, format, left, right)
6572 tree type;
6573 int curtype;
6574 int format;
6575 int left;
6576 int right;
6577 {
6578 if (obstack_object_size (&util_obstack) > 0
6579 && *(obstack_next_free (&util_obstack) - 1) == '^')
6580 {
6581 tree name = TYPE_NAME (type);
6582
6583 /* we have a reference; this is a NeXT extension. */
6584
6585 if (obstack_object_size (&util_obstack) - curtype == 1
6586 && format == OBJC_ENCODE_INLINE_DEFS)
6587 {
6588 /* Output format of struct for first level only. */
6589 tree fields = TYPE_FIELDS (type);
6590
6591 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6592 {
6593 obstack_1grow (&util_obstack, left);
6594 obstack_grow (&util_obstack,
6595 IDENTIFIER_POINTER (name),
6596 strlen (IDENTIFIER_POINTER (name)));
6597 obstack_1grow (&util_obstack, '=');
6598 }
6599 else
6600 {
6601 obstack_1grow (&util_obstack, left);
6602 obstack_grow (&util_obstack, "?=", 2);
6603 }
6604
6605 for ( ; fields; fields = TREE_CHAIN (fields))
6606 encode_field_decl (fields, curtype, format);
6607
6608 obstack_1grow (&util_obstack, right);
6609 }
6610
6611 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6612 {
6613 obstack_1grow (&util_obstack, left);
6614 obstack_grow (&util_obstack,
6615 IDENTIFIER_POINTER (name),
6616 strlen (IDENTIFIER_POINTER (name)));
6617 obstack_1grow (&util_obstack, right);
6618 }
6619
6620 else
6621 {
6622 /* We have an untagged structure or a typedef. */
6623 obstack_1grow (&util_obstack, left);
6624 obstack_1grow (&util_obstack, '?');
6625 obstack_1grow (&util_obstack, right);
6626 }
6627 }
6628
6629 else
6630 {
6631 tree name = TYPE_NAME (type);
6632 tree fields = TYPE_FIELDS (type);
6633
6634 if (format == OBJC_ENCODE_INLINE_DEFS
6635 || generating_instance_variables)
6636 {
6637 obstack_1grow (&util_obstack, left);
6638 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6639 obstack_grow (&util_obstack,
6640 IDENTIFIER_POINTER (name),
6641 strlen (IDENTIFIER_POINTER (name)));
6642 else
6643 obstack_1grow (&util_obstack, '?');
6644
6645 obstack_1grow (&util_obstack, '=');
6646
6647 for (; fields; fields = TREE_CHAIN (fields))
6648 {
6649 if (generating_instance_variables)
6650 {
6651 tree fname = DECL_NAME (fields);
6652
6653 obstack_1grow (&util_obstack, '"');
6654 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6655 {
6656 obstack_grow (&util_obstack,
6657 IDENTIFIER_POINTER (fname),
6658 strlen (IDENTIFIER_POINTER (fname)));
6659 }
6660
6661 obstack_1grow (&util_obstack, '"');
6662 }
6663
6664 encode_field_decl (fields, curtype, format);
6665 }
6666
6667 obstack_1grow (&util_obstack, right);
6668 }
6669
6670 else
6671 {
6672 obstack_1grow (&util_obstack, left);
6673 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6674 obstack_grow (&util_obstack,
6675 IDENTIFIER_POINTER (name),
6676 strlen (IDENTIFIER_POINTER (name)));
6677 else
6678 /* We have an untagged structure or a typedef. */
6679 obstack_1grow (&util_obstack, '?');
6680
6681 obstack_1grow (&util_obstack, right);
6682 }
6683 }
6684 }
6685
6686 static void
6687 encode_aggregate (type, curtype, format)
6688 tree type;
6689 int curtype;
6690 int format;
6691 {
6692 enum tree_code code = TREE_CODE (type);
6693
6694 switch (code)
6695 {
6696 case RECORD_TYPE:
6697 {
6698 encode_aggregate_within(type, curtype, format, '{', '}');
6699 break;
6700 }
6701 case UNION_TYPE:
6702 {
6703 encode_aggregate_within(type, curtype, format, '(', ')');
6704 break;
6705 }
6706
6707 case ENUMERAL_TYPE:
6708 obstack_1grow (&util_obstack, 'i');
6709 break;
6710
6711 default:
6712 break;
6713 }
6714 }
6715
6716 /* Support bitfields. The current version of Objective-C does not support
6717 them. The string will consist of one or more "b:n"'s where n is an
6718 integer describing the width of the bitfield. Currently, classes in
6719 the kit implement a method "-(char *)describeBitfieldStruct:" that
6720 simulates this. If they do not implement this method, the archiver
6721 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6722 according to the GNU compiler. After looking at the "kit", it appears
6723 that all classes currently rely on this default behavior, rather than
6724 hand generating this string (which is tedious). */
6725
6726 static void
6727 encode_bitfield (width)
6728 int width;
6729 {
6730 char buffer[40];
6731 sprintf (buffer, "b%d", width);
6732 obstack_grow (&util_obstack, buffer, strlen (buffer));
6733 }
6734 \f
6735 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6736
6737 static void
6738 encode_type (type, curtype, format)
6739 tree type;
6740 int curtype;
6741 int format;
6742 {
6743 enum tree_code code = TREE_CODE (type);
6744
6745 if (code == INTEGER_TYPE)
6746 {
6747 if (integer_zerop (TYPE_MIN_VALUE (type)))
6748 {
6749 /* Unsigned integer types. */
6750
6751 if (TYPE_MODE (type) == QImode)
6752 obstack_1grow (&util_obstack, 'C');
6753 else if (TYPE_MODE (type) == HImode)
6754 obstack_1grow (&util_obstack, 'S');
6755 else if (TYPE_MODE (type) == SImode)
6756 {
6757 if (type == long_unsigned_type_node)
6758 obstack_1grow (&util_obstack, 'L');
6759 else
6760 obstack_1grow (&util_obstack, 'I');
6761 }
6762 else if (TYPE_MODE (type) == DImode)
6763 obstack_1grow (&util_obstack, 'Q');
6764 }
6765
6766 else
6767 /* Signed integer types. */
6768 {
6769 if (TYPE_MODE (type) == QImode)
6770 obstack_1grow (&util_obstack, 'c');
6771 else if (TYPE_MODE (type) == HImode)
6772 obstack_1grow (&util_obstack, 's');
6773 else if (TYPE_MODE (type) == SImode)
6774 {
6775 if (type == long_integer_type_node)
6776 obstack_1grow (&util_obstack, 'l');
6777 else
6778 obstack_1grow (&util_obstack, 'i');
6779 }
6780
6781 else if (TYPE_MODE (type) == DImode)
6782 obstack_1grow (&util_obstack, 'q');
6783 }
6784 }
6785
6786 else if (code == REAL_TYPE)
6787 {
6788 /* Floating point types. */
6789
6790 if (TYPE_MODE (type) == SFmode)
6791 obstack_1grow (&util_obstack, 'f');
6792 else if (TYPE_MODE (type) == DFmode
6793 || TYPE_MODE (type) == TFmode)
6794 obstack_1grow (&util_obstack, 'd');
6795 }
6796
6797 else if (code == VOID_TYPE)
6798 obstack_1grow (&util_obstack, 'v');
6799
6800 else if (code == ARRAY_TYPE)
6801 encode_array (type, curtype, format);
6802
6803 else if (code == POINTER_TYPE)
6804 encode_pointer (type, curtype, format);
6805
6806 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6807 encode_aggregate (type, curtype, format);
6808
6809 else if (code == FUNCTION_TYPE) /* '?' */
6810 obstack_1grow (&util_obstack, '?');
6811 }
6812
6813 static void
6814 encode_complete_bitfield (int position, tree type, int size)
6815 {
6816 enum tree_code code = TREE_CODE (type);
6817 char buffer[40];
6818 char charType = '?';
6819
6820 if (code == INTEGER_TYPE)
6821 {
6822 if (integer_zerop (TYPE_MIN_VALUE (type)))
6823 {
6824 /* Unsigned integer types. */
6825
6826 if (TYPE_MODE (type) == QImode)
6827 charType = 'C';
6828 else if (TYPE_MODE (type) == HImode)
6829 charType = 'S';
6830 else if (TYPE_MODE (type) == SImode)
6831 {
6832 if (type == long_unsigned_type_node)
6833 charType = 'L';
6834 else
6835 charType = 'I';
6836 }
6837 else if (TYPE_MODE (type) == DImode)
6838 charType = 'Q';
6839 }
6840
6841 else
6842 /* Signed integer types. */
6843 {
6844 if (TYPE_MODE (type) == QImode)
6845 charType = 'c';
6846 else if (TYPE_MODE (type) == HImode)
6847 charType = 's';
6848 else if (TYPE_MODE (type) == SImode)
6849 {
6850 if (type == long_integer_type_node)
6851 charType = 'l';
6852 else
6853 charType = 'i';
6854 }
6855
6856 else if (TYPE_MODE (type) == DImode)
6857 charType = 'q';
6858 }
6859 }
6860
6861 else
6862 abort ();
6863
6864 sprintf (buffer, "b%d%c%d", position, charType, size);
6865 obstack_grow (&util_obstack, buffer, strlen (buffer));
6866 }
6867
6868 static void
6869 encode_field_decl (field_decl, curtype, format)
6870 tree field_decl;
6871 int curtype;
6872 int format;
6873 {
6874 tree type;
6875
6876 type = TREE_TYPE (field_decl);
6877
6878 /* If this field is obviously a bitfield, or is a bitfield that has been
6879 clobbered to look like a ordinary integer mode, go ahead and generate
6880 the bitfield typing information. */
6881 if (flag_next_runtime)
6882 {
6883 if (DECL_BIT_FIELD (field_decl))
6884 encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6885 else
6886 encode_type (TREE_TYPE (field_decl), curtype, format);
6887 }
6888 else
6889 {
6890 if (DECL_BIT_FIELD (field_decl))
6891 encode_complete_bitfield (int_bit_position (field_decl),
6892 DECL_BIT_FIELD_TYPE (field_decl),
6893 tree_low_cst (DECL_SIZE (field_decl), 1));
6894 else
6895 encode_type (TREE_TYPE (field_decl), curtype, format);
6896 }
6897 }
6898
6899 static tree
6900 expr_last (complex_expr)
6901 tree complex_expr;
6902 {
6903 tree next;
6904
6905 if (complex_expr)
6906 while ((next = TREE_OPERAND (complex_expr, 0)))
6907 complex_expr = next;
6908
6909 return complex_expr;
6910 }
6911 \f
6912 /* The selector of the current method,
6913 or NULL if we aren't compiling a method. */
6914
6915 tree
6916 maybe_objc_method_name (decl)
6917 tree decl ATTRIBUTE_UNUSED;
6918 {
6919 if (method_context)
6920 return METHOD_SEL_NAME (method_context);
6921 else
6922 return 0;
6923 }
6924
6925 /* Transform a method definition into a function definition as follows:
6926 - synthesize the first two arguments, "self" and "_cmd". */
6927
6928 void
6929 start_method_def (method)
6930 tree method;
6931 {
6932 tree decl_specs;
6933
6934 /* Required to implement _msgSuper. */
6935 method_context = method;
6936 UOBJC_SUPER_decl = NULL_TREE;
6937
6938 /* Must be called BEFORE start_function. */
6939 pushlevel (0);
6940
6941 /* Generate prototype declarations for arguments..."new-style". */
6942
6943 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
6944 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6945 else
6946 /* Really a `struct objc_class *'. However, we allow people to
6947 assign to self, which changes its type midstream. */
6948 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6949
6950 push_parm_decl (build_tree_list
6951 (build_tree_list (decl_specs,
6952 build1 (INDIRECT_REF, NULL_TREE, self_id)),
6953 build_tree_list (unused_list, NULL_TREE)));
6954
6955 #ifdef OBJC_INT_SELECTORS
6956 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
6957 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
6958 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
6959 build_tree_list (unused_list, NULL_TREE)));
6960 #else /* not OBJC_INT_SELECTORS */
6961 decl_specs = build_tree_list (NULL_TREE,
6962 xref_tag (RECORD_TYPE,
6963 get_identifier (TAG_SELECTOR)));
6964 push_parm_decl (build_tree_list
6965 (build_tree_list (decl_specs,
6966 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6967 build_tree_list (unused_list, NULL_TREE)));
6968 #endif /* not OBJC_INT_SELECTORS */
6969
6970 /* Generate argument declarations if a keyword_decl. */
6971 if (METHOD_SEL_ARGS (method))
6972 {
6973 tree arglist = METHOD_SEL_ARGS (method);
6974 do
6975 {
6976 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6977 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6978
6979 if (arg_decl)
6980 {
6981 tree last_expr = expr_last (arg_decl);
6982
6983 /* Unite the abstract decl with its name. */
6984 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6985 push_parm_decl (build_tree_list
6986 (build_tree_list (arg_spec, arg_decl),
6987 build_tree_list (NULL_TREE, NULL_TREE)));
6988
6989 /* Unhook: restore the abstract declarator. */
6990 TREE_OPERAND (last_expr, 0) = NULL_TREE;
6991 }
6992
6993 else
6994 push_parm_decl (build_tree_list
6995 (build_tree_list (arg_spec,
6996 KEYWORD_ARG_NAME (arglist)),
6997 build_tree_list (NULL_TREE, NULL_TREE)));
6998
6999 arglist = TREE_CHAIN (arglist);
7000 }
7001 while (arglist);
7002 }
7003
7004 if (METHOD_ADD_ARGS (method) != NULL_TREE
7005 && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7006 {
7007 /* We have a variable length selector - in "prototype" format. */
7008 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7009 while (akey)
7010 {
7011 /* This must be done prior to calling pushdecl. pushdecl is
7012 going to change our chain on us. */
7013 tree nextkey = TREE_CHAIN (akey);
7014 pushdecl (akey);
7015 akey = nextkey;
7016 }
7017 }
7018 }
7019
7020 static void
7021 warn_with_method (message, mtype, method)
7022 const char *message;
7023 int mtype;
7024 tree method;
7025 {
7026 if (count_error (1) == 0)
7027 return;
7028
7029 report_error_function (DECL_SOURCE_FILE (method));
7030
7031 fprintf (stderr, "%s:%d: warning: ",
7032 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
7033 memset (errbuf, 0, BUFSIZE);
7034 fprintf (stderr, "%s `%c%s'\n",
7035 message, mtype, gen_method_decl (method, errbuf));
7036 }
7037
7038 /* Return 1 if METHOD is consistent with PROTO. */
7039
7040 static int
7041 comp_method_with_proto (method, proto)
7042 tree method, proto;
7043 {
7044 static tree function_type = 0;
7045
7046 /* Create a function_type node once. */
7047 if (!function_type)
7048 {
7049 function_type = make_node (FUNCTION_TYPE);
7050 ggc_add_tree_root (&function_type, 1);
7051 }
7052
7053 /* Install argument types - normally set by build_function_type. */
7054 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
7055
7056 /* install return type */
7057 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
7058
7059 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
7060 }
7061
7062 /* Return 1 if PROTO1 is consistent with PROTO2. */
7063
7064 static int
7065 comp_proto_with_proto (proto0, proto1)
7066 tree proto0, proto1;
7067 {
7068 static tree function_type[2];
7069
7070 /* Create a couple function_type node's once. */
7071 if (!function_type[0])
7072 {
7073 function_type[0] = make_node (FUNCTION_TYPE);
7074 function_type[1] = make_node (FUNCTION_TYPE);
7075 ggc_add_tree_root (function_type, 2);
7076 }
7077
7078 /* Install argument types; normally set by build_function_type. */
7079 TYPE_ARG_TYPES (function_type[0]) = get_arg_type_list (proto0, METHOD_REF, 0);
7080 TYPE_ARG_TYPES (function_type[1]) = get_arg_type_list (proto1, METHOD_REF, 0);
7081
7082 /* Install return type. */
7083 TREE_TYPE (function_type[0]) = groktypename (TREE_TYPE (proto0));
7084 TREE_TYPE (function_type[1]) = groktypename (TREE_TYPE (proto1));
7085
7086 return comptypes (function_type[0], function_type[1]);
7087 }
7088
7089 /* - Generate an identifier for the function. the format is "_n_cls",
7090 where 1 <= n <= nMethods, and cls is the name the implementation we
7091 are processing.
7092 - Install the return type from the method declaration.
7093 - If we have a prototype, check for type consistency. */
7094
7095 static void
7096 really_start_method (method, parmlist)
7097 tree method, parmlist;
7098 {
7099 tree sc_spec, ret_spec, ret_decl, decl_specs;
7100 tree method_decl, method_id;
7101 const char *sel_name, *class_name, *cat_name;
7102 char *buf;
7103
7104 /* Synth the storage class & assemble the return type. */
7105 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7106 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7107 decl_specs = chainon (sc_spec, ret_spec);
7108
7109 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7110 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
7111 cat_name = ((TREE_CODE (implementation_context)
7112 == CLASS_IMPLEMENTATION_TYPE)
7113 ? NULL
7114 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
7115 method_slot++;
7116
7117 /* Make sure this is big enough for any plausible method label. */
7118 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7119 + (cat_name ? strlen (cat_name) : 0));
7120
7121 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7122 class_name, cat_name, sel_name, method_slot);
7123
7124 method_id = get_identifier (buf);
7125
7126 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7127
7128 /* Check the declarator portion of the return type for the method. */
7129 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7130 {
7131 /* Unite the complex decl (specified in the abstract decl) with the
7132 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7133 tree save_expr = expr_last (ret_decl);
7134
7135 TREE_OPERAND (save_expr, 0) = method_decl;
7136 method_decl = ret_decl;
7137
7138 /* Fool the parser into thinking it is starting a function. */
7139 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE);
7140
7141 /* Unhook: this has the effect of restoring the abstract declarator. */
7142 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7143 }
7144
7145 else
7146 {
7147 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7148
7149 /* Fool the parser into thinking it is starting a function. */
7150 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE);
7151
7152 /* Unhook: this has the effect of restoring the abstract declarator. */
7153 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7154 }
7155
7156 METHOD_DEFINITION (method) = current_function_decl;
7157
7158 if (implementation_template != implementation_context)
7159 {
7160 tree proto;
7161
7162 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7163 proto = lookup_instance_method_static (implementation_template,
7164 METHOD_SEL_NAME (method));
7165 else
7166 proto = lookup_class_method_static (implementation_template,
7167 METHOD_SEL_NAME (method));
7168
7169 if (proto && ! comp_method_with_proto (method, proto))
7170 {
7171 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7172
7173 warn_with_method ("conflicting types for", type, method);
7174 warn_with_method ("previous declaration of", type, proto);
7175 }
7176 }
7177 }
7178
7179 /* The following routine is always called...this "architecture" is to
7180 accommodate "old-style" variable length selectors.
7181
7182 - a:a b:b // prototype ; id c; id d; // old-style. */
7183
7184 void
7185 continue_method_def ()
7186 {
7187 tree parmlist;
7188
7189 if (METHOD_ADD_ARGS (method_context) == objc_ellipsis_node)
7190 /* We have a `, ...' immediately following the selector. */
7191 parmlist = get_parm_info (0);
7192 else
7193 parmlist = get_parm_info (1); /* place a `void_at_end' */
7194
7195 /* Set self_decl from the first argument...this global is used by
7196 build_ivar_reference calling build_indirect_ref. */
7197 self_decl = TREE_PURPOSE (parmlist);
7198
7199 poplevel (0, 0, 0);
7200 really_start_method (method_context, parmlist);
7201 store_parm_decls ();
7202 }
7203
7204 /* Called by the parser, from the `pushlevel' production. */
7205
7206 void
7207 add_objc_decls ()
7208 {
7209 if (!UOBJC_SUPER_decl)
7210 {
7211 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7212 build_tree_list (NULL_TREE,
7213 objc_super_template),
7214 0, NULL_TREE, NULL_TREE);
7215
7216 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7217
7218 /* This prevents `unused variable' warnings when compiling with -Wall. */
7219 TREE_USED (UOBJC_SUPER_decl) = 1;
7220 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7221 }
7222 }
7223
7224 /* _n_Method (id self, SEL sel, ...)
7225 {
7226 struct objc_super _S;
7227 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7228 } */
7229
7230 tree
7231 get_super_receiver ()
7232 {
7233 if (method_context)
7234 {
7235 tree super_expr, super_expr_list;
7236
7237 /* Set receiver to self. */
7238 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7239 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7240 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7241
7242 /* Set class to begin searching. */
7243 super_expr = build_component_ref (UOBJC_SUPER_decl,
7244 get_identifier ("class"));
7245
7246 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7247 {
7248 /* [_cls, __cls]Super are "pre-built" in
7249 synth_forward_declarations. */
7250
7251 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7252 ((TREE_CODE (method_context)
7253 == INSTANCE_METHOD_DECL)
7254 ? ucls_super_ref
7255 : uucls_super_ref));
7256 }
7257
7258 else
7259 /* We have a category. */
7260 {
7261 tree super_name = CLASS_SUPER_NAME (implementation_template);
7262 tree super_class;
7263
7264 if (!super_name)
7265 {
7266 error ("no super class declared in interface for `%s'",
7267 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7268 return error_mark_node;
7269 }
7270
7271 if (flag_next_runtime)
7272 {
7273 super_class = get_class_reference (super_name);
7274 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7275 super_class
7276 = build_component_ref (build_indirect_ref (super_class, "->"),
7277 get_identifier ("isa"));
7278 }
7279 else
7280 {
7281 add_class_reference (super_name);
7282 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7283 ? objc_get_class_decl : objc_get_meta_class_decl);
7284 assemble_external (super_class);
7285 super_class
7286 = build_function_call
7287 (super_class,
7288 build_tree_list
7289 (NULL_TREE,
7290 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7291 IDENTIFIER_POINTER (super_name))));
7292 }
7293
7294 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7295 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7296 }
7297
7298 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7299
7300 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7301 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7302
7303 return build_compound_expr (super_expr_list);
7304 }
7305 else
7306 {
7307 error ("[super ...] must appear in a method context");
7308 return error_mark_node;
7309 }
7310 }
7311
7312 static tree
7313 encode_method_def (func_decl)
7314 tree func_decl;
7315 {
7316 tree parms;
7317 int stack_size;
7318 HOST_WIDE_INT max_parm_end = 0;
7319 char buffer[40];
7320 tree result;
7321
7322 /* Return type. */
7323 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7324 obstack_object_size (&util_obstack),
7325 OBJC_ENCODE_INLINE_DEFS);
7326
7327 /* Stack size. */
7328 for (parms = DECL_ARGUMENTS (func_decl); parms;
7329 parms = TREE_CHAIN (parms))
7330 {
7331 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7332 + int_size_in_bytes (TREE_TYPE (parms)));
7333
7334 if (! offset_is_register && parm_end > max_parm_end)
7335 max_parm_end = parm_end;
7336 }
7337
7338 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7339
7340 sprintf (buffer, "%d", stack_size);
7341 obstack_grow (&util_obstack, buffer, strlen (buffer));
7342
7343 /* Argument types. */
7344 for (parms = DECL_ARGUMENTS (func_decl); parms;
7345 parms = TREE_CHAIN (parms))
7346 {
7347 /* Type. */
7348 encode_type (TREE_TYPE (parms),
7349 obstack_object_size (&util_obstack),
7350 OBJC_ENCODE_INLINE_DEFS);
7351
7352 /* Compute offset. */
7353 sprintf (buffer, "%d", forwarding_offset (parms));
7354
7355 /* Indicate register. */
7356 if (offset_is_register)
7357 obstack_1grow (&util_obstack, '+');
7358
7359 obstack_grow (&util_obstack, buffer, strlen (buffer));
7360 }
7361
7362 obstack_1grow (&util_obstack, 0);
7363 result = get_identifier (obstack_finish (&util_obstack));
7364 obstack_free (&util_obstack, util_firstobj);
7365 return result;
7366 }
7367
7368 static void
7369 objc_expand_function_end ()
7370 {
7371 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7372 }
7373
7374 void
7375 finish_method_def ()
7376 {
7377 lang_expand_function_end = objc_expand_function_end;
7378 finish_function (0);
7379 lang_expand_function_end = NULL;
7380
7381 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7382 since the optimizer may find "may be used before set" errors. */
7383 method_context = NULL_TREE;
7384 }
7385
7386 #if 0
7387 int
7388 lang_report_error_function (decl)
7389 tree decl;
7390 {
7391 if (method_context)
7392 {
7393 fprintf (stderr, "In method `%s'\n",
7394 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7395 return 1;
7396 }
7397
7398 else
7399 return 0;
7400 }
7401 #endif
7402
7403 static int
7404 is_complex_decl (type)
7405 tree type;
7406 {
7407 return (TREE_CODE (type) == ARRAY_TYPE
7408 || TREE_CODE (type) == FUNCTION_TYPE
7409 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7410 }
7411
7412 \f
7413 /* Code to convert a decl node into text for a declaration in C. */
7414
7415 static char tmpbuf[256];
7416
7417 static void
7418 adorn_decl (decl, str)
7419 tree decl;
7420 char *str;
7421 {
7422 enum tree_code code = TREE_CODE (decl);
7423
7424 if (code == ARRAY_REF)
7425 {
7426 tree an_int_cst = TREE_OPERAND (decl, 1);
7427
7428 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7429 sprintf (str + strlen (str), "[%ld]",
7430 (long) TREE_INT_CST_LOW (an_int_cst));
7431 else
7432 strcat (str, "[]");
7433 }
7434
7435 else if (code == ARRAY_TYPE)
7436 {
7437 tree an_int_cst = TYPE_SIZE (decl);
7438 tree array_of = TREE_TYPE (decl);
7439
7440 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7441 sprintf (str + strlen (str), "[%ld]",
7442 (long) (TREE_INT_CST_LOW (an_int_cst)
7443 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7444 else
7445 strcat (str, "[]");
7446 }
7447
7448 else if (code == CALL_EXPR)
7449 {
7450 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7451
7452 strcat (str, "(");
7453 while (chain)
7454 {
7455 gen_declaration (chain, str);
7456 chain = TREE_CHAIN (chain);
7457 if (chain)
7458 strcat (str, ", ");
7459 }
7460 strcat (str, ")");
7461 }
7462
7463 else if (code == FUNCTION_TYPE)
7464 {
7465 tree chain = TYPE_ARG_TYPES (decl);
7466
7467 strcat (str, "(");
7468 while (chain && TREE_VALUE (chain) != void_type_node)
7469 {
7470 gen_declaration (TREE_VALUE (chain), str);
7471 chain = TREE_CHAIN (chain);
7472 if (chain && TREE_VALUE (chain) != void_type_node)
7473 strcat (str, ", ");
7474 }
7475 strcat (str, ")");
7476 }
7477
7478 else if (code == INDIRECT_REF)
7479 {
7480 strcpy (tmpbuf, "*");
7481 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7482 {
7483 tree chain;
7484
7485 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7486 chain;
7487 chain = TREE_CHAIN (chain))
7488 {
7489 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7490 {
7491 strcat (tmpbuf, " ");
7492 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7493 }
7494 }
7495 if (str[0])
7496 strcat (tmpbuf, " ");
7497 }
7498 strcat (tmpbuf, str);
7499 strcpy (str, tmpbuf);
7500 }
7501
7502 else if (code == POINTER_TYPE)
7503 {
7504 strcpy (tmpbuf, "*");
7505 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7506 {
7507 if (TREE_READONLY (decl))
7508 strcat (tmpbuf, " const");
7509 if (TYPE_VOLATILE (decl))
7510 strcat (tmpbuf, " volatile");
7511 if (str[0])
7512 strcat (tmpbuf, " ");
7513 }
7514 strcat (tmpbuf, str);
7515 strcpy (str, tmpbuf);
7516 }
7517 }
7518
7519 static char *
7520 gen_declarator (decl, buf, name)
7521 tree decl;
7522 char *buf;
7523 const char *name;
7524 {
7525 if (decl)
7526 {
7527 enum tree_code code = TREE_CODE (decl);
7528 char *str;
7529 tree op;
7530 int wrap = 0;
7531
7532 switch (code)
7533 {
7534 case ARRAY_REF:
7535 case INDIRECT_REF:
7536 case CALL_EXPR:
7537 op = TREE_OPERAND (decl, 0);
7538
7539 /* We have a pointer to a function or array...(*)(), (*)[] */
7540 if ((code == ARRAY_REF || code == CALL_EXPR)
7541 && op && TREE_CODE (op) == INDIRECT_REF)
7542 wrap = 1;
7543
7544 str = gen_declarator (op, buf, name);
7545
7546 if (wrap)
7547 {
7548 strcpy (tmpbuf, "(");
7549 strcat (tmpbuf, str);
7550 strcat (tmpbuf, ")");
7551 strcpy (str, tmpbuf);
7552 }
7553
7554 adorn_decl (decl, str);
7555 break;
7556
7557 case ARRAY_TYPE:
7558 case FUNCTION_TYPE:
7559 case POINTER_TYPE:
7560 strcpy (buf, name);
7561 str = buf;
7562
7563 /* This clause is done iteratively rather than recursively. */
7564 do
7565 {
7566 op = (is_complex_decl (TREE_TYPE (decl))
7567 ? TREE_TYPE (decl) : NULL_TREE);
7568
7569 adorn_decl (decl, str);
7570
7571 /* We have a pointer to a function or array...(*)(), (*)[] */
7572 if (code == POINTER_TYPE
7573 && op && (TREE_CODE (op) == FUNCTION_TYPE
7574 || TREE_CODE (op) == ARRAY_TYPE))
7575 {
7576 strcpy (tmpbuf, "(");
7577 strcat (tmpbuf, str);
7578 strcat (tmpbuf, ")");
7579 strcpy (str, tmpbuf);
7580 }
7581
7582 decl = (is_complex_decl (TREE_TYPE (decl))
7583 ? TREE_TYPE (decl) : NULL_TREE);
7584 }
7585
7586 while (decl && (code = TREE_CODE (decl)))
7587 ;
7588
7589 break;
7590
7591 case IDENTIFIER_NODE:
7592 /* Will only happen if we are processing a "raw" expr-decl. */
7593 strcpy (buf, IDENTIFIER_POINTER (decl));
7594 return buf;
7595
7596 default:
7597 abort ();
7598 }
7599
7600 return str;
7601 }
7602
7603 else
7604 /* We have an abstract declarator or a _DECL node. */
7605 {
7606 strcpy (buf, name);
7607 return buf;
7608 }
7609 }
7610
7611 static void
7612 gen_declspecs (declspecs, buf, raw)
7613 tree declspecs;
7614 char *buf;
7615 int raw;
7616 {
7617 if (raw)
7618 {
7619 tree chain;
7620
7621 for (chain = nreverse (copy_list (declspecs));
7622 chain; chain = TREE_CHAIN (chain))
7623 {
7624 tree aspec = TREE_VALUE (chain);
7625
7626 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7627 strcat (buf, IDENTIFIER_POINTER (aspec));
7628 else if (TREE_CODE (aspec) == RECORD_TYPE)
7629 {
7630 if (TYPE_NAME (aspec))
7631 {
7632 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7633
7634 if (! TREE_STATIC_TEMPLATE (aspec))
7635 strcat (buf, "struct ");
7636 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7637
7638 /* NEW!!! */
7639 if (protocol_list)
7640 {
7641 tree chain = protocol_list;
7642
7643 strcat (buf, " <");
7644 while (chain)
7645 {
7646 strcat (buf,
7647 IDENTIFIER_POINTER
7648 (PROTOCOL_NAME (TREE_VALUE (chain))));
7649 chain = TREE_CHAIN (chain);
7650 if (chain)
7651 strcat (buf, ", ");
7652 }
7653 strcat (buf, ">");
7654 }
7655 }
7656
7657 else
7658 strcat (buf, "untagged struct");
7659 }
7660
7661 else if (TREE_CODE (aspec) == UNION_TYPE)
7662 {
7663 if (TYPE_NAME (aspec))
7664 {
7665 if (! TREE_STATIC_TEMPLATE (aspec))
7666 strcat (buf, "union ");
7667 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7668 }
7669 else
7670 strcat (buf, "untagged union");
7671 }
7672
7673 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7674 {
7675 if (TYPE_NAME (aspec))
7676 {
7677 if (! TREE_STATIC_TEMPLATE (aspec))
7678 strcat (buf, "enum ");
7679 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7680 }
7681 else
7682 strcat (buf, "untagged enum");
7683 }
7684
7685 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7686 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7687
7688 else if (IS_ID (aspec))
7689 {
7690 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7691
7692 strcat (buf, "id");
7693 if (protocol_list)
7694 {
7695 tree chain = protocol_list;
7696
7697 strcat (buf, " <");
7698 while (chain)
7699 {
7700 strcat (buf,
7701 IDENTIFIER_POINTER
7702 (PROTOCOL_NAME (TREE_VALUE (chain))));
7703 chain = TREE_CHAIN (chain);
7704 if (chain)
7705 strcat (buf, ", ");
7706 }
7707 strcat (buf, ">");
7708 }
7709 }
7710 if (TREE_CHAIN (chain))
7711 strcat (buf, " ");
7712 }
7713 }
7714 else
7715 {
7716 /* Type qualifiers. */
7717 if (TREE_READONLY (declspecs))
7718 strcat (buf, "const ");
7719 if (TYPE_VOLATILE (declspecs))
7720 strcat (buf, "volatile ");
7721
7722 switch (TREE_CODE (declspecs))
7723 {
7724 /* Type specifiers. */
7725
7726 case INTEGER_TYPE:
7727 declspecs = TYPE_MAIN_VARIANT (declspecs);
7728
7729 /* Signed integer types. */
7730
7731 if (declspecs == short_integer_type_node)
7732 strcat (buf, "short int ");
7733 else if (declspecs == integer_type_node)
7734 strcat (buf, "int ");
7735 else if (declspecs == long_integer_type_node)
7736 strcat (buf, "long int ");
7737 else if (declspecs == long_long_integer_type_node)
7738 strcat (buf, "long long int ");
7739 else if (declspecs == signed_char_type_node
7740 || declspecs == char_type_node)
7741 strcat (buf, "char ");
7742
7743 /* Unsigned integer types. */
7744
7745 else if (declspecs == short_unsigned_type_node)
7746 strcat (buf, "unsigned short ");
7747 else if (declspecs == unsigned_type_node)
7748 strcat (buf, "unsigned int ");
7749 else if (declspecs == long_unsigned_type_node)
7750 strcat (buf, "unsigned long ");
7751 else if (declspecs == long_long_unsigned_type_node)
7752 strcat (buf, "unsigned long long ");
7753 else if (declspecs == unsigned_char_type_node)
7754 strcat (buf, "unsigned char ");
7755 break;
7756
7757 case REAL_TYPE:
7758 declspecs = TYPE_MAIN_VARIANT (declspecs);
7759
7760 if (declspecs == float_type_node)
7761 strcat (buf, "float ");
7762 else if (declspecs == double_type_node)
7763 strcat (buf, "double ");
7764 else if (declspecs == long_double_type_node)
7765 strcat (buf, "long double ");
7766 break;
7767
7768 case RECORD_TYPE:
7769 if (TYPE_NAME (declspecs)
7770 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7771 {
7772 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7773
7774 if (! TREE_STATIC_TEMPLATE (declspecs))
7775 strcat (buf, "struct ");
7776 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7777
7778 if (protocol_list)
7779 {
7780 tree chain = protocol_list;
7781
7782 strcat (buf, " <");
7783 while (chain)
7784 {
7785 strcat (buf,
7786 IDENTIFIER_POINTER
7787 (PROTOCOL_NAME (TREE_VALUE (chain))));
7788 chain = TREE_CHAIN (chain);
7789 if (chain)
7790 strcat (buf, ", ");
7791 }
7792 strcat (buf, ">");
7793 }
7794 }
7795
7796 else
7797 strcat (buf, "untagged struct");
7798
7799 strcat (buf, " ");
7800 break;
7801
7802 case UNION_TYPE:
7803 if (TYPE_NAME (declspecs)
7804 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7805 {
7806 strcat (buf, "union ");
7807 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7808 strcat (buf, " ");
7809 }
7810
7811 else
7812 strcat (buf, "untagged union ");
7813 break;
7814
7815 case ENUMERAL_TYPE:
7816 if (TYPE_NAME (declspecs)
7817 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7818 {
7819 strcat (buf, "enum ");
7820 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7821 strcat (buf, " ");
7822 }
7823
7824 else
7825 strcat (buf, "untagged enum ");
7826 break;
7827
7828 case VOID_TYPE:
7829 strcat (buf, "void ");
7830 break;
7831
7832 case POINTER_TYPE:
7833 {
7834 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7835
7836 strcat (buf, "id");
7837 if (protocol_list)
7838 {
7839 tree chain = protocol_list;
7840
7841 strcat (buf, " <");
7842 while (chain)
7843 {
7844 strcat (buf,
7845 IDENTIFIER_POINTER
7846 (PROTOCOL_NAME (TREE_VALUE (chain))));
7847 chain = TREE_CHAIN (chain);
7848 if (chain)
7849 strcat (buf, ", ");
7850 }
7851
7852 strcat (buf, ">");
7853 }
7854 }
7855 break;
7856
7857 default:
7858 break;
7859 }
7860 }
7861 }
7862
7863 static char *
7864 gen_declaration (atype_or_adecl, buf)
7865 tree atype_or_adecl;
7866 char *buf;
7867 {
7868 char declbuf[256];
7869
7870 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7871 {
7872 tree declspecs; /* "identifier_node", "record_type" */
7873 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7874
7875 /* We have a "raw", abstract declarator (typename). */
7876 declarator = TREE_VALUE (atype_or_adecl);
7877 declspecs = TREE_PURPOSE (atype_or_adecl);
7878
7879 gen_declspecs (declspecs, buf, 1);
7880 if (declarator)
7881 {
7882 strcat (buf, " ");
7883 strcat (buf, gen_declarator (declarator, declbuf, ""));
7884 }
7885 }
7886
7887 else
7888 {
7889 tree atype;
7890 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7891 tree declarator; /* "array_type", "function_type", "pointer_type". */
7892
7893 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7894 || TREE_CODE (atype_or_adecl) == PARM_DECL
7895 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7896 atype = TREE_TYPE (atype_or_adecl);
7897 else
7898 /* Assume we have a *_type node. */
7899 atype = atype_or_adecl;
7900
7901 if (is_complex_decl (atype))
7902 {
7903 tree chain;
7904
7905 /* Get the declaration specifier; it is at the end of the list. */
7906 declarator = chain = atype;
7907 do
7908 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7909 while (is_complex_decl (chain));
7910 declspecs = chain;
7911 }
7912
7913 else
7914 {
7915 declspecs = atype;
7916 declarator = NULL_TREE;
7917 }
7918
7919 gen_declspecs (declspecs, buf, 0);
7920
7921 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7922 || TREE_CODE (atype_or_adecl) == PARM_DECL
7923 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7924 {
7925 const char *decl_name =
7926 (DECL_NAME (atype_or_adecl)
7927 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
7928
7929 if (declarator)
7930 {
7931 strcat (buf, " ");
7932 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7933 }
7934
7935 else if (decl_name[0])
7936 {
7937 strcat (buf, " ");
7938 strcat (buf, decl_name);
7939 }
7940 }
7941 else if (declarator)
7942 {
7943 strcat (buf, " ");
7944 strcat (buf, gen_declarator (declarator, declbuf, ""));
7945 }
7946 }
7947
7948 return buf;
7949 }
7950
7951 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7952
7953 static char *
7954 gen_method_decl (method, buf)
7955 tree method;
7956 char *buf;
7957 {
7958 tree chain;
7959
7960 if (RAW_TYPESPEC (method) != objc_object_reference)
7961 {
7962 strcpy (buf, "(");
7963 gen_declaration (TREE_TYPE (method), buf);
7964 strcat (buf, ")");
7965 }
7966
7967 chain = METHOD_SEL_ARGS (method);
7968 if (chain)
7969 {
7970 /* We have a chain of keyword_decls. */
7971 do
7972 {
7973 if (KEYWORD_KEY_NAME (chain))
7974 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7975
7976 strcat (buf, ":");
7977 if (RAW_TYPESPEC (chain) != objc_object_reference)
7978 {
7979 strcat (buf, "(");
7980 gen_declaration (TREE_TYPE (chain), buf);
7981 strcat (buf, ")");
7982 }
7983
7984 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7985 if ((chain = TREE_CHAIN (chain)))
7986 strcat (buf, " ");
7987 }
7988 while (chain);
7989
7990 if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
7991 strcat (buf, ", ...");
7992 else if (METHOD_ADD_ARGS (method))
7993 {
7994 /* We have a tree list node as generate by get_parm_info. */
7995 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7996
7997 /* Know we have a chain of parm_decls. */
7998 while (chain)
7999 {
8000 strcat (buf, ", ");
8001 gen_declaration (chain, buf);
8002 chain = TREE_CHAIN (chain);
8003 }
8004 }
8005 }
8006
8007 else
8008 /* We have a unary selector. */
8009 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8010
8011 return buf;
8012 }
8013 \f
8014 /* Debug info. */
8015
8016 static void
8017 dump_interface (fp, chain)
8018 FILE *fp;
8019 tree chain;
8020 {
8021 char *buf = (char *)xmalloc (256);
8022 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8023 tree ivar_decls = CLASS_RAW_IVARS (chain);
8024 tree nst_methods = CLASS_NST_METHODS (chain);
8025 tree cls_methods = CLASS_CLS_METHODS (chain);
8026
8027 fprintf (fp, "\n@interface %s", my_name);
8028
8029 if (CLASS_SUPER_NAME (chain))
8030 {
8031 const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8032 fprintf (fp, " : %s\n", super_name);
8033 }
8034 else
8035 fprintf (fp, "\n");
8036
8037 if (ivar_decls)
8038 {
8039 fprintf (fp, "{\n");
8040 do
8041 {
8042 memset (buf, 0, 256);
8043 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8044 ivar_decls = TREE_CHAIN (ivar_decls);
8045 }
8046 while (ivar_decls);
8047 fprintf (fp, "}\n");
8048 }
8049
8050 while (nst_methods)
8051 {
8052 memset (buf, 0, 256);
8053 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8054 nst_methods = TREE_CHAIN (nst_methods);
8055 }
8056
8057 while (cls_methods)
8058 {
8059 memset (buf, 0, 256);
8060 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8061 cls_methods = TREE_CHAIN (cls_methods);
8062 }
8063 fprintf (fp, "\n@end");
8064 }
8065
8066 /* Demangle function for Objective-C */
8067 static const char *
8068 objc_demangle (mangled)
8069 const char *mangled;
8070 {
8071 char *demangled, *cp;
8072
8073 if (mangled[0] == '_' &&
8074 (mangled[1] == 'i' || mangled[1] == 'c') &&
8075 mangled[2] == '_')
8076 {
8077 cp = demangled = xmalloc(strlen(mangled) + 2);
8078 if (mangled[1] == 'i')
8079 *cp++ = '-'; /* for instance method */
8080 else
8081 *cp++ = '+'; /* for class method */
8082 *cp++ = '['; /* opening left brace */
8083 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8084 while (*cp && *cp == '_')
8085 cp++; /* skip any initial underbars in class name */
8086 cp = strchr(cp, '_'); /* find first non-initial underbar */
8087 if (cp == NULL)
8088 {
8089 free(demangled); /* not mangled name */
8090 return mangled;
8091 }
8092 if (cp[1] == '_') /* easy case: no category name */
8093 {
8094 *cp++ = ' '; /* replace two '_' with one ' ' */
8095 strcpy(cp, mangled + (cp - demangled) + 2);
8096 }
8097 else
8098 {
8099 *cp++ = '('; /* less easy case: category name */
8100 cp = strchr(cp, '_');
8101 if (cp == 0)
8102 {
8103 free(demangled); /* not mangled name */
8104 return mangled;
8105 }
8106 *cp++ = ')';
8107 *cp++ = ' '; /* overwriting 1st char of method name... */
8108 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8109 }
8110 while (*cp && *cp == '_')
8111 cp++; /* skip any initial underbars in method name */
8112 for (; *cp; cp++)
8113 if (*cp == '_')
8114 *cp = ':'; /* replace remaining '_' with ':' */
8115 *cp++ = ']'; /* closing right brace */
8116 *cp++ = 0; /* string terminator */
8117 return demangled;
8118 }
8119 else
8120 return mangled; /* not an objc mangled name */
8121 }
8122
8123 static const char *
8124 objc_printable_name (decl, kind)
8125 tree decl;
8126 int kind ATTRIBUTE_UNUSED;
8127 {
8128 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8129 }
8130
8131 static void
8132 init_objc ()
8133 {
8134 /* Add the special tree codes of Objective C to the tables. */
8135
8136 #define LAST_CODE LAST_C_TREE_CODE
8137
8138 gcc_obstack_init (&util_obstack);
8139 util_firstobj = (char *) obstack_finish (&util_obstack);
8140
8141 memcpy (tree_code_type + (int) LAST_CODE,
8142 objc_tree_code_type,
8143 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
8144 memcpy (tree_code_length + (int) LAST_CODE,
8145 objc_tree_code_length,
8146 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (int)));
8147 memcpy (tree_code_name + (int) LAST_CODE,
8148 objc_tree_code_name,
8149 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (char *)));
8150
8151 errbuf = (char *)xmalloc (BUFSIZE);
8152 hash_init ();
8153 synth_module_prologue ();
8154
8155 /* Change the default error function */
8156 decl_printable_name = objc_printable_name;
8157 lang_expand_expr = c_expand_expr;
8158 lang_expand_decl_stmt = c_expand_decl_stmt;
8159 }
8160 \f
8161 static void
8162 finish_objc ()
8163 {
8164 struct imp_entry *impent;
8165 tree chain;
8166 /* The internally generated initializers appear to have missing braces.
8167 Don't warn about this. */
8168 int save_warn_missing_braces = warn_missing_braces;
8169 warn_missing_braces = 0;
8170
8171 generate_forward_declaration_to_string_table ();
8172
8173 #ifdef OBJC_PROLOGUE
8174 OBJC_PROLOGUE;
8175 #endif
8176
8177 /* Process the static instances here because initialization of objc_symtab
8178 depends on them. */
8179 if (objc_static_instances)
8180 generate_static_references ();
8181
8182 if (implementation_context || class_names_chain
8183 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8184 generate_objc_symtab_decl ();
8185
8186 for (impent = imp_list; impent; impent = impent->next)
8187 {
8188 implementation_context = impent->imp_context;
8189 implementation_template = impent->imp_template;
8190
8191 UOBJC_CLASS_decl = impent->class_decl;
8192 UOBJC_METACLASS_decl = impent->meta_decl;
8193
8194 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8195 {
8196 /* all of the following reference the string pool... */
8197 generate_ivar_lists ();
8198 generate_dispatch_tables ();
8199 generate_shared_structures ();
8200 }
8201 else
8202 {
8203 generate_dispatch_tables ();
8204 generate_category (implementation_context);
8205 }
8206 }
8207
8208 /* If we are using an array of selectors, we must always
8209 finish up the array decl even if no selectors were used. */
8210 if (! flag_next_runtime || sel_ref_chain)
8211 build_selector_translation_table ();
8212
8213 if (protocol_chain)
8214 generate_protocols ();
8215
8216 if (implementation_context || class_names_chain || objc_static_instances
8217 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8218 {
8219 /* Arrange for Objc data structures to be initialized at run time. */
8220 const char *init_name = build_module_descriptor ();
8221 if (init_name)
8222 assemble_constructor (init_name);
8223 }
8224
8225 /* Dump the class references. This forces the appropriate classes
8226 to be linked into the executable image, preserving unix archive
8227 semantics. This can be removed when we move to a more dynamically
8228 linked environment. */
8229
8230 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8231 {
8232 handle_class_ref (chain);
8233 if (TREE_PURPOSE (chain))
8234 generate_classref_translation_entry (chain);
8235 }
8236
8237 for (impent = imp_list; impent; impent = impent->next)
8238 handle_impent (impent);
8239
8240 /* Dump the string table last. */
8241
8242 generate_strings ();
8243
8244 if (flag_gen_declaration)
8245 {
8246 add_class (implementation_context);
8247 dump_interface (gen_declaration_file, implementation_context);
8248 }
8249
8250 if (warn_selector)
8251 {
8252 int slot;
8253 hash hsh;
8254
8255 /* Run through the selector hash tables and print a warning for any
8256 selector which has multiple methods. */
8257
8258 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8259 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8260 if (hsh->list)
8261 {
8262 tree meth = hsh->key;
8263 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8264 ? '-' : '+');
8265 attr loop;
8266
8267 warning ("potential selector conflict for method `%s'",
8268 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8269 warn_with_method ("found", type, meth);
8270 for (loop = hsh->list; loop; loop = loop->next)
8271 warn_with_method ("found", type, loop->value);
8272 }
8273
8274 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8275 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8276 if (hsh->list)
8277 {
8278 tree meth = hsh->key;
8279 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8280 ? '-' : '+');
8281 attr loop;
8282
8283 warning ("potential selector conflict for method `%s'",
8284 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8285 warn_with_method ("found", type, meth);
8286 for (loop = hsh->list; loop; loop = loop->next)
8287 warn_with_method ("found", type, loop->value);
8288 }
8289 }
8290
8291 warn_missing_braces = save_warn_missing_braces;
8292 }
8293 \f
8294 /* Subroutines of finish_objc. */
8295
8296 static void
8297 generate_classref_translation_entry (chain)
8298 tree chain;
8299 {
8300 tree expr, name, decl_specs, decl, sc_spec;
8301 tree type;
8302
8303 type = TREE_TYPE (TREE_PURPOSE (chain));
8304
8305 expr = add_objc_string (TREE_VALUE (chain), class_names);
8306 expr = build_c_cast (type, expr); /* cast! */
8307
8308 name = DECL_NAME (TREE_PURPOSE (chain));
8309
8310 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8311
8312 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8313 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8314
8315 /* The decl that is returned from start_decl is the one that we
8316 forward declared in build_class_reference. */
8317 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8318 finish_decl (decl, expr, NULL_TREE);
8319 return;
8320 }
8321
8322 static void
8323 handle_class_ref (chain)
8324 tree chain;
8325 {
8326 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8327 if (! flag_next_runtime)
8328 {
8329 tree decl;
8330 char *string = (char *) alloca (strlen (name) + 30);
8331 tree exp;
8332
8333 sprintf (string, "%sobjc_class_name_%s",
8334 (flag_next_runtime ? "." : "__"), name);
8335
8336 /* Make a decl for this name, so we can use its address in a tree. */
8337 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8338 DECL_EXTERNAL (decl) = 1;
8339 TREE_PUBLIC (decl) = 1;
8340
8341 pushdecl (decl);
8342 rest_of_decl_compilation (decl, 0, 0, 0);
8343
8344 /* Make following constant read-only (why not)? */
8345 readonly_data_section ();
8346
8347 exp = build1 (ADDR_EXPR, string_type_node, decl);
8348
8349 /* Align the section properly. */
8350 assemble_constant_align (exp);
8351
8352 /* Inform the assembler about this new external thing. */
8353 assemble_external (decl);
8354
8355 /* Output a constant to reference this address. */
8356 output_constant (exp, int_size_in_bytes (string_type_node));
8357 }
8358 else
8359 {
8360 /* This overreliance on our assembler (i.e. lack of portability)
8361 should be dealt with at some point. The GNU strategy (above)
8362 won't work either, but it is a start. */
8363 char *string = (char *) alloca (strlen (name) + 30);
8364 sprintf (string, ".reference .objc_class_name_%s", name);
8365 assemble_asm (my_build_string (strlen (string) + 1, string));
8366 }
8367 }
8368
8369 static void
8370 handle_impent (impent)
8371 struct imp_entry *impent;
8372 {
8373 implementation_context = impent->imp_context;
8374 implementation_template = impent->imp_template;
8375
8376 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8377 {
8378 const char *class_name =
8379 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8380 char *string = (char *) alloca (strlen (class_name) + 30);
8381
8382 if (flag_next_runtime)
8383 {
8384 /* Grossly unportable.
8385 People should know better than to assume
8386 such things about assembler syntax! */
8387 sprintf (string, ".objc_class_name_%s=0", class_name);
8388 assemble_asm (my_build_string (strlen (string) + 1, string));
8389
8390 sprintf (string, ".globl .objc_class_name_%s", class_name);
8391 assemble_asm (my_build_string (strlen (string) + 1, string));
8392 }
8393
8394 else
8395 {
8396 sprintf (string, "%sobjc_class_name_%s",
8397 (flag_next_runtime ? "." : "__"), class_name);
8398 assemble_global (string);
8399 assemble_label (string);
8400 }
8401 }
8402
8403 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8404 {
8405 const char *class_name =
8406 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8407 const char *class_super_name =
8408 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8409 char *string = (char *) alloca (strlen (class_name)
8410 + strlen (class_super_name) + 30);
8411
8412 /* Do the same for categories. Even though no references to these
8413 symbols are generated automatically by the compiler, it gives
8414 you a handle to pull them into an archive by hand. */
8415 if (flag_next_runtime)
8416 {
8417 /* Grossly unportable. */
8418 sprintf (string, ".objc_category_name_%s_%s=0",
8419 class_name, class_super_name);
8420 assemble_asm (my_build_string (strlen (string) + 1, string));
8421
8422 sprintf (string, ".globl .objc_category_name_%s_%s",
8423 class_name, class_super_name);
8424 assemble_asm (my_build_string (strlen (string) + 1, string));
8425 }
8426
8427 else
8428 {
8429 sprintf (string, "%sobjc_category_name_%s_%s",
8430 (flag_next_runtime ? "." : "__"),
8431 class_name, class_super_name);
8432 assemble_global (string);
8433 assemble_label (string);
8434 }
8435 }
8436 }
8437 \f
8438 #ifdef DEBUG
8439
8440 static void
8441 objc_debug (fp)
8442 FILE *fp;
8443 {
8444 char *buf = (char *)xmalloc (256);
8445
8446 { /* dump function prototypes */
8447 tree loop = UOBJC_MODULES_decl;
8448
8449 fprintf (fp, "\n\nfunction prototypes:\n");
8450 while (loop)
8451 {
8452 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8453 {
8454 /* We have a function definition: generate prototype. */
8455 memset (errbuf, 0, BUFSIZE);
8456 gen_declaration (loop, errbuf);
8457 fprintf (fp, "%s;\n", errbuf);
8458 }
8459 loop = TREE_CHAIN (loop);
8460 }
8461 }
8462 {
8463 /* Dump global chains. */
8464 tree loop;
8465 int i, index = 0, offset = 0;
8466 hash hashlist;
8467
8468 for (i = 0; i < SIZEHASHTABLE; i++)
8469 {
8470 if (hashlist = nst_method_hash_list[i])
8471 {
8472 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8473 do
8474 {
8475 memset (buf, 0, 256);
8476 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8477 hashlist = hashlist->next;
8478 }
8479 while (hashlist);
8480 }
8481 }
8482
8483 for (i = 0; i < SIZEHASHTABLE; i++)
8484 {
8485 if (hashlist = cls_method_hash_list[i])
8486 {
8487 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8488 do
8489 {
8490 memset (buf, 0, 256);
8491 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8492 hashlist = hashlist->next;
8493 }
8494 while (hashlist);
8495 }
8496 }
8497
8498 fprintf (fp, "\nsel_refdef_chain:\n");
8499 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8500 {
8501 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8502 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8503 index++;
8504 /* add one for the '\0' character */
8505 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8506 }
8507
8508 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8509 }
8510 }
8511 #endif
8512
8513 void
8514 print_lang_statistics ()
8515 {
8516 }
8517
8518 static void
8519 ggc_mark_imp_list (arg)
8520 void *arg;
8521 {
8522 struct imp_entry *impent;
8523
8524 for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
8525 {
8526 ggc_mark_tree (impent->imp_context);
8527 ggc_mark_tree (impent->imp_template);
8528 ggc_mark_tree (impent->class_decl);
8529 ggc_mark_tree (impent->meta_decl);
8530 }
8531 }
8532
8533 static void
8534 ggc_mark_hash_table (arg)
8535 void *arg;
8536 {
8537 hash *hash_table = *(hash **)arg;
8538 hash hst;
8539 attr list;
8540 int i;
8541
8542 if (hash_table == NULL)
8543 return;
8544 for (i = 0; i < SIZEHASHTABLE; i++)
8545 for (hst = hash_table [i]; hst; hst = hst->next)
8546 {
8547 ggc_mark_tree (hst->key);
8548 for (list = hst->list; list; list = list->next)
8549 ggc_mark_tree (list->value);
8550 }
8551 }
8552
8553 /* Add GC roots for variables local to this file. */
8554 static void
8555 objc_act_parse_init ()
8556 {
8557 ggc_add_tree_root (&objc_ellipsis_node, 1);
8558 ggc_add_tree_root (objc_global_trees, OCTI_MAX);
8559 ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list);
8560 ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table);
8561 ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table);
8562 }
8563
8564 /* Look up ID as an instance variable. */
8565 tree
8566 lookup_objc_ivar (id)
8567 tree id;
8568 {
8569 tree decl;
8570
8571 if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8572 /* we have a message to super */
8573 return get_super_receiver ();
8574 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8575 {
8576 if (is_private (decl))
8577 return error_mark_node;
8578 else
8579 return build_ivar_reference (id);
8580 }
8581 else
8582 return 0;
8583 }
8584
8585 /* Parser callbacks. */
8586 void
8587 forget_protocol_qualifiers ()
8588 {
8589 C_IS_RESERVED_WORD (ridpointers[(int) RID_IN]) = 0;
8590 C_IS_RESERVED_WORD (ridpointers[(int) RID_OUT]) = 0;
8591 C_IS_RESERVED_WORD (ridpointers[(int) RID_INOUT]) = 0;
8592 C_IS_RESERVED_WORD (ridpointers[(int) RID_BYCOPY]) = 0;
8593 C_IS_RESERVED_WORD (ridpointers[(int) RID_BYREF]) = 0;
8594 C_IS_RESERVED_WORD (ridpointers[(int) RID_ONEWAY]) = 0;
8595 }
8596
8597 void
8598 remember_protocol_qualifiers ()
8599 {
8600 C_IS_RESERVED_WORD (ridpointers[(int) RID_IN]) = 1;
8601 C_IS_RESERVED_WORD (ridpointers[(int) RID_OUT]) = 1;
8602 C_IS_RESERVED_WORD (ridpointers[(int) RID_INOUT]) = 1;
8603 C_IS_RESERVED_WORD (ridpointers[(int) RID_BYCOPY]) = 1;
8604 C_IS_RESERVED_WORD (ridpointers[(int) RID_BYREF]) = 1;
8605 C_IS_RESERVED_WORD (ridpointers[(int) RID_ONEWAY]) = 1;
8606 }
This page took 0.413951 seconds and 6 git commands to generate.