From b2858c9f3ed8275a61ee02421b8fc51ab070c79e Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 3 Jun 2015 08:24:50 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/pr64223-1.c | 12 ++++ gcc/testsuite/gcc.dg/pr64223-2.c | 13 ++++ gcc/tree.c | 103 ++++++++++++++++++++----------- 5 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr64223-1.c create mode 100644 gcc/testsuite/gcc.dg/pr64223-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8813ade38d5..ad33c67fa12 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-06-03 Marek Polacek + + 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 PR tree-optimization/63916 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 026dd538696..d3280fc20f3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-06-03 Marek Polacek + + 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 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 00000000000..015bfd87fb9 --- /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 00000000000..2a1627e99b2 --- /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 ca48c60dd10..805e2cc42c9 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); } -- 2.30.2