diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index a6428797c01..a8dbd7083bb 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -10,6 +10,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_bit_utils.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_chrono.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_cxx_stdatomic.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_doom_core.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_filebuf.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_format_ucd_tables.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_formatter.hpp diff --git a/stl/inc/__msvc_doom_core.hpp b/stl/inc/__msvc_doom_core.hpp new file mode 100644 index 00000000000..1300f8081cd --- /dev/null +++ b/stl/inc/__msvc_doom_core.hpp @@ -0,0 +1,54 @@ +// __msvc_doom_core.hpp internal header (core) + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef __MSVC_DOOM_CORE_HPP +#define __MSVC_DOOM_CORE_HPP +#include +#if _STL_COMPILER_PREPROCESSOR + +#ifdef _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION +#include +#elif defined(_M_CEE) +#include +#endif // ^^^ defined(_M_CEE) ^^^ + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +// The STL's "doom function" can be replaced. Notes: +// * It must not throw. (Attempting to throw would slam into noexcept.) +// * Common case: If it doesn't return, it should be marked as `[[noreturn]]`. +// * Uncommon case: If it returns, the STL will attempt to "continue on error", behaving as if no checking was done. +// + For example, a legacy codebase with a long startup time might want to log errors for investigation later. +// + WARNING: If you replace the STL's "doom function" to "continue on error", you do so at your own risk! +// After the STL has detected a precondition violation, undefined behavior is imminent. The STL will support +// "continue on error" by proceeding to do what it would have done anyways (instead of falling off the end of +// a non-void function, etc.), but it will not attempt to replace undefined behavior with implementation-defined +// behavior. (For example, we will not transform `pop_back()` of an empty `vector` to be a no-op.) +#ifndef _MSVC_STL_DOOM_FUNCTION +#ifdef _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION // The user wants to use abort(): +#define _MSVC_STL_DOOM_FUNCTION(mesg) _CSTD abort() +#elif defined(__clang__) // Use the Clang intrinsic: +#define _MSVC_STL_DOOM_FUNCTION(mesg) __builtin_verbose_trap("MSVC STL error", mesg) +#elif defined(_M_CEE) // TRANSITION, VSO-2457624 (/clr silent bad codegen for __fastfail); /clr:pure lacks __fastfail +#define _MSVC_STL_DOOM_FUNCTION(mesg) ::_invoke_watson(nullptr, nullptr, nullptr, 0, 0) +#else // Use the MSVC __fastfail intrinsic: +extern "C" __declspec(noreturn) void __fastfail(unsigned int); // declared by +#define _MSVC_STL_DOOM_FUNCTION(mesg) \ + __fastfail(5); /* __fastfail(FAST_FAIL_INVALID_ARG), value defined by */ \ + _STL_UNREACHABLE /* TRANSITION, DevCom-10914110 */ +#endif // choose "doom function" +#endif // ^^^ !defined(_MSVC_STL_DOOM_FUNCTION) ^^^ + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR +#endif // __MSVC_DOOM_CORE_HPP diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index 536c2fb4990..e94f92bd534 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -8,6 +8,7 @@ "__msvc_bit_utils.hpp", "__msvc_chrono.hpp", "__msvc_cxx_stdatomic.hpp", + "__msvc_doom_core.hpp", "__msvc_filebuf.hpp", "__msvc_format_ucd_tables.hpp", "__msvc_formatter.hpp", diff --git a/stl/inc/utility b/stl/inc/utility index b2593825b03..98c3268f481 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -7,6 +7,7 @@ #define _UTILITY_ #include #if _STL_COMPILER_PREPROCESSOR +#include <__msvc_doom_core.hpp> #include #include @@ -1013,6 +1014,9 @@ _NODISCARD constexpr underlying_type_t<_Ty> to_underlying(_Ty _Value) noexcept { } _EXPORT_STD [[noreturn]] __forceinline void unreachable() noexcept /* strengthened */ { +#ifdef _DEBUG + _MSVC_STL_DOOM_FUNCTION("std::unreachable() called"); +#endif // defined(_DEBUG) _STL_UNREACHABLE; } diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 97361f553af..1b61260960b 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -18,6 +18,7 @@ _EMIT_STL_ERROR( STL1005, "Tried to include a non-core C++ Standard Library header file with _ENFORCE_ONLY_CORE_HEADERS defined."); #endif // defined(_ENFORCE_ONLY_CORE_HEADERS) +#include <__msvc_doom_core.hpp> #include #include @@ -248,31 +249,6 @@ _EMIT_STL_ERROR(STL1008, "_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER has been "It was superseded by _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION."); #endif -// The STL's "doom function" can be replaced. Notes: -// * It must not throw. (Attempting to throw would slam into noexcept.) -// * Common case: If it doesn't return, it should be marked as `[[noreturn]]`. -// * Uncommon case: If it returns, the STL will attempt to "continue on error", behaving as if no checking was done. -// + For example, a legacy codebase with a long startup time might want to log errors for investigation later. -// + WARNING: If you replace the STL's "doom function" to "continue on error", you do so at your own risk! -// After the STL has detected a precondition violation, undefined behavior is imminent. The STL will support -// "continue on error" by proceeding to do what it would have done anyways (instead of falling off the end of -// a non-void function, etc.), but it will not attempt to replace undefined behavior with implementation-defined -// behavior. (For example, we will not transform `pop_back()` of an empty `vector` to be a no-op.) -#ifndef _MSVC_STL_DOOM_FUNCTION -#ifdef _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION // The user wants to use abort(): -#define _MSVC_STL_DOOM_FUNCTION(mesg) _CSTD abort() -#elif defined(__clang__) // Use the Clang intrinsic: -#define _MSVC_STL_DOOM_FUNCTION(mesg) __builtin_verbose_trap("MSVC STL error", mesg) -#elif defined(_M_CEE) // TRANSITION, VSO-2457624 (/clr silent bad codegen for __fastfail); /clr:pure lacks __fastfail -#define _MSVC_STL_DOOM_FUNCTION(mesg) ::_invoke_watson(nullptr, nullptr, nullptr, 0, 0) -#else // Use the MSVC __fastfail intrinsic: -extern "C" __declspec(noreturn) void __fastfail(unsigned int); // declared by -#define _MSVC_STL_DOOM_FUNCTION(mesg) \ - __fastfail(5); /* __fastfail(FAST_FAIL_INVALID_ARG), value defined by */ \ - _STL_UNREACHABLE /* TRANSITION, DevCom-10914110 */ -#endif // choose "doom function" -#endif // ^^^ !defined(_MSVC_STL_DOOM_FUNCTION) ^^^ - #define _STL_REPORT_ERROR(mesg) \ _RPTF0(_CRT_ASSERT, mesg); \ _MSVC_STL_DOOM_FUNCTION(mesg) diff --git a/tests/std/tests/GH_001411_core_headers/test.cpp b/tests/std/tests/GH_001411_core_headers/test.cpp index 3e7a01bd520..0acfed55223 100644 --- a/tests/std/tests/GH_001411_core_headers/test.cpp +++ b/tests/std/tests/GH_001411_core_headers/test.cpp @@ -8,6 +8,7 @@ // Also test GH-3103 ": Investigate making this a core header" and other internal core headers #include <__msvc_int128.hpp> +#include <__msvc_minmax.hpp> #include <__msvc_system_error_abi.hpp> #include <__msvc_threads_core.hpp> #include <__msvc_xlocinfo_types.hpp> @@ -25,6 +26,7 @@ #endif // ^^^ _HAS_CXX20 ^^^ // <__msvc_bit_utils.hpp> is included by and +// <__msvc_doom_core.hpp> is included by // <__msvc_iter_core.hpp> is included by // should not be included outside of // is included by diff --git a/tests/std/tests/P0627R6_unreachable/env.lst b/tests/std/tests/P0627R6_unreachable/env.lst index 642f530ffad..11ebe9a5bc0 100644 --- a/tests/std/tests/P0627R6_unreachable/env.lst +++ b/tests/std/tests/P0627R6_unreachable/env.lst @@ -2,3 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception RUNALL_INCLUDE ..\usual_latest_matrix.lst +RUNALL_CROSSLIST +* PM_CL="" +* PM_CL="/D_MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION" diff --git a/tests/std/tests/P0627R6_unreachable/test.cpp b/tests/std/tests/P0627R6_unreachable/test.cpp index 818ba92eaad..b0527764a00 100644 --- a/tests/std/tests/P0627R6_unreachable/test.cpp +++ b/tests/std/tests/P0627R6_unreachable/test.cpp @@ -1,8 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include -#include +#include // Only include to test compilation of doom function without additional includes. constexpr char test_impl(const int arg) { switch (arg) { @@ -18,13 +17,13 @@ constexpr char test_impl(const int arg) { } constexpr bool test() { - assert(test_impl(1) == 'a'); - assert(test_impl(2) == 'z'); - return true; + return test_impl(1) == 'a' && test_impl(2) == 'z'; } int main() { - test(); + if (!test()) { + return 1; + } static_assert(test()); static_assert(noexcept(std::unreachable())); // strengthened }