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: OndÅej BÃlka <neleai at seznam dot cz>
- Cc: Trevor Saunders <tsaunders at mozilla dot com>, <gcc at gcc dot gnu dot org>
- Date: Wed, 30 Oct 2013 16:23:20 +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> <20131030144909 dot GA4555 at tsaunders-iceball dot corp dot tor1 dot mozilla dot com> <20131030145959 dot GA15771 at domone dot podge>
On 30/10/13 15:59, OndÅej BÃlka wrote:
> On Wed, Oct 30, 2013 at 10:49:09AM -0400, Trevor Saunders wrote:
>> On Wed, Oct 30, 2013 at 10:00:07AM +0100, 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.
>>
>> For an example of something that implements this see
>> http://mxr.mozilla.org/mozilla-central/source/mfbt/CheckedInt.h which is
>> used by WebKit / Blink as well aiui.
>>
> That also does not work in strict sense as it assumes two complement
> arithmetic which standard does not guarantee and is one of reasons why
> signed overflows has undefined behavior.
>
I believe that's only a minor reason for making signed overflows
undefined behaviour. If it were a matter of implementation, I think it
would have been made "implementation defined" rather than "undefined",
so that two's complement machines could use wrapping while other systems
(which are very rare now) could have other defined overflow behaviour.
The main reason (again, this is my guess - I don't know what the C
standards folk /actually/ thought) is that there is no obvious "correct"
behaviour for signed overflow. There are so many logical choices -
wraparound (like in java), trapping (for processors that support this),
setting errno, saturating, throwing an exception (as is done here), etc.
Signed overflow is an indication of a bug in the code, or that you've
got garbage in and are therefore happy with garbage out. By making this
undefined behaviour, the compiler can then optimise better (though buggy
code could get worse).