__attribute__ ((constructor))
[official-gcc.git] / gcc / objc / objc-act.c
blob96be32f0b9113c5f37fdc90685c9f769dac4789c
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
3 Author: Steve Naroff.
5 This file is part of GNU CC.
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.
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.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Purpose: This module implements the Objective-C 4.0 language.
23 compatibility issues (with the Stepstone translator):
25 - does not recognize the following 3.3 constructs.
26 @requires, @classes, @messages, = (...)
27 - methods with variable arguments must conform to ANSI standard.
28 - tagged structure definitions that appear in BOTH the interface
29 and implementation are not allowed.
30 - public/private: all instance variables are public within the
31 context of the implementation...I consider this to be a bug in
32 the translator.
33 - statically allocated objects are not supported. the user will
34 receive an error if this service is requested.
36 code generation `options':
38 - OBJC_INT_SELECTORS */
40 #include <stdio.h>
41 #include "config.h"
42 #include "tree.h"
43 #include "c-tree.h"
44 #include "c-lex.h"
45 #include "flags.h"
46 #include "objc-act.h"
47 #include "input.h"
48 #include "function.h"
51 /* This is the default way of generating a method name. */
52 /* I am not sure it is really correct.
53 Perhaps there's a danger that it will make name conflicts
54 if method names contain underscores. -- rms. */
55 #ifndef OBJC_GEN_METHOD_LABEL
56 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
57 do { \
58 char *temp; \
59 sprintf ((BUF), "_%s_%s_%s_%s", \
60 ((IS_INST) ? "i" : "c"), \
61 (CLASS_NAME), \
62 ((CAT_NAME)? (CAT_NAME) : ""), \
63 (SEL_NAME)); \
64 for (temp = (BUF); *temp; temp++) \
65 if (*temp == ':') *temp = '_'; \
66 } while (0)
67 #endif
69 /* These need specifying. */
70 #ifndef OBJC_FORWARDING_STACK_OFFSET
71 #define OBJC_FORWARDING_STACK_OFFSET 0
72 #endif
74 #ifndef OBJC_FORWARDING_MIN_OFFSET
75 #define OBJC_FORWARDING_MIN_OFFSET 0
76 #endif
78 /* Define the special tree codes that we use. */
80 /* Table indexed by tree code giving a string containing a character
81 classifying the tree code. Possibilities are
82 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
84 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
86 char *objc_tree_code_type[] = {
87 "x",
88 #include "objc-tree.def"
90 #undef DEFTREECODE
92 /* Table indexed by tree code giving number of expression
93 operands beyond the fixed part of the node structure.
94 Not used for types or decls. */
96 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
98 int objc_tree_code_length[] = {
100 #include "objc-tree.def"
102 #undef DEFTREECODE
104 /* Names of tree components.
105 Used for printing out the tree and error messages. */
106 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
108 char *objc_tree_code_name[] = {
109 "@@dummy",
110 #include "objc-tree.def"
112 #undef DEFTREECODE
114 /* Set up for use of obstacks. */
116 #include "obstack.h"
118 #define obstack_chunk_alloc xmalloc
119 #define obstack_chunk_free free
121 /* This obstack is used to accumulate the encoding of a data type. */
122 static struct obstack util_obstack;
123 /* This points to the beginning of obstack contents,
124 so we can free the whole contents. */
125 char *util_firstobj;
127 /* for encode_method_def */
128 #include "rtl.h"
129 #include "c-parse.h"
131 #define OBJC_VERSION (flag_next_runtime ? 5 : 6)
132 #define PROTOCOL_VERSION 2
134 #define NULLT (tree) 0
136 #define OBJC_ENCODE_INLINE_DEFS 0
137 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
139 /*** Private Interface (procedures) ***/
141 /* used by compile_file */
143 static void init_objc PROTO((void));
144 static void finish_objc PROTO((void));
146 /* code generation */
148 static void synth_module_prologue PROTO((void));
149 static tree build_constructor PROTO((tree, tree));
150 static char *build_module_descriptor PROTO((void));
151 static tree init_module_descriptor PROTO((tree));
152 static tree build_objc_method_call PROTO((int, tree, tree, tree, tree, tree));
153 static void generate_strings PROTO((void));
154 static tree get_proto_encoding PROTO((tree));
155 static void build_selector_translation_table PROTO((void));
156 static tree build_ivar_chain PROTO((tree, int));
158 static tree build_ivar_template PROTO((void));
159 static tree build_method_template PROTO((void));
160 static tree build_private_template PROTO((tree));
161 static void build_class_template PROTO((void));
162 static void build_selector_template PROTO((void));
163 static void build_category_template PROTO((void));
164 static tree build_super_template PROTO((void));
165 static tree build_category_initializer PROTO((tree, tree, tree, tree, tree, tree));
166 static tree build_protocol_initializer PROTO((tree, tree, tree, tree, tree));
168 static void synth_forward_declarations PROTO((void));
169 static void generate_ivar_lists PROTO((void));
170 static void generate_dispatch_tables PROTO((void));
171 static void generate_shared_structures PROTO((void));
172 static tree generate_protocol_list PROTO((tree));
173 static void generate_forward_declaration_to_string_table PROTO((void));
174 static void build_protocol_reference PROTO((tree));
176 static tree init_selector PROTO((int));
177 static tree build_keyword_selector PROTO((tree));
178 static tree synth_id_with_class_suffix PROTO((char *, tree));
180 /* from expr.c */
181 extern int apply_args_register_offset PROTO((int));
183 /* misc. bookkeeping */
185 typedef struct hashed_entry *hash;
186 typedef struct hashed_attribute *attr;
188 struct hashed_attribute
190 attr next;
191 tree value;
193 struct hashed_entry
195 attr list;
196 hash next;
197 tree key;
200 static void hash_init PROTO((void));
201 static void hash_enter PROTO((hash *, tree));
202 static hash hash_lookup PROTO((hash *, tree));
203 static void hash_add_attr PROTO((hash, tree));
204 static tree lookup_method PROTO((tree, tree));
205 static tree lookup_instance_method_static PROTO((tree, tree));
206 static tree lookup_class_method_static PROTO((tree, tree));
207 static tree add_class PROTO((tree));
208 static void add_category PROTO((tree, tree));
210 enum string_section
212 class_names, /* class, category, protocol, module names */
213 meth_var_names, /* method and variable names */
214 meth_var_types /* method and variable type descriptors */
217 static tree add_objc_string PROTO((tree, enum string_section));
218 static tree build_objc_string_decl PROTO((tree, enum string_section));
219 static tree build_selector_reference_decl PROTO((tree));
221 /* protocol additions */
223 static tree add_protocol PROTO((tree));
224 static tree lookup_protocol PROTO((tree));
225 static tree lookup_and_install_protocols PROTO((tree));
227 /* type encoding */
229 static void encode_type_qualifiers PROTO((tree));
230 static void encode_pointer PROTO((tree, int, int));
231 static void encode_array PROTO((tree, int, int));
232 static void encode_aggregate PROTO((tree, int, int));
233 static void encode_bitfield PROTO((int, int));
234 static void encode_type PROTO((tree, int, int));
235 static void encode_field_decl PROTO((tree, int, int));
237 static void really_start_method PROTO((tree, tree));
238 static int comp_method_with_proto PROTO((tree, tree));
239 static int comp_proto_with_proto PROTO((tree, tree));
240 static tree get_arg_type_list PROTO((tree, int, int));
241 static tree expr_last PROTO((tree));
243 /* utilities for debugging and error diagnostics: */
245 static void warn_with_method PROTO((char *, int, tree));
246 static void error_with_ivar PROTO((char *, tree, tree));
247 static char *gen_method_decl PROTO((tree, char *));
248 static char *gen_declaration PROTO((tree, char *));
249 static char *gen_declarator PROTO((tree, char *, char *));
250 static int is_complex_decl PROTO((tree));
251 static void adorn_decl PROTO((tree, char *));
252 static void dump_interface PROTO((FILE *, tree));
254 /* everything else. */
256 static void objc_fatal PROTO((void));
257 static tree define_decl PROTO((tree, tree));
258 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
259 static tree lookup_protocol_in_reflist PROTO((tree, tree));
260 static tree create_builtin_decl PROTO((enum tree_code, tree, char *));
261 static tree my_build_string PROTO((int, char *));
262 static void build_objc_symtab_template PROTO((void));
263 static tree init_def_list PROTO((tree));
264 static tree init_objc_symtab PROTO((tree));
265 static void forward_declare_categories PROTO((void));
266 static void generate_objc_symtab_decl PROTO((void));
267 static tree build_selector PROTO((tree));
268 static tree build_msg_pool_reference PROTO((int));
269 static tree build_typed_selector_reference PROTO((tree, tree));
270 static tree build_selector_reference PROTO((tree));
271 static tree build_class_reference_decl PROTO((tree));
272 static void add_class_reference PROTO((tree));
273 static tree objc_copy_list PROTO((tree, tree *));
274 static tree build_protocol_template PROTO((void));
275 static tree build_descriptor_table_initializer PROTO((tree, tree));
276 static tree build_method_prototype_list_template PROTO((tree, int));
277 static tree build_method_prototype_template PROTO((void));
278 static int forwarding_offset PROTO((tree));
279 static tree encode_method_prototype PROTO((tree, tree));
280 static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree));
281 static void generate_method_descriptors PROTO((tree));
282 static tree build_tmp_function_decl PROTO((void));
283 static void hack_method_prototype PROTO((tree, tree));
284 static void generate_protocol_references PROTO((tree));
285 static void generate_protocols PROTO((void));
286 static void check_ivars PROTO((tree, tree));
287 static tree build_ivar_list_template PROTO((tree, int));
288 static tree build_method_list_template PROTO((tree, int));
289 static tree build_ivar_list_initializer PROTO((tree, tree));
290 static tree generate_ivars_list PROTO((tree, char *, int, tree));
291 static tree build_dispatch_table_initializer PROTO((tree, tree));
292 static tree generate_dispatch_table PROTO((tree, char *, int, tree));
293 static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree, tree, int, tree, tree, tree));
294 static void generate_category PROTO((tree));
295 static int is_objc_type_qualifier PROTO((tree));
296 static tree adjust_type_for_id_default PROTO((tree));
297 static tree check_duplicates PROTO((hash));
298 static tree receiver_is_class_object PROTO((tree));
299 static int check_methods PROTO((tree, tree, int));
300 static int conforms_to_protocol PROTO((tree, tree));
301 static void check_protocols PROTO((tree, char *, char *));
302 static tree encode_method_def PROTO((tree));
303 static void gen_declspecs PROTO((tree, char *, int));
304 static void generate_classref_translation_entry PROTO((tree));
305 static void handle_class_ref PROTO((tree));
307 /*** Private Interface (data) ***/
309 /* reserved tag definitions: */
311 #define TYPE_ID "id"
312 #define TAG_OBJECT "objc_object"
313 #define TAG_CLASS "objc_class"
314 #define TAG_SUPER "objc_super"
315 #define TAG_SELECTOR "objc_selector"
317 #define UTAG_CLASS "_objc_class"
318 #define UTAG_IVAR "_objc_ivar"
319 #define UTAG_IVAR_LIST "_objc_ivar_list"
320 #define UTAG_METHOD "_objc_method"
321 #define UTAG_METHOD_LIST "_objc_method_list"
322 #define UTAG_CATEGORY "_objc_category"
323 #define UTAG_MODULE "_objc_module"
324 #define UTAG_SYMTAB "_objc_symtab"
325 #define UTAG_SUPER "_objc_super"
326 #define UTAG_SELECTOR "_objc_selector"
328 #define UTAG_PROTOCOL "_objc_protocol"
329 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
330 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
331 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
333 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
334 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
336 static char* TAG_GETCLASS;
337 static char* TAG_GETMETACLASS;
338 static char* TAG_MSGSEND;
339 static char* TAG_MSGSENDSUPER;
340 static char* TAG_EXECCLASS;
342 /* Set by `continue_class' and checked by `is_public'. */
344 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
345 #define TYPED_OBJECT(type) \
346 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
348 /* Some commonly used instances of "identifier_node". */
350 static tree self_id, ucmd_id;
352 static tree self_decl, umsg_decl, umsg_super_decl;
353 static tree objc_get_class_decl, objc_get_meta_class_decl;
355 static tree super_type, selector_type, id_type, objc_class_type;
356 static tree instance_type, protocol_type;
358 /* Type checking macros. */
360 #define IS_ID(TYPE) \
361 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
362 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
363 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
364 #define IS_SUPER(TYPE) \
365 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
367 static tree class_chain = NULLT;
368 static tree alias_chain = NULLT;
369 static tree interface_chain = NULLT;
370 static tree protocol_chain = NULLT;
372 /* chains to manage selectors that are referenced and defined in the module */
374 static tree cls_ref_chain = NULLT; /* classes referenced */
375 static tree sel_ref_chain = NULLT; /* selectors referenced */
377 /* chains to manage uniquing of strings */
379 static tree class_names_chain = NULLT;
380 static tree meth_var_names_chain = NULLT;
381 static tree meth_var_types_chain = NULLT;
383 /* hash tables to manage the global pool of method prototypes */
385 static hash *nst_method_hash_list = 0;
386 static hash *cls_method_hash_list = 0;
388 /* backend data declarations */
390 static tree UOBJC_SYMBOLS_decl;
391 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
392 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
393 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
394 static tree UOBJC_SELECTOR_TABLE_decl;
395 static tree UOBJC_MODULES_decl;
396 static tree UOBJC_STRINGS_decl;
398 /* The following are used when compiling a class implementation.
399 implementation_template will normally be an interface, however if
400 none exists this will be equal to implementation_context...it is
401 set in start_class. */
403 static tree implementation_context = NULLT,
404 implementation_template = NULLT;
406 struct imp_entry
408 struct imp_entry *next;
409 tree imp_context;
410 tree imp_template;
411 tree class_decl; /* _OBJC_CLASS_<my_name>; */
412 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
415 static void handle_impent PROTO((struct imp_entry *));
417 static struct imp_entry *imp_list = 0;
418 static int imp_count = 0; /* `@implementation' */
419 static int cat_count = 0; /* `@category' */
421 static tree objc_class_template, objc_category_template, uprivate_record;
422 static tree objc_protocol_template, objc_selector_template;
423 static tree ucls_super_ref, uucls_super_ref;
425 static tree objc_method_template, objc_ivar_template;
426 static tree objc_symtab_template, objc_module_template;
427 static tree objc_super_template, objc_object_reference;
429 static tree objc_object_id, objc_class_id, objc_id_id;
430 static tree constant_string_id;
431 static tree constant_string_type;
432 static tree UOBJC_SUPER_decl;
434 static tree method_context = NULLT;
435 static int method_slot = 0; /* used by start_method_def */
437 #define BUFSIZE 1024
439 static char *errbuf; /* a buffer for error diagnostics */
441 /* data imported from tree.c */
443 extern struct obstack permanent_obstack, *current_obstack, *rtl_obstack;
444 extern enum debug_info_type write_symbols;
446 /* data imported from toplev.c */
448 extern char *dump_base_name;
450 /* Generate code for GNU or NeXT runtime environment. */
452 #ifdef NEXT_OBJC_RUNTIME
453 int flag_next_runtime = 1;
454 #else
455 int flag_next_runtime = 0;
456 #endif
458 int flag_typed_selectors;
460 /* Open and close the file for outputting class declarations, if requested. */
462 int flag_gen_declaration = 0;
464 FILE *gen_declaration_file;
466 /* Warn if multiple methods are seen for the same selector, but with
467 different argument types. */
469 int warn_selector = 0;
471 /* Warn if methods required by a protocol are not implemented in the
472 class adopting it. When turned off, methods inherited to that
473 class are also considered implemented */
475 int flag_warn_protocol = 1;
477 /* tells "encode_pointer/encode_aggregate" whether we are generating
478 type descriptors for instance variables (as opposed to methods).
479 Type descriptors for instance variables contain more information
480 than methods (for static typing and embedded structures). This
481 was added to support features being planned for dbkit2. */
483 static int generating_instance_variables = 0;
485 void
486 lang_init ()
488 /* the beginning of the file is a new line; check for # */
489 /* With luck, we discover the real source file's name from that
490 and put it in input_filename. */
491 ungetc (check_newline (), finput);
493 /* The line number can be -1 if we had -g3 and the input file
494 had a directive specifying line 0. But we want predefined
495 functions to have a line number of 0, not -1. */
496 if (lineno == -1)
497 lineno = 0;
499 /* If gen_declaration desired, open the output file. */
500 if (flag_gen_declaration)
502 int dump_base_name_length = strlen (dump_base_name);
503 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
504 strcpy (dumpname, dump_base_name);
505 strcat (dumpname, ".decl");
506 gen_declaration_file = fopen (dumpname, "w");
507 if (gen_declaration_file == 0)
508 pfatal_with_name (dumpname);
511 if (flag_next_runtime)
513 TAG_GETCLASS = "objc_getClass";
514 TAG_GETMETACLASS = "objc_getMetaClass";
515 TAG_MSGSEND = "objc_msgSend";
516 TAG_MSGSENDSUPER = "objc_msgSendSuper";
517 TAG_EXECCLASS = "__objc_execClass";
519 else
521 TAG_GETCLASS = "objc_get_class";
522 TAG_GETMETACLASS = "objc_get_meta_class";
523 TAG_MSGSEND = "objc_msg_lookup";
524 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
525 TAG_EXECCLASS = "__objc_exec_class";
526 flag_typed_selectors = 1;
529 if (doing_objc_thang)
530 init_objc ();
533 static void
534 objc_fatal ()
536 fatal ("Objective-C text in C source file");
539 void
540 finish_file ()
542 if (doing_objc_thang)
543 finish_objc (); /* Objective-C finalization */
545 if (gen_declaration_file)
546 fclose (gen_declaration_file);
549 void
550 lang_finish ()
554 char *
555 lang_identify ()
557 return "objc";
561 lang_decode_option (p)
562 char *p;
564 if (!strcmp (p, "-lang-objc"))
565 doing_objc_thang = 1;
566 else if (!strcmp (p, "-gen-decls"))
567 flag_gen_declaration = 1;
568 else if (!strcmp (p, "-Wselector"))
569 warn_selector = 1;
570 else if (!strcmp (p, "-Wno-selector"))
571 warn_selector = 0;
572 else if (!strcmp (p, "-Wprotocol"))
573 flag_warn_protocol = 1;
574 else if (!strcmp (p, "-Wno-protocol"))
575 flag_warn_protocol = 0;
576 else if (!strcmp (p, "-fgnu-runtime"))
577 flag_next_runtime = 0;
578 else if (!strcmp (p, "-fno-next-runtime"))
579 flag_next_runtime = 0;
580 else if (!strcmp (p, "-fno-gnu-runtime"))
581 flag_next_runtime = 1;
582 else if (!strcmp (p, "-fnext-runtime"))
583 flag_next_runtime = 1;
584 else
585 return c_decode_option (p);
587 return 1;
590 static tree
591 define_decl (declarator, declspecs)
592 tree declarator;
593 tree declspecs;
595 tree decl = start_decl (declarator, declspecs, 0);
596 finish_decl (decl, NULLT, NULLT);
597 return decl;
600 /* Return 1 if LHS and RHS are compatible types for assignment or
601 various other operations. Return 0 if they are incompatible, and
602 return -1 if we choose to not decide. When the operation is
603 REFLEXIVE, check for compatibility in either direction.
605 For statically typed objects, an assignment of the form `a' = `b'
606 is permitted if:
608 `a' is of type "id",
609 `a' and `b' are the same class type, or
610 `a' and `b' are of class types A and B such that B is a descendant of A. */
613 maybe_objc_comptypes (lhs, rhs, reflexive)
614 tree lhs, rhs;
615 int reflexive;
617 if (doing_objc_thang)
618 return objc_comptypes (lhs, rhs, reflexive);
619 return -1;
622 static tree
623 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
624 tree rproto_list;
625 tree sel_name;
626 int class_meth;
628 tree rproto, p;
629 tree fnd = 0;
631 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
633 p = TREE_VALUE (rproto);
635 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
637 if ((fnd = lookup_method (class_meth
638 ? PROTOCOL_CLS_METHODS (p)
639 : PROTOCOL_NST_METHODS (p), sel_name)))
641 else if (PROTOCOL_LIST (p))
642 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p), sel_name, class_meth);
644 else
645 ; /* an identifier...if we could not find a protocol. */
647 if (fnd)
648 return fnd;
650 return 0;
653 static tree
654 lookup_protocol_in_reflist (rproto_list, lproto)
655 tree rproto_list;
656 tree lproto;
658 tree rproto, p;
660 /* make sure the protocol is support by the object on the rhs */
661 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
663 tree fnd = 0;
664 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
666 p = TREE_VALUE (rproto);
668 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
670 if (lproto == p)
671 fnd = lproto;
673 else if (PROTOCOL_LIST (p))
674 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
677 if (fnd)
678 return fnd;
681 else
682 ; /* an identifier...if we could not find a protocol. */
684 return 0;
687 /* Return 1 if LHS and RHS are compatible types for assignment
688 or various other operations. Return 0 if they are incompatible,
689 and return -1 if we choose to not decide. When the operation
690 is REFLEXIVE, check for compatibility in either direction. */
693 objc_comptypes (lhs, rhs, reflexive)
694 tree lhs;
695 tree rhs;
696 int reflexive;
698 /* new clause for protocols */
700 if (TREE_CODE (lhs) == POINTER_TYPE
701 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
702 && TREE_CODE (rhs) == POINTER_TYPE
703 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
705 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
706 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
708 if (lhs_is_proto)
710 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
711 tree rproto, rproto_list;
712 tree p;
714 if (rhs_is_proto)
716 rproto_list = TYPE_PROTOCOL_LIST (rhs);
718 /* Make sure the protocol is supported by the object
719 on the rhs. */
720 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
722 p = TREE_VALUE (lproto);
723 rproto = lookup_protocol_in_reflist (rproto_list, p);
725 if (!rproto)
726 warning ("object does not conform to the `%s' protocol",
727 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
730 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
732 tree rname = TYPE_NAME (TREE_TYPE (rhs));
733 tree rinter;
735 /* Make sure the protocol is supported by the object
736 on the rhs. */
737 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
739 p = TREE_VALUE (lproto);
740 rproto = 0;
741 rinter = lookup_interface (rname);
743 while (rinter && !rproto)
745 tree cat;
747 rproto_list = CLASS_PROTOCOL_LIST (rinter);
748 rproto = lookup_protocol_in_reflist (rproto_list, p);
750 /* NEW!!! */
751 /* Check for protocols adopted by categories. */
752 cat = CLASS_CATEGORY_LIST (rinter);
753 while (cat && !rproto)
755 rproto_list = CLASS_PROTOCOL_LIST (cat);
756 rproto = lookup_protocol_in_reflist (rproto_list, p);
758 cat = CLASS_CATEGORY_LIST (cat);
761 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
763 if (!rproto)
764 warning ("class `%s' does not implement the `%s' protocol",
765 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
766 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
770 return 1; /* may change...based on whether there was any mismatch */
772 else if (rhs_is_proto)
774 /* lhs is not a protocol...warn if it is statically typed */
776 if (TYPED_OBJECT (TREE_TYPE (lhs)))
777 return 0;
778 else
779 return 1; /* one of the types is a protocol */
781 else
782 return -1; /* defer to comptypes */
784 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
785 ; /* fall thru...this is the case we have been handling all along */
786 else
787 return -1; /* defer to comptypes */
789 /* End of new protocol support. */
791 /* `id' = `<class> *', `<class> *' = `id' */
793 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
794 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
795 return 1;
797 /* `id' = `Class', `Class' = `id' */
799 else if ((TYPE_NAME (lhs) == objc_object_id
800 && TYPE_NAME (rhs) == objc_class_id)
801 || (TYPE_NAME (lhs) == objc_class_id
802 && TYPE_NAME (rhs) == objc_object_id))
803 return 1;
805 /* `<class> *' = `<class> *' */
807 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
809 tree lname = TYPE_NAME (lhs);
810 tree rname = TYPE_NAME (rhs);
811 tree inter;
813 if (lname == rname)
814 return 1;
816 /* If the left hand side is a super class of the right hand side,
817 allow it. */
818 for (inter = lookup_interface (rname); inter;
819 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
820 if (lname == CLASS_SUPER_NAME (inter))
821 return 1;
823 /* Allow the reverse when reflexive. */
824 if (reflexive)
825 for (inter = lookup_interface (lname); inter;
826 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
827 if (rname == CLASS_SUPER_NAME (inter))
828 return 1;
830 return 0;
832 else
833 return -1; /* defer to comptypes */
836 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
838 void
839 objc_check_decl (decl)
840 tree decl;
842 tree type = TREE_TYPE (decl);
844 if (TREE_CODE (type) == RECORD_TYPE
845 && TREE_STATIC_TEMPLATE (type)
846 && type != constant_string_type)
848 error_with_decl (decl, "`%s' cannot be statically allocated");
849 fatal ("statically allocated objects not supported");
853 void
854 maybe_objc_check_decl (decl)
855 tree decl;
857 if (doing_objc_thang)
858 objc_check_decl (decl);
861 /* Implement static typing. At this point, we know we have an interface. */
863 tree
864 get_static_reference (interface, protocols)
865 tree interface;
866 tree protocols;
868 tree type = xref_tag (RECORD_TYPE, interface);
870 if (protocols)
872 tree t, m = TYPE_MAIN_VARIANT (type);
873 struct obstack *ambient_obstack = current_obstack;
875 current_obstack = &permanent_obstack;
876 t = copy_node (type);
877 TYPE_BINFO (t) = make_tree_vec (2);
879 /* Add this type to the chain of variants of TYPE. */
880 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
881 TYPE_NEXT_VARIANT (m) = t;
883 current_obstack = ambient_obstack;
885 /* Look up protocols and install in lang specific list. */
886 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
888 /* This forces a new pointer type to be created later
889 (in build_pointer_type)...so that the new template
890 we just created will actually be used...what a hack! */
891 if (TYPE_POINTER_TO (t))
892 TYPE_POINTER_TO (t) = NULL;
894 type = t;
897 return type;
900 tree
901 get_object_reference (protocols)
902 tree protocols;
904 tree type_decl = lookup_name (objc_id_id);
905 tree type;
907 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
909 type = TREE_TYPE (type_decl);
910 if (TYPE_MAIN_VARIANT (type) != id_type)
911 warning ("Unexpected type for `id' (%s)",
912 gen_declaration (type, errbuf));
914 else
916 fatal ("Undefined type `id', please import <objc/objc.h>");
919 /* This clause creates a new pointer type that is qualified with
920 the protocol specification...this info is used later to do more
921 elaborate type checking. */
922 if (protocols)
924 tree t, m = TYPE_MAIN_VARIANT (type);
925 struct obstack *ambient_obstack = current_obstack;
927 current_obstack = &permanent_obstack;
928 t = copy_node (type);
929 TYPE_BINFO (t) = make_tree_vec (2);
931 /* Add this type to the chain of variants of TYPE. */
932 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
933 TYPE_NEXT_VARIANT (m) = t;
935 current_obstack = ambient_obstack;
937 /* look up protocols...and install in lang specific list */
938 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
940 /* This forces a new pointer type to be created later
941 (in build_pointer_type)...so that the new template
942 we just created will actually be used...what a hack! */
943 if (TYPE_POINTER_TO (t))
944 TYPE_POINTER_TO (t) = NULL;
946 type = t;
948 return type;
951 static tree
952 lookup_and_install_protocols (protocols)
953 tree protocols;
955 tree proto;
956 tree prev = NULL;
957 tree return_value = protocols;
959 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
961 tree ident = TREE_VALUE (proto);
962 tree p = lookup_protocol (ident);
964 if (!p)
966 error ("Cannot find protocol declaration for `%s'",
967 IDENTIFIER_POINTER (ident));
968 if (prev)
969 TREE_CHAIN (prev) = TREE_CHAIN (proto);
970 else
971 return_value = TREE_CHAIN (proto);
973 else
975 /* replace identifier with actual protocol node */
976 TREE_VALUE (proto) = p;
977 prev = proto;
980 return return_value;
983 /* Create and push a decl for a built-in external variable or field NAME.
984 CODE says which.
985 TYPE is its data type. */
987 static tree
988 create_builtin_decl (code, type, name)
989 enum tree_code code;
990 tree type;
991 char *name;
993 tree decl = build_decl (code, get_identifier (name), type);
994 if (code == VAR_DECL)
996 TREE_STATIC (decl) = 1;
997 make_decl_rtl (decl, 0, 1);
998 pushdecl (decl);
1000 return decl;
1003 /* purpose: "play" parser, creating/installing representations
1004 of the declarations that are required by Objective-C.
1006 model:
1008 type_spec--------->sc_spec
1009 (tree_list) (tree_list)
1012 identifier_node identifier_node */
1014 static void
1015 synth_module_prologue ()
1017 tree temp_type;
1018 tree super_p;
1020 /* defined in `objc.h' */
1021 objc_object_id = get_identifier (TAG_OBJECT);
1023 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1025 id_type = build_pointer_type (objc_object_reference);
1027 objc_id_id = get_identifier (TYPE_ID);
1028 objc_class_id = get_identifier (TAG_CLASS);
1030 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1031 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1032 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1034 /* Declare type of selector-objects that represent an operation name. */
1036 #ifdef OBJC_INT_SELECTORS
1037 /* `unsigned int' */
1038 selector_type = unsigned_type_node;
1039 #else
1040 /* `struct objc_selector *' */
1041 selector_type
1042 = build_pointer_type (xref_tag (RECORD_TYPE,
1043 get_identifier (TAG_SELECTOR)));
1044 #endif /* not OBJC_INT_SELECTORS */
1046 /* Forward declare type, or else the prototype for msgSendSuper will
1047 complain. */
1049 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1050 get_identifier (TAG_SUPER)));
1053 /* id objc_msgSend (id, SEL, ...); */
1055 temp_type
1056 = build_function_type (id_type,
1057 tree_cons (NULL_TREE, id_type,
1058 tree_cons (NULLT, selector_type, NULLT)));
1060 if (! flag_next_runtime)
1062 umsg_decl = build_decl (FUNCTION_DECL,
1063 get_identifier (TAG_MSGSEND), temp_type);
1064 DECL_EXTERNAL (umsg_decl) = 1;
1065 TREE_PUBLIC (umsg_decl) = 1;
1066 DECL_INLINE (umsg_decl) = 1;
1068 if (flag_traditional && TAG_MSGSEND[0] != '_')
1069 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1071 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1072 pushdecl (umsg_decl);
1074 else
1075 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
1077 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1079 temp_type
1080 = build_function_type (id_type,
1081 tree_cons (NULL_TREE, super_p,
1082 tree_cons (NULLT, selector_type, NULLT)));
1084 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1085 temp_type, NOT_BUILT_IN, 0);
1087 /* id objc_getClass (const char *); */
1089 temp_type = build_function_type (id_type,
1090 tree_cons (NULLT,
1091 const_string_type_node,
1092 tree_cons (NULLT, void_type_node, NULLT)));
1094 objc_get_class_decl
1095 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
1097 /* id objc_getMetaClass (const char *); */
1099 objc_get_meta_class_decl
1100 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
1102 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1104 if (! flag_next_runtime)
1106 if (flag_typed_selectors)
1108 /* supress outputting debug symbols, because
1109 dbxout_init hasn'r been called yet... */
1110 enum debug_info_type save_write_symbols = write_symbols;
1111 write_symbols = NO_DEBUG;
1113 build_selector_template ();
1114 temp_type = build_array_type (objc_selector_template, NULLT);
1116 write_symbols = save_write_symbols;
1118 else
1119 temp_type = build_array_type (selector_type, NULLT);
1121 layout_type (temp_type);
1122 UOBJC_SELECTOR_TABLE_decl
1123 = create_builtin_decl (VAR_DECL, temp_type,
1124 "_OBJC_SELECTOR_TABLE");
1128 generate_forward_declaration_to_string_table ();
1130 /* Forward declare constant_string_id and constant_string_type. */
1131 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1132 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1135 /* Custom build_string which sets TREE_TYPE! */
1137 static tree
1138 my_build_string (len, str)
1139 int len;
1140 char *str;
1142 int wide_flag = 0;
1143 tree a_string = build_string (len, str);
1144 /* Some code from combine_strings, which is local to c-parse.y. */
1145 if (TREE_TYPE (a_string) == int_array_type_node)
1146 wide_flag = 1;
1148 TREE_TYPE (a_string) =
1149 build_array_type (wide_flag ? integer_type_node : char_type_node,
1150 build_index_type (build_int_2 (len - 1, 0)));
1152 TREE_CONSTANT (a_string) = 1; /* puts string in the ".text" segment */
1153 TREE_STATIC (a_string) = 1;
1155 return a_string;
1158 /* Return a newly constructed OBJC_STRING_CST node whose value is
1159 the LEN characters at STR.
1160 The TREE_TYPE is not initialized. */
1162 tree
1163 build_objc_string (len, str)
1164 int len;
1165 char *str;
1167 tree s = build_string (len, str);
1169 TREE_SET_CODE (s, OBJC_STRING_CST);
1170 return s;
1173 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1174 NXConstantString which points at the concatenation of those strings.
1175 We place the string object in the __string_objects section of the
1176 __OBJC segment. The Objective-C runtime will initialize the isa
1177 pointers of the string objects to point at the NXConstantString
1178 class object. */
1180 tree
1181 build_objc_string_object (strings)
1182 tree strings;
1184 tree string, initlist, constructor;
1185 int length;
1187 if (!doing_objc_thang)
1188 objc_fatal ();
1190 if (lookup_interface (constant_string_id) == NULLT)
1192 error ("Cannot find interface declaration for `%s'",
1193 IDENTIFIER_POINTER (constant_string_id));
1194 return error_mark_node;
1197 add_class_reference (constant_string_id);
1199 /* combine_strings will work for OBJC_STRING_CST's too. */
1200 string = combine_strings (strings);
1201 TREE_SET_CODE (string, STRING_CST);
1202 length = TREE_STRING_LENGTH (string) - 1;
1204 /* & ((NXConstantString) {0, string, length}) */
1206 initlist = build_tree_list (NULLT, build_int_2 (0, 0));
1207 initlist = tree_cons (NULLT, build_unary_op (ADDR_EXPR, string, 1),
1208 initlist);
1209 initlist = tree_cons (NULLT, build_int_2 (length, 0), initlist);
1210 constructor = build_constructor (constant_string_type,
1211 nreverse (initlist));
1213 return build_unary_op (ADDR_EXPR, constructor, 1);
1216 /* Build a static constant CONSTRUCTOR
1217 with type TYPE and elements ELTS. */
1219 static tree
1220 build_constructor (type, elts)
1221 tree type, elts;
1223 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1225 TREE_CONSTANT (constructor) = 1;
1226 TREE_STATIC (constructor) = 1;
1227 TREE_READONLY (constructor) = 1;
1229 return constructor;
1232 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1234 /* Predefine the following data type:
1236 struct _objc_symtab
1238 long sel_ref_cnt;
1239 SEL *refs;
1240 short cls_def_cnt;
1241 short cat_def_cnt;
1242 void *defs[cls_def_cnt + cat_def_cnt];
1243 }; */
1245 static void
1246 build_objc_symtab_template ()
1248 tree field_decl, field_decl_chain, index;
1250 objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1252 /* long sel_ref_cnt; */
1254 field_decl = create_builtin_decl (FIELD_DECL,
1255 long_integer_type_node,
1256 "sel_ref_cnt");
1257 field_decl_chain = field_decl;
1259 /* SEL *refs; */
1261 field_decl = create_builtin_decl (FIELD_DECL,
1262 build_pointer_type (selector_type),
1263 "refs");
1264 chainon (field_decl_chain, field_decl);
1266 /* short cls_def_cnt; */
1268 field_decl = create_builtin_decl (FIELD_DECL,
1269 short_integer_type_node,
1270 "cls_def_cnt");
1271 chainon (field_decl_chain, field_decl);
1273 /* short cat_def_cnt; */
1275 field_decl = create_builtin_decl (FIELD_DECL,
1276 short_integer_type_node,
1277 "cat_def_cnt");
1278 chainon (field_decl_chain, field_decl);
1280 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1282 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1283 imp_count == 0 && cat_count == 0
1284 ? -1 : 0));
1285 field_decl = create_builtin_decl (FIELD_DECL,
1286 build_array_type (ptr_type_node, index),
1287 "defs");
1288 chainon (field_decl_chain, field_decl);
1290 finish_struct (objc_symtab_template, field_decl_chain);
1293 /* Create the initial value for the `defs' field of _objc_symtab.
1294 This is a CONSTRUCTOR. */
1296 static tree
1297 init_def_list (type)
1298 tree type;
1300 tree expr, initlist = NULLT;
1301 struct imp_entry *impent;
1303 if (imp_count)
1304 for (impent = imp_list; impent; impent = impent->next)
1306 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1308 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1309 initlist = tree_cons (NULLT, expr, initlist);
1313 if (cat_count)
1314 for (impent = imp_list; impent; impent = impent->next)
1316 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1318 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1319 initlist = tree_cons (NULLT, expr, initlist);
1322 return build_constructor (type, nreverse (initlist));
1325 /* Construct the initial value for all of _objc_symtab. */
1327 static tree
1328 init_objc_symtab (type)
1329 tree type;
1331 tree initlist;
1333 /* sel_ref_cnt = { ..., 5, ... } */
1335 initlist = build_tree_list (NULLT, build_int_2 (0, 0));
1337 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1339 if (flag_next_runtime || ! sel_ref_chain)
1340 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1341 else
1342 initlist = tree_cons (NULLT,
1343 build_unary_op (ADDR_EXPR,
1344 UOBJC_SELECTOR_TABLE_decl, 1),
1345 initlist);
1347 /* cls_def_cnt = { ..., 5, ... } */
1349 initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
1351 /* cat_def_cnt = { ..., 5, ... } */
1353 initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
1355 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1357 if (imp_count || cat_count)
1359 tree field = TYPE_FIELDS (type);
1360 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1362 initlist = tree_cons (NULLT, init_def_list (TREE_TYPE (field)),
1363 initlist);
1366 return build_constructor (type, nreverse (initlist));
1369 /* Push forward-declarations of all the categories
1370 so that init_def_list can use them in a CONSTRUCTOR. */
1372 static void
1373 forward_declare_categories ()
1375 struct imp_entry *impent;
1376 tree sav = implementation_context;
1377 for (impent = imp_list; impent; impent = impent->next)
1379 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1381 /* Set an invisible arg to synth_id_with_class_suffix. */
1382 implementation_context = impent->imp_context;
1383 impent->class_decl
1384 = create_builtin_decl (VAR_DECL, objc_category_template,
1385 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1388 implementation_context = sav;
1391 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1392 and initialized appropriately. */
1394 static void
1395 generate_objc_symtab_decl ()
1397 tree sc_spec;
1399 if (!objc_category_template)
1400 build_category_template ();
1402 /* forward declare categories */
1403 if (cat_count)
1404 forward_declare_categories ();
1406 if (!objc_symtab_template)
1407 build_objc_symtab_template ();
1409 sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
1411 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1412 tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
1414 end_temporary_allocation (); /* start_decl trying to be smart about inits */
1415 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1416 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1417 finish_decl (UOBJC_SYMBOLS_decl,
1418 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1419 NULLT);
1422 static tree
1423 init_module_descriptor (type)
1424 tree type;
1426 tree initlist, expr;
1428 /* version = { 1, ... } */
1430 expr = build_int_2 (OBJC_VERSION, 0);
1431 initlist = build_tree_list (NULLT, expr);
1433 /* size = { ..., sizeof (struct objc_module), ... } */
1435 expr = size_in_bytes (objc_module_template);
1436 initlist = tree_cons (NULLT, expr, initlist);
1438 /* name = { ..., "foo.m", ... } */
1440 expr = add_objc_string (get_identifier (input_filename), class_names);
1441 initlist = tree_cons (NULLT, expr, initlist);
1443 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1445 if (UOBJC_SYMBOLS_decl)
1446 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1447 else
1448 expr = build_int_2 (0, 0);
1449 initlist = tree_cons (NULLT, expr, initlist);
1451 return build_constructor (type, nreverse (initlist));
1454 /* Write out the data structures to describe Objective C classes defined.
1455 If appropriate, compile and output a setup function to initialize them.
1456 Return a string which is the name of a function to call to initialize
1457 the Objective C data structures for this file (and perhaps for other files
1458 also).
1460 struct objc_module { ... } _OBJC_MODULE = { ... };
1464 static char *
1465 build_module_descriptor ()
1467 tree decl_specs, field_decl, field_decl_chain;
1469 objc_module_template = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1471 /* long version; */
1473 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1474 field_decl = get_identifier ("version");
1475 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1476 field_decl_chain = field_decl;
1478 /* long size; */
1480 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1481 field_decl = get_identifier ("size");
1482 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1483 chainon (field_decl_chain, field_decl);
1485 /* char *name; */
1487 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1488 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
1489 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1490 chainon (field_decl_chain, field_decl);
1492 /* struct objc_symtab *symtab; */
1494 decl_specs = get_identifier (UTAG_SYMTAB);
1495 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
1496 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
1497 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1498 chainon (field_decl_chain, field_decl);
1500 finish_struct (objc_module_template, field_decl_chain);
1502 /* create an instance of "objc_module" */
1504 decl_specs = tree_cons (NULLT, objc_module_template,
1505 build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
1507 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1508 decl_specs, 1);
1510 end_temporary_allocation (); /* start_decl trying to be smart about inits */
1511 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1512 finish_decl (UOBJC_MODULES_decl,
1513 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1514 NULLT);
1516 /* Mark the decl to avoid "defined but not used" warning. */
1517 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1519 /* Generate a constructor call for the module descriptor.
1520 This code was generated by reading the grammar rules
1521 of c-parse.y; Therefore, it may not be the most efficient
1522 way of generating the requisite code. */
1524 if (flag_next_runtime)
1525 return 0;
1528 tree parms, function_decl, decelerator, void_list_node;
1529 tree function_type;
1530 extern tree get_file_function_name ();
1531 tree init_function_name = get_file_function_name ('I');
1533 /* Declare void __objc_execClass (void*); */
1535 void_list_node = build_tree_list (NULL_TREE, void_type_node);
1536 function_type
1537 = build_function_type (void_type_node,
1538 tree_cons (NULL_TREE, ptr_type_node,
1539 void_list_node));
1540 function_decl = build_decl (FUNCTION_DECL,
1541 get_identifier (TAG_EXECCLASS),
1542 function_type);
1543 DECL_EXTERNAL (function_decl) = 1;
1544 TREE_PUBLIC (function_decl) = 1;
1546 pushdecl (function_decl);
1547 rest_of_decl_compilation (function_decl, 0, 0, 0);
1549 parms
1550 = build_tree_list (NULLT,
1551 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1552 decelerator = build_function_call (function_decl, parms);
1554 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1556 start_function (void_list_node,
1557 build_parse_node (CALL_EXPR, init_function_name,
1558 /* This has the format of the output
1559 of get_parm_info. */
1560 tree_cons (NULL_TREE, NULL_TREE,
1561 void_list_node),
1562 NULL_TREE),
1564 #if 0 /* This should be turned back on later
1565 for the systems where collect is not needed. */
1566 /* Make these functions nonglobal
1567 so each file can use the same name. */
1568 TREE_PUBLIC (current_function_decl) = 0;
1569 #endif
1570 TREE_USED (current_function_decl) = 1;
1571 store_parm_decls ();
1573 assemble_external (function_decl);
1574 c_expand_expr_stmt (decelerator);
1576 TREE_PUBLIC (current_function_decl) = 1;
1578 function_decl = current_function_decl;
1579 finish_function (0);
1581 /* Return the name of the constructor function. */
1582 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1586 /* extern const char _OBJC_STRINGS[]; */
1588 static void
1589 generate_forward_declaration_to_string_table ()
1591 tree sc_spec, decl_specs, expr_decl;
1593 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
1594 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1596 expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1598 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1601 /* Output all strings. */
1603 static void
1604 generate_strings ()
1606 tree sc_spec, decl_specs, expr_decl;
1607 tree chain, string_expr;
1608 tree string, decl;
1610 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1612 string = TREE_VALUE (chain);
1613 decl = TREE_PURPOSE (chain);
1614 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1615 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1616 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
1617 decl = start_decl (expr_decl, decl_specs, 1);
1618 end_temporary_allocation ();
1619 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1620 IDENTIFIER_POINTER (string));
1621 finish_decl (decl, string_expr, NULLT);
1624 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1626 string = TREE_VALUE (chain);
1627 decl = TREE_PURPOSE (chain);
1628 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1629 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1630 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
1631 decl = start_decl (expr_decl, decl_specs, 1);
1632 end_temporary_allocation ();
1633 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1634 IDENTIFIER_POINTER (string));
1635 finish_decl (decl, string_expr, NULLT);
1638 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1640 string = TREE_VALUE (chain);
1641 decl = TREE_PURPOSE (chain);
1642 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1643 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1644 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
1645 decl = start_decl (expr_decl, decl_specs, 1);
1646 end_temporary_allocation ();
1647 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1648 IDENTIFIER_POINTER (string));
1649 finish_decl (decl, string_expr, NULLT);
1653 static tree
1654 build_selector_reference_decl (name)
1655 tree name;
1657 tree decl, ident;
1658 char buf[256];
1659 struct obstack *save_current_obstack = current_obstack;
1660 struct obstack *save_rtl_obstack = rtl_obstack;
1661 static int idx = 0;
1663 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
1665 /* new stuff */
1666 rtl_obstack = current_obstack = &permanent_obstack;
1667 ident = get_identifier (buf);
1669 decl = build_decl (VAR_DECL, ident, selector_type);
1670 DECL_EXTERNAL (decl) = 1;
1671 TREE_PUBLIC (decl) = 1;
1672 TREE_USED (decl) = 1;
1673 TREE_READONLY (decl) = 1;
1675 make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
1676 pushdecl_top_level (decl); /* our `extended/custom' pushdecl in c-decl.c */
1678 current_obstack = save_current_obstack;
1679 rtl_obstack = save_rtl_obstack;
1681 return decl;
1684 /* Just a handy wrapper for add_objc_string. */
1686 static tree
1687 build_selector (ident)
1688 tree ident;
1690 tree expr = add_objc_string (ident, meth_var_names);
1691 if (flag_typed_selectors)
1692 return expr;
1693 else
1694 return build_c_cast (selector_type, expr); /* cast! */
1697 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
1698 The cast stops the compiler from issuing the following message:
1699 grok.m: warning: initialization of non-const * pointer from const *
1700 grok.m: warning: initialization between incompatible pointer types. */
1702 static tree
1703 build_msg_pool_reference (offset)
1704 int offset;
1706 tree expr = build_int_2 (offset, 0);
1707 tree cast;
1709 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
1710 expr = build_unary_op (ADDR_EXPR, expr, 0);
1712 cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
1713 build1 (INDIRECT_REF, NULLT, NULLT));
1714 TREE_TYPE (expr) = groktypename (cast);
1715 return expr;
1718 static tree
1719 init_selector (offset)
1720 int offset;
1722 tree expr = build_msg_pool_reference (offset);
1723 TREE_TYPE (expr) = selector_type; /* cast */
1724 return expr;
1727 static void
1728 build_selector_translation_table ()
1730 tree sc_spec, decl_specs;
1731 tree chain, initlist = NULLT;
1732 int offset = 0;
1733 tree decl, var_decl, name;
1735 /* The corresponding pop_obstacks is in finish_decl,
1736 called at the end of this function. */
1737 if (! flag_next_runtime)
1738 push_obstacks_nochange ();
1740 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1742 tree expr;
1744 expr = build_selector (TREE_VALUE (chain));
1746 if (flag_next_runtime)
1748 name = DECL_NAME (TREE_PURPOSE (chain));
1750 sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
1752 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
1753 decl_specs = tree_cons (NULLT, selector_type, sc_spec);
1755 var_decl = name;
1757 /* the `decl' that is returned from start_decl is the one that we
1758 forward declared in `build_selector_reference' */
1759 decl = start_decl (var_decl, decl_specs, 1);
1762 /* add one for the '\0' character */
1763 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1765 if (flag_next_runtime)
1767 end_temporary_allocation ();
1768 finish_decl (decl, expr, NULLT);
1770 else
1772 if (flag_typed_selectors)
1774 tree eltlist = NULLT;
1775 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
1776 eltlist = tree_cons (NULLT, expr, NULLT);
1777 eltlist = tree_cons (NULLT, encoding, eltlist);
1778 expr = build_constructor (objc_selector_template,
1779 nreverse (eltlist));
1781 initlist = tree_cons (NULLT, expr, initlist);
1786 if (! flag_next_runtime)
1788 /* Cause the variable and its initial value to be actually output. */
1789 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
1790 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
1791 /* NULL terminate the list and fix the decl for output. */
1792 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1793 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
1794 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1795 nreverse (initlist));
1796 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULLT);
1797 current_function_decl = NULLT;
1802 static tree
1803 get_proto_encoding (proto)
1804 tree proto;
1806 tree encoding;
1807 if (proto)
1809 tree tmp_decl;
1811 if (! METHOD_ENCODING (proto))
1813 tmp_decl = build_tmp_function_decl ();
1814 hack_method_prototype (proto, tmp_decl);
1815 encoding = encode_method_prototype (proto, tmp_decl);
1816 METHOD_ENCODING (proto) = encoding;
1818 else
1819 encoding = METHOD_ENCODING (proto);
1821 return add_objc_string (encoding, meth_var_types);
1823 else
1824 return build_int_2 (0, 0);
1827 /* sel_ref_chain is a list whose "value" fields will be instances of
1828 identifier_node that represent the selector. */
1830 static tree
1831 build_typed_selector_reference (ident, proto)
1832 tree ident, proto;
1834 tree *chain = &sel_ref_chain;
1835 tree expr;
1836 int index = 0;
1838 while (*chain)
1840 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
1841 goto return_at_index;
1842 index++;
1843 chain = &TREE_CHAIN (*chain);
1846 *chain = perm_tree_cons (proto, ident, NULLT);
1848 return_at_index:
1849 expr = build_unary_op (ADDR_EXPR,
1850 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
1851 build_int_2 (index, 0)),
1853 return build_c_cast (selector_type, expr);
1856 static tree
1857 build_selector_reference (ident)
1858 tree ident;
1860 tree *chain = &sel_ref_chain;
1861 tree expr;
1862 int index = 0;
1864 while (*chain)
1866 if (TREE_VALUE (*chain) == ident)
1867 return (flag_next_runtime
1868 ? TREE_PURPOSE (*chain)
1869 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
1870 build_int_2 (index, 0)));
1872 index++;
1873 chain = &TREE_CHAIN (*chain);
1876 expr = build_selector_reference_decl (ident);
1878 *chain = perm_tree_cons (expr, ident, NULLT);
1880 return (flag_next_runtime
1881 ? expr
1882 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
1883 build_int_2 (index, 0)));
1886 static tree
1887 build_class_reference_decl (name)
1888 tree name;
1890 tree decl, ident;
1891 char buf[256];
1892 struct obstack *save_current_obstack = current_obstack;
1893 struct obstack *save_rtl_obstack = rtl_obstack;
1894 static int idx = 0;
1896 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
1898 /* new stuff */
1899 rtl_obstack = current_obstack = &permanent_obstack;
1900 ident = get_identifier (buf);
1902 decl = build_decl (VAR_DECL, ident, objc_class_type);
1903 DECL_EXTERNAL (decl) = 1;
1904 TREE_PUBLIC (decl) = 1;
1905 TREE_USED (decl) = 1;
1906 TREE_READONLY (decl) = 1;
1908 make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
1909 pushdecl_top_level (decl); /* our `extended/custom' pushdecl in c-decl.c */
1911 current_obstack = save_current_obstack;
1912 rtl_obstack = save_rtl_obstack;
1914 return decl;
1917 /* Create a class reference, but don't create a variable to reference
1918 it. */
1920 static void
1921 add_class_reference (ident)
1922 tree ident;
1924 tree chain;
1926 if ((chain = cls_ref_chain))
1928 tree tail;
1931 if (ident == TREE_VALUE (chain))
1932 return;
1934 tail = chain;
1935 chain = TREE_CHAIN (chain);
1937 while (chain);
1939 /* append to the end of the list */
1940 TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1942 else
1943 cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1946 /* Get a class reference, creating it if necessary. Also create the
1947 reference variable. */
1949 tree
1950 get_class_reference (ident)
1951 tree ident;
1953 if (flag_next_runtime)
1955 tree *chain;
1956 tree decl;
1958 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
1959 if (TREE_VALUE (*chain) == ident)
1961 if (! TREE_PURPOSE (*chain))
1962 TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
1963 return TREE_PURPOSE (*chain);
1966 decl = build_class_reference_decl (ident);
1967 *chain = perm_tree_cons (decl, ident, NULLT);
1968 return decl;
1970 else
1972 tree params;
1974 add_class_reference (ident);
1976 params = build_tree_list (NULLT,
1977 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
1978 IDENTIFIER_POINTER (ident)));
1980 assemble_external (objc_get_class_decl);
1981 return build_function_call (objc_get_class_decl, params);
1985 /* sel_refdef_chain is a list whose "value" fields will be instances
1986 of identifier_node that represent the selector. It returns the
1987 offset of the selector from the beginning of the _OBJC_STRINGS
1988 pool. This offset is typically used by init_selector during code
1989 generation.
1991 For each string section we have a chain which maps identifier nodes
1992 to decls for the strings. */
1994 static tree
1995 add_objc_string (ident, section)
1996 tree ident;
1997 enum string_section section;
1999 tree *chain, decl;
2001 if (section == class_names)
2002 chain = &class_names_chain;
2003 else if (section == meth_var_names)
2004 chain = &meth_var_names_chain;
2005 else if (section == meth_var_types)
2006 chain = &meth_var_types_chain;
2008 while (*chain)
2010 if (TREE_VALUE (*chain) == ident)
2011 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2013 chain = &TREE_CHAIN (*chain);
2016 decl = build_objc_string_decl (ident, section);
2018 *chain = perm_tree_cons (decl, ident, NULLT);
2020 return build_unary_op (ADDR_EXPR, decl, 1);
2023 static tree
2024 build_objc_string_decl (name, section)
2025 tree name;
2026 enum string_section section;
2028 tree decl, ident;
2029 char buf[256];
2030 struct obstack *save_current_obstack = current_obstack;
2031 struct obstack *save_rtl_obstack = rtl_obstack;
2032 static int class_names_idx = 0;
2033 static int meth_var_names_idx = 0;
2034 static int meth_var_types_idx = 0;
2036 if (section == class_names)
2037 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2038 else if (section == meth_var_names)
2039 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2040 else if (section == meth_var_types)
2041 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2043 rtl_obstack = current_obstack = &permanent_obstack;
2044 ident = get_identifier (buf);
2046 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2047 DECL_EXTERNAL (decl) = 1;
2048 TREE_PUBLIC (decl) = 1;
2049 TREE_USED (decl) = 1;
2050 TREE_READONLY (decl) = 1;
2051 TREE_CONSTANT (decl) = 1;
2053 make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation */
2054 pushdecl_top_level (decl); /* our `extended/custom' pushdecl in c-decl.c */
2056 current_obstack = save_current_obstack;
2057 rtl_obstack = save_rtl_obstack;
2059 return decl;
2063 void
2064 objc_declare_alias (alias_ident, class_ident)
2065 tree alias_ident;
2066 tree class_ident;
2068 if (!doing_objc_thang)
2069 objc_fatal ();
2071 if (is_class_name (class_ident) != class_ident)
2072 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2073 else if (is_class_name (alias_ident))
2074 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2075 else
2076 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2079 void
2080 objc_declare_class (ident_list)
2081 tree ident_list;
2083 tree list;
2085 if (!doing_objc_thang)
2086 objc_fatal ();
2088 for (list = ident_list; list; list = TREE_CHAIN (list))
2090 tree ident = TREE_VALUE (list);
2091 tree decl;
2093 if ((decl = lookup_name (ident)))
2095 error ("`%s' redeclared as different kind of symbol",
2096 IDENTIFIER_POINTER (ident));
2097 error_with_decl (decl, "previous declaration of `%s'");
2100 if (! is_class_name (ident))
2102 tree record = xref_tag (RECORD_TYPE, ident);
2103 TREE_STATIC_TEMPLATE (record) = 1;
2104 class_chain = tree_cons (NULLT, ident, class_chain);
2109 tree
2110 is_class_name (ident)
2111 tree ident;
2113 tree chain;
2115 if (lookup_interface (ident))
2116 return ident;
2118 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2120 if (ident == TREE_VALUE (chain))
2121 return ident;
2124 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2126 if (ident == TREE_VALUE (chain))
2127 return TREE_PURPOSE (chain);
2130 return 0;
2133 tree
2134 lookup_interface (ident)
2135 tree ident;
2137 tree chain;
2139 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2141 if (ident == CLASS_NAME (chain))
2142 return chain;
2144 return NULLT;
2147 static tree
2148 objc_copy_list (list, head)
2149 tree list;
2150 tree *head;
2152 tree newlist = NULL_TREE, tail = NULL_TREE;
2154 while (list)
2156 tail = copy_node (list);
2158 /* The following statement fixes a bug when inheriting instance
2159 variables that are declared to be bitfields. finish_struct
2160 expects to find the width of the bitfield in DECL_INITIAL,
2161 which it nulls out after processing the decl of the super
2162 class...rather than change the way finish_struct works (which
2163 is risky), I create the situation it expects...s.naroff
2164 (7/23/89). */
2166 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2167 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2169 newlist = chainon (newlist, tail);
2170 list = TREE_CHAIN (list);
2172 *head = newlist;
2173 return tail;
2176 /* Used by: build_private_template, get_class_ivars, and
2177 continue_class. COPY is 1 when called from @defs. In this case
2178 copy all fields. Otherwise don't copy leaf ivars since we rely on
2179 them being side-effected exactly once by finish_struct. */
2181 static tree
2182 build_ivar_chain (interface, copy)
2183 tree interface;
2184 int copy;
2186 tree my_name, super_name, ivar_chain;
2188 my_name = CLASS_NAME (interface);
2189 super_name = CLASS_SUPER_NAME (interface);
2191 /* Possibly copy leaf ivars. */
2192 if (copy)
2193 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2194 else
2195 ivar_chain = CLASS_IVARS (interface);
2197 while (super_name)
2199 tree op1;
2200 tree super_interface = lookup_interface (super_name);
2202 if (!super_interface)
2204 /* fatal did not work with 2 args...should fix */
2205 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2206 IDENTIFIER_POINTER (super_name),
2207 IDENTIFIER_POINTER (my_name));
2208 exit (34);
2210 if (super_interface == interface)
2212 fatal ("Circular inheritance in interface declaration for `%s'",
2213 IDENTIFIER_POINTER (super_name));
2215 interface = super_interface;
2216 my_name = CLASS_NAME (interface);
2217 super_name = CLASS_SUPER_NAME (interface);
2219 op1 = CLASS_IVARS (interface);
2220 if (op1)
2222 tree head, tail = objc_copy_list (op1, &head);
2224 /* Prepend super class ivars...make a copy of the list, we
2225 do not want to alter the original. */
2226 TREE_CHAIN (tail) = ivar_chain;
2227 ivar_chain = head;
2230 return ivar_chain;
2233 /* struct <classname> {
2234 struct objc_class *isa;
2236 }; */
2238 static tree
2239 build_private_template (class)
2240 tree class;
2242 tree ivar_context;
2244 if (CLASS_STATIC_TEMPLATE (class))
2246 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2247 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2249 else
2251 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2253 ivar_context = build_ivar_chain (class, 0);
2255 finish_struct (uprivate_record, ivar_context);
2257 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2259 /* mark this record as class template - for class type checking */
2260 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2262 instance_type = groktypename (build_tree_list (build_tree_list (NULLT, uprivate_record),
2263 build1 (INDIRECT_REF, NULLT, NULLT)));
2264 return ivar_context;
2267 /* Begin code generation for protocols... */
2269 /* struct objc_protocol {
2270 char *protocol_name;
2271 struct objc_protocol **protocol_list;
2272 struct objc_method_desc *instance_methods;
2273 struct objc_method_desc *class_methods;
2274 }; */
2276 static tree
2277 build_protocol_template ()
2279 tree decl_specs, field_decl, field_decl_chain;
2280 tree template;
2282 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2284 /* struct objc_class *isa; */
2286 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2287 get_identifier (UTAG_CLASS)));
2288 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
2289 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2290 field_decl_chain = field_decl;
2292 /* char *protocol_name; */
2294 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
2295 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_name"));
2296 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2297 chainon (field_decl_chain, field_decl);
2299 /* struct objc_protocol **protocol_list; */
2301 decl_specs = build_tree_list (NULLT, template);
2302 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
2303 field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
2304 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2305 chainon (field_decl_chain, field_decl);
2307 /* struct objc_method_list *instance_methods; */
2309 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2310 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2311 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
2312 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2313 chainon (field_decl_chain, field_decl);
2315 /* struct objc_method_list *class_methods; */
2317 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2318 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2319 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
2320 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2321 chainon (field_decl_chain, field_decl);
2323 return finish_struct (template, field_decl_chain);
2326 static tree
2327 build_descriptor_table_initializer (type, entries)
2328 tree type;
2329 tree entries;
2331 tree initlist = NULLT;
2335 tree eltlist = NULLT;
2337 eltlist = tree_cons (NULLT, build_selector (METHOD_SEL_NAME (entries)), NULLT);
2338 eltlist = tree_cons (NULLT, add_objc_string (METHOD_ENCODING (entries), meth_var_types), eltlist);
2340 initlist = tree_cons (NULLT, build_constructor (type, nreverse (eltlist)), initlist);
2342 entries = TREE_CHAIN (entries);
2344 while (entries);
2346 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2349 /* struct objc_method_prototype_list {
2350 int count;
2351 struct objc_method_prototype {
2352 SEL name;
2353 char *types;
2354 } list[1];
2355 }; */
2357 static tree
2358 build_method_prototype_list_template (list_type, size)
2359 tree list_type;
2360 int size;
2362 tree objc_ivar_list_record;
2363 tree decl_specs, field_decl, field_decl_chain;
2365 /* generate an unnamed struct definition */
2367 objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
2369 /* int method_count; */
2371 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
2372 field_decl = get_identifier ("method_count");
2374 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2375 field_decl_chain = field_decl;
2377 /* struct objc_method method_list[]; */
2379 decl_specs = build_tree_list (NULLT, list_type);
2380 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2381 build_int_2 (size, 0));
2383 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2384 chainon (field_decl_chain, field_decl);
2386 finish_struct (objc_ivar_list_record, field_decl_chain);
2388 return objc_ivar_list_record;
2391 static tree
2392 build_method_prototype_template ()
2394 tree proto_record;
2395 tree decl_specs, field_decl, field_decl_chain;
2397 proto_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2399 #ifdef OBJC_INT_SELECTORS
2400 /* unsigned int _cmd; */
2401 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
2402 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
2403 field_decl = get_identifier ("_cmd");
2404 #else /* OBJC_INT_SELECTORS */
2405 /* struct objc_selector *_cmd; */
2406 decl_specs = tree_cons (NULLT, xref_tag (RECORD_TYPE,
2407 get_identifier (TAG_SELECTOR)), NULLT);
2408 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
2409 #endif /* OBJC_INT_SELECTORS */
2411 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2412 field_decl_chain = field_decl;
2414 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
2415 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
2416 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2417 chainon (field_decl_chain, field_decl);
2419 finish_struct (proto_record, field_decl_chain);
2421 return proto_record;
2424 /* True if last call to forwarding_offset yielded a register offset */
2425 static int offset_is_register;
2427 static int
2428 forwarding_offset (parm)
2429 tree parm;
2431 int offset_in_bytes;
2433 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2435 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2437 /* ??? Here we assume that the parm address is indexed
2438 off the frame pointer or arg pointer.
2439 If that is not true, we produce meaningless results,
2440 but do not crash. */
2441 if (GET_CODE (addr) == PLUS
2442 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2443 offset_in_bytes = INTVAL (XEXP (addr, 1));
2444 else
2445 offset_in_bytes = 0;
2447 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2448 offset_is_register = 0;
2450 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2452 int regno = REGNO (DECL_INCOMING_RTL (parm));
2453 offset_in_bytes = apply_args_register_offset (regno);
2454 offset_is_register = 1;
2456 else
2457 return 0;
2459 /* This is the case where the parm is passed as an int or double
2460 and it is converted to a char, short or float and stored back
2461 in the parmlist. In this case, describe the parm
2462 with the variable's declared type, and adjust the address
2463 if the least significant bytes (which we are using) are not
2464 the first ones. */
2465 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2466 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2467 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2469 return offset_in_bytes;
2472 static tree
2473 encode_method_prototype (method_decl, func_decl)
2474 tree method_decl;
2475 tree func_decl;
2477 tree parms;
2478 int stack_size, i;
2479 tree user_args;
2480 int max_parm_end = 0;
2481 char buf[40];
2482 tree result;
2484 /* `oneway' and 'bycopy', for remote object are the only method qualifiers */
2485 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2487 /* C type */
2488 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2489 obstack_object_size (&util_obstack),
2490 OBJC_ENCODE_INLINE_DEFS);
2492 /* stack size */
2493 for (parms = DECL_ARGUMENTS (func_decl); parms;
2494 parms = TREE_CHAIN (parms))
2496 int parm_end = (forwarding_offset (parms)
2497 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2498 / BITS_PER_UNIT));
2500 if (!offset_is_register && max_parm_end < parm_end)
2501 max_parm_end = parm_end;
2504 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2506 sprintf (buf, "%d", stack_size);
2507 obstack_grow (&util_obstack, buf, strlen (buf));
2509 user_args = METHOD_SEL_ARGS (method_decl);
2511 /* argument types */
2512 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2513 parms = TREE_CHAIN (parms), i++)
2515 /* process argument qualifiers for user supplied arguments */
2516 if (i > 1)
2518 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2519 user_args = TREE_CHAIN (user_args);
2522 /* type */
2523 encode_type (TREE_TYPE (parms),
2524 obstack_object_size (&util_obstack),
2525 OBJC_ENCODE_INLINE_DEFS);
2527 /* compute offset */
2528 sprintf (buf, "%d", forwarding_offset (parms));
2530 /* indicate register */
2531 if (offset_is_register)
2532 obstack_1grow (&util_obstack, '+');
2534 obstack_grow (&util_obstack, buf, strlen (buf));
2537 obstack_1grow (&util_obstack, '\0');
2538 result = get_identifier (obstack_finish (&util_obstack));
2539 obstack_free (&util_obstack, util_firstobj);
2540 return result;
2543 static tree
2544 generate_descriptor_table (type, name, size, list, proto)
2545 tree type;
2546 char *name;
2547 int size;
2548 tree list;
2549 tree proto;
2551 tree sc_spec, decl_specs, decl, initlist;
2553 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2554 decl_specs = tree_cons (NULLT, type, sc_spec);
2556 decl = start_decl (synth_id_with_class_suffix (name, proto),
2557 decl_specs, 1);
2558 end_temporary_allocation ();
2560 initlist = build_tree_list (NULLT, build_int_2 (size, 0));
2561 initlist = tree_cons (NULLT, list, initlist);
2563 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2564 NULLT);
2566 return decl;
2569 static void
2570 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2571 tree protocol;
2573 static tree objc_method_prototype_template;
2574 tree initlist, chain, method_list_template;
2575 tree cast, variable_length_type;
2576 int size;
2578 if (!objc_method_prototype_template)
2579 objc_method_prototype_template = build_method_prototype_template ();
2581 cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2582 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))), NULLT);
2583 variable_length_type = groktypename (cast);
2585 chain = PROTOCOL_CLS_METHODS (protocol);
2586 if (chain)
2588 size = list_length (chain);
2590 method_list_template
2591 = build_method_prototype_list_template (objc_method_prototype_template,
2592 size);
2594 initlist
2595 = build_descriptor_table_initializer (objc_method_prototype_template,
2596 chain);
2598 UOBJC_CLASS_METHODS_decl
2599 = generate_descriptor_table (method_list_template,
2600 "_OBJC_PROTOCOL_CLASS_METHODS",
2601 size, initlist, protocol);
2602 /* cast! */
2603 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2605 else
2606 UOBJC_CLASS_METHODS_decl = 0;
2608 chain = PROTOCOL_NST_METHODS (protocol);
2609 if (chain)
2611 size = list_length (chain);
2613 method_list_template
2614 = build_method_prototype_list_template (objc_method_prototype_template,
2615 size);
2616 initlist
2617 = build_descriptor_table_initializer (objc_method_prototype_template,
2618 chain);
2620 UOBJC_INSTANCE_METHODS_decl
2621 = generate_descriptor_table (method_list_template,
2622 "_OBJC_PROTOCOL_INSTANCE_METHODS",
2623 size, initlist, protocol);
2624 /* cast! */
2625 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
2627 else
2628 UOBJC_INSTANCE_METHODS_decl = 0;
2631 static tree
2632 build_tmp_function_decl ()
2634 tree decl_specs, expr_decl, parms;
2635 static int xxx = 0;
2636 char buffer[80];
2638 /* struct objc_object *objc_xxx (id, SEL, ...); */
2639 pushlevel (0);
2640 decl_specs = build_tree_list (NULLT, objc_object_reference);
2641 push_parm_decl (build_tree_list (decl_specs,
2642 build1 (INDIRECT_REF, NULLT, NULLT)));
2644 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2645 get_identifier (TAG_SELECTOR)));
2646 expr_decl = build1 (INDIRECT_REF, NULLT, NULLT);
2648 push_parm_decl (build_tree_list (decl_specs, expr_decl));
2649 parms = get_parm_info (0);
2650 poplevel (0, 0, 0);
2652 decl_specs = build_tree_list (NULLT, objc_object_reference);
2653 sprintf (buffer, "__objc_tmp_%x", xxx++);
2654 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULLT);
2655 expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
2657 return define_decl (expr_decl, decl_specs);
2660 static void
2661 hack_method_prototype (nst_methods, tmp_decl)
2662 tree nst_methods;
2663 tree tmp_decl;
2665 tree parms;
2667 /* Hack to avoid problem with static typing of self arg. */
2668 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
2669 start_method_def (nst_methods);
2670 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
2672 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
2673 parms = get_parm_info (0); /* we have a `, ...' */
2674 else
2675 parms = get_parm_info (1); /* place a `void_at_end' */
2677 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
2679 /* Usually called from store_parm_decls -> init_function_start. */
2681 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
2682 current_function_decl = tmp_decl;
2685 /* Code taken from start_function. */
2686 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
2687 /* Promote the value to int before returning it. */
2688 if (TREE_CODE (restype) == INTEGER_TYPE
2689 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
2690 restype = integer_type_node;
2691 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
2694 init_function_start (tmp_decl, "objc-act", 0);
2696 /* Typically called from expand_function_start for function definitions. */
2697 assign_parms (tmp_decl, 0);
2699 /* install return type */
2700 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
2704 static void
2705 generate_protocol_references (plist)
2706 tree plist;
2708 tree lproto;
2710 /* forward declare protocols referenced */
2711 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2713 tree proto = TREE_VALUE (lproto);
2715 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
2716 && PROTOCOL_NAME (proto))
2718 if (! PROTOCOL_FORWARD_DECL (proto))
2719 build_protocol_reference (proto);
2721 if (PROTOCOL_LIST (proto))
2722 generate_protocol_references (PROTOCOL_LIST (proto));
2727 static void
2728 generate_protocols ()
2730 tree p, tmp_decl, encoding;
2731 tree sc_spec, decl_specs, decl;
2732 tree initlist, protocol_name_expr, refs_decl, refs_expr;
2733 tree cast_type2 = 0;
2735 tmp_decl = build_tmp_function_decl ();
2737 if (! objc_protocol_template)
2738 objc_protocol_template = build_protocol_template ();
2740 /* if a protocol was directly referenced, pull in indirect references */
2741 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2742 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2743 generate_protocol_references (PROTOCOL_LIST (p));
2745 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2747 tree nst_methods = PROTOCOL_NST_METHODS (p);
2748 tree cls_methods = PROTOCOL_CLS_METHODS (p);
2750 /* if protocol wasn't referenced, don't generate any code */
2751 if (! PROTOCOL_FORWARD_DECL (p))
2752 continue;
2754 /* Make sure we link in the Protocol class. */
2755 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2757 while (nst_methods)
2759 if (! METHOD_ENCODING (nst_methods))
2761 hack_method_prototype (nst_methods, tmp_decl);
2762 encoding = encode_method_prototype (nst_methods, tmp_decl);
2763 METHOD_ENCODING (nst_methods) = encoding;
2765 nst_methods = TREE_CHAIN (nst_methods);
2768 while (cls_methods)
2770 if (! METHOD_ENCODING (cls_methods))
2772 hack_method_prototype (cls_methods, tmp_decl);
2773 encoding = encode_method_prototype (cls_methods, tmp_decl);
2774 METHOD_ENCODING (cls_methods) = encoding;
2777 cls_methods = TREE_CHAIN (cls_methods);
2779 generate_method_descriptors (p);
2781 if (PROTOCOL_LIST (p))
2782 refs_decl = generate_protocol_list (p);
2783 else
2784 refs_decl = 0;
2786 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
2788 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2789 decl_specs = tree_cons (NULLT, objc_protocol_template, sc_spec);
2791 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
2792 decl_specs, 1);
2793 end_temporary_allocation ();
2795 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2797 if (refs_decl)
2799 if (!cast_type2)
2800 cast_type2
2801 = groktypename (build_tree_list (build_tree_list (NULLT, objc_protocol_template),
2802 build1 (INDIRECT_REF, NULLT,
2803 build1 (INDIRECT_REF, NULLT, NULLT))));
2805 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
2806 TREE_TYPE (refs_expr) = cast_type2;
2808 else
2809 refs_expr = build_int_2 (0, 0);
2811 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
2812 by generate_method_descriptors, which is called above. */
2813 initlist = build_protocol_initializer (TREE_TYPE (decl),
2814 protocol_name_expr, refs_expr,
2815 UOBJC_INSTANCE_METHODS_decl,
2816 UOBJC_CLASS_METHODS_decl);
2817 finish_decl (decl, initlist, NULLT);
2819 /* Mark the decl as used to avoid "defined but not used" warning. */
2820 TREE_USED (decl) = 1;
2824 static tree
2825 build_protocol_initializer (type, protocol_name, protocol_list,
2826 instance_methods, class_methods)
2827 tree type;
2828 tree protocol_name;
2829 tree protocol_list;
2830 tree instance_methods;
2831 tree class_methods;
2833 tree initlist = NULLT, expr;
2834 static tree cast_type = 0;
2836 if (!cast_type)
2837 cast_type
2838 = groktypename (build_tree_list
2839 (build_tree_list (NULLT,
2840 xref_tag (RECORD_TYPE,
2841 get_identifier (UTAG_CLASS))),
2842 build1 (INDIRECT_REF, NULLT, NULLT)));
2844 /* filling the "isa" in with one allows the runtime system to
2845 detect that the version change...should remove before final release */
2847 expr = build_int_2 (PROTOCOL_VERSION, 0);
2848 TREE_TYPE (expr) = cast_type;
2849 initlist = tree_cons (NULLT, expr, initlist);
2850 initlist = tree_cons (NULLT, protocol_name, initlist);
2851 initlist = tree_cons (NULLT, protocol_list, initlist);
2853 if (!instance_methods)
2854 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2855 else
2857 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
2858 initlist = tree_cons (NULLT, expr, initlist);
2860 if (!class_methods)
2861 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2862 else
2864 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
2865 initlist = tree_cons (NULLT, expr, initlist);
2867 return build_constructor (type, nreverse (initlist));
2869 /* end code generation for protocols... */
2871 /* struct objc_category {
2872 char *category_name;
2873 char *class_name;
2874 struct objc_method_list *instance_methods;
2875 struct objc_method_list *class_methods;
2876 struct objc_protocol_list *protocols;
2877 }; */
2879 static void
2880 build_category_template ()
2882 tree decl_specs, field_decl, field_decl_chain;
2884 objc_category_template = start_struct (RECORD_TYPE,
2885 get_identifier (UTAG_CATEGORY));
2886 /* char *category_name; */
2888 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
2889 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
2890 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2891 field_decl_chain = field_decl;
2893 /* char *class_name; */
2895 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
2896 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
2897 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2898 chainon (field_decl_chain, field_decl);
2900 /* struct objc_method_list *instance_methods; */
2902 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2903 get_identifier (UTAG_METHOD_LIST)));
2904 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
2905 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2906 chainon (field_decl_chain, field_decl);
2908 /* struct objc_method_list *class_methods; */
2910 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2911 get_identifier (UTAG_METHOD_LIST)));
2912 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
2913 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2914 chainon (field_decl_chain, field_decl);
2916 /* struct objc_protocol **protocol_list; */
2918 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2919 get_identifier (UTAG_PROTOCOL)));
2920 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
2921 field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
2922 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT)
2924 chainon (field_decl_chain, field_decl);
2926 finish_struct (objc_category_template, field_decl_chain);
2929 /* struct objc_selector {
2930 void *sel_id;
2931 char *sel_type;
2932 }; */
2934 static void
2935 build_selector_template ()
2938 tree decl_specs, field_decl, field_decl_chain;
2940 objc_selector_template
2941 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
2943 /* void *sel_id; */
2945 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_VOID]);
2946 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sel_id"));
2947 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2948 field_decl_chain = field_decl;
2950 /* char *sel_type; */
2952 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
2953 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sel_type"));
2954 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2955 chainon (field_decl_chain, field_decl);
2957 finish_struct (objc_selector_template, field_decl_chain);
2960 /* struct objc_class {
2961 struct objc_class *isa;
2962 struct objc_class *super_class;
2963 char *name;
2964 long version;
2965 long info;
2966 long instance_size;
2967 struct objc_ivar_list *ivars;
2968 struct objc_method_list *methods;
2969 if (flag_next_runtime)
2970 struct objc_cache *cache;
2971 else {
2972 struct sarray *dtable;
2973 struct objc_class *subclass_list;
2974 struct objc_class *sibling_class;
2976 struct objc_protocol_list *protocols;
2977 }; */
2979 static void
2980 build_class_template ()
2982 tree decl_specs, field_decl, field_decl_chain;
2984 objc_class_template = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
2986 /* struct objc_class *isa; */
2988 decl_specs = build_tree_list (NULLT, objc_class_template);
2989 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
2990 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2991 field_decl_chain = field_decl;
2993 /* struct objc_class *super_class; */
2995 decl_specs = build_tree_list (NULLT, objc_class_template);
2996 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
2997 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
2998 chainon (field_decl_chain, field_decl);
3000 /* char *name; */
3002 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
3003 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
3004 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3005 chainon (field_decl_chain, field_decl);
3007 /* long version; */
3009 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
3010 field_decl = get_identifier ("version");
3011 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3012 chainon (field_decl_chain, field_decl);
3014 /* long info; */
3016 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
3017 field_decl = get_identifier ("info");
3018 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3019 chainon (field_decl_chain, field_decl);
3021 /* long instance_size; */
3023 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
3024 field_decl = get_identifier ("instance_size");
3025 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3026 chainon (field_decl_chain, field_decl);
3028 /* struct objc_ivar_list *ivars; */
3030 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3031 get_identifier (UTAG_IVAR_LIST)));
3032 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
3033 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3034 chainon (field_decl_chain, field_decl);
3036 /* struct objc_method_list *methods; */
3038 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3039 get_identifier (UTAG_METHOD_LIST)));
3040 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
3041 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3042 chainon (field_decl_chain, field_decl);
3044 if (flag_next_runtime)
3046 /* struct objc_cache *cache; */
3048 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3049 get_identifier ("objc_cache")));
3050 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
3051 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3052 chainon (field_decl_chain, field_decl);
3054 else
3056 /* struct sarray *dtable; */
3058 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3059 get_identifier ("sarray")));
3060 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("dtable"));
3061 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3062 chainon (field_decl_chain, field_decl);
3064 /* struct objc_class *subclass_list; */
3066 decl_specs = build_tree_list (NULLT, objc_class_template);
3067 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("subclass_list"));
3068 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3069 chainon (field_decl_chain, field_decl);
3071 /* struct objc_class *sibling_class; */
3073 decl_specs = build_tree_list (NULLT, objc_class_template);
3074 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sibling_class"));
3075 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3076 chainon (field_decl_chain, field_decl);
3079 /* struct objc_protocol **protocol_list; */
3081 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3082 get_identifier (UTAG_PROTOCOL)));
3083 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
3084 field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
3085 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3086 chainon (field_decl_chain, field_decl);
3089 finish_struct (objc_class_template, field_decl_chain);
3092 /* Generate appropriate forward declarations for an implementation. */
3094 static void
3095 synth_forward_declarations ()
3097 tree sc_spec, decl_specs, an_id;
3099 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3101 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3103 sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
3104 decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
3105 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3106 TREE_USED (UOBJC_CLASS_decl) = 1;
3108 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3110 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3111 implementation_context);
3113 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3114 TREE_USED (UOBJC_METACLASS_decl) = 1;
3116 /* pre-build the following entities - for speed/convenience. */
3118 an_id = get_identifier ("super_class");
3119 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3120 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3123 static void
3124 error_with_ivar (message, decl, rawdecl)
3125 char *message;
3126 tree decl;
3127 tree rawdecl;
3129 count_error (0);
3131 report_error_function (DECL_SOURCE_FILE (decl));
3133 fprintf (stderr, "%s:%d: ",
3134 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3135 bzero (errbuf, BUFSIZE);
3136 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3139 #define USERTYPE(t) (TREE_CODE (t) == RECORD_TYPE || \
3140 TREE_CODE (t) == UNION_TYPE || \
3141 TREE_CODE (t) == ENUMERAL_TYPE)
3143 static void
3144 check_ivars (inter, imp)
3145 tree inter;
3146 tree imp;
3148 tree intdecls = CLASS_IVARS (inter);
3149 tree impdecls = CLASS_IVARS (imp);
3150 tree rawintdecls = CLASS_RAW_IVARS (inter);
3151 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3153 while (1)
3155 tree t1, t2;
3157 if (intdecls == 0 && impdecls == 0)
3158 break;
3159 if (intdecls == 0 || impdecls == 0)
3161 error ("inconsistent instance variable specification");
3162 break;
3164 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3166 if (!comptypes (t1, t2))
3168 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3170 error_with_ivar ("conflicting instance variable type",
3171 impdecls, rawimpdecls);
3172 error_with_ivar ("previous declaration of",
3173 intdecls, rawintdecls);
3175 else /* both the type and the name don't match */
3177 error ("inconsistent instance variable specification");
3178 break;
3181 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3183 error_with_ivar ("conflicting instance variable name",
3184 impdecls, rawimpdecls);
3185 error_with_ivar ("previous declaration of",
3186 intdecls, rawintdecls);
3188 intdecls = TREE_CHAIN (intdecls);
3189 impdecls = TREE_CHAIN (impdecls);
3190 rawintdecls = TREE_CHAIN (rawintdecls);
3191 rawimpdecls = TREE_CHAIN (rawimpdecls);
3195 /* Set super_type to the data type node for struct objc_super *,
3196 first defining struct objc_super itself.
3197 This needs to be done just once per compilation. */
3199 static tree
3200 build_super_template ()
3202 tree record, decl_specs, field_decl, field_decl_chain;
3204 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3206 /* struct objc_object *self; */
3208 decl_specs = build_tree_list (NULLT, objc_object_reference);
3209 field_decl = get_identifier ("self");
3210 field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
3211 field_decl = grokfield (input_filename, lineno,
3212 field_decl, decl_specs, NULLT);
3213 field_decl_chain = field_decl;
3215 /* struct objc_class *class; */
3217 decl_specs = get_identifier (UTAG_CLASS);
3218 decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
3219 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
3221 field_decl = grokfield (input_filename, lineno,
3222 field_decl, decl_specs, NULLT);
3223 chainon (field_decl_chain, field_decl);
3225 finish_struct (record, field_decl_chain);
3227 /* `struct objc_super *' */
3228 super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
3229 build1 (INDIRECT_REF,
3230 NULLT, NULLT)));
3231 return record;
3234 /* struct objc_ivar {
3235 char *ivar_name;
3236 char *ivar_type;
3237 int ivar_offset;
3238 }; */
3240 static tree
3241 build_ivar_template ()
3243 tree objc_ivar_id, objc_ivar_record;
3244 tree decl_specs, field_decl, field_decl_chain;
3246 objc_ivar_id = get_identifier (UTAG_IVAR);
3247 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3249 /* char *ivar_name; */
3251 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
3252 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
3254 field_decl = grokfield (input_filename, lineno, field_decl,
3255 decl_specs, NULLT);
3256 field_decl_chain = field_decl;
3258 /* char *ivar_type; */
3260 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
3261 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
3263 field_decl = grokfield (input_filename, lineno, field_decl,
3264 decl_specs, NULLT);
3265 chainon (field_decl_chain, field_decl);
3267 /* int ivar_offset; */
3269 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
3270 field_decl = get_identifier ("ivar_offset");
3272 field_decl = grokfield (input_filename, lineno, field_decl,
3273 decl_specs, NULLT);
3274 chainon (field_decl_chain, field_decl);
3276 finish_struct (objc_ivar_record, field_decl_chain);
3278 return objc_ivar_record;
3281 /* struct {
3282 int ivar_count;
3283 struct objc_ivar ivar_list[ivar_count];
3284 }; */
3286 static tree
3287 build_ivar_list_template (list_type, size)
3288 tree list_type;
3289 int size;
3291 tree objc_ivar_list_record;
3292 tree decl_specs, field_decl, field_decl_chain;
3294 objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
3296 /* int ivar_count; */
3298 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
3299 field_decl = get_identifier ("ivar_count");
3301 field_decl = grokfield (input_filename, lineno, field_decl,
3302 decl_specs, NULLT);
3303 field_decl_chain = field_decl;
3305 /* struct objc_ivar ivar_list[]; */
3307 decl_specs = build_tree_list (NULLT, list_type);
3308 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3309 build_int_2 (size, 0));
3311 field_decl = grokfield (input_filename, lineno,
3312 field_decl, decl_specs, NULLT);
3313 chainon (field_decl_chain, field_decl);
3315 finish_struct (objc_ivar_list_record, field_decl_chain);
3317 return objc_ivar_list_record;
3320 /* struct {
3321 int method_next;
3322 int method_count;
3323 struct objc_method method_list[method_count];
3324 }; */
3326 static tree
3327 build_method_list_template (list_type, size)
3328 tree list_type;
3329 int size;
3331 tree objc_ivar_list_record;
3332 tree decl_specs, field_decl, field_decl_chain;
3334 objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
3336 /* int method_next; */
3338 decl_specs = build_tree_list (NULLT,
3339 xref_tag (RECORD_TYPE,
3340 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3341 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_next"));
3342 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3343 field_decl_chain = field_decl;
3345 /* int method_count; */
3347 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
3348 field_decl = get_identifier ("method_count");
3350 field_decl = grokfield (input_filename, lineno,
3351 field_decl, decl_specs, NULLT);
3352 chainon (field_decl_chain, field_decl);
3354 /* struct objc_method method_list[]; */
3356 decl_specs = build_tree_list (NULLT, list_type);
3357 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3358 build_int_2 (size, 0));
3360 field_decl = grokfield (input_filename, lineno,
3361 field_decl, decl_specs, NULLT);
3362 chainon (field_decl_chain, field_decl);
3364 finish_struct (objc_ivar_list_record, field_decl_chain);
3366 return objc_ivar_list_record;
3369 static tree
3370 build_ivar_list_initializer (type, field_decl)
3371 tree type;
3372 tree field_decl;
3374 tree initlist = NULLT;
3378 tree ivar = NULLT;
3380 /* set name */
3381 if (DECL_NAME (field_decl))
3382 ivar = tree_cons (NULLT,
3383 add_objc_string (DECL_NAME (field_decl),
3384 meth_var_names),
3385 ivar);
3386 else
3387 /* unnamed bit-field ivar (yuck). */
3388 ivar = tree_cons (NULLT, build_int_2 (0, 0), ivar);
3390 /* set type */
3391 encode_field_decl (field_decl,
3392 obstack_object_size (&util_obstack),
3393 OBJC_ENCODE_DONT_INLINE_DEFS);
3394 obstack_1grow (&util_obstack, 0); /* null terminate string */
3395 ivar
3396 = tree_cons
3397 (NULLT,
3398 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3399 meth_var_types),
3400 ivar);
3401 obstack_free (&util_obstack, util_firstobj);
3403 /* set offset */
3404 ivar
3405 = tree_cons
3406 (NULLT,
3407 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3408 / BITS_PER_UNIT),
3410 ivar);
3412 initlist = tree_cons (NULLT,
3413 build_constructor (type, nreverse (ivar)),
3414 initlist);
3416 field_decl = TREE_CHAIN (field_decl);
3418 while (field_decl);
3420 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3423 static tree
3424 generate_ivars_list (type, name, size, list)
3425 tree type;
3426 char *name;
3427 int size;
3428 tree list;
3430 tree sc_spec, decl_specs, decl, initlist;
3432 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
3433 decl_specs = tree_cons (NULLT, type, sc_spec);
3435 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3436 decl_specs, 1);
3437 end_temporary_allocation ();
3439 initlist = build_tree_list (NULLT, build_int_2 (size, 0));
3440 initlist = tree_cons (NULLT, list, initlist);
3442 finish_decl (decl,
3443 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3444 NULLT);
3446 return decl;
3449 static void
3450 generate_ivar_lists ()
3452 tree initlist, ivar_list_template, chain;
3453 tree cast, variable_length_type;
3454 int size;
3456 generating_instance_variables = 1;
3458 if (!objc_ivar_template)
3459 objc_ivar_template = build_ivar_template ();
3461 cast
3462 = build_tree_list
3463 (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3464 get_identifier (UTAG_IVAR_LIST))),
3465 NULLT);
3466 variable_length_type = groktypename (cast);
3468 /* only generate class variables for the root of the inheritance
3469 hierarchy since these will be the same for every class */
3471 if (CLASS_SUPER_NAME (implementation_template) == NULLT
3472 && (chain = TYPE_FIELDS (objc_class_template)))
3474 size = list_length (chain);
3476 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3477 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3479 UOBJC_CLASS_VARIABLES_decl
3480 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3481 size, initlist);
3482 /* cast! */
3483 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3485 else
3486 UOBJC_CLASS_VARIABLES_decl = 0;
3488 chain = CLASS_IVARS (implementation_template);
3489 if (chain)
3491 size = list_length (chain);
3492 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3493 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3495 UOBJC_INSTANCE_VARIABLES_decl
3496 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3497 size, initlist);
3498 /* cast! */
3499 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3501 else
3502 UOBJC_INSTANCE_VARIABLES_decl = 0;
3504 generating_instance_variables = 0;
3507 static tree
3508 build_dispatch_table_initializer (type, entries)
3509 tree type;
3510 tree entries;
3512 tree initlist = NULLT;
3516 tree elemlist = NULLT;
3518 elemlist = tree_cons (NULLT, build_selector (METHOD_SEL_NAME (entries)),
3519 NULLT);
3521 elemlist = tree_cons (NULLT, add_objc_string (METHOD_ENCODING (entries),
3522 meth_var_types),
3523 elemlist);
3525 elemlist = tree_cons (NULLT,
3526 build_unary_op (ADDR_EXPR, METHOD_DEFINITION (entries), 1),
3527 elemlist);
3529 initlist = tree_cons (NULLT,
3530 build_constructor (type, nreverse (elemlist)),
3531 initlist);
3533 entries = TREE_CHAIN (entries);
3535 while (entries);
3537 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3540 /* To accomplish method prototyping without generating all kinds of
3541 inane warnings, the definition of the dispatch table entries were
3542 changed from:
3544 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3546 struct objc_method { SEL _cmd; ...; void *_imp; }; */
3548 static tree
3549 build_method_template ()
3551 tree _SLT_record;
3552 tree decl_specs, field_decl, field_decl_chain;
3554 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3556 #ifdef OBJC_INT_SELECTORS
3557 /* unsigned int _cmd; */
3558 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
3559 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
3560 field_decl = get_identifier ("_cmd");
3561 #else /* not OBJC_INT_SELECTORS */
3562 /* struct objc_selector *_cmd; */
3563 decl_specs = tree_cons (NULLT,
3564 xref_tag (RECORD_TYPE,
3565 get_identifier (TAG_SELECTOR)),
3566 NULLT);
3567 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
3568 #endif /* not OBJC_INT_SELECTORS */
3570 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3571 field_decl_chain = field_decl;
3573 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
3574 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
3575 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3576 chainon (field_decl_chain, field_decl);
3578 /* void *_imp; */
3580 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
3581 field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
3582 field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
3583 chainon (field_decl_chain, field_decl);
3585 finish_struct (_SLT_record, field_decl_chain);
3587 return _SLT_record;
3591 static tree
3592 generate_dispatch_table (type, name, size, list)
3593 tree type;
3594 char *name;
3595 int size;
3596 tree list;
3598 tree sc_spec, decl_specs, decl, initlist;
3600 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
3601 decl_specs = tree_cons (NULLT, type, sc_spec);
3603 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3604 decl_specs, 1);
3605 end_temporary_allocation ();
3607 initlist = build_tree_list (NULLT, build_int_2 (0, 0));
3608 initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
3609 initlist = tree_cons (NULLT, list, initlist);
3611 finish_decl (decl,
3612 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3613 NULLT);
3615 return decl;
3618 static void
3619 generate_dispatch_tables ()
3621 tree initlist, chain, method_list_template;
3622 tree cast, variable_length_type;
3623 int size;
3625 if (!objc_method_template)
3626 objc_method_template = build_method_template ();
3628 cast
3629 = build_tree_list
3630 (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
3631 get_identifier (UTAG_METHOD_LIST))),
3632 NULLT);
3633 variable_length_type = groktypename (cast);
3635 chain = CLASS_CLS_METHODS (implementation_context);
3636 if (chain)
3638 size = list_length (chain);
3640 method_list_template = build_method_list_template (objc_method_template, size);
3641 initlist = build_dispatch_table_initializer (objc_method_template, chain);
3643 UOBJC_CLASS_METHODS_decl
3644 = generate_dispatch_table (method_list_template,
3645 ((TREE_CODE (implementation_context)
3646 == CLASS_IMPLEMENTATION_TYPE)
3647 ? "_OBJC_CLASS_METHODS"
3648 : "_OBJC_CATEGORY_CLASS_METHODS"),
3649 size, initlist);
3650 /* cast! */
3651 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3653 else
3654 UOBJC_CLASS_METHODS_decl = 0;
3656 chain = CLASS_NST_METHODS (implementation_context);
3657 if (chain)
3659 size = list_length (chain);
3661 method_list_template = build_method_list_template (objc_method_template, size);
3662 initlist = build_dispatch_table_initializer (objc_method_template, chain);
3664 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
3665 UOBJC_INSTANCE_METHODS_decl
3666 = generate_dispatch_table (method_list_template,
3667 "_OBJC_INSTANCE_METHODS",
3668 size, initlist);
3669 else
3670 /* we have a category */
3671 UOBJC_INSTANCE_METHODS_decl
3672 = generate_dispatch_table (method_list_template,
3673 "_OBJC_CATEGORY_INSTANCE_METHODS",
3674 size, initlist);
3675 /* cast! */
3676 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
3678 else
3679 UOBJC_INSTANCE_METHODS_decl = 0;
3682 static tree
3683 generate_protocol_list (i_or_p)
3684 tree i_or_p;
3686 static tree cast_type = 0;
3687 tree initlist, decl_specs, sc_spec;
3688 tree refs_decl, expr_decl, lproto, e, plist;
3689 int size = 0;
3691 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
3692 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
3693 plist = CLASS_PROTOCOL_LIST (i_or_p);
3694 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
3695 plist = PROTOCOL_LIST (i_or_p);
3696 else
3697 abort ();
3699 if (!cast_type)
3700 cast_type
3701 = groktypename
3702 (build_tree_list
3703 (build_tree_list (NULLT,
3704 xref_tag (RECORD_TYPE,
3705 get_identifier (UTAG_PROTOCOL))),
3706 build1 (INDIRECT_REF, NULLT, NULLT)));
3708 /* compute size */
3709 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3710 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
3711 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
3712 size++;
3714 /* build initializer */
3715 initlist = tree_cons (NULLT, build_int_2 (0, 0), NULLT);
3717 e = build_int_2 (size, 0);
3718 TREE_TYPE (e) = cast_type;
3719 initlist = tree_cons (NULLT, e, initlist);
3721 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3723 tree pval = TREE_VALUE (lproto);
3725 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
3726 && PROTOCOL_FORWARD_DECL (pval))
3728 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
3729 initlist = tree_cons (NULLT, e, initlist);
3733 /* static struct objc_protocol *refs[n]; */
3735 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
3736 decl_specs = tree_cons (NULLT, xref_tag (RECORD_TYPE,
3737 get_identifier (UTAG_PROTOCOL)),
3738 sc_spec);
3740 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
3741 expr_decl = build_nt (ARRAY_REF,
3742 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
3743 i_or_p),
3744 build_int_2 (size + 2, 0));
3745 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
3746 expr_decl = build_nt (ARRAY_REF,
3747 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
3748 i_or_p),
3749 build_int_2 (size + 2, 0));
3750 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
3751 expr_decl = build_nt (ARRAY_REF,
3752 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
3753 i_or_p),
3754 build_int_2 (size + 2, 0));
3756 expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
3758 refs_decl = start_decl (expr_decl, decl_specs, 1);
3759 end_temporary_allocation ();
3761 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
3762 nreverse (initlist)),
3763 NULLT);
3765 return refs_decl;
3768 static tree
3769 build_category_initializer (type, cat_name, class_name,
3770 instance_methods, class_methods, protocol_list)
3771 tree type;
3772 tree cat_name;
3773 tree class_name;
3774 tree instance_methods;
3775 tree class_methods;
3776 tree protocol_list;
3778 tree initlist = NULLT, expr;
3780 initlist = tree_cons (NULLT, cat_name, initlist);
3781 initlist = tree_cons (NULLT, class_name, initlist);
3783 if (!instance_methods)
3784 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3785 else
3787 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3788 initlist = tree_cons (NULLT, expr, initlist);
3790 if (!class_methods)
3791 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3792 else
3794 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3795 initlist = tree_cons (NULLT, expr, initlist);
3798 /* protocol_list = */
3799 if (!protocol_list)
3800 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3801 else
3803 static tree cast_type2;
3805 if (!cast_type2)
3806 cast_type2
3807 = groktypename
3808 (build_tree_list
3809 (build_tree_list (NULLT,
3810 xref_tag (RECORD_TYPE,
3811 get_identifier (UTAG_PROTOCOL))),
3812 build1 (INDIRECT_REF, NULLT,
3813 build1 (INDIRECT_REF, NULLT, NULLT))));
3815 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
3816 TREE_TYPE (expr) = cast_type2;
3817 initlist = tree_cons (NULLT, expr, initlist);
3820 return build_constructor (type, nreverse (initlist));
3823 /* struct objc_class {
3824 struct objc_class *isa;
3825 struct objc_class *super_class;
3826 char *name;
3827 long version;
3828 long info;
3829 long instance_size;
3830 struct objc_ivar_list *ivars;
3831 struct objc_method_list *methods;
3832 if (flag_next_runtime)
3833 struct objc_cache *cache;
3834 else {
3835 struct sarray *dtable;
3836 struct objc_class *subclass_list;
3837 struct objc_class *sibling_class;
3839 struct objc_protocol_list *protocols;
3840 }; */
3842 static tree
3843 build_shared_structure_initializer (type, isa, super, name, size, status,
3844 dispatch_table, ivar_list, protocol_list)
3845 tree type;
3846 tree isa;
3847 tree super;
3848 tree name;
3849 tree size;
3850 int status;
3851 tree dispatch_table;
3852 tree ivar_list;
3853 tree protocol_list;
3855 tree initlist = NULLT, expr;
3857 /* isa = */
3858 initlist = tree_cons (NULLT, isa, initlist);
3860 /* super_class = */
3861 initlist = tree_cons (NULLT, super, initlist);
3863 /* name = */
3864 initlist = tree_cons (NULLT, default_conversion (name), initlist);
3866 /* version = */
3867 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3869 /* info = */
3870 initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
3872 /* instance_size = */
3873 initlist = tree_cons (NULLT, size, initlist);
3875 /* objc_ivar_list = */
3876 if (!ivar_list)
3877 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3878 else
3880 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
3881 initlist = tree_cons (NULLT, expr, initlist);
3884 /* objc_method_list = */
3885 if (!dispatch_table)
3886 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3887 else
3889 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
3890 initlist = tree_cons (NULLT, expr, initlist);
3893 if (flag_next_runtime)
3894 /* method_cache = */
3895 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3896 else
3898 /* dtable = */
3899 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3901 /* subclass_list = */
3902 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3904 /* sibling_class = */
3905 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3908 /* protocol_list = */
3909 if (! protocol_list)
3910 initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
3911 else
3913 static tree cast_type2;
3915 if (!cast_type2)
3916 cast_type2
3917 = groktypename
3918 (build_tree_list
3919 (build_tree_list (NULLT,
3920 xref_tag (RECORD_TYPE,
3921 get_identifier (UTAG_PROTOCOL))),
3922 build1 (INDIRECT_REF, NULLT,
3923 build1 (INDIRECT_REF, NULLT, NULLT))));
3925 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
3926 TREE_TYPE (expr) = cast_type2;
3927 initlist = tree_cons (NULLT, expr, initlist);
3930 return build_constructor (type, nreverse (initlist));
3933 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
3934 static void
3935 generate_category (cat)
3936 tree cat;
3938 tree sc_spec, decl_specs, decl;
3939 tree initlist, cat_name_expr, class_name_expr;
3940 tree protocol_decl, category;
3942 add_class_reference (CLASS_NAME (cat));
3943 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
3945 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
3947 category = CLASS_CATEGORY_LIST (implementation_template);
3949 /* find the category interface from the class it is associated with */
3950 while (category)
3952 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
3953 break;
3954 category = CLASS_CATEGORY_LIST (category);
3957 if (category && CLASS_PROTOCOL_LIST (category))
3959 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
3960 protocol_decl = generate_protocol_list (category);
3962 else
3963 protocol_decl = 0;
3965 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
3966 decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
3968 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
3969 implementation_context),
3970 decl_specs, 1);
3971 end_temporary_allocation ();
3973 initlist = build_category_initializer (TREE_TYPE (decl),
3974 cat_name_expr, class_name_expr,
3975 UOBJC_INSTANCE_METHODS_decl,
3976 UOBJC_CLASS_METHODS_decl,
3977 protocol_decl);
3979 TREE_USED (decl) = 1;
3980 finish_decl (decl, initlist, NULLT);
3983 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
3984 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
3986 static void
3987 generate_shared_structures ()
3989 tree sc_spec, decl_specs, decl;
3990 tree name_expr, super_expr, root_expr;
3991 tree my_root_id = NULLT, my_super_id = NULLT;
3992 tree cast_type, initlist, protocol_decl;
3994 my_super_id = CLASS_SUPER_NAME (implementation_template);
3995 if (my_super_id)
3997 add_class_reference (my_super_id);
3999 /* Compute "my_root_id" - this is required for code generation.
4000 the "isa" for all meta class structures points to the root of
4001 the inheritance hierarchy (e.g. "__Object")... */
4002 my_root_id = my_super_id;
4005 tree my_root_int = lookup_interface (my_root_id);
4007 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4008 my_root_id = CLASS_SUPER_NAME (my_root_int);
4009 else
4010 break;
4012 while (1);
4014 else /* no super class */
4016 my_root_id = CLASS_NAME (implementation_template);
4019 cast_type
4020 = groktypename (build_tree_list (build_tree_list (NULLT,
4021 objc_class_template),
4022 build1 (INDIRECT_REF, NULLT, NULLT)));
4024 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4025 class_names);
4027 /* install class `isa' and `super' pointers at runtime */
4028 if (my_super_id)
4030 super_expr = add_objc_string (my_super_id, class_names);
4031 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4033 else
4034 super_expr = build_int_2 (0, 0);
4036 root_expr = add_objc_string (my_root_id, class_names);
4037 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4039 if (CLASS_PROTOCOL_LIST (implementation_template))
4041 generate_protocol_references (CLASS_PROTOCOL_LIST (implementation_template));
4042 protocol_decl = generate_protocol_list (implementation_template);
4044 else
4045 protocol_decl = 0;
4047 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4049 sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
4050 decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
4052 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1);
4053 end_temporary_allocation ();
4055 initlist
4056 = build_shared_structure_initializer
4057 (TREE_TYPE (decl),
4058 root_expr, super_expr, name_expr,
4059 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4060 / BITS_PER_UNIT),
4062 2 /*CLS_META*/,
4063 UOBJC_CLASS_METHODS_decl,
4064 UOBJC_CLASS_VARIABLES_decl,
4065 protocol_decl);
4067 finish_decl (decl, initlist, NULLT);
4069 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4071 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1);
4072 end_temporary_allocation ();
4074 initlist
4075 = build_shared_structure_initializer
4076 (TREE_TYPE (decl),
4077 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4078 super_expr, name_expr,
4079 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4080 / BITS_PER_UNIT),
4082 1 /*CLS_FACTORY*/,
4083 UOBJC_INSTANCE_METHODS_decl,
4084 UOBJC_INSTANCE_VARIABLES_decl,
4085 protocol_decl);
4087 finish_decl (decl, initlist, NULLT);
4090 static tree
4091 synth_id_with_class_suffix (preamble, ctxt)
4092 char *preamble;
4093 tree ctxt;
4095 char *string;
4096 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4097 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4099 char *class_name
4100 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4101 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4102 sprintf (string, "%s_%s", preamble,
4103 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4105 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4106 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4108 /* we have a category */
4109 char *class_name
4110 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4111 char *class_super_name
4112 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4113 string = (char *) alloca (strlen (preamble)
4114 + strlen (class_name)
4115 + strlen (class_super_name)
4116 + 3);
4117 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4119 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4121 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4122 string = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4123 sprintf (string, "%s_%s", preamble, protocol_name);
4125 return get_identifier (string);
4128 static int
4129 is_objc_type_qualifier (node)
4130 tree node;
4132 return (TREE_CODE (node) == IDENTIFIER_NODE
4133 && (node == ridpointers [(int) RID_CONST]
4134 || node == ridpointers [(int) RID_VOLATILE]
4135 || node == ridpointers [(int) RID_IN]
4136 || node == ridpointers [(int) RID_OUT]
4137 || node == ridpointers [(int) RID_INOUT]
4138 || node == ridpointers [(int) RID_BYCOPY]
4139 || node == ridpointers [(int) RID_ONEWAY]));
4142 /* If type is empty or only type qualifiers are present, add default
4143 type of id (otherwise grokdeclarator will default to int). */
4145 static tree
4146 adjust_type_for_id_default (type)
4147 tree type;
4149 tree declspecs, chain;
4151 if (!type)
4152 return build_tree_list (build_tree_list (NULLT, objc_object_reference),
4153 build1 (INDIRECT_REF, NULLT, NULLT));
4155 declspecs = TREE_PURPOSE (type);
4157 /* Determine if a typespec is present. */
4158 for (chain = declspecs;
4159 chain;
4160 chain = TREE_CHAIN (chain))
4162 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4163 return type;
4166 return build_tree_list (tree_cons (NULLT, objc_object_reference, declspecs),
4167 build1 (INDIRECT_REF, NULLT, NULLT));
4170 /* usage:
4171 keyworddecl:
4172 selector ':' '(' typename ')' identifier
4174 purpose:
4175 transform an Objective-C keyword argument into
4176 the C equivalent parameter declarator.
4178 in: key_name, an "identifier_node" (optional).
4179 arg_type, a "tree_list" (optional).
4180 arg_name, an "identifier_node".
4182 note: it would be really nice to strongly type the preceding
4183 arguments in the function prototype; however, then i
4184 could not use the "accessor" macros defined in "tree.h".
4186 out: an instance of "keyword_decl". */
4188 tree
4189 build_keyword_decl (key_name, arg_type, arg_name)
4190 tree key_name;
4191 tree arg_type;
4192 tree arg_name;
4194 tree keyword_decl;
4196 /* if no type is specified, default to "id" */
4197 arg_type = adjust_type_for_id_default (arg_type);
4199 keyword_decl = make_node (KEYWORD_DECL);
4201 TREE_TYPE (keyword_decl) = arg_type;
4202 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4203 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4205 return keyword_decl;
4208 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4209 static tree
4210 build_keyword_selector (selector)
4211 tree selector;
4213 int len = 0;
4214 tree key_chain, key_name;
4215 char *buf;
4217 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4219 if (TREE_CODE (selector) == KEYWORD_DECL)
4220 key_name = KEYWORD_KEY_NAME (key_chain);
4221 else if (TREE_CODE (selector) == TREE_LIST)
4222 key_name = TREE_PURPOSE (key_chain);
4224 if (key_name)
4225 len += IDENTIFIER_LENGTH (key_name) + 1;
4226 else /* just a ':' arg */
4227 len++;
4229 buf = (char *)alloca (len + 1);
4230 bzero (buf, len + 1);
4232 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4234 if (TREE_CODE (selector) == KEYWORD_DECL)
4235 key_name = KEYWORD_KEY_NAME (key_chain);
4236 else if (TREE_CODE (selector) == TREE_LIST)
4237 key_name = TREE_PURPOSE (key_chain);
4239 if (key_name)
4240 strcat (buf, IDENTIFIER_POINTER (key_name));
4241 strcat (buf, ":");
4243 return get_identifier (buf);
4246 /* used for declarations and definitions */
4248 tree
4249 build_method_decl (code, ret_type, selector, add_args)
4250 enum tree_code code;
4251 tree ret_type;
4252 tree selector;
4253 tree add_args;
4255 tree method_decl;
4257 /* if no type is specified, default to "id" */
4258 ret_type = adjust_type_for_id_default (ret_type);
4260 method_decl = make_node (code);
4261 TREE_TYPE (method_decl) = ret_type;
4263 /* If we have a keyword selector, create an identifier_node that
4264 represents the full selector name (`:' included)... */
4265 if (TREE_CODE (selector) == KEYWORD_DECL)
4267 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4268 METHOD_SEL_ARGS (method_decl) = selector;
4269 METHOD_ADD_ARGS (method_decl) = add_args;
4271 else
4273 METHOD_SEL_NAME (method_decl) = selector;
4274 METHOD_SEL_ARGS (method_decl) = NULLT;
4275 METHOD_ADD_ARGS (method_decl) = NULLT;
4278 return method_decl;
4281 #define METHOD_DEF 0
4282 #define METHOD_REF 1
4284 /* Used by `build_message_expr' and `comp_method_types'. Return an
4285 argument list for method METH. CONTEXT is either METHOD_DEF or
4286 METHOD_REF, saying whether we are trying to define a method or call
4287 one. SUPERFLAG says this is for a send to super; this makes a
4288 difference for the NeXT calling sequence in which the lookup and
4289 the method call are done together. */
4291 static tree
4292 get_arg_type_list (meth, context, superflag)
4293 tree meth;
4294 int context;
4295 int superflag;
4297 tree arglist, akey;
4299 /* receiver type */
4300 if (flag_next_runtime && superflag)
4301 arglist = build_tree_list (NULLT, super_type);
4302 else if (context == METHOD_DEF)
4303 arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
4304 else
4305 arglist = build_tree_list (NULLT, id_type);
4307 /* selector type - will eventually change to `int' */
4308 chainon (arglist, build_tree_list (NULLT, selector_type));
4310 /* build a list of argument types */
4311 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4313 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4314 chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
4317 if (METHOD_ADD_ARGS (meth) == (tree)1)
4318 /* We have a `, ...' immediately following the selector,
4319 finalize the arglist...simulate get_parm_info (0). */
4321 else if (METHOD_ADD_ARGS (meth))
4323 /* we have a variable length selector */
4324 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4325 chainon (arglist, add_arg_list);
4327 else
4328 /* finalize the arglist...simulate get_parm_info (1) */
4329 chainon (arglist, build_tree_list (NULLT, void_type_node));
4331 return arglist;
4334 static tree
4335 check_duplicates (hsh)
4336 hash hsh;
4338 tree meth = NULLT;
4340 if (hsh)
4342 meth = hsh->key;
4344 if (hsh->list)
4346 /* we have two methods with the same name and different types */
4347 attr loop;
4348 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4350 warning ("multiple declarations for method `%s'",
4351 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4353 warn_with_method ("using", type, meth);
4354 for (loop = hsh->list; loop; loop = loop->next)
4355 warn_with_method ("also found", type, loop->value);
4358 return meth;
4361 /* If RECEIVER is a class reference, return the identifier node for the
4362 referenced class. RECEIVER is created by get_class_reference, so we
4363 check the exact form created depending on which runtimes are used. */
4365 static tree
4366 receiver_is_class_object (receiver)
4367 tree receiver;
4369 tree chain, exp, arg;
4370 if (flag_next_runtime)
4372 /* The receiver is a variable created by build_class_reference_decl. */
4373 if (TREE_CODE (receiver) == VAR_DECL
4374 && TREE_TYPE (receiver) == objc_class_type)
4375 /* Look up the identifier. */
4376 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4377 if (TREE_PURPOSE (chain) == receiver)
4378 return TREE_VALUE (chain);
4380 else
4382 /* The receiver is a function call that returns an id. Check if
4383 it is a call to objc_getClass, if so, pick up the class name. */
4384 if ((exp = TREE_OPERAND (receiver, 0))
4385 && TREE_CODE (exp) == ADDR_EXPR
4386 && (exp = TREE_OPERAND (exp, 0))
4387 && TREE_CODE (exp) == FUNCTION_DECL
4388 && exp == objc_get_class_decl
4389 /* we have a call to objc_getClass! */
4390 && (arg = TREE_OPERAND (receiver, 1))
4391 && TREE_CODE (arg) == TREE_LIST
4392 && (arg = TREE_VALUE (arg)))
4394 STRIP_NOPS (arg);
4395 if (TREE_CODE (arg) == ADDR_EXPR
4396 && (arg = TREE_OPERAND (arg, 0))
4397 && TREE_CODE (arg) == STRING_CST)
4398 /* finally, we have the class name */
4399 return get_identifier (TREE_STRING_POINTER (arg));
4402 return 0;
4405 /* If we are currently building a message expr, this holds
4406 the identifier of the selector of the message. This is
4407 used when printing warnings about argument mismatches. */
4409 static tree building_objc_message_expr = 0;
4411 tree
4412 maybe_building_objc_message_expr ()
4414 return building_objc_message_expr;
4417 /* Construct an expression for sending a message.
4418 MESS has the object to send to in TREE_PURPOSE
4419 and the argument list (including selector) in TREE_VALUE.
4421 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4422 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4424 tree
4425 build_message_expr (mess)
4426 tree mess;
4428 tree receiver = TREE_PURPOSE (mess);
4429 tree selector, self_object;
4430 tree rtype, sel_name;
4431 tree args = TREE_VALUE (mess);
4432 tree method_params = NULLT;
4433 tree method_prototype = NULLT;
4434 tree retval;
4435 int statically_typed = 0, statically_allocated = 0;
4436 tree class_ident = 0;
4438 /* 1 if this is sending to the superclass. */
4439 int super;
4441 if (!doing_objc_thang)
4442 objc_fatal ();
4444 if (TREE_CODE (receiver) == ERROR_MARK)
4445 return error_mark_node;
4447 /* determine receiver type */
4448 rtype = TREE_TYPE (receiver);
4449 super = IS_SUPER (rtype);
4451 if (! super)
4453 if (TREE_STATIC_TEMPLATE (rtype))
4454 statically_allocated = 1;
4455 else if (TREE_CODE (rtype) == POINTER_TYPE
4456 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4457 statically_typed = 1;
4458 else if ((flag_next_runtime
4459 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4460 && (class_ident = receiver_is_class_object (receiver)))
4462 else if (! IS_ID (rtype)
4463 /* Allow any type that matches objc_class_type. */
4464 && ! comptypes (rtype, objc_class_type))
4466 bzero (errbuf, BUFSIZE);
4467 warning ("invalid receiver type `%s'",
4468 gen_declaration (rtype, errbuf));
4470 if (statically_allocated)
4471 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4473 /* Don't evaluate the receiver twice. */
4474 receiver = save_expr (receiver);
4475 self_object = receiver;
4477 else
4478 /* If sending to `super', use current self as the object. */
4479 self_object = self_decl;
4481 /* Obtain the full selector name. */
4483 if (TREE_CODE (args) == IDENTIFIER_NODE)
4484 /* a unary selector */
4485 sel_name = args;
4486 else if (TREE_CODE (args) == TREE_LIST)
4487 sel_name = build_keyword_selector (args);
4489 /* Build the parameter list to give to the method. */
4491 method_params = NULLT;
4492 if (TREE_CODE (args) == TREE_LIST)
4494 tree chain = args, prev = NULLT;
4496 /* We have a keyword selector--check for comma expressions. */
4497 while (chain)
4499 tree element = TREE_VALUE (chain);
4501 /* We have a comma expression, must collapse... */
4502 if (TREE_CODE (element) == TREE_LIST)
4504 if (prev)
4505 TREE_CHAIN (prev) = element;
4506 else
4507 args = element;
4509 prev = chain;
4510 chain = TREE_CHAIN (chain);
4512 method_params = args;
4515 /* Determine operation return type. */
4517 if (IS_SUPER (rtype))
4519 tree iface;
4521 if (CLASS_SUPER_NAME (implementation_template))
4523 iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4525 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4526 method_prototype = lookup_instance_method_static (iface, sel_name);
4527 else
4528 method_prototype = lookup_class_method_static (iface, sel_name);
4530 if (iface && !method_prototype)
4531 warning ("`%s' does not respond to `%s'",
4532 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4533 IDENTIFIER_POINTER (sel_name));
4535 else
4537 error ("no super class declared in interface for `%s'",
4538 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4539 return error_mark_node;
4543 else if (statically_allocated)
4545 tree ctype = TREE_TYPE (rtype);
4546 tree iface = lookup_interface (TYPE_NAME (rtype));
4548 if (iface)
4549 method_prototype = lookup_instance_method_static (iface, sel_name);
4551 /* NEW!!! */
4552 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4553 method_prototype
4554 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4555 sel_name, 0);
4557 if (!method_prototype)
4558 warning ("`%s' does not respond to `%s'",
4559 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
4560 IDENTIFIER_POINTER (sel_name));
4562 else if (statically_typed)
4564 tree ctype = TREE_TYPE (rtype);
4566 /* `self' is now statically_typed...all methods should be visible
4567 within the context of the implementation... */
4568 if (implementation_context
4569 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
4571 method_prototype = lookup_instance_method_static (implementation_template, sel_name);
4573 /* NEW!!! */
4574 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4575 method_prototype
4576 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4577 sel_name, 0);
4579 if (! method_prototype
4580 && implementation_template != implementation_context)
4581 /* the method is not published in the interface...check locally */
4582 method_prototype
4583 = lookup_method (CLASS_NST_METHODS (implementation_context),
4584 sel_name);
4586 else
4588 tree iface;
4590 if ((iface = lookup_interface (TYPE_NAME (ctype))))
4591 method_prototype = lookup_instance_method_static (iface, sel_name);
4593 if (! method_prototype)
4595 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
4596 if (protocol_list)
4597 method_prototype
4598 = lookup_method_in_protocol_list (protocol_list, sel_name, 0);
4602 if (!method_prototype)
4603 warning ("`%s' does not respond to `%s'",
4604 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
4605 IDENTIFIER_POINTER (sel_name));
4607 else if (class_ident)
4609 if (implementation_context
4610 && CLASS_NAME (implementation_context) == class_ident)
4612 method_prototype
4613 = lookup_class_method_static (implementation_template, sel_name);
4615 if (!method_prototype
4616 && implementation_template != implementation_context)
4617 /* the method is not published in the interface...check locally */
4618 method_prototype
4619 = lookup_method (CLASS_CLS_METHODS (implementation_context),
4620 sel_name);
4622 else
4624 tree iface;
4626 if ((iface = lookup_interface (class_ident)))
4627 method_prototype = lookup_class_method_static (iface, sel_name);
4630 if (!method_prototype)
4632 warning ("cannot find class (factory) method.");
4633 warning ("return type for `%s' defaults to id",
4634 IDENTIFIER_POINTER (sel_name));
4637 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
4639 /* An anonymous object that has been qualified with a protocol. */
4641 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
4643 method_prototype = lookup_method_in_protocol_list (protocol_list,
4644 sel_name, 0);
4646 if (!method_prototype)
4648 hash hsh;
4650 warning ("method `%s' not implemented by protocol.",
4651 IDENTIFIER_POINTER (sel_name));
4653 /* try and find the method signiture in the global pools! */
4655 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
4656 hsh = hash_lookup (cls_method_hash_list, sel_name);
4658 if (!(method_prototype = check_duplicates (hsh)))
4659 warning ("return type defaults to id");
4662 else
4664 hash hsh;
4666 /* we think we have an instance...loophole: extern id Object; */
4667 hsh = hash_lookup (nst_method_hash_list, sel_name);
4668 if (!hsh)
4669 /* for various loopholes...like sending messages to self in a
4670 factory context... */
4671 hsh = hash_lookup (cls_method_hash_list, sel_name);
4673 method_prototype = check_duplicates (hsh);
4674 if (!method_prototype)
4676 warning ("cannot find method.");
4677 warning ("return type for `%s' defaults to id",
4678 IDENTIFIER_POINTER (sel_name));
4682 /* Save the selector name for printing error messages. */
4683 building_objc_message_expr = sel_name;
4685 /* Build the parameters list for looking up the method.
4686 These are the object itself and the selector. */
4688 if (flag_typed_selectors)
4689 selector = build_typed_selector_reference (sel_name, method_prototype);
4690 else
4691 selector = build_selector_reference (sel_name);
4693 retval = build_objc_method_call (super, method_prototype,
4694 receiver, self_object,
4695 selector, method_params);
4697 building_objc_message_expr = 0;
4699 return retval;
4702 /* Build a tree expression to send OBJECT the operation SELECTOR,
4703 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
4704 assuming the method has prototype METHOD_PROTOTYPE.
4705 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
4706 Use METHOD_PARAMS as list of args to pass to the method.
4707 If SUPER_FLAG is nonzero, we look up the superclass's method. */
4709 static tree
4710 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
4711 selector, method_params)
4712 int super_flag;
4713 tree method_prototype, lookup_object, object, selector, method_params;
4715 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
4716 tree rcv_p = (super_flag
4717 ? build_pointer_type (xref_tag (RECORD_TYPE,
4718 get_identifier (TAG_SUPER)))
4719 : id_type);
4721 if (flag_next_runtime)
4723 if (! method_prototype)
4725 method_params = tree_cons (NULLT, lookup_object,
4726 tree_cons (NULLT, selector,
4727 method_params));
4728 assemble_external (sender);
4729 return build_function_call (sender, method_params);
4731 else
4733 /* This is a real kludge, but it is used only for the Next.
4734 Clobber the data type of SENDER temporarily to accept
4735 all the arguments for this operation, and to return
4736 whatever this operation returns. */
4737 tree arglist = NULLT;
4738 tree retval;
4740 /* Save the proper contents of SENDER's data type. */
4741 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
4742 tree savret = TREE_TYPE (TREE_TYPE (sender));
4744 /* Install this method's argument types. */
4745 arglist = get_arg_type_list (method_prototype, METHOD_REF,
4746 super_flag);
4747 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
4749 /* Install this method's return type. */
4750 TREE_TYPE (TREE_TYPE (sender))
4751 = groktypename (TREE_TYPE (method_prototype));
4753 /* Call SENDER with all the parameters. This will do type
4754 checking using the arg types for this method. */
4755 method_params = tree_cons (NULLT, lookup_object,
4756 tree_cons (NULLT, selector,
4757 method_params));
4758 assemble_external (sender);
4759 retval = build_function_call (sender, method_params);
4761 /* Restore SENDER's return/argument types. */
4762 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
4763 TREE_TYPE (TREE_TYPE (sender)) = savret;
4764 return retval;
4767 else
4769 /* This is the portable way.
4770 First call the lookup function to get a pointer to the method,
4771 then cast the pointer, then call it with the method arguments. */
4772 tree method;
4774 /* Avoid trouble since we may evaluate each of these twice. */
4775 object = save_expr (object);
4776 selector = save_expr (selector);
4778 lookup_object = build_c_cast (rcv_p, lookup_object); /* cast! */
4780 assemble_external (sender);
4781 method
4782 = build_function_call (sender,
4783 tree_cons (NULLT, lookup_object,
4784 tree_cons (NULLT, selector, NULLT)));
4786 /* If we have a method prototype, construct the data type this
4787 method needs, and cast what we got from SENDER into a pointer
4788 to that type. */
4789 if (method_prototype)
4791 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
4792 super_flag);
4793 tree valtype = groktypename (TREE_TYPE (method_prototype));
4794 tree fake_function_type = build_function_type (valtype, arglist);
4795 TREE_TYPE (method) = build_pointer_type (fake_function_type);
4797 else
4798 TREE_TYPE (method)
4799 = build_pointer_type (build_function_type (ptr_type_node, NULLT));
4801 /* Pass the object to the method. */
4802 assemble_external (method);
4803 return build_function_call (method,
4804 tree_cons (NULLT, object,
4805 tree_cons (NULLT, selector,
4806 method_params)));
4810 static void
4811 build_protocol_reference (p)
4812 tree p;
4814 tree decl, ident, ptype;
4815 struct obstack *save_current_obstack = current_obstack;
4816 struct obstack *save_rtl_obstack = rtl_obstack;
4818 rtl_obstack = current_obstack = &permanent_obstack;
4820 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
4822 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
4823 ptype
4824 = groktypename (build_tree_list (build_tree_list (NULLT,
4825 objc_protocol_template),
4826 NULLT));
4828 if (IDENTIFIER_GLOBAL_VALUE (ident))
4829 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
4830 else
4832 decl = build_decl (VAR_DECL, ident, ptype);
4833 DECL_EXTERNAL (decl) = 1;
4834 TREE_PUBLIC (decl) = 1;
4835 TREE_USED (decl) = 1;
4837 /* usually called from `rest_of_decl_compilation' */
4838 make_decl_rtl (decl, 0, 1);
4839 /* our `extended/custom' pushdecl in c-decl.c */
4840 pushdecl_top_level (decl);
4842 current_obstack = save_current_obstack;
4843 rtl_obstack = save_rtl_obstack;
4845 PROTOCOL_FORWARD_DECL (p) = decl;
4848 tree
4849 build_protocol_expr (protoname)
4850 tree protoname;
4852 tree expr;
4853 tree p;
4855 if (!doing_objc_thang)
4856 objc_fatal ();
4858 p = lookup_protocol (protoname);
4860 if (!p)
4862 error ("Cannot find protocol declaration for `%s'",
4863 IDENTIFIER_POINTER (protoname));
4864 return error_mark_node;
4867 if (!PROTOCOL_FORWARD_DECL (p))
4868 build_protocol_reference (p);
4870 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
4872 TREE_TYPE (expr) = protocol_type;
4874 return expr;
4877 tree
4878 build_selector_expr (selnamelist)
4879 tree selnamelist;
4881 tree selname;
4883 if (!doing_objc_thang)
4884 objc_fatal ();
4886 /* obtain the full selector name */
4887 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
4888 /* a unary selector */
4889 selname = selnamelist;
4890 else if (TREE_CODE (selnamelist) == TREE_LIST)
4891 selname = build_keyword_selector (selnamelist);
4893 if (flag_typed_selectors)
4894 return build_typed_selector_reference (selname, 0);
4895 else
4896 return build_selector_reference (selname);
4899 tree
4900 build_encode_expr (type)
4901 tree type;
4903 tree result;
4904 char *string;
4906 if (!doing_objc_thang)
4907 objc_fatal ();
4909 encode_type (type, obstack_object_size (&util_obstack),
4910 OBJC_ENCODE_INLINE_DEFS);
4911 obstack_1grow (&util_obstack, 0); /* null terminate string */
4912 string = obstack_finish (&util_obstack);
4914 /* synthesize a string that represents the encoded struct/union */
4915 result = my_build_string (strlen (string) + 1, string);
4916 obstack_free (&util_obstack, util_firstobj);
4917 return result;
4920 tree
4921 build_ivar_reference (id)
4922 tree id;
4924 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
4926 /* Historically, a class method that produced objects (factory
4927 method) would assign `self' to the instance that it
4928 allocated. This would effectively turn the class method into
4929 an instance method. Following this assignment, the instance
4930 variables could be accessed. That practice, while safe,
4931 violates the simple rule that a class method should not refer
4932 to an instance variable. It's better to catch the cases
4933 where this is done unknowingly than to support the above
4934 paradigm. */
4935 warning ("instance variable `%s' accessed in class method",
4936 IDENTIFIER_POINTER (id));
4937 TREE_TYPE (self_decl) = instance_type; /* cast */
4940 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
4943 #define HASH_ALLOC_LIST_SIZE 170
4944 #define ATTR_ALLOC_LIST_SIZE 170
4945 #define SIZEHASHTABLE 257
4947 /* make positive */
4948 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
4950 static void
4951 hash_init ()
4953 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
4954 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
4956 if (!nst_method_hash_list || !cls_method_hash_list)
4957 perror ("unable to allocate space in objc-tree.c");
4958 else
4960 int i;
4962 for (i = 0; i < SIZEHASHTABLE; i++)
4964 nst_method_hash_list[i] = 0;
4965 cls_method_hash_list[i] = 0;
4970 static void
4971 hash_enter (hashlist, method)
4972 hash *hashlist;
4973 tree method;
4975 static hash hash_alloc_list = 0;
4976 static int hash_alloc_index = 0;
4977 hash obj;
4978 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
4980 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
4982 hash_alloc_index = 0;
4983 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
4984 * HASH_ALLOC_LIST_SIZE);
4985 if (! hash_alloc_list)
4986 perror ("unable to allocate in objc-tree.c");
4988 obj = &hash_alloc_list[hash_alloc_index++];
4989 obj->list = 0;
4990 obj->next = hashlist[slot];
4991 obj->key = method;
4993 hashlist[slot] = obj; /* append to front */
4996 static hash
4997 hash_lookup (hashlist, sel_name)
4998 hash *hashlist;
4999 tree sel_name;
5001 hash target;
5003 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5005 while (target)
5007 if (sel_name == METHOD_SEL_NAME (target->key))
5008 return target;
5010 target = target->next;
5012 return 0;
5015 static void
5016 hash_add_attr (entry, value)
5017 hash entry;
5018 tree value;
5020 static attr attr_alloc_list = 0;
5021 static int attr_alloc_index = 0;
5022 attr obj;
5024 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5026 attr_alloc_index = 0;
5027 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5028 * ATTR_ALLOC_LIST_SIZE);
5029 if (! attr_alloc_list)
5030 perror ("unable to allocate in objc-tree.c");
5032 obj = &attr_alloc_list[attr_alloc_index++];
5033 obj->next = entry->list;
5034 obj->value = value;
5036 entry->list = obj; /* append to front */
5039 static tree
5040 lookup_method (mchain, method)
5041 tree mchain;
5042 tree method;
5044 tree key;
5046 if (TREE_CODE (method) == IDENTIFIER_NODE)
5047 key = method;
5048 else
5049 key = METHOD_SEL_NAME (method);
5051 while (mchain)
5053 if (METHOD_SEL_NAME (mchain) == key)
5054 return mchain;
5055 mchain = TREE_CHAIN (mchain);
5057 return NULLT;
5060 static tree
5061 lookup_instance_method_static (interface, ident)
5062 tree interface;
5063 tree ident;
5065 tree inter = interface;
5066 tree chain = CLASS_NST_METHODS (inter);
5067 tree meth = NULLT;
5071 if ((meth = lookup_method (chain, ident)))
5072 return meth;
5074 if (CLASS_CATEGORY_LIST (inter))
5076 tree category = CLASS_CATEGORY_LIST (inter);
5077 chain = CLASS_NST_METHODS (category);
5081 if ((meth = lookup_method (chain, ident)))
5082 return meth;
5084 /* NEW!!! */
5085 /* Check for instance methods in protocols in categories. */
5086 if (CLASS_PROTOCOL_LIST (category))
5088 if ((meth = (lookup_method_in_protocol_list
5089 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5090 return meth;
5093 if ((category = CLASS_CATEGORY_LIST (category)))
5094 chain = CLASS_NST_METHODS (category);
5096 while (category);
5099 if (CLASS_PROTOCOL_LIST (inter))
5101 if ((meth = (lookup_method_in_protocol_list
5102 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5103 return meth;
5106 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5107 chain = CLASS_NST_METHODS (inter);
5109 while (inter);
5111 return meth;
5114 static tree
5115 lookup_class_method_static (interface, ident)
5116 tree interface;
5117 tree ident;
5119 tree inter = interface;
5120 tree chain = CLASS_CLS_METHODS (inter);
5121 tree meth = NULLT;
5122 tree root_inter = NULLT;
5126 if ((meth = lookup_method (chain, ident)))
5127 return meth;
5129 if (CLASS_CATEGORY_LIST (inter))
5131 tree category = CLASS_CATEGORY_LIST (inter);
5132 chain = CLASS_CLS_METHODS (category);
5136 if ((meth = lookup_method (chain, ident)))
5137 return meth;
5139 /* NEW!!! */
5140 /* Check for class methods in protocols in categories. */
5141 if (CLASS_PROTOCOL_LIST (category))
5143 if ((meth = (lookup_method_in_protocol_list
5144 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5145 return meth;
5148 if ((category = CLASS_CATEGORY_LIST (category)))
5149 chain = CLASS_CLS_METHODS (category);
5151 while (category);
5154 /* NEW!!! */
5155 /* Check for class methods in protocols. */
5156 if (CLASS_PROTOCOL_LIST (inter))
5158 if ((meth = (lookup_method_in_protocol_list
5159 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5160 return meth;
5163 root_inter = inter;
5164 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5165 chain = CLASS_CLS_METHODS (inter);
5167 while (inter);
5169 /* NEW!!! */
5170 /* Simulate wrap around. */
5171 return lookup_instance_method_static (root_inter, ident);
5174 tree
5175 add_class_method (class, method)
5176 tree class;
5177 tree method;
5179 tree mth;
5180 hash hsh;
5182 /* We will have allocated the method parameter declarations on the
5183 maybepermanent_obstack. Need to make sure they stick around! */
5184 preserve_data ();
5186 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5188 /* put method on list in reverse order */
5189 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5190 CLASS_CLS_METHODS (class) = method;
5192 else
5194 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5195 error ("duplicate definition of class method `%s'.",
5196 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5197 else
5199 /* check types, if different complain */
5200 if (!comp_proto_with_proto (method, mth))
5201 error ("duplicate declaration of class method `%s'.",
5202 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5206 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5208 /* install on a global chain */
5209 hash_enter (cls_method_hash_list, method);
5211 else
5213 /* check types, if different add to a list */
5214 if (!comp_proto_with_proto (method, hsh->key))
5215 hash_add_attr (hsh, method);
5217 return method;
5220 tree
5221 add_instance_method (class, method)
5222 tree class;
5223 tree method;
5225 tree mth;
5226 hash hsh;
5228 /* We will have allocated the method parameter declarations on the
5229 maybepermanent_obstack. Need to make sure they stick around! */
5230 preserve_data ();
5232 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5234 /* put method on list in reverse order */
5235 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5236 CLASS_NST_METHODS (class) = method;
5238 else
5240 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5241 error ("duplicate definition of instance method `%s'.",
5242 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5243 else
5245 /* check types, if different complain */
5246 if (!comp_proto_with_proto (method, mth))
5247 error ("duplicate declaration of instance method `%s'.",
5248 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5252 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5254 /* install on a global chain */
5255 hash_enter (nst_method_hash_list, method);
5257 else
5259 /* check types, if different add to a list */
5260 if (!comp_proto_with_proto (method, hsh->key))
5261 hash_add_attr (hsh, method);
5263 return method;
5266 static tree
5267 add_class (class)
5268 tree class;
5270 /* put interfaces on list in reverse order */
5271 TREE_CHAIN (class) = interface_chain;
5272 interface_chain = class;
5273 return interface_chain;
5276 static void
5277 add_category (class, category)
5278 tree class;
5279 tree category;
5281 /* put categories on list in reverse order */
5283 tree cat = CLASS_CATEGORY_LIST (class);
5284 while (cat)
5286 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5287 warning ("duplicate interface declaration for category `%s(%s)'",
5288 IDENTIFIER_POINTER (CLASS_NAME (class)),
5289 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5290 cat = CLASS_CATEGORY_LIST (cat);
5293 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5294 CLASS_CATEGORY_LIST (class) = category;
5297 /* Called after parsing each instance variable declaration. Necessary to
5298 preserve typedefs and implement public/private...
5300 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5302 tree
5303 add_instance_variable (class, public, declarator, declspecs, width)
5304 tree class;
5305 int public;
5306 tree declarator;
5307 tree declspecs;
5308 tree width;
5310 tree field_decl, raw_decl;
5312 raw_decl = build_tree_list (declspecs /*purpose*/, declarator/*value*/);
5314 if (CLASS_RAW_IVARS (class))
5315 chainon (CLASS_RAW_IVARS (class), raw_decl);
5316 else
5317 CLASS_RAW_IVARS (class) = raw_decl;
5319 field_decl = grokfield (input_filename, lineno,
5320 declarator, declspecs, width);
5322 /* overload the public attribute, it is not used for FIELD_DECL's */
5323 switch (public)
5325 case 0:
5326 TREE_PUBLIC (field_decl) = 0;
5327 TREE_PRIVATE (field_decl) = 0;
5328 TREE_PROTECTED (field_decl) = 1;
5329 break;
5331 case 1:
5332 TREE_PUBLIC (field_decl) = 1;
5333 TREE_PRIVATE (field_decl) = 0;
5334 TREE_PROTECTED (field_decl) = 0;
5335 break;
5337 case 2:
5338 TREE_PUBLIC (field_decl) = 0;
5339 TREE_PRIVATE (field_decl) = 1;
5340 TREE_PROTECTED (field_decl) = 0;
5341 break;
5345 if (CLASS_IVARS (class))
5346 chainon (CLASS_IVARS (class), field_decl);
5347 else
5348 CLASS_IVARS (class) = field_decl;
5350 return class;
5353 tree
5354 is_ivar (decl_chain, ident)
5355 tree decl_chain;
5356 tree ident;
5358 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5359 if (DECL_NAME (decl_chain) == ident)
5360 return decl_chain;
5361 return NULL_TREE;
5364 /* True if the ivar is private and we are not in its implementation. */
5367 is_private (decl)
5368 tree decl;
5370 if (TREE_PRIVATE (decl)
5371 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5373 error ("instance variable `%s' is declared private",
5374 IDENTIFIER_POINTER (DECL_NAME (decl)));
5375 return 1;
5377 else
5378 return 0;
5381 /* we have an instance variable reference, check to see if it is public...*/
5384 is_public (expr, identifier)
5385 tree expr;
5386 tree identifier;
5388 tree basetype = TREE_TYPE (expr);
5389 enum tree_code code = TREE_CODE (basetype);
5390 tree decl;
5392 if (code == RECORD_TYPE)
5394 if (TREE_STATIC_TEMPLATE (basetype))
5396 if (!lookup_interface (TYPE_NAME (basetype)))
5398 error ("Cannot find interface declaration for `%s'",
5399 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5400 return 0;
5403 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5405 if (TREE_PUBLIC (decl))
5406 return 1;
5408 /* important difference between the Stepstone translator:
5409 all instance variables should be public within the context
5410 of the implementation. */
5411 if (implementation_context
5412 && (((TREE_CODE (implementation_context)
5413 == CLASS_IMPLEMENTATION_TYPE)
5414 || (TREE_CODE (implementation_context)
5415 == CATEGORY_IMPLEMENTATION_TYPE))
5416 && (CLASS_NAME (implementation_context)
5417 == TYPE_NAME (basetype))))
5418 return ! is_private (decl);
5420 error ("instance variable `%s' is declared %s",
5421 IDENTIFIER_POINTER (identifier),
5422 TREE_PRIVATE (decl) ? "private" : "protected");
5423 return 0;
5426 else if (implementation_context && (basetype == objc_object_reference))
5428 TREE_TYPE (expr) = uprivate_record;
5429 warning ("static access to object of type `id'");
5432 return 1;
5435 /* implement @defs (<classname>) within struct bodies. */
5437 tree
5438 get_class_ivars (interface)
5439 tree interface;
5441 if (!doing_objc_thang)
5442 objc_fatal ();
5444 return build_ivar_chain (interface, 1);
5447 /* make sure all entries in "chain" are also in "list" */
5449 static int
5450 check_methods (chain, list, mtype)
5451 tree chain;
5452 tree list;
5453 int mtype;
5455 int first = 1;
5457 while (chain)
5459 if (!lookup_method (list, chain))
5461 if (first)
5463 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
5464 warning ("incomplete implementation of class `%s'",
5465 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5466 else if (TREE_CODE (implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
5467 warning ("incomplete implementation of category `%s'",
5468 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5469 first = 0;
5471 warning ("method definition for `%c%s' not found",
5472 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5474 chain = TREE_CHAIN (chain);
5476 return first;
5479 static int
5480 conforms_to_protocol (class, protocol)
5481 tree class;
5482 tree protocol;
5484 while (protocol)
5486 tree p = CLASS_PROTOCOL_LIST (class);
5487 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5488 p = TREE_CHAIN (p);
5489 if (!p)
5491 tree super = (CLASS_SUPER_NAME (class)
5492 ? lookup_interface (CLASS_SUPER_NAME (class))
5493 : NULL_TREE);
5494 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5495 if (!tmp)
5496 return 0;
5498 protocol = TREE_CHAIN (protocol);
5500 return 1;
5503 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5504 CONTEXT. This is one of two mechanisms to check protocol integrity
5507 static int
5508 check_methods_accessible (chain, context, mtype)
5509 tree chain;
5510 tree context; /* implementation_context */
5511 int mtype;
5513 int first = 1;
5514 tree list;
5515 tree base_context = context;
5517 while (chain)
5519 context = base_context;
5520 while (context)
5522 if (mtype == '+')
5523 list = CLASS_CLS_METHODS (context);
5524 else
5525 list = CLASS_NST_METHODS (context);
5527 if (lookup_method (list, chain))
5528 break;
5530 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5531 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5532 context = (CLASS_SUPER_NAME (context)
5533 ? lookup_interface (CLASS_SUPER_NAME (context))
5534 : NULL_TREE);
5536 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5537 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5538 context = (CLASS_NAME (context)
5539 ? lookup_interface (CLASS_NAME (context))
5540 : NULL_TREE);
5541 else
5542 abort ();
5545 if (context == NULL_TREE)
5547 if (first)
5549 if (TREE_CODE (implementation_context)
5550 == CLASS_IMPLEMENTATION_TYPE)
5551 warning ("incomplete implementation of class `%s'",
5552 IDENTIFIER_POINTER
5553 (CLASS_NAME (implementation_context)));
5554 else if (TREE_CODE (implementation_context)
5555 == CATEGORY_IMPLEMENTATION_TYPE)
5556 warning ("incomplete implementation of category `%s'",
5557 IDENTIFIER_POINTER
5558 (CLASS_SUPER_NAME (implementation_context)));
5559 first = 0;
5561 warning ("method definition for `%c%s' not found",
5562 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5565 chain = TREE_CHAIN (chain); /* next method... */
5567 return first;
5570 static void
5571 check_protocols (proto_list, type, name)
5572 tree proto_list;
5573 char *type;
5574 char *name;
5576 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
5578 tree p = TREE_VALUE (proto_list);
5580 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
5582 int f1, f2;
5584 /* Ensure that all protocols have bodies! */
5585 if (flag_warn_protocol) {
5586 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
5587 CLASS_CLS_METHODS (implementation_context),
5588 '+');
5589 f2 = check_methods (PROTOCOL_NST_METHODS (p),
5590 CLASS_NST_METHODS (implementation_context),
5591 '-');
5592 } else {
5593 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
5594 implementation_context,
5595 '+');
5596 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
5597 implementation_context,
5598 '-');
5601 if (!f1 || !f2)
5602 warning ("%s `%s' does not fully implement the `%s' protocol",
5603 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
5606 else
5607 ; /* an identifier...if we could not find a protocol. */
5609 /* Check protocols recursively. */
5610 if (PROTOCOL_LIST (p))
5612 tree super_class
5613 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5614 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
5615 check_protocols (PROTOCOL_LIST (p), type, name);
5620 /* Make sure that the class CLASS_NAME is defined
5621 CODE says which kind of thing CLASS_NAME ought to be.
5622 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
5623 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
5625 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
5626 whose matching pop is in continue_class. */
5628 tree
5629 start_class (code, class_name, super_name, protocol_list)
5630 enum tree_code code;
5631 tree class_name;
5632 tree super_name;
5633 tree protocol_list;
5635 tree class, decl;
5637 if (code == CLASS_INTERFACE_TYPE)
5639 push_obstacks_nochange ();
5640 end_temporary_allocation ();
5643 if (!doing_objc_thang)
5644 objc_fatal ();
5646 class = make_node (code);
5647 TYPE_BINFO (class) = make_tree_vec (5);
5649 CLASS_NAME (class) = class_name;
5650 CLASS_SUPER_NAME (class) = super_name;
5651 CLASS_CLS_METHODS (class) = NULL_TREE;
5653 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
5655 error ("`%s' redeclared as different kind of symbol",
5656 IDENTIFIER_POINTER (class_name));
5657 error_with_decl (decl, "previous declaration of `%s'");
5660 if (code == CLASS_IMPLEMENTATION_TYPE)
5663 static tree implemented_classes = 0;
5664 tree chain = implemented_classes;
5665 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
5666 if (TREE_VALUE (chain) == class_name)
5668 error ("reimplementation of class `%s'",
5669 IDENTIFIER_POINTER (class_name));
5670 return error_mark_node;
5672 implemented_classes = perm_tree_cons (NULLT, class_name,
5673 implemented_classes);
5676 /* pre-build the following entities - for speed/convenience. */
5677 if (!self_id)
5678 self_id = get_identifier ("self");
5679 if (!ucmd_id)
5680 ucmd_id = get_identifier ("_cmd");
5682 if (!objc_super_template)
5683 objc_super_template = build_super_template ();
5685 method_slot = 0; /* reset for multiple classes per file */
5687 implementation_context = class;
5689 /* lookup the interface for this implementation. */
5691 if (!(implementation_template = lookup_interface (class_name)))
5693 warning ("Cannot find interface declaration for `%s'",
5694 IDENTIFIER_POINTER (class_name));
5695 add_class (implementation_template = implementation_context);
5698 /* if a super class has been specified in the implementation,
5699 insure it conforms to the one specified in the interface */
5701 if (super_name
5702 && (super_name != CLASS_SUPER_NAME (implementation_template)))
5704 tree previous_name = CLASS_SUPER_NAME (implementation_template);
5705 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
5706 error ("conflicting super class name `%s'",
5707 IDENTIFIER_POINTER (super_name));
5708 error ("previous declaration of `%s'", name);
5710 else if (! super_name)
5712 CLASS_SUPER_NAME (implementation_context)
5713 = CLASS_SUPER_NAME (implementation_template);
5716 else if (code == CLASS_INTERFACE_TYPE)
5718 if (lookup_interface (class_name))
5719 warning ("duplicate interface declaration for class `%s'",
5720 IDENTIFIER_POINTER (class_name));
5721 else
5722 add_class (class);
5724 if (protocol_list)
5725 CLASS_PROTOCOL_LIST (class)
5726 = lookup_and_install_protocols (protocol_list);
5728 else if (code == CATEGORY_INTERFACE_TYPE)
5730 tree class_category_is_assoc_with;
5732 /* for a category, class_name is really the name of the class that
5733 the following set of methods will be associated with...we must
5734 find the interface so that can derive the objects template */
5736 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
5738 error ("Cannot find interface declaration for `%s'",
5739 IDENTIFIER_POINTER (class_name));
5740 exit (1);
5742 else
5743 add_category (class_category_is_assoc_with, class);
5745 if (protocol_list)
5746 CLASS_PROTOCOL_LIST (class)
5747 = lookup_and_install_protocols (protocol_list);
5749 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
5751 /* pre-build the following entities - for speed/convenience. */
5752 if (!self_id)
5753 self_id = get_identifier ("self");
5754 if (!ucmd_id)
5755 ucmd_id = get_identifier ("_cmd");
5757 if (!objc_super_template)
5758 objc_super_template = build_super_template ();
5760 method_slot = 0; /* reset for multiple classes per file */
5762 implementation_context = class;
5764 /* for a category, class_name is really the name of the class that
5765 the following set of methods will be associated with...we must
5766 find the interface so that can derive the objects template */
5768 if (!(implementation_template = lookup_interface (class_name)))
5770 error ("Cannot find interface declaration for `%s'",
5771 IDENTIFIER_POINTER (class_name));
5772 exit (1);
5775 return class;
5778 tree
5779 continue_class (class)
5780 tree class;
5782 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
5783 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
5785 struct imp_entry *imp_entry;
5786 tree ivar_context;
5788 /* check consistency of the instance variables. */
5790 if (CLASS_IVARS (class))
5791 check_ivars (implementation_template, class);
5793 /* code generation */
5795 ivar_context = build_private_template (implementation_template);
5797 if (!objc_class_template)
5798 build_class_template ();
5800 if (!(imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
5801 perror ("unable to allocate in objc-tree.c");
5803 imp_entry->next = imp_list;
5804 imp_entry->imp_context = class;
5805 imp_entry->imp_template = implementation_template;
5807 synth_forward_declarations ();
5808 imp_entry->class_decl = UOBJC_CLASS_decl;
5809 imp_entry->meta_decl = UOBJC_METACLASS_decl;
5811 /* append to front and increment count */
5812 imp_list = imp_entry;
5813 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5814 imp_count++;
5815 else
5816 cat_count++;
5818 return ivar_context;
5820 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
5822 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
5824 if (!TYPE_FIELDS (record))
5826 finish_struct (record, build_ivar_chain (class, 0));
5827 CLASS_STATIC_TEMPLATE (class) = record;
5829 /* mark this record as a class template - for static typing */
5830 TREE_STATIC_TEMPLATE (record) = 1;
5832 return NULLT;
5834 else
5835 return error_mark_node;
5838 /* This is called once we see the "@end" in an interface/implementation. */
5840 void
5841 finish_class (class)
5842 tree class;
5844 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5846 /* all code generation is done in finish_objc */
5848 if (implementation_template != implementation_context)
5850 /* ensure that all method listed in the interface contain bodies! */
5851 check_methods (CLASS_CLS_METHODS (implementation_template),
5852 CLASS_CLS_METHODS (implementation_context), '+');
5853 check_methods (CLASS_NST_METHODS (implementation_template),
5854 CLASS_NST_METHODS (implementation_context), '-');
5856 if (CLASS_PROTOCOL_LIST (implementation_template))
5857 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
5858 "class",
5859 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5862 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
5864 tree category = CLASS_CATEGORY_LIST (implementation_template);
5866 /* find the category interface from the class it is associated with */
5867 while (category)
5869 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
5870 break;
5871 category = CLASS_CATEGORY_LIST (category);
5874 if (category)
5876 /* ensure that all method listed in the interface contain bodies! */
5877 check_methods (CLASS_CLS_METHODS (category),
5878 CLASS_CLS_METHODS (implementation_context), '+');
5879 check_methods (CLASS_NST_METHODS (category),
5880 CLASS_NST_METHODS (implementation_context), '-');
5882 if (CLASS_PROTOCOL_LIST (category))
5883 check_protocols (CLASS_PROTOCOL_LIST (category),
5884 "category",
5885 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5888 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
5890 tree decl_specs;
5891 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
5892 char *string = (char *) alloca (strlen (class_name) + 3);
5894 /* extern struct objc_object *_<my_name>; */
5896 sprintf (string, "_%s", class_name);
5898 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
5899 decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
5900 define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
5901 decl_specs);
5905 static tree
5906 add_protocol (protocol)
5907 tree protocol;
5909 /* put protocol on list in reverse order */
5910 TREE_CHAIN (protocol) = protocol_chain;
5911 protocol_chain = protocol;
5912 return protocol_chain;
5915 static tree
5916 lookup_protocol (ident)
5917 tree ident;
5919 tree chain;
5921 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
5923 if (ident == PROTOCOL_NAME (chain))
5924 return chain;
5926 return NULLT;
5929 tree
5930 start_protocol (code, name, list)
5931 enum tree_code code;
5932 tree name;
5933 tree list;
5935 tree protocol;
5937 if (!doing_objc_thang)
5938 objc_fatal ();
5940 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
5941 if (!objc_protocol_template)
5942 objc_protocol_template = build_protocol_template ();
5944 protocol = make_node (code);
5945 TYPE_BINFO (protocol) = make_tree_vec (2);
5947 PROTOCOL_NAME (protocol) = name;
5948 PROTOCOL_LIST (protocol) = list;
5950 lookup_and_install_protocols (list);
5952 if (lookup_protocol (name))
5953 warning ("duplicate declaration for protocol `%s'",
5954 IDENTIFIER_POINTER (name));
5955 else
5956 add_protocol (protocol);
5958 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
5960 return protocol;
5963 void
5964 finish_protocol (protocol)
5965 tree protocol;
5970 /* "Encode" a data type into a string, which grows in util_obstack.
5971 ??? What is the FORMAT? Someone please document this! */
5973 static void
5974 encode_type_qualifiers (declspecs)
5975 tree declspecs;
5977 tree spec;
5979 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
5981 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
5982 obstack_1grow (&util_obstack, 'r');
5983 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
5984 obstack_1grow (&util_obstack, 'n');
5985 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
5986 obstack_1grow (&util_obstack, 'N');
5987 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
5988 obstack_1grow (&util_obstack, 'o');
5989 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
5990 obstack_1grow (&util_obstack, 'O');
5991 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
5992 obstack_1grow (&util_obstack, 'V');
5996 /* Encode a pointer type. */
5998 static void
5999 encode_pointer (type, curtype, format)
6000 tree type;
6001 int curtype;
6002 int format;
6004 tree pointer_to = TREE_TYPE (type);
6006 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6008 if (TYPE_NAME (pointer_to)
6009 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6011 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6013 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6015 obstack_1grow (&util_obstack, '@');
6016 return;
6018 else if (TREE_STATIC_TEMPLATE (pointer_to))
6020 if (generating_instance_variables)
6022 obstack_1grow (&util_obstack, '@');
6023 obstack_1grow (&util_obstack, '"');
6024 obstack_grow (&util_obstack, name, strlen (name));
6025 obstack_1grow (&util_obstack, '"');
6026 return;
6028 else
6030 obstack_1grow (&util_obstack, '@');
6031 return;
6034 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6036 obstack_1grow (&util_obstack, '#');
6037 return;
6039 #ifndef OBJC_INT_SELECTORS
6040 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6042 obstack_1grow (&util_obstack, ':');
6043 return;
6045 #endif /* OBJC_INT_SELECTORS */
6048 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6049 && TYPE_MODE (pointer_to) == QImode)
6051 obstack_1grow (&util_obstack, '*');
6052 return;
6055 /* we have a type that does not get special treatment... */
6057 /* NeXT extension */
6058 obstack_1grow (&util_obstack, '^');
6059 encode_type (pointer_to, curtype, format);
6062 static void
6063 encode_array (type, curtype, format)
6064 tree type;
6065 int curtype;
6066 int format;
6068 tree an_int_cst = TYPE_SIZE (type);
6069 tree array_of = TREE_TYPE (type);
6070 char buffer[40];
6072 /* An incomplete array is treated like a pointer. */
6073 if (an_int_cst == NULL)
6075 /* split for obvious reasons. North-Keys 30 Mar 1991 */
6076 encode_pointer (type, curtype, format);
6077 return;
6080 sprintf (buffer, "[%d",
6081 (TREE_INT_CST_LOW (an_int_cst)
6082 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6083 obstack_grow (&util_obstack, buffer, strlen (buffer));
6084 encode_type (array_of, curtype, format);
6085 obstack_1grow (&util_obstack, ']');
6086 return;
6089 static void
6090 encode_aggregate (type, curtype, format)
6091 tree type;
6092 int curtype;
6093 int format;
6095 enum tree_code code = TREE_CODE (type);
6097 switch (code)
6099 case RECORD_TYPE:
6101 if (obstack_object_size (&util_obstack) > 0
6102 && *(obstack_next_free (&util_obstack) - 1) == '^')
6104 tree name = TYPE_NAME (type);
6106 /* we have a reference - this is a NeXT extension */
6108 if (obstack_object_size (&util_obstack) - curtype == 1
6109 && format == OBJC_ENCODE_INLINE_DEFS)
6111 /* output format of struct for first level only! */
6113 tree fields = TYPE_FIELDS (type);
6115 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6117 obstack_1grow (&util_obstack, '{');
6118 obstack_grow (&util_obstack,
6119 IDENTIFIER_POINTER (name),
6120 strlen (IDENTIFIER_POINTER (name)));
6121 obstack_1grow (&util_obstack, '=');
6123 else
6124 obstack_grow (&util_obstack, "{?=", 3);
6126 for ( ; fields; fields = TREE_CHAIN (fields))
6127 encode_field_decl (fields, curtype, format);
6128 obstack_1grow (&util_obstack, '}');
6130 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6132 obstack_1grow (&util_obstack, '{');
6133 obstack_grow (&util_obstack,
6134 IDENTIFIER_POINTER (name),
6135 strlen (IDENTIFIER_POINTER (name)));
6136 obstack_1grow (&util_obstack, '}');
6138 else /* we have an untagged structure or a typedef */
6139 obstack_grow (&util_obstack, "{?}", 3);
6141 else
6143 tree name = TYPE_NAME (type);
6144 tree fields = TYPE_FIELDS (type);
6146 if (format == OBJC_ENCODE_INLINE_DEFS
6147 || generating_instance_variables)
6149 obstack_1grow (&util_obstack, '{');
6150 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6151 obstack_grow (&util_obstack,
6152 IDENTIFIER_POINTER (name),
6153 strlen (IDENTIFIER_POINTER (name)));
6154 else
6155 obstack_1grow (&util_obstack, '?');
6157 obstack_1grow (&util_obstack, '=');
6159 for (; fields; fields = TREE_CHAIN (fields))
6161 if (generating_instance_variables)
6163 tree fname = DECL_NAME (fields);
6165 obstack_1grow (&util_obstack, '"');
6166 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6168 obstack_grow (&util_obstack,
6169 IDENTIFIER_POINTER (fname),
6170 strlen (IDENTIFIER_POINTER (fname)));
6172 obstack_1grow (&util_obstack, '"');
6174 encode_field_decl (fields, curtype, format);
6176 obstack_1grow (&util_obstack, '}');
6178 else
6180 obstack_1grow (&util_obstack, '{');
6181 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6182 obstack_grow (&util_obstack,
6183 IDENTIFIER_POINTER (name),
6184 strlen (IDENTIFIER_POINTER (name)));
6185 else /* we have an untagged structure or a typedef */
6186 obstack_1grow (&util_obstack, '?');
6187 obstack_1grow (&util_obstack, '}');
6190 break;
6192 case UNION_TYPE:
6194 if (*obstack_next_free (&util_obstack) == '^'
6195 || format != OBJC_ENCODE_INLINE_DEFS)
6197 /* we have a reference - this is a NeXT extension--
6198 or we don't want the details. */
6199 if (TYPE_NAME (type)
6200 && TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
6202 obstack_1grow (&util_obstack, '(');
6203 obstack_grow (&util_obstack,
6204 IDENTIFIER_POINTER (TYPE_NAME (type)),
6205 strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
6206 obstack_1grow (&util_obstack, ')');
6208 else /* we have an untagged structure or a typedef */
6209 obstack_grow (&util_obstack, "(?)", 3);
6211 else
6213 tree fields = TYPE_FIELDS (type);
6214 obstack_1grow (&util_obstack, '(');
6215 for ( ; fields; fields = TREE_CHAIN (fields))
6216 encode_field_decl (fields, curtype, format);
6217 obstack_1grow (&util_obstack, ')');
6219 break;
6222 case ENUMERAL_TYPE:
6223 obstack_1grow (&util_obstack, 'i');
6224 break;
6228 /* Support bitfields, the current version of Objective-C does not support
6229 them. the string will consist of one or more "b:n"'s where n is an
6230 integer describing the width of the bitfield. Currently, classes in
6231 the kit implement a method "-(char *)describeBitfieldStruct:" that
6232 simulates this...if they do not implement this method, the archiver
6233 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6234 according to the GNU compiler. After looking at the "kit", it appears
6235 that all classes currently rely on this default behavior, rather than
6236 hand generating this string (which is tedious). */
6238 static void
6239 encode_bitfield (width, format)
6240 int width;
6241 int format;
6243 char buffer[40];
6244 sprintf (buffer, "b%d", width);
6245 obstack_grow (&util_obstack, buffer, strlen (buffer));
6248 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6250 static void
6251 encode_type (type, curtype, format)
6252 tree type;
6253 int curtype;
6254 int format;
6256 enum tree_code code = TREE_CODE (type);
6258 if (code == INTEGER_TYPE)
6260 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6261 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6263 /* unsigned integer types */
6265 if (TYPE_MODE (type) == QImode) /* 'C' */
6266 obstack_1grow (&util_obstack, 'C');
6267 else if (TYPE_MODE (type) == HImode) /* 'S' */
6268 obstack_1grow (&util_obstack, 'S');
6269 else if (TYPE_MODE (type) == SImode)
6271 if (type == long_unsigned_type_node)
6272 obstack_1grow (&util_obstack, 'L'); /* 'L' */
6273 else
6274 obstack_1grow (&util_obstack, 'I'); /* 'I' */
6276 else if (TYPE_MODE (type) == DImode) /* 'Q' */
6277 obstack_1grow (&util_obstack, 'Q');
6279 else /* signed integer types */
6281 if (TYPE_MODE (type) == QImode) /* 'c' */
6282 obstack_1grow (&util_obstack, 'c');
6283 else if (TYPE_MODE (type) == HImode) /* 's' */
6284 obstack_1grow (&util_obstack, 's');
6285 else if (TYPE_MODE (type) == SImode) /* 'i' */
6287 if (type == long_integer_type_node)
6288 obstack_1grow (&util_obstack, 'l'); /* 'l' */
6289 else
6290 obstack_1grow (&util_obstack, 'i'); /* 'i' */
6292 else if (TYPE_MODE (type) == DImode) /* 'q' */
6293 obstack_1grow (&util_obstack, 'q');
6296 else if (code == REAL_TYPE)
6298 /* floating point types */
6300 if (TYPE_MODE (type) == SFmode) /* 'f' */
6301 obstack_1grow (&util_obstack, 'f');
6302 else if (TYPE_MODE (type) == DFmode
6303 || TYPE_MODE (type) == TFmode) /* 'd' */
6304 obstack_1grow (&util_obstack, 'd');
6307 else if (code == VOID_TYPE) /* 'v' */
6308 obstack_1grow (&util_obstack, 'v');
6310 else if (code == ARRAY_TYPE)
6311 encode_array (type, curtype, format);
6313 else if (code == POINTER_TYPE)
6314 encode_pointer (type, curtype, format);
6316 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6317 encode_aggregate (type, curtype, format);
6319 else if (code == FUNCTION_TYPE) /* '?' */
6320 obstack_1grow (&util_obstack, '?');
6323 static void
6324 encode_field_decl (field_decl, curtype, format)
6325 tree field_decl;
6326 int curtype;
6327 int format;
6329 tree type;
6331 /* If this field is obviously a bitfield, or is a bitfield that has been
6332 clobbered to look like a ordinary integer mode, go ahead and generate
6333 the bitfield typing information. */
6334 type = TREE_TYPE (field_decl);
6335 if (DECL_BIT_FIELD (field_decl))
6336 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6337 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6338 && DECL_FIELD_SIZE (field_decl)
6339 && TYPE_MODE (type) > DECL_MODE (field_decl))
6340 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6341 else
6342 encode_type (TREE_TYPE (field_decl), curtype, format);
6345 static tree
6346 expr_last (complex_expr)
6347 tree complex_expr;
6349 tree next;
6351 if (complex_expr)
6352 while ((next = TREE_OPERAND (complex_expr, 0)))
6353 complex_expr = next;
6354 return complex_expr;
6357 /* The selector of the current method,
6358 or NULL if we aren't compiling a method. */
6360 tree
6361 maybe_objc_method_name (decl)
6362 tree decl;
6364 if (method_context)
6365 return METHOD_SEL_NAME (method_context);
6366 else
6367 return 0;
6370 /* Transform a method definition into a function definition as follows:
6371 - synthesize the first two arguments, "self" and "_cmd". */
6373 void
6374 start_method_def (method)
6375 tree method;
6377 tree decl_specs;
6379 /* Required to implement _msgSuper. */
6380 method_context = method;
6381 UOBJC_SUPER_decl = NULLT;
6383 pushlevel (0); /* Must be called BEFORE start_function. */
6385 /* Generate prototype declarations for arguments..."new-style". */
6387 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
6388 decl_specs = build_tree_list (NULLT, uprivate_record);
6389 else
6390 /* really a `struct objc_class *'...however we allow people to
6391 assign to self...which changes its type midstream. */
6392 decl_specs = build_tree_list (NULLT, objc_object_reference);
6394 push_parm_decl (build_tree_list (decl_specs,
6395 build1 (INDIRECT_REF, NULLT, self_id)));
6397 #ifdef OBJC_INT_SELECTORS
6398 decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
6399 decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
6400 push_parm_decl (build_tree_list (decl_specs, ucmd_id));
6401 #else /* not OBJC_INT_SELECTORS */
6402 decl_specs = build_tree_list (NULLT,
6403 xref_tag (RECORD_TYPE,
6404 get_identifier (TAG_SELECTOR)));
6405 push_parm_decl (build_tree_list (decl_specs,
6406 build1 (INDIRECT_REF, NULLT, ucmd_id)));
6407 #endif /* not OBJC_INT_SELECTORS */
6409 /* generate argument declarations if a keyword_decl */
6410 if (METHOD_SEL_ARGS (method))
6412 tree arglist = METHOD_SEL_ARGS (method);
6415 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6416 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6418 if (arg_decl)
6420 tree last_expr = expr_last (arg_decl);
6422 /* unite the abstract decl with its name */
6423 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6424 push_parm_decl (build_tree_list (arg_spec, arg_decl));
6425 /* unhook...restore the abstract declarator */
6426 TREE_OPERAND (last_expr, 0) = NULLT;
6428 else
6429 push_parm_decl (build_tree_list (arg_spec,
6430 KEYWORD_ARG_NAME (arglist)));
6432 arglist = TREE_CHAIN (arglist);
6434 while (arglist);
6437 if (METHOD_ADD_ARGS (method) > (tree)1)
6439 /* we have a variable length selector - in "prototype" format */
6440 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6441 while (akey)
6443 /* This must be done prior to calling pushdecl. pushdecl is
6444 going to change our chain on us. */
6445 tree nextkey = TREE_CHAIN (akey);
6446 pushdecl (akey);
6447 akey = nextkey;
6452 static void
6453 warn_with_method (message, mtype, method)
6454 char *message;
6455 int mtype;
6456 tree method;
6458 if (count_error (1) == 0)
6459 return;
6461 report_error_function (DECL_SOURCE_FILE (method));
6463 fprintf (stderr, "%s:%d: warning: ",
6464 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
6465 bzero (errbuf, BUFSIZE);
6466 fprintf (stderr, "%s `%c%s'\n",
6467 message, mtype, gen_method_decl (method, errbuf));
6470 /* return 1 if `method' is consistent with `proto' */
6472 static int
6473 comp_method_with_proto (method, proto)
6474 tree method, proto;
6476 static tree function_type = 0;
6478 /* create a function_type node once */
6479 if (!function_type)
6481 struct obstack *ambient_obstack = current_obstack;
6483 current_obstack = &permanent_obstack;
6484 function_type = make_node (FUNCTION_TYPE);
6485 current_obstack = ambient_obstack;
6488 /* Install argument types - normally set by build_function_type. */
6489 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
6491 /* install return type */
6492 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
6494 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
6497 /* return 1 if `proto1' is consistent with `proto2' */
6499 static int
6500 comp_proto_with_proto (proto1, proto2)
6501 tree proto1, proto2;
6503 static tree function_type1 = 0, function_type2 = 0;
6505 /* create a couple function_type node's once */
6506 if (!function_type1)
6508 struct obstack *ambient_obstack = current_obstack;
6510 current_obstack = &permanent_obstack;
6511 function_type1 = make_node (FUNCTION_TYPE);
6512 function_type2 = make_node (FUNCTION_TYPE);
6513 current_obstack = ambient_obstack;
6516 /* Install argument types - normally set by build_function_type. */
6517 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
6518 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
6520 /* install return type */
6521 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
6522 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
6524 return comptypes (function_type1, function_type2);
6527 /* - generate an identifier for the function. the format is "_n_cls",
6528 where 1 <= n <= nMethods, and cls is the name the implementation we
6529 are processing.
6530 - install the return type from the method declaration.
6531 - if we have a prototype, check for type consistency. */
6533 static void
6534 really_start_method (method, parmlist)
6535 tree method, parmlist;
6537 tree sc_spec, ret_spec, ret_decl, decl_specs;
6538 tree method_decl, method_id;
6539 char *buf, *sel_name, *class_name, *cat_name;
6541 /* synth the storage class & assemble the return type */
6542 sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
6543 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
6544 decl_specs = chainon (sc_spec, ret_spec);
6546 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
6547 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
6548 cat_name = ((TREE_CODE (implementation_context)
6549 == CLASS_IMPLEMENTATION_TYPE)
6550 ? NULL
6551 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6552 method_slot++;
6553 /* Make sure this is big enough for any plausible method label. */
6554 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
6555 + (cat_name ? strlen (cat_name) : 0));
6557 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
6558 class_name, cat_name, sel_name, method_slot);
6560 method_id = get_identifier (buf);
6562 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
6564 /* check the declarator portion of the return type for the method */
6565 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
6567 /* unite the complex decl (specified in the abstract decl) with the
6568 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
6569 tree save_expr = expr_last (ret_decl);
6571 TREE_OPERAND (save_expr, 0) = method_decl;
6572 method_decl = ret_decl;
6573 /* fool the parser into thinking it is starting a function */
6574 start_function (decl_specs, method_decl, 0);
6575 /* unhook...this has the effect of restoring the abstract declarator */
6576 TREE_OPERAND (save_expr, 0) = NULLT;
6578 else
6580 TREE_VALUE (TREE_TYPE (method)) = method_decl;
6581 /* fool the parser into thinking it is starting a function */
6582 start_function (decl_specs, method_decl, 0);
6583 /* unhook...this has the effect of restoring the abstract declarator */
6584 TREE_VALUE (TREE_TYPE (method)) = NULLT;
6587 METHOD_DEFINITION (method) = current_function_decl;
6589 /* Check consistency...start_function, pushdecl, duplicate_decls. */
6591 if (implementation_template != implementation_context)
6593 tree proto;
6595 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
6596 proto = lookup_instance_method_static (implementation_template,
6597 METHOD_SEL_NAME (method));
6598 else
6599 proto = lookup_class_method_static (implementation_template,
6600 METHOD_SEL_NAME (method));
6602 if (proto && ! comp_method_with_proto (method, proto))
6604 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
6606 warn_with_method ("conflicting types for", type, method);
6607 warn_with_method ("previous declaration of", type, proto);
6612 /* The following routine is always called...this "architecture" is to
6613 accommodate "old-style" variable length selectors.
6615 - a:a b:b // prototype ; id c; id d; // old-style. */
6617 void
6618 continue_method_def ()
6620 tree parmlist;
6622 if (METHOD_ADD_ARGS (method_context) == (tree)1)
6623 /* We have a `, ...' immediately following the selector. */
6624 parmlist = get_parm_info (0);
6625 else
6626 parmlist = get_parm_info (1); /* place a `void_at_end' */
6628 /* Set self_decl from the first argument...this global is used by
6629 build_ivar_reference calling build_indirect_ref. */
6630 self_decl = TREE_PURPOSE (parmlist);
6632 poplevel (0, 0, 0); /* must be called BEFORE start_function. */
6634 really_start_method (method_context, parmlist);
6636 store_parm_decls (); /* must be called AFTER start_function. */
6639 /* Called by the parser, from the `pushlevel' production. */
6641 void
6642 add_objc_decls ()
6644 if (!UOBJC_SUPER_decl)
6646 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
6647 build_tree_list (NULLT,
6648 objc_super_template),
6651 finish_decl (UOBJC_SUPER_decl, NULLT, NULLT);
6653 /* this prevents `unused variable' warnings when compiling with -Wall. */
6654 DECL_IN_SYSTEM_HEADER (UOBJC_SUPER_decl) = 1;
6658 /* _n_Method (id self, SEL sel, ...)
6660 struct objc_super _S;
6661 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
6662 } */
6664 tree
6665 get_super_receiver ()
6667 if (method_context)
6669 tree super_expr, super_expr_list;
6671 /* set receiver to self */
6672 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
6673 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
6674 super_expr_list = build_tree_list (NULLT, super_expr);
6676 /* set class to begin searching */
6677 super_expr = build_component_ref (UOBJC_SUPER_decl,
6678 get_identifier ("class"));
6680 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
6682 /* [_cls, __cls]Super are "pre-built" in
6683 synth_forward_declarations. */
6685 super_expr = build_modify_expr (super_expr, NOP_EXPR,
6686 ((TREE_CODE (method_context)
6687 == INSTANCE_METHOD_DECL)
6688 ? ucls_super_ref
6689 : uucls_super_ref));
6691 else /* we have a category... */
6693 tree super_name = CLASS_SUPER_NAME (implementation_template);
6694 tree super_class;
6696 if (!super_name) /* Barf if super used in a category of Object. */
6698 error ("no super class declared in interface for `%s'",
6699 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
6700 return error_mark_node;
6703 if (flag_next_runtime)
6705 super_class = get_class_reference (super_name);
6706 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
6707 super_class
6708 = build_component_ref (build_indirect_ref (super_class, "->"),
6709 get_identifier ("isa"));
6711 else
6713 add_class_reference (super_name);
6714 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
6715 ? objc_get_class_decl : objc_get_meta_class_decl);
6716 assemble_external (super_class);
6717 super_class
6718 = build_function_call
6719 (super_class,
6720 build_tree_list (NULLT,
6721 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
6722 IDENTIFIER_POINTER (super_name))));
6725 /* cast! */
6726 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
6727 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
6729 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
6731 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
6732 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
6734 return build_compound_expr (super_expr_list);
6736 else
6738 error ("[super ...] must appear in a method context");
6739 return error_mark_node;
6743 static tree
6744 encode_method_def (func_decl)
6745 tree func_decl;
6747 tree parms;
6748 int stack_size;
6749 int max_parm_end = 0;
6750 char buffer[40];
6751 tree result;
6753 /* return type */
6754 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
6755 obstack_object_size (&util_obstack),
6756 OBJC_ENCODE_INLINE_DEFS);
6757 /* stack size */
6758 for (parms = DECL_ARGUMENTS (func_decl); parms;
6759 parms = TREE_CHAIN (parms))
6761 int parm_end = (forwarding_offset (parms)
6762 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
6763 / BITS_PER_UNIT));
6765 if (!offset_is_register && parm_end > max_parm_end)
6766 max_parm_end = parm_end;
6769 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
6771 sprintf (buffer, "%d", stack_size);
6772 obstack_grow (&util_obstack, buffer, strlen (buffer));
6774 /* argument types */
6775 for (parms = DECL_ARGUMENTS (func_decl); parms;
6776 parms = TREE_CHAIN (parms))
6778 /* type */
6779 encode_type (TREE_TYPE (parms),
6780 obstack_object_size (&util_obstack),
6781 OBJC_ENCODE_INLINE_DEFS);
6783 /* compute offset */
6784 sprintf (buffer, "%d", forwarding_offset (parms));
6786 /* indicate register */
6787 if (offset_is_register)
6788 obstack_1grow (&util_obstack, '+');
6790 obstack_grow (&util_obstack, buffer, strlen (buffer));
6793 obstack_1grow (&util_obstack, 0); /* null terminate string */
6794 result = get_identifier (obstack_finish (&util_obstack));
6795 obstack_free (&util_obstack, util_firstobj);
6796 return result;
6799 void
6800 finish_method_def ()
6802 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
6804 finish_function (0);
6806 /* this must be done AFTER finish_function, since the optimizer may
6807 find "may be used before set" errors. */
6808 method_context = NULLT; /* required to implement _msgSuper. */
6812 lang_report_error_function (decl)
6813 tree decl;
6815 if (method_context)
6817 fprintf (stderr, "In method `%s'\n",
6818 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
6819 return 1;
6821 else
6822 return 0;
6825 static int
6826 is_complex_decl (type)
6827 tree type;
6829 return (TREE_CODE (type) == ARRAY_TYPE
6830 || TREE_CODE (type) == FUNCTION_TYPE
6831 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
6835 /* Code to convert a decl node into text for a declaration in C. */
6837 static char tmpbuf[256];
6839 static void
6840 adorn_decl (decl, str)
6841 tree decl;
6842 char *str;
6844 enum tree_code code = TREE_CODE (decl);
6846 if (code == ARRAY_REF)
6848 tree an_int_cst = TREE_OPERAND (decl, 1);
6850 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
6851 sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst));
6852 else
6853 strcat (str, "[]");
6855 else if (code == ARRAY_TYPE)
6857 tree an_int_cst = TYPE_SIZE (decl);
6858 tree array_of = TREE_TYPE (decl);
6860 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
6861 sprintf (str + strlen (str), "[%d]",
6862 (TREE_INT_CST_LOW (an_int_cst)
6863 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6864 else
6865 strcat (str, "[]");
6867 else if (code == CALL_EXPR)
6869 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
6871 strcat (str, "(");
6872 while (chain)
6874 gen_declaration (chain, str);
6875 chain = TREE_CHAIN (chain);
6876 if (chain)
6877 strcat (str, ", ");
6879 strcat (str, ")");
6881 else if (code == FUNCTION_TYPE)
6883 tree chain = TYPE_ARG_TYPES (decl); /* a list of types */
6885 strcat (str, "(");
6886 while (chain && TREE_VALUE (chain) != void_type_node)
6888 gen_declaration (TREE_VALUE (chain), str);
6889 chain = TREE_CHAIN (chain);
6890 if (chain && TREE_VALUE (chain) != void_type_node)
6891 strcat (str, ", ");
6893 strcat (str, ")");
6895 else if (code == INDIRECT_REF)
6897 strcpy (tmpbuf, "*");
6898 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
6900 tree chain;
6902 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
6903 chain;
6904 chain = TREE_CHAIN (chain))
6906 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
6908 strcat (tmpbuf, " ");
6909 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
6912 if (str[0])
6913 strcat (tmpbuf, " ");
6915 strcat (tmpbuf, str);
6916 strcpy (str, tmpbuf);
6918 else if (code == POINTER_TYPE)
6920 strcpy (tmpbuf, "*");
6921 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
6923 if (TREE_READONLY (decl))
6924 strcat (tmpbuf, " const");
6925 if (TYPE_VOLATILE (decl))
6926 strcat (tmpbuf, " volatile");
6927 if (str[0])
6928 strcat (tmpbuf, " ");
6930 strcat (tmpbuf, str);
6931 strcpy (str, tmpbuf);
6935 static char *
6936 gen_declarator (decl, buf, name)
6937 tree decl;
6938 char *buf;
6939 char *name;
6941 if (decl)
6943 enum tree_code code = TREE_CODE (decl);
6944 char *str;
6945 tree op;
6946 int wrap = 0;
6948 switch (code)
6950 case ARRAY_REF:
6951 case INDIRECT_REF:
6952 case CALL_EXPR:
6953 op = TREE_OPERAND (decl, 0);
6955 /* we have a pointer to a function or array...(*)(), (*)[] */
6956 if ((code == ARRAY_REF || code == CALL_EXPR)
6957 && op && TREE_CODE (op) == INDIRECT_REF)
6958 wrap = 1;
6960 str = gen_declarator (op, buf, name);
6962 if (wrap)
6964 strcpy (tmpbuf, "(");
6965 strcat (tmpbuf, str);
6966 strcat (tmpbuf, ")");
6967 strcpy (str, tmpbuf);
6970 adorn_decl (decl, str);
6971 break;
6973 case ARRAY_TYPE:
6974 case FUNCTION_TYPE:
6975 case POINTER_TYPE:
6976 strcpy (buf, name);
6977 str = buf;
6979 /* this clause is done iteratively...rather than recursively */
6982 op = (is_complex_decl (TREE_TYPE (decl))
6983 ? TREE_TYPE (decl) : NULLT);
6985 adorn_decl (decl, str);
6987 /* we have a pointer to a function or array...(*)(), (*)[] */
6988 if (code == POINTER_TYPE
6989 && op && (TREE_CODE (op) == FUNCTION_TYPE
6990 || TREE_CODE (op) == ARRAY_TYPE))
6992 strcpy (tmpbuf, "(");
6993 strcat (tmpbuf, str);
6994 strcat (tmpbuf, ")");
6995 strcpy (str, tmpbuf);
6998 decl = (is_complex_decl (TREE_TYPE (decl))
6999 ? TREE_TYPE (decl) : NULLT);
7001 while (decl && (code = TREE_CODE (decl)));
7003 break;
7005 case IDENTIFIER_NODE:
7006 /* will only happen if we are processing a "raw" expr-decl. */
7007 strcpy (buf, IDENTIFIER_POINTER (decl));
7008 return buf;
7011 return str;
7013 else /* we have an abstract declarator or a _DECL node */
7015 strcpy (buf, name);
7016 return buf;
7020 static void
7021 gen_declspecs (declspecs, buf, raw)
7022 tree declspecs;
7023 char *buf;
7024 int raw;
7026 if (raw)
7028 tree chain;
7030 for (chain = nreverse (copy_list (declspecs));
7031 chain; chain = TREE_CHAIN (chain))
7033 tree aspec = TREE_VALUE (chain);
7035 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7036 strcat (buf, IDENTIFIER_POINTER (aspec));
7037 else if (TREE_CODE (aspec) == RECORD_TYPE)
7039 if (TYPE_NAME (aspec))
7041 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7043 if (! TREE_STATIC_TEMPLATE (aspec))
7044 strcat (buf, "struct ");
7045 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7047 /* NEW!!! */
7048 if (protocol_list)
7050 tree chain = protocol_list;
7052 strcat (buf, " <");
7053 while (chain)
7055 strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
7056 chain = TREE_CHAIN (chain);
7057 if (chain)
7058 strcat (buf, ", ");
7060 strcat (buf, ">");
7063 else
7064 strcat (buf, "untagged struct");
7066 else if (TREE_CODE (aspec) == UNION_TYPE)
7068 if (TYPE_NAME (aspec))
7070 if (! TREE_STATIC_TEMPLATE (aspec))
7071 strcat (buf, "union ");
7072 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7074 else
7075 strcat (buf, "untagged union");
7077 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7079 if (TYPE_NAME (aspec))
7081 if (! TREE_STATIC_TEMPLATE (aspec))
7082 strcat (buf, "enum ");
7083 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7085 else
7086 strcat (buf, "untagged enum");
7088 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7090 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7092 /* NEW!!! */
7093 else if (IS_ID (aspec))
7095 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7097 strcat (buf, "id");
7098 if (protocol_list)
7100 tree chain = protocol_list;
7102 strcat (buf, " <");
7103 while (chain)
7105 strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
7106 chain = TREE_CHAIN (chain);
7107 if (chain)
7108 strcat (buf, ", ");
7110 strcat (buf, ">");
7113 if (TREE_CHAIN (chain))
7114 strcat (buf, " ");
7117 else
7119 /* type qualifiers */
7121 if (TREE_READONLY (declspecs))
7122 strcat (buf, "const ");
7123 if (TYPE_VOLATILE (declspecs))
7124 strcat (buf, "volatile ");
7126 switch (TREE_CODE (declspecs))
7128 /* type specifiers */
7130 case INTEGER_TYPE: /* signed integer types */
7131 declspecs = TYPE_MAIN_VARIANT (declspecs);
7133 if (declspecs == short_integer_type_node) /* 's' */
7134 strcat (buf, "short int ");
7135 else if (declspecs == integer_type_node) /* 'i' */
7136 strcat (buf, "int ");
7137 else if (declspecs == long_integer_type_node) /* 'l' */
7138 strcat (buf, "long int ");
7139 else if (declspecs == long_long_integer_type_node) /* 'l' */
7140 strcat (buf, "long long int ");
7141 else if (declspecs == signed_char_type_node /* 'c' */
7142 || declspecs == char_type_node)
7143 strcat (buf, "char ");
7145 /* unsigned integer types */
7147 else if (declspecs == short_unsigned_type_node) /* 'S' */
7148 strcat (buf, "unsigned short ");
7149 else if (declspecs == unsigned_type_node) /* 'I' */
7150 strcat (buf, "unsigned int ");
7151 else if (declspecs == long_unsigned_type_node) /* 'L' */
7152 strcat (buf, "unsigned long ");
7153 else if (declspecs == long_long_unsigned_type_node) /* 'L' */
7154 strcat (buf, "unsigned long long ");
7155 else if (declspecs == unsigned_char_type_node) /* 'C' */
7156 strcat (buf, "unsigned char ");
7157 break;
7159 case REAL_TYPE: /* floating point types */
7160 declspecs = TYPE_MAIN_VARIANT (declspecs);
7162 if (declspecs == float_type_node) /* 'f' */
7163 strcat (buf, "float ");
7164 else if (declspecs == double_type_node) /* 'd' */
7165 strcat (buf, "double ");
7166 else if (declspecs == long_double_type_node) /* 'd' */
7167 strcat (buf, "long double ");
7168 break;
7170 case RECORD_TYPE:
7171 if (TYPE_NAME (declspecs)
7172 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7174 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7176 if (! TREE_STATIC_TEMPLATE (declspecs))
7177 strcat (buf, "struct ");
7178 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7179 /* NEW!!! */
7180 if (protocol_list)
7182 tree chain = protocol_list;
7184 strcat (buf, " <");
7185 while (chain)
7187 strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
7188 chain = TREE_CHAIN (chain);
7189 if (chain)
7190 strcat (buf, ", ");
7192 strcat (buf, ">");
7195 else
7196 strcat (buf, "untagged struct");
7198 strcat (buf, " ");
7199 break;
7201 case UNION_TYPE:
7202 if (TYPE_NAME (declspecs)
7203 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7205 strcat (buf, "union ");
7206 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7207 strcat (buf, " ");
7209 else
7210 strcat (buf, "untagged union ");
7211 break;
7213 case ENUMERAL_TYPE:
7214 if (TYPE_NAME (declspecs)
7215 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7217 strcat (buf, "enum ");
7218 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7219 strcat (buf, " ");
7221 else
7222 strcat (buf, "untagged enum ");
7223 break;
7225 case VOID_TYPE:
7226 strcat (buf, "void ");
7227 break;
7229 /* NEW!!! */
7230 case POINTER_TYPE:
7232 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7234 strcat (buf, "id");
7235 if (protocol_list)
7237 tree chain = protocol_list;
7239 strcat (buf, " <");
7240 while (chain)
7242 strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
7243 chain = TREE_CHAIN (chain);
7244 if (chain)
7245 strcat (buf, ", ");
7247 strcat (buf, ">");
7254 static char *
7255 gen_declaration (atype_or_adecl, buf)
7256 tree atype_or_adecl;
7257 char *buf;
7259 char declbuf[256];
7261 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7263 tree declspecs; /* "identifier_node", "record_type" */
7264 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7266 /* we have a "raw", abstract declarator (typename) */
7267 declarator = TREE_VALUE (atype_or_adecl);
7268 declspecs = TREE_PURPOSE (atype_or_adecl);
7270 gen_declspecs (declspecs, buf, 1);
7271 if (declarator)
7273 strcat (buf, " ");
7274 strcat (buf, gen_declarator (declarator, declbuf, ""));
7277 else
7279 tree atype;
7280 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7281 tree declarator; /* "array_type", "function_type", "pointer_type". */
7283 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7284 || TREE_CODE (atype_or_adecl) == PARM_DECL
7285 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7286 atype = TREE_TYPE (atype_or_adecl);
7287 else
7288 atype = atype_or_adecl; /* assume we have a *_type node */
7290 if (is_complex_decl (atype))
7292 tree chain;
7294 /* get the declaration specifier...it is at the end of the list */
7295 declarator = chain = atype;
7297 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7298 while (is_complex_decl (chain));
7299 declspecs = chain;
7301 else
7303 declspecs = atype;
7304 declarator = NULLT;
7307 gen_declspecs (declspecs, buf, 0);
7309 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7310 || TREE_CODE (atype_or_adecl) == PARM_DECL
7311 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7313 char *decl_name = (DECL_NAME (atype_or_adecl)
7314 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
7315 : "");
7317 if (declarator)
7319 strcat (buf, " ");
7320 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7322 else if (decl_name[0])
7324 strcat (buf, " ");
7325 strcat (buf, decl_name);
7328 else if (declarator)
7330 strcat (buf, " ");
7331 strcat (buf, gen_declarator (declarator, declbuf, ""));
7334 return buf;
7337 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7339 static char *
7340 gen_method_decl (method, buf)
7341 tree method;
7342 char *buf;
7344 tree chain;
7346 if (RAW_TYPESPEC (method) != objc_object_reference)
7348 strcpy (buf, "(");
7349 gen_declaration (TREE_TYPE (method), buf);
7350 strcat (buf, ")");
7353 chain = METHOD_SEL_ARGS (method);
7354 if (chain)
7355 { /* we have a chain of keyword_decls */
7358 if (KEYWORD_KEY_NAME (chain))
7359 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7361 strcat (buf, ":");
7362 if (RAW_TYPESPEC (chain) != objc_object_reference)
7364 strcat (buf, "(");
7365 gen_declaration (TREE_TYPE (chain), buf);
7366 strcat (buf, ")");
7368 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7369 if ((chain = TREE_CHAIN (chain)))
7370 strcat (buf, " ");
7372 while (chain);
7374 if (METHOD_ADD_ARGS (method) == (tree)1)
7375 strcat (buf, ", ...");
7376 else if (METHOD_ADD_ARGS (method))
7378 /* we have a tree list node as generate by get_parm_info. */
7379 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7380 /* know we have a chain of parm_decls */
7381 while (chain)
7383 strcat (buf, ", ");
7384 gen_declaration (chain, buf);
7385 chain = TREE_CHAIN (chain);
7389 else /* we have a unary selector */
7390 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7392 return buf;
7395 /* debug info... */
7397 static void
7398 dump_interface (fp, chain)
7399 FILE *fp;
7400 tree chain;
7402 char *buf = (char *)xmalloc (256);
7403 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7404 tree ivar_decls = CLASS_RAW_IVARS (chain);
7405 tree nst_methods = CLASS_NST_METHODS (chain);
7406 tree cls_methods = CLASS_CLS_METHODS (chain);
7408 fprintf (fp, "\n@interface %s", my_name);
7410 if (CLASS_SUPER_NAME (chain))
7412 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7413 fprintf (fp, " : %s\n", super_name);
7415 else
7416 fprintf (fp, "\n");
7418 if (ivar_decls)
7420 fprintf (fp, "{\n");
7423 bzero (buf, 256);
7424 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7425 ivar_decls = TREE_CHAIN (ivar_decls);
7427 while (ivar_decls);
7428 fprintf (fp, "}\n");
7431 while (nst_methods)
7433 bzero (buf, 256);
7434 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7435 nst_methods = TREE_CHAIN (nst_methods);
7438 while (cls_methods)
7440 bzero (buf, 256);
7441 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7442 cls_methods = TREE_CHAIN (cls_methods);
7444 fprintf (fp, "\n@end");
7447 static void
7448 init_objc ()
7450 /* Add the special tree codes of Objective C to the tables. */
7452 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
7454 gcc_obstack_init (&util_obstack);
7455 util_firstobj = (char *) obstack_finish (&util_obstack);
7457 tree_code_type
7458 = (char **) xrealloc (tree_code_type,
7459 sizeof (char *) * LAST_OBJC_TREE_CODE);
7460 tree_code_length
7461 = (int *) xrealloc (tree_code_length,
7462 sizeof (int) * LAST_OBJC_TREE_CODE);
7463 tree_code_name
7464 = (char **) xrealloc (tree_code_name,
7465 sizeof (char *) * LAST_OBJC_TREE_CODE);
7466 bcopy ((char *) objc_tree_code_type,
7467 (char *) (tree_code_type + (int) LAST_CODE),
7468 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7469 * sizeof (char *)));
7470 bcopy ((char *) objc_tree_code_length,
7471 (char *) (tree_code_length + (int) LAST_CODE),
7472 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7473 * sizeof (int)));
7474 bcopy ((char *) objc_tree_code_name,
7475 (char *) (tree_code_name + (int) LAST_CODE),
7476 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7477 * sizeof (char *)));
7479 errbuf = (char *)xmalloc (BUFSIZE);
7480 hash_init ();
7481 synth_module_prologue ();
7484 static void
7485 finish_objc ()
7487 struct imp_entry *impent;
7488 tree chain;
7489 /* The internally generated initializers appear to have missing braces.
7490 Don't warn about this. */
7491 int save_warn_missing_braces = warn_missing_braces;
7492 warn_missing_braces = 0;
7494 generate_forward_declaration_to_string_table ();
7496 #ifdef OBJC_PROLOGUE
7497 OBJC_PROLOGUE;
7498 #endif
7500 if (implementation_context || class_names_chain
7501 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7502 generate_objc_symtab_decl ();
7504 for (impent = imp_list; impent; impent = impent->next)
7506 implementation_context = impent->imp_context;
7507 implementation_template = impent->imp_template;
7509 UOBJC_CLASS_decl = impent->class_decl;
7510 UOBJC_METACLASS_decl = impent->meta_decl;
7512 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7514 /* all of the following reference the string pool... */
7515 generate_ivar_lists ();
7516 generate_dispatch_tables ();
7517 generate_shared_structures ();
7519 else
7521 generate_dispatch_tables ();
7522 generate_category (implementation_context);
7526 /* If we are using an array of selectors, we must always
7527 finish up the array decl even if no selectors were used. */
7528 if (! flag_next_runtime || sel_ref_chain)
7529 build_selector_translation_table ();
7531 if (protocol_chain)
7532 generate_protocols ();
7534 if (implementation_context || class_names_chain
7535 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7537 /* Arrange for Objc data structures to be initialized at run time. */
7538 char *init_name = build_module_descriptor ();
7539 if (init_name)
7540 assemble_constructor (init_name);
7543 /* dump the class references...this forces the appropriate classes
7544 to be linked into the executable image, preserving unix archive
7545 semantics...this can be removed when we move to a more dynamically
7546 linked environment. */
7547 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
7549 handle_class_ref (chain);
7550 if (TREE_PURPOSE (chain))
7551 generate_classref_translation_entry (chain);
7554 for (impent = imp_list; impent; impent = impent->next)
7555 handle_impent (impent);
7557 /* dump the string table last */
7559 generate_strings ();
7561 if (flag_gen_declaration)
7563 add_class (implementation_context);
7564 dump_interface (gen_declaration_file, implementation_context);
7567 if (warn_selector)
7569 int slot;
7570 hash hsh;
7572 /* Run through the selector hash tables and print a warning for any
7573 selector which has multiple methods. */
7575 for (slot = 0; slot < SIZEHASHTABLE; slot++)
7576 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
7577 if (hsh->list)
7579 tree meth = hsh->key;
7580 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
7581 ? '-' : '+');
7582 attr loop;
7584 warning ("potential selector conflict for method `%s'",
7585 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
7586 warn_with_method ("found", type, meth);
7587 for (loop = hsh->list; loop; loop = loop->next)
7588 warn_with_method ("found", type, loop->value);
7591 for (slot = 0; slot < SIZEHASHTABLE; slot++)
7592 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
7593 if (hsh->list)
7595 tree meth = hsh->key;
7596 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
7597 ? '-' : '+');
7598 attr loop;
7600 warning ("potential selector conflict for method `%s'",
7601 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
7602 warn_with_method ("found", type, meth);
7603 for (loop = hsh->list; loop; loop = loop->next)
7604 warn_with_method ("found", type, loop->value);
7608 warn_missing_braces = save_warn_missing_braces;
7611 /* Subroutines of finish_objc. */
7613 static void
7614 generate_classref_translation_entry (chain)
7615 tree chain;
7617 tree expr, name, decl_specs, decl, sc_spec;
7618 tree type;
7620 type = TREE_TYPE (TREE_PURPOSE (chain));
7622 expr = add_objc_string (TREE_VALUE (chain), class_names);
7623 expr = build_c_cast (type, expr); /* cast! */
7625 name = DECL_NAME (TREE_PURPOSE (chain));
7627 sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
7629 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
7630 decl_specs = tree_cons (NULLT, type, sc_spec);
7632 /* the `decl' that is returned from start_decl is the one that we
7633 forward declared in `build_class_reference'. */
7634 decl = start_decl (name, decl_specs, 1);
7635 end_temporary_allocation ();
7636 finish_decl (decl, expr, NULLT);
7637 return;
7640 static void
7641 handle_class_ref (chain)
7642 tree chain;
7644 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
7645 if (! flag_next_runtime)
7647 tree decl;
7648 char *string = (char *) alloca (strlen (name) + 30);
7649 tree exp;
7651 sprintf (string, "%sobjc_class_name_%s",
7652 (flag_next_runtime ? "." : "__"), name);
7654 /* Make a decl for this name, so we can use its address in a tree. */
7655 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
7656 DECL_EXTERNAL (decl) = 1;
7657 TREE_PUBLIC (decl) = 1;
7659 pushdecl (decl);
7660 rest_of_decl_compilation (decl, 0, 0, 0);
7662 /* Make following constant read-only (why not)? */
7663 readonly_data_section ();
7665 exp = build1 (ADDR_EXPR, string_type_node, decl);
7667 /* Align the section properly. */
7668 assemble_constant_align (exp);
7670 /* Inform the assembler about this new external thing. */
7671 assemble_external (decl);
7673 /* Output a constant to reference this address. */
7674 output_constant (exp, int_size_in_bytes (string_type_node));
7676 else
7678 /* This overreliance on our assembler (i.e. lack of portability)
7679 should be dealt with at some point. The GNU strategy (above)
7680 won't work either, but it is a start. */
7681 char *string = (char *) alloca (strlen (name) + 30);
7682 sprintf (string, ".reference .objc_class_name_%s", name);
7683 assemble_asm (my_build_string (strlen (string) + 1, string));
7687 static void
7688 handle_impent (impent)
7689 struct imp_entry *impent;
7691 implementation_context = impent->imp_context;
7692 implementation_template = impent->imp_template;
7694 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
7696 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
7697 char *string = (char *) alloca (strlen (class_name) + 30);
7699 if (flag_next_runtime)
7701 /* Grossly unportable.
7702 People should know better than to assume
7703 such things about assembler syntax! */
7704 sprintf (string, ".objc_class_name_%s=0", class_name);
7705 assemble_asm (my_build_string (strlen (string) + 1, string));
7707 sprintf (string, ".globl .objc_class_name_%s", class_name);
7708 assemble_asm (my_build_string (strlen (string) + 1, string));
7710 else
7712 sprintf (string, "%sobjc_class_name_%s",
7713 (flag_next_runtime ? "." : "__"), class_name);
7714 assemble_global (string);
7715 assemble_label (string);
7718 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
7720 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
7721 char *class_super_name
7722 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
7723 char *string = (char *) alloca (strlen (class_name)
7724 + strlen (class_super_name) + 30);
7726 /* Do the same for categories. Even though no references to these
7727 symbols are generated automatically by the compiler, it gives
7728 you a handle to pull them into an archive by hand. */
7729 if (flag_next_runtime)
7731 /* Grossly unportable. */
7732 sprintf (string, ".objc_category_name_%s_%s=0",
7733 class_name, class_super_name);
7734 assemble_asm (my_build_string (strlen (string) + 1, string));
7736 sprintf (string, ".globl .objc_category_name_%s_%s",
7737 class_name, class_super_name);
7738 assemble_asm (my_build_string (strlen (string) + 1, string));
7740 else
7742 sprintf (string, "%sobjc_category_name_%s_%s",
7743 (flag_next_runtime ? "." : "__"),
7744 class_name, class_super_name);
7745 assemble_global (string);
7746 assemble_label (string);
7751 #ifdef DEBUG
7753 static void
7754 objc_debug (fp)
7755 FILE *fp;
7757 char *buf = (char *)xmalloc (256);
7759 { /* dump function prototypes */
7760 tree loop = UOBJC_MODULES_decl;
7762 fprintf (fp, "\n\nfunction prototypes:\n");
7763 while (loop)
7765 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
7767 /* we have a function definition - generate prototype */
7768 bzero (errbuf, BUFSIZE);
7769 gen_declaration (loop, errbuf);
7770 fprintf (fp, "%s;\n", errbuf);
7772 loop = TREE_CHAIN (loop);
7775 { /* dump global chains */
7776 tree loop;
7777 int i, index = 0, offset = 0;
7778 hash hashlist;
7780 for (i = 0; i < SIZEHASHTABLE; i++)
7782 if (hashlist = nst_method_hash_list[i])
7784 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
7787 bzero (buf, 256);
7788 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
7789 hashlist = hashlist->next;
7791 while (hashlist);
7794 for (i = 0; i < SIZEHASHTABLE; i++)
7796 if (hashlist = cls_method_hash_list[i])
7798 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
7801 bzero (buf, 256);
7802 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
7803 hashlist = hashlist->next;
7805 while (hashlist);
7808 fprintf (fp, "\nsel_refdef_chain:\n");
7809 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
7811 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
7812 IDENTIFIER_POINTER (TREE_VALUE (loop)));
7813 index++;
7814 /* add one for the '\0' character */
7815 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
7817 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
7820 #endif
7822 void
7823 print_lang_statistics ()