|
|
1.1 ! root 1: /* Call-backs for C++ error reporting. ! 2: This code is non-reentrant. ! 3: Copyright (C) 1993 Free Software Foundation, Inc. ! 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 "tree.h" ! 23: #include "cp-tree.h" ! 24: #include "obstack.h" ! 25: #include <ctype.h> ! 26: ! 27: typedef char* cp_printer (); ! 28: ! 29: #define C code_as_string ! 30: #define D decl_as_string ! 31: #define E expr_as_string ! 32: #define L language_as_string ! 33: #define T type_as_string ! 34: ! 35: #define _ (cp_printer *) 0 ! 36: cp_printer * cp_printers[256] = ! 37: { ! 38: /*0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 39: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */ ! 40: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */ ! 41: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ ! 42: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ ! 43: _, _, _, C, D, E, _, _, _, _, _, _, L, _, _, _, /* 0x40 */ ! 44: _, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */ ! 45: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ ! 46: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */ ! 47: }; ! 48: #undef C ! 49: #undef D ! 50: #undef E ! 51: #undef L ! 52: #undef T ! 53: #undef _ ! 54: ! 55: #define obstack_chunk_alloc xmalloc ! 56: #define obstack_chunk_free free ! 57: ! 58: /* Obstack where we build text strings for overloading, etc. */ ! 59: static struct obstack scratch_obstack; ! 60: static char *scratch_firstobj; ! 61: ! 62: # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) ! 63: # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) ! 64: # define OB_PUTC2(C1,C2) \ ! 65: (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2))) ! 66: # define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1)) ! 67: # define OB_PUTID(ID) \ ! 68: (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \ ! 69: IDENTIFIER_LENGTH (ID))) ! 70: # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) ! 71: # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) ! 72: # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \ ! 73: OB_PUTCP (digit_buffer); } while (0) ! 74: ! 75: # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t))) ! 76: ! 77: static void dump_type (), dump_decl (), dump_function_decl (); ! 78: static void dump_expr (), dump_unary_op (), dump_binary_op (); ! 79: static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix (); ! 80: static void dump_function_name (); ! 81: ! 82: void ! 83: init_error () ! 84: { ! 85: gcc_obstack_init (&scratch_obstack); ! 86: scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0); ! 87: } ! 88: ! 89: /* Counter to help build parameter names in case they were omitted. */ ! 90: static int dummy_name; ! 91: ! 92: enum pad { none, before, after }; ! 93: ! 94: static void ! 95: dump_readonly_or_volatile (t, p) ! 96: tree t; ! 97: enum pad p; ! 98: { ! 99: if (TYPE_READONLY (t) || TYPE_VOLATILE (t)) ! 100: { ! 101: if (p == before) OB_PUTC (' '); ! 102: if (TYPE_READONLY (t)) ! 103: OB_PUTS ("const"); ! 104: if (TYPE_VOLATILE (t)) ! 105: OB_PUTS ("volatile"); ! 106: if (p == after) OB_PUTC (' '); ! 107: } ! 108: } ! 109: ! 110: /* This must be large enough to hold any printed integer or floating-point ! 111: value. */ ! 112: static char digit_buffer[128]; ! 113: ! 114: /* Dump into the obstack a human-readable equivalent of TYPE. */ ! 115: static void ! 116: dump_type (t, v) ! 117: tree t; ! 118: int v; /* verbose? */ ! 119: { ! 120: if (t == NULL_TREE) ! 121: return; ! 122: ! 123: if (TYPE_PTRMEMFUNC_P (t)) ! 124: goto offset_type; ! 125: ! 126: switch (TREE_CODE (t)) ! 127: { ! 128: case ERROR_MARK: ! 129: OB_PUTS ("<error>"); ! 130: break; ! 131: ! 132: case UNKNOWN_TYPE: ! 133: OB_PUTS ("<unknown type>"); ! 134: break; ! 135: ! 136: case TREE_LIST: ! 137: /* i.e. function taking no arguments */ ! 138: if (t != void_list_node) ! 139: { ! 140: dump_type (TREE_VALUE (t), v); ! 141: /* Can this happen other than for default arguments? */ ! 142: if (TREE_PURPOSE (t) && v) ! 143: { ! 144: OB_PUTS (" = "); ! 145: dump_expr (TREE_PURPOSE (t)); ! 146: } ! 147: if (TREE_CHAIN (t)) ! 148: { ! 149: if (TREE_CHAIN (t) != void_list_node) ! 150: { ! 151: OB_PUTC2 (',', ' '); ! 152: dump_type (TREE_CHAIN (t), v); ! 153: } ! 154: } ! 155: else OB_PUTS (" ..."); ! 156: } ! 157: break; ! 158: ! 159: case IDENTIFIER_NODE: ! 160: OB_PUTID (t); ! 161: break; ! 162: ! 163: case TREE_VEC: ! 164: dump_type (BINFO_TYPE (t), v); ! 165: break; ! 166: ! 167: case RECORD_TYPE: ! 168: case UNION_TYPE: ! 169: case ENUMERAL_TYPE: ! 170: dump_aggr_type (t, v); ! 171: break; ! 172: ! 173: case TYPE_DECL: ! 174: dump_readonly_or_volatile (t, after); ! 175: OB_PUTID (DECL_NAME (t)); ! 176: break; ! 177: ! 178: case INTEGER_TYPE: ! 179: if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t)) ! 180: OB_PUTS ("unsigned "); ! 181: else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t)) ! 182: OB_PUTS ("signed "); ! 183: ! 184: /* fall through. */ ! 185: case REAL_TYPE: ! 186: case VOID_TYPE: ! 187: dump_readonly_or_volatile (t, after); ! 188: OB_PUTID (TYPE_IDENTIFIER (t)); ! 189: break; ! 190: ! 191: case TEMPLATE_TYPE_PARM: ! 192: OB_PUTS ("<template type parm "); ! 193: OB_PUTID (TYPE_IDENTIFIER (t)); ! 194: OB_PUTC ('>'); ! 195: break; ! 196: ! 197: case UNINSTANTIATED_P_TYPE: ! 198: OB_PUTID (DECL_NAME (UPT_TEMPLATE (t))); ! 199: OB_PUTS ("<...>"); ! 200: break; ! 201: ! 202: /* This is not always necessary for pointers and such, but doing this ! 203: reduces code size. */ ! 204: case ARRAY_TYPE: ! 205: case POINTER_TYPE: ! 206: case REFERENCE_TYPE: ! 207: case OFFSET_TYPE: ! 208: offset_type: ! 209: case FUNCTION_TYPE: ! 210: case METHOD_TYPE: ! 211: dump_type_prefix (t, v); ! 212: dump_type_suffix (t, v); ! 213: break; ! 214: ! 215: default: ! 216: my_friendly_abort (68); ! 217: ! 218: } ! 219: } ! 220: ! 221: /* Print out a class declaration, in the form `class foo'. */ ! 222: static void ! 223: dump_aggr_type (t, v) ! 224: tree t; ! 225: int v; /* verbose? */ ! 226: { ! 227: tree name; ! 228: char *variety; ! 229: ! 230: if (TREE_CODE (t) == ENUMERAL_TYPE) ! 231: variety = "enum"; ! 232: else if (TREE_CODE (t) == UNION_TYPE) ! 233: variety = "union"; ! 234: else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t)) ! 235: variety = "class"; ! 236: else ! 237: variety = "struct"; ! 238: ! 239: dump_readonly_or_volatile (t, after); ! 240: ! 241: if (v) ! 242: { ! 243: OB_PUTCP (variety); ! 244: OB_PUTC (' '); ! 245: } ! 246: ! 247: name = TYPE_NAME (t); ! 248: ! 249: if (DECL_CONTEXT (name)) ! 250: { ! 251: /* FUNCTION_DECL or RECORD_TYPE */ ! 252: dump_decl (DECL_CONTEXT (name), 0); ! 253: OB_PUTC2 (':', ':'); ! 254: } ! 255: ! 256: /* kludge around wierd behavior on g++.brendan/line1.C */ ! 257: if (TREE_CODE (name) != IDENTIFIER_NODE) ! 258: name = DECL_NAME (name); ! 259: ! 260: if (ANON_AGGRNAME_P (name)) ! 261: { ! 262: OB_PUTS ("<anonymous"); ! 263: if (!v) ! 264: { ! 265: OB_PUTC (' '); ! 266: OB_PUTCP (variety); ! 267: } ! 268: OB_PUTC ('>'); ! 269: } ! 270: else ! 271: OB_PUTID (name); ! 272: } ! 273: ! 274: /* Dump into the obstack the initial part of the output for a given type. ! 275: This is necessary when dealing with things like functions returning ! 276: functions. Examples: ! 277: ! 278: return type of `int (* fee ())()': pointer -> function -> int. Both ! 279: pointer (and reference and offset) and function (and member) types must ! 280: deal with prefix and suffix. ! 281: ! 282: Arrays must also do this for DECL nodes, like int a[], and for things like ! 283: int *[]&. */ ! 284: ! 285: static void ! 286: dump_type_prefix (t, v) ! 287: tree t; ! 288: int v; /* verbosity */ ! 289: { ! 290: if (TYPE_PTRMEMFUNC_P (t)) ! 291: { ! 292: t = TYPE_PTRMEMFUNC_FN_TYPE (t); ! 293: goto offset_type; ! 294: } ! 295: ! 296: switch (TREE_CODE (t)) ! 297: { ! 298: case POINTER_TYPE: ! 299: { ! 300: tree sub = TREE_TYPE (t); ! 301: ! 302: dump_type_prefix (sub, v); ! 303: /* A tree for a member pointer looks like pointer to offset, ! 304: so let the OFFSET_TYPE case handle it. */ ! 305: if (TREE_CODE (sub) != OFFSET_TYPE) ! 306: { ! 307: switch (TREE_CODE (sub)) ! 308: { ! 309: /* We don't want int ( *)() */ ! 310: case FUNCTION_TYPE: ! 311: case METHOD_TYPE: ! 312: break; ! 313: ! 314: case POINTER_TYPE: ! 315: /* We don't want "char * *" */ ! 316: if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub))) ! 317: break; ! 318: /* But we do want "char *const *" */ ! 319: ! 320: default: ! 321: OB_PUTC (' '); ! 322: } ! 323: OB_PUTC ('*'); ! 324: dump_readonly_or_volatile (t, none); ! 325: } ! 326: } ! 327: break; ! 328: ! 329: case REFERENCE_TYPE: ! 330: { ! 331: tree sub = TREE_TYPE (t); ! 332: dump_type_prefix (sub, v); ! 333: ! 334: switch (TREE_CODE (sub)) ! 335: { ! 336: case POINTER_TYPE: ! 337: /* We don't want "char * &" */ ! 338: if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub))) ! 339: break; ! 340: /* But we do want "char *const &" */ ! 341: ! 342: default: ! 343: OB_PUTC (' '); ! 344: } ! 345: } ! 346: OB_PUTC ('&'); ! 347: dump_readonly_or_volatile (t, none); ! 348: break; ! 349: ! 350: case OFFSET_TYPE: ! 351: offset_type: ! 352: dump_type_prefix (TREE_TYPE (t), v); ! 353: if (NEXT_CODE (t) != FUNCTION_TYPE && NEXT_CODE (t) != METHOD_TYPE) ! 354: OB_PUTC (' '); ! 355: if (TREE_CODE (t) == OFFSET_TYPE) ! 356: dump_type (TYPE_OFFSET_BASETYPE (t), 0); ! 357: else /* pointer to member function */ ! 358: dump_type (TYPE_METHOD_BASETYPE (TREE_TYPE (t)), 0); ! 359: OB_PUTC2 (':', ':'); ! 360: OB_PUTC ('*'); ! 361: dump_readonly_or_volatile (t, none); ! 362: break; ! 363: ! 364: /* Can only be reached through function pointer -- this would not be ! 365: correct if FUNCTION_DECLs used it. */ ! 366: case FUNCTION_TYPE: ! 367: case METHOD_TYPE: ! 368: dump_type_prefix (TREE_TYPE (t), v); ! 369: OB_PUTC2 (' ', '('); ! 370: break; ! 371: ! 372: case ARRAY_TYPE: ! 373: dump_type_prefix (TREE_TYPE (t), v); ! 374: break; ! 375: ! 376: case ENUMERAL_TYPE: ! 377: case ERROR_MARK: ! 378: case IDENTIFIER_NODE: ! 379: case INTEGER_TYPE: ! 380: case REAL_TYPE: ! 381: case RECORD_TYPE: ! 382: case TEMPLATE_TYPE_PARM: ! 383: case TREE_LIST: ! 384: case TYPE_DECL: ! 385: case TREE_VEC: ! 386: case UNINSTANTIATED_P_TYPE: ! 387: case UNION_TYPE: ! 388: case UNKNOWN_TYPE: ! 389: case VOID_TYPE: ! 390: dump_type (t, v); ! 391: break; ! 392: ! 393: default: ! 394: my_friendly_abort (65); ! 395: } ! 396: } ! 397: ! 398: static void ! 399: dump_type_suffix (t, v) ! 400: tree t; ! 401: int v; /* verbose? */ ! 402: { ! 403: if (TYPE_PTRMEMFUNC_P (t)) ! 404: t = TYPE_PTRMEMFUNC_FN_TYPE (t); ! 405: ! 406: switch (TREE_CODE (t)) ! 407: { ! 408: case POINTER_TYPE: ! 409: case REFERENCE_TYPE: ! 410: case OFFSET_TYPE: ! 411: dump_type_suffix (TREE_TYPE (t), v); ! 412: break; ! 413: ! 414: /* Can only be reached through function pointer */ ! 415: case FUNCTION_TYPE: ! 416: case METHOD_TYPE: ! 417: { ! 418: tree arg; ! 419: OB_PUTC2 (')', '('); ! 420: arg = TYPE_ARG_TYPES (t); ! 421: if (TREE_CODE (t) == METHOD_TYPE) ! 422: arg = TREE_CHAIN (arg); ! 423: ! 424: if (arg) ! 425: dump_type (arg, v); ! 426: else ! 427: OB_PUTS ("..."); ! 428: OB_PUTC (')'); ! 429: if (TREE_CODE (t) == METHOD_TYPE) ! 430: dump_readonly_or_volatile ! 431: (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before); ! 432: dump_type_suffix (TREE_TYPE (t), v); ! 433: break; ! 434: } ! 435: ! 436: case ARRAY_TYPE: ! 437: OB_PUTC ('['); ! 438: if (TYPE_DOMAIN (t)) ! 439: OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1); ! 440: OB_PUTC (']'); ! 441: dump_type_suffix (TREE_TYPE (t), v); ! 442: break; ! 443: ! 444: case ENUMERAL_TYPE: ! 445: case ERROR_MARK: ! 446: case IDENTIFIER_NODE: ! 447: case INTEGER_TYPE: ! 448: case REAL_TYPE: ! 449: case RECORD_TYPE: ! 450: case TEMPLATE_TYPE_PARM: ! 451: case TREE_LIST: ! 452: case TYPE_DECL: ! 453: case TREE_VEC: ! 454: case UNINSTANTIATED_P_TYPE: ! 455: case UNION_TYPE: ! 456: case UNKNOWN_TYPE: ! 457: case VOID_TYPE: ! 458: break; ! 459: ! 460: default: ! 461: my_friendly_abort (67); ! 462: } ! 463: } ! 464: ! 465: /* Return a function declaration which corresponds to the IDENTIFIER_NODE ! 466: argument. */ ! 467: tree ! 468: ident_fndecl (t) ! 469: tree t; ! 470: { ! 471: tree n = IDENTIFIER_GLOBAL_VALUE (t); ! 472: ! 473: if (TREE_CODE (n) == FUNCTION_DECL) ! 474: return n; ! 475: else if (TREE_CODE (n) == TREE_LIST ! 476: && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL) ! 477: return TREE_VALUE (n); ! 478: else ! 479: my_friendly_abort (66); ! 480: } ! 481: ! 482: #ifndef NO_DOLLAR_IN_LABEL ! 483: # define GLOBAL_THING "_GLOBAL_$" ! 484: #else ! 485: # ifndef NO_DOT_IN_LABEL ! 486: # define GLOBAL_THING "_GLOBAL_." ! 487: # else ! 488: # define GLOBAL_THING "_GLOBAL__" ! 489: # endif ! 490: #endif ! 491: ! 492: #define GLOBAL_IORD_P(NODE) \ ! 493: !strncmp(IDENTIFIER_POINTER(NODE),GLOBAL_THING,sizeof(GLOBAL_THING)-1) ! 494: ! 495: void ! 496: dump_global_iord (t) ! 497: tree t; ! 498: { ! 499: char *name = IDENTIFIER_POINTER (t); ! 500: ! 501: OB_PUTS ("(static "); ! 502: if (name [sizeof (GLOBAL_THING) - 1] == 'I') ! 503: OB_PUTS ("initializers"); ! 504: else if (name [sizeof (GLOBAL_THING) - 1] == 'D') ! 505: OB_PUTS ("destructors"); ! 506: else ! 507: my_friendly_abort (352); ! 508: ! 509: OB_PUTS (" for "); ! 510: OB_PUTCP (input_filename); ! 511: OB_PUTC (')'); ! 512: } ! 513: ! 514: static void ! 515: dump_decl (t, v) ! 516: tree t; ! 517: int v; /* verbosity */ ! 518: { ! 519: if (t == NULL_TREE) ! 520: return; ! 521: ! 522: switch (TREE_CODE (t)) ! 523: { ! 524: case ERROR_MARK: ! 525: OB_PUTS (" /* decl error */ "); ! 526: break; ! 527: ! 528: case VAR_DECL: ! 529: if (VTABLE_NAME_P (DECL_NAME (t))) ! 530: { ! 531: OB_PUTS ("vtable for "); ! 532: dump_type (DECL_CONTEXT (t), v); ! 533: break; ! 534: } ! 535: /* else fall through */ ! 536: case FIELD_DECL: ! 537: case PARM_DECL: ! 538: if (v) ! 539: { ! 540: dump_type_prefix (TREE_TYPE (t), v); ! 541: OB_PUTC(' '); ! 542: } ! 543: /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */ ! 544: if (TREE_CODE (t) == FIELD_DECL ! 545: || (TREE_CODE (t) == VAR_DECL && DECL_CONTEXT (t) ! 546: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')) ! 547: { ! 548: dump_type (DECL_CONTEXT (t), 0); ! 549: OB_PUTC2(':', ':'); ! 550: } ! 551: if (DECL_NAME (t)) ! 552: dump_decl (DECL_NAME (t), v); ! 553: else ! 554: OB_PUTS ("<anon>"); ! 555: if (v) dump_type_suffix (TREE_TYPE (t), v); ! 556: break; ! 557: ! 558: case ARRAY_REF: ! 559: dump_decl (TREE_OPERAND (t, 0), v); ! 560: OB_PUTC ('['); ! 561: dump_decl (TREE_OPERAND (t, 1), v); ! 562: OB_PUTC (']'); ! 563: break; ! 564: ! 565: /* So that we can do dump_decl in dump_aggr_type and have it work for ! 566: both class and function scope. */ ! 567: case RECORD_TYPE: ! 568: case UNION_TYPE: ! 569: case ENUMERAL_TYPE: ! 570: dump_type (t, v); ! 571: break; ! 572: ! 573: case TYPE_DECL: ! 574: dump_type (TREE_TYPE (t), v); ! 575: break; ! 576: ! 577: case TYPE_EXPR: ! 578: my_friendly_abort (69); ! 579: break; ! 580: ! 581: /* These special cases are duplicated here so that other functions ! 582: can feed identifiers to cp_error and get them demangled properly. */ ! 583: case IDENTIFIER_NODE: ! 584: if (DESTRUCTOR_NAME_P (t)) ! 585: { ! 586: OB_PUTC ('~'); ! 587: dump_decl (DECL_NAME (ident_fndecl (t)), 0); ! 588: } ! 589: else if (IDENTIFIER_TYPENAME_P (t)) ! 590: { ! 591: OB_PUTS ("operator "); ! 592: /* Not exactly IDENTIFIER_TYPE_VALUE. */ ! 593: dump_type (TREE_TYPE (t), 0); ! 594: break; ! 595: } ! 596: else if (IDENTIFIER_OPNAME_P (t)) ! 597: { ! 598: char *name_string = operator_name_string (t); ! 599: OB_PUTS ("operator "); ! 600: OB_PUTCP (name_string); ! 601: } ! 602: else ! 603: OB_PUTID (t); ! 604: break; ! 605: ! 606: case FUNCTION_DECL: ! 607: if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t))) ! 608: dump_global_iord (DECL_ASSEMBLER_NAME (t)); ! 609: else ! 610: dump_function_decl (t, v); ! 611: break; ! 612: ! 613: case TEMPLATE_DECL: ! 614: switch (NEXT_CODE (t)) ! 615: { ! 616: case METHOD_TYPE: ! 617: case FUNCTION_TYPE: ! 618: dump_function_decl (t, v); ! 619: break; ! 620: ! 621: default: ! 622: my_friendly_abort (353); ! 623: } ! 624: break; ! 625: ! 626: case LABEL_DECL: ! 627: OB_PUTID (DECL_NAME (t)); ! 628: break; ! 629: ! 630: case CONST_DECL: ! 631: if (NEXT_CODE (t) == ENUMERAL_TYPE) ! 632: { ! 633: if (DECL_CONTEXT (t)) ! 634: { ! 635: dump_decl (DECL_CONTEXT (t), 0); ! 636: OB_PUTC2 (':', ':'); ! 637: } ! 638: OB_PUTID (DECL_NAME (t)); ! 639: } ! 640: else ! 641: dump_expr (DECL_INITIAL (t), 0); ! 642: break; ! 643: ! 644: default: ! 645: my_friendly_abort (70); ! 646: } ! 647: } ! 648: ! 649: /* Pretty printing for announce_function. T is the declaration of the ! 650: function we are interested in seeing. V is non-zero if we should print ! 651: the type that this function returns. */ ! 652: ! 653: static void ! 654: dump_function_decl (t, v) ! 655: tree t; ! 656: int v; ! 657: { ! 658: tree name = DECL_ASSEMBLER_NAME (t); ! 659: tree fntype = TREE_TYPE (t); ! 660: tree parmtypes = TYPE_ARG_TYPES (fntype); ! 661: tree cname = NULL_TREE; ! 662: int spaces = 0; ! 663: ! 664: if (DECL_CLASS_CONTEXT (t)) ! 665: cname = DECL_CLASS_CONTEXT (t); ! 666: /* this is for partially instantiated template methods */ ! 667: else if (TREE_CODE (fntype) == METHOD_TYPE) ! 668: cname = TREE_TYPE (TREE_VALUE (parmtypes)); ! 669: ! 670: if (v) ! 671: { ! 672: if (DECL_STATIC_FUNCTION_P (t)) ! 673: OB_PUTS ("static "); ! 674: ! 675: if (! IDENTIFIER_TYPENAME_P (name)) ! 676: { ! 677: dump_type_prefix (TREE_TYPE (fntype), 1); ! 678: OB_PUTC (' '); ! 679: } ! 680: } ! 681: ! 682: if (cname) ! 683: { ! 684: dump_type (cname, 0); ! 685: OB_PUTC2 (':', ':'); ! 686: if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes) ! 687: parmtypes = TREE_CHAIN (parmtypes); ! 688: if (DECL_CONSTRUCTOR_FOR_VBASE_P (t)) ! 689: /* Skip past "in_charge" identifier. */ ! 690: parmtypes = TREE_CHAIN (parmtypes); ! 691: } ! 692: ! 693: if (DESTRUCTOR_NAME_P (name)) ! 694: parmtypes = TREE_CHAIN (parmtypes); ! 695: ! 696: dump_function_name (t); ! 697: ! 698: OB_PUTC ('('); ! 699: ! 700: if (parmtypes) ! 701: dump_type (parmtypes, v); ! 702: else ! 703: OB_PUTS ("..."); ! 704: ! 705: OB_PUTC (')'); ! 706: ! 707: if (v && ! IDENTIFIER_TYPENAME_P (name)) ! 708: dump_type_suffix (TREE_TYPE (fntype), 1); ! 709: ! 710: if (TREE_CODE (fntype) == METHOD_TYPE) ! 711: dump_readonly_or_volatile ! 712: (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before); ! 713: } ! 714: ! 715: /* Handle the function name for a FUNCTION_DECL node, grokking operators ! 716: and destructors properly. */ ! 717: static void ! 718: dump_function_name (t) ! 719: tree t; ! 720: { ! 721: tree name = DECL_NAME (t); ! 722: ! 723: /* There ought to be a better way to find out whether or not something is ! 724: a destructor. */ ! 725: if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))) ! 726: { ! 727: OB_PUTC ('~'); ! 728: dump_decl (name, 0); ! 729: } ! 730: else if (IDENTIFIER_TYPENAME_P (name)) ! 731: { ! 732: /* This cannot use the hack that the operator's return ! 733: type is stashed off of its name because it may be ! 734: used for error reporting. In the case of conflicting ! 735: declarations, both will have the same name, yet ! 736: the types will be different, hence the TREE_TYPE field ! 737: of the first name will be clobbered by the second. */ ! 738: OB_PUTS ("operator "); ! 739: dump_type (TREE_TYPE (TREE_TYPE (t)), 0); ! 740: } ! 741: else if (IDENTIFIER_OPNAME_P (name)) ! 742: { ! 743: char *name_string = operator_name_string (name); ! 744: OB_PUTS ("operator "); ! 745: OB_PUTCP (name_string); ! 746: } ! 747: else ! 748: dump_decl (name, 0); ! 749: } ! 750: ! 751: static void ! 752: dump_char (c) ! 753: char c; ! 754: { ! 755: switch (c) ! 756: { ! 757: case '\n': ! 758: OB_PUTS ("\\n"); ! 759: break; ! 760: case '\t': ! 761: OB_PUTS ("\\t"); ! 762: break; ! 763: case '\v': ! 764: OB_PUTS ("\\v"); ! 765: break; ! 766: case '\b': ! 767: OB_PUTS ("\\b"); ! 768: break; ! 769: case '\r': ! 770: OB_PUTS ("\\r"); ! 771: break; ! 772: case '\f': ! 773: OB_PUTS ("\\f"); ! 774: break; ! 775: case '\a': ! 776: OB_PUTS ("\\a"); ! 777: break; ! 778: case '\\': ! 779: OB_PUTS ("\\\\"); ! 780: break; ! 781: case '\'': ! 782: OB_PUTS ("\\'"); ! 783: break; ! 784: case '\"': ! 785: OB_PUTS ("\\\""); ! 786: break; ! 787: default: ! 788: if (isprint (c)) ! 789: OB_PUTC (c); ! 790: else ! 791: { ! 792: sprintf (digit_buffer, "\\%03o", (int) c); ! 793: OB_PUTCP (digit_buffer); ! 794: } ! 795: } ! 796: } ! 797: ! 798: /* Print out a list of initializers (subr of dump_expr) */ ! 799: static void ! 800: dump_expr_list (l) ! 801: tree l; ! 802: { ! 803: while (l) ! 804: { ! 805: dump_expr (TREE_VALUE (l), 0); ! 806: if (TREE_CHAIN (l)) ! 807: OB_PUTC2 (',', ' '); ! 808: l = TREE_CHAIN (l); ! 809: } ! 810: } ! 811: ! 812: /* Print out an expression */ ! 813: static void ! 814: dump_expr (t, nop) ! 815: tree t; ! 816: int nop; /* suppress parens */ ! 817: { ! 818: switch (TREE_CODE (t)) ! 819: { ! 820: case VAR_DECL: ! 821: case PARM_DECL: ! 822: case FIELD_DECL: ! 823: case CONST_DECL: ! 824: case FUNCTION_DECL: ! 825: dump_decl (t, 0); ! 826: break; ! 827: ! 828: case INTEGER_CST: ! 829: { ! 830: tree type = TREE_TYPE (t); ! 831: my_friendly_assert (type != 0, 81); ! 832: ! 833: /* If it's an enum, output its tag, rather than its value. */ ! 834: if (TREE_CODE (type) == ENUMERAL_TYPE) ! 835: { ! 836: char *p = enum_name_string (t, type); ! 837: OB_PUTCP (p); ! 838: } ! 839: else if (type == char_type_node ! 840: || type == signed_char_type_node ! 841: || type == unsigned_char_type_node) ! 842: { ! 843: OB_PUTC ('\''); ! 844: dump_char (TREE_INT_CST_LOW (t)); ! 845: OB_PUTC ('\''); ! 846: } ! 847: else if (TREE_INT_CST_HIGH (t) ! 848: != (TREE_INT_CST_LOW (t) >> (HOST_BITS_PER_WIDE_INT - 1))) ! 849: { ! 850: tree val = t; ! 851: if (TREE_INT_CST_HIGH (val) < 0) ! 852: { ! 853: OB_PUTC ('-'); ! 854: val = build_int_2 (~TREE_INT_CST_LOW (val), ! 855: -TREE_INT_CST_HIGH (val)); ! 856: } ! 857: /* Would "%x%0*x" or "%x%*0x" get zero-padding on all ! 858: systems? */ ! 859: { ! 860: static char format[10]; /* "%x%09999x\0" */ ! 861: if (!format[0]) ! 862: sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4); ! 863: sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val), ! 864: TREE_INT_CST_LOW (val)); ! 865: OB_PUTCP (digit_buffer); ! 866: } ! 867: } ! 868: else ! 869: OB_PUTI (TREE_INT_CST_LOW (t)); ! 870: } ! 871: break; ! 872: ! 873: case REAL_CST: ! 874: #ifndef REAL_IS_NOT_DOUBLE ! 875: sprintf (digit_buffer, "%g", TREE_REAL_CST (t)); ! 876: #else ! 877: { ! 878: int i; ! 879: char *p = (char *) &TREE_REAL_CST (t); ! 880: sprintf (digit_buffer, "0x"); ! 881: for (i = 0; i < sizeof TREE_REAL_CST (t); i++) ! 882: sprintf (digit_buffer + 2 + 2*i, "%02x", *p++); ! 883: } ! 884: #endif ! 885: OB_PUTCP (digit_buffer); ! 886: break; ! 887: ! 888: case STRING_CST: ! 889: { ! 890: char *p = TREE_STRING_POINTER (t); ! 891: int len = TREE_STRING_LENGTH (t) - 1; ! 892: int i; ! 893: ! 894: OB_PUTC ('\"'); ! 895: for (i = 0; i < len; i++) ! 896: dump_char (p[i]); ! 897: OB_PUTC ('\"'); ! 898: } ! 899: break; ! 900: ! 901: case COMPOUND_EXPR: ! 902: dump_binary_op (",", t); ! 903: break; ! 904: ! 905: case COND_EXPR: ! 906: OB_PUTC ('('); ! 907: dump_expr (TREE_OPERAND (t, 0), 0); ! 908: OB_PUTS (" ? "); ! 909: dump_expr (TREE_OPERAND (t, 1), 0); ! 910: OB_PUTS (" : "); ! 911: dump_expr (TREE_OPERAND (t, 2), 0); ! 912: OB_PUTC (')'); ! 913: break; ! 914: ! 915: case SAVE_EXPR: ! 916: if (TREE_HAS_CONSTRUCTOR (t)) ! 917: { ! 918: OB_PUTS ("new "); ! 919: dump_type (TREE_TYPE (TREE_TYPE (t)), 0); ! 920: PARM_DECL_EXPR (t) = 1; ! 921: } ! 922: else ! 923: { ! 924: sorry ("operand of SAVE_EXPR not understood"); ! 925: goto error; ! 926: } ! 927: break; ! 928: ! 929: case NEW_EXPR: ! 930: OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t))); ! 931: OB_PUTC ('('); ! 932: dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); ! 933: OB_PUTC (')'); ! 934: break; ! 935: ! 936: case CALL_EXPR: ! 937: dump_expr (TREE_OPERAND (t, 0), 0); ! 938: OB_PUTC2 (' ', '('); ! 939: dump_expr_list (TREE_OPERAND (t, 1)); ! 940: OB_PUTC (')'); ! 941: break; ! 942: ! 943: case WITH_CLEANUP_EXPR: ! 944: /* Note that this only works for G++ cleanups. If somebody ! 945: builds a general cleanup, there's no way to represent it. */ ! 946: dump_expr (TREE_OPERAND (t, 0), 0); ! 947: break; ! 948: ! 949: case TARGET_EXPR: ! 950: /* Note that this only works for G++ target exprs. If somebody ! 951: builds a general TARGET_EXPR, there's no way to represent that ! 952: it initializes anything other that the parameter slot for the ! 953: default argument. Note we may have cleared out the first ! 954: operand in expand_expr, so don't go killing ourselves. */ ! 955: if (TREE_OPERAND (t, 1)) ! 956: dump_expr (TREE_OPERAND (t, 1), 0); ! 957: break; ! 958: ! 959: case MODIFY_EXPR: ! 960: case PLUS_EXPR: ! 961: case MINUS_EXPR: ! 962: case MULT_EXPR: ! 963: case TRUNC_DIV_EXPR: ! 964: case TRUNC_MOD_EXPR: ! 965: case MIN_EXPR: ! 966: case MAX_EXPR: ! 967: case LSHIFT_EXPR: ! 968: case RSHIFT_EXPR: ! 969: case BIT_IOR_EXPR: ! 970: case BIT_XOR_EXPR: ! 971: case BIT_AND_EXPR: ! 972: case BIT_ANDTC_EXPR: ! 973: case TRUTH_ANDIF_EXPR: ! 974: case TRUTH_ORIF_EXPR: ! 975: case LT_EXPR: ! 976: case LE_EXPR: ! 977: case GT_EXPR: ! 978: case GE_EXPR: ! 979: case EQ_EXPR: ! 980: case NE_EXPR: ! 981: dump_binary_op (opname_tab[(int) TREE_CODE (t)], t); ! 982: break; ! 983: ! 984: case CEIL_DIV_EXPR: ! 985: case FLOOR_DIV_EXPR: ! 986: case ROUND_DIV_EXPR: ! 987: dump_binary_op ("/", t); ! 988: break; ! 989: ! 990: case CEIL_MOD_EXPR: ! 991: case FLOOR_MOD_EXPR: ! 992: case ROUND_MOD_EXPR: ! 993: dump_binary_op ("%", t); ! 994: break; ! 995: ! 996: case COMPONENT_REF: ! 997: dump_binary_op (".", t); ! 998: break; ! 999: ! 1000: case CONVERT_EXPR: ! 1001: dump_unary_op ("+", t, nop); ! 1002: break; ! 1003: ! 1004: case ADDR_EXPR: ! 1005: if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL ! 1006: || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST) ! 1007: dump_expr (TREE_OPERAND (t, 0), 0); ! 1008: else ! 1009: dump_unary_op ("&", t, nop); ! 1010: break; ! 1011: ! 1012: case INDIRECT_REF: ! 1013: if (TREE_HAS_CONSTRUCTOR (t)) ! 1014: { ! 1015: t = TREE_OPERAND (t, 0); ! 1016: my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237); ! 1017: dump_expr (TREE_OPERAND (t, 0), 0); ! 1018: OB_PUTC ('('); ! 1019: dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); ! 1020: OB_PUTC (')'); ! 1021: } ! 1022: else ! 1023: dump_unary_op ("*", t, nop); ! 1024: break; ! 1025: ! 1026: case NEGATE_EXPR: ! 1027: case BIT_NOT_EXPR: ! 1028: case TRUTH_NOT_EXPR: ! 1029: case PREDECREMENT_EXPR: ! 1030: case PREINCREMENT_EXPR: ! 1031: dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, nop); ! 1032: break; ! 1033: ! 1034: case POSTDECREMENT_EXPR: ! 1035: case POSTINCREMENT_EXPR: ! 1036: OB_PUTC ('('); ! 1037: dump_expr (TREE_OPERAND (t, 0), 0); ! 1038: OB_PUTCP (opname_tab[(int)TREE_CODE (t)]); ! 1039: OB_PUTC (')'); ! 1040: break; ! 1041: ! 1042: case NON_LVALUE_EXPR: ! 1043: /* FIXME: This is a KLUDGE workaround for a parsing problem. There ! 1044: should be another level of INDIRECT_REF so that I don't have to do ! 1045: this. */ ! 1046: if (NEXT_CODE (t) == POINTER_TYPE) ! 1047: { ! 1048: tree next = TREE_TYPE (TREE_TYPE (t)); ! 1049: ! 1050: while (TREE_CODE (next) == POINTER_TYPE) ! 1051: next = TREE_TYPE (next); ! 1052: ! 1053: if (TREE_CODE (next) == FUNCTION_TYPE) ! 1054: { ! 1055: if (!nop) OB_PUTC ('('); ! 1056: OB_PUTC ('*'); ! 1057: dump_expr (TREE_OPERAND (t, 0), 1); ! 1058: if (!nop) OB_PUTC (')'); ! 1059: break; ! 1060: } ! 1061: /* else FALLTHRU */ ! 1062: } ! 1063: dump_expr (TREE_OPERAND (t, 0), 0); ! 1064: break; ! 1065: ! 1066: case NOP_EXPR: ! 1067: dump_expr (TREE_OPERAND (t, 0), nop); ! 1068: break; ! 1069: ! 1070: case CONSTRUCTOR: ! 1071: OB_PUTC ('{'); ! 1072: dump_expr_list (CONSTRUCTOR_ELTS (t), 0); ! 1073: OB_PUTC ('}'); ! 1074: break; ! 1075: ! 1076: /* This list is incomplete, but should suffice for now. ! 1077: It is very important that `sorry' does not call ! 1078: `report_error_function'. That could cause an infinite loop. */ ! 1079: default: ! 1080: sorry ("`%s' not supported by dump_expr", ! 1081: tree_code_name[(int) TREE_CODE (t)]); ! 1082: ! 1083: /* fall through to ERROR_MARK... */ ! 1084: case ERROR_MARK: ! 1085: error: ! 1086: OB_PUTCP ("/* error */"); ! 1087: break; ! 1088: } ! 1089: } ! 1090: ! 1091: static void ! 1092: dump_binary_op (opstring, t) ! 1093: char *opstring; ! 1094: tree t; ! 1095: { ! 1096: OB_PUTC ('('); ! 1097: dump_expr (TREE_OPERAND (t, 0), 1); ! 1098: OB_PUTC (' '); ! 1099: OB_PUTCP (opstring); ! 1100: OB_PUTC (' '); ! 1101: dump_expr (TREE_OPERAND (t, 1), 1); ! 1102: OB_PUTC (')'); ! 1103: } ! 1104: ! 1105: static void ! 1106: dump_unary_op (opstring, t, nop) ! 1107: char *opstring; ! 1108: tree t; ! 1109: int nop; ! 1110: { ! 1111: if (!nop) OB_PUTC ('('); ! 1112: OB_PUTCP (opstring); ! 1113: dump_expr (TREE_OPERAND (t, 0), 1); ! 1114: if (!nop) OB_PUTC (')'); ! 1115: } ! 1116: ! 1117: char * ! 1118: fndecl_as_string (cname, fndecl, print_ret_type_p) ! 1119: tree cname, fndecl; ! 1120: int print_ret_type_p; ! 1121: { ! 1122: return decl_as_string (fndecl, print_ret_type_p); ! 1123: } ! 1124: ! 1125: /* Same, but handtype a _TYPE. ! 1126: Called from convert_to_reference, mangle_class_name_for_template, ! 1127: build_unary_op, and GNU_xref_decl. */ ! 1128: char * ! 1129: type_as_string (typ, v) ! 1130: tree typ; ! 1131: int v; ! 1132: { ! 1133: OB_INIT (); ! 1134: ! 1135: dump_type (typ, v); ! 1136: ! 1137: OB_FINISH (); ! 1138: ! 1139: return (char *)obstack_base (&scratch_obstack); ! 1140: } ! 1141: ! 1142: char * ! 1143: expr_as_string (decl, v) ! 1144: tree decl; ! 1145: int v; ! 1146: { ! 1147: OB_INIT (); ! 1148: ! 1149: dump_expr (decl, 1); ! 1150: ! 1151: OB_FINISH (); ! 1152: ! 1153: return (char *)obstack_base (&scratch_obstack); ! 1154: } ! 1155: ! 1156: /* A cross between type_as_string and fndecl_as_string. ! 1157: Only called from substitute_nice_name. */ ! 1158: char * ! 1159: decl_as_string (decl, v) ! 1160: tree decl; ! 1161: int v; ! 1162: { ! 1163: OB_INIT (); ! 1164: ! 1165: dump_decl (decl, v); ! 1166: ! 1167: OB_FINISH (); ! 1168: ! 1169: return (char *)obstack_base (&scratch_obstack); ! 1170: } ! 1171: ! 1172: char * ! 1173: cp_file_of (t) ! 1174: tree t; ! 1175: { ! 1176: if (TREE_CODE (t) == PARM_DECL) ! 1177: return DECL_SOURCE_FILE (DECL_CONTEXT (t)); ! 1178: else ! 1179: return DECL_SOURCE_FILE (t); ! 1180: } ! 1181: ! 1182: int ! 1183: cp_line_of (t) ! 1184: tree t; ! 1185: { ! 1186: if (TREE_CODE (t) == PARM_DECL) ! 1187: return DECL_SOURCE_LINE (DECL_CONTEXT (t)); ! 1188: else ! 1189: return DECL_SOURCE_LINE (t); ! 1190: } ! 1191: ! 1192: char * ! 1193: code_as_string (c, v) ! 1194: enum tree_code c; ! 1195: int v; ! 1196: { ! 1197: return tree_code_name [c]; ! 1198: } ! 1199: ! 1200: char * ! 1201: language_as_string (c, v) ! 1202: enum languages c; ! 1203: int v; ! 1204: { ! 1205: switch (c) ! 1206: { ! 1207: case lang_c: ! 1208: return "C"; ! 1209: ! 1210: case lang_cplusplus: ! 1211: return "C++"; ! 1212: ! 1213: default: ! 1214: my_friendly_abort (355); ! 1215: } ! 1216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.