Re: No sscanf Expected Type Warnings When Used Through A Template

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux