aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/Interp/Integral.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Interp/Integral.h')
-rw-r--r--clang/lib/AST/Interp/Integral.h126
1 files changed, 74 insertions, 52 deletions
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 46cd611ee389..8a742333ae57 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -53,17 +53,17 @@ template <> struct Repr<64, true> { using Type = int64_t; };
/// These wrappers are required to shared an interface between APSint and
/// builtin primitive numeral types, while optimising for storage and
/// allowing methods operating on primitive type to compile to fast code.
-template <unsigned Bits, bool Signed> class Integral {
+template <unsigned Bits, bool Signed> class Integral final {
private:
template <unsigned OtherBits, bool OtherSigned> friend class Integral;
// The primitive representing the integral.
- using T = typename Repr<Bits, Signed>::Type;
- T V;
+ using ReprT = typename Repr<Bits, Signed>::Type;
+ ReprT V;
/// Primitive representing limits.
- static const auto Min = std::numeric_limits<T>::min();
- static const auto Max = std::numeric_limits<T>::max();
+ static const auto Min = std::numeric_limits<ReprT>::min();
+ static const auto Max = std::numeric_limits<ReprT>::max();
/// Construct an integral from anything that is convertible to storage.
template <typename T> explicit Integral(T V) : V(V) {}
@@ -107,7 +107,7 @@ public:
return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed);
}
APSInt toAPSInt(unsigned NumBits) const {
- if (Signed)
+ if constexpr (Signed)
return APSInt(toAPSInt().sextOrTrunc(NumBits), !Signed);
else
return APSInt(toAPSInt().zextOrTrunc(NumBits), !Signed);
@@ -124,25 +124,27 @@ public:
bool isMin() const { return *this == min(bitWidth()); }
- bool isMinusOne() const { return Signed && V == T(-1); }
+ bool isMinusOne() const { return Signed && V == ReprT(-1); }
constexpr static bool isSigned() { return Signed; }
- bool isNegative() const { return V < T(0); }
+ bool isNegative() const { return V < ReprT(0); }
bool isPositive() const { return !isNegative(); }
ComparisonCategoryResult compare(const Integral &RHS) const {
return Compare(V, RHS.V);
}
- unsigned countLeadingZeros() const { return llvm::countLeadingZeros<T>(V); }
+ unsigned countLeadingZeros() const {
+ return llvm::countLeadingZeros<ReprT>(V);
+ }
Integral truncate(unsigned TruncBits) const {
if (TruncBits >= Bits)
return *this;
- const T BitMask = (T(1) << T(TruncBits)) - 1;
- const T SignBit = T(1) << (TruncBits - 1);
- const T ExtMask = ~BitMask;
+ const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1;
+ const ReprT SignBit = ReprT(1) << (TruncBits - 1);
+ const ReprT ExtMask = ~BitMask;
return Integral((V & BitMask) | (Signed && (V & SignBit) ? ExtMask : 0));
}
@@ -155,9 +157,11 @@ public:
return Integral(Max);
}
- template <typename T>
- static std::enable_if_t<std::is_integral<T>::value, Integral> from(T Value) {
- return Integral(Value);
+ template <typename ValT> static Integral from(ValT Value) {
+ if constexpr (std::is_integral<ValT>::value)
+ return Integral(Value);
+ else
+ return Integral::from(static_cast<Integral::ReprT>(Value));
}
template <unsigned SrcBits, bool SrcSign>
@@ -167,7 +171,7 @@ public:
}
template <bool SrcSign> static Integral from(Integral<0, SrcSign> Value) {
- if (SrcSign)
+ if constexpr (SrcSign)
return Integral(Value.V.getSExtValue());
else
return Integral(Value.V.getZExtValue());
@@ -180,15 +184,15 @@ public:
}
static bool inRange(int64_t Value, unsigned NumBits) {
- return CheckRange<T, Min, Max>(Value);
+ return CheckRange<ReprT, Min, Max>(Value);
}
static bool increment(Integral A, Integral *R) {
- return add(A, Integral(T(1)), A.bitWidth(), R);
+ return add(A, Integral(ReprT(1)), A.bitWidth(), R);
}
static bool decrement(Integral A, Integral *R) {
- return sub(A, Integral(T(1)), A.bitWidth(), R);
+ return sub(A, Integral(ReprT(1)), A.bitWidth(), R);
}
static bool add(Integral A, Integral B, unsigned OpBits, Integral *R) {
@@ -203,56 +207,74 @@ public:
return CheckMulUB(A.V, B.V, R->V);
}
-private:
- template <typename T>
- static std::enable_if_t<std::is_signed<T>::value, bool> CheckAddUB(T A, T B,
- T &R) {
- return llvm::AddOverflow<T>(A, B, R);
+ static bool rem(Integral A, Integral B, unsigned OpBits, Integral *R) {
+ *R = Integral(A.V % B.V);
+ return false;
+ }
+
+ static bool div(Integral A, Integral B, unsigned OpBits, Integral *R) {
+ *R = Integral(A.V / B.V);
+ return false;
}
- template <typename T>
- static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckAddUB(T A, T B,
- T &R) {
- R = A + B;
+ static bool bitAnd(Integral A, Integral B, unsigned OpBits, Integral *R) {
+ *R = Integral(A.V & B.V);
return false;
}
- template <typename T>
- static std::enable_if_t<std::is_signed<T>::value, bool> CheckSubUB(T A, T B,
- T &R) {
- return llvm::SubOverflow<T>(A, B, R);
+ static bool bitOr(Integral A, Integral B, unsigned OpBits, Integral *R) {
+ *R = Integral(A.V | B.V);
+ return false;
}
- template <typename T>
- static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckSubUB(T A, T B,
- T &R) {
- R = A - B;
+ static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R) {
+ *R = Integral(A.V ^ B.V);
return false;
}
- template <typename T>
- static std::enable_if_t<std::is_signed<T>::value, bool> CheckMulUB(T A, T B,
- T &R) {
- return llvm::MulOverflow<T>(A, B, R);
+ static bool neg(Integral A, Integral *R) {
+ *R = -A;
+ return false;
}
- template <typename T>
- static std::enable_if_t<std::is_unsigned<T>::value, bool> CheckMulUB(T A, T B,
- T &R) {
- R = A * B;
+ static bool comp(Integral A, Integral *R) {
+ *R = Integral(~A.V);
return false;
}
- template <typename T, T Min, T Max>
- static std::enable_if_t<std::is_signed<T>::value, bool>
- CheckRange(int64_t V) {
- return Min <= V && V <= Max;
+private:
+ template <typename T> static bool CheckAddUB(T A, T B, T &R) {
+ if constexpr (std::is_signed_v<T>) {
+ return llvm::AddOverflow<T>(A, B, R);
+ } else {
+ R = A + B;
+ return false;
+ }
}
- template <typename T, T Min, T Max>
- static std::enable_if_t<std::is_unsigned<T>::value, bool>
- CheckRange(int64_t V) {
- return V >= 0 && static_cast<uint64_t>(V) <= Max;
+ template <typename T> static bool CheckSubUB(T A, T B, T &R) {
+ if constexpr (std::is_signed_v<T>) {
+ return llvm::SubOverflow<T>(A, B, R);
+ } else {
+ R = A - B;
+ return false;
+ }
+ }
+
+ template <typename T> static bool CheckMulUB(T A, T B, T &R) {
+ if constexpr (std::is_signed_v<T>) {
+ return llvm::MulOverflow<T>(A, B, R);
+ } else {
+ R = A * B;
+ return false;
+ }
+ }
+ template <typename T, T Min, T Max> static bool CheckRange(int64_t V) {
+ if constexpr (std::is_signed_v<T>) {
+ return Min <= V && V <= Max;
+ } else {
+ return V >= 0 && static_cast<uint64_t>(V) <= Max;
+ }
}
};