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