The attached patch refines the logic used to suggest the format attribute to filter out functions that use string literals and constants as formats.
This change has the effect of not suggesting the attribute for functions like the one below (since the attribute couldn't very be used with it): void g (char *d, __builtin_va_list va) { vsprintf (d, "%i", va); } I started seeing the warnings after my recent changes to the Wformat-length patch and couldn't find a good way to suppress them other than via #pragma GCC diagnostic. Martin
PR c/77336 - -Wsuggest-attribute=format warning overly simplistic gcc/c-family/ChangeLog: 2016-08-23 Martin Sebor <mse...@redhat.com> PR c/77336 * c-format.c (check_function_format): Avoid issuing warnings for functions unless they call format functions with non-constant format strings. gcc/testsuite/ChangeLog: 2016-08-23 Martin Sebor <mse...@redhat.com> PR c/77336 * gcc.dg/format/miss-7.c: New test. diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index ad434f8..413962e 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "c-format.h" #include "diagnostic.h" #include "selftest.h" +#include "builtins.h" /* Handle attributes associated with format checking. */ @@ -1212,9 +1213,17 @@ check_function_format (tree attrs, int nargs, tree *argarray) params = tree_cons (NULL_TREE, argarray[i], params); check_format_info (&info, params); } + + /* Attempt to detect whether the current function might benefit + from the format attribute if the called function is decorated + with it. Avoid using calls with string literal formats for + guidance since those are unlikely to be viable candidates. */ if (warn_suggest_attribute_format && info.first_arg_num == 0 && (format_types[info.format_type].flags - & (int) FMT_FLAG_ARG_CONVERT)) + & (int) FMT_FLAG_ARG_CONVERT) + /* c_strlen will fail for a function parameter but succeed + for a literal or constant array. */ + && !c_strlen (argarray[info.format_num - 1], 1)) { tree c; for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); @@ -1242,8 +1251,9 @@ check_function_format (tree attrs, int nargs, tree *argarray) break; } if (args != 0) - warning (OPT_Wsuggest_attribute_format, "function might " - "be possible candidate for %qs format attribute", + warning (OPT_Wsuggest_attribute_format, "function %qD " + "might be a candidate for %qs format attribute", + current_function_decl, format_types[info.format_type].name); } } diff --git a/gcc/testsuite/gcc.dg/format/miss-7.c b/gcc/testsuite/gcc.dg/format/miss-7.c new file mode 100644 index 0000000..828b781 --- /dev/null +++ b/gcc/testsuite/gcc.dg/format/miss-7.c @@ -0,0 +1,36 @@ +/* PR77336 - -Wsuggest-attribute=format warning overly simplistic */ +/* { dg-do compile } */ +/* { dg-options "-Wsuggest-attribute=format" } */ + +#include "format.h" + +const char format[] = "%i"; + +void foo (char *d, unsigned n, va_list va) +{ + (void)&n; + + /* The following calls don't imply that the enclosing function is + a candiate for the format attribute because it uses a string + constant as the format. */ + vsnprintf (d, n, "%i", va); + + vsnprintf (d, n, format, va); + + /* In theory this should not trigger the warning either but GCC + doesn't treat the local static constant the same way as the + global and issues a false positive. + const char fmt[] = "%i"; + vsnprintf (d, n, fmt, va); + */ +} + +void bar (char *d, unsigned n, const char *f, va_list va) +{ + (void)&n; + + /* The following call suggests that the enclosing function might + be a candiate for the format attribute because it doesn't use + a string literal as the format. */ + vsnprintf (d, n, f, va); /* { dg-warning "function .bar. might be a candidate for .gnu_printf. format attribute" } */ +}