Index: llvm/trunk/include/llvm/Support/CheckedArithmetic.h =================================================================== --- llvm/trunk/include/llvm/Support/CheckedArithmetic.h +++ llvm/trunk/include/llvm/Support/CheckedArithmetic.h @@ -16,66 +16,61 @@ #define LLVM_SUPPORT_CHECKEDARITHMETIC_H #include "llvm/ADT/APInt.h" +#include "llvm/ADT/Optional.h" #include namespace { /// Utility function to apply a given method of \c APInt \p F to \p LHS and -/// \p RHS, and write the output into \p Res. -/// \return Whether the operation overflows. +/// \p RHS. +/// \return Empty optional if the operation overflows, or result otherwise. template typename std::enable_if::value && sizeof(T) * 8 <= 64, - bool>::type -checkedOp(T LHS, T RHS, F Op, T *Res = nullptr, bool Signed = true) { + llvm::Optional>::type +checkedOp(T LHS, T RHS, F Op, bool Signed = true) { llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed); llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed); bool Overflow; llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow); - if (Res) - *Res = Signed ? Out.getSExtValue() : Out.getZExtValue(); - return Overflow; + if (Overflow) + return llvm::None; + return Signed ? Out.getSExtValue() : Out.getZExtValue(); } } namespace llvm { -/// Add two signed integers \p LHS and \p RHS, write into \p Res if non-null. -/// Does not guarantee saturating arithmetic. -/// \return Whether the result overflows. +/// Add two signed integers \p LHS and \p RHS, return wrapped result if +/// available. template -typename std::enable_if::value, bool>::type -checkedAdd(T LHS, T RHS, T *Res = nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov, Res); +typename std::enable_if::value, llvm::Optional>::type +checkedAdd(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov); } -/// Multiply two signed integers \p LHS and \p RHS, write into \p Res if -/// non-null. -/// Does not guarantee saturating arithmetic. -/// \return Whether the result overflows. +/// Multiply two signed integers \p LHS and \p RHS, return wrapped result +/// if available. template -typename std::enable_if::value, bool>::type -checkedMul(T LHS, T RHS, T *Res = nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::smul_ov, Res); +typename std::enable_if::value, llvm::Optional>::type +checkedMul(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::smul_ov); } -/// Add two unsigned integers \p LHS and \p RHS, write into \p Res if non-null. -/// Does not guarantee saturating arithmetic. -/// \return Whether the result overflows. +/// Add two unsigned integers \p LHS and \p RHS, return wrapped result +/// if available. template -typename std::enable_if::value, bool>::type -checkedAddUnsigned(T LHS, T RHS, T *Res = nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, Res, /*Signed=*/false); +typename std::enable_if::value, llvm::Optional>::type +checkedAddUnsigned(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false); } -/// Multiply two unsigned integers \p LHS and \p RHS, write into \p Res if -/// non-null. -/// Does not guarantee saturating arithmetic. -/// \return Whether the result overflows. +/// Multiply two unsigned integers \p LHS and \p RHS, return wrapped result +/// if available. template -typename std::enable_if::value, bool>::type -checkedMulUnsigned(T LHS, T RHS, T *Res = nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, Res, /*Signed=*/false); +typename std::enable_if::value, llvm::Optional>::type +checkedMulUnsigned(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false); } } // End llvm namespace Index: llvm/trunk/unittests/Support/CheckedArithmeticTest.cpp =================================================================== --- llvm/trunk/unittests/Support/CheckedArithmeticTest.cpp +++ llvm/trunk/unittests/Support/CheckedArithmeticTest.cpp @@ -6,65 +6,53 @@ namespace { TEST(CheckedArithmetic, CheckedAdd) { - int64_t Out; const int64_t Max = std::numeric_limits::max(); const int64_t Min = std::numeric_limits::min(); - EXPECT_EQ(checkedAdd(Max, Max, &Out), true); - EXPECT_EQ(checkedAdd(Min, -1, &Out), true); - EXPECT_EQ(checkedAdd(Max, 1, &Out), true); - EXPECT_EQ(checkedAdd(10, 1, &Out), false); - EXPECT_EQ(Out, 11); + EXPECT_EQ(checkedAdd(Max, Max), None); + EXPECT_EQ(checkedAdd(Min, -1), None); + EXPECT_EQ(checkedAdd(Max, 1), None); + EXPECT_EQ(checkedAdd(10, 1), Optional(11)); } TEST(CheckedArithmetic, CheckedAddSmall) { - int16_t Out; const int16_t Max = std::numeric_limits::max(); const int16_t Min = std::numeric_limits::min(); - EXPECT_EQ(checkedAdd(Max, Max, &Out), true); - EXPECT_EQ(checkedAdd(Min, -1, &Out), true); - EXPECT_EQ(checkedAdd(Max, 1, &Out), true); - EXPECT_EQ(checkedAdd(10, 1, &Out), false); - EXPECT_EQ(Out, 11); + EXPECT_EQ(checkedAdd(Max, Max), None); + EXPECT_EQ(checkedAdd(Min, -1), None); + EXPECT_EQ(checkedAdd(Max, 1), None); + EXPECT_EQ(checkedAdd(10, 1), Optional(11)); } TEST(CheckedArithmetic, CheckedMul) { - int64_t Out; const int64_t Max = std::numeric_limits::max(); const int64_t Min = std::numeric_limits::min(); - EXPECT_EQ(checkedMul(Max, 2, &Out), true); - EXPECT_EQ(checkedMul(Max, Max, &Out), true); - EXPECT_EQ(checkedMul(Min, 2, &Out), true); - EXPECT_EQ(checkedMul(10, 2, &Out), false); - EXPECT_EQ(Out, 20); + EXPECT_EQ(checkedMul(Max, 2), None); + EXPECT_EQ(checkedMul(Max, Max), None); + EXPECT_EQ(checkedMul(Min, 2), None); + EXPECT_EQ(checkedMul(10, 2), Optional(20)); } TEST(CheckedArithmetic, CheckedMulSmall) { - int16_t Out; const int16_t Max = std::numeric_limits::max(); const int16_t Min = std::numeric_limits::min(); - EXPECT_EQ(checkedMul(Max, 2, &Out), true); - EXPECT_EQ(checkedMul(Max, Max, &Out), true); - EXPECT_EQ(checkedMul(Min, 2, &Out), true); - EXPECT_EQ(checkedMul(10, 2, &Out), false); - EXPECT_EQ(Out, 20); + EXPECT_EQ(checkedMul(Max, 2), None); + EXPECT_EQ(checkedMul(Max, Max), None); + EXPECT_EQ(checkedMul(Min, 2), None); + EXPECT_EQ(checkedMul(10, 2), Optional(20)); } TEST(CheckedArithmetic, CheckedAddUnsigned) { - uint64_t Out; const uint64_t Max = std::numeric_limits::max(); - EXPECT_EQ(checkedAddUnsigned(Max, Max, &Out), true); - EXPECT_EQ(checkedAddUnsigned(Max, 1, &Out), true); - EXPECT_EQ(checkedAddUnsigned(10, 1, &Out), false); - EXPECT_EQ(Out, uint64_t(11)); + EXPECT_EQ(checkedAddUnsigned(Max, Max), None); + EXPECT_EQ(checkedAddUnsigned(Max, 1), None); + EXPECT_EQ(checkedAddUnsigned(10, 1), Optional(11)); } TEST(CheckedArithmetic, CheckedMulUnsigned) { - uint64_t Out; const uint64_t Max = std::numeric_limits::max(); - EXPECT_EQ(checkedMulUnsigned(Max, 2, &Out), true); - EXPECT_EQ(checkedMulUnsigned(Max, Max, &Out), true); - EXPECT_EQ(checkedMulUnsigned(10, 2, &Out), false); - EXPECT_EQ(Out, uint64_t(20)); + EXPECT_EQ(checkedMulUnsigned(Max, 2), llvm::None); + EXPECT_EQ(checkedMulUnsigned(Max, Max), llvm::None); + EXPECT_EQ(checkedMulUnsigned(10, 2), Optional(20)); }