Timm =?utf-8?q?Bäder?= <tbae...@redhat.com> Message-ID: <llvm/llvm-project/pull/67961/cl...@github.com> In-Reply-To:
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/67961 Before this patch, we would run into an assertion in `APInt::get{S,Z}ExtValue()` because the `AllOnes` value had more than 64 active bits. >From 80bd890c332654458014c4acc20709b9cbb6eb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Sun, 1 Oct 2023 19:57:03 +0200 Subject: [PATCH 1/2] [clang][Interp] Implement IntegralAP::comp --- clang/lib/AST/Interp/IntegralAP.h | 1 - clang/test/AST/Interp/literals.cpp | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index b2b367f30c238fe..b29aac2a73e3243 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -210,7 +210,6 @@ template <bool Signed> class IntegralAP final { } static bool comp(IntegralAP A, IntegralAP *R) { - assert(false); *R = IntegralAP(~A.V); return false; } diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index eca0e4c2cbd26f1..00182ba4ab1d918 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -52,6 +52,9 @@ namespace i128 { constexpr int128_t Two = (int128_t)1 << 1ul; static_assert(Two == 2, ""); + constexpr uint128_t AllOnes = ~static_cast<uint128_t>(0); + static_assert(AllOnes == static_cast<uint128_t>(-1), ""); + #if __cplusplus >= 201402L template <typename T> constexpr T CastFrom(__int128_t A) { >From 31ed85d44562ed1e5fe4714a5b659e5da8720f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 2 Oct 2023 10:46:22 +0200 Subject: [PATCH 2/2] [clang][Interp] Fix value truncation when casting int128 to smaller size --- clang/lib/AST/Interp/IntegralAP.h | 21 +++++++++++++-------- clang/test/AST/Interp/literals.cpp | 8 +++++++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index b29aac2a73e3243..f67b15dbc9b31ac 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -55,14 +55,14 @@ template <bool Signed> class IntegralAP final { bool operator<=(IntegralAP RHS) const { return V <= RHS.V; } explicit operator bool() const { return !V.isZero(); } - explicit operator int8_t() const { return V.getSExtValue(); } - explicit operator uint8_t() const { return V.getZExtValue(); } - explicit operator int16_t() const { return V.getSExtValue(); } - explicit operator uint16_t() const { return V.getZExtValue(); } - explicit operator int32_t() const { return V.getSExtValue(); } - explicit operator uint32_t() const { return V.getZExtValue(); } - explicit operator int64_t() const { return V.getSExtValue(); } - explicit operator uint64_t() const { return V.getZExtValue(); } + explicit operator int8_t() const { return truncateCast<int8_t>(V); } + explicit operator uint8_t() const { return truncateCast<uint8_t>(V); } + explicit operator int16_t() const { return truncateCast<int16_t>(V); } + explicit operator uint16_t() const { return truncateCast<uint16_t>(V); } + explicit operator int32_t() const { return truncateCast<int32_t>(V); } + explicit operator uint32_t() const { return truncateCast<uint32_t>(V); } + explicit operator int64_t() const { return truncateCast<int64_t>(V); } + explicit operator uint64_t() const { return truncateCast<uint64_t>(V); } template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) { assert(NumBits > 0); @@ -248,6 +248,11 @@ template <bool Signed> class IntegralAP final { R->V = A.V - B.V; return false; // Success! } + + template <typename T> static T truncateCast(const APSInt &V) { + return std::is_signed_v<T> ? V.trunc(sizeof(T) * 8).getSExtValue() + : V.trunc(sizeof(T) * 8).getZExtValue(); + } }; template <bool Signed> diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 00182ba4ab1d918..65d211422ddac92 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -53,7 +53,7 @@ namespace i128 { static_assert(Two == 2, ""); constexpr uint128_t AllOnes = ~static_cast<uint128_t>(0); - static_assert(AllOnes == static_cast<uint128_t>(-1), ""); + static_assert(AllOnes == UINT128_MAX, ""); #if __cplusplus >= 201402L template <typename T> @@ -70,6 +70,12 @@ namespace i128 { static_assert(CastFrom<double>(12) == 12, ""); static_assert(CastFrom<long double>(12) == 12, ""); + static_assert(CastFrom<char>(AllOnes) == -1, ""); + static_assert(CastFrom<unsigned char>(AllOnes) == 0xFF, ""); + static_assert(CastFrom<long>(AllOnes) == -1, ""); + static_assert(CastFrom<unsigned short>(AllOnes) == 0xFFFF, ""); + static_assert(CastFrom<int>(AllOnes) == -1, ""); + template <typename T> constexpr __int128 CastTo(T A) { int128_t B = (int128_t)A; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits