//===----------------------------------------------------------------------===// // // Philipp Schubert // // Copyright (c) 2017 - 2021 // Secure Software Engineering Group // Heinz Nixdorf Institute // Paderborn University // philipp.schubert@upb.de // //===----------------------------------------------------------------------===// #include #include #include #include constexpr int max = std::numeric_limits::max(); constexpr int min = std::numeric_limits::min(); class sint { private: int value; public: sint() : value(0) {} sint(int i) : value(i) {} ~sint() = default; sint(const sint &s) = default; sint &operator=(const sint &s) = default; sint(sint &&s) = default; sint &operator=(sint &&s) = default; int getUnderlyingValue() const noexcept { return value; } friend sint operator+(sint lhs, sint rhs) { int result; if(__builtin_sadd_overflow(lhs.getUnderlyingValue(), rhs.getUnderlyingValue(), &result)) { throw std::overflow_error("addition overflow"); } return result; } friend sint operator-(sint lhs, sint rhs) { int result; if(__builtin_ssub_overflow(lhs.getUnderlyingValue(), rhs.getUnderlyingValue(), &result)) { throw std::overflow_error("subtraction overflow"); } return result; } friend sint operator*(sint lhs, sint rhs) { int result; if(__builtin_smul_overflow(lhs.getUnderlyingValue(), rhs.getUnderlyingValue(), &result)) { throw std::overflow_error("multiplication overflow"); } return result; } friend sint operator/(sint lhs, sint rhs) { if(rhs.getUnderlyingValue()==0) { throw std::overflow_error("division by 0"); } //If two's complement constexpr bool twos = min != -max; if(twos && lhs.getUnderlyingValue() == min && rhs.getUnderlyingValue() == -1) { throw std::overflow_error("division with integer maximum and -1"); } return lhs.getUnderlyingValue()/rhs.getUnderlyingValue(); } sint &operator++() { *this = *this + 1; return *this; } sint operator++(int) { sint out(*this); ++(*this); return out; } sint &operator--() { *this = *this - 1; return *this; } sint operator--(int) { sint out(*this); --(*this); return out; } friend std::ostream &operator<<(std::ostream &os, const sint &s) { return os << s.getUnderlyingValue(); } }; const sint smax = max; const sint smin = min; int main() { // You are of course free to extend these tests! // // just a small test sint a = 1; sint b(41); sint c = a + b; std::cout << c << '\n'; // // setup some values sint result; // // test operator+ // result = max + sint(10); // std::cout << result << '\n'; // result = min + sint(-10); // std::cout << result << '\n'; // // test operator- // result = min - sint(10); // std::cout << result << '\n'; // result = max - sint(-10); // std::cout << result << '\n'; // // test operator* // result = max * sint(2); // std::cout << result << '\n'; // result = min * sint(2); // std::cout << result << '\n'; // test operator/ // result = sint(42) / sint(0); // std::cout << result << '\n'; // result = min / sint(-2); // std::cout << result << '\n'; return 0; }