@@ -123,10 +123,10 @@ namespace pythonic
123123 // Check if an operation would overflow without performing it
124124 // ============================================================================
125125
126+ #ifdef _MSC_VER
126127 template <Integral T>
127128 constexpr bool would_add_overflow (T a, T b) noexcept
128129 {
129- #ifdef _MSC_VER
130130 T res = a + b;
131131 if constexpr (std::is_signed_v<T>)
132132 {
@@ -136,16 +136,20 @@ namespace pythonic
136136 {
137137 return res < a;
138138 }
139+ }
139140#else
141+ template <Integral T>
142+ constexpr bool would_add_overflow (T a, T b) noexcept
143+ {
140144 T res;
141145 return __builtin_add_overflow (a, b, &res);
142- #endif
143146 }
147+ #endif
144148
149+ #ifdef _MSC_VER
145150 template <Integral T>
146151 constexpr bool would_sub_overflow (T a, T b) noexcept
147152 {
148- #ifdef _MSC_VER
149153 T res = a - b;
150154 if constexpr (std::is_signed_v<T>)
151155 {
@@ -155,16 +159,20 @@ namespace pythonic
155159 {
156160 return res > a;
157161 }
162+ }
158163#else
164+ template <Integral T>
165+ constexpr bool would_sub_overflow (T a, T b) noexcept
166+ {
159167 T res;
160168 return __builtin_sub_overflow (a, b, &res);
161- #endif
162169 }
170+ #endif
163171
172+ #ifdef _MSC_VER
164173 template <Integral T>
165174 constexpr bool would_mul_overflow (T a, T b) noexcept
166175 {
167- #ifdef _MSC_VER
168176 T res = a * b;
169177 if constexpr (std::is_signed_v<T>)
170178 {
@@ -175,11 +183,15 @@ namespace pythonic
175183 {
176184 return (a != 0 && b > std::numeric_limits<T>::max () / a);
177185 }
186+ }
178187#else
188+ template <Integral T>
189+ constexpr bool would_mul_overflow (T a, T b) noexcept
190+ {
179191 T res;
180192 return __builtin_mul_overflow (a, b, &res);
181- #endif
182193 }
194+ #endif
183195
184196 // Floating point doesn't have traditional overflow, but we can check for infinity
185197 template <FloatingPoint T>
@@ -206,10 +218,10 @@ namespace pythonic
206218 // Return type is always T
207219 // ============================================================================
208220
221+ #ifdef _MSC_VER
209222 template <Integral T>
210223 T add_throw (T a, T b)
211224 {
212- #ifdef _MSC_VER
213225 T res = a + b;
214226 bool overflow;
215227 if constexpr (std::is_signed_v<T>)
@@ -221,15 +233,23 @@ namespace pythonic
221233 overflow = res < a;
222234 }
223235 if (overflow)
236+ {
237+ throw PythonicOverflowError (" integer addition overflow" );
238+ }
239+ return res;
240+ }
224241#else
242+ template <Integral T>
243+ T add_throw (T a, T b)
244+ {
225245 T res;
226246 if (__builtin_add_overflow (a, b, &res))
227- #endif
228247 {
229248 throw PythonicOverflowError (" integer addition overflow" );
230249 }
231250 return res;
232251 }
252+ #endif
233253
234254 template <FloatingPoint T>
235255 T add_throw (T a, T b)
@@ -242,10 +262,10 @@ namespace pythonic
242262 return res;
243263 }
244264
265+ #ifdef _MSC_VER
245266 template <Integral T>
246267 T sub_throw (T a, T b)
247268 {
248- #ifdef _MSC_VER
249269 T res = a - b;
250270 bool overflow;
251271 if constexpr (std::is_signed_v<T>)
@@ -257,15 +277,23 @@ namespace pythonic
257277 overflow = res > a;
258278 }
259279 if (overflow)
280+ {
281+ throw PythonicOverflowError (" integer subtraction overflow" );
282+ }
283+ return res;
284+ }
260285#else
286+ template <Integral T>
287+ T sub_throw (T a, T b)
288+ {
261289 T res;
262290 if (__builtin_sub_overflow (a, b, &res))
263- #endif
264291 {
265292 throw PythonicOverflowError (" integer subtraction overflow" );
266293 }
267294 return res;
268295 }
296+ #endif
269297
270298 template <FloatingPoint T>
271299 T sub_throw (T a, T b)
@@ -278,10 +306,10 @@ namespace pythonic
278306 return res;
279307 }
280308
309+ #ifdef _MSC_VER
281310 template <Integral T>
282311 T mul_throw (T a, T b)
283312 {
284- #ifdef _MSC_VER
285313 T res = a * b;
286314 bool overflow;
287315 if constexpr (std::is_signed_v<T>)
@@ -294,15 +322,23 @@ namespace pythonic
294322 overflow = (a != 0 && b > std::numeric_limits<T>::max () / a);
295323 }
296324 if (overflow)
325+ {
326+ throw PythonicOverflowError (" integer multiplication overflow" );
327+ }
328+ return res;
329+ }
297330#else
331+ template <Integral T>
332+ T mul_throw (T a, T b)
333+ {
298334 T res;
299335 if (__builtin_mul_overflow (a, b, &res))
300- #endif
301336 {
302337 throw PythonicOverflowError (" integer multiplication overflow" );
303338 }
304339 return res;
305340 }
341+ #endif
306342
307343 template <FloatingPoint T>
308344 T mul_throw (T a, T b)
0 commit comments