Thank you that is a helpful pointer to get me on my way. > You should be able to solve the problem by adding > __attribute__((format(scanf, blah blah))) to your template function, > which tells the compiler it requires a string literal that meets the > scanf format rules. Then calls to your own sccanf wrapper can be > checked (assuming you pass a string literal to the wrapper). I don't think I can use the format attribute on a variadic function template. When I try to do so I get an error stating: sscanf_template_warnings_example_with__attribute__.cpp:12:6: error: args to be formatted is not ‘...’ bool the_message_scanner(const char *message, const char *format, Ts const&...ts) I do not see that limitation mentioned in the document you have pointed to so perhaps I am just trying to use the system incorrectly. The limitation was mentioned on http://zverovich.net/2015/04/22/compile-time-checking-of-printf-args-in-cppformat.html which provides some helpful suggestions about using a macro in some cases. The best I could come up with so far is the following: #include <stdarg.h> #include <stdio.h> bool message_scanner(const char *message, const char *format, ...) __attribute__((format(__scanf__,2,3))); // Cannot use __attribute__ format on variadic function templates //template<class...Ts> //bool the_message_scanner(const char *message, const char *format, Ts const&...ts) // __attribute__((format(__scanf__,2,3))); template<class...Ts> bool the_message_scanner(const char *message, const char *format, Ts const&...ts) { size_t num_scanned(sscanf(message, format, ts...)); bool got_them_all(num_scanned == sizeof...(ts)); return got_them_all; } bool message_scanner(const char *message, const char *format, ...) { va_list args; bool state(false); va_start(args,format); state = the_message_scanner(message, format, args); va_end(args); return state; } int main () { bool correct(false); short int anInt(0); char aChar('c'); float aFloat(0.0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wwrite-strings" char* message = "EXAMPLE001:01,02"; #pragma GCC diagnostic pop // Warnings are given about expected argument types if(message_scanner(message, "<EXAMPLE%x:%x,%i", &anInt, &aChar, &aFloat)) { correct = true; } // Warnings are given about expected argument types if(2==sscanf(message, "<EXAMPLE%x:%x,%i", &anInt, &aChar, &aFloat)) { correct = true; } return correct?0:1; } The indirection through a function that uses __VA_ARGS__ seems a little inelegant but it is possible this is the best that can be done when mashing together some C and C++ behaviour. I would have liked to use something like stringstrem but there isn't any steam support on my target system. If anyone else has any other comments or suggestions about the code I have come up with I would be grateful to hear them. I am pleased to have an alternative to commenting in and out sscanf equivalent lines. -- Thomas Thorne <tafthorne@xxxxxxxxxxxxxx> -----Original Message----- From: Jonathan Wakely <jwakely.gcc@xxxxxxxxx> To: TafThorne@xxxxxxxxxxxxxx CC: gcc-help <gcc-help@xxxxxxxxxxx> Subject: Re: No sscanf Expected Type Warnings When Used Through A Template Date: Fri, 13 Nov 2015 09:59:08 +0000 On 13 November 2015 at 09:31, Thomas Thorne <tafthorne@xxxxxxxxx> wrote: > Good Morning, > > I have come across something that I feel a shortcoming in the warnings > that gcc issues when compiling some C++ code. Calling it a bug seems a > bit harsh so I thought I would ask this mailing list of their opinion > before raising an issue. When I use a template to perform some sscanf > work on a string I loose some of the -Wformat warnings about the > expected argument types. > > Here is a set of C++ code that demonstrates the warnings occurring for > sscanf and not happening for the template. This has nothing to do with templates, you get exactly the same behaviour (i.e. no warnings) if you replace the function template with: bool message_scanner(const char *message, const char *format, short int* i, char* c, float* f) { size_t num_scanned(sscanf(message,format,i, c, f)); bool got_them_all(num_scanned == 3); return got_them_all; } The problem is simply that the compiler can't check the call to sscanf unless the first argument is a string literal. You should be able to solve the problem by adding __attribute__((format(scanf, blah blah))) to your template function, which tells the compiler it requires a string literal that meets the scanf format rules. Then calls to your own sccanf wrapper can be checked (assuming you pass a string literal to the wrapper). The format attribute is documented at https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
Attachment:
signature.asc
Description: This is a digitally signed message part