diff --git a/stl/inc/limits b/stl/inc/limits index ad6f5f1a01..c39893639b 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -120,7 +120,10 @@ struct _Num_int_base : _Num_base { // base for integer types static constexpr bool is_exact = true; static constexpr bool is_integer = true; static constexpr bool is_specialized = true; - static constexpr int radix = 2; +#if !defined(__clang__) || defined(_M_X64) && !defined(_M_ARM64EC) || defined(_M_IX86) + static constexpr bool traps = true; +#endif + static constexpr int radix = 2; }; struct _Num_float_base : _Num_base { // base for floating-point types @@ -178,6 +181,7 @@ public: return 0; } + static constexpr bool traps = false; static constexpr int digits = 1; }; @@ -222,6 +226,7 @@ public: static constexpr bool is_signed = CHAR_MIN != 0; static constexpr bool is_modulo = CHAR_MIN == 0; + static constexpr bool traps = false; static constexpr int digits = 8 - (CHAR_MIN != 0); static constexpr int digits10 = 2; }; @@ -266,6 +271,7 @@ public: } static constexpr bool is_signed = true; + static constexpr bool traps = false; static constexpr int digits = 7; static constexpr int digits10 = 2; }; @@ -310,6 +316,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 8; static constexpr int digits10 = 2; }; @@ -355,6 +362,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 8; static constexpr int digits10 = 2; }; @@ -400,6 +408,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 16; static constexpr int digits10 = 4; }; @@ -488,6 +497,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 16; static constexpr int digits10 = 4; }; @@ -532,6 +542,7 @@ public: } static constexpr bool is_signed = true; + static constexpr bool traps = false; static constexpr int digits = 15; static constexpr int digits10 = 4; }; @@ -710,6 +721,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 16; static constexpr int digits10 = 4; }; diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 343abccc27..191c6e6bdf 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -733,11 +733,6 @@ std/depr/depr.c.headers/tgmath_h.pass.cpp:2 FAIL # *** CLANG ISSUES, NOT YET ANALYZED *** -# Not analyzed. Clang apparently defines platform macros differently from C1XX. -# The test inspects `__x86_64__` and `__i386__`, which MSVC doesn't define. -# SKIPPED because this fails for x64/x86 and passes for ARM64. -std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp:2 SKIPPED - # Not analyzed. Possibly C++20 equality operator rewrite issues. std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp:2 FAIL std/utilities/expected/expected.void/equality/equality.other_expected.pass.cpp:2 FAIL @@ -996,6 +991,15 @@ std/containers/sequences/vector/trivial_relocation.pass.cpp:1 FAIL # Not analyzed, likely bogus test. constexpr fails with "vector iterators incompatible". std/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.default.pass.cpp FAIL +# Problems in this test: +# - Clang does not trap on Arm64, but MSVC does. +# - The test inspects `__x86_64__` and `__i386__`, which MSVC doesn't define. +# - The __x86_64__ is defined on ARM64EC, but it is expected to behave like ARM64 +# :2 SKIPPED because this passes for x64/x86/ARM64 and fails for ARM64EC. +std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp:0 FAIL +std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp:1 FAIL +std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp:2 SKIPPED + # *** LIKELY STL BUGS *** # Not analyzed, likely STL bugs. Various assertions. diff --git a/tests/std/test.lst b/tests/std/test.lst index c502981b96..4fe33488f8 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -272,6 +272,7 @@ tests\GH_005546_containers_size_type_cast tests\GH_005553_regex_character_translation tests\GH_005768_pow_accuracy tests\GH_005800_stable_sort_large_alignment +tests\GH_005816_numeric_limits_traps tests\LWG2381_num_get_floating_point tests\LWG2510_tag_classes tests\LWG2597_complex_branch_cut diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/env.lst b/tests/std/tests/GH_005816_numeric_limits_traps/env.lst new file mode 100644 index 0000000000..19f025bd0e --- /dev/null +++ b/tests/std/tests/GH_005816_numeric_limits_traps/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp new file mode 100644 index 0000000000..ee4316c57a --- /dev/null +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +template +constexpr bool traps_ = std::numeric_limits::traps; + +#if defined(_M_IX86) || defined(_M_X64) && !defined(_M_ARM64EC) +static_assert(traps_, + "The #ED hardware exception always happens for zero division and for division overflow INT_MIN/-1. " + "It is translated to the corresponding SEH exceptions"); +#elif defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) +#ifdef __clang__ +static_assert(!traps_, "The hardware does not trap. Clang compiles code as is, so there's no trap"); +#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +static_assert(traps_, "The hardware does not trap. MSVC inserts check for zero to trap zero division. " + "It does not insert checks for INT_MIN/-1 division overflow though"); +#endif // ^^^ !defined(__clang__) ^^^ +#else // ^^^ defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) ^^^ +#error Unsupported hardware +#endif + +static_assert(traps_ == traps_ && traps_ == traps_ // + && traps_ == traps_ && traps_ == traps_ + && traps_ == traps_ && traps_ == traps_, + "all non-promoted integers should trap or not trap equally"); + +static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); + +static_assert(!traps_ && !traps_ && !traps_ // + && !traps_ && !traps_ && !traps_ && !traps_, + "promoted integers do not trap for a moot reason; see LWG-554 resolution"); + +#ifdef __cpp_char8_t +static_assert(!traps_, "promoted integers do not trap for a moot reason; see LWG-554 resolution"); +#endif + +static_assert(!traps_ && !traps_ && !traps_, + "floats don't trap because even if '/fp:except' is passed, it should be enabled at runtime");