1 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s 2 // expected-no-diagnostics 3 4 #include <limits.h> 5 6 int a() { 7 const int x = 3; 8 static int z; 9 constexpr int *y = &z; 10 return []() { return __builtin_sub_overflow((int)x, (int)x, (int *)y); }(); 11 } 12 int a2() { 13 const int x = 3; 14 static int z; 15 constexpr int *y = &z; 16 return []() { return __builtin_sub_overflow(x, x, y); }(); 17 } 18 19 template<typename T> 20 struct Result { 21 bool B; 22 T Value; 23 constexpr bool operator==(const Result<T> &Other) { 24 return B == Other.B && Value == Other.Value; 25 } 26 }; 27 28 29 template <typename RET, typename LHS, typename RHS> 30 constexpr Result<RET> add(LHS &&lhs, RHS &&rhs) { 31 RET sum{}; 32 return {__builtin_add_overflow(lhs, rhs, &sum), sum}; 33 } 34 35 static_assert(add<short>(static_cast<char>(120), static_cast<char>(10)) == Result<short>{false, 130}); 36 static_assert(add<char>(static_cast<short>(120), static_cast<short>(10)) == Result<char>{true, -126}); 37 static_assert(add<unsigned int>(INT_MAX, INT_MAX) == Result<unsigned int>{false, static_cast<unsigned int>(INT_MAX) * 2u}); 38 static_assert(add<int>(static_cast<unsigned int>(INT_MAX), 1u) == Result<int>{true, INT_MIN}); 39 40 static_assert(add<int>(17, 22) == Result<int>{false, 39}); 41 static_assert(add<int>(INT_MAX - 22, 24) == Result<int>{true, INT_MIN + 1}); 42 static_assert(add<int>(INT_MIN + 22, -23) == Result<int>{true, INT_MAX}); 43 44 template <typename RET, typename LHS, typename RHS> 45 constexpr Result<RET> sub(LHS &&lhs, RHS &&rhs) { 46 RET sum{}; 47 return {__builtin_sub_overflow(lhs, rhs, &sum), sum}; 48 } 49 50 static_assert(sub<unsigned char>(static_cast<char>(0),static_cast<char>(1)) == Result<unsigned char>{true, UCHAR_MAX}); 51 static_assert(sub<char>(static_cast<unsigned char>(0),static_cast<unsigned char>(1)) == Result<char>{false, -1}); 52 static_assert(sub<unsigned short>(static_cast<short>(0),static_cast<short>(1)) == Result<unsigned short>{true, USHRT_MAX}); 53 54 static_assert(sub<int>(17,22) == Result<int>{false, -5}); 55 static_assert(sub<int>(INT_MAX - 22, -23) == Result<int>{true, INT_MIN}); 56 static_assert(sub<int>(INT_MIN + 22, 23) == Result<int>{true, INT_MAX}); 57 58 template <typename RET, typename LHS, typename RHS> 59 constexpr Result<RET> mul(LHS &&lhs, RHS &&rhs) { 60 RET sum{}; 61 return {__builtin_mul_overflow(lhs, rhs, &sum), sum}; 62 } 63 64 static_assert(mul<int>(17,22) == Result<int>{false, 374}); 65 static_assert(mul<int>(INT_MAX / 22, 23) == Result<int>{true, -2049870757}); 66 static_assert(mul<int>(INT_MIN / 22, -23) == Result<int>{true, -2049870757}); 67 68 constexpr Result<int> sadd(int lhs, int rhs) { 69 int sum{}; 70 return {__builtin_sadd_overflow(lhs, rhs, &sum), sum}; 71 } 72 73 static_assert(sadd(17,22) == Result<int>{false, 39}); 74 static_assert(sadd(INT_MAX - 22, 23) == Result<int>{true, INT_MIN}); 75 static_assert(sadd(INT_MIN + 22, -23) == Result<int>{true, INT_MAX}); 76 77 constexpr Result<int> ssub(int lhs, int rhs) { 78 int sum{}; 79 return {__builtin_ssub_overflow(lhs, rhs, &sum), sum}; 80 } 81 82 static_assert(ssub(17,22) == Result<int>{false, -5}); 83 static_assert(ssub(INT_MAX - 22, -23) == Result<int>{true, INT_MIN}); 84 static_assert(ssub(INT_MIN + 22, 23) == Result<int>{true, INT_MAX}); 85 86 constexpr Result<int> smul(int lhs, int rhs) { 87 int sum{}; 88 return {__builtin_smul_overflow(lhs, rhs, &sum), sum}; 89 } 90 91 static_assert(smul(17,22) == Result<int>{false, 374}); 92 static_assert(smul(INT_MAX / 22, 23) == Result<int>{true, -2049870757}); 93 static_assert(smul(INT_MIN / 22, -23) == Result<int>{true, -2049870757}); 94