diff options
author | Marek Polacek <polacek@redhat.com> | 2015-06-03 08:24:50 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2015-06-03 08:24:50 +0000 |
commit | b2858c9f3ed8275a61ee02421b8fc51ab070c79e (patch) | |
tree | d4477da9734232d08a6931b572a242888d3bc413 | |
parent | 4da60082232bc3dbf5782687e9f0ff25d733de10 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr64223-1.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr64223-2.c | 13 | ||||
-rw-r--r-- | gcc/tree.c | 103 |
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 } */ +} @@ -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); } |