STL Fixes In VS 2015 Update 1

December 7th, 2015

VS 2015 Update 1 is now available, and it contains numerous STL fixes. (This is the first time since 2010 SP1 that we’ve shipped STL fixes outside of a major version. Nothing was severely broken in 2015 RTM – we’re just trying to deliver fixes to you faster, and our internal processes are making this easier.) As usual, I’ve written up an exhaustive changelog, like Part 1 and Part 2 for the fixes in 2015 RTM. Note that while Update 1 contains many compiler/IDE/etc. improvements (including partial support for Expression SFINAE), they aren’t mentioned here – I can’t personally keep track of everything!

First, Steve Wishnousky recently joined the VC Libraries team, and he got a couple of fixes into Update 1:

* unordered_meow::max_bucket_count() was returning an incorrect value (VSO#144294/Connect#1764567). Now it’s correct.

* Our internal helper functions _Allocate() and _Deallocate() were unnecessarily templated, producing larger-than-necessary object files (VSO#130290). Now they’re de-templatized, which should shrink object files slightly.

Also, Hong Hong fixed a couple of bugs reported in <future> which were caused by its internal inclusion of <ppltasks.h>/etc.:

* <future> didn’t respect _HAS_EXCEPTIONS=0 (TFS#1127004/Connect#1137364). While this is currently undocumented, untested, and unsupported by Microsoft, we decided to fix this problem anyways.

* <future> was indirectly defining a non-Standard stdx::declval() (TFS#1194345/Connect#1494998). This internal helper has been renamed to Concurrency::details::declval(). (For the time being, it’s by design that <future> drags in the non-_Ugly Concurrency namespace and the machinery within.)

Next, I fixed several bugs:

* Given enable_shared_from_this<X>, attempting to use shared_ptr<volatile X> would fail to compile (TFS#1178296). Now volatile works like const always has.

* allocator_traits incorrectly assumed that UserAlloc::construct()/destroy() returned void (when they existed), triggering compiler errors for non-void return types (TFS#1184701). Now we properly accept (and ignore) non-void return types.

* In 2015 RTM’s tuple_size/tuple_element, I tried to be helpful by static_asserting about non-tuple-ish things. Unfortunately, that prevents SFINAE, so it’s non-conformant (TFS#1192603, TFS#1205400/Connect#1600812). Now we’re following the Standard.

* The Standard requires rethrow_exception() to be marked [[noreturn]], but ours wasn’t, which could break code at compile time (VSO#125155/Connect#1657472). In addition to fixing this, I checked for any other missing occurrences (there weren’t any), and I changed every __declspec(noreturn) in the STL to be [[noreturn]] instead. (They’re synonymous, so this is simply an attempt to use Standard machinery when possible. Note that the CRT continues to use the __declspec.)

* In 2015 RTM’s mem_fn(), I tried to be clever by handling a particularly obscure scenario with calling conventions. This had a barely-observable effect on the function’s signature, which users inevitably noticed (VSO#134162). I’ve removed the cleverness, so mem_fn() follows the Standard exactly.

* atomic<FunctionPointer> was accidentally using non-Standard behavior from C1XX, VC’s compiler front-end (TFS#1181758/Connect#1393505). (The issue was: When casting between void * and Object *, static_cast and reinterpret_cast are equivalent. However, when casting between void * and Function *, static_cast is forbidden while reinterpret_cast works, N4567 5.2.10 [expr.reinterpret.cast]/8.) <atomic> now uses reinterpret_cast, following the Standard.

* In addition to <atomic>, I fixed the STL’s headers (and tests) to work with Clang/C2 (“Clang with Microsoft CodeGen”), which will also benefit Clang/LLVM. Our headers had very little accidental usage of non-Standard behavior to begin with, thanks to many years of stringent testing with EDG (the front-end used for IntelliSense), so only a few header changes were necessary. As part of this work, I reported many bugs in Clang/C2 which were fixed before releasing, so you’ll never suffer from them. This even identified a few bugs (e.g. type traits, CRLFs in raw string literals) and opportunities for improvement in Clang itself, which will benefit Clang/LLVM for Windows and non-Windows platforms. Special thanks to David Majnemer (unaffiliated with Microsoft) and the other Clang devs who implemented these bugfixes and improvements upstream.

Technical details: Clang 3.7 shipped with a couple of options, -fms-extensions and -fms-compatibility. -fms-extensions controls non-Standard features like __declspec(dllexport), which the STL requires to get its job done. -fms-compatibility controls “bug compatibility” (i.e. making Clang imitate C1XX bugs), but when David and I met at CppCon 2015, we realized that there are two kinds of bug compatibility: bugs that affect ABI (e.g. layout) and bugs that don’t affect ABI (e.g. accepts-invalid). So there have been changes committed to Clang’s post-3.7 trunk (and ported to the Clang/C2 release). Now, ABI-relevant bug compatibility is always enabled when targeting Windows, as this is required to be link-compatible with C1XX/C2 binaries. ABI-irrelevant bug compatibility is controlled by -fms-compatibility. Our STL’s headers (and tests) now work with -fno-ms -compatibility, the strictest level of conformance. (There’s one minor exception: <future> drags in <ppltasks.h> which was doing something non-conformant although fairly innocuous. The Standard doesn’t permit incomplete classes to be returned by value, even from “imaginary” functions that are declared but never defined. By the time I discovered this, it was too late to get a fix into Update 1, so Clang/C2 was temporarily hacked before releasing in order to accept this specific thing. I’ve fixed <ppltasks.h> for Update 2, so the Clang/C2 workaround can eventually be removed.)

* While I was in the neighborhood, I also fixed the STL’s headers to work with /Za, and added comprehensive test coverage. /Za is C1XX’s option to enable extra conformance, but it also enables extra compiler bugs in rarely-used codepaths, so we discourage its use. (I stopped testing the STL with /Za years ago when it broke perfectly valid uses of vector<unique_ptr<T>>. That was eventually fixed, but I didn’t resume testing until now.)

Note that /Za is still affected by a compiler bug that will prevent you from using it with the STL (in general). VSO#122298/Connect#1331482 “__declspec(selectany) constexpr doesn’t work with /Za” triggers linker errors when multiple translation units drag in <limits>, which was constexprized in 2015 RTM. The compiler has been fixed for Update 2. (I temporarily worked around it in the STL’s tests – we have only one with multiple TUs, hilariously enough.)

* numeric_limits<float/double/long double>::infinity()/quiet_NaN()/signaling_NaN() are now constexpr, powered by GCC/Clang’s compiler builtins that have been implemented in C1XX/EDG. Note that signaling_NaN() specifically is affected by a C1XX bug (VSO#128935/Connect#1686806), causing the sNaN’s bits to be modified as they’re returned from a function, which the STL obviously can’t work around.

* <exception> was missing several occurrences of noexcept, which I’ve added.

* The performance of shared_ptr’s atomic operations (the weird free functions, not the normal refcount manipulations) has been improved by avoiding unnecessary copies.

* bitset<0>’s member functions misbehaved at runtime, as found by Clang/libc++’s test suite (TFS#917456, TFS#917467). Now they behave correctly, although bitset<0> is still the most useless thing imaginable.

Finally, although I don’t usually list compiler fixes even when they affect the STL (e.g. <type_traits>), there’s one worth mentioning:

* Tanveer Gani fixed VSO#103444 “constexpr constructors are emitting dynamic initializers”. This affected the newly-constexprized STL, most importantly std::once_flag, which is now being statically initialized as required by the Standard. Note that this fix has some limitations that don’t affect the STL (e.g. having virtuals still prevents static initialization), and there’s a spurious warning that can be disabled – see Tanveer’s answer to this StackOverflow question for more information.

That’s the end of the STL’s Update 1 changelog. Steve Wishnousky (@SteveWishnousky), our other new hire Billy O’Neal (@MalwareMinigun), and I are working on many more changes for Update 2 – we’ve already checked in dozens of fixes and 9 features! (This will be the first time since 2008 SP1 that we’ve shipped STL features outside of a major version.)

Stephan T. Lavavej (@StephanTLavavej)

Senior Developer – Visual C++ Libraries

stl@microsoft.com