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