iangilham.com

By on

software bugs

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