Update June 8, 2021: The C11 and C17 announcement post has instructions on how to get the latest Windows SDK that works with the conformant preprocessor.
We are excited to announce full support for a conformant preprocessor in the MSVC toolset starting with Visual Studio 2019 version 16.6 Preview 2.
Since the original blog post announcing preprocessor conformance changes, we’ve come a long way and are now ready to announce the completion of the C/C++ conformant preprocessor and its move to a non-experimental, fully supported state via the /Zc:preprocessor
switch. Alongside standard conformance, the preprocessor also supports C++20’s __VA_OPT__
and is also available in the C language mode.
What’s new:
To reach conformance, a couple of additional features have been added to the preprocessor and MSVC compiler, including a variety of bug fixes, __VA_OPT__
, and _Pragma
support.
Bugfixes involving various parts of the preprocessor, from parameter expansion and special macro names like __FUNCSIG__ to reporting arity errors and line number fixes. Special thanks to Edward Diener for providing a lot of valuable feedback!
__VA_OPT__
__VA_OPT__
is a new feature of variadic macros in C++20. It lets you optionally insert tokens depending on if a variadic macro is invoked with additional arguments. An example usage is comma elision in a standardized manner.
#define M(X, …) X __VA_OPT__(,) __VA_ARGS__ M(3) // expands to 3 M(3, 4) // expands to 3, 4
_Pragma
The _Pragma operator has been one of the long-standing deficiencies of the preprocessor, and a blocker in being standard conformant in C++ and C99. Though MSVC had the non-conformant __pragma, the semantics differ in that _Pragma takes a string literal as its parameter instead of a series of preprocessor tokens. This feature is now implemented.
_Pragma(“once”) #define GUARD _Pragma(“once”)
Miscellaneous
There were some contextual keyword changes relating to modules. These changes unblock further C++20 modules work.
Preprocessor-only output (via /E and /P) is now prettier, reducing the amount of line directives and fixing some formatting issues.
Enabling the conformant preprocessor in your environment
All that is needed to use the conformant preprocessor is to add /Zc:preprocessor
to your compilation flags. The flag is available in C and C++ language modes. It works with any language level, but we plan to enable it for /std:c++latest
in a future release.
Language mode | /Zc:preprocessor |
/std:c++14 | Not implied |
/std:c++17 | Not implied |
/std:c++latest | Implied in a future update (Not implied in VS 2019 v16.6) |
The conformant preprocessor can be tested by checking if the macro _MSVC_TRADITIONAL
is defined and set to 0.
#if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // old behavior #else // new behavior #endif
The legacy preprocessor is not going anywhere, it will continue to serve as a compatibility layer for old code, but it will only be serviced with the intention of keeping old code working. Additionally, the /experimental:preprocessor
switch is still available and will activate /Zc:preprocessor
in VS 2019 v16.6 but will be removed in a future release. Any projects that have been configured to use the experimental switch should migrate to the supported version.
What’s next:
Improved diagnostics are in the works, which will provide a better expansion context for macro invocation and errors.
This feature is not currently implied by any other flags, but we are planning to include it in /std:c++latest once we stabilize the public SDK headers from using non-conformant macros. Using the latest Windows SDK is advised, as many of the noisy warnings are fixed in later SDK versions.
Call to Action
Let us know how the conformant preprocessor works for you! Get it in Visual Studio 2019 version 16.6 Preview 2 (please see https://visualstudio.microsoft.com/vs/preview/ for download links) and try it out.
As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC).
Can the latest public Windows SDK headers compile with this new preprocessor?
Not at the moment, but we are working on improving this scenario and updating the SDK.
With /Wv:18 SDK headers compile.
But WDK headers are not.
There Are only few macros affected in the WDK headers.
Is it possible to fix them in the upcoming 20H1 WDK release ?
If it can speed up, I can submit a patch 😉