Visual Studio 2003 compiler bug in Managed C++ - false positive warning
I found a compiler bug at work yesterday while adding a large bitfield enum to
the .Net interop layer of a project. The main project is a set of native C++
DLLs built primarily with Visual Studio 2003. We have other targets but as the
lowest common denominator, everything has to work on the legacy compiler.
The .Net layer is a mixed assembly built with Managed C++ (now known
as /clr:oldSyntax
).
There is a large enum used as a bitfield in the data API of this project. Unfortunately it has grown to 46 distinct values, so an enum based on a 32-bit integer is no longer appropriate. Adding the new values and changing the underlying type of the enum to Int64 causes the compiler to complain:
[FlagsAttribute]
__value enum eLongChangedFlags : Int64
{
None = 0,
Foo = 1 << 0,
Bar = 1 << 1,
// ...
Scary = 1 << 44
// warning C4309: 'initializing' : truncation of constant value
};
This is counter-intuitive at first, but it is essentially saying that a large
number like 1 << 44
(17,592,186,044,416) is out of range of the possible
values that the underlying number type can represent. This is incorrect,
so we have to assume the compiler still thinks we are dealing with a 32-bit
integer or worse.
There wasn't a lot of information about this error on the internet but there
are a few related known bugs in the old compiler. Tellingly, compiling this
in Visual Studio 2005 did not give me the same warning. To verify if the
enum values have in fact been truncated, we need a test application. I found
some code on StackOverflow that suited my purpose and just debugged into
it to see what value Scary
ultimately represented. It was correct, not
truncated and not overflowing into negative figures. The compiler warning
is wrong.
To silence the warning I added a couple of pragmas to the original code:
#if _MSC_VER <= 1310
// Disable false positive warning on VS2003 compiler.
// The code has been verified to work, despite the scary warning.
// warning C4309: 'initializing' : truncation of constant value
#pragma warning(disable:4309)
#endif
[FlagsAttribute]
__value enum eLongChangedFlags : Int64
{
None = 0,
Foo = 1 << 0,
Bar = 1 << 1,
// ...
Scary = 1 << 44,
};
#if _MSC_VER <= 1310
// re-enable compiler warning in case of further issues elsewhere
#pragma warning(default:4309)
#endif