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