aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-06-03 08:24:50 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-06-03 08:24:50 +0000
commitb2858c9f3ed8275a61ee02421b8fc51ab070c79e (patch)
treed4477da9734232d08a6931b572a242888d3bc413
parent4da60082232bc3dbf5782687e9f0ff25d733de10 (diff)
downloadgcc-b2858c9f3ed8275a61ee02421b8fc51ab070c79e.zip
gcc-b2858c9f3ed8275a61ee02421b8fc51ab070c79e.tar.gz
gcc-b2858c9f3ed8275a61ee02421b8fc51ab070c79e.tar.bz2
re PR c/64223 (same warning repeated twice with same line number)
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr64223-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr64223-2.c13
-rw-r--r--gcc/tree.c103
5 files changed, 106 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8813ade..ad33c67 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 026dd53..d3280fc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..015bfd8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64223-1.c
@@ -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
index 0000000..2a1627e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64223-2.c
@@ -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 } */
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index ca48c60d..805e2cc 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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);
}