From: Simon Marchi Date: Sun, 4 Feb 2018 18:10:28 +0000 (-0500) Subject: Don't trust templates from DW_AT_name X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fusers%2Fsimark%2Ftemplate-suffix;p=thirdparty%2Fbinutils-gdb.git Don't trust templates from DW_AT_name With gcc 8 (and clang?) the non-type template arguments (constants) don't include the integer suffixes anymore. For example, with template class foo { ... }; foo<10u> used to generate foo<10u> as the DW_AT_name, now it generates foo<10>. This is a problem when things look up "foo<10u>" and don't find it. For example, when trying to print an instance of that class through a base class pointer, GDB would first demangle the symbol for that class' vtable, which would give "vtable for foo<10u>". GDB would then take the "foo<10u>" from that string and try to look up the type. With the new DW_AT_name, it would fail to look it up, and fail to print the value. This patch makes it so GDB doesn't trust the templates contained in DW_AT_name. Instead, it re-builds the name from the DW_AT_template_* DIES in the format that it expects (with the integer suffixes). --- diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index c4c0918e26a..12b908652c9 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -454,6 +454,21 @@ c_val_print_int (struct type *type, struct type *unresolved_type, : options->output_format); val_print_scalar_formatted (type, embedded_offset, original_value, &opts, 0, stream); + + if (opts.print_suffix) + { + struct type *t = check_typedef (type); + + if (TYPE_UNSIGNED (t)) + fputc_filtered ('u', stream); + + /* Is there a better way to do this? Just looking at the size doesn't + work. */ + if (strstr (TYPE_NAME (t), "long long") != NULL) + fputs_filtered ("ll", stream); + else if (strstr (TYPE_NAME (t), "long") != NULL) + fputc_filtered ('l', stream); + } } else { diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 51d0f39f75e..1960ccc4d10 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -9211,7 +9211,7 @@ partial_die_full_name (struct partial_die_info *pdi, { fixup_partial_die (pdi, cu); - if (pdi->name != NULL && strchr (pdi->name, '<') == NULL) + if (pdi->name != NULL) { struct die_info *die; struct attribute attr; @@ -10875,6 +10875,22 @@ dwarf2_compute_name (const char *name, if (name == NULL) name = dwarf2_name (die, cu); + /* If there is a template in the name, strip it and let the code below + re-compute it. */ + gdb::unique_xmalloc_ptr holder; + if (name != NULL) + { + const char *opening = strchr (name, '<'); + if (opening != NULL) + { + /* In this case, name will get copied/modified and re-assigned, + so we can free this copy. */ + holder.reset (xstrdup (name)); + holder.get ()[opening - name] = '\0'; + name = holder.get (); + } + } + /* For Fortran GDB prefers DW_AT_*linkage_name for the physname if present but otherwise compute it by typename_concat inside GDB. FIXME: Actually this is not really true, or at least not always true. @@ -10942,7 +10958,7 @@ dwarf2_compute_name (const char *name, templates; two instantiated function templates are allowed to differ only by their return types, which we do not add here. */ - if (cu->language == language_cplus && strchr (name, '<') == NULL) + if (cu->language == language_cplus) { struct attribute *attr; struct die_info *child; @@ -11026,6 +11042,7 @@ dwarf2_compute_name (const char *name, the radix. */ get_formatted_print_options (&opts, 'd'); opts.raw = 1; + opts.print_suffix = true; value_print (v, &buf, &opts); release_value (v); value_free (v); diff --git a/gdb/valprint.c b/gdb/valprint.c index 3104e0b45e1..0105cdea948 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -109,7 +109,8 @@ struct value_print_options user_print_options = 1, /* pascal_static_field_print */ 0, /* raw */ 0, /* summary */ - 1 /* symbol_print */ + 1, /* symbol_print */ + false, /* print_suffix */ }; /* Initialize *OPTS to be a copy of the user print options. */ diff --git a/gdb/valprint.h b/gdb/valprint.h index f005c31f871..248d9304997 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -92,6 +92,10 @@ struct value_print_options /* If nonzero, when printing a pointer, print the symbol to which it points, if any. */ int symbol_print; + + /* If true, print the integer suffixes (u for unsigned, l for long, ll for + long long). */ + bool print_suffix; }; /* The global print options set by the user. In general this should