|
|
1.1 ! root 1: /* Functions dealing with signatures and signature pointers/references. ! 2: Copyright (C) 1992 Free Software Foundation, Inc. ! 3: Contributed by Gerald Baumgartner ([email protected]) ! 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: ! 22: #include "config.h" ! 23: #include <stdio.h> ! 24: #include "obstack.h" ! 25: #include "tree.h" ! 26: #include "cp-tree.h" ! 27: #include "flags.h" ! 28: #include "assert.h" ! 29: ! 30: extern struct obstack *current_obstack; ! 31: extern struct obstack permanent_obstack; ! 32: extern struct obstack *saveable_obstack; ! 33: ! 34: extern void error (); ! 35: extern void sorry (); ! 36: extern void compiler_error (); ! 37: extern void make_decl_rtl PROTO((tree, char *, int)); ! 38: ! 39: /* Used to help generate globally unique names for signature tables. */ ! 40: ! 41: static int global_sigtable_name_counter; ! 42: ! 43: /* Build an identifier for a signature pointer or reference, so we ! 44: can use it's name in function name mangling. */ ! 45: ! 46: static tree ! 47: build_signature_pointer_or_reference_name (to_type, constp, volatilep, refp) ! 48: tree to_type; ! 49: int constp, volatilep, refp; ! 50: { ! 51: char * sig_name = TYPE_NAME_STRING (to_type); ! 52: int name_len = TYPE_NAME_LENGTH (to_type) + constp + volatilep; ! 53: char * name; ! 54: ! 55: if (refp) ! 56: { ! 57: name = (char *) alloca (name_len + sizeof (SIGNATURE_REFERENCE_NAME) +2); ! 58: sprintf (name, SIGNATURE_REFERENCE_NAME_FORMAT, ! 59: constp ? "C" : "", volatilep ? "V": "", sig_name); ! 60: } ! 61: else ! 62: { ! 63: name = (char *) alloca (name_len + sizeof (SIGNATURE_POINTER_NAME) + 2); ! 64: sprintf (name, SIGNATURE_POINTER_NAME_FORMAT, ! 65: constp ? "C" : "", volatilep ? "V": "", sig_name); ! 66: } ! 67: return get_identifier (name); ! 68: } ! 69: ! 70: /* Build a DECL node for a signature pointer or reference, so we can ! 71: tell the debugger the structure of signature pointers/references. ! 72: This function is called at most eight times for a given signature, ! 73: once for each [const] [volatile] signature pointer/reference. */ ! 74: ! 75: static void ! 76: build_signature_pointer_or_reference_decl (type, name) ! 77: tree type, name; ! 78: { ! 79: tree decl; ! 80: ! 81: /* We don't enter this declaration in any sort of symbol table. */ ! 82: decl = build_decl (TYPE_DECL, name, type); ! 83: TYPE_NAME (type) = decl; ! 84: TREE_CHAIN (type) = decl; ! 85: } ! 86: ! 87: /* Construct, lay out and return the type of pointers or references ! 88: to signature TO_TYPE. If such a type has already been constructed, ! 89: reuse it. If CONSTP or VOLATILEP is specified, make the `optr' const ! 90: or volatile, respectively. If we are constructing a const/volatile ! 91: type variant and the main type variant doesn't exist yet, it is built ! 92: as well. If REFP is 1, we construct a signature reference, otherwise ! 93: a signature pointer is constructed. ! 94: ! 95: This function is a subroutine of `build_signature_pointer_type' and ! 96: `build_signature_reference_type'. */ ! 97: ! 98: static tree ! 99: build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) ! 100: tree to_type; ! 101: int constp, volatilep, refp; ! 102: { ! 103: register tree t, m; ! 104: register struct obstack *ambient_obstack = current_obstack; ! 105: register struct obstack *ambient_saveable_obstack = saveable_obstack; ! 106: ! 107: m = refp ? SIGNATURE_REFERENCE_TO (to_type) : SIGNATURE_POINTER_TO (to_type); ! 108: ! 109: /* If we don't have the main variant yet, construct it. */ ! 110: if (m == NULL_TREE ! 111: && (constp || volatilep)) ! 112: m = build_signature_pointer_or_reference_type (to_type, 0, 0, refp); ! 113: ! 114: /* Treat any nonzero argument as 1. */ ! 115: constp = !!constp; ! 116: volatilep = !!volatilep; ! 117: refp = !!refp; ! 118: ! 119: /* If not generating auxiliary info, search the chain of variants to see ! 120: if there is already one there just like the one we need to have. If so, ! 121: use that existing one. ! 122: ! 123: We don't do this in the case where we are generating aux info because ! 124: in that case we want each typedef names to get it's own distinct type ! 125: node, even if the type of this new typedef is the same as some other ! 126: (existing) type. */ ! 127: ! 128: if (m && !flag_gen_aux_info) ! 129: for (t = m; t; t = TYPE_NEXT_VARIANT (t)) ! 130: if (constp == TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t)))) ! 131: && volatilep == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t))))) ! 132: return t; ! 133: ! 134: /* We need a new one. If TO_TYPE is permanent, make this permanent too. */ ! 135: if (TREE_PERMANENT (to_type)) ! 136: { ! 137: current_obstack = &permanent_obstack; ! 138: saveable_obstack = &permanent_obstack; ! 139: } ! 140: ! 141: /* A signature pointer or reference to a signature `s' looks like this: ! 142: ! 143: struct { ! 144: void * optr; ! 145: const s * sptr; ! 146: vtbl_type_node * vptr; ! 147: }; ! 148: ! 149: A `const' signature pointer/reference is a ! 150: ! 151: struct { ! 152: const void * optr; ! 153: const s * sptr; ! 154: vtbl_type_node * vptr; ! 155: }; ! 156: ! 157: Similarly, for `volatile' and `const volatile'. ! 158: */ ! 159: ! 160: t = make_lang_type (RECORD_TYPE); ! 161: { ! 162: tree obj_type = build_type_variant (void_type_node, constp, volatilep); ! 163: tree optr_type = build_pointer_type (obj_type); ! 164: tree optr, sptr, vptr; ! 165: ! 166: optr = build_lang_field_decl (FIELD_DECL, ! 167: get_identifier (SIGNATURE_OPTR_NAME), ! 168: optr_type); ! 169: DECL_FIELD_CONTEXT (optr) = t; ! 170: DECL_CLASS_CONTEXT (optr) = t; ! 171: ! 172: if (m) ! 173: { ! 174: /* We can share `sptr' and `vptr' among type variants. */ ! 175: sptr = TREE_CHAIN (TYPE_FIELDS (m)); ! 176: vptr = TREE_CHAIN (sptr); ! 177: } ! 178: else ! 179: { ! 180: tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0); ! 181: ! 182: sptr = build_lang_field_decl (FIELD_DECL, ! 183: get_identifier (SIGNATURE_SPTR_NAME), ! 184: build_pointer_type (sig_tbl_type)); ! 185: vptr = build_lang_field_decl (FIELD_DECL, ! 186: get_identifier (SIGNATURE_VPTR_NAME), ! 187: build_pointer_type (vtbl_type_node)); ! 188: DECL_FIELD_CONTEXT (sptr) = t; ! 189: DECL_CLASS_CONTEXT (sptr) = t; ! 190: DECL_FIELD_CONTEXT (vptr) = t; ! 191: DECL_CLASS_CONTEXT (vptr) = t; ! 192: TREE_CHAIN (sptr) = vptr; ! 193: TREE_CHAIN (vptr) = NULL_TREE; ! 194: } ! 195: ! 196: TREE_CHAIN (optr) = sptr; ! 197: TYPE_FIELDS (t) = optr; ! 198: /* To make `build_vfn_ref' work when building a signature method call. */ ! 199: CLASSTYPE_VFIELD (t) = vptr; ! 200: DECL_FCONTEXT (CLASSTYPE_VFIELD (t)) = t; ! 201: TYPE_ALIGN (t) = TYPE_ALIGN (optr_type); ! 202: } ! 203: ! 204: { ! 205: tree name = build_signature_pointer_or_reference_name (to_type, constp, ! 206: volatilep, refp); ! 207: ! 208: /* Build a DECL node for this type, so the debugger has access to it. */ ! 209: build_signature_pointer_or_reference_decl (t, name); ! 210: } ! 211: ! 212: CLASSTYPE_GOT_SEMICOLON (t) = 1; ! 213: IS_SIGNATURE_POINTER (t) = ! refp; ! 214: IS_SIGNATURE_REFERENCE (t) = refp; ! 215: SIGNATURE_TYPE (t) = to_type; ! 216: ! 217: if (m) ! 218: { ! 219: /* Add this type to the chain of variants of TYPE. ! 220: Every type has to be its own TYPE_MAIN_VARIANT. */ ! 221: TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); ! 222: TYPE_NEXT_VARIANT (m) = t; ! 223: } ! 224: else if (refp) ! 225: /* Record this type as the reference to TO_TYPE. */ ! 226: SIGNATURE_REFERENCE_TO (to_type) = t; ! 227: else ! 228: /* Record this type as the pointer to TO_TYPE. */ ! 229: SIGNATURE_POINTER_TO (to_type) = t; ! 230: ! 231: /* Lay out the type. This function has many callers that are concerned ! 232: with expression-construction, and this simplifies them all. ! 233: Also, it guarantees the TYPE_SIZE is permanent if the type is. */ ! 234: layout_type (t); ! 235: ! 236: current_obstack = ambient_obstack; ! 237: saveable_obstack = ambient_saveable_obstack; ! 238: ! 239: /* Ouput debug information for this type. */ ! 240: rest_of_type_compilation (t, 1); ! 241: ! 242: return t; ! 243: } ! 244: ! 245: /* Construct, lay out and return the type of pointers to signature TO_TYPE. */ ! 246: ! 247: tree ! 248: build_signature_pointer_type (to_type, constp, volatilep) ! 249: tree to_type; ! 250: int constp, volatilep; ! 251: { ! 252: return ! 253: build_signature_pointer_or_reference_type (to_type, constp, volatilep, 0); ! 254: } ! 255: ! 256: /* Construct, lay out and return the type of pointers to signature TO_TYPE. */ ! 257: ! 258: tree ! 259: build_signature_reference_type (to_type, constp, volatilep) ! 260: tree to_type; ! 261: int constp, volatilep; ! 262: { ! 263: return ! 264: build_signature_pointer_or_reference_type (to_type, constp, volatilep, 1); ! 265: } ! 266: ! 267: /* Return the name of the signature table (as an IDENTIFIER_NODE) ! 268: for the given signature type SIG_TYPE and rhs type RHS_TYPE. */ ! 269: ! 270: static tree ! 271: get_sigtable_name (sig_type, rhs_type) ! 272: tree sig_type, rhs_type; ! 273: { ! 274: tree sig_type_id = build_typename_overload (sig_type); ! 275: tree rhs_type_id = build_typename_overload (rhs_type); ! 276: char *buf = (char *) alloca (sizeof (SIGTABLE_NAME_FORMAT_LONG) ! 277: + IDENTIFIER_LENGTH (sig_type_id) ! 278: + IDENTIFIER_LENGTH (rhs_type_id) + 20); ! 279: char *sig_ptr = IDENTIFIER_POINTER (sig_type_id); ! 280: char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id); ! 281: int i, j; ! 282: ! 283: for (i = 0; sig_ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ! 284: /* do nothing */; ! 285: while (sig_ptr[i] >= '0' && sig_ptr[i] <= '9') ! 286: i += 1; ! 287: ! 288: for (j = 0; rhs_ptr[j] == OPERATOR_TYPENAME_FORMAT[j]; j++) ! 289: /* do nothing */; ! 290: while (rhs_ptr[j] >= '0' && rhs_ptr[j] <= '9') ! 291: j += 1; ! 292: ! 293: if (IS_SIGNATURE (rhs_type)) ! 294: sprintf (buf, SIGTABLE_NAME_FORMAT_LONG, sig_ptr+i, rhs_ptr+j, ! 295: global_sigtable_name_counter++); ! 296: else ! 297: sprintf (buf, SIGTABLE_NAME_FORMAT, sig_ptr+i, rhs_ptr+j); ! 298: return get_identifier (buf); ! 299: } ! 300: ! 301: /* Build a field decl that points to a signature member function. */ ! 302: ! 303: static tree ! 304: build_member_function_pointer (member) ! 305: tree member; ! 306: { ! 307: char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member)); ! 308: int namlen = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (member)); ! 309: char *name; ! 310: tree entry; ! 311: ! 312: name = (char *) alloca (namlen + sizeof (SIGNATURE_FIELD_NAME) + 2); ! 313: sprintf (name, SIGNATURE_FIELD_NAME_FORMAT, namstr); ! 314: ! 315: /* @@ Do we really want to xref signature table fields? */ ! 316: GNU_xref_ref (current_function_decl, name); ! 317: ! 318: entry = build_lang_field_decl (FIELD_DECL, get_identifier (name), ! 319: TYPE_MAIN_VARIANT (sigtable_entry_type)); ! 320: TREE_CONSTANT (entry) = 1; ! 321: TREE_READONLY (entry) = 1; ! 322: ! 323: /* @@ Do we really want to xref signature table fields? */ ! 324: GNU_xref_decl (current_function_decl, entry); ! 325: ! 326: return entry; ! 327: } ! 328: ! 329: /* For each FUNCTION_DECL in a signature we construct a member function ! 330: pointer of the appropriate type. We also need two flags to test ! 331: whether the member function pointer points to a virtual function or ! 332: to a default implementation. Those flags will be the two lower order ! 333: bits of the member function pointer (or the two higher order bits, ! 334: based on the configuration). ! 335: ! 336: The new FIELD_DECLs are appended at the end of the last (and only) ! 337: sublist of `list_of_fieldlists.' ! 338: ! 339: As a side effect, each member function in the signature gets the ! 340: `decl.ignored' bit turned on, so we don't output debug info for it. */ ! 341: ! 342: void ! 343: append_signature_fields (list_of_fieldlists) ! 344: tree list_of_fieldlists; ! 345: { ! 346: tree l, x; ! 347: tree last_x = NULL_TREE; ! 348: tree mfptr; ! 349: tree last_mfptr; ! 350: tree mfptr_list = NULL_TREE; ! 351: ! 352: /* For signatures it should actually be only a list with one element. */ ! 353: for (l = list_of_fieldlists; l; l = TREE_CHAIN (l)) ! 354: { ! 355: for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x)) ! 356: { ! 357: if (TREE_CODE (x) == FUNCTION_DECL) ! 358: { ! 359: mfptr = build_member_function_pointer (x); ! 360: DECL_MEMFUNC_POINTER_TO (x) = mfptr; ! 361: DECL_MEMFUNC_POINTING_TO (mfptr) = x; ! 362: DECL_IGNORED_P (x) = 1; ! 363: DECL_IN_AGGR_P (mfptr) = 1; ! 364: if (! mfptr_list) ! 365: mfptr_list = last_mfptr = mfptr; ! 366: else ! 367: { ! 368: TREE_CHAIN (last_mfptr) = mfptr; ! 369: last_mfptr = mfptr; ! 370: } ! 371: } ! 372: last_x = x; ! 373: } ! 374: } ! 375: ! 376: /* Append the lists. */ ! 377: if (last_x && mfptr_list) ! 378: { ! 379: TREE_CHAIN (last_x) = mfptr_list; ! 380: TREE_CHAIN (last_mfptr) = NULL_TREE; ! 381: } ! 382: } ! 383: ! 384: /* Compare the types of a signature member function and a class member ! 385: function. Returns 1 if the types are in the C++ `<=' relationship. ! 386: ! 387: If we have a signature pointer/reference as argument or return type ! 388: we don't want to do a recursive conformance check. The conformance ! 389: check only succeeds if both LHS and RHS refer to the same signature ! 390: pointer. Otherwise we need to keep information about parameter types ! 391: around at run time to initialize the signature table correctly. */ ! 392: ! 393: static int ! 394: match_method_types (sig_mtype, class_mtype) ! 395: tree sig_mtype, class_mtype; ! 396: { ! 397: tree sig_return_type = TREE_TYPE (sig_mtype); ! 398: tree sig_arg_types = TYPE_ARG_TYPES (sig_mtype); ! 399: tree class_return_type = TREE_TYPE (class_mtype); ! 400: tree class_arg_types = TYPE_ARG_TYPES (class_mtype); ! 401: ! 402: /* The return types have to be the same. */ ! 403: if (! comptypes (sig_return_type, class_return_type, 1)) ! 404: return 0; ! 405: ! 406: /* Compare the first argument `this.' */ ! 407: { ! 408: /* Get the type of what the `optr' is pointing to. */ ! 409: tree sig_this = ! 410: TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types)))); ! 411: tree class_this = TREE_VALUE (class_arg_types); ! 412: ! 413: if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */ ! 414: class_this = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (class_this))); ! 415: else ! 416: class_this = TREE_TYPE (class_this); ! 417: ! 418: /* If a signature method's `this' is const or volatile, so has to be ! 419: the corresponding class method's `this.' */ ! 420: if ((TYPE_READONLY (sig_this) && ! TYPE_READONLY (class_this)) ! 421: || (TYPE_VOLATILE (sig_this) && ! TYPE_VOLATILE (class_this))) ! 422: return 0; ! 423: } ! 424: ! 425: sig_arg_types = TREE_CHAIN (sig_arg_types); ! 426: class_arg_types = TREE_CHAIN (class_arg_types); ! 427: ! 428: /* The number of arguments and the argument types have to be the same. */ ! 429: return compparms (sig_arg_types, class_arg_types, 3); ! 430: } ! 431: ! 432: /* Undo casts of opaque type variables to the RHS types. */ ! 433: static void ! 434: undo_casts (sig_ty) ! 435: tree sig_ty; ! 436: { ! 437: tree field = TYPE_FIELDS (sig_ty); ! 438: ! 439: /* Since all the FIELD_DECLs for the signature table entries are at the end ! 440: of the chain (see `append_signature_fields'), we can do it this way. */ ! 441: for (; field && TREE_CODE (field) != FIELD_DECL; field = TREE_CHAIN (field)) ! 442: if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == opaque_type_node) ! 443: TREE_TYPE (TREE_TYPE (field)) = TREE_TYPE (ptr_type_node); ! 444: } ! 445: ! 446: /* Do the type checking necessary to see whether the `rhs' conforms to ! 447: the lhs's `sig_ty'. Depending on the type of `rhs' return a NULL_TREE, ! 448: an integer_zero_node, a constructor, or an expression offsetting the ! 449: `rhs' signature table. */ ! 450: ! 451: static tree ! 452: build_signature_table_constructor (sig_ty, rhs) ! 453: tree sig_ty, rhs; ! 454: { ! 455: tree rhstype = TREE_TYPE (rhs); ! 456: tree sig_field = TYPE_FIELDS (sig_ty); ! 457: tree result = NULL_TREE; ! 458: tree first_rhs_field = NULL_TREE; ! 459: tree last_rhs_field; ! 460: int sig_ptr_p = IS_SIGNATURE (rhstype); ! 461: int offset_p = sig_ptr_p; ! 462: ! 463: rhstype = sig_ptr_p ? rhstype : TREE_TYPE (rhstype); ! 464: ! 465: if (CLASSTYPE_TAGS (sig_ty)) ! 466: { ! 467: sorry ("conformance check with signature containing class declarations"); ! 468: return error_mark_node; ! 469: } ! 470: ! 471: for (; sig_field; sig_field = TREE_CHAIN (sig_field)) ! 472: { ! 473: tree basetype_path, baselink, basetypes; ! 474: tree sig_method, sig_mname, sig_mtype; ! 475: tree rhs_method, tbl_entry; ! 476: ! 477: if (TREE_CODE (sig_field) == TYPE_DECL) ! 478: { ! 479: tree sig_field_type = TREE_TYPE (sig_field); ! 480: ! 481: if (TYPE_MAIN_VARIANT (sig_field_type) == opaque_type_node) ! 482: { ! 483: /* We've got an opaque type here. */ ! 484: tree oty_name = DECL_NAME (sig_field); ! 485: tree oty_type = lookup_field (rhstype, oty_name, 1, 1); ! 486: ! 487: if (oty_type == NULL_TREE || oty_type == error_mark_node) ! 488: { ! 489: cp_error ("class `%T' does not contain type `%T'", ! 490: rhstype, oty_type); ! 491: undo_casts (sig_ty); ! 492: return error_mark_node; ! 493: } ! 494: oty_type = TREE_TYPE (oty_type); ! 495: ! 496: /* Cast `sig_field' to be of type `oty_type'. This will be ! 497: undone in `undo_casts' by walking over all the TYPE_DECLs. */ ! 498: TREE_TYPE (sig_field_type) = TREE_TYPE (oty_type); ! 499: } ! 500: /* If we don't have an opaque type, we can ignore the `typedef'. */ ! 501: continue; ! 502: } ! 503: ! 504: /* Find the signature method corresponding to `sig_field'. */ ! 505: sig_method = DECL_MEMFUNC_POINTING_TO (sig_field); ! 506: sig_mname = DECL_NAME (sig_method); ! 507: sig_mtype = TREE_TYPE (sig_method); ! 508: ! 509: basetype_path = TYPE_BINFO (rhstype); ! 510: baselink = lookup_fnfields (basetype_path, sig_mname, 0); ! 511: if (baselink == NULL_TREE || baselink == error_mark_node) ! 512: { ! 513: if (! IS_DEFAULT_IMPLEMENTATION (sig_method)) ! 514: { ! 515: cp_error ("class `%T' does not contain method `%D'", ! 516: rhstype, sig_mname); ! 517: undo_casts (sig_ty); ! 518: return error_mark_node; ! 519: } ! 520: else ! 521: { ! 522: /* We use the signature's default implementation. */ ! 523: rhs_method = sig_method; ! 524: } ! 525: } ! 526: else ! 527: { ! 528: /* Find the class method of the correct type. */ ! 529: ! 530: basetypes = TREE_PURPOSE (baselink); ! 531: if (TREE_CODE (basetypes) == TREE_LIST) ! 532: basetypes = TREE_VALUE (basetypes); ! 533: ! 534: rhs_method = TREE_VALUE (baselink); ! 535: for (; rhs_method; rhs_method = TREE_CHAIN (rhs_method)) ! 536: if (sig_mname == DECL_NAME (rhs_method) ! 537: && ! DECL_STATIC_FUNCTION_P (rhs_method) ! 538: && match_method_types (sig_mtype, TREE_TYPE (rhs_method))) ! 539: break; ! 540: ! 541: if (rhs_method == NULL_TREE ! 542: || (compute_access (basetypes, rhs_method) ! 543: != access_public)) ! 544: { ! 545: error ("class `%s' does not contain a method conforming to `%s'", ! 546: TYPE_NAME_STRING (rhstype), ! 547: fndecl_as_string (NULL, sig_method, 1)); ! 548: undo_casts (sig_ty); ! 549: return error_mark_node; ! 550: } ! 551: } ! 552: ! 553: if (sig_ptr_p && rhs_method != sig_method) ! 554: { ! 555: tree rhs_field = DECL_MEMFUNC_POINTER_TO (rhs_method); ! 556: ! 557: if (first_rhs_field == NULL_TREE) ! 558: { ! 559: first_rhs_field = rhs_field; ! 560: last_rhs_field = rhs_field; ! 561: } ! 562: else if (TREE_CHAIN (last_rhs_field) == rhs_field) ! 563: last_rhs_field = rhs_field; ! 564: else ! 565: offset_p = 0; ! 566: ! 567: tbl_entry = build_component_ref (rhs, DECL_NAME (rhs_field), ! 568: NULL_TREE, 1); ! 569: } ! 570: else ! 571: { ! 572: tree code, offset, pfn; ! 573: ! 574: if (rhs_method == sig_method) ! 575: { ! 576: code = integer_two_node; ! 577: offset = integer_zero_node; ! 578: pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); ! 579: TREE_TYPE (pfn) = ptr_type_node; ! 580: offset_p = 0; /* we can't offset the rhs sig table */ ! 581: } ! 582: else if (DECL_VINDEX (rhs_method)) ! 583: { ! 584: code = integer_one_node; ! 585: offset = DECL_VINDEX (rhs_method); ! 586: pfn = null_pointer_node; ! 587: } ! 588: else ! 589: { ! 590: code = integer_zero_node; ! 591: offset = integer_zero_node; ! 592: pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); ! 593: TREE_TYPE (pfn) = ptr_type_node; ! 594: TREE_ADDRESSABLE (rhs_method) = 1; ! 595: } ! 596: ! 597: tbl_entry = tree_cons (NULL_TREE, code, ! 598: tree_cons (NULL_TREE, offset, ! 599: build_tree_list (NULL_TREE, pfn))); ! 600: tbl_entry = build_nt (CONSTRUCTOR, NULL_TREE, tbl_entry); ! 601: TREE_HAS_CONSTRUCTOR (tbl_entry) = 1; ! 602: TREE_CONSTANT (tbl_entry) = 1; ! 603: } ! 604: ! 605: /* Chain those function address expressions together. */ ! 606: if (result) ! 607: result = tree_cons (NULL_TREE, tbl_entry, result); ! 608: else ! 609: result = build_tree_list (NULL_TREE, tbl_entry); ! 610: } ! 611: ! 612: if (result == NULL_TREE) ! 613: { ! 614: /* The signature was empty, we don't need a signature table. */ ! 615: undo_casts (sig_ty); ! 616: return NULL_TREE; ! 617: } ! 618: ! 619: if (offset_p) ! 620: { ! 621: if (first_rhs_field == TYPE_FIELDS (rhstype)) ! 622: { ! 623: /* The sptr field on the lhs can be copied from the rhs. */ ! 624: undo_casts (sig_ty); ! 625: return integer_zero_node; ! 626: } ! 627: else ! 628: { ! 629: /* The sptr field on the lhs will point into the rhs sigtable. */ ! 630: undo_casts (sig_ty); ! 631: return build_component_ref (rhs, DECL_NAME (first_rhs_field), ! 632: NULL_TREE, 0); ! 633: } ! 634: } ! 635: ! 636: /* We need to construct a new signature table. */ ! 637: result = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (result)); ! 638: TREE_HAS_CONSTRUCTOR (result) = 1; ! 639: TREE_CONSTANT (result) = !sig_ptr_p; ! 640: ! 641: undo_casts (sig_ty); ! 642: return result; ! 643: } ! 644: ! 645: /* Build a signature table declaration and initialize it or return an ! 646: existing one if we built one already. If we don't get a constructor ! 647: as initialization expression, we don't need a new signature table ! 648: variable and just hand back the init expression. ! 649: ! 650: The declaration processing is done by hand instead of using `finish_decl' ! 651: so that we can make signature pointers global variables instead of ! 652: static ones. */ ! 653: ! 654: static tree ! 655: build_sigtable (sig_type, rhs_type, init_from) ! 656: tree sig_type, rhs_type, init_from; ! 657: { ! 658: tree name = NULL_TREE; ! 659: tree decl = NULL_TREE; ! 660: tree init_expr; ! 661: ! 662: push_obstacks_nochange (); ! 663: end_temporary_allocation (); ! 664: ! 665: if (! IS_SIGNATURE (rhs_type)) ! 666: { ! 667: name = get_sigtable_name (sig_type, rhs_type); ! 668: decl = IDENTIFIER_GLOBAL_VALUE (name); ! 669: } ! 670: if (decl == NULL_TREE) ! 671: { ! 672: tree init; ! 673: ! 674: /* We allow only one signature table to be generated for signatures ! 675: with opaque types. Otherwise we create a loophole in the type ! 676: system since we could cast data from one classes implementation ! 677: of the opaque type to that of another class. */ ! 678: if (SIGNATURE_HAS_OPAQUE_TYPEDECLS (sig_type) ! 679: && SIGTABLE_HAS_BEEN_GENERATED (sig_type)) ! 680: { ! 681: error ("signature with opaque type implemented by multiple classes"); ! 682: return error_mark_node; ! 683: } ! 684: SIGTABLE_HAS_BEEN_GENERATED (sig_type) = 1; ! 685: ! 686: init_expr = build_signature_table_constructor (sig_type, init_from); ! 687: if (init_expr == NULL_TREE || TREE_CODE (init_expr) != CONSTRUCTOR) ! 688: return init_expr; ! 689: ! 690: if (name == NULL_TREE) ! 691: name = get_sigtable_name (sig_type, rhs_type); ! 692: { ! 693: tree context = current_function_decl; ! 694: ! 695: /* Make the signature table global, not just static in whichever ! 696: function a signature pointer/ref is used for the first time. */ ! 697: current_function_decl = NULL_TREE; ! 698: decl = pushdecl_top_level (build_decl (VAR_DECL, name, sig_type)); ! 699: current_function_decl = context; ! 700: } ! 701: IDENTIFIER_GLOBAL_VALUE (name) = decl; ! 702: store_init_value (decl, init_expr); ! 703: if (IS_SIGNATURE (rhs_type)) ! 704: { ! 705: init = DECL_INITIAL (decl); ! 706: DECL_INITIAL (decl) = error_mark_node; ! 707: } ! 708: ! 709: DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node), ! 710: DECL_ALIGN (decl)); ! 711: #if 0 ! 712: /* GDB-4.7 doesn't find the initialization value of a signature table ! 713: when it is constant. */ ! 714: TREE_READONLY (decl) = 1; ! 715: #endif ! 716: TREE_STATIC (decl) = 1; ! 717: TREE_USED (decl) = 1; ! 718: ! 719: make_decl_rtl (decl, NULL, 1); ! 720: if (IS_SIGNATURE (rhs_type)) ! 721: expand_static_init (decl, init); ! 722: } ! 723: ! 724: pop_obstacks (); ! 725: ! 726: return decl; ! 727: } ! 728: ! 729: /* Create a constructor or modify expression if the LHS of an assignment ! 730: is a signature pointer or a signature reference. If LHS is a record ! 731: type node, we build a constructor, otherwise a compound expression. */ ! 732: ! 733: tree ! 734: build_signature_pointer_constructor (lhs, rhs) ! 735: tree lhs, rhs; ! 736: { ! 737: register struct obstack *ambient_obstack = current_obstack; ! 738: register struct obstack *ambient_saveable_obstack = saveable_obstack; ! 739: int initp = (TREE_CODE (lhs) == RECORD_TYPE); ! 740: tree lhstype = initp ? lhs : TREE_TYPE (lhs); ! 741: tree rhstype = TREE_TYPE (rhs); ! 742: tree sig_ty = SIGNATURE_TYPE (lhstype); ! 743: tree sig_tbl, sptr_expr, optr_expr, vptr_expr; ! 744: tree result; ! 745: ! 746: if (! ((TREE_CODE (rhstype) == POINTER_TYPE ! 747: && TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE) ! 748: || (TYPE_LANG_SPECIFIC (rhstype) && ! 749: (IS_SIGNATURE_POINTER (rhstype) ! 750: || IS_SIGNATURE_REFERENCE (rhstype))))) ! 751: { ! 752: error ("invalid assignment to signature pointer or reference"); ! 753: return error_mark_node; ! 754: } ! 755: ! 756: if (TYPE_SIZE (sig_ty) == NULL_TREE) ! 757: { ! 758: cp_error ("undefined signature `%T' used in signature %s declaration", ! 759: sig_ty, ! 760: IS_SIGNATURE_POINTER (lhstype) ? "pointer" : "reference"); ! 761: return error_mark_node; ! 762: } ! 763: ! 764: /* If SIG_TY is permanent, make the signature table constructor and ! 765: the signature pointer/reference constructor permanent too. */ ! 766: if (TREE_PERMANENT (sig_ty)) ! 767: { ! 768: current_obstack = &permanent_obstack; ! 769: saveable_obstack = &permanent_obstack; ! 770: } ! 771: ! 772: if (TYPE_LANG_SPECIFIC (rhstype) && ! 773: (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype))) ! 774: { ! 775: if (SIGNATURE_TYPE (rhstype) == sig_ty) ! 776: { ! 777: /* LHS and RHS are signature pointers/refs of the same signature. */ ! 778: optr_expr = build_optr_ref (rhs); ! 779: sptr_expr = build_sptr_ref (rhs); ! 780: vptr_expr = build_vptr_ref (rhs); ! 781: } ! 782: else ! 783: { ! 784: /* We need to create a new signature table and copy ! 785: elements from the rhs signature table. */ ! 786: tree rhs_sptr_ref = build_sptr_ref (rhs); ! 787: tree rhs_tbl = build1 (INDIRECT_REF, SIGNATURE_TYPE (rhstype), ! 788: rhs_sptr_ref); ! 789: ! 790: sig_tbl = build_sigtable (sig_ty, SIGNATURE_TYPE (rhstype), rhs_tbl); ! 791: if (sig_tbl == error_mark_node) ! 792: return error_mark_node; ! 793: ! 794: optr_expr = build_optr_ref (rhs); ! 795: if (sig_tbl == NULL_TREE) ! 796: /* The signature was empty. The signature pointer is ! 797: pretty useless, but the user has been warned. */ ! 798: sptr_expr = copy_node (null_pointer_node); ! 799: else if (sig_tbl == integer_zero_node) ! 800: sptr_expr = rhs_sptr_ref; ! 801: else ! 802: sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); ! 803: TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); ! 804: vptr_expr = build_vptr_ref (rhs); ! 805: } ! 806: } ! 807: else ! 808: { ! 809: tree rhs_vptr; ! 810: ! 811: if (TYPE_USES_COMPLEX_INHERITANCE (TREE_TYPE (rhstype))) ! 812: { ! 813: sorry ("class with multiple inheritance as implementation of signature"); ! 814: return error_mark_node; ! 815: } ! 816: ! 817: sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs); ! 818: if (sig_tbl == error_mark_node) ! 819: return error_mark_node; ! 820: ! 821: optr_expr = rhs; ! 822: if (sig_tbl == NULL_TREE) ! 823: /* The signature was empty. The signature pointer is ! 824: pretty useless, but the user has been warned. */ ! 825: { ! 826: sptr_expr = copy_node (null_pointer_node); ! 827: TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); ! 828: } ! 829: else ! 830: sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); ! 831: if (CLASSTYPE_VFIELD (TREE_TYPE (rhstype))) ! 832: { ! 833: rhs_vptr = DECL_NAME (CLASSTYPE_VFIELD (TREE_TYPE (rhstype))); ! 834: vptr_expr = build_component_ref (build_indirect_ref (rhs, 0), ! 835: rhs_vptr, NULL_TREE, 0); ! 836: } ! 837: else ! 838: vptr_expr = copy_node (null_pointer_node); ! 839: TREE_TYPE (vptr_expr) = build_pointer_type (vtbl_type_node); ! 840: } ! 841: ! 842: if (initp) ! 843: { ! 844: result = tree_cons (NULL_TREE, optr_expr, ! 845: tree_cons (NULL_TREE, sptr_expr, ! 846: build_tree_list (NULL_TREE, vptr_expr))); ! 847: result = build_nt (CONSTRUCTOR, NULL_TREE, result); ! 848: TREE_HAS_CONSTRUCTOR (result) = 1; ! 849: result = digest_init (lhstype, result, 0); ! 850: } ! 851: else ! 852: { ! 853: if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)) ! 854: readonly_error (lhs, "assignment", 0); ! 855: ! 856: optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR, ! 857: optr_expr); ! 858: sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR, ! 859: sptr_expr); ! 860: vptr_expr = build_modify_expr (build_vptr_ref (lhs), NOP_EXPR, ! 861: vptr_expr); ! 862: ! 863: result = tree_cons (NULL_TREE, optr_expr, ! 864: tree_cons (NULL_TREE, sptr_expr, ! 865: tree_cons (NULL_TREE, vptr_expr, ! 866: build_tree_list (NULL_TREE, ! 867: lhs)))); ! 868: result = build_compound_expr (result); ! 869: } ! 870: ! 871: current_obstack = ambient_obstack; ! 872: saveable_obstack = ambient_saveable_obstack; ! 873: return result; ! 874: } ! 875: ! 876: /* Build a temporary variable declaration for the instance of a signature ! 877: member function call if it isn't a declaration node already. Simply ! 878: using a SAVE_EXPR doesn't work since we need `this' in both branches ! 879: of a conditional expression. */ ! 880: ! 881: static tree ! 882: save_this (instance) ! 883: tree instance; ! 884: { ! 885: tree decl; ! 886: ! 887: if (TREE_CODE_CLASS (TREE_CODE (instance)) == 'd') ! 888: decl = instance; ! 889: else ! 890: { ! 891: decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (instance)); ! 892: DECL_REGISTER (decl) = 1; ! 893: layout_decl (decl, 0); ! 894: expand_decl (decl); ! 895: } ! 896: ! 897: return decl; ! 898: } ! 899: ! 900: /* Build a signature member function call. Looks up the signature table ! 901: entry corresponding to FUNCTION. Depending on the value of the CODE ! 902: field, either call the function in PFN directly, or use OFFSET to ! 903: index INSTANCE's virtual function table. */ ! 904: ! 905: tree ! 906: build_signature_method_call (basetype, instance, function, parms) ! 907: tree basetype, instance, function, parms; ! 908: { ! 909: tree saved_instance = save_this (instance); /* Create temp for `this'. */ ! 910: tree signature_tbl_ptr = build_sptr_ref (saved_instance); ! 911: tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function)); ! 912: tree basetype_path = TYPE_BINFO (basetype); ! 913: tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype, ! 914: signature_tbl_ptr), ! 915: sig_field_name, basetype_path, 1); ! 916: tree code, offset, pfn, vfn; ! 917: tree deflt_call = NULL_TREE, direct_call, virtual_call, result; ! 918: ! 919: code = build_component_ref (tbl_entry, get_identifier (SIGTABLE_CODE_NAME), ! 920: NULL_TREE, 1); ! 921: offset = build_component_ref (tbl_entry, ! 922: get_identifier (SIGTABLE_OFFSET_NAME), ! 923: NULL_TREE, 1); ! 924: pfn = build_component_ref (tbl_entry, get_identifier (SIGTABLE_PFN_NAME), ! 925: NULL_TREE, 1); ! 926: TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function)); ! 927: ! 928: if (IS_DEFAULT_IMPLEMENTATION (function)) ! 929: { ! 930: pfn = save_expr (pfn); ! 931: deflt_call = build_function_call (pfn, ! 932: tree_cons (NULL_TREE, saved_instance, ! 933: TREE_CHAIN (parms))); ! 934: } ! 935: ! 936: { ! 937: /* Cast the signature method to have `this' of a normal pointer type. */ ! 938: tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))); ! 939: ! 940: TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = ! 941: build_type_variant (TYPE_POINTER_TO (basetype), ! 942: TYPE_READONLY (old_this), ! 943: TYPE_VOLATILE (old_this)); ! 944: ! 945: direct_call = build_function_call (pfn, parms); ! 946: ! 947: vfn = build_vfn_ref (&TREE_VALUE (parms), saved_instance, offset); ! 948: TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); ! 949: virtual_call = build_function_call (vfn, parms); ! 950: ! 951: /* Undo the cast, make `this' a signature pointer again. */ ! 952: TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this; ! 953: } ! 954: ! 955: /* Once the function was found, there should be no reason why we ! 956: couldn't build the member function pointer call. */ ! 957: if (!direct_call || direct_call == error_mark_node ! 958: || !virtual_call || virtual_call == error_mark_node ! 959: || (IS_DEFAULT_IMPLEMENTATION (function) ! 960: && (!deflt_call || deflt_call == error_mark_node))) ! 961: { ! 962: compiler_error ("cannot build call of signature member function `%s'", ! 963: fndecl_as_string (NULL, function, 1)); ! 964: return error_mark_node; ! 965: } ! 966: ! 967: if (IS_DEFAULT_IMPLEMENTATION (function)) ! 968: { ! 969: tree test = build_binary_op_nodefault (EQ_EXPR, code, integer_one_node, ! 970: EQ_EXPR); ! 971: result = build_conditional_expr (code, ! 972: build_conditional_expr (test, ! 973: virtual_call, ! 974: deflt_call), ! 975: direct_call); ! 976: } ! 977: else ! 978: result = build_conditional_expr (code, virtual_call, direct_call); ! 979: ! 980: /* If we created a temporary variable for `this', initialize it first. */ ! 981: if (instance != saved_instance) ! 982: result = build (COMPOUND_EXPR, TREE_TYPE (result), ! 983: build_modify_expr (saved_instance, NOP_EXPR, instance), ! 984: result); ! 985: ! 986: return result; ! 987: } ! 988: ! 989: /* Create a COMPONENT_REF expression for referencing the OPTR field ! 990: of a signature pointer or reference. */ ! 991: ! 992: tree ! 993: build_optr_ref (instance) ! 994: tree instance; ! 995: { ! 996: tree field = get_identifier (SIGNATURE_OPTR_NAME); ! 997: ! 998: return build_component_ref (instance, field, NULL_TREE, 1); ! 999: } ! 1000: ! 1001: /* Create a COMPONENT_REF expression for referencing the SPTR field ! 1002: of a signature pointer or reference. */ ! 1003: ! 1004: tree ! 1005: build_sptr_ref (instance) ! 1006: tree instance; ! 1007: { ! 1008: tree field = get_identifier (SIGNATURE_SPTR_NAME); ! 1009: ! 1010: return build_component_ref (instance, field, NULL_TREE, 1); ! 1011: } ! 1012: ! 1013: /* Create a COMPONENT_REF expression for referencing the VPTR field ! 1014: of a signature pointer or reference. */ ! 1015: ! 1016: tree ! 1017: build_vptr_ref (instance) ! 1018: tree instance; ! 1019: { ! 1020: tree field = get_identifier (SIGNATURE_VPTR_NAME); ! 1021: ! 1022: return build_component_ref (instance, field, NULL_TREE, 1); ! 1023: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.