CheckedArithmetic: llvm::Optional => std::optional
This commit is contained in:
parent
4b1b9e22b3
commit
3dfacc0a56
|
@ -560,7 +560,7 @@ uint64_t EmulateInstructionARM64::
|
||||||
AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in,
|
AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in,
|
||||||
EmulateInstructionARM64::ProcState &proc_state) {
|
EmulateInstructionARM64::ProcState &proc_state) {
|
||||||
uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
|
uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
|
||||||
llvm::Optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y));
|
std::optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y));
|
||||||
bool overflow = !signed_sum;
|
bool overflow = !signed_sum;
|
||||||
if (!overflow)
|
if (!overflow)
|
||||||
overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in));
|
overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in));
|
||||||
|
|
|
@ -641,7 +641,7 @@ public:
|
||||||
/// \returns false if the instruction doesn't belong to the group.
|
/// \returns false if the instruction doesn't belong to the group.
|
||||||
bool insertMember(InstTy *Instr, int32_t Index, Align NewAlign) {
|
bool insertMember(InstTy *Instr, int32_t Index, Align NewAlign) {
|
||||||
// Make sure the key fits in an int32_t.
|
// Make sure the key fits in an int32_t.
|
||||||
Optional<int32_t> MaybeKey = checkedAdd(Index, SmallestKey);
|
std::optional<int32_t> MaybeKey = checkedAdd(Index, SmallestKey);
|
||||||
if (!MaybeKey)
|
if (!MaybeKey)
|
||||||
return false;
|
return false;
|
||||||
int32_t Key = *MaybeKey;
|
int32_t Key = *MaybeKey;
|
||||||
|
@ -664,7 +664,7 @@ public:
|
||||||
} else if (Key < SmallestKey) {
|
} else if (Key < SmallestKey) {
|
||||||
|
|
||||||
// Make sure the largest index fits in an int32_t.
|
// Make sure the largest index fits in an int32_t.
|
||||||
Optional<int32_t> MaybeLargestIndex = checkedSub(LargestKey, Key);
|
std::optional<int32_t> MaybeLargestIndex = checkedSub(LargestKey, Key);
|
||||||
if (!MaybeLargestIndex)
|
if (!MaybeLargestIndex)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
#define LLVM_SUPPORT_CHECKEDARITHMETIC_H
|
#define LLVM_SUPPORT_CHECKEDARITHMETIC_H
|
||||||
|
|
||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -26,7 +26,7 @@ namespace {
|
||||||
/// \return Empty optional if the operation overflows, or result otherwise.
|
/// \return Empty optional if the operation overflows, or result otherwise.
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
std::enable_if_t<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
|
std::enable_if_t<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
|
||||||
llvm::Optional<T>>
|
std::optional<T>>
|
||||||
checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
|
checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
|
||||||
llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
|
llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
|
||||||
llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
|
llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
|
||||||
|
@ -44,7 +44,7 @@ namespace llvm {
|
||||||
/// \return Optional of sum if no signed overflow occurred,
|
/// \return Optional of sum if no signed overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
|
||||||
checkedAdd(T LHS, T RHS) {
|
checkedAdd(T LHS, T RHS) {
|
||||||
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
|
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ checkedAdd(T LHS, T RHS) {
|
||||||
/// \return Optional of sum if no signed overflow occurred,
|
/// \return Optional of sum if no signed overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
|
||||||
checkedSub(T LHS, T RHS) {
|
checkedSub(T LHS, T RHS) {
|
||||||
return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
|
return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ checkedSub(T LHS, T RHS) {
|
||||||
/// \return Optional of product if no signed overflow occurred,
|
/// \return Optional of product if no signed overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
|
||||||
checkedMul(T LHS, T RHS) {
|
checkedMul(T LHS, T RHS) {
|
||||||
return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
|
return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ checkedMul(T LHS, T RHS) {
|
||||||
/// \return Optional of result if no signed overflow occurred,
|
/// \return Optional of result if no signed overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_signed<T>::value, std::optional<T>>
|
||||||
checkedMulAdd(T A, T B, T C) {
|
checkedMulAdd(T A, T B, T C) {
|
||||||
if (auto Product = checkedMul(A, B))
|
if (auto Product = checkedMul(A, B))
|
||||||
return checkedAdd(*Product, C);
|
return checkedAdd(*Product, C);
|
||||||
|
@ -82,7 +82,7 @@ checkedMulAdd(T A, T B, T C) {
|
||||||
/// \return Optional of sum if no unsigned overflow occurred,
|
/// \return Optional of sum if no unsigned overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
|
||||||
checkedAddUnsigned(T LHS, T RHS) {
|
checkedAddUnsigned(T LHS, T RHS) {
|
||||||
return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
|
return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ checkedAddUnsigned(T LHS, T RHS) {
|
||||||
/// \return Optional of product if no unsigned overflow occurred,
|
/// \return Optional of product if no unsigned overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
|
||||||
checkedMulUnsigned(T LHS, T RHS) {
|
checkedMulUnsigned(T LHS, T RHS) {
|
||||||
return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
|
return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ checkedMulUnsigned(T LHS, T RHS) {
|
||||||
/// \return Optional of result if no unsigned overflow occurred,
|
/// \return Optional of result if no unsigned overflow occurred,
|
||||||
/// \c None otherwise.
|
/// \c None otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
|
std::enable_if_t<std::is_unsigned<T>::value, std::optional<T>>
|
||||||
checkedMulAddUnsigned(T A, T B, T C) {
|
checkedMulAddUnsigned(T A, T B, T C) {
|
||||||
if (auto Product = checkedMulUnsigned(A, B))
|
if (auto Product = checkedMulUnsigned(A, B))
|
||||||
return checkedAddUnsigned(*Product, C);
|
return checkedAddUnsigned(*Product, C);
|
||||||
|
|
|
@ -206,7 +206,7 @@ Expected<ExpressionValue> llvm::operator+(const ExpressionValue &LeftOperand,
|
||||||
if (LeftOperand.isNegative() && RightOperand.isNegative()) {
|
if (LeftOperand.isNegative() && RightOperand.isNegative()) {
|
||||||
int64_t LeftValue = cantFail(LeftOperand.getSignedValue());
|
int64_t LeftValue = cantFail(LeftOperand.getSignedValue());
|
||||||
int64_t RightValue = cantFail(RightOperand.getSignedValue());
|
int64_t RightValue = cantFail(RightOperand.getSignedValue());
|
||||||
Optional<int64_t> Result = checkedAdd<int64_t>(LeftValue, RightValue);
|
std::optional<int64_t> Result = checkedAdd<int64_t>(LeftValue, RightValue);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
return make_error<OverflowError>();
|
return make_error<OverflowError>();
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ Expected<ExpressionValue> llvm::operator+(const ExpressionValue &LeftOperand,
|
||||||
// Both values are positive at this point.
|
// Both values are positive at this point.
|
||||||
uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue());
|
uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue());
|
||||||
uint64_t RightValue = cantFail(RightOperand.getUnsignedValue());
|
uint64_t RightValue = cantFail(RightOperand.getUnsignedValue());
|
||||||
Optional<uint64_t> Result =
|
std::optional<uint64_t> Result =
|
||||||
checkedAddUnsigned<uint64_t>(LeftValue, RightValue);
|
checkedAddUnsigned<uint64_t>(LeftValue, RightValue);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
return make_error<OverflowError>();
|
return make_error<OverflowError>();
|
||||||
|
@ -241,7 +241,7 @@ Expected<ExpressionValue> llvm::operator-(const ExpressionValue &LeftOperand,
|
||||||
// Result <= -1 - (max int64_t) which overflows on 1- and 2-complement.
|
// Result <= -1 - (max int64_t) which overflows on 1- and 2-complement.
|
||||||
if (RightValue > (uint64_t)std::numeric_limits<int64_t>::max())
|
if (RightValue > (uint64_t)std::numeric_limits<int64_t>::max())
|
||||||
return make_error<OverflowError>();
|
return make_error<OverflowError>();
|
||||||
Optional<int64_t> Result =
|
std::optional<int64_t> Result =
|
||||||
checkedSub(LeftValue, static_cast<int64_t>(RightValue));
|
checkedSub(LeftValue, static_cast<int64_t>(RightValue));
|
||||||
if (!Result)
|
if (!Result)
|
||||||
return make_error<OverflowError>();
|
return make_error<OverflowError>();
|
||||||
|
@ -306,7 +306,7 @@ Expected<ExpressionValue> llvm::operator*(const ExpressionValue &LeftOperand,
|
||||||
// Result will be positive and can overflow.
|
// Result will be positive and can overflow.
|
||||||
uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue());
|
uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue());
|
||||||
uint64_t RightValue = cantFail(RightOperand.getUnsignedValue());
|
uint64_t RightValue = cantFail(RightOperand.getUnsignedValue());
|
||||||
Optional<uint64_t> Result =
|
std::optional<uint64_t> Result =
|
||||||
checkedMulUnsigned<uint64_t>(LeftValue, RightValue);
|
checkedMulUnsigned<uint64_t>(LeftValue, RightValue);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
return make_error<OverflowError>();
|
return make_error<OverflowError>();
|
||||||
|
|
|
@ -11,7 +11,7 @@ TEST(CheckedArithmetic, CheckedAdd) {
|
||||||
EXPECT_EQ(checkedAdd<int64_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedAdd<int64_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int64_t>(Min, -1), std::nullopt);
|
EXPECT_EQ(checkedAdd<int64_t>(Min, -1), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int64_t>(Max, 1), std::nullopt);
|
EXPECT_EQ(checkedAdd<int64_t>(Max, 1), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int64_t>(10, 1), Optional<int64_t>(11));
|
EXPECT_EQ(checkedAdd<int64_t>(10, 1), std::optional<int64_t>(11));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedAddSmall) {
|
TEST(CheckedArithmetic, CheckedAddSmall) {
|
||||||
|
@ -20,7 +20,7 @@ TEST(CheckedArithmetic, CheckedAddSmall) {
|
||||||
EXPECT_EQ(checkedAdd<int16_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedAdd<int16_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int16_t>(Min, -1), std::nullopt);
|
EXPECT_EQ(checkedAdd<int16_t>(Min, -1), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int16_t>(Max, 1), std::nullopt);
|
EXPECT_EQ(checkedAdd<int16_t>(Max, 1), std::nullopt);
|
||||||
EXPECT_EQ(checkedAdd<int16_t>(10, 1), Optional<int64_t>(11));
|
EXPECT_EQ(checkedAdd<int16_t>(10, 1), std::optional<int64_t>(11));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMul) {
|
TEST(CheckedArithmetic, CheckedMul) {
|
||||||
|
@ -29,7 +29,7 @@ TEST(CheckedArithmetic, CheckedMul) {
|
||||||
EXPECT_EQ(checkedMul<int64_t>(Max, 2), std::nullopt);
|
EXPECT_EQ(checkedMul<int64_t>(Max, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int64_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedMul<int64_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int64_t>(Min, 2), std::nullopt);
|
EXPECT_EQ(checkedMul<int64_t>(Min, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int64_t>(10, 2), Optional<int64_t>(20));
|
EXPECT_EQ(checkedMul<int64_t>(10, 2), std::optional<int64_t>(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMulAdd) {
|
TEST(CheckedArithmetic, CheckedMulAdd) {
|
||||||
|
@ -38,7 +38,7 @@ TEST(CheckedArithmetic, CheckedMulAdd) {
|
||||||
EXPECT_EQ(checkedMulAdd<int64_t>(Max, 1, 2), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int64_t>(Max, 1, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int64_t>(1, 1, Max), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int64_t>(1, 1, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int64_t>(1, -1, Min), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int64_t>(1, -1, Min), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int64_t>(10, 2, 3), Optional<int64_t>(23));
|
EXPECT_EQ(checkedMulAdd<int64_t>(10, 2, 3), std::optional<int64_t>(23));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMulSmall) {
|
TEST(CheckedArithmetic, CheckedMulSmall) {
|
||||||
|
@ -47,7 +47,7 @@ TEST(CheckedArithmetic, CheckedMulSmall) {
|
||||||
EXPECT_EQ(checkedMul<int16_t>(Max, 2), std::nullopt);
|
EXPECT_EQ(checkedMul<int16_t>(Max, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int16_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedMul<int16_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int16_t>(Min, 2), std::nullopt);
|
EXPECT_EQ(checkedMul<int16_t>(Min, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMul<int16_t>(10, 2), Optional<int16_t>(20));
|
EXPECT_EQ(checkedMul<int16_t>(10, 2), std::optional<int16_t>(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMulAddSmall) {
|
TEST(CheckedArithmetic, CheckedMulAddSmall) {
|
||||||
|
@ -56,28 +56,28 @@ TEST(CheckedArithmetic, CheckedMulAddSmall) {
|
||||||
EXPECT_EQ(checkedMulAdd<int16_t>(Max, 1, 2), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int16_t>(Max, 1, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int16_t>(1, 1, Max), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int16_t>(1, 1, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int16_t>(1, -1, Min), std::nullopt);
|
EXPECT_EQ(checkedMulAdd<int16_t>(1, -1, Min), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAdd<int16_t>(10, 2, 3), Optional<int16_t>(23));
|
EXPECT_EQ(checkedMulAdd<int16_t>(10, 2, 3), std::optional<int16_t>(23));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedAddUnsigned) {
|
TEST(CheckedArithmetic, CheckedAddUnsigned) {
|
||||||
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
||||||
EXPECT_EQ(checkedAddUnsigned<uint64_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedAddUnsigned<uint64_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedAddUnsigned<uint64_t>(Max, 1), std::nullopt);
|
EXPECT_EQ(checkedAddUnsigned<uint64_t>(Max, 1), std::nullopt);
|
||||||
EXPECT_EQ(checkedAddUnsigned<uint64_t>(10, 1), Optional<uint64_t>(11));
|
EXPECT_EQ(checkedAddUnsigned<uint64_t>(10, 1), std::optional<uint64_t>(11));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMulUnsigned) {
|
TEST(CheckedArithmetic, CheckedMulUnsigned) {
|
||||||
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
||||||
EXPECT_EQ(checkedMulUnsigned<uint64_t>(Max, 2), std::nullopt);
|
EXPECT_EQ(checkedMulUnsigned<uint64_t>(Max, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulUnsigned<uint64_t>(Max, Max), std::nullopt);
|
EXPECT_EQ(checkedMulUnsigned<uint64_t>(Max, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulUnsigned<uint64_t>(10, 2), Optional<uint64_t>(20));
|
EXPECT_EQ(checkedMulUnsigned<uint64_t>(10, 2), std::optional<uint64_t>(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CheckedArithmetic, CheckedMulAddUnsigned) {
|
TEST(CheckedArithmetic, CheckedMulAddUnsigned) {
|
||||||
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
const uint64_t Max = std::numeric_limits<uint64_t>::max();
|
||||||
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(Max, 1, 2), std::nullopt);
|
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(Max, 1, 2), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(1, 1, Max), std::nullopt);
|
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(1, 1, Max), std::nullopt);
|
||||||
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(10, 2, 3), Optional<uint64_t>(23));
|
EXPECT_EQ(checkedMulAddUnsigned<uint64_t>(10, 2, 3), std::optional<uint64_t>(23));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue