diff --git a/stl/inc/limits b/stl/inc/limits index ad6f5f1a01..0baa86fcdf 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; }; 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..2b1ea6a718 --- /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 + +#if defined(_M_IX86) || defined(_M_X64) && !defined(_M_ARM64EC) +// The #ED hardware exception always happens for zero division and for division overflow INT_MIN/-1 +// It is translated to the corresponding SEH exceptions +constexpr bool _Integer_zero_division_traps = true; +#elif defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) +// The hardware does not trap. +#ifdef __clang__ +// Clang compiles code as is, so there's no trap +constexpr bool _Integer_zero_division_traps = false; +#else // ^^^ defined(__clang__) / !defined(__clang__) vvv +// MSVC inserts check for zero to trap zero division. +// It does not insert checks for INT_MIN/-1 division overflow though. +constexpr bool _Integer_zero_division_traps = true; +#endif // ^^^ !defined(__clang__) ^^^ +#else // ^^^ defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) ^^^ +#error Unsupported hardware +#endif + +template +constexpr bool traps_ = std::numeric_limits::traps; + +static_assert(traps_ == _Integer_zero_division_traps, + "integer trap behavior should match the expectation from the current platform and complier"); + +static_assert(traps_ == traps_ && traps_ == traps_ && traps_ == traps_ + && traps_ == traps_ && traps_ == traps_ + && traps_ == traps_ // + && traps_ == traps_ && traps_ == traps_ + && traps_ == traps_ && traps_ == traps_, + "all 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_, + "floats don't trap because even if '/fp:except' is passed, it should be enabled at runtime");