https://gcc.gnu.org/g:b92e8826eb34599f8693403aacf8a655bb591780
commit r17-1150-gb92e8826eb34599f8693403aacf8a655bb591780 Author: Peter Damianov <[email protected]> Date: Tue Apr 28 17:54:50 2026 +0100 c++: Improve -fdump-lang-class output When I was researching to write my blogpost about vtables: https://peter0x44.github.io/posts/vtables-itanium-abi/ I noticed a few improvements I could make to -fdump-lang-class's output -fdump-lang-class prepended "0x" to HOST_WIDE_INT_PRINT_HEX outputs, but the macro already includes that prefix, producing "0x0x..." in dumps. Some vtable entries hold signed values e.g. vcall offsets, vbase offsets, offset-to-top. When expr_as_string prints those INTEGER_CSTs, negative offsets appear as large (unsigned) values. Print integer vtable entries as signed values, and keep expr_as_string for all other entries. gcc/cp/ChangeLog: * class.cc (dump_vtable_entry): New function. (dump_array): Use it. (dump_class_hierarchy_r): Drop redundant literal 0x from HOST_WIDE_INT_PRINT_HEX formatting. (dump_vtable): Likewise. Signed-off-by: Peter Damianov <[email protected]> Diff: --- gcc/cp/class.cc | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index a20fad116e71..8755403d3620 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -167,6 +167,7 @@ static int maybe_indent_hierarchy (FILE *, int, int); static tree dump_class_hierarchy_r (FILE *, dump_flags_t, tree, tree, int); static void dump_class_hierarchy (tree); static void dump_class_hierarchy_1 (FILE *, dump_flags_t, tree); +static void dump_vtable_entry (FILE *, tree); static void dump_array (FILE *, tree); static void dump_vtable (tree, tree, tree); static void dump_vtt (tree, tree); @@ -9762,7 +9763,7 @@ dump_class_hierarchy_r (FILE *stream, tree base_binfo; int i; - fprintf (stream, "%s (0x" HOST_WIDE_INT_PRINT_HEX ") ", + fprintf (stream, "%s (" HOST_WIDE_INT_PRINT_HEX ") ", type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER), (HOST_WIDE_INT) (uintptr_t) binfo); if (binfo != igo) @@ -9785,7 +9786,7 @@ dump_class_hierarchy_r (FILE *stream, if (BINFO_PRIMARY_P (binfo)) { indented = maybe_indent_hierarchy (stream, indent + 3, indented); - fprintf (stream, " primary-for %s (0x" HOST_WIDE_INT_PRINT_HEX ")", + fprintf (stream, " primary-for %s (" HOST_WIDE_INT_PRINT_HEX ")", type_as_string (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)), TFF_PLAIN_IDENTIFIER), (HOST_WIDE_INT) (uintptr_t) BINFO_INHERITANCE_CHAIN (binfo)); @@ -9878,6 +9879,23 @@ dump_class_hierarchy (tree t) } } +/* Dump VALUE, a vtable entry, to STREAM. Print integer offsets as signed + values. */ + +static void +dump_vtable_entry (FILE *stream, tree value) +{ + /* Vtable offset entries are stored in the pointer-sized vtable entry + type, but should be displayed as signed ptrdiff_t values. */ + tree cst = value; + STRIP_NOPS (cst); + + if (TREE_CODE (cst) == INTEGER_CST) + print_decs (wi::to_wide (cst), stream); + else + fprintf (stream, "%s", expr_as_string (value, TFF_PLAIN_IDENTIFIER)); +} + static void dump_array (FILE * stream, tree decl) { @@ -9896,8 +9914,11 @@ dump_array (FILE * stream, tree decl) FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), ix, value) - fprintf (stream, "%-4ld %s\n", (long)(ix * elt), - expr_as_string (value, TFF_PLAIN_IDENTIFIER)); + { + fprintf (stream, "%-4ld ", (long)(ix * elt)); + dump_vtable_entry (stream, value); + fprintf (stream, "\n"); + } } static void @@ -9919,7 +9940,7 @@ dump_vtable (tree t, tree binfo, tree vtable) if (ctor_vtbl_p) { if (!BINFO_VIRTUAL_P (binfo)) - fprintf (stream, " (0x" HOST_WIDE_INT_PRINT_HEX " instance)", + fprintf (stream, " (" HOST_WIDE_INT_PRINT_HEX " instance)", (HOST_WIDE_INT) (uintptr_t) binfo); fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER)); }
