[clang] [clang][Interp] Fix value truncation when casting int128 to smaller size (PR #67961)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 2 08:42:19 PDT 2023
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/67961
>From 377e0b069ff0d68ff4a4cdd690b62e555bdf8d8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 2 Oct 2023 10:46:22 +0200
Subject: [PATCH] [clang][Interp] Fix value truncation when casting int128 to
smaller size
---
clang/lib/AST/Interp/IntegralAP.h | 22 ++++++++++++++--------
clang/test/AST/Interp/literals.cpp | 10 +++++++++-
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h
index 42f44354cbd2599..0876d7fae958a54 100644
--- a/clang/lib/AST/Interp/IntegralAP.h
+++ b/clang/lib/AST/Interp/IntegralAP.h
@@ -32,6 +32,12 @@ template <unsigned Bits, bool Signed> class Integral;
class Boolean;
template <bool Signed> class IntegralAP final {
+private:
+ 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();
+ }
+
public:
APSInt V;
@@ -55,14 +61,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);
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 00182ba4ab1d918..00875bcf44dc8e6 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,14 @@ 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, "");
+ static_assert(CastFrom<int128_t>(AllOnes) == -1, "");
+ static_assert(CastFrom<uint128_t>(AllOnes) == AllOnes, "");
+
template <typename T>
constexpr __int128 CastTo(T A) {
int128_t B = (int128_t)A;
More information about the cfe-commits
mailing list