_Safe_add checks for overflow but does not do anything to report the problem!


Looking at VC++ source files I find in ratio the following:

what is the purpose of _Safe_add_integer_arithmetic_overflow_error?



1
2
3
4
5
6
7
8
9
inline void _Safe_add_integer_arithmetic_overflow_error() noexcept {}

_NODISCARD constexpr intmax_t _Safe_add(const intmax_t _Ax, const intmax_t _Bx) noexcept {
    if (_Sign_of(_Ax) == _Sign_of(_Bx) && _Abs(_Ax) > INTMAX_MAX - _Abs(_Bx)) {
        _Safe_add_integer_arithmetic_overflow_error();
    }

    return _Ax + _Bx;
}


How does calling this void function alert us that there would be overflow?

First of all, any symbols (e.g. functions) starting with two underscore characters or starting with an underscore character followed by an upper case letter (as is the case here), are "reserved" names for the compiler's internal usage.

Secondly, my guess would be that the internal "helper" function _Safe_add_integer_arithmetic_overflow_error() triggers the error handler and/or sets errno, if the given arguments (in this case the arguments for _Safe_add() function) would cause and arithmetic overflow.

Also, this probably is one of those "intrinsic" functions (built-in functions) that the compiler "knows" how to generate the code for. So, the empty function definition, which you see in the header file, probably is just a "stub" to satisfy static code analyzers and the like...

Note that error handler functions are different from C++ exceptions:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/set-invalid-parameter-handler-set-thread-local-invalid-parameter-handler?view=msvc-170#remarks

As for the errno global variable, please see:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/errno-doserrno-sys-errlist-and-sys-nerr?view=msvc-170

(BTW: I can not find _Safe_add() in my VC++)
Last edited on
BTW: I can not find _Safe_add() in my VC++)


It's in VS2022 ratio L41
It's in VS2022 ratio L41

And that would translate to which of the currently 12 VS2022 versions? 17.0-17.11.

Or is this in the not-yet-released 17.12?
Here's the code in Microsoft's STL implementation
https://github.com/microsoft/STL/blob/main/stl/inc/ratio#L41

How does calling this void function alert us that there would be overflow?
_Safe_add is constexpr and _Safe_add_integer_arithmetic_overflow_error is not.
In a constant-evaluated context, _Safe_add can't call _Safe_add_integer_arithmetic_overflow_error without getting a compiler error.

Here's an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void f() {}
constexpr bool g(bool x) { if (x) f(); return x; }
template <bool> struct a{};

int main()
{
    // no checking at runtime
    g(false); // ok
    g(true);  // ok

    // ...but produces a compiler error if used in a constant expression
    a<g(false)> a1; // ok
    a<g(true)> a2;  // error: non-type template argument is not a constant expression
}

https://godbolt.org/z/W3s5Ksacv
Last edited on
Neat example, thanks.
Topic archived. No new replies allowed.