Announcing full support for a C/C++ conformant preprocessor in MSVC
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.
To reach conformance, a couple of additional features have been added to the preprocessor and MSVC compiler, including a variety of bug fixes,
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__ 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
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”)
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.
|/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.
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 (firstname.lastname@example.org). 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).