This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [RFC] Detect most integer overflows.
- From: David Brown <david at westcontrol dot com>
- To: Kai Tietz <ktietz70 at googlemail dot com>
- Cc: Andrew Haley <aph at redhat dot com>, OndÅej BÃlka <neleai at seznam dot cz>, Richard Biener <richard dot guenther at gmail dot com>, "Hannes Frederic Sowa" <hannes at stressinduktion dot org>, "gcc at gnu dot org" <gcc at gnu dot org>
- Date: Wed, 30 Oct 2013 15:03:40 +0100
- Subject: Re: [RFC] Detect most integer overflows.
- Authentication-results: sourceware.org; auth=none
- References: <20131026192912 dot GA25428 at domone dot podge> <20131026235014 dot GF18009 at order dot stressinduktion dot org> <CAFiYyc0+wTbE1FwwLscquWvoEtM6JQw4p5qhnhBmGtVCMkx9fQ at mail dot gmail dot com> <20131030083413 dot GA12183 at domone dot podge> <5270C63C dot 6030406 at redhat dot com> <CAEwic4a9O7a2S34NEzZ5iq2oef=5Agmr863Thj5=MsENa_nxGg at mail dot gmail dot com>
On 30/10/13 10:00, Kai Tietz wrote:
> 2013/10/30 Andrew Haley <aph@redhat.com>:
>> On 10/30/2013 08:34 AM, OndÅej BÃlka wrote:
>>
>>>>
>>> The reasons of adding builtins is performance. Without that one can
>>> write a simple template to generically check overflows like
>>>
>>> template <class C> class overflow {
>>> public:
>>> C val;
>>> overflow <C> operator + (overflow <C> &y) {
>>> overflow <C> ret;
>>> if (val > 0 && y.val > 0 && val + y.val < val)
>>> throw std::overflow_error();
>>> /* ... */
>>> ret.val = val + y.val;
>>> return ret;
>>> }
>>> /* ... */
>>> };
>>
>> How is that going to work? The compiler can simply eliminate this line:
>>
>> if (val > 0 && y.val > 0 && val + y.val < val)
>> throw std::overflow_error();
>>
>> because it knows that the guard is always false. I suppose it could be
>> compiled with -fwrapv.
>>
>> Andrew.
>
> Right, as Andrew pointed out, this doesn't work. You are falling into
> the pit of optimization on assumptions of overflow.
>
> The way, which might work, is to do checks on unsigned types. As for
> unsigned-integer-scalar-types overflow is defined.
>
> Kai
>
Technically speaking, casting your signed values to unsigned and using
that to detect overflow will not necessarily work - I think it would be
"implementation defined". But almost all architectures use two's
compliment arithmetic, and it will work there.
I don't know if this is legal C++ (I haven't had enough practice at this
stuff), but the principle would be:
if (val > 0 && y.val > 0 &&
(signed) ((unsigned C) val + (unsigned C) y.val) < val)
throw std::overflow_error();
You also need:
if (val < 0 && y.val < 0 &&
(signed) ((unsigned C) val + (unsigned C) y.val) > val)
throw std::overflow_error();