C++ Logo


Advanced search

Re: [ub] P1407R0: Tell Programmers About Signed Integer Overflow Behavior

From: Scott Schurr <s.scott.schurr_at_[hidden]>
Date: Wed, 30 Jan 2019 11:07:43 -0800
Hi John, Melissa, and Hubert,

John noted:
> Can I take this opportunity to recommend that we consider library
solutions to our numerics
> problems? There are mature, widely used class-based literal types out
there which tackle
> such problems. (And yes, they support wrap, trap, snap and crap.) We
could put a lot more
> effort into exploring their standardization.

That's a worthwhile point. But I'm not convinced that standardizing new
integer types really addresses the problem at hand, although they do
improve the situation. The addition of smart pointers did not make raw
pointers go away. The advantage we had with raw pointers is that people
already recognized them as dangerous. For the most part people don't know
how dangerous their integers are because integers usually are well
behaved. So the addition of smart integers is unlikely to make "raw"
integers go away either.

And I have to suspect that standardizing new integer types is a couple of
standards cycles away or more.

On Wed, Jan 30, 2019 at 7:32 AM Hubert Tong <
hubert.reinterpretcast_at_[hidden]> wrote:

> On Wed, Jan 30, 2019 at 3:51 AM Myria <myriachan_at_[hidden]> wrote:
>> This document doesn't mention another possible behavior of signed
>> overflow: saturation. Saturation arithmetic supposedly is what many DSPs
>> do on overflow, but I wouldn't know.
Thanks for pointing that out. Yes, saturation might be considered a
desirable behavior, and I believe it's fairly common for floating point. I
haven't personally seen hardware- or language-level saturation implemented
anywhere for integers. The three Analog Devices DSPs that I have used in
the past did not support saturation for integer operations. But that
doesn't say anything about TI, Motorola, or other DSP vendors. So integer
saturation might be out there in the wild. If anyone is aware of a
documented case, that would be great to know about.

So, yes, I should at least mention saturation as a potential behavior. If
there's an R1 of the paper I'll include that point.

> I call the three cases of when there is implementation-defined behavior as
>> "snap", "trap" and "wrap" for the alliteration. I suppose the "can't
>> happen" / undefined case could be "crap". =^-^=
>> I just noticed a problem in the document's example: fixed-size types.
>> This is problematic because of integer promotion. Imagine a system in
>> which "int" were 64 bits. Then this code:
>> auto const ret = a + 100u;
>> would actually generate a result of type "const unsigned int", which is
>> 64 bits on such a platform. Then the overflow check does not work, and the
>> result won't saturate as intended.
>> This clouds the actual issue you're trying to get at. Using simply "int"
>> and "unsigned int" for the example solves the problem.
> I'm inclined to point the finger at "auto" here. Although this code would
> also not have been written if we taught to avoid relying on the "modulo"
> behaviour. The (I believe Google) check while processing JF's paper was
> that even unsigned overflow was often a bug.

Yes, I think auto is the problem. I didn't want to use auto in the
example, but I was trying to get the lines to not wrap in the Tony table.
As many people have noted, auto has fewer characters. Sounds like I need
to get rid of auto in the example and find a way to format the code.
Thanks for pointing that out.

> I am also going to ask the author if there is a response to a reaction
> that this encourages breaking the language into dialects.

Personally, I don't think it encourages breaking the language into dialects
any more than there already are dialects. GCC and Clang both offer the
-fwrapv and -ftrapv flags for people who want to control what happens on
signed integer overflow. So, at some level, the dialects are already
present. This change may make the dialects more explicit, but they already

> I would also like the author's take on the intended treatment of the
> well-formedness of signed overflow in constexpr.

The paper proposes that signed integer overflow should be implementation
defined. I'm the least qualified language lawyer on the committee, but my
take is that most implementations would stop compilation and issue a
diagnostic on constexpr signed integer overflow, even if the runtime
implementation does modulus wrapping. That is in line with preexisting
expectations for constexpr evaluation of floating point -- that constexpr
floating point evaluation need not have the same result as would occur at
runtime. And, personally, I'd be completely fine with that. But, since
it's up to the implementation, other models are possible.

Those are both great questions and, if there's an R1 of the paper, I'll
include both of them in the Reactions and Responses section. Thanks for
the help.

Another example of how using fixed-sized types can cloud issues due to
>> promotion:
>> std::uint16_t x = 65535u;
>> x *= x; // undefined behavior on most of today's platforms because of
>> promotion to signed int
That's fascinating and a bit appalling. And, now that you've pointed that
out, I see how it happens. I think that probably should be added to the
Motivating Example section of the paper if there is an R1 version.

At this point, do people think it would be worthwhile for me to put
together an R1 of the paper and put it on the Kona wiki? Or are we good
with the discussion on the reflector being sufficient for the moment?

Thanks again for your help and consideration.

Scott Schurr

> Melissa
>> On Tue, Jan 29, 2019 at 6:04 PM Scott Schurr <s.scott.schurr_at_[hidden]>
>> wrote:
>>> Greeting again SG12,
>>> Here's another email that I think got trapped for moderation yesterday
>>> but apparently can get through now. Sorry for the additional noise.
>>> Scott Schurr
>>> S.Scott.Schurr_at_[hidden]
>>> On Mon, Jan 28, 2019 at 10:13 AM Scott Schurr <s.scott.schurr_at_[hidden]>
>>> wrote:
>>>> Hi John,
>>>> Nice to hear from you. Thanks for your interest in the paper.
>>>> Regarding whether "can't happen" is a behavior, I'm expecting to hear
>>>> varied well studied opinions (like yours) during the paper discussion. My
>>>> perspective is that "can't happen" cannot be defined in a mechanistic way.
>>>> It's not like, "The gear used to turn left but now turns right." However I
>>>> think that "can't happen" can be defined in the sense that the result of an
>>>> explosion can be quite well defined. Given an explosion of sufficient
>>>> yield at a certain location there is a high probability that the building
>>>> will collapse, but we're uncertain where the individual bricks will fall.
>>>> We still understand the outcome sufficiently well to be able to talk about
>>>> it.
>>>> My feeling is that it's not that different from talking about race
>>>> conditions. We really don't know what the consequence of a race condition
>>>> will be. But we can define a race condition.
>>>> Thanks for your thoughts.
>>>> Scott Schurr
>>>> S.Scott.Schurr_at_[hidden]
>>>> On Sat, Jan 26, 2019 at 2:13 AM John McFarlane <john_at_[hidden]>
>>>> wrote:
>>>>> When I read that title, I also had the reaction "you have the wrong
>>>>> target" but in my case, I assumed the target was SG20. I think it's a great
>>>>> paper to send to that study group.
>>>>> My main concern, though, boils down to the idea that "Can't happen" is
>>>>> somehow a behaviour. It seems to be suggested, for example, that overflow
>>>>> as it occurs in current implementations can realistically be defined. I'm
>>>>> not sure that's practical because such behaviour is highly sensitive to
>>>>> many non-obvious factors. Overflow at a single point in the code may
>>>>> produce wildly different 'behaviours' depending on factors such as: from
>>>>> where it's invoked, various toolchain options and minor revisions to the
>>>>> implementation. And even with this information at hand, the write-up might
>>>>> well be onerous to the implementer and worse than useless for the user
>>>>> because it would involve describing in much detail the optimization
>>>>> algorithms involved. So I don't think implementation-defined is a
>>>>> straight-forward solution to the problem.
>>>>> Generally, I agree I'd like to see effort put toward thinking of the
>>>>> correct way to deliver the idea of UB. It's the wrong wording to give to
>>>>> users of the language. It's implementor speak. Like a bailiff using
>>>>> legalese to explain why somebody has just lost their home, it causes
>>>>> confusion and anger.
>>>>> On Sat, 26 Jan 2019 at 08:54 Marc Glisse <marc.glisse_at_[hidden]> wrote:
>>>>>> Hello,
>>>>>> just a couple points missing from the paper:
>>>>>> 1) with g++-7 -O2 -Wall, the motivating example on the left produces:
>>>>>> <source>: In function 'int32_t add_100_without_wrap(int32_t)':
>>>>>> <source>:8:3: warning: assuming signed overflow does not occur when
>>>>>> assuming that (X + c) < X is always false [-Wstrict-overflow]
>>>>>> if (ret < a)
>>>>>> However, we removed the warning from gcc-8 because it was too noisy
>>>>>> and
>>>>>> impossible to work around when the optimization is what you actually
>>>>>> want.
>>>>>> 2) At least with gcc, -ftrapv doesn't really work. You need
>>>>>> -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error
>>>>>> for
>>>>>> something roughly equivalent to what -ftrapv is supposed to do.
>>>>>> Now my opinion: you have the wrong target. Compilers that have a
>>>>>> -fwrapv
>>>>>> option (or -ftrapv or ubsan or ...) already indirectly describe the
>>>>>> default behavior as undefined (and the standard already describes it
>>>>>> as
>>>>>> undefined), so it is already documented. Adding a sentence or 2 in
>>>>>> the
>>>>>> standard and on pages that nobody reads won't help. It seems that you
>>>>>> want
>>>>>> to talk either to teachers, so they warn their students more about
>>>>>> the
>>>>>> properties of signed overflow, or to compiler writers, to convince
>>>>>> them to
>>>>>> change the default to -fwrapv or -ftrapv (I hope they don't) or add
>>>>>> more
>>>>>> warnings.
>>>>>> --
>>>>>> Marc Glisse
>>>>>> _______________________________________________
>>>>>> ub mailing list
>>>>>> ub_at_[hidden]
>>>>>> http://www.open-std.org/mailman/listinfo/ub
>>>>> _______________________________________________
>>> ub mailing list
>>> ub_at_[hidden]
>>> http://www.open-std.org/mailman/listinfo/ub
>> _______________________________________________
>> ub mailing list
>> ub_at_[hidden]
>> http://www.open-std.org/mailman/listinfo/ub
> _______________________________________________
> ub mailing list
> ub_at_[hidden]
> http://www.open-std.org/mailman/listinfo/ub

Received on 2019-01-30 20:07:56