1 // Test to exercise that the type-specific integer arithmetic built-ins
2 // with overflow checking can be used in C++ 14 constant expressions.
3 // -Woverflow is disabled to prevent (bogus?) G++ warnings.
4 // { dg-do compile { target c++14 } }
5 // { dg-additional-options "-Wno-overflow" }
6 
7 #define SCHAR_MAX    __SCHAR_MAX__
8 #define SHRT_MAX     __SHRT_MAX__
9 #define INT_MAX	     __INT_MAX__
10 #define LONG_MAX     __LONG_MAX__
11 #define LLONG_MAX    __LONG_LONG_MAX__
12 
13 #define SCHAR_MIN    (-__SCHAR_MAX__ - 1)
14 #define SHRT_MIN     (-__SHRT_MAX__ - 1)
15 #define INT_MIN	     (-__INT_MAX__ - 1)
16 #define LONG_MIN     (-__LONG_MAX__ - 1)
17 #define LLONG_MIN    (-__LONG_LONG_MAX__ - 1)
18 
19 #define UCHAR_MAX    (SCHAR_MAX * 2U + 1)
20 #define USHRT_MAX    (SHRT_MAX * 2U + 1)
21 #define UINT_MAX     (INT_MAX * 2U + 1)
22 #define ULONG_MAX    (LONG_MAX * 2LU + 1)
23 #define ULLONG_MAX   (LLONG_MAX * 2LLU + 1)
24 
25 #define USCHAR_MIN   (-__USCHAR_MAX__ - 1)
26 #define USHRT_MIN    (-__USHRT_MAX__ - 1)
27 #define UINT_MIN     (-__UINT_MAX__ - 1)
28 #define ULONG_MIN    (-__ULONG_MAX__ - 1)
29 #define ULLONG_MIN   (-__ULONG_LONG_MAX__ - 1)
30 
31 // Helper macros.
32 #define sadd(x, y) ((x) + (y))
33 #define saddl(x, y) ((x) + (y))
34 #define saddll(x, y) ((x) + (y))
35 #define uadd(x, y) ((x) + (y))
36 #define uaddl(x, y) ((x) + (y))
37 #define uaddll(x, y) ((x) + (y))
38 #define ssub(x, y) ((x) - (y))
39 #define ssubl(x, y) ((x) - (y))
40 #define ssubll(x, y) ((x) - (y))
41 #define usub(x, y) ((x) - (y))
42 #define usubl(x, y) ((x) - (y))
43 #define usubll(x, y) ((x) - (y))
44 #define smul(x, y) ((x) * (y))
45 #define smull(x, y) ((x) * (y))
46 #define smulll(x, y) ((x) * (y))
47 #define umul(x, y) ((x) * (y))
48 #define umull(x, y) ((x) * (y))
49 #define umulll(x, y) ((x) * (y))
50 
51 // Result object.
52 template <class T>
53 struct Res
54 {
ResRes55   constexpr Res (T a, bool v): z (a), v (v) { }
56   T z; bool v;
57 };
58 
59 template <class T>
60 constexpr bool operator== (Res<T> a, Res<T> b)
61 {
62   return a.z == b.z && a.v == b.v;
63 }
64 
65 #define StaticAssert(expr) static_assert ((expr), #expr)
66 
67 #define CONCAT(a, b)   a ## b
68 #define CAT(a, b)      CONCAT (a, b)
69 
70 // Helper to determine the type of the result of the arithmetic
71 // as specified by the built-ins.
72 template <class T> struct ResType { typedef T type; };
73 template <>        struct ResType<signed char> { typedef int type; };
74 template <>        struct ResType<unsigned char> { typedef unsigned type; };
75 template <>        struct ResType<signed short> { typedef int type; };
76 template <>        struct ResType<unsigned short> { typedef unsigned type; };
77 
78 // Macro to define a single test case verifying that integer overflow
79 // is detected when expected, and when not, that the result matches
80 // the result computed using ordinary arithmetic.  The result cannot
81 // be tested in the presence of overflow since it's not a core
82 // constant expression.
83 #define TEST(op, T, x, y, vflow)					\
84   constexpr Res<T> CAT (op, __LINE__)(T a, T b)				\
85   {									\
86     ResType<T>::type c = 0;						\
87     bool v = __builtin_ ## op ## _overflow (a, b, &c);			\
88     return Res<T>(c, v);						\
89   }									\
90   StaticAssert (vflow ? CAT (op, __LINE__)(x, y).v			\
91 		: CAT (op, __LINE__)(x, y) == Res<T>(op (x, y), vflow))
92 
93 /* Signed int addition.  */
94 TEST (sadd,   signed char,    0,         0,         0);
95 TEST (sadd,   signed char,    0,         SCHAR_MAX, 0);
96 TEST (sadd,   signed char,    1,         SCHAR_MAX, 0);
97 TEST (sadd,   signed char,    SCHAR_MAX, SCHAR_MAX, 0);
98 TEST (sadd,   signed char,    0,         SCHAR_MIN, 0);
99 TEST (sadd,   signed char,   -1,         SCHAR_MIN, 0);
100 
101 TEST (sadd,   short,          0,         0,         0);
102 TEST (sadd,   short,          0,         SHRT_MAX,  0);
103 TEST (sadd,   short,          1,         SHRT_MAX,  0);
104 TEST (sadd,   short,          SHRT_MAX,  SHRT_MAX,  0);
105 TEST (sadd,   short,          0,         SHRT_MIN,  0);
106 TEST (sadd,   short,         -1,         SHRT_MIN,  0);
107 TEST (sadd,   short,          SHRT_MIN,  SHRT_MIN,  0);
108 
109 TEST (sadd,   int,            0,         0,         0);
110 TEST (sadd,   int,            0,         INT_MAX,   0);
111 TEST (sadd,   int,            1,         INT_MAX,   1);
112 TEST (sadd,   int,            INT_MAX,   INT_MAX,   1);
113 TEST (sadd,   int,            0,         INT_MIN,   0);
114 TEST (sadd,   int,           -1,         INT_MIN,   1);
115 TEST (sadd,   int,            INT_MIN,   INT_MIN,   1);
116 
117 /* Signed long addition.  */
118 TEST (saddl,  long,           0L,        0L,        0);
119 TEST (saddl,  long,           0L,        LONG_MAX,  0);
120 TEST (saddl,  long,           1L,        LONG_MAX,  1);
121 TEST (saddl,  long,           LONG_MAX,  LONG_MAX,  1);
122 TEST (saddl,  long,           0L,        LONG_MIN,  0);
123 TEST (saddl,  long,          -1L,        LONG_MIN,  1);
124 TEST (saddl,  long,           LONG_MIN,  LONG_MIN,  1);
125 
126 TEST (saddll, long long,      0LL,       0LL,        0);
127 TEST (saddll, long long,      0LL,       LLONG_MAX,  0);
128 TEST (saddll, long long,      1LL,       LLONG_MAX,  1);
129 TEST (saddll, long long,      LLONG_MAX, LLONG_MAX,  1);
130 TEST (saddll, long long,      0LL,       LLONG_MIN,  0);
131 TEST (saddll, long long,     -1LL,       LLONG_MIN,  1);
132 TEST (saddll, long long,      LLONG_MIN, LLONG_MIN,  1);
133 
134 /* Unsigned int addition.  */
135 TEST (uadd,   unsigned char,  0U,        0U,         0);
136 TEST (uadd,   unsigned char,  0U,        UCHAR_MAX, 0);
137 TEST (uadd,   unsigned char,  1U,        UCHAR_MAX, 0);
138 TEST (uadd,   unsigned char,  UCHAR_MAX, UCHAR_MAX, 0);
139 
140 TEST (uadd,   unsigned short, 0U,        0U,         0);
141 TEST (uadd,   unsigned short, 0U,        USHRT_MAX,  0);
142 TEST (uadd,   unsigned short, 1U,        USHRT_MAX,  0);
143 TEST (uadd,   unsigned short, USHRT_MAX, USHRT_MAX,  0);
144 
145 TEST (uadd,   unsigned,       0U,        0U,         0);
146 TEST (uadd,   unsigned,       0U,        UINT_MAX,   0);
147 TEST (uadd,   unsigned,       1U,        UINT_MAX,   1);
148 TEST (uadd,   unsigned,       UINT_MAX,  UINT_MAX,   1);
149 
150 /* Unsigned long addition.  */
151 TEST (uaddl,  unsigned long,  0UL,       0UL,       0);
152 TEST (uaddl,  unsigned long,  0UL,       ULONG_MAX, 0);
153 TEST (uaddl,  unsigned long,  1UL,       ULONG_MAX, 1);
154 TEST (uaddl,  unsigned long,  ULONG_MAX, ULONG_MAX, 1);
155 
156 TEST (uaddll, unsigned long long, 0ULL,       0ULL,       0);
157 TEST (uaddll, unsigned long long, 0ULL,       ULLONG_MAX, 0);
158 TEST (uaddll, unsigned long long, 1ULL,       ULLONG_MAX, 1);
159 TEST (uaddll, unsigned long long, ULLONG_MAX, ULLONG_MAX, 1);
160 
161 /* Signed int subtraction.  */
162 TEST (ssub,   signed char,    0,         0,          0);
163 TEST (ssub,   signed char,    0,         SCHAR_MAX,  0);
164 TEST (ssub,   signed char,    1,         SCHAR_MAX,  0);
165 TEST (ssub,   signed char,    SCHAR_MAX, SCHAR_MAX,  0);
166 TEST (ssub,   signed char,    0,         SCHAR_MIN,  0);
167 TEST (ssub,   signed char,   -1,         SCHAR_MIN,  0);
168 
169 TEST (ssub,   short,          0,         0,          0);
170 TEST (ssub,   short,          0,         SHRT_MAX,   0);
171 TEST (ssub,   short,          1,         SHRT_MAX,   0);
172 TEST (ssub,   short,          SHRT_MAX,  SHRT_MAX,   0);
173 TEST (ssub,   short,          0,         SHRT_MIN,   0);
174 TEST (ssub,   short,         -1,         SHRT_MIN,   0);
175 TEST (ssub,   short,          SHRT_MIN,  SHRT_MIN,   0);
176 
177 TEST (ssub,   int,            0,         0,          0);
178 TEST (ssub,   int,            0,         INT_MAX,    0);
179 TEST (ssub,   int,            1,         INT_MAX,    0);
180 TEST (ssub,   int,            INT_MAX,   INT_MAX,    0);
181 TEST (ssub,   int,            0,         INT_MIN,    1);
182 TEST (ssub,   int,           -1,         INT_MIN,    0);
183 TEST (ssub,   int,            INT_MIN,   INT_MIN,    0);
184 
185 /* Signed long subtraction.  */
186 TEST (ssubl,  long,           0L,        0L,         0);
187 TEST (ssubl,  long,           0L,        LONG_MAX,   0);
188 TEST (ssubl,  long,           1L,        LONG_MAX,   0);
189 TEST (ssubl,  long,           LONG_MAX,  LONG_MAX,   0);
190 TEST (ssubl,  long,           0L,        LONG_MIN,   1);
191 TEST (ssubl,  long,          -1L,        LONG_MIN,   0);
192 TEST (ssubl,  long,           LONG_MIN,  LONG_MIN,   0);
193 
194 /* Signed long long subtraction.  */
195 TEST (ssubll, long long,      0LL,       0LL,        0);
196 TEST (ssubll, long long,      0LL,       LLONG_MAX,  0);
197 TEST (ssubll, long long,      1LL,       LLONG_MAX,  0);
198 TEST (ssubll, long long,      LLONG_MAX, LLONG_MAX,  0);
199 TEST (ssubll, long long,      0LL,       LLONG_MIN,  1);
200 TEST (ssubll, long long,     -1LL,       LLONG_MIN,  0);
201 TEST (ssubll, long long,      LLONG_MIN, LLONG_MIN,  0);
202 
203 /* Unsigned int subtraction.  */
204 TEST (usub,   unsigned char,  0U,        0U,         0);
205 TEST (usub,   unsigned char,  0U,        UCHAR_MAX,  1);
206 TEST (usub,   unsigned char,  1U,        UCHAR_MAX,  1);
207 TEST (usub,   unsigned char,  UCHAR_MAX, UCHAR_MAX,  0);
208 
209 TEST (usub,   unsigned short, 0U,        0U,         0);
210 TEST (usub,   unsigned short, 0U,        USHRT_MAX,  1);
211 TEST (usub,   unsigned short, 1U,        USHRT_MAX,  1);
212 TEST (usub,   unsigned short, USHRT_MAX, USHRT_MAX,  0);
213 
214 TEST (usub,   unsigned,       0U,        0U,         0);
215 TEST (usub,   unsigned,       0U,        UINT_MAX,   1);
216 TEST (usub,   unsigned,       1U,        UINT_MAX,   1);
217 TEST (usub,   unsigned,       UINT_MAX,  UINT_MAX,   0);
218 
219 /* Unsigned long subtraction.  */
220 TEST (usubl,  unsigned long,  0UL,       0UL,       0);
221 TEST (usubl,  unsigned long,  0UL,       ULONG_MAX, 1);
222 TEST (usubl,  unsigned long,  1UL,       ULONG_MAX, 1);
223 TEST (usubl,  unsigned long,  ULONG_MAX, ULONG_MAX, 0);
224 
225 /* Unsigned long long subtraction.  */
226 TEST (usubll, unsigned long long,  0ULL,       0ULL,       0);
227 TEST (usubll, unsigned long long,  0ULL,       ULLONG_MAX, 1);
228 TEST (usubll, unsigned long long,  1ULL,       ULLONG_MAX, 1);
229 TEST (usubll, unsigned long long,  ULLONG_MAX, ULLONG_MAX, 0);
230