From cadf873c83ad7ea7c638e6d98fc5f20752702b03 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 24 Jan 2008 18:59:52 +0000 Subject: [PATCH] Added additional overloaded operators for APSInt to match the operators of APInt. While some operators were already specifically overloaded for APSInt, others resulted in using the overloaded operator methods in APInt, which would result in the signedness bit being lost. Modified the APSInt(APInt&) constructor to be "explicit" and to take an extra (optional) flag to indicate the signedness. Making the ctor explicit will catch any implicit conversations between APSInt -> APInt -> APSInt that results in the signedness flag being lost. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46316 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APSInt.h | 150 +++++++++++++++++++++++++++++++------- 1 file changed, 125 insertions(+), 25 deletions(-) diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 1fc083d9ba6..d08714fda24 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -26,7 +26,9 @@ public: /// APSInt ctor - Create an APSInt with the specified width, default to /// unsigned. explicit APSInt(uint32_t BitWidth) : APInt(BitWidth, 0), IsUnsigned(true) {} - APSInt(const APInt &I) : APInt(I), IsUnsigned(true) {} + + explicit APSInt(const APInt &I, bool isUnsigned = true) + : APInt(I), IsUnsigned(isUnsigned) {} APSInt &operator=(const APSInt &RHS) { APInt::operator=(RHS); @@ -58,6 +60,21 @@ public: return APInt::toString(Radix, isSigned()); } + APSInt& extend(uint32_t width) { + if (IsUnsigned) + zext(width); + else + sext(width); + return *this; + } + + APSInt& extOrTrunc(uint32_t width) { + if (IsUnsigned) + zextOrTrunc(width); + else + sextOrTrunc(width); + return *this; + } const APSInt &operator%=(const APSInt &RHS) { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); @@ -77,36 +94,19 @@ public: } APSInt operator%(const APSInt &RHS) const { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); - return IsUnsigned ? urem(RHS) : srem(RHS); + return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); } APSInt operator/(const APSInt &RHS) const { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); - return IsUnsigned ? udiv(RHS) : sdiv(RHS); - } - - const APSInt &operator>>=(unsigned Amt) { - *this = *this >> Amt; - return *this; - } - - APSInt& extend(uint32_t width) { - if (IsUnsigned) - zext(width); - else - sext(width); - return *this; - } - - APSInt& extOrTrunc(uint32_t width) { - if (IsUnsigned) - zextOrTrunc(width); - else - sextOrTrunc(width); - return *this; + return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); } APSInt operator>>(unsigned Amt) const { - return IsUnsigned ? lshr(Amt) : ashr(Amt); + return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); + } + APSInt& operator>>=(unsigned Amt) { + *this = *this >> Amt; + return *this; } inline bool operator<(const APSInt& RHS) const { @@ -126,6 +126,106 @@ public: return IsUnsigned ? uge(RHS) : sge(RHS); } + // The remaining operators just wrap the logic of APInt, but retain the + // signedness information. + + APSInt operator<<(unsigned Bits) { + return APSInt(static_cast(*this) << Bits, IsUnsigned); + } + APSInt& operator<<=(unsigned Amt) { + *this = *this << Amt; + return *this; + } + + APSInt& operator++() { + static_cast(*this)++; + return *this; + } + APSInt& operator--() { + static_cast(*this)++; + return *this; + } + APSInt operator++(int) { + return APSInt(++static_cast(*this), IsUnsigned); + } + APSInt operator--(int) { + return APSInt(--static_cast(*this), IsUnsigned); + } + APSInt operator-() const { + return APSInt(-static_cast(*this), IsUnsigned); + } + APSInt& operator+=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) += RHS; + return *this; + } + APSInt& operator-=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) -= RHS; + return *this; + } + APSInt& operator*=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) *= RHS; + return *this; + } + APSInt& operator&=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) &= RHS; + return *this; + } + APSInt& operator|=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) |= RHS; + return *this; + } + APSInt& operator^=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) ^= RHS; + return *this; + } + + APSInt operator&(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) & RHS, IsUnsigned); + } + APSInt And(const APSInt& RHS) const { + return this->operator&(RHS); + } + + APSInt operator|(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) | RHS, IsUnsigned); + } + APSInt Or(const APSInt& RHS) const { + return this->operator|(RHS); + } + + + APSInt operator^(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) ^ RHS, IsUnsigned); + } + APSInt Xor(const APSInt& RHS) const { + return this->operator^(RHS); + } + + APSInt operator*(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) * RHS, IsUnsigned); + } + APSInt operator+(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) + RHS, IsUnsigned); + } + APSInt operator-(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) - RHS, IsUnsigned); + } + APSInt operator~() { + return APSInt(~static_cast(*this), IsUnsigned); + } + /// Profile - Used to insert APSInt objects, or objects that contain APSInt /// objects, into FoldingSets. void Profile(FoldingSetNodeID& ID) const;