This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Detect most integer overflows.


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();




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]