MSVC C++20 and the /std:c++20 Switch - C++ Team Blog (original) (raw)

September 2nd, 2021

0 reactions

Daniel Griffing

Principal Engineering Manager

We are excited to announce that in Visual Studio 2019 version 16.11, we have added the /std:c++20 switch to the set of language mode switches available. The addition of this switch indicates that we’ve reached a point of sufficient stabilization of the MSVC C++20 feature set for it be used in production, with full support in VS servicing updates.

This blog post focuses on describing our level of C++20 feature support, compiler-supported extensions, and the remaining feature set differences between MSVC and the ISO C++ standard as of Visual Studio 2019 version 16.11 and Visual Studio 2022 version 17.0

C++ Language Modes and Compatibility Guarantees

First introduced in Visual Studio 2015, the MSVC compiler has included C++ language mode switches to indicate the targeted level of standard conformance and we now support three stable language modes: /std:c++14, /std:c++17, /std:c++20 (as of VS 2019 v16.11) and one preview mode (/std:c++latest).

The stable modes indicate that features under those modes are ready for production use and have ABI compatibility guarantees. The /std:c++latest mode contains ISO C++ features without strong guarantees for compatibility, allowing iteration based upon issues identified in testing, ISO C++ standard changes, and community feedback which may impact ABI stability of those features. Once stabilized, features under /std:c++latest will be moved under an applicable stable mode.

Language Mode Language Mode enables strict-conformance (/permissive-) ABI Stable Notes
/std:c++14 No Yes See **Note A
/std:c++17 No Yes See **Note A
/std:c++20 Yes Yes See **Note B
/std:c++latest Yes No See **Note B

** Note A: Strict conformance mode is opt-in via the /permissive- compiler switch

**Note B: Some functionality such as C++20 Modules require strict-conformance mode to be enabled due to strong dependency on ISO C++ semantic behaviors. Compatibility mode (/permissive) is supported as an opt-in switch with some C++20 functionality disabled.

C++20 Features added in VS 2019 v16.9 and later

Below is a summary of language and library C++20 features implemented since the last feature update.

A more detailed changelog is available for the STL on its GitHub repo including information on the awesome community contributors who have provided feature implementations and bug fixes to the STL

VS 2019 v16.9

C++20 Language Features

C++20 Library Features

VS 2019 v16.10 & v16.11

C++20 Language Features

C++20 Library Features

VS 2022 17.0 (still in Preview)

C++20 Language Features

C++20 Library DRs

ISO C++20 Continuing Work, Defect Reports, and Clarifications

As part of implementing C++20, there were some late discoveries which required changes to the ISO C++20 standard via the standard committee’s Defect Report (DR) process. This included Existing implementations (pre-DR) for these features are available under the /std:c++latest switch. We’re also tracking the DRs and are implementing those issue resolutions under /std:c++latest. Our plan is to make these capabilities available under the /std:c++20 switch after implementation of the full set of Standard Library DRs has completed. Progress on these features can be tracked on the MSVC STL GitHub site through its C++20 DRs project.

In the compiler, we are working with ISO C++ and other toolchain vendors to clarify expectations around allowing virtual functions to be constexpr (P1064R0). There are a couple of possibilities for implementation, which have significant ABI implications as to whether this is implemented via vtable entry. In the interim, we have implemented two modes, under /experimental:constevalVfuncVtable and /experimental:constevalVfuncNoVtable, which implement the most likely resolutions to this ambiguity. Once a decision is made on how to proceed, we’ll bring that capability under /std:c++20 and /std:c++latest.

Additionally, there were some feature areas that were unintentionally partially implemented. We are working to get those areas filled. For VS 2022 v17.0, we have implemented the requires-expression portion of the Concepts feature (P0734R0), which is scheduled to ship in VS 2022 v17.0. We’re also working to complete implementation of Core Issue 1581: “When are constexpr member functions defined?,” which is tracking towards inclusion in a VS 2022 update after v17.0.

MSVC Extensions and ABI

C++20 [[no_unique_address]]

Implementation of C++20 [[no_unique_address]] included a couple of additional challenges due to the ABI-breaking impact (changing object layout) of applying this optimization. This is problematic due to the MSVC compiler ignoring attributes that are not known, as allowed by the standard, resulting in scenarios where MSVC ABI compatibility guarantees would be broken for standard C++ code:

It was decided to hold-off on enabling the optimization for the [[no_unique_address]] attribute in the MSVC compiler until our next ABI breaking revision of the MSVC toolset, where it will be enabled across all language modes.

However, we do recognize that there are some customers who are in a position to take advantage of this optimization without worrying about linking binaries across versions of the MSVC toolset. For this audience, we have made this optimization available in VS 2019 v16.9 and later through an extension attribute that affects optimization across all compiler language modes, [[msvc::no_unique_address]].

#include

#if _MSC_VER >= 1929 // VS2019 v16.10 and later (_MSC_FULL_VER >= 192829913 for VS 2019 v16.9) // Works with /std:c++14 and /std:c++17, and performs optimization

#define NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]

#else

// no-op in MSVC v14x ABI #define NO_UNIQUE_ADDRESS /* [[no_unique_address]] */

#endif

struct Empty {};

struct A {     int a;     NO_UNIQUE_ADDRESS Empty b; };

int main() {     A inst{ 0 };

    // [[msvc::no_unique_address]] : sizeof(inst) == 4.     // [[no_unique_address]] : sizeof(inst) == 8.     std::cout << sizeof(inst) << "\n"; }

C++20 Coroutine support for C++14/C++17 (/await:strict)

The /await:strict option can be used in place of /await for C++20 compatible coroutine support in projects that build in C++14 or C++17 mode. In /await:strict mode library support is provided in <coroutine> and in the std namespace. For full clarity, this behavior is on-by-default under /std:c++20 without any /await* switch usage.

Strict mode disables language extensions present in /await that were not adopted into the C++20 standard. Use of such features with /await:strict will result in a compiler error. Strict mode also implements coroutine behaviors such as promise parameter preview that are not available under /await due to binary compatibility issues with older releases.

Note: coroutine state objects obtained from coroutine_handle<T>::address() are not compatible between /await and /await:strict modes. Using coroutine_handle<T>::from_address() on an address obtained from a coroutine handle created in an incompatible mode will result in undefined behavior.

More Information

For Visual Studio changes (beyond the C++ toolset) and download links, see the VS 2019 Release Notes and VS 2022 Preview Release Notes. You can report bugs through Developer Community, and you can also report STL bugs via microsoft/STL GitHub issues.