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