re PR c/64223 (same warning repeated twice with same line number)
authorMarek Polacek <polacek@redhat.com>
Wed, 3 Jun 2015 08:24:50 +0000 (08:24 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 3 Jun 2015 08:24:50 +0000 (08:24 +0000)
PR c/64223
PR c/29358
* tree.c (attribute_value_equal): Handle attribute format.
(cmp_attrib_identifiers): Factor out of lookup_ident_attribute.

* gcc.dg/pr64223-1.c: New test.
* gcc.dg/pr64223-2.c: New test.

From-SVN: r224062

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr64223-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr64223-2.c [new file with mode: 0644]
gcc/tree.c

index 8813ade38d50570eec5ee4d1a5359655ecd5d046..ad33c67fa127118a74280dd11b5053dd756ab3d1 100644 (file)
@@ -1,3 +1,10 @@
+2015-06-03  Marek Polacek  <polacek@redhat.com>
+
+       PR c/64223
+       PR c/29358
+       * tree.c (attribute_value_equal): Handle attribute format.
+       (cmp_attrib_identifiers): Factor out of lookup_ident_attribute.
+
 2015-06-03  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/63916
index 026dd538696ce3c846673fca43a2260d53bc34ff..d3280fc20f34bd94e9d4bdd9df4d8bf9a82b5b84 100644 (file)
@@ -1,3 +1,10 @@
+2015-06-03  Marek Polacek  <polacek@redhat.com>
+
+       PR c/64223
+       PR c/29358
+       * gcc.dg/pr64223-1.c: New test.
+       * gcc.dg/pr64223-2.c: New test.
+
 2015-06-03  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/63916
diff --git a/gcc/testsuite/gcc.dg/pr64223-1.c b/gcc/testsuite/gcc.dg/pr64223-1.c
new file mode 100644 (file)
index 0000000..015bfd8
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR c/64223: Test for duplicated warnings.  */
+/* { dg-do compile } */
+/* { dg-options "-Wformat" } */
+
+int printf (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+
+void
+foo (void)
+{
+  printf ("%d\n", 0UL); /* { dg-bogus "expects argument of type.*expects argument of type" } */
+ /* { dg-warning "expects argument of type" "" { target *-*-* } 10 } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr64223-2.c b/gcc/testsuite/gcc.dg/pr64223-2.c
new file mode 100644 (file)
index 0000000..2a1627e
--- /dev/null
@@ -0,0 +1,13 @@
+/* PR c/64223: Test for duplicated warnings.  */
+/* { dg-do compile } */
+/* { dg-options "-Wformat" } */
+
+int myprintf (const char *, ...) __attribute__ ((__format__ (printf, 1, 2)));
+int myprintf (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+
+void
+foo (void)
+{
+  myprintf ("%d\n", 0UL); /* { dg-bogus "expects argument of type.*expects argument of type" } */
+ /* { dg-warning "expects argument of type" "" { target *-*-* } 11 } */
+}
index ca48c60dd1090b6a2abb1345feb6c46ed231b799..805e2cc42c9b2303457e9066c124d985ecbbb962 100644 (file)
@@ -4871,9 +4871,53 @@ simple_cst_list_equal (const_tree l1, const_tree l2)
   return l1 == l2;
 }
 
+/* Compare two identifier nodes representing attributes.  Either one may
+   be in wrapped __ATTR__ form.  Return true if they are the same, false
+   otherwise.  */
+
+static bool
+cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
+{
+  /* Make sure we're dealing with IDENTIFIER_NODEs.  */
+  gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
+                      && TREE_CODE (attr2) == IDENTIFIER_NODE);
+
+  /* Identifiers can be compared directly for equality.  */
+  if (attr1 == attr2)
+    return true;
+
+  /* If they are not equal, they may still be one in the form
+     'text' while the other one is in the form '__text__'.  TODO:
+     If we were storing attributes in normalized 'text' form, then
+     this could all go away and we could take full advantage of
+     the fact that we're comparing identifiers. :-)  */
+  const size_t attr1_len = IDENTIFIER_LENGTH (attr1);
+  const size_t attr2_len = IDENTIFIER_LENGTH (attr2);
+
+  if (attr2_len == attr1_len + 4)
+    {
+      const char *p = IDENTIFIER_POINTER (attr2);
+      const char *q = IDENTIFIER_POINTER (attr1);
+      if (p[0] == '_' && p[1] == '_'
+         && p[attr2_len - 2] == '_' && p[attr2_len - 1] == '_'
+         && strncmp (q, p + 2, attr1_len) == 0)
+       return true;;
+    }
+  else if (attr2_len + 4 == attr1_len)
+    {
+      const char *p = IDENTIFIER_POINTER (attr2);
+      const char *q = IDENTIFIER_POINTER (attr1);
+      if (q[0] == '_' && q[1] == '_'
+         && q[attr1_len - 2] == '_' && q[attr1_len - 1] == '_'
+         && strncmp (q + 2, p, attr2_len) == 0)
+       return true;
+    }
+
+  return false;
+}
+
 /* Compare two attributes for their value identity.  Return true if the
-   attribute values are known to be equal; otherwise return false.
-*/
+   attribute values are known to be equal; otherwise return false.  */
 
 bool
 attribute_value_equal (const_tree attr1, const_tree attr2)
@@ -4883,10 +4927,25 @@ attribute_value_equal (const_tree attr1, const_tree attr2)
 
   if (TREE_VALUE (attr1) != NULL_TREE
       && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
-      && TREE_VALUE (attr2) != NULL
+      && TREE_VALUE (attr2) != NULL_TREE
       && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
-    return (simple_cst_list_equal (TREE_VALUE (attr1),
-                                  TREE_VALUE (attr2)) == 1);
+    {
+      /* Handle attribute format.  */
+      if (is_attribute_p ("format", TREE_PURPOSE (attr1)))
+       {
+         attr1 = TREE_VALUE (attr1);
+         attr2 = TREE_VALUE (attr2);
+         /* Compare the archetypes (printf/scanf/strftime/...).  */
+         if (!cmp_attrib_identifiers (TREE_VALUE (attr1),
+                                      TREE_VALUE (attr2)))
+           return false;
+         /* Archetypes are the same.  Compare the rest.  */
+         return (simple_cst_list_equal (TREE_CHAIN (attr1),
+                                        TREE_CHAIN (attr2)) == 1);
+       }
+      return (simple_cst_list_equal (TREE_VALUE (attr1),
+                                    TREE_VALUE (attr2)) == 1);
+    }
 
   if ((flag_openmp || flag_openmp_simd)
       && TREE_VALUE (attr1) && TREE_VALUE (attr2)
@@ -6037,38 +6096,10 @@ lookup_ident_attribute (tree attr_identifier, tree list)
       gcc_checking_assert (TREE_CODE (get_attribute_name (list))
                           == IDENTIFIER_NODE);
 
-      /* Identifiers can be compared directly for equality.  */
-      if (attr_identifier == get_attribute_name (list))
+      if (cmp_attrib_identifiers (attr_identifier,
+                                 get_attribute_name (list)))
+       /* Found it.  */
        break;
-
-      /* If they are not equal, they may still be one in the form
-        'text' while the other one is in the form '__text__'.  TODO:
-        If we were storing attributes in normalized 'text' form, then
-        this could all go away and we could take full advantage of
-        the fact that we're comparing identifiers. :-)  */
-      {
-       size_t attr_len = IDENTIFIER_LENGTH (attr_identifier);
-       size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
-
-       if (ident_len == attr_len + 4)
-         {
-           const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
-           const char *q = IDENTIFIER_POINTER (attr_identifier);
-           if (p[0] == '_' && p[1] == '_'
-               && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
-               && strncmp (q, p + 2, attr_len) == 0)
-             break;
-         }
-       else if (ident_len + 4 == attr_len)
-         {
-           const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
-           const char *q = IDENTIFIER_POINTER (attr_identifier);
-           if (q[0] == '_' && q[1] == '_'
-               && q[attr_len - 2] == '_' && q[attr_len - 1] == '_'
-               && strncmp (q + 2, p, ident_len) == 0)
-             break;
-         }
-      }
       list = TREE_CHAIN (list);
     }