Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-Werror=format: how can the compiler know

I wrote this intentionally wrong code

printf("%d %d", 1);

compiling with g++ and -Werror=format.

The compiler gives this very impressive warning:

error: format '%d' expects a matching 'int' argument [-Werror=format]

As far as I can see, there's no way the compiler can tell that the code is wrong, because the format string isn't parsed until runtime.

My question: does the compiler have a special feature that kicks in for printf and similar libc functions, or is this a feature I could use for my own functions? String literals?

like image 589
XPlatformer Avatar asked Dec 06 '13 13:12

XPlatformer


2 Answers

As far as I can see, there's no way the compiler can tell that the code is wrong, because the format string isn't parsed until runtime.

As long as the format string is a string literal, it can be parsed at compile time. If it isn't (which is usually a bad idea anyway), then you can get a warning about that from -Wformat-security.

does the compiler have a special feature that kicks in for printf and similar libc functions?

Yes.

or is this a feature I could use for my own functions?

Yes, as long as you're using the same style of format string as printf (or various other standard functions like scanf or strftime).

void my_printf(Something, char const * format, SomethingElse, ...)
    __attribute__ ((format (printf,2,4)));

to indicate that the second argument is a printf-style format string, and the values to format begin with the fourth. See http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html.

like image 172
Mike Seymour Avatar answered Oct 07 '22 04:10

Mike Seymour


Well, printf definitely parses the format string at runtime in order to do its job. But nowhere is it written that the compiler may not choose to parse it itself if it wants to.

The documentation for -Wformat says that this is exactly what happens:

-Wformat

-Wformat=n

Check calls to printf and scanf, etc., to make sure that the arguments supplied have > types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see Function Attributes), in the printf, scanf, strftime and strfmon (an X/Open extension, not in the C standard) families (or other target-specific families). Which functions are checked without format attributes having been specified depends on the standard version selected, and such checks of functions without the attribute specified are disabled by -ffreestanding or -fno-builtin.

The formats are checked against the format features supported by GNU libc version 2.2. These include all ISO C90 and C99 features, as well as features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations may not support all these features; GCC does not support warning about features that go beyond a particular library's limitations. However, if -Wpedantic is used with -Wformat, warnings are given about format features not in the selected standard version (but not for strfmon formats, since those are not in any version of the C standard). See Options Controlling C Dialect.

Update: Turns out you can use it on your own functions. Mike has the details.

like image 31
Jon Avatar answered Oct 07 '22 04:10

Jon