1 // PR c++/70507 - integer overflow builtins not constant expressions
2 // { dg-do compile { target c++11 } }
4 #define SCHAR_MAX __SCHAR_MAX__
5 #define SHRT_MAX __SHRT_MAX__
6 #define INT_MAX __INT_MAX__
7 #define LONG_MAX __LONG_MAX__
8 #define LLONG_MAX __LONG_LONG_MAX__
10 #define SCHAR_MIN (-__SCHAR_MAX__ - 1)
11 #define SHRT_MIN (-__SHRT_MAX__ - 1)
12 #define INT_MIN (-__INT_MAX__ - 1)
13 #define LONG_MIN (-__LONG_MAX__ - 1)
14 #define LLONG_MIN (-__LONG_LONG_MAX__ - 1)
16 #define UCHAR_MAX (SCHAR_MAX * 2U + 1)
17 #define USHRT_MAX (SHRT_MAX * 2U + 1)
18 #define UINT_MAX (INT_MAX * 2U + 1)
19 #define ULONG_MAX (LONG_MAX * 2LU + 1)
20 #define ULLONG_MAX (LLONG_MAX * 2LLU + 1)
22 #define USCHAR_MIN (-__USCHAR_MAX__ - 1)
23 #define USHRT_MIN (-__USHRT_MAX__ - 1)
24 #define UINT_MIN (-__UINT_MAX__ - 1)
25 #define ULONG_MIN (-__ULONG_MAX__ - 1)
26 #define ULLONG_MIN (-__ULONG_LONG_MAX__ - 1)
28 #define Assert(expr) static_assert ((expr), #expr)
31 constexpr T add (T x, T y, T z = T ())
33 return __builtin_add_overflow (x, y, &z) ? 0 : z;
37 constexpr T sub (T x, T y, T z = T ())
39 return __builtin_sub_overflow (x, y, &z) ? 0 : z;
43 constexpr T mul (T x, T y, T z = T ())
45 return __builtin_mul_overflow (x, y, &z) ? 0 : z;
48 #define TEST_ADD(T, x, y, z) Assert (z == add<T>(x, y))
49 #define TEST_SUB(T, x, y, z) Assert (z == sub<T>(x, y))
50 #define TEST_MUL(T, x, y, z) Assert (z == mul<T>(x, y))
53 TEST_ADD (signed char, 0, 0, 0);
54 TEST_ADD (signed char, 0, SCHAR_MAX, SCHAR_MAX);
55 TEST_ADD (signed char, 1, SCHAR_MAX, 0); // overflow
56 TEST_ADD (signed char, SCHAR_MAX, SCHAR_MAX, 0); // overflow
57 TEST_ADD (signed char, 0, SCHAR_MIN, SCHAR_MIN);
58 TEST_ADD (signed char, -1, SCHAR_MIN, 0); // overflow
60 TEST_ADD (short, 0, 0, 0);
61 TEST_ADD (short, 0, SHRT_MAX, SHRT_MAX);
62 TEST_ADD (short, 1, SHRT_MAX, 0); // overflow
63 TEST_ADD (short, SHRT_MAX, SHRT_MAX, 0); // overflow
64 TEST_ADD (short, 0, SHRT_MIN, SHRT_MIN);
65 TEST_ADD (short, -1, SHRT_MIN, 0); // overflow
66 TEST_ADD (short, SHRT_MIN, SHRT_MIN, 0); // overflow
68 TEST_ADD (int, 0, 0, 0);
69 TEST_ADD (int, 0, INT_MAX, INT_MAX);
70 TEST_ADD (int, 1, INT_MAX, 0); // overflow
71 TEST_ADD (int, INT_MAX, INT_MAX, 0); // overflow
72 TEST_ADD (int, 0, INT_MIN, INT_MIN);
73 TEST_ADD (int, -1, INT_MIN, 0); // overflow
74 TEST_ADD (int, INT_MIN, INT_MIN, 0); // overflow
76 TEST_ADD (long, 0, 0, 0);
77 TEST_ADD (long, 0, LONG_MAX, LONG_MAX);
78 TEST_ADD (long, 1, LONG_MAX, 0); // overflow
79 TEST_ADD (long, LONG_MAX, LONG_MAX, 0); // overflow
80 TEST_ADD (long, 0, LONG_MIN, LONG_MIN);
81 TEST_ADD (long, -1, LONG_MIN, 0); // overflow
82 TEST_ADD (long, LONG_MIN, LONG_MIN, 0); // overflow
84 TEST_ADD (long long, 0, 0, 0);
85 TEST_ADD (long long, 0, LLONG_MAX, LLONG_MAX);
86 TEST_ADD (long long, 1, LLONG_MAX, 0); // overflow
87 TEST_ADD (long long, LLONG_MAX, LLONG_MAX, 0); // overflow
88 TEST_ADD (long long, 0, LLONG_MIN, LLONG_MIN);
89 TEST_ADD (long long, -1, LLONG_MIN, 0); // overflow
90 TEST_ADD (long long, LLONG_MIN, LLONG_MIN, 0); // overflow
92 TEST_ADD (unsigned char, 0, 0, 0);
93 TEST_ADD (unsigned char, 0, UCHAR_MAX, UCHAR_MAX);
94 TEST_ADD (unsigned char, 1, UCHAR_MAX, 0); // overflow
96 TEST_ADD (unsigned char, UCHAR_MAX, UCHAR_MAX, 0); // overflow
97 TEST_ADD (unsigned short, 0, 0, 0);
98 TEST_ADD (unsigned short, 0, USHRT_MAX, USHRT_MAX);
99 TEST_ADD (unsigned short, 1, USHRT_MAX, 0); // overflow
100 TEST_ADD (unsigned short, USHRT_MAX, USHRT_MAX, 0); // overflow
102 TEST_ADD (unsigned, 0, 0, 0);
103 TEST_ADD (unsigned, 0, UINT_MAX, UINT_MAX);
104 TEST_ADD (unsigned, 1, UINT_MAX, 0); // overflow
105 TEST_ADD (unsigned, UINT_MAX, UINT_MAX, 0); // overflow
107 TEST_ADD (unsigned long, 0, 0, 0);
108 TEST_ADD (unsigned long, 0, ULONG_MAX, ULONG_MAX);
109 TEST_ADD (unsigned long, 1, ULONG_MAX, 0); // overflow
110 TEST_ADD (unsigned long, ULONG_MAX, ULONG_MAX, 0); // overflow
112 TEST_ADD (unsigned long long, 0, 0, 0);
113 TEST_ADD (unsigned long long, 0, ULLONG_MAX, ULLONG_MAX);
114 TEST_ADD (unsigned long long, 1, ULLONG_MAX, 0); // overflow
115 TEST_ADD (unsigned long long, ULLONG_MAX, ULLONG_MAX, 0); // overflow
118 // Make sure the built-ins are accepted in the following contexts
119 // where constant expressions are required and that they return
120 // the expected overflow value.
125 a0 = __builtin_add_overflow_p ( 1, 1, 0),
126 a1 = __builtin_add_overflow_p (INT_MAX, 1, 0)
133 s0 = __builtin_sub_overflow_p ( 1, 1, 0),
134 s1 = __builtin_sub_overflow_p (INT_MIN, 1, 0)
141 m0 = __builtin_add_overflow_p ( 1, 1, 0),
142 m1 = __builtin_add_overflow_p (INT_MAX, INT_MAX, 0)
150 namespace TemplateArg {
152 template <class T, class U, class V,
153 T x, U y, bool v, bool z = __builtin_add_overflow_p (x, y, V ())>
158 template <class T, class U, class V,
159 T x, U y, bool v, bool z = __builtin_sub_overflow_p (x, y, V ())>
164 template <class T, class U, class V,
165 T x, U y, bool v, bool z = __builtin_mul_overflow_p (x, y, V ())>
170 template struct Add<int, int, int, 1, 1, false>;
171 template struct Add<int, int, int, 1, INT_MAX, true>;
173 template struct Sub<int, int, int, 1, 1, false>;
174 template struct Sub<int, int, int, -2, INT_MAX, true>;
176 template struct Mul<int, int, int, 1, 1, false>;
177 template struct Mul<int, int, int, 2, INT_MAX / 2 + 1, true>;
179 } // namespace TemplateArg
181 #if __cplusplus >= 201402L
183 namespace Initializer {
191 add_vflow (int a, int b)
194 Result res = { a + b, __builtin_add_overflow_p (a, b, int ()) };
196 // The following fails to compile because of c++/71391 - error
197 // on aggregate initialization with side-effects in a constexpr
200 Result res = { 0, __builtin_add_overflow (a, b, &c) };
206 constexpr Result sum = add_vflow (123, 456);
207 Assert (sum.res == 123 + 456);
210 } // namespace Initializer
212 #endif // __cplusplus >= 201402L