From 2b4fb315518cc62cc096ac06369146e0f5757a76 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 28 Oct 2025 18:07:29 +0200 Subject: [PATCH 01/28] Integer coverage --- tests/std/test.lst | 1 + .../GH_005816_numeric_limits_traps/env.lst | 4 +++ .../GH_005816_numeric_limits_traps/test.cpp | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/std/tests/GH_005816_numeric_limits_traps/env.lst create mode 100644 tests/std/tests/GH_005816_numeric_limits_traps/test.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 9dabf29d512..f80cae63fd0 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -272,6 +272,7 @@ tests\GH_005472_do_not_overlap tests\GH_005546_containers_size_type_cast tests\GH_005553_regex_character_translation tests\GH_005768_pow_accuracy +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 00000000000..19f025bd0e6 --- /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.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp new file mode 100644 index 00000000000..dc8a8140a79 --- /dev/null +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension +#else +#pragma warning(disable : 4984) // warning C4984: 'if constexpr' is a C++17 language extension +#endif // __clang__ + +void trap_operation() { + volatile int op1{1}; + volatile int op2{0}; + volatile int res = op1 / op2; + (void) res; +} + +int main(int argc, char* argv[]) { + if constexpr (std::numeric_limits::traps) { + std_testing::death_test_executive exec; + const std_testing::death_function_t one_trap[] = {trap_operation}; + exec.add_death_tests(one_trap); + return exec.run(argc, argv); + } else { + trap_operation(); + } +} From 9833a4ac8a6b6d6e69085de132da170cd8ca411d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 28 Oct 2025 18:07:40 +0200 Subject: [PATCH 02/28] Product code fix --- stl/inc/limits | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stl/inc/limits b/stl/inc/limits index ad6f5f1a013..ae4d9050a8f 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(_M_IX86) || defined(_M_X64) + 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; }; From b17606a28ecc69db8e9487c7cbb7352402ed8a0d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 28 Oct 2025 19:07:06 +0200 Subject: [PATCH 03/28] Skip numeric.limits.members/traps.pass.cpp for Clang. (cherry picked from commit c31c5e2a611ac13f256f3e39848fa9f9d6e24d51) --- tests/libcxx/expected_results.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 0253413ab1d..343abccc27a 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -734,7 +734,9 @@ 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. -std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp:2 FAIL +# 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 From 97e6faa637f2e1b4ac236ce60733e9881021735f Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 28 Oct 2025 19:31:01 +0200 Subject: [PATCH 04/28] Skippy skip --- tests/libcxx/expected_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 343abccc27a..7888e8e5612 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -736,7 +736,7 @@ std/depr/depr.c.headers/tgmath_h.pass.cpp:2 FAIL # 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 +std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp SKIPPED # Not analyzed. Possibly C++20 equality operator rewrite issues. std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp:2 FAIL From e627022e93ab6119c7235c618e9a512b05b234b5 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 18:34:52 +0200 Subject: [PATCH 05/28] it is always the trap --- stl/inc/limits | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index ae4d9050a8f..2d1bbc0a8b7 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -120,10 +120,8 @@ 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; -#if defined(_M_IX86) || defined(_M_X64) - static constexpr bool traps = true; -#endif - static constexpr int radix = 2; + static constexpr bool traps = true; + static constexpr int radix = 2; }; struct _Num_float_base : _Num_base { // base for floating-point types From ad6a32fa55da91d75da3a230424e1e155df7e294 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 19:24:07 +0200 Subject: [PATCH 06/28] but Clang --- stl/inc/limits | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index 2d1bbc0a8b7..12b6e72d769 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -120,8 +120,12 @@ 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 bool traps = true; - static constexpr int radix = 2; +#if !defined(__clang__) || defined(__x86_64__) || defined(__i386__) + static constexpr bool traps = true; +#else // ^^^ not Clang or x64 or x86 / Clang and not x64 and not x86 vvv + static constexpr bool traps = false; +#endif // ^^^ Clang and not x64 and not x86 ^^^ + static constexpr int radix = 2; }; struct _Num_float_base : _Num_base { // base for floating-point types From 816d158c601339a1276cad84f5f3c72cd00fca86 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 19:46:47 +0200 Subject: [PATCH 07/28] concise override --- stl/inc/limits | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index 12b6e72d769..fbb9b824818 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -122,9 +122,7 @@ struct _Num_int_base : _Num_base { // base for integer types static constexpr bool is_specialized = true; #if !defined(__clang__) || defined(__x86_64__) || defined(__i386__) static constexpr bool traps = true; -#else // ^^^ not Clang or x64 or x86 / Clang and not x64 and not x86 vvv - static constexpr bool traps = false; -#endif // ^^^ Clang and not x64 and not x86 ^^^ +#endif // ^^^ not Clang or x64 or x86 ^^^ static constexpr int radix = 2; }; From 6996605ebcead4cf8caef355027100a59faea430 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 19:49:11 +0200 Subject: [PATCH 08/28] Spell that more naturally --- tests/std/tests/GH_005816_numeric_limits_traps/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp index dc8a8140a79..8917ed349c4 100644 --- a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp @@ -12,9 +12,9 @@ #endif // __clang__ void trap_operation() { - volatile int op1{1}; - volatile int op2{0}; - volatile int res = op1 / op2; + const volatile int op1 = 1; + const volatile int op2 = 0; + const volatile int res = op1 / op2; (void) res; } From 3347a99a6e9625f4cf06f0a0e89b121bdb312de7 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 19:59:28 +0200 Subject: [PATCH 09/28] Now we know --- tests/libcxx/expected_results.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 7888e8e5612..2672d3c5c1a 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 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,14 @@ 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 +# Two 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. +# :2 SKIPPED because this fails for x64/x86 and passes for ARM64. +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. From a49bce3e303e127a66f57d42c80c2e7be357fe5c Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 20:45:13 +0200 Subject: [PATCH 10/28] comprehensive compile-time coverage --- .../GH_005816_numeric_limits_traps/test.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp index 8917ed349c4..1597d0732ce 100644 --- a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp @@ -11,6 +11,21 @@ #pragma warning(disable : 4984) // warning C4984: 'if constexpr' is a C++17 language extension #endif // __clang__ +template +constexpr bool traps_ = std::numeric_limits::traps; + +static_assert(!traps_, "bool does not trap for a moot reason"); + +static_assert(!traps_ && !traps_ && !traps_, + "floats don't trap because even if '/fp:except' is passed, it should be enabled at runtime"); + +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"); + void trap_operation() { const volatile int op1 = 1; const volatile int op2 = 0; @@ -19,7 +34,7 @@ void trap_operation() { } int main(int argc, char* argv[]) { - if constexpr (std::numeric_limits::traps) { + if constexpr (traps_) { std_testing::death_test_executive exec; const std_testing::death_function_t one_trap[] = {trap_operation}; exec.add_death_tests(one_trap); From e1a996e541cb652d942c188ae4fecf3cd46b34f1 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 20:54:27 +0200 Subject: [PATCH 11/28] nicer test format --- .../std/tests/GH_005816_numeric_limits_traps/test.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp index 1597d0732ce..4c7224dfa2b 100644 --- a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp @@ -7,9 +7,9 @@ #ifdef __clang__ #pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension -#else +#else // ^^^ defined(__clang__) / !defined(__clang__) vvv #pragma warning(disable : 4984) // warning C4984: 'if constexpr' is a C++17 language extension -#endif // __clang__ +#endif // ^^^ !defined(__clang__) ^^^ template constexpr bool traps_ = std::numeric_limits::traps; @@ -21,9 +21,9 @@ static_assert(!traps_ && !traps_ && !traps_, static_assert(traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_ - && 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"); void trap_operation() { From 257f831bb27577b34b17ad04f07d7d84e3ae0779 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 30 Oct 2025 21:34:13 +0200 Subject: [PATCH 12/28] No longer SKIPPED actually --- tests/libcxx/expected_results.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 2672d3c5c1a..021b35a0a81 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -994,10 +994,8 @@ std/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.default. # Two 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. -# :2 SKIPPED because this fails for x64/x86 and passes for ARM64. 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 *** From 4ede9b1b7fdbcd1c82e37c53c015b4476db38d4b Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 2 Nov 2025 13:09:33 +0200 Subject: [PATCH 13/28] No more death, no more execution! --- .../{test.cpp => test.compile.pass.cpp} | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) rename tests/std/tests/GH_005816_numeric_limits_traps/{test.cpp => test.compile.pass.cpp} (52%) diff --git a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp similarity index 52% rename from tests/std/tests/GH_005816_numeric_limits_traps/test.cpp rename to tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp index 4c7224dfa2b..d7f37ffcc97 100644 --- a/tests/std/tests/GH_005816_numeric_limits_traps/test.cpp +++ b/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp @@ -3,21 +3,29 @@ #include -#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 exxcptions +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__ -#pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension +// Clang compiles code as is, so there's no trap +constexpr bool _Integer_zero_division_traps = false; #else // ^^^ defined(__clang__) / !defined(__clang__) vvv -#pragma warning(disable : 4984) // warning C4984: 'if constexpr' is a C++17 language extension +// MSVC inserts check for zero to trap zero division. +// It does not insert thecks 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_, "bool does not trap for a moot reason"); - -static_assert(!traps_ && !traps_ && !traps_, - "floats don't trap because even if '/fp:except' is passed, it should be enabled at runtime"); +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_ @@ -26,20 +34,7 @@ static_assert(traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_, "all integers should trap or not trap equally"); -void trap_operation() { - const volatile int op1 = 1; - const volatile int op2 = 0; - const volatile int res = op1 / op2; - (void) res; -} +static_assert(!traps_, "bool does not trap for a moot reason"); -int main(int argc, char* argv[]) { - if constexpr (traps_) { - std_testing::death_test_executive exec; - const std_testing::death_function_t one_trap[] = {trap_operation}; - exec.add_death_tests(one_trap); - return exec.run(argc, argv); - } else { - trap_operation(); - } -} +static_assert(!traps_ && !traps_ && !traps_, + "floats don't trap because even if '/fp:except' is passed, it should be enabled at runtime"); From 72bd6f4d3dd332a5f467f29a7cce1477ba513d43 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 2 Nov 2025 13:18:10 +0200 Subject: [PATCH 14/28] spelling --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index d7f37ffcc97..04f2ac71c59 100644 --- 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 @@ -5,7 +5,7 @@ #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 exxcptions +// 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. From 614a323c2abb78dbf4ce4896b815ed4f64e8e843 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 2 Nov 2025 13:34:53 +0200 Subject: [PATCH 15/28] spelling --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 04f2ac71c59..8486e3f1a51 100644 --- 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 @@ -14,7 +14,7 @@ constexpr bool _Integer_zero_division_traps = true; 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 thecks for INT_MIN/-1 division overflow though. +// 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) ^^^ From c9c5ab7944fffba2d97b9b22b0b4ccb918991993 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 2 Nov 2025 14:47:34 +0200 Subject: [PATCH 16/28] ARM64EC fix --- stl/inc/limits | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index fbb9b824818..0baa86fcdfb 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -120,9 +120,9 @@ 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; -#if !defined(__clang__) || defined(__x86_64__) || defined(__i386__) +#if !defined(__clang__) || defined(_M_X64) && !defined(_M_ARM64EC) || defined(_M_IX86) static constexpr bool traps = true; -#endif // ^^^ not Clang or x64 or x86 ^^^ +#endif static constexpr int radix = 2; }; From 1c3179e0cbd205f6200a35b049262243df037daa Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 2 Nov 2025 15:32:28 +0200 Subject: [PATCH 17/28] back 2 skipped --- tests/libcxx/expected_results.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 021b35a0a81..191c6e6bdf3 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -991,11 +991,14 @@ 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 -# Two problems in this test: +# 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 *** From b0fa9a649f0cffc99bd6abe5dbcb8cf8661ccbe9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 6 Nov 2025 09:00:41 +0200 Subject: [PATCH 18/28] mention LWG-554 --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 8486e3f1a51..2b1ea6a7187 100644 --- 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 @@ -34,7 +34,7 @@ static_assert(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"); +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"); From db1c4c7c9d78e6a05557edb4df4d7bec65ac1107 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 12:55:35 +0200 Subject: [PATCH 19/28] promoted integers don't trap --- stl/inc/limits | 8 ++++++++ .../test.compile.pass.cpp | 14 ++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index 0baa86fcdfb..c39893639b8 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -226,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; }; @@ -270,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; }; @@ -314,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; }; @@ -359,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; }; @@ -404,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; }; @@ -492,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; }; @@ -536,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; }; @@ -714,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/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp b/tests/std/tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp index 2b1ea6a7187..f9a3052a333 100644 --- 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 @@ -27,14 +27,20 @@ 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_ // +static_assert(traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_, - "all integers should trap or not trap equally"); + "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_, + "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"); From 1354e26edebc94aa1ed7be4d8292ba5a99983011 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 13:01:35 +0200 Subject: [PATCH 20/28] missing wchar_t --- .../GH_005816_numeric_limits_traps/test.compile.pass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index f9a3052a333..9bebb03cfc9 100644 --- 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 @@ -34,8 +34,8 @@ static_assert(traps_ == traps_ && traps_ == tra static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); -static_assert( - !traps_ && !traps_ && !traps_ && !traps_ && !traps_, +static_assert(!traps_ && !traps_ && !traps_ // + && !traps_ && !traps_ && !traps_, "promoted integers do not trap for a moot reason; see LWG-554 resolution"); #ifdef __cpp_char8_t From 870d8ee6d5fefaa64e86e187c27f119d4edfd96d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 13:31:49 +0200 Subject: [PATCH 21/28] missing short --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 9bebb03cfc9..92cec3ba470 100644 --- 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 @@ -35,7 +35,7 @@ static_assert(traps_ == traps_ && traps_ == tra static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); static_assert(!traps_ && !traps_ && !traps_ // - && !traps_ && !traps_ && !traps_, + && !traps_ && !traps_ && !traps_ && !traps_, "promoted integers do not trap for a moot reason; see LWG-554 resolution"); #ifdef __cpp_char8_t From a10866e337866d1c6d1d052b4def63c402aaef18 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 13:32:12 +0200 Subject: [PATCH 22/28] Avoid variable and comments --- .../test.compile.pass.cpp | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) 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 index 92cec3ba470..c53d121cdb4 100644 --- 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 @@ -3,30 +3,25 @@ #include +template +constexpr bool traps_ = std::numeric_limits::traps; + #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; +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) // The hardware does not trap. #ifdef __clang__ -// Clang compiles code as is, so there's no trap -constexpr bool _Integer_zero_division_traps = false; +static_assert(!traps_, "Clang compiles code as is, so there's no trap"); #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; +static_assert(traps_, "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 -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_, From b60b033371ad96ff0d1b0e517b4ae03f729ab74e Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 13:34:37 +0200 Subject: [PATCH 23/28] unnecessary transitivity --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index c53d121cdb4..009a1d3b4a3 100644 --- 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 @@ -22,7 +22,7 @@ static_assert(traps_, "MSVC inserts check for zero to trap zero division. " #error Unsupported hardware #endif -static_assert(traps_ == traps_ && traps_ == traps_ +static_assert(traps_ == traps_ && traps_ == traps_ // && traps_ == traps_ && traps_ == traps_ && traps_ == traps_ && traps_ == traps_, "all non-promoted integers should trap or not trap equally"); From a9ae3eb2e37a2a0f7cfb3c8e3dd2f7fb0e98e386 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 15 Nov 2025 14:08:30 +0200 Subject: [PATCH 24/28] even fewer comments --- .../GH_005816_numeric_limits_traps/test.compile.pass.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 index 009a1d3b4a3..ee4316c57ae 100644 --- 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 @@ -11,12 +11,11 @@ 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) -// The hardware does not trap. #ifdef __clang__ -static_assert(!traps_, "Clang compiles code as is, so there's no trap"); +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_, "MSVC inserts check for zero to trap zero division. " - "It does not insert checks for INT_MIN/-1 division overflow though."); +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 From 167deb4ec8efcf7890def9330851d2745cdd4179 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 16 Nov 2025 11:37:12 +0200 Subject: [PATCH 25/28] Don't trap on promoted uint32_t --- stl/inc/limits | 1 + .../test.compile.pass.cpp | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index c39893639b8..e97fb16359a 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -453,6 +453,7 @@ public: } static constexpr bool is_modulo = true; + static constexpr bool traps = false; static constexpr int digits = 32; static constexpr int digits10 = 9; }; 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 index ee4316c57ae..1f582c5511c 100644 --- 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 @@ -21,15 +21,24 @@ static_assert(traps_, "The hardware does not trap. MSVC inserts check for z #error Unsupported hardware #endif -static_assert(traps_ == traps_ && traps_ == traps_ // - && traps_ == traps_ && traps_ == traps_ - && traps_ == traps_ && traps_ == traps_, +template +constexpr bool promoted_and_traps_if_int_does = std::is_same_v && traps_ == traps_; + +static_assert(promoted_and_traps_if_int_does // + && promoted_and_traps_if_int_does && promoted_and_traps_if_int_does + && promoted_and_traps_if_int_does && promoted_and_traps_if_int_does, "all non-promoted integers should trap or not trap equally"); +template +constexpr bool not_promoted_and_does_not_trap = !std::is_same_v && !traps_; + static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); -static_assert(!traps_ && !traps_ && !traps_ // - && !traps_ && !traps_ && !traps_ && !traps_, +static_assert(not_promoted_and_does_not_trap && not_promoted_and_does_not_trap + && not_promoted_and_does_not_trap // + && not_promoted_and_does_not_trap && not_promoted_and_does_not_trap + && not_promoted_and_does_not_trap && not_promoted_and_does_not_trap + && not_promoted_and_does_not_trap, "promoted integers do not trap for a moot reason; see LWG-554 resolution"); #ifdef __cpp_char8_t From 6780f4c5290954e2f2e995c34b43eae97dde7292 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 16 Nov 2025 11:37:35 +0200 Subject: [PATCH 26/28] elaborate --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 1f582c5511c..c03a492518f 100644 --- 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 @@ -9,7 +9,7 @@ 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"); + "These are translated to STATUS_INTEGER_DIVIDE_BY_ZERO and STATUS_INTEGER_OVERFLOW 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"); From a6936c2d367aa1b0b4cccfb00b949ac0daa2ef57 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 16 Nov 2025 11:44:18 +0200 Subject: [PATCH 27/28] backwards --- .../test.compile.pass.cpp | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) 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 index c03a492518f..e9e899c7728 100644 --- 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 @@ -22,27 +22,29 @@ static_assert(traps_, "The hardware does not trap. MSVC inserts check for z #endif template -constexpr bool promoted_and_traps_if_int_does = std::is_same_v && traps_ == traps_; +constexpr bool non_promoted_and_traps_if_int_does = std::is_same_v && traps_ == traps_; -static_assert(promoted_and_traps_if_int_does // - && promoted_and_traps_if_int_does && promoted_and_traps_if_int_does - && promoted_and_traps_if_int_does && promoted_and_traps_if_int_does, +static_assert(non_promoted_and_traps_if_int_does // + && non_promoted_and_traps_if_int_does && non_promoted_and_traps_if_int_does + && non_promoted_and_traps_if_int_does + && non_promoted_and_traps_if_int_does, "all non-promoted integers should trap or not trap equally"); template -constexpr bool not_promoted_and_does_not_trap = !std::is_same_v && !traps_; +constexpr bool promoted_and_does_not_trap = !std::is_same_v && !traps_; -static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); +static_assert(promoted_and_does_not_trap, "bool does not trap for a moot reason; see LWG-554 resolution"); -static_assert(not_promoted_and_does_not_trap && not_promoted_and_does_not_trap - && not_promoted_and_does_not_trap // - && not_promoted_and_does_not_trap && not_promoted_and_does_not_trap - && not_promoted_and_does_not_trap && not_promoted_and_does_not_trap - && not_promoted_and_does_not_trap, +static_assert(promoted_and_does_not_trap && promoted_and_does_not_trap + && promoted_and_does_not_trap // + && promoted_and_does_not_trap && promoted_and_does_not_trap + && promoted_and_does_not_trap && promoted_and_does_not_trap + && promoted_and_does_not_trap, "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"); +static_assert( + promoted_and_does_not_trap, "promoted integers do not trap for a moot reason; see LWG-554 resolution"); #endif static_assert(!traps_ && !traps_ && !traps_, From 44ef94fb2100c133b177c1cc517693b03b1441f6 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 16 Nov 2025 11:45:45 +0200 Subject: [PATCH 28/28] don't binary negate bool --- .../tests/GH_005816_numeric_limits_traps/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index e9e899c7728..6df0f83a307 100644 --- 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 @@ -33,7 +33,7 @@ static_assert(non_promoted_and_traps_if_int_does // template constexpr bool promoted_and_does_not_trap = !std::is_same_v && !traps_; -static_assert(promoted_and_does_not_trap, "bool does not trap for a moot reason; see LWG-554 resolution"); +static_assert(!traps_, "bool does not trap for a moot reason; see LWG-554 resolution"); static_assert(promoted_and_does_not_trap && promoted_and_does_not_trap && promoted_and_does_not_trap //