The other day I upgraded my Windows build environment from MSVC2013 to MSVC2017, and lo and behold, a function in my program that had been working fine for years (and still works fine under g++/clang) suddenly started giving incorrect results when compiled with MSVC2017.
I was able to rewrite the function to give correct results again, but the experience made me curious -- was my function invoking undefined behavior (that just happened to give correct results until now), or was the code well-defined and MSVC2017 was being buggy?
Below is a trivial program showing a toy version of the function both before and after I rewrote it. In particular, does the function maybe_invokes_undefined_behavior(), as shown below, invoke undefined behavior, when called with an argument of value -32762?
#include <stdio.h>
enum {ciFirstToken = -32768};
// This function sometimes gives unexpected results under MSVC2017
void maybe_invokes_undefined_behavior(short token)
{
if (token >= 0) return;
token -= ciFirstToken; // does this invoke undefined behavior if (token==-32762) and (ciFirstToken==-32768)?
if (token == 6)
{
printf("Token is 6, as expected (unexpected behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token); // under MSVC2017 this prints -65530 !?
}
}
// This function is rewritten to use int-math instead of short-math and always gives the expected result
void allgood(short token16)
{
if (token16 >= 0) return;
int token = token16;
token -= ciFirstToken;
if (token == 6)
{
printf("Token is 6, as expected (odd behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token);
}
}
int main(int, char **)
{
maybe_invokes_undefined_behavior(-32762);
allgood(-32762);
return 0;
}