Announcing full support for a C/C++ conformant preprocessor in MSVC

Elnar Dakeshov

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).

20 comments

Discussion is closed. Login to edit/delete existing comments.

  • shbouwhuis@gmail.com 0

    I’ve been looking for the state of C++20 support in Visual Studio 2019, but can’t seem to find a page with what is and what isn’t implemented yet.
    Is it language-wise feature complete? Is STL feature complete? Is it production ready? Is it in alpha state?

    Could you please inform us of the progress? I saw the Visual Studio roadmap, but couldn’t get a clear picture.

    • Me Gusta 0

      While my comment with direct links is awaiting moderation, if you go to the cppreference website, you should find a page there named C++ compiler support.

      • shbouwhuis@gmail.com 0

        I know that page, but I thought that page was always fairly far behind (old information). But I think that page together with the one Laurent Lessieux suggested will give me a good idea.
        Thanks!

        • Me Gusta 0

          That page is very up to date. It has everything up to the current preview.
          To give an idea, the numbers in the VC column refers to the compiler toolset version. You can get this from running cl.exe on the command line. As an example, the current release version gives:

          Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28612 for x64

          So the current release is 19.25. The current preview is 19.26. If you look through the VC column you will find features listed with 19.25 and 19.26, and if you look for the C99 preprocessor under the C++11 features then you will see that it is marked as fully implemented as of version 19.26.
          Heck, it even has a couple of 19.27 library features listed, and that version isn’t even in preview yet. They are probably getting that by monitoring the STL repository on GitHub.
          So it is quite accurate.

    • laurent lessieux 0

      Are you looking for something like that?

      Visual Studio C++ Conformance
      It is the best I could find. Very interesting to see the progress being done and realizing how much is left. I can’t wait to get the final C++20 support.

      • shbouwhuis@gmail.com 0

        Yesss, that page is actually pretty good! I searched on the Microsoft site instead of Github.
        Thanks for the info!

  • Alastair Taylor 0

    #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL
    // new behavior
    #else
    // old behavior
    #endif

    Is that correct? As https://devblogs.microsoft.com/cppblog/msvc-preprocessor-progress-towards-conformance/ has it as

    #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL
    // Logic using the traditional preprocessor
    #else
    // Logic using cross-platform compatible preprocessor
    #endif

    • Elnar DakeshovMicrosoft employee 0

      Fixed, thanks Alastair.

  • Rick de Water 0

    “but we plan to enable it explicitly for /std:c++latest in a future release.”

    Don’t you mean implicitly?

    • Elnar DakeshovMicrosoft employee 0

      We mean that /Zc:preprocessor will be implied by /std:c++latest in a future release. Updated to clear up wording, thanks!

  • Paul Topping 0

    One of the things I have always wanted is a way to generate the preprocessed intermediate file (.i) for a given .cpp with just a menu command. This would be very handy for looking into the occasional macro blunder. I’ll admit that I haven’t looked for it in years but, AFAIK, we still have to change the project to do this via compiler arguments and then change it back afterwards. It’s not super hard but it also can’t be hard to just provide a Preprocess Only menu command to produce the file without changing the project.

    • Paul Topping 0

      I looked again, expecting a Preprocess command within the Build category of commands but no such luck. In my configuration, I would put it right next to Compile in the Build menu.

        • Alexander Sklar 1

          +100 to Paul’s point. It is frankly inconceivable that there isn’t a straightforward way to preprocess a cpp file from the UI without having to build your own msbuild task or some other way in order to pass the preprocess to file flag

    • shbouwhuis@gmail.com 0

      The bigger problem is that changing the project settings means that EVERYTHING has to be recompiled again. So, a very base project in your project chain potentially means hours of wasted time.

  • Victor Derks 0

    Enabling this option generates:
    CppUnitTest.h(120,114): warning C5104: found ‘L#methodName’ in macro replacement list,

    for the Visual Studio C++ unit test headers that are shipped with Visual Studio 2019 16.6. Preview 2.0
    It seems that using the new preprocessor is not possible for VC++ unit test projects as TEST_METHOD macro cannot be expanded correctly.

  • e4lam 0

    Can the latest public Windows SDK headers compile with this new preprocessor?

    • Elnar DakeshovMicrosoft employee 0

      Not at the moment, but we are working on improving this scenario and updating the SDK.

      • NN 0

        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 😉

Feedback usabilla icon