]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Don't trust templates from DW_AT_name users/simark/template-suffix
authorSimon Marchi <simon.marchi@polymtl.ca>
Sun, 4 Feb 2018 18:10:28 +0000 (13:10 -0500)
committerSimon Marchi <simon.marchi@polymtl.ca>
Mon, 5 Feb 2018 03:21:08 +0000 (22:21 -0500)
With gcc 8 (and clang?) the non-type template arguments (constants)
don't include the integer suffixes anymore.  For example, with

  template <unsigned int X>
  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).

gdb/c-valprint.c
gdb/dwarf2read.c
gdb/valprint.c
gdb/valprint.h

index c4c0918e26afe58dc488f0d1ba2a39af4b1bddd7..12b908652c9097d15101b12017950b09ed312db0 100644 (file)
@@ -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
     {
index 51d0f39f75e92a004d44062c65f6aaf1a293e275..1960ccc4d10fed454afff1009102f4720a6ee3d2 100644 (file)
@@ -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<char> 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);
index 3104e0b45e10955a8d503ad89581b25c6ebb9aab..0105cdea9484cdb946b1171c328529f71d985025 100644 (file)
@@ -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.  */
index f005c31f87168d5c17e3c4cef9f6f7b829a397b0..248d9304997d5c14303132a79b21d79e9729806e 100644 (file)
@@ -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