C++ Language Updates in MSVC Build Tools v14.50
It has been some time since we have provided an update on MSVC progress, and this one comes with the latest major update to our IDE: Visual Studio 2026 version 18.0. This version of Visual Studio ships with the MSVC Build Tools version 14.50, which includes version 19.50 of the MSVC compiler. You can try out the improvements by downloading the Insiders release. Also, if you want to track updates in the Standard Library, check out the STL Changelog, which is regularly updated. Let’s jump right into the updates!
C++23 Features
As C++ standards progress in MSVC, you can follow along using the cppreference compiler support table and help us identify what we should be working on next!
- P0849R8 (auto(x): decay-copy in the language)
// Prior to P0849R8:
void pop_front_alike(auto& x) {
using T = std::decay_t<decltype(x.front())>;
std::erase(x, T(x.front()));
}
// After P0849R8:
void pop_front_alike(auto& x) {
std::erase(x, auto(x.front()));
}
- P2437R1 Implement C++23
#warning
// Valid prior to C++23.
#error bad configuration...
// Valid after C++23.
#warning configuration deprecated...
- CWG Issue 2586 (Explicit object parameter for assignment and comparison)
struct S {
S& operator=(this S&, const S&) = default; // Valid after CWG2586.
auto operator<=>(this const S&, const S&) = default; // Valid after CWG2586.
};
- P2280R4, allowing references to unknown values during constant evaluation
template <typename T, size_t N>
constexpr size_t array_size(T (&)[N]) {
return N;
}
void check(int const (¶m)[3]) {
constexpr auto s2 = array_size(param); // Previously ill-formed, now accepted as a constant expression after P2280R4.
}
Smaller Conformance Updates
-
- CWG2635 – Constrained structured bindings.
- CWG2465 (Coroutine parameters passed to a promise constructor)
- P2360R0 which extends the definition of an init-statement to allow an alias-declaration
- CWG2496 – ref-qualifiers and virtual overriding.
- CWG2506: Structured bindings and array cv-qualifiers.
- CWG2507 (default arguments for operator[]).
- CWG2585: No change required to behavior.
- P2290R3 C++23 Hex/oct delimited escape sequence support in string literals.
- CWG2521 which deprecates ‘operator string-literal identifier’.
- CWG2528 which relaxes conversion rules for the spaceship operator.
- P2797R0: Proposed resolution for CWG2692 Static and explicit object member functions with the same parameter-type-lists.
- P2266R3 Simpler implicit move.
- Implement a warning to notify of the enum type change caused by /Zc:enumTypes.
Compiler Improvements in v14.50
C++/CLI
- Fix ICE on use of ‘auto’ in member declarations in C++/CLI managed types
- Fix crash in compiler in C++/CLI code using ref-types on stack
- Visual Studio 17.12 introduced multiple errors while building managed C++ code in an MFC application
Diagnostics
- Fix an incorrect diagnostic about implicit enum type conversions in C even when the code explicitly converts the expression
constexpr
- Fixes several errors involving virtual function calls at compile-time.
- MSVC erroneously claims the return value of a virtual constexpr function-call operator is not a constant expression
- C++20 constexpr virtual polymorphism is broken in MSVC but works in ClangCL and intellisense
- Virtual constexpr function did not evaluate to a constant
- Unable to use virtual function in constexpr expression
- constexpr should reject overflow from addition and left shifting of constants
- Fix scenarios where constructors should be made implicitly constexpr
- Fixes scenario when initializing a constexpr variable with a consteval call
- Fix an issue with constexpr static data members and the CRTP.
- Fixes a bug related to evaluating destructors of constant objects too early; objects appeared at runtime to be in their destroyed state.
- Fix an issue with constexpr lambda captures and guaranteed copy elision with a compiler generated call to memset.
- Allow consteval constructor calls as argument of direct-initialization.
- Fixed an issue where calling certain
consteval
functions in anif consteval
would sometimes produce a compiler error. - Allow constexpr references to be initialized with derived class rvalue.
- wrong code bug in constexpr evaluation
C++ Modules
- Fix bug with importing friend declaration where the class-head-name was in a particular qualified-id form, encountered in nlohmann/json library.
- Fix compiler crash when using-declarations are used from a specialization inside a module.
- Fix an issue that std::expected can’t be specialized in some cases when imported from a module.
- Fixed an issue where functions using types from a named module would sometimes not execute properly or cause linker failures.
- Fix issue when importing a constexpr function with static local variables
- Fixed an issue where the compiler would sometimes not respect a
#pragma warning(disable:...)
when the pragma appeared in a module or header unit. - Fixed various issues preventing Unreal Engine 5 from building with header units.
- C++ modules compiler error: Base class undefined
- C++20 modules + boost::asio still being weird
- C++20 modules: specialzations in the global module fragment are discarded even if they are decl-rechable
Conformance
- Add support for ‘[[maybe_unused]]’ on labels and fix an issue where warning C4102 (unreferenced label) was being emitted when the only reference was from a discarded branch of an if-constexpr statement.
- Diagnose ill-formed friend explicit specializations that were incorrectly accepted in C++20 or later.
- Fix an issue with the compiler allowing specifiers (other than type-specifiers) as part of a type-id
- Add a switch, ‘/Zc:enumEncoding’, to correctly encode the use of an enumeration as a non-type template parameter.
- Fix an issue in which the compiler did not issue a diagnostic if a user did not prepend a dependent template-id with the ‘template’ keyword.
- Fix an issue with the compiler allowing specifiers (other than type-specifiers) as part of a type-id
Reliability
- Fix an ICE when explicitly instantiating a class template which has friend functions.
- Fix an ICE involving explicit variable template instantiations when PCH files are used.
- Fix a compiler crash involving deep nesting of aggregates, non-aggregates, and initializer lists
- Fix an issue with nested generic lambdas and an issue with using ‘template’ in a qualified-id
- Fixes internal compiler error when elaborating a struct with the same name as overloaded member functions
- Fixed a logic error that caused an exponential growth in memory usage during type deduction if a class type had a lot of base classes
- Fix an issue with the IL we generate for a temporary that it bound to a non-static data member of reference type.
- Fix a compiler ICE when the nested lambda inside a generic lambda references a qualified name.
- Fixed an ICE after error when the compiler saw an
if constexpr
with empty condition. - Fix a compiler crash associated with initializing a bit field.
- Fix an issue with the compiler complaining about an ill-formed pure-specifier within a function template
- Fix a compiler ICE when the nested lambda inside a generic lambda references a captured variable.
- Fix crash when comma missing between designated initializers
- Fixes a compiler crash with initialization of aggregates involving commas and initializer lists.
- Fix an issue with lambdas and non-type template parameters whose type is a pointer-to-member.
- Correct bad code generation for certain templated conversion operators
- Fix an internal compiler error during initialization of nested aggregates with initializer lists
- ICE when trying to access not captured pointer in lambda
- fatal error C1001: Internal compiler error.
Correctness
- Fix an issue with exception handling and unions; and an issue with the handling of an rvalue reference in the context of a lambda.
- Fix an issue when explicit instantiation sometimes picks the wrong overload which has a requires clause.
- Correct some semantic issues with noexcept specifiers and compile errors for some noexcept specifiers on member functions.
- Fix an issue with phase-1 name binding in a non-static data member initializer
- Fix an incorrect value category for expressions involving indirections and arrays.
- Fix a syntax error when parsing certain template-ids in alias declarations inside some templates.
- Fix an issue with partial ordering and template parameter objects
- Fix a bad error C2355 on ‘this’ in a local class declaration.
- Fix an issue with the re-declaration of constexpr variables and an issue with parsing a bit-field width within a partial specialization of a class template.
- Fix an issue causing __declspec(no_sanitize_address) to be ignored on lambdas and forward-declared functions.
- Fix incorrect point of instantiation when an inline static data member has a class template specialization type.
- Fix an issue when a static operator() was also an abbreviated function template.
- Fix an issue with no_unique_address and class types with common subobjects.
- [[[msvc::no_unique_address]] incorrectly optimizes mixed structs with leading nested empty struct](https://developercommunity.visualstudio.com/t/msvc::no_unique_address-fails-to-opt/10892814)
- Fix an issue with template template parameters and default template arguments
- Fix incorrect resolution of a name referring to the enclosing class template.
- Fix an issue causing error C2106 on certain member-access expressions that should be lvalues.
- Fixed an issue where
decltype
would sometimes return the wrong type when used with ternary expressions. - Fix 1) an issue with C++23 multi-dimensional array indexing; 2) an issue with allowing ‘[[maybe_unused]]’ on a label; and 3) an issue with the compiler being too eager to instantiate a specialization of a function template.
- Fix an issue with C4100 (unreferenced parameter) and abbreviated function template; and an issue with a missing warning for using a comma operator in subscript expression
- Fix spurious unreferenced variable warning for OpenMP private loop variable.
- Fix issues with ‘std::bit_cast’, integral non-type template parameters and instantiation of variable templates.
- Fix spurious warning C4193 when compiling some preprocessed files
- Fix a missing error when aggregate initialization is incorrectly used during class template argument deduction.
- Fix determination of value category for certain kinds of expressions involving a sub-expression that is a conditional expression.
- Fix an issue with an elaborated class-specifier in a template argument list
- Fix an issue with operator binding and an issue with binding local class types.
- Fix a couple of issue related to using enum declarations.
- MSVC does not compile a function type with multiple parentheses
- Defining class method outside the class, with concept
- Variable Declaration Allowed Inside Switch Case Without Scoping Operator
- No warning C4706 for assignment to std::unqiue_ptr used as a condition
- VS 17.14. “if constexpr (requires ” doesn’t work correctly
- Incorrect overload resolution for static operator()
- Lvalue-to-rvalue conversion rules for std::nullptr_t are violated
- Error message depends on unused parameter pack
- In-class initialization of pointer-to-member + virtual function make MSVC to compile incorrectly
- MSVC Compiler Bug: requires Constraint Fails to Remove Non-Matching Template Candidates, Leading to Compilation Error
- Regression: c++ compilation failure in code generated by Qt’s meta object compiler
- Rejects valid pack expansion in base specifier in lambda body
Correctness (C compiler)
- In C23, don’t decay functions to function pointers when used as an argument to
typeof
Closing
As always, we welcome your feedback. Feel free to send any comments through e-mail at visualcpp@microsoft.com, through Twitter @visualc, or through BlueSky @msftcpp.bsky.social. Also, feel free to follow Cameron DaCamara on Twitter @starfreakclone.
If you encounter other problems with MSVC in Visual Studio 2026 please let us know via the Report a Problem option, either from the installer or the Visual Studio IDE itself. For suggestions or bug reports, let us know through Developer Community.
Is there a way to benefit from v145 toolset with cmake?
It seems only v143 is visible to cmake (latest cmake version 4.1.1).
Thanks
i’m on cmake 4.0.2 and it recognized the v145 toolset just fine, in fact the same codebase that couldn’t compile on v143, compiled successfully on v145, the compiler was choking on type ids across modules where it yields an internal compiler error.