We made a number of improvements to C++ compiler warnings in Visual Studio 2015 Preview.
The printf family of functions
The community has made it clear that printf and its cousins are still heavily used and would benefit from more rigorous diagnostics when used. In Visual Studio 2015 Preview, the compiler will check that the number of arguments you provide to these functions match the number of arguments expected by the format string:
printf(“%d %dn”, 1); //C4317
printf(“%dn”, 1, 2); //C4422
The compiler will emit:
warning C4317: ‘printf’ : not enough arguments passed for format string
warning C4422: ‘printf’ : too many arguments passed for format string
Furthermore, specifiers that aren’t allowed to be used in some variants of printf will also emit warnings:
int n;
printf_s(“Test %n”, &n); //C4426
Here, printf_s is the security-enhanced version of printf, which disallows %n. The warning is:
warning C4426: ‘%n’ is not allowed in the format string of function ‘printf_s’
In Visual Studio 2015 RTW, we will add warnings that also check the types of the parameters passed to these functions.
Shadowed variables
A variable declaration “shadows” another if the enclosing scope already contains a variable with the same name. For example:
void f(int x)
{
int y;
{
char x; //C4457
char y; //C4456
}
}
The inner declaration of x shadows the parameter of function f, so the compiler will emit:
warning C4457: declaration of ‘x’ hides function parameter
The inner declaration of y shadows the declaration of y in the function scope, so the compiler will emit:
warning C4456: declaration of ‘y’ hides previous local declaration
Note that, as before, a variable declaration with the same name as a function parameter but not enclosed in an inner scope triggers an error instead:
void f(int x)
{
char x; //C2082
}
The compiler emits:
error C2082: redefinition of formal parameter ‘x’
Old code?
If you use /WX, these new warnings could cause some of your old projects to no longer build. To work around this, you can use #pragma warning or the /wd compiler option to disable them. Alternatively, a new compiler option has been added to allow you to control the set of warnings emitted by the compiler, in order to facilitate the compilation of code that you don’t wish to modify. To suppress warnings introduced after compiler version XX.YY.ZZZZ, use /Wv:XX.YY.ZZZZ. XX is the major version number of the compiler, which is 15 for Visual Studio 2008, 16 for Visual Studio 2010, 17 for Visual Studio 2012, and 18 for Visual Studio 2013.
However, for projects that are still in active development, we strongly encourage you to keep all new warnings enabled and fix the code instead, because they will likely help you write programs that are more robust and more secure.
Great news!
Is VS2015 going to offer something like GCC's format function attribute or kencc's varargck pragma? Based on this blog post, it looks like the checks are only done by the compiler for a fixed set of known functions (which is a good start!).
Does the compiler also check scanf family function calls? Especially their “secure” counterparts are often used wrong by beginners, because some specifiers require an additional argument of type unsigned int. If they aren't, is this planned for a future version?
This is indeed a good start but without some equivalent to gcc "__attribute__ ((__format__ (__printf__, m, n)))" it's not going to be nearly as useful as it could be, I hope this is in the plans as well!
Very good. Now, not only we will fight with the evil inside printf(). It's everywhere: http://www.viva64.com/…/V576 . There are so many mistakes.
Another question: Will the compiler be able to distinguish between the legacy VC and ISO C format specifiers (which are available in VS2015, too) in wide char functions? That seems a bit harder to implement.
wprintf(L"%sn", L"hello world!"); // legacy VC
wprintf(L"%lsn", L"hello world!"); // ISO C (as %s is for char*)
I would also like to know if it is effective on the family of printf functions, especially the variadic forms.
Do these warnings replace the specific code analysis warnings? Do we now two parts that check for these issues. Wouldn't it make sense to remove the code analysis warnings now (maybe this improves code analysis performance)?
Glad to hear about these warnings. I have a few other suggestions for warnings (probably disabled by default) that would be very useful in cleaning up old code:
1) Conversion of literal 0 to a pointer type (nullptr should be used here).
2) C-style cast used in C++ code.
3) Virtual function could be declared 'override'.
4) Function could be declared 'noexcept'. (Triggered if a function throws no exceptions, and calls only 'noexcept' functions.
5) Variable could be declared 'const'. (Triggered if a stack variable is never modified after its declaration).
6) Parameter could be declared 'const'. (The same for parameters, unless the function is overriding a base class virtual).
7) Function could be declared 'const'. (The same for *this, unless the function is overriding a base class virtual).
It might also be nice to have a warning that identified likely candidates for 'constexpr'.
@S. Colcord, thanks for the suggestions! Email me if you are open to be contacted for follow up, ebattali@microsoft.com
@C.
Yes, currently the compiler does only check a small set of known functions, but this will change. We will implement scanf checking for RTM, and when we add actual type checking for format strings, we will make sure that the difference between legacy VC and ISO C formats is handled correctly. We will also consider implementing some of these other suggestions, such as the format function attribute.
@Vertex
We have not modified the static analyzer's behaviors w.r.t. printf, so these new warnings do currently overlap. We have no immediate plans to address this.
@Kangyuan Niu:
"We have not modified the static analyzer's behaviors w.r.t. printf": What's the impact of that for %s vs %S?
@Eric Battalio: If you're taking suggestions on warnings, something akin to -Wdelete-non-virtual-dtor <gcc.gnu.org/…/VerboseDiagnostics would be grand. The existing almost-equivalent opt-in warning of C4265 is becoming increasingly useless. (<thread> doesn't compile cleanly with it, and <functional> started not compiling cleanly with it in CTP4.)
Reply to S. Colcord
> 2) C-style cast used in C++ code.
You can use this diagnostic: http://www.viva64.com/…/0201
> 6) Parameter could be declared 'const'.
Partly: http://www.viva64.com/…/0298
Glad to see the many improved warnings. By "the community", I bet you mean Bruce Dawson.
I chuckled when I saw Andrey mentioning PVS-Studio.
(and yes, , cppcat is on my christmas list)
The new warnings are really great! Not only the two mentioned here, but also the one about implicitly noexcept destructors throwing exceptions and the one about a deprecated langugage feature I did't even know about that Crypto++ uses. Thanks for not only caring about new language features, but also about code quality!