[multiple changes]
authorAndreas Krebbel <krebbel@gcc.gnu.org>
Thu, 25 Sep 2014 07:37:36 +0000 (07:37 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Thu, 25 Sep 2014 07:37:36 +0000 (07:37 +0000)
2014-09-25  Andreas Arnez  <arnez@linux.vnet.ibm.com>

PR 63300/debug
* tree.c (check_base_type): New.
(check_qualified_type): Exploit new helper function above.
* tree.h (check_base_type): New prototype.
* dwarf2out.c (get_nearest_type_subqualifiers): New.
(modified_type_die): Fix handling for qualifiers.  Qualifiers to
"peel off" are now determined using get_nearest_type_subqualifiers.

2014-09-25  Mark Wielaard  <mjw@redhat.com>

PR 63300/debug
* gcc.dg/debug/dwarf2/stacked-qualified-types-1.c: New testcase.
* gcc.dg/debug/dwarf2/stacked-qualified-types-2.c: Likewise.
* gcc.dg/guality/pr63300-const-volatile.c: New testcase.

From-SVN: r215582

gcc/dwarf2out.c
gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr63300-const-volatile.c [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index 1ae8dc32c49b84b501365cc67d436ccd8ea45a79..b5fcfa430992c7ac0a05179a0aa84eebc6e9ea20 100644 (file)
@@ -10461,6 +10461,40 @@ decl_quals (const_tree decl)
             ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED));
 }
 
+/* Determine the TYPE whose qualifiers match the largest strict subset
+   of the given TYPE_QUALS, and return its qualifiers.  Ignore all
+   qualifiers outside QUAL_MASK.  */
+
+static int
+get_nearest_type_subqualifiers (tree type, int type_quals, int qual_mask)
+{
+  tree t;
+  int best_rank = 0, best_qual = 0, max_rank;
+
+  type_quals &= qual_mask;
+  max_rank = popcount_hwi (type_quals) - 1;
+
+  for (t = TYPE_MAIN_VARIANT (type); t && best_rank < max_rank;
+       t = TYPE_NEXT_VARIANT (t))
+    {
+      int q = TYPE_QUALS (t) & qual_mask;
+
+      if ((q & type_quals) == q && q != type_quals
+         && check_base_type (t, type))
+       {
+         int rank = popcount_hwi (q);
+
+         if (rank > best_rank)
+           {
+             best_rank = rank;
+             best_qual = q;
+           }
+       }
+    }
+
+  return best_qual;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
    entry that chains various modifiers in front of the given type.  */
 
@@ -10474,12 +10508,14 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
   tree qualified_type;
   tree name, low, high;
   dw_die_ref mod_scope;
+  /* Only these cv-qualifiers are currently handled.  */
+  const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
+                           | TYPE_QUAL_RESTRICT);
 
   if (code == ERROR_MARK)
     return NULL;
 
-  /* Only these cv-qualifiers are currently handled.  */
-  cv_quals &= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT);
+  cv_quals &= cv_qual_mask;
 
   /* Don't emit DW_TAG_restrict_type for DWARFv2, since it is a type
      tag modifier (and not an attribute) old consumers won't be able
@@ -10530,7 +10566,7 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
       else
        {
          int dquals = TYPE_QUALS_NO_ADDR_SPACE (dtype);
-         dquals &= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT);
+         dquals &= cv_qual_mask;
          if ((dquals & ~cv_quals) != TYPE_UNQUALIFIED
              || (cv_quals == dquals && DECL_ORIGINAL_TYPE (name) != type))
            /* cv-unqualified version of named type.  Just use
@@ -10543,33 +10579,33 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
 
   mod_scope = scope_die_for (type, context_die);
 
-  if ((cv_quals & TYPE_QUAL_CONST)
-      /* If there are multiple type modifiers, prefer a path which
-        leads to a qualified type.  */
-      && (((cv_quals & ~TYPE_QUAL_CONST) == TYPE_UNQUALIFIED)
-         || get_qualified_type (type, cv_quals) == NULL_TREE
-         || (get_qualified_type (type, cv_quals & ~TYPE_QUAL_CONST)
-             != NULL_TREE)))
-    {
-      mod_type_die = new_die (DW_TAG_const_type, mod_scope, type);
-      sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_CONST,
-                                  context_die);
-    }
-  else if ((cv_quals & TYPE_QUAL_VOLATILE)
-          && (((cv_quals & ~TYPE_QUAL_VOLATILE) == TYPE_UNQUALIFIED)
-              || get_qualified_type (type, cv_quals) == NULL_TREE
-              || (get_qualified_type (type, cv_quals & ~TYPE_QUAL_VOLATILE)
-                  != NULL_TREE)))
-    {
-      mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type);
-      sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_VOLATILE,
-                                  context_die);
-    }
-  else if (cv_quals & TYPE_QUAL_RESTRICT)
-    {
-      mod_type_die = new_die (DW_TAG_restrict_type, mod_scope, type);
-      sub_die = modified_type_die (type, cv_quals & ~TYPE_QUAL_RESTRICT,
-                                  context_die);
+  if (cv_quals)
+    {
+      struct qual_info { int q; enum dwarf_tag t; };
+      static const struct qual_info qual_info[] =
+       {
+         { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
+         { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
+         { TYPE_QUAL_CONST, DW_TAG_const_type },
+       };
+      int sub_quals;
+      unsigned i;
+
+      /* Determine a lesser qualified type that most closely matches
+        this one.  Then generate DW_TAG_* entries for the remaining
+        qualifiers.  */
+      sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
+                                                 cv_qual_mask);
+      mod_type_die = modified_type_die (type, sub_quals, context_die);
+
+      for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
+       if (qual_info[i].q & cv_quals & ~sub_quals)
+         {
+           dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
+           if (mod_type_die)
+             add_AT_die_ref (d, DW_AT_type, mod_type_die);
+           mod_type_die = d;
+         }
     }
   else if (code == POINTER_TYPE)
     {
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-1.c
new file mode 100644 (file)
index 0000000..6f40901
--- /dev/null
@@ -0,0 +1,18 @@
+/* PR63300 make sure we don't duplicate type qualifiers unneeded.  */
+/* { dg-do compile } */
+/* { dg-options "-gdwarf -dA" } */
+
+/* This should give us:
+   - One const type pointing to a char
+   - One volatile type pointing to a char
+   - Either one const type pointing to the volatile type pointing to a char
+     or one volatile type pointing to the const type pointing to a char.
+     But not both.  */
+
+char a;
+const char b;
+volatile const char c;
+volatile char d;
+const volatile char e;
+
+/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile)_type" 3 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/stacked-qualified-types-2.c
new file mode 100644 (file)
index 0000000..5a8d3a0
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR63300 make sure we don't duplicate type qualifiers unneeded.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -gdwarf-4 -dA" } */
+
+/* This should give us:
+   - One restrict type pointing to a char pointer.
+   - One volatile type pointing to the restrict type.
+   - One const type pointing to the restrict type.
+   - Either one const type pointing to the volatile type pointing to
+     the restrict type or one volatile type pointing to the const type
+     pointing to the restrict type.  But not both.  */
+
+char * restrict a;
+char * const restrict b;
+char * const volatile restrict c;
+char * volatile restrict d;
+
+/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_restrict_type" 1 } } */
+/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_(?:const|volatile)_type" 3 } } */
diff --git a/gcc/testsuite/gcc.dg/guality/pr63300-const-volatile.c b/gcc/testsuite/gcc.dg/guality/pr63300-const-volatile.c
new file mode 100644 (file)
index 0000000..b8d75ed
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR63300 'const volatile' sometimes stripped in debug info */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+int
+main (int argc, char **argv)
+{
+  const volatile int v = argc;
+  return v - argc;
+}
+
+/* { dg-final { gdb-test 9 "type:v" "const volatile int" } } */
index a46210ff1b27608a43f12957814c14f6e1bc8935..2f4d194dee56937081329bab88b8ceccde484c5d 100644 (file)
@@ -6185,13 +6185,12 @@ set_type_quals (tree type, int type_quals)
   TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
 }
 
-/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
+/* Returns true iff unqualified CAND and BASE are equivalent.  */
 
 bool
-check_qualified_type (const_tree cand, const_tree base, int type_quals)
+check_base_type (const_tree cand, const_tree base)
 {
-  return (TYPE_QUALS (cand) == type_quals
-         && TYPE_NAME (cand) == TYPE_NAME (base)
+  return (TYPE_NAME (cand) == TYPE_NAME (base)
          /* Apparently this is needed for Objective-C.  */
          && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
          /* Check alignment.  */
@@ -6200,6 +6199,15 @@ check_qualified_type (const_tree cand, const_tree base, int type_quals)
                                   TYPE_ATTRIBUTES (base)));
 }
 
+/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
+
+bool
+check_qualified_type (const_tree cand, const_tree base, int type_quals)
+{
+  return (TYPE_QUALS (cand) == type_quals
+         && check_base_type (cand, base));
+}
+
 /* Returns true iff CAND is equivalent to BASE with ALIGN.  */
 
 static bool
index cd3187dd05aff31a61ec92fca81841c8684bdca0..254129a420af75cb1680aafa6ffc78f31ed1906e 100644 (file)
@@ -3829,6 +3829,10 @@ extern tree merge_dllimport_decl_attributes (tree, tree);
 extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
 #endif
 
+/* Returns true iff unqualified CAND and BASE are equivalent.  */
+
+extern bool check_base_type (const_tree cand, const_tree base);
+
 /* Check whether CAND is suitable to be returned from get_qualified_type
    (BASE, TYPE_QUALS).  */