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