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