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