From 81d41f811a1bb11bd1246169726da781f3a0a4e8 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 15 Oct 2024 09:33:44 +0200 Subject: [PATCH] [APInt] Fix getAllOnes() with zero width (#112227) This makes sure that APInt::getAllOnes() keeps working after the APInt constructor assertions are enabled. I'm relaxing the requirement for the signed case to either an all zeros or all ones integer. This is basically saying that we can interpret the zero-width integer as either positive or negative. --- llvm/include/llvm/ADT/APInt.h | 21 ++++++++++++++------- llvm/unittests/ADT/APIntTest.cpp | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index a42dae8887392d3..63a138527b32e12 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -112,14 +112,21 @@ class [[nodiscard]] APInt { bool implicitTrunc = true) : BitWidth(numBits) { if (!implicitTrunc) { - if (BitWidth == 0) { - assert(val == 0 && "Value must be zero for 0-bit APInt"); - } else if (isSigned) { - assert(llvm::isIntN(BitWidth, val) && - "Value is not an N-bit signed value"); + if (isSigned) { + if (BitWidth == 0) { + assert((val == 0 || val == uint64_t(-1)) && + "Value must be 0 or -1 for signed 0-bit APInt"); + } else { + assert(llvm::isIntN(BitWidth, val) && + "Value is not an N-bit signed value"); + } } else { - assert(llvm::isUIntN(BitWidth, val) && - "Value is not an N-bit unsigned value"); + if (BitWidth == 0) { + assert(val == 0 && "Value must be zero for unsigned 0-bit APInt"); + } else { + assert(llvm::isUIntN(BitWidth, val) && + "Value is not an N-bit unsigned value"); + } } } if (isSingleWord()) { diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 7a9ac5562e77224..4d5553fcbd1e3fb 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -3423,6 +3423,7 @@ TEST(APIntTest, ZeroWidth) { EXPECT_EQ(0U, ZW.getBitWidth()); EXPECT_EQ(0U, APInt(0, ArrayRef({0, 1, 2})).getBitWidth()); EXPECT_EQ(0U, APInt(0, "0", 10).getBitWidth()); + EXPECT_EQ(0U, APInt::getAllOnes(0).getBitWidth()); // Default constructor is single bit wide. EXPECT_EQ(1U, APInt().getBitWidth());