STL Fixes In VS 2015 Update 3

August 12th, 2016

VS 2015 Update 3 was released over a month ago. While its release notes mentioned some STL fixes, here’s a comprehensive list.

(Previous changelogs: RTM Part 1, RTM Part 2, Update 1, Update 2 features, and Update 2 fixes.)

STL Features

/std:c++latest enables the following new features: P0025R1 “clamp()”, P0185R1 “is_swappable, is_nothrow_swappable”, and P0272R1 “Non-const basic_string::data()”.

/std:c++latest also controls the removal of the following old features: N4190 “Removing auto_ptr, random_shuffle(), And Old <functional> Stuff”, P0004R1 “Removing Deprecated Iostreams Aliases”, LWG 2385 “function::assign allocator argument doesn’t make sense”, and various non-Standard features (the std::tr1 namespace, some TR1-only machinery, and the std::identity struct).

The compiler options /std:c++14 and /std:c++latest are newly available in Update 3.

/std:c++14 (which is the default) defines _MSVC_LANG to 201402 and says, “enable C++14 features as they become available, and enable the set of C++17 features that shipped in Update 2”. (This is intentionally different from Clang and GCC’s -std=c++14 mode.)

/std:c++latest defines _MSVC_LANG > 201402 (the exact value is subject to change) and says, “enable all features as they become available, including feature removals; I love conforming to the latest Working Paper and I am willing to accept arbitrary source breaking changes”.

Because our STL implementation supports three-and-a-half compilers (C1XX, Clang, EDG-imitating-C1XX, and EDG-imitating-Clang), we have a separate macro to control the STL’s mode. We inspect _MSVC_LANG if it’s defined, otherwise we inspect __cplusplus. (C1XX will not update __cplusplus’s value until it has implemented all C++11 features.) Then the STL defines _HAS_CXX17 to 0 or 1, and this is used to control the behavior of our headers. We will support overriding this macro, but only in one direction. /std:c++latest /D_HAS_CXX17=0 is an acceptable request for new compiler behavior, but old STL behavior. However, /std:c++14 /D_HAS_CXX17=1 is unacceptable (requesting old compiler behavior, but new STL behavior) – we aren’t attempting to block this and it’ll work for the time being, but it can and probably will stop working at some point in the future (whenever a new STL feature needs to take a dependency on a new compiler feature).

In general, LWG issue resolutions will be implemented unconditionally, and will not be controlled by _HAS_CXX17.

Finally, while we don’t support fine-grained control of C++17 STL features, we have separate macros for the feature removals. They are _HAS_AUTO_PTR_ETC, _HAS_OLD_IOSTREAMS_MEMBERS, _HAS_FUNCTION_ASSIGN, _HAS_TR1_NAMESPACE, and _HAS_IDENTITY_STRUCT. They’re defined to 0 or 1 depending on the value of _HAS_CXX17, but they can be overridden (and we support all combinations).

LWG Issues

We implemented C++14’s LWG 2064 “More noexcept issues in basic_string”.

We also implemented C++17’s LWG 2296 “std::addressof should be constexpr”, LWG 2596 “vector::data() should use addressof”, and LWG 2688 “clamp misses preconditions and has extraneous condition on result”.

STL Fixes

In Update 2, we removed metaprogramming in an internal _Destroy_range() helper. This metaprogramming was unnecessary in release mode, but its removal significantly impacted debug mode performance (VSO#213185, VSO#218398/Connect#2661660, VSO#219797/Connect#2683478). In Update 3, we’ve fixed this regression by restoring and improving the metaprogramming. Unlike the pre-Update 2 metaprogramming, the new metaprogramming calls a user-defined allocator’s destroy() if it is present. User-defined allocators may need to use the C++11 minimal allocator interface in order to restore pre-Update 2 debug performance, typically by removing construct() and destroy() member functions.

Improved performance by generalizing a metaprogramming optimization to apply to user-defined allocators, not just std::allocator (VSO#189231). This optimization is activated when construct() and destroy() aren’t provided by the user-defined allocator.

Fixed silent bad codegen in atomic<int64_t>/atomic<uint64_t> on x86 (VSO#212461).

The STL now avoids using thread-safe “magic statics” except when absolutely necessary, improving codegen.

tuple’s perfect forwarding constructor now avoids out-competing the copy constructor, fixing compiler errors in certain scenarios (VSO#215996/Connect#2632801, VSO#216014/Connect#2633029).

Improved performance of std::equal and std::lexicographical_compare by dispatching to memcmp and memchr more aggressively, resulting in large performance improvements in some scenarios; e.g. equal(char*,char*,char*, char*) on 64-bit platforms (VSO#180464).

Improved performance of debug builds significantly by reducing the number of bookkeeping function calls in our iterator debugging machinery.

Improved performance of string::push_back another 40% vs. Update 2 in release builds, with more substantial improvements in debug builds.

Improved performance of debug builds across all standard algorithms by eliminating several kinds of empty template metaprogramming support calls (e.g. _Iter_cat).

Improved performance across all algorithms that take function objects by reducing the number of function object copies (VSO#91245).

Applied improved diagnostics for _SCL_INSECURE_DEPRECATE messages to the remaining algorithms (in Update 2 only a small number of algorithms were hooked into the new deprecation mechanism). This also improves the debugging experience when debugging into the standard algorithms, as there is no longer any _ITERATOR_DEBUG_LEVEL preprocessor interaction declaring multiple copies of standard algorithms (VSO#180466).

Fixed an inability to compile some functions like mismatch(iter, iter, T[]) due to an interaction between C++14’s dual-range algorithms and our slightly non-standard _ITERATOR_DEBUG_ARRAY_OVERLOADS (VSO#211972).

Improved performance of std::mismatch under _ITERATOR_DEBUG_LEVEL 1 and 2 by range checking the second range where possible ahead of iteration.

Fixed violations of the off-by-default warning C4242 in the STL (VSO#194854). Note that we fix off-by-default warnings rarely and on a case-by-case basis. Our policy is to remain /W4 /analyze clean, but we do not attempt to be /Wall clean.

Fixed a possible integer overflow bug in std::pop_heap (VSO#204655).

Fixed a potential hang under /clr:pure due to CLR-inserted LoadLibrary calls while holding the locale lock.

Fixed the return value of atomic<UDT>::operator=() (VSO#197633/Connect#2430244). Note that atomic<integral> and atomic<T *> were unaffected.

Improved performance of exception_ptr by using make_shared() internally.

Reduced stack space consumption of regex matching, avoiding stack overflows in more cases (VSO#208146).

Fixed subtract_with_carry_engine::seed() to take result_type instead of unsigned long (VSO#214595/Connect#2610325).

Fixed the behavior of subtract_with_carry_engine when m == numeric_limits<result_type>::digits (VSO#219985).

We eliminated more unintentional usage of non-Standard compiler extensions in STL headers, improving conformance and making Clang happier (VSO#192363). Note that the iostreams headers contained three in-class specializations of _Getvals(), which is a non-Standard technique. Due to binary compatibility concerns, this remains unchanged in Update 3, but has been fixed for the next major version of the STL. (Clang accepts this without emitting a warning because STL headers are system headers.)

In RTM through Update 2, the STL contained an undocumented “escape hatch” to disable constexpr usage, which involved _CONST_FUN and _CONST_DATA macros appearing throughout the STL’s headers. This turned out to be unnecessary, so in Update 3 we’ve eliminated these macros. Now the STL’s headers mention “constexpr” unconditionally.

std::is_assignable is now powered by a compiler hook for Clang (previously implemented for C1XX), simplifying the STL’s headers and potentially improving compiler throughput.

std::addressof() is now powered by a compiler hook for C1XX and Clang, allowing it to be constexpr and improving compiler throughput.

STL containers and iterators now support “fancy pointers”.

Function templates in locale code now defend themselves against overloaded comma operators.

The STL now correctly handles POCS allocators (propagate_on_container_swap). Note that POCCA/POCMA (propagate_on_container_copy_assignment/propagate_on_container_move_assignment) are being severely mishandled, up to and including silent bad codegen. They have been fixed for the next release of the STL.

Billy Robert O’Neal III – @MalwareMinigun

SDE II – Visual C++ Libraries

bion@microsoft.com

Casey Carter – @CoderCasey

SDE II – Visual C++ Libraries

cacarter@microsoft.com

Stephan T. Lavavej – @StephanTLavavej

Senior Developer – Visual C++ Libraries

stl@microsoft.com