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 bool b = __builtin_add_overflow(lhs, rhs, &sum); 33 return {b, sum}; 34 } 35 36 static_assert(add<short>(static_cast<char>(120), static_cast<char>(10)) == Result<short>{false, 130}); 37 static_assert(add<char>(static_cast<short>(120), static_cast<short>(10)) == Result<char>{true, -126}); 38 static_assert(add<unsigned int>(INT_MAX, INT_MAX) == Result<unsigned int>{false, static_cast<unsigned int>(INT_MAX) * 2u}); 39 static_assert(add<int>(static_cast<unsigned int>(INT_MAX), 1u) == Result<int>{true, INT_MIN}); 40 41 static_assert(add<int>(17, 22) == Result<int>{false, 39}); 42 static_assert(add<int>(INT_MAX - 22, 24) == Result<int>{true, INT_MIN + 1}); 43 static_assert(add<int>(INT_MIN + 22, -23) == Result<int>{true, INT_MAX}); 44 45 template <typename RET, typename LHS, typename RHS> 46 constexpr Result<RET> sub(LHS &&lhs, RHS &&rhs) { 47 RET sum{}; 48 bool b = __builtin_sub_overflow(lhs, rhs, &sum); 49 return {b, sum}; 50 } 51 52 static_assert(sub<unsigned char>(static_cast<char>(0),static_cast<char>(1)) == Result<unsigned char>{true, UCHAR_MAX}); 53 static_assert(sub<char>(static_cast<unsigned char>(0),static_cast<unsigned char>(1)) == Result<char>{false, -1}); 54 static_assert(sub<unsigned short>(static_cast<short>(0),static_cast<short>(1)) == Result<unsigned short>{true, USHRT_MAX}); 55 56 static_assert(sub<int>(17,22) == Result<int>{false, -5}); 57 static_assert(sub<int>(INT_MAX - 22, -23) == Result<int>{true, INT_MIN}); 58 static_assert(sub<int>(INT_MIN + 22, 23) == Result<int>{true, INT_MAX}); 59 60 template <typename RET, typename LHS, typename RHS> 61 constexpr Result<RET> mul(LHS &&lhs, RHS &&rhs) { 62 RET sum{}; 63 bool b = __builtin_mul_overflow(lhs, rhs, &sum); 64 return {b, sum}; 65 } 66 67 static_assert(mul<int>(17,22) == Result<int>{false, 374}); 68 static_assert(mul<int>(INT_MAX / 22, 23) == Result<int>{true, -2049870757}); 69 static_assert(mul<int>(INT_MIN / 22, -23) == Result<int>{true, -2049870757}); 70 71 constexpr Result<int> sadd(int lhs, int rhs) { 72 int sum{}; 73 bool b = __builtin_sadd_overflow(lhs, rhs, &sum); 74 return {b, sum}; 75 } 76 77 static_assert(sadd(17,22) == Result<int>{false, 39}); 78 static_assert(sadd(INT_MAX - 22, 23) == Result<int>{true, INT_MIN}); 79 static_assert(sadd(INT_MIN + 22, -23) == Result<int>{true, INT_MAX}); 80 81 constexpr Result<int> ssub(int lhs, int rhs) { 82 int sum{}; 83 bool b = __builtin_ssub_overflow(lhs, rhs, &sum); 84 return {b, sum}; 85 } 86 87 static_assert(ssub(17,22) == Result<int>{false, -5}); 88 static_assert(ssub(INT_MAX - 22, -23) == Result<int>{true, INT_MIN}); 89 static_assert(ssub(INT_MIN + 22, 23) == Result<int>{true, INT_MAX}); 90 91 constexpr Result<int> smul(int lhs, int rhs) { 92 int sum{}; 93 bool b = __builtin_smul_overflow(lhs, rhs, &sum); 94 return {b, sum}; 95 } 96 97 static_assert(smul(17,22) == Result<int>{false, 374}); 98 static_assert(smul(INT_MAX / 22, 23) == Result<int>{true, -2049870757}); 99 static_assert(smul(INT_MIN / 22, -23) == Result<int>{true, -2049870757}); 100