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