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