|
|
1.1 ! root 1: /* Language-dependent node constructors for parse phase of GNU compiler. ! 2: Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. ! 3: Hacked by Michael Tiemann ([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: #include "config.h" ! 22: #include <stdio.h> ! 23: #include "obstack.h" ! 24: #include "tree.h" ! 25: #include "cp-tree.h" ! 26: #include "flags.h" ! 27: #include "assert.h" ! 28: ! 29: #define CEIL(x,y) (((x) + (y) - 1) / (y)) ! 30: ! 31: /* Return nonzero if REF is an lvalue valid for this language. ! 32: Lvalues can be assigned, unless they have TREE_READONLY. ! 33: Lvalues can have their address taken, unless they have TREE_REGDECL. */ ! 34: ! 35: int ! 36: lvalue_p (ref) ! 37: tree ref; ! 38: { ! 39: register enum tree_code code = TREE_CODE (ref); ! 40: ! 41: if (language_lvalue_valid (ref)) ! 42: switch (code) ! 43: { ! 44: case COMPONENT_REF: ! 45: return lvalue_p (TREE_OPERAND (ref, 0)); ! 46: ! 47: case STRING_CST: ! 48: return 1; ! 49: ! 50: case VAR_DECL: ! 51: if (TREE_READONLY (ref) && ! TREE_STATIC (ref) ! 52: && DECL_LANG_SPECIFIC (ref) ! 53: && DECL_IN_AGGR_P (ref)) ! 54: return 0; ! 55: case INDIRECT_REF: ! 56: case ARRAY_REF: ! 57: case PARM_DECL: ! 58: case RESULT_DECL: ! 59: case ERROR_MARK: ! 60: if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE ! 61: && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) ! 62: return 1; ! 63: break; ! 64: ! 65: case TARGET_EXPR: ! 66: case WITH_CLEANUP_EXPR: ! 67: return 1; ! 68: ! 69: case CALL_EXPR: ! 70: if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE ! 71: /* unary_complex_lvalue knows how to deal with this case. */ ! 72: || TREE_ADDRESSABLE (TREE_TYPE (ref))) ! 73: return 1; ! 74: break; ! 75: ! 76: /* A currently unresolved scope ref. */ ! 77: case SCOPE_REF: ! 78: abort (); ! 79: case OFFSET_REF: ! 80: if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) ! 81: return 1; ! 82: if (TREE_CODE (TREE_OPERAND (ref, 1)) == VAR_DECL) ! 83: if (TREE_READONLY (ref) && ! TREE_STATIC (ref) ! 84: && DECL_LANG_SPECIFIC (ref) ! 85: && DECL_IN_AGGR_P (ref)) ! 86: return 0; ! 87: else ! 88: return 1; ! 89: break; ! 90: } ! 91: return 0; ! 92: } ! 93: ! 94: /* Return nonzero if REF is an lvalue valid for this language; ! 95: otherwise, print an error message and return zero. */ ! 96: ! 97: int ! 98: lvalue_or_else (ref, string) ! 99: tree ref; ! 100: char *string; ! 101: { ! 102: int win = lvalue_p (ref); ! 103: if (! win) ! 104: error ("invalid lvalue in %s", string); ! 105: return win; ! 106: } ! 107: ! 108: /* INIT is a CALL_EXPR which needs info about its target. ! 109: TYPE is the type that this initialization should appear to have. ! 110: ! 111: Build an encapsulation of the initialization to perform ! 112: and return it so that it can be processed by language-independent ! 113: and language-specific expression expanders. ! 114: ! 115: If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression. ! 116: Otherwise, cleanups are not built here. For example, when building ! 117: an initialization for a stack slot, since the called function handles ! 118: the cleanup, we would not want to do it here. */ ! 119: tree ! 120: build_cplus_new (type, init, with_cleanup_p) ! 121: tree type; ! 122: tree init; ! 123: int with_cleanup_p; ! 124: { ! 125: tree slot = build (VAR_DECL, type); ! 126: tree rval = build (NEW_EXPR, type, ! 127: TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); ! 128: TREE_ADDRESSABLE (rval) = 1; ! 129: rval = build (TARGET_EXPR, type, slot, rval, 0); ! 130: TREE_SIDE_EFFECTS (rval) = 1; ! 131: TREE_ADDRESSABLE (rval) = 1; ! 132: ! 133: if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type)) ! 134: rval = build (WITH_CLEANUP_EXPR, type, rval, 0, ! 135: build_delete (TYPE_POINTER_TO (type), ! 136: build_unary_op (ADDR_EXPR, slot, 0), ! 137: integer_two_node, ! 138: LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0)); ! 139: TREE_SIDE_EFFECTS (rval) = 1; ! 140: return rval; ! 141: } ! 142: ! 143: tree ! 144: break_out_cleanups (exp) ! 145: tree exp; ! 146: { ! 147: tree tmp = exp; ! 148: ! 149: if (TREE_CODE (tmp) == CALL_EXPR ! 150: && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp))) ! 151: return build_cplus_new (TREE_TYPE (tmp), tmp, 1); ! 152: ! 153: while (TREE_CODE (tmp) == NOP_EXPR ! 154: || TREE_CODE (tmp) == CONVERT_EXPR ! 155: || TREE_CODE (tmp) == NON_LVALUE_EXPR) ! 156: { ! 157: if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR ! 158: && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0)))) ! 159: { ! 160: TREE_OPERAND (tmp, 0) ! 161: = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)), ! 162: TREE_OPERAND (tmp, 0), 1); ! 163: break; ! 164: } ! 165: else ! 166: tmp = TREE_OPERAND (tmp, 0); ! 167: } ! 168: return exp; ! 169: } ! 170: ! 171: extern struct obstack *current_obstack; ! 172: extern struct obstack permanent_obstack, class_obstack; ! 173: extern struct obstack *saveable_obstack; ! 174: ! 175: /* Here is how primitive or already-canonicalized types' hash ! 176: codes are made. MUST BE CONSISTENT WITH tree.c !!! */ ! 177: #define TYPE_HASH(TYPE) ((int) (TYPE) & 0777777) ! 178: ! 179: /* Construct, lay out and return the type of methods belonging to class ! 180: BASETYPE and whose arguments and values are described by TYPE. ! 181: If that type exists already, reuse it. ! 182: TYPE must be a FUNCTION_TYPE node. */ ! 183: ! 184: tree ! 185: build_cplus_method_type (basetype, rettype, argtypes) ! 186: tree basetype, rettype, argtypes; ! 187: { ! 188: register tree t; ! 189: tree ptype = build_pointer_type (basetype); ! 190: int hashcode; ! 191: ! 192: /* Make a node of the sort we want. */ ! 193: t = make_node (METHOD_TYPE); ! 194: ! 195: TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); ! 196: TREE_TYPE (t) = rettype; ! 197: ptype = build_type_variant (ptype, !flag_this_is_variable, 0); ! 198: ! 199: /* The actual arglist for this function includes a "hidden" argument ! 200: which is "this". Put it into the list of argument types. */ ! 201: ! 202: TYPE_ARG_TYPES (t) = tree_cons (NULL, ptype, argtypes); ! 203: ! 204: /* If we already have such a type, use the old one and free this one. ! 205: Note that it also frees up the above cons cell if found. */ ! 206: hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes); ! 207: t = type_hash_canon (hashcode, t); ! 208: ! 209: if (TYPE_SIZE (t) == 0) ! 210: layout_type (t); ! 211: ! 212: return t; ! 213: } ! 214: ! 215: tree ! 216: build_cplus_staticfn_type (basetype, rettype, argtypes) ! 217: tree basetype, rettype, argtypes; ! 218: { ! 219: register tree t; ! 220: tree ptype = build_pointer_type (basetype); ! 221: int hashcode; ! 222: ! 223: /* Make a node of the sort we want. */ ! 224: t = make_node (FUNCTION_TYPE); ! 225: ! 226: TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); ! 227: TREE_TYPE (t) = rettype; ! 228: ! 229: /* The actual arglist for this function includes a "hidden" argument ! 230: which is "this". Put it into the list of argument types. */ ! 231: ! 232: TYPE_ARG_TYPES (t) = argtypes; ! 233: ! 234: /* If we already have such a type, use the old one and free this one. ! 235: Note that it also frees up the above cons cell if found. */ ! 236: hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes); ! 237: t = type_hash_canon (hashcode, t); ! 238: ! 239: if (TYPE_SIZE (t) == 0) ! 240: layout_type (t); ! 241: ! 242: return t; ! 243: } ! 244: ! 245: tree ! 246: build_cplus_array_type (elt_type, index_type) ! 247: tree elt_type; ! 248: tree index_type; ! 249: { ! 250: register struct obstack *ambient_obstack = current_obstack; ! 251: register struct obstack *ambient_saveable_obstack = saveable_obstack; ! 252: tree t; ! 253: ! 254: /* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent, ! 255: make this permanent too. */ ! 256: if (TREE_PERMANENT (elt_type) ! 257: && (index_type == 0 || TREE_PERMANENT (index_type))) ! 258: { ! 259: current_obstack = &permanent_obstack; ! 260: saveable_obstack = &permanent_obstack; ! 261: } ! 262: ! 263: t = build_array_type (elt_type, index_type); ! 264: ! 265: /* Push these needs up so that initialization takes place ! 266: more easily. */ ! 267: TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type)); ! 268: TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type)); ! 269: current_obstack = ambient_obstack; ! 270: saveable_obstack = ambient_saveable_obstack; ! 271: return t; ! 272: } ! 273: ! 274: /* This is temporary until later. */ ! 275: /* Construct, lay out and return the type of objects which are of type TYPE ! 276: as members of type BASETYPE. If that type exists already, reuse it. */ ! 277: tree ! 278: build_member_type (basetype, type) ! 279: tree basetype, type; ! 280: { ! 281: register tree t; ! 282: int hashcode; ! 283: ! 284: assert (TREE_CODE (type) != FUNCTION_TYPE); ! 285: ! 286: /* Make a node of the sort we want. */ ! 287: t = make_node (OFFSET_TYPE); ! 288: TYPE_OFFSET_BASETYPE (t) = basetype; ! 289: TREE_TYPE (t) = type; ! 290: hashcode = TYPE_HASH (basetype) + TYPE_HASH (type); ! 291: t = type_hash_canon (hashcode, t); ! 292: ! 293: return t; ! 294: } ! 295: ! 296: /* Add OFFSET to all child types of T. ! 297: ! 298: OFFSET, which is a type offset, is number of bytes. ! 299: ! 300: Note that we don't have to worry about having two paths to the ! 301: same base type, since this type owns its association list. */ ! 302: void ! 303: propagate_binfo_offsets (binfo, offset) ! 304: tree binfo; ! 305: tree offset; ! 306: { ! 307: tree t = BINFO_TYPE (binfo); ! 308: tree binfos = BINFO_BASETYPES (binfo); ! 309: int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; ! 310: ! 311: for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) ! 312: { ! 313: tree child = TREE_VEC_ELT (binfos, i); ! 314: ! 315: if (TREE_VIA_VIRTUAL (child)) ! 316: i += 1; ! 317: else ! 318: { ! 319: int j; ! 320: tree child_binfos = BINFO_BASETYPES (child); ! 321: tree basetype = BINFO_TYPE (child); ! 322: tree delta; ! 323: ! 324: for (j = i+1; j < n_baselinks; j++) ! 325: if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) ! 326: { ! 327: /* The next basetype offset must take into account the space ! 328: between the classes, not just the size of each class. */ ! 329: delta = size_binop (MINUS_EXPR, ! 330: BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), ! 331: BINFO_OFFSET (child)); ! 332: break; ! 333: } ! 334: ! 335: #if 0 ! 336: if (BINFO_OFFSET_ZEROP (child)) ! 337: BINFO_OFFSET (child) = offset; ! 338: else ! 339: BINFO_OFFSET (child) ! 340: = size_binop (PLUS_EXPR, BINFO_OFFSET (child), offset); ! 341: #else ! 342: BINFO_OFFSET (child) = offset; ! 343: #endif ! 344: if (child_binfos) ! 345: { ! 346: int k; ! 347: tree chain = NULL_TREE; ! 348: ! 349: /* Now unshare the structure beneath CHILD. */ ! 350: for (k = TREE_VEC_LENGTH (child_binfos)-1; ! 351: k >= 0; k--) ! 352: { ! 353: tree child_child = TREE_VEC_ELT (child_binfos, k); ! 354: if (! TREE_VIA_VIRTUAL (child_child)) ! 355: TREE_VEC_ELT (child_binfos, k) ! 356: = make_binfo (BINFO_OFFSET (child_child), ! 357: BINFO_TYPE (child_child), ! 358: BINFO_VTABLE (child_child), ! 359: BINFO_VIRTUALS (child_child), ! 360: chain); ! 361: chain = TREE_VEC_ELT (child_binfos, k); ! 362: TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (child_child); ! 363: } ! 364: /* Now propagate the offset to the children. */ ! 365: propagate_binfo_offsets (child, offset); ! 366: } ! 367: ! 368: /* Go to our next class that counts for offset propagation. */ ! 369: i = j; ! 370: if (i < n_baselinks) ! 371: offset = size_binop (PLUS_EXPR, offset, delta); ! 372: } ! 373: } ! 374: } ! 375: ! 376: /* Compute the actual offsets that our virtual base classes ! 377: will have *for this type*. This must be performed after ! 378: the fields are laid out, since virtual baseclasses must ! 379: lay down at the end of the record. ! 380: ! 381: Returns the maximum number of virtual functions any of the virtual ! 382: baseclasses provide. */ ! 383: int ! 384: layout_vbasetypes (rec, max) ! 385: tree rec; ! 386: int max; ! 387: { ! 388: /* Get all the virtual base types that this type uses. ! 389: The TREE_VALUE slot holds the virtual baseclass type. */ ! 390: tree vbase_types = get_vbase_types (rec); ! 391: ! 392: #ifdef STRUCTURE_SIZE_BOUNDARY ! 393: unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); ! 394: #else ! 395: unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); ! 396: #endif ! 397: ! 398: /* Record size so far is CONST_SIZE + VAR_SIZE bits, ! 399: where CONST_SIZE is an integer ! 400: and VAR_SIZE is a tree expression. ! 401: If VAR_SIZE is null, the size is just CONST_SIZE. ! 402: Naturally we try to avoid using VAR_SIZE. */ ! 403: register unsigned const_size = 0; ! 404: register tree var_size = 0; ! 405: int nonvirtual_const_size; ! 406: tree nonvirtual_var_size; ! 407: ! 408: CLASSTYPE_VBASECLASSES (rec) = vbase_types; ! 409: ! 410: if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST) ! 411: const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec)); ! 412: else ! 413: var_size = TYPE_SIZE (rec); ! 414: ! 415: nonvirtual_const_size = const_size; ! 416: nonvirtual_var_size = var_size; ! 417: ! 418: while (vbase_types) ! 419: { ! 420: tree basetype = BINFO_TYPE (vbase_types); ! 421: tree offset; ! 422: ! 423: if (const_size == 0) ! 424: offset = integer_zero_node; ! 425: else ! 426: offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); ! 427: ! 428: if (CLASSTYPE_VSIZE (basetype) > max) ! 429: max = CLASSTYPE_VSIZE (basetype); ! 430: BINFO_OFFSET (vbase_types) = offset; ! 431: ! 432: if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST) ! 433: const_size += MAX (record_align, ! 434: TREE_INT_CST_LOW (TYPE_SIZE (basetype)) ! 435: - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); ! 436: else if (var_size == 0) ! 437: var_size = TYPE_SIZE (basetype); ! 438: else ! 439: var_size = size_binop (PLUS_EXPR, var_size, TYPE_SIZE (basetype)); ! 440: ! 441: vbase_types = TREE_CHAIN (vbase_types); ! 442: } ! 443: ! 444: if (const_size != nonvirtual_const_size) ! 445: { ! 446: CLASSTYPE_VBASE_SIZE (rec) ! 447: = size_int (const_size - nonvirtual_const_size); ! 448: TYPE_SIZE (rec) = size_int (const_size); ! 449: } ! 450: ! 451: /* Now propagate offset information throughout the lattice ! 452: under the vbase type. */ ! 453: for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types; ! 454: vbase_types = TREE_CHAIN (vbase_types)) ! 455: { ! 456: tree child_binfos = BINFO_BASETYPES (vbase_types); ! 457: ! 458: if (child_binfos) ! 459: { ! 460: tree chain = NULL_TREE; ! 461: int j; ! 462: /* Now unshare the structure beneath CHILD. */ ! 463: ! 464: for (j = TREE_VEC_LENGTH (child_binfos)-1; ! 465: j >= 0; j--) ! 466: { ! 467: tree child_child = TREE_VEC_ELT (child_binfos, j); ! 468: if (! TREE_VIA_VIRTUAL (child_child)) ! 469: TREE_VEC_ELT (child_binfos, j) ! 470: = make_binfo (BINFO_OFFSET (child_child), ! 471: BINFO_TYPE (child_child), ! 472: BINFO_VTABLE (child_child), ! 473: BINFO_VIRTUALS (child_child), ! 474: chain); ! 475: chain = TREE_VEC_ELT (child_binfos, j); ! 476: TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (child_child); ! 477: } ! 478: ! 479: propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); ! 480: } ! 481: } ! 482: ! 483: return max; ! 484: } ! 485: ! 486: /* Lay out the base types of a record type, REC. ! 487: Tentatively set the size and alignment of REC ! 488: according to the base types alone. ! 489: ! 490: Offsets for immediate nonvirtual baseclasses are also computed here. ! 491: ! 492: Returns list of virtual base classes in a FIELD_DECL chain. */ ! 493: tree ! 494: layout_basetypes (rec, binfos) ! 495: tree rec, binfos; ! 496: { ! 497: /* Chain to hold all the new FIELD_DECLs which point at virtual ! 498: base classes. */ ! 499: tree vbase_decls = NULL_TREE; ! 500: ! 501: #ifdef STRUCTURE_SIZE_BOUNDARY ! 502: int record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); ! 503: #else ! 504: int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); ! 505: #endif ! 506: ! 507: /* Record size so far is CONST_SIZE + VAR_SIZE bits, ! 508: where CONST_SIZE is an integer ! 509: and VAR_SIZE is a tree expression. ! 510: If VAR_SIZE is null, the size is just CONST_SIZE. ! 511: Naturally we try to avoid using VAR_SIZE. */ ! 512: register int const_size = 0; ! 513: register tree var_size = 0; ! 514: int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; ! 515: ! 516: /* Handle basetypes almost like fields, but record their ! 517: offsets differently. */ ! 518: ! 519: for (i = 0; i < n_baseclasses; i++) ! 520: { ! 521: int inc, desired_align, int_vbase_size; ! 522: register tree child = TREE_VEC_ELT (binfos, i); ! 523: register tree basetype = BINFO_TYPE (child); ! 524: tree decl, offset; ! 525: ! 526: if (TYPE_SIZE (basetype) == 0) ! 527: { ! 528: error_with_aggr_type (child, "base class `%s' has incomplete type"); ! 529: TREE_VIA_PUBLIC (child) = 1; ! 530: TREE_VIA_VIRTUAL (child) = 0; ! 531: continue; ! 532: } ! 533: ! 534: /* All basetypes are recorded in the association list of the ! 535: derived type. */ ! 536: ! 537: if (TREE_VIA_VIRTUAL (child)) ! 538: { ! 539: tree binfo; ! 540: int j; ! 541: char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype) ! 542: + sizeof (VBASE_NAME) + 1); ! 543: ! 544: /* The offset for a virtual base class is only used in computing ! 545: virtual function tables and for initializing virtual base ! 546: pointers. It is built once `get_vbase_types' is called. */ ! 547: ! 548: /* If this basetype can come from another vbase pointer ! 549: without an additional indirection, we will share ! 550: that pointer. If an indirection is involved, we ! 551: make our own pointer. */ ! 552: for (j = 0; j < n_baseclasses; j++) ! 553: { ! 554: tree other_child = TREE_VEC_ELT (binfos, j); ! 555: if (! TREE_VIA_VIRTUAL (other_child) ! 556: && binfo_member (basetype, ! 557: CLASSTYPE_VBASECLASSES (BINFO_TYPE (other_child)))) ! 558: goto got_it; ! 559: } ! 560: sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); ! 561: decl = build_lang_decl (FIELD_DECL, get_identifier (name), ! 562: build_pointer_type (basetype)); ! 563: DECL_ASSEMBLER_NAME (decl) = get_identifier ("$vb"); ! 564: DECL_VIRTUAL_P (decl) = 1; ! 565: DECL_FIELD_CONTEXT (decl) = rec; ! 566: DECL_CLASS_CONTEXT (decl) = rec; ! 567: DECL_FCONTEXT (decl) = basetype; ! 568: TREE_CHAIN (decl) = vbase_decls; ! 569: vbase_decls = decl; ! 570: ! 571: if (TYPE_HAS_DESTRUCTOR (basetype) ! 572: && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) ! 573: { ! 574: warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), ! 575: "destructor `%s' non-virtual"); ! 576: warning ("in inheritance relationship `%s: virtual %s'", ! 577: TYPE_NAME_STRING (rec), ! 578: TYPE_NAME_STRING (basetype)); ! 579: } ! 580: got_it: ! 581: /* The space this decl occupies has already been accounted for. */ ! 582: continue; ! 583: } ! 584: ! 585: if (const_size == 0) ! 586: offset = integer_zero_node; ! 587: else ! 588: { ! 589: /* Give each base type the alignment it wants. */ ! 590: const_size = CEIL (const_size, TYPE_ALIGN (basetype)) ! 591: * TYPE_ALIGN (basetype); ! 592: offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); ! 593: ! 594: if (TYPE_HAS_DESTRUCTOR (basetype) ! 595: && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) ! 596: { ! 597: warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0), ! 598: "destructor `%s' non-virtual"); ! 599: warning ("in inheritance relationship `%s: virtual %s'", ! 600: TYPE_NAME_STRING (rec), ! 601: TYPE_NAME_STRING (basetype)); ! 602: } ! 603: } ! 604: BINFO_OFFSET (child) = offset; ! 605: if (CLASSTYPE_VSIZE (basetype)) ! 606: { ! 607: BINFO_VTABLE (child) = TYPE_BINFO_VTABLE (basetype); ! 608: BINFO_VIRTUALS (child) = TYPE_BINFO_VIRTUALS (basetype); ! 609: } ! 610: TREE_CHAIN (child) = TYPE_BINFO (rec); ! 611: TYPE_BINFO (rec) = child; ! 612: ! 613: /* Add only the amount of storage not present in ! 614: the virtual baseclasses. */ ! 615: ! 616: int_vbase_size = TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)); ! 617: if (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) > int_vbase_size) ! 618: { ! 619: inc = MAX (record_align, ! 620: (TREE_INT_CST_LOW (TYPE_SIZE (basetype)) ! 621: - int_vbase_size)); ! 622: ! 623: /* Record must have at least as much alignment as any field. */ ! 624: desired_align = TYPE_ALIGN (basetype); ! 625: record_align = MAX (record_align, desired_align); ! 626: ! 627: const_size += inc; ! 628: } ! 629: } ! 630: ! 631: if (const_size) ! 632: CLASSTYPE_SIZE (rec) = size_int (const_size); ! 633: else ! 634: CLASSTYPE_SIZE (rec) = integer_zero_node; ! 635: CLASSTYPE_ALIGN (rec) = record_align; ! 636: ! 637: return vbase_decls; ! 638: } ! 639: ! 640: /* Hashing of lists so that we don't make duplicates. ! 641: The entry point is `list_hash_canon'. */ ! 642: ! 643: /* Each hash table slot is a bucket containing a chain ! 644: of these structures. */ ! 645: ! 646: struct list_hash ! 647: { ! 648: struct list_hash *next; /* Next structure in the bucket. */ ! 649: int hashcode; /* Hash code of this list. */ ! 650: tree list; /* The list recorded here. */ ! 651: }; ! 652: ! 653: /* Now here is the hash table. When recording a list, it is added ! 654: to the slot whose index is the hash code mod the table size. ! 655: Note that the hash table is used for several kinds of lists. ! 656: While all these live in the same table, they are completely independent, ! 657: and the hash code is computed differently for each of these. */ ! 658: ! 659: #define TYPE_HASH_SIZE 59 ! 660: struct list_hash *list_hash_table[TYPE_HASH_SIZE]; ! 661: ! 662: /* Compute a hash code for a list (chain of TREE_LIST nodes ! 663: with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the ! 664: TREE_COMMON slots), by adding the hash codes of the individual entries. */ ! 665: ! 666: int ! 667: list_hash (list) ! 668: tree list; ! 669: { ! 670: register int hashcode = 0; ! 671: ! 672: if (TREE_CHAIN (list)) ! 673: hashcode += TYPE_HASH (TREE_CHAIN (list)); ! 674: ! 675: if (TREE_VALUE (list)) ! 676: hashcode += TYPE_HASH (TREE_VALUE (list)); ! 677: else ! 678: hashcode += 1007; ! 679: if (TREE_PURPOSE (list)) ! 680: hashcode += TYPE_HASH (TREE_PURPOSE (list)); ! 681: else ! 682: hashcode += 1009; ! 683: return hashcode; ! 684: } ! 685: ! 686: /* Look in the type hash table for a type isomorphic to TYPE. ! 687: If one is found, return it. Otherwise return 0. */ ! 688: ! 689: tree ! 690: list_hash_lookup (hashcode, list) ! 691: int hashcode; ! 692: tree list; ! 693: { ! 694: register struct list_hash *h; ! 695: for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) ! 696: if (h->hashcode == hashcode ! 697: && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list) ! 698: && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list) ! 699: && TREE_PURPOSE (h->list) == TREE_PURPOSE (list) ! 700: && TREE_VALUE (h->list) == TREE_VALUE (list) ! 701: && TREE_CHAIN (h->list) == TREE_CHAIN (list)) ! 702: { ! 703: assert (TREE_TYPE (h->list) == TREE_TYPE (list)); ! 704: return h->list; ! 705: } ! 706: return 0; ! 707: } ! 708: ! 709: /* Add an entry to the list-hash-table ! 710: for a list TYPE whose hash code is HASHCODE. */ ! 711: ! 712: void ! 713: list_hash_add (hashcode, list) ! 714: int hashcode; ! 715: tree list; ! 716: { ! 717: register struct list_hash *h; ! 718: ! 719: h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash)); ! 720: h->hashcode = hashcode; ! 721: h->list = list; ! 722: h->next = list_hash_table[hashcode % TYPE_HASH_SIZE]; ! 723: list_hash_table[hashcode % TYPE_HASH_SIZE] = h; ! 724: } ! 725: ! 726: /* Given TYPE, and HASHCODE its hash code, return the canonical ! 727: object for an identical list if one already exists. ! 728: Otherwise, return TYPE, and record it as the canonical object ! 729: if it is a permanent object. ! 730: ! 731: To use this function, first create a list of the sort you want. ! 732: Then compute its hash code from the fields of the list that ! 733: make it different from other similar lists. ! 734: Then call this function and use the value. ! 735: This function frees the list you pass in if it is a duplicate. */ ! 736: ! 737: /* Set to 1 to debug without canonicalization. Never set by program. */ ! 738: int debug_no_list_hash = 0; ! 739: ! 740: tree ! 741: list_hash_canon (hashcode, list) ! 742: int hashcode; ! 743: tree list; ! 744: { ! 745: tree t1; ! 746: ! 747: if (debug_no_list_hash) ! 748: return list; ! 749: ! 750: t1 = list_hash_lookup (hashcode, list); ! 751: if (t1 != 0) ! 752: { ! 753: obstack_free (&class_obstack, list); ! 754: return t1; ! 755: } ! 756: ! 757: /* If this is a new list, record it for later reuse. */ ! 758: list_hash_add (hashcode, list); ! 759: ! 760: return list; ! 761: } ! 762: ! 763: tree ! 764: hash_tree_cons (via_public, via_virtual, purpose, value, chain) ! 765: int via_public, via_virtual; ! 766: tree purpose, value, chain; ! 767: { ! 768: struct obstack *ambient_obstack = current_obstack; ! 769: tree t; ! 770: int hashcode; ! 771: ! 772: current_obstack = &class_obstack; ! 773: t = tree_cons (purpose, value, chain); ! 774: TREE_VIA_PUBLIC (t) = via_public; ! 775: TREE_VIA_VIRTUAL (t) = via_virtual; ! 776: hashcode = list_hash (t); ! 777: t = list_hash_canon (hashcode, t); ! 778: current_obstack = ambient_obstack; ! 779: return t; ! 780: } ! 781: ! 782: /* Constructor for hashed lists. */ ! 783: tree ! 784: hash_tree_chain (value, chain) ! 785: tree value, chain; ! 786: { ! 787: struct obstack *ambient_obstack = current_obstack; ! 788: tree t; ! 789: int hashcode; ! 790: ! 791: current_obstack = &class_obstack; ! 792: t = tree_cons (NULL_TREE, value, chain); ! 793: hashcode = list_hash (t); ! 794: t = list_hash_canon (hashcode, t); ! 795: current_obstack = ambient_obstack; ! 796: return t; ! 797: } ! 798: ! 799: /* Similar, but used for concatenating two lists. */ ! 800: tree ! 801: hash_chainon (list1, list2) ! 802: tree list1, list2; ! 803: { ! 804: if (list2 == 0) ! 805: return list1; ! 806: if (list1 == 0) ! 807: return list2; ! 808: if (TREE_CHAIN (list1) == NULL_TREE) ! 809: return hash_tree_chain (TREE_VALUE (list1), list2); ! 810: return hash_tree_chain (TREE_VALUE (list1), ! 811: hash_chainon (TREE_CHAIN (list1), list2)); ! 812: } ! 813: ! 814: tree ! 815: get_decl_list (value) ! 816: tree value; ! 817: { ! 818: tree list = NULL_TREE; ! 819: ! 820: if (TREE_CODE (value) == IDENTIFIER_NODE) ! 821: { ! 822: list = IDENTIFIER_AS_LIST (value); ! 823: if (list != NULL_TREE ! 824: && (TREE_CODE (list) != TREE_LIST ! 825: || TREE_VALUE (list) != value)) ! 826: list = NULL_TREE; ! 827: else if (IDENTIFIER_HAS_TYPE_VALUE (value) ! 828: && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE) ! 829: { ! 830: tree type = IDENTIFIER_TYPE_VALUE (value); ! 831: if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) ! 832: CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, NULL_TREE); ! 833: list = CLASSTYPE_ID_AS_LIST (type); ! 834: } ! 835: } ! 836: else if (TREE_CODE (value) == RECORD_TYPE ! 837: && TYPE_LANG_SPECIFIC (value)) ! 838: list = CLASSTYPE_AS_LIST (value); ! 839: ! 840: if (list != NULL_TREE) ! 841: { ! 842: assert (TREE_CHAIN (list) == NULL_TREE); ! 843: return list; ! 844: } ! 845: ! 846: return build_decl_list (NULL_TREE, value); ! 847: } ! 848: ! 849: /* Look in the type hash table for a type isomorphic to ! 850: `build_tree_list (NULL_TREE, VALUE)'. ! 851: If one is found, return it. Otherwise return 0. */ ! 852: ! 853: tree ! 854: list_hash_lookup_or_cons (value) ! 855: tree value; ! 856: { ! 857: register int hashcode = TYPE_HASH (value); ! 858: register struct list_hash *h; ! 859: struct obstack *ambient_obstack; ! 860: tree list = NULL_TREE; ! 861: ! 862: if (TREE_CODE (value) == IDENTIFIER_NODE) ! 863: { ! 864: list = IDENTIFIER_AS_LIST (value); ! 865: if (list != NULL_TREE ! 866: && (TREE_CODE (list) != TREE_LIST ! 867: || TREE_VALUE (list) != value)) ! 868: list = NULL_TREE; ! 869: else if (IDENTIFIER_HAS_TYPE_VALUE (value) ! 870: && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE) ! 871: { ! 872: /* If the type name and constructor name are different, don't ! 873: write constructor name into type. */ ! 874: extern tree constructor_name (); ! 875: if (IDENTIFIER_TYPEDECL_VALUE (value) ! 876: && IDENTIFIER_TYPEDECL_VALUE (value) != constructor_name (value)) ! 877: list = tree_cons (NULL_TREE, value, NULL_TREE); ! 878: else ! 879: { ! 880: tree type = IDENTIFIER_TYPE_VALUE (value); ! 881: if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) ! 882: CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, ! 883: NULL_TREE); ! 884: list = CLASSTYPE_ID_AS_LIST (type); ! 885: } ! 886: } ! 887: } ! 888: else if (TREE_CODE (value) == TYPE_DECL ! 889: && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE ! 890: && TYPE_LANG_SPECIFIC (TREE_TYPE (value))) ! 891: list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value)); ! 892: else if (TREE_CODE (value) == RECORD_TYPE ! 893: && TYPE_LANG_SPECIFIC (value)) ! 894: list = CLASSTYPE_AS_LIST (value); ! 895: ! 896: if (list != NULL_TREE) ! 897: { ! 898: assert (TREE_CHAIN (list) == NULL_TREE); ! 899: return list; ! 900: } ! 901: ! 902: if (debug_no_list_hash) ! 903: return hash_tree_chain (value, NULL_TREE); ! 904: ! 905: for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) ! 906: if (h->hashcode == hashcode ! 907: && TREE_VIA_VIRTUAL (h->list) == 0 ! 908: && TREE_VIA_PUBLIC (h->list) == 0 ! 909: && TREE_PURPOSE (h->list) == 0 ! 910: && TREE_VALUE (h->list) == value) ! 911: { ! 912: assert (TREE_TYPE (h->list) == 0); ! 913: assert (TREE_CHAIN (h->list) == 0); ! 914: return h->list; ! 915: } ! 916: ! 917: ambient_obstack = current_obstack; ! 918: current_obstack = &class_obstack; ! 919: list = build_tree_list (NULL_TREE, value); ! 920: list_hash_add (hashcode, list); ! 921: current_obstack = ambient_obstack; ! 922: return list; ! 923: } ! 924: ! 925: /* Build an association between TYPE and some parameters: ! 926: ! 927: OFFSET is the offset added to `this' to convert it to a pointer ! 928: of type `TYPE *' ! 929: ! 930: VTABLE is the virtual function table with which to initialize ! 931: sub-objects of type TYPE. ! 932: ! 933: VIRTUALS are the virtual functions sitting in VTABLE. ! 934: ! 935: CHAIN are more associations we must retain. */ ! 936: ! 937: tree ! 938: make_binfo (offset, type, vtable, virtuals, chain) ! 939: tree offset, type; ! 940: tree vtable, virtuals; ! 941: tree chain; ! 942: { ! 943: tree binfo = make_tree_vec (5); ! 944: tree old_binfo = TYPE_BINFO (type); ! 945: tree last; ! 946: ! 947: TREE_CHAIN (binfo) = chain; ! 948: if (chain) ! 949: TREE_USED (binfo) = TREE_USED (chain); ! 950: ! 951: TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type); ! 952: TREE_VEC_ELT (binfo, 1) = offset; ! 953: TREE_VEC_ELT (binfo, 2) = vtable; ! 954: TREE_VEC_ELT (binfo, 3) = virtuals; ! 955: ! 956: last = binfo; ! 957: if (old_binfo != NULL_TREE ! 958: && BINFO_BASETYPES (old_binfo) != NULL_TREE) ! 959: { ! 960: int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type); ! 961: tree binfos = TYPE_BINFO_BASETYPES (type); ! 962: ! 963: BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses); ! 964: for (i = 0; i < n_baseclasses; i++) ! 965: { ! 966: tree child = TREE_VEC_ELT (binfos, i); ! 967: tree old_child = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0; ! 968: BINFO_BASETYPE (binfo, i) = child; ! 969: if (old_binfo) ! 970: { ! 971: TREE_VIA_PUBLIC (child) = TREE_VIA_PUBLIC (old_child); ! 972: TREE_VIA_VIRTUAL (child) = TREE_VIA_VIRTUAL (old_child); ! 973: } ! 974: } ! 975: } ! 976: return binfo; ! 977: } ! 978: ! 979: tree ! 980: copy_binfo (list) ! 981: tree list; ! 982: { ! 983: tree binfo = copy_list (list); ! 984: tree rval = binfo; ! 985: while (binfo) ! 986: { ! 987: TREE_USED (binfo) = 0; ! 988: if (BINFO_BASETYPES (binfo)) ! 989: BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo)); ! 990: binfo = TREE_CHAIN (binfo); ! 991: } ! 992: return rval; ! 993: } ! 994: ! 995: /* Return the binfo value for ELEM in TYPE. Due to structure ! 996: sharing, we may find ELEM only in the association list ! 997: belonging to a basetype of TYPE. ! 998: ! 999: COPYING is 0 if we just want an binfo value without needing ! 1000: to modify it. ! 1001: COPYING is 1 if we want the binfo value in order to modify it. ! 1002: In this case, if we don't find ELEM immediately in the binfo ! 1003: values of TYPE, we return a copy. ! 1004: COPYING is -1 if we are called recursively and need a copy. ! 1005: In this case we return a copy of ELEM at the point we find it. */ ! 1006: tree ! 1007: binfo_value (elem, type, copying) ! 1008: tree elem; ! 1009: tree type; ! 1010: int copying; ! 1011: { ! 1012: tree binfo = TYPE_BINFO (type); ! 1013: tree last; ! 1014: tree rval = NULL_TREE; ! 1015: ! 1016: /* Dispose quickly of degenerate case. */ ! 1017: if (elem == type) ! 1018: return copying < 0 ? copy_binfo (binfo) : binfo; ! 1019: ! 1020: /* Look for ELEM in two passes. First pass checks the entire binfo list. ! 1021: Second pass recursively searches the binfo lists of binfos. */ ! 1022: while (binfo) ! 1023: { ! 1024: if (elem == BINFO_TYPE (binfo)) ! 1025: /* If we find it on the main spine, then ! 1026: there can be no ambiguity. */ ! 1027: return copying < 0 ? copy_binfo (binfo) : binfo; ! 1028: last = binfo; ! 1029: binfo = TREE_CHAIN (binfo); ! 1030: } ! 1031: ! 1032: for (binfo = TYPE_BINFO (type); ! 1033: binfo != TREE_CHAIN (last); ! 1034: binfo = TREE_CHAIN (binfo)) ! 1035: { ! 1036: /* ??? Should this condition instead test ! 1037: BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type) ??? */ ! 1038: if (BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type)) ! 1039: { ! 1040: tree nval = binfo_value (elem, BINFO_TYPE (binfo), copying ? -1 : 0); ! 1041: ! 1042: if (nval) ! 1043: { ! 1044: if (copying && rval == NULL_TREE) ! 1045: chainon (TYPE_BINFO (type), nval); ! 1046: ! 1047: if (rval && BINFO_TYPE (rval) != BINFO_TYPE (nval)) ! 1048: /* If we find it underneath, we must make sure that ! 1049: there are no two ways to do it. */ ! 1050: compiler_error ("base class `%s' ambiguous in binfo_value", ! 1051: TYPE_NAME_STRING (elem)); ! 1052: else ! 1053: rval = nval; ! 1054: } ! 1055: } ! 1056: } ! 1057: return rval; ! 1058: } ! 1059: ! 1060: tree ! 1061: reverse_path (path) ! 1062: tree path; ! 1063: { ! 1064: register tree prev = 0, tmp, next; ! 1065: for (tmp = path; tmp; tmp = next) ! 1066: { ! 1067: next = BINFO_INHERITANCE_CHAIN (tmp); ! 1068: BINFO_INHERITANCE_CHAIN (tmp) = prev; ! 1069: prev = tmp; ! 1070: } ! 1071: return prev; ! 1072: } ! 1073: ! 1074: tree ! 1075: virtual_member (elem, list) ! 1076: tree elem; ! 1077: tree list; ! 1078: { ! 1079: tree t; ! 1080: tree rval, nval; ! 1081: ! 1082: for (t = list; t; t = TREE_CHAIN (t)) ! 1083: if (elem == BINFO_TYPE (t)) ! 1084: return t; ! 1085: rval = 0; ! 1086: for (t = list; t; t = TREE_CHAIN (t)) ! 1087: { ! 1088: tree binfos = BINFO_BASETYPES (t); ! 1089: int i; ! 1090: ! 1091: if (binfos != NULL_TREE) ! 1092: for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) ! 1093: { ! 1094: nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0); ! 1095: if (nval) ! 1096: { ! 1097: if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) ! 1098: abort (); ! 1099: rval = nval; ! 1100: } ! 1101: } ! 1102: } ! 1103: return rval; ! 1104: } ! 1105: ! 1106: /* Return the offset (as an INTEGER_CST) for ELEM in LIST. ! 1107: INITIAL_OFFSET is the value to add to the offset that ELEM's ! 1108: binfo entry in LIST provides. ! 1109: ! 1110: Returns NULL if ELEM does not have an binfo value in LIST. */ ! 1111: ! 1112: tree ! 1113: virtual_offset (elem, list, initial_offset) ! 1114: tree elem; ! 1115: tree list; ! 1116: tree initial_offset; ! 1117: { ! 1118: tree vb, offset; ! 1119: tree rval, nval; ! 1120: ! 1121: for (vb = list; vb; vb = TREE_CHAIN (vb)) ! 1122: if (elem == BINFO_TYPE (vb)) ! 1123: return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb)); ! 1124: rval = 0; ! 1125: for (vb = list; vb; vb = TREE_CHAIN (vb)) ! 1126: { ! 1127: tree binfos = BINFO_BASETYPES (vb); ! 1128: int i; ! 1129: ! 1130: if (binfos == NULL_TREE) ! 1131: continue; ! 1132: ! 1133: for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) ! 1134: { ! 1135: nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0); ! 1136: if (nval) ! 1137: { ! 1138: if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) ! 1139: abort (); ! 1140: offset = BINFO_OFFSET (vb); ! 1141: rval = nval; ! 1142: } ! 1143: } ! 1144: } ! 1145: if (rval == NULL_TREE) ! 1146: return rval; ! 1147: return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval)); ! 1148: } ! 1149: ! 1150: void ! 1151: debug_binfo (elem) ! 1152: tree elem; ! 1153: { ! 1154: int i; ! 1155: tree virtuals; ! 1156: ! 1157: fprintf (stderr, "type \"%s\"; offset = %d\n", ! 1158: TYPE_NAME_STRING (BINFO_TYPE (elem)), ! 1159: TREE_INT_CST_LOW (BINFO_OFFSET (elem))); ! 1160: fprintf (stderr, "vtable type:\n"); ! 1161: debug_tree (BINFO_TYPE (elem)); ! 1162: if (BINFO_VTABLE (elem)) ! 1163: fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); ! 1164: else ! 1165: fprintf (stderr, "no vtable decl yet\n"); ! 1166: fprintf (stderr, "virtuals:\n"); ! 1167: virtuals = BINFO_VIRTUALS (elem); ! 1168: if (virtuals != 0) ! 1169: { ! 1170: virtuals = TREE_CHAIN (virtuals); ! 1171: if (flag_dossier) ! 1172: virtuals = TREE_CHAIN (virtuals); ! 1173: } ! 1174: i = 1; ! 1175: while (virtuals) ! 1176: { ! 1177: tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); ! 1178: fprintf (stderr, "%s [%d =? %d]\n", ! 1179: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), ! 1180: i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); ! 1181: virtuals = TREE_CHAIN (virtuals); ! 1182: i += 1; ! 1183: } ! 1184: } ! 1185: ! 1186: /* Return the length of a chain of nodes chained through DECL_CHAIN. ! 1187: We expect a null pointer to mark the end of the chain. ! 1188: This is the Lisp primitive `length'. */ ! 1189: ! 1190: int ! 1191: decl_list_length (t) ! 1192: tree t; ! 1193: { ! 1194: register tree tail; ! 1195: register int len = 0; ! 1196: ! 1197: assert (TREE_CODE (t) == FUNCTION_DECL); ! 1198: for (tail = t; tail; tail = DECL_CHAIN (tail)) ! 1199: len++; ! 1200: ! 1201: return len; ! 1202: } ! 1203: ! 1204: tree ! 1205: fnaddr_from_vtable_entry (entry) ! 1206: tree entry; ! 1207: { ! 1208: return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))); ! 1209: } ! 1210: ! 1211: void ! 1212: set_fnaddr_from_vtable_entry (entry, value) ! 1213: tree entry, value; ! 1214: { ! 1215: TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value; ! 1216: } ! 1217: ! 1218: tree ! 1219: function_arg_chain (t) ! 1220: tree t; ! 1221: { ! 1222: return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t))); ! 1223: } ! 1224: ! 1225: int ! 1226: promotes_to_aggr_type (t, code) ! 1227: tree t; ! 1228: enum tree_code code; ! 1229: { ! 1230: if (TREE_CODE (t) == code) ! 1231: t = TREE_TYPE (t); ! 1232: return IS_AGGR_TYPE (t); ! 1233: } ! 1234: ! 1235: int ! 1236: is_aggr_type_2 (t1, t2) ! 1237: tree t1, t2; ! 1238: { ! 1239: if (TREE_CODE (t1) != TREE_CODE (t2)) ! 1240: return 0; ! 1241: return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2); ! 1242: } ! 1243: ! 1244: /* Give message using types TYPE1 and TYPE2 as arguments. ! 1245: PFN is the function which will print the message; ! 1246: S is the format string for PFN to use. */ ! 1247: void ! 1248: message_2_types (pfn, s, type1, type2) ! 1249: void (*pfn) (); ! 1250: char *s; ! 1251: tree type1, type2; ! 1252: { ! 1253: tree name1 = TYPE_NAME (type1); ! 1254: tree name2 = TYPE_NAME (type2); ! 1255: if (TREE_CODE (name1) == TYPE_DECL) ! 1256: name1 = DECL_NAME (name1); ! 1257: if (TREE_CODE (name2) == TYPE_DECL) ! 1258: name2 = DECL_NAME (name2); ! 1259: (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2)); ! 1260: } ! 1261: ! 1262: #define PRINT_RING_SIZE 4 ! 1263: ! 1264: char * ! 1265: lang_printable_name (decl) ! 1266: tree decl; ! 1267: { ! 1268: static tree decl_ring[PRINT_RING_SIZE]; ! 1269: static char *print_ring[PRINT_RING_SIZE]; ! 1270: static int ring_counter; ! 1271: int i; ! 1272: ! 1273: if (TREE_CODE (decl) != FUNCTION_DECL ! 1274: || DECL_LANG_SPECIFIC (decl) == 0) ! 1275: { ! 1276: if (DECL_NAME (decl)) ! 1277: { ! 1278: if (THIS_NAME_P (DECL_NAME (decl))) ! 1279: return "this"; ! 1280: return IDENTIFIER_POINTER (DECL_NAME (decl)); ! 1281: } ! 1282: return "((anonymous))"; ! 1283: } ! 1284: ! 1285: /* See if this print name is lying around. */ ! 1286: for (i = 0; i < PRINT_RING_SIZE; i++) ! 1287: if (decl_ring[i] == decl) ! 1288: /* yes, so return it. */ ! 1289: return print_ring[i]; ! 1290: ! 1291: if (++ring_counter == PRINT_RING_SIZE) ! 1292: ring_counter = 0; ! 1293: ! 1294: if (current_function_decl != NULL_TREE) ! 1295: { ! 1296: if (decl_ring[ring_counter] == current_function_decl) ! 1297: ring_counter += 1; ! 1298: if (ring_counter == PRINT_RING_SIZE) ! 1299: ring_counter = 0; ! 1300: if (decl_ring[ring_counter] == current_function_decl) ! 1301: abort (); ! 1302: } ! 1303: ! 1304: if (print_ring[ring_counter]) ! 1305: free (print_ring[ring_counter]); ! 1306: ! 1307: { ! 1308: int print_ret_type_p ! 1309: = (!DECL_CONSTRUCTOR_P (decl) ! 1310: && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); ! 1311: ! 1312: char *name = (char *)fndecl_as_string (0, decl, print_ret_type_p); ! 1313: print_ring[ring_counter] = (char *)malloc (strlen (name) + 1); ! 1314: strcpy (print_ring[ring_counter], name); ! 1315: decl_ring[ring_counter] = decl; ! 1316: } ! 1317: return print_ring[ring_counter]; ! 1318: } ! 1319: ! 1320: /* Comparison function for sorting identifiers in RAISES lists. ! 1321: Note that because IDENTIFIER_NODEs are unique, we can sort ! 1322: them by address, saving an indirection. */ ! 1323: static int ! 1324: id_cmp (p1, p2) ! 1325: tree *p1, *p2; ! 1326: { ! 1327: return (int)TREE_VALUE (*p1) - (int)TREE_VALUE (*p2); ! 1328: } ! 1329: ! 1330: /* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions ! 1331: listed in RAISES. */ ! 1332: tree ! 1333: build_exception_variant (ctype, type, raises) ! 1334: tree ctype, type; ! 1335: tree raises; ! 1336: { ! 1337: int i; ! 1338: tree v = TYPE_MAIN_VARIANT (type); ! 1339: tree t, t2, cname; ! 1340: tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree)); ! 1341: int constp = TYPE_READONLY (type); ! 1342: int volatilep = TYPE_VOLATILE (type); ! 1343: ! 1344: if (raises && TREE_CHAIN (raises)) ! 1345: { ! 1346: for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++) ! 1347: a[i] = t; ! 1348: /* NULL terminator for list. */ ! 1349: a[i] = NULL_TREE; ! 1350: qsort (a, i, sizeof (tree), id_cmp); ! 1351: while (i--) ! 1352: TREE_CHAIN (a[i]) = a[i+1]; ! 1353: raises = a[0]; ! 1354: } ! 1355: else if (raises) ! 1356: /* do nothing. */; ! 1357: else ! 1358: return build_type_variant (v, constp, volatilep); ! 1359: ! 1360: if (ctype) ! 1361: { ! 1362: cname = TYPE_NAME (ctype); ! 1363: if (TREE_CODE (cname) == TYPE_DECL) ! 1364: cname = DECL_NAME (cname); ! 1365: } ! 1366: else ! 1367: cname = NULL_TREE; ! 1368: ! 1369: for (t = raises; t; t = TREE_CHAIN (t)) ! 1370: { ! 1371: /* See that all the exceptions we are thinking about ! 1372: raising have been declared. */ ! 1373: tree this_cname = lookup_exception_cname (ctype, cname, t); ! 1374: tree decl = lookup_exception_object (this_cname, TREE_VALUE (t), 1); ! 1375: ! 1376: if (decl == NULL_TREE) ! 1377: decl = lookup_exception_object (this_cname, TREE_VALUE (t), 0); ! 1378: /* Place canonical exception decl into TREE_TYPE of RAISES list. */ ! 1379: TREE_TYPE (t) = decl; ! 1380: } ! 1381: ! 1382: for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v)) ! 1383: { ! 1384: if (TYPE_READONLY (v) != constp ! 1385: || TYPE_VOLATILE (v) != volatilep) ! 1386: continue; ! 1387: ! 1388: t = raises; ! 1389: t2 = TYPE_RAISES_EXCEPTIONS (v); ! 1390: while (t && t2) ! 1391: { ! 1392: if (TREE_TYPE (t) == TREE_TYPE (t2)) ! 1393: { ! 1394: t = TREE_CHAIN (t); ! 1395: t2 = TREE_CHAIN (t2); ! 1396: } ! 1397: else break; ! 1398: } ! 1399: if (t || t2) ! 1400: continue; ! 1401: /* List of exceptions raised matches previously found list. ! 1402: ! 1403: @@ Nice to free up storage used in consing up the ! 1404: @@ list of exceptions raised. */ ! 1405: return v; ! 1406: } ! 1407: ! 1408: /* Need to build a new variant. */ ! 1409: v = copy_node (type); ! 1410: TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type); ! 1411: TYPE_NEXT_VARIANT (type) = v; ! 1412: if (raises && ! TREE_PERMANENT (raises)) ! 1413: { ! 1414: push_obstacks_nochange (); ! 1415: end_temporary_allocation (); ! 1416: raises = copy_list (raises); ! 1417: pop_obstacks (); ! 1418: } ! 1419: TYPE_RAISES_EXCEPTIONS (v) = raises; ! 1420: return v; ! 1421: } ! 1422: ! 1423: /* Subroutine of make_permanent_node. ! 1424: ! 1425: Assuming T is a node build bottom-up, make it all exist on ! 1426: permanent obstack, if it is not permanent already. */ ! 1427: static tree ! 1428: make_deep_copy (t) ! 1429: tree t; ! 1430: { ! 1431: enum tree_code code; ! 1432: ! 1433: if (t == NULL_TREE || TREE_PERMANENT (t)) ! 1434: return t; ! 1435: ! 1436: switch (code = TREE_CODE (t)) ! 1437: { ! 1438: case ERROR_MARK: ! 1439: return error_mark_node; ! 1440: ! 1441: case VAR_DECL: ! 1442: case FUNCTION_DECL: ! 1443: case CONST_DECL: ! 1444: break; ! 1445: ! 1446: case PARM_DECL: ! 1447: { ! 1448: tree chain = TREE_CHAIN (t); ! 1449: t = copy_node (t); ! 1450: TREE_CHAIN (t) = make_deep_copy (chain); ! 1451: TREE_TYPE (t) = make_deep_copy (TREE_TYPE (t)); ! 1452: DECL_INITIAL (t) = make_deep_copy (DECL_INITIAL (t)); ! 1453: DECL_SIZE (t) = make_deep_copy (DECL_SIZE (t)); ! 1454: return t; ! 1455: } ! 1456: ! 1457: case TREE_LIST: ! 1458: { ! 1459: tree chain = TREE_CHAIN (t); ! 1460: t = copy_node (t); ! 1461: TREE_PURPOSE (t) = make_deep_copy (TREE_PURPOSE (t)); ! 1462: TREE_VALUE (t) = make_deep_copy (TREE_VALUE (t)); ! 1463: TREE_CHAIN (t) = make_deep_copy (chain); ! 1464: return t; ! 1465: } ! 1466: ! 1467: case TREE_VEC: ! 1468: { ! 1469: int len = TREE_VEC_LENGTH (t); ! 1470: ! 1471: t = copy_node (t); ! 1472: while (len--) ! 1473: TREE_VEC_ELT (t, len) = make_deep_copy (TREE_VEC_ELT (t, len)); ! 1474: return t; ! 1475: } ! 1476: ! 1477: case INTEGER_CST: ! 1478: case REAL_CST: ! 1479: case STRING_CST: ! 1480: return copy_node (t); ! 1481: ! 1482: case COND_EXPR: ! 1483: case TARGET_EXPR: ! 1484: case NEW_EXPR: ! 1485: t = copy_node (t); ! 1486: TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); ! 1487: TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1)); ! 1488: TREE_OPERAND (t, 2) = make_deep_copy (TREE_OPERAND (t, 2)); ! 1489: return t; ! 1490: ! 1491: case SAVE_EXPR: ! 1492: t = copy_node (t); ! 1493: TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); ! 1494: return t; ! 1495: ! 1496: case MODIFY_EXPR: ! 1497: case PLUS_EXPR: ! 1498: case MINUS_EXPR: ! 1499: case MULT_EXPR: ! 1500: case TRUNC_DIV_EXPR: ! 1501: case TRUNC_MOD_EXPR: ! 1502: case MIN_EXPR: ! 1503: case MAX_EXPR: ! 1504: case LSHIFT_EXPR: ! 1505: case RSHIFT_EXPR: ! 1506: case BIT_IOR_EXPR: ! 1507: case BIT_XOR_EXPR: ! 1508: case BIT_AND_EXPR: ! 1509: case BIT_ANDTC_EXPR: ! 1510: case TRUTH_ANDIF_EXPR: ! 1511: case TRUTH_ORIF_EXPR: ! 1512: case LT_EXPR: ! 1513: case LE_EXPR: ! 1514: case GT_EXPR: ! 1515: case GE_EXPR: ! 1516: case EQ_EXPR: ! 1517: case NE_EXPR: ! 1518: case CEIL_DIV_EXPR: ! 1519: case FLOOR_DIV_EXPR: ! 1520: case ROUND_DIV_EXPR: ! 1521: case CEIL_MOD_EXPR: ! 1522: case FLOOR_MOD_EXPR: ! 1523: case ROUND_MOD_EXPR: ! 1524: case COMPOUND_EXPR: ! 1525: case PREDECREMENT_EXPR: ! 1526: case PREINCREMENT_EXPR: ! 1527: case POSTDECREMENT_EXPR: ! 1528: case POSTINCREMENT_EXPR: ! 1529: case CALL_EXPR: ! 1530: t = copy_node (t); ! 1531: TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); ! 1532: TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1)); ! 1533: return t; ! 1534: ! 1535: case CONVERT_EXPR: ! 1536: case ADDR_EXPR: ! 1537: case INDIRECT_REF: ! 1538: case NEGATE_EXPR: ! 1539: case BIT_NOT_EXPR: ! 1540: case TRUTH_NOT_EXPR: ! 1541: case NOP_EXPR: ! 1542: case COMPONENT_REF: ! 1543: t = copy_node (t); ! 1544: TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); ! 1545: return t; ! 1546: ! 1547: /* This list is incomplete, but should suffice for now. ! 1548: It is very important that `sorry' does not call ! 1549: `report_error_function'. That could cause an infinite loop. */ ! 1550: default: ! 1551: sorry ("initializer contains unrecognized tree code"); ! 1552: return error_mark_node; ! 1553: ! 1554: } ! 1555: abort (); ! 1556: /* NOTREACHED */ ! 1557: return NULL_TREE; ! 1558: } ! 1559: ! 1560: /* Assuming T is a node built bottom-up, make it all exist on ! 1561: permanent obstack, if it is not permanent already. */ ! 1562: tree ! 1563: copy_to_permanent (t) ! 1564: tree t; ! 1565: { ! 1566: register struct obstack *ambient_obstack = current_obstack; ! 1567: register struct obstack *ambient_saveable_obstack = saveable_obstack; ! 1568: ! 1569: if (t == NULL_TREE || TREE_PERMANENT (t)) ! 1570: return t; ! 1571: ! 1572: saveable_obstack = &permanent_obstack; ! 1573: current_obstack = saveable_obstack; ! 1574: ! 1575: t = make_deep_copy (t); ! 1576: ! 1577: current_obstack = ambient_obstack; ! 1578: saveable_obstack = ambient_saveable_obstack; ! 1579: ! 1580: return t; ! 1581: } ! 1582: ! 1583: int ! 1584: lang_simple_cst_equal (t1, t2) ! 1585: tree t1, t2; ! 1586: { ! 1587: register enum tree_code code1, code2; ! 1588: int cmp; ! 1589: ! 1590: if (t1 == t2) ! 1591: return 1; ! 1592: if (t1 == 0 || t2 == 0) ! 1593: return 0; ! 1594: ! 1595: code1 = TREE_CODE (t1); ! 1596: code2 = TREE_CODE (t2); ! 1597: ! 1598: switch (code1) ! 1599: { ! 1600: case NEW_EXPR: ! 1601: cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); ! 1602: if (cmp <= 0) ! 1603: return cmp; ! 1604: return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); ! 1605: ! 1606: default: ! 1607: return -1; ! 1608: } ! 1609: } ! 1610: ! 1611: void ! 1612: print_lang_statistics () ! 1613: { ! 1614: extern struct obstack maybepermanent_obstack; ! 1615: print_obstack_statistics ("class_obstack", &class_obstack); ! 1616: print_obstack_statistics ("permanent_obstack", &permanent_obstack); ! 1617: print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack); ! 1618: print_search_statistics (); ! 1619: print_class_statistics (); ! 1620: } ! 1621: ! 1622: /* This is used by the `assert' macro. It is provided in libgcc.a, ! 1623: which `cc' doesn't know how to link. */ ! 1624: void ! 1625: __eprintf (string, expression, line, filename) ! 1626: #ifdef __STDC__ ! 1627: const char *string; ! 1628: const char *expression; ! 1629: int line; ! 1630: const char *filename; ! 1631: #else ! 1632: char *string; ! 1633: char *expression; ! 1634: int line; ! 1635: char *filename; ! 1636: #endif ! 1637: { ! 1638: fprintf (stderr, string, expression, line, filename); ! 1639: fflush (stderr); ! 1640: abort (); ! 1641: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.