Windows.h clobbers public regulated data types generated code

While working on a project using nnvg, I discovered that my code built perfectly with GCC, but would fail to build with MSVC. The error was in the generated header file for Given the following struct declaration:

typedef struct
    /// saturated float32 pascal
    float pascal;  /* Line 86 */
} uavcan_si_unit_pressure_Scalar_1_0;

MSVC was reporting a syntax error at the declaration of float pascal (followed by about a million more errors):

....\out\uavcan\si\unit\pressure\Scalar_1_0.h(86): error C2059: syntax error: ';'

I was quite puzzled by this for several hours. After much digging, I found that some of my code was including Windows.h before including all the generated headers. It turns out that minwindef.h, which is included by Windows.h, contains the following:

#if (!defined(_MAC)) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
#define pascal __stdcall
#define pascal

Thus, after the preprocessor stage, the declaration was changed from float pascal; to float __stdcall;, which does indeed result in invalid syntax at the semicolon. Naturally, this was trivially fixed by adding #undef pascal after including Windows.h. However, since this include was in code which I cannot modify, I instead resorted to copying the default C templates for nnvg and adding #undef pascal to base.j2.

As I could find almost no evidence online that this pascal macro existed in the first place, and furthermore, I could find no evidence that anyone had run into this with nunavut before, I thought it best to make this post for future readers who may encounter the same headache I did.

My environment:

  • Windows 10
  • Visual Studio 2022 (Professional)
  • MSVC version 19.34.31937.0
  • Windows 10 SDK version 10.0.22621.0

Nice find. I’ve opened `pascal` is a keyword on Windows · Issue #318 · OpenCyphal/nunavut · GitHub to track a fix for this.