C++ Logo


Advanced search

[std-proposals] Remove integer promotions (was: Reduce undefined behavior of signed integer literal arithmetic operations)

From: Alejandro Colomar <alx.manpages_at_[hidden]>
Date: Fri, 28 Apr 2023 14:08:09 +0200
Hello Sebastian, Jonathan,

On 4/28/23 13:45, Sebastian Wittmeier via Std-Proposals wrote:
> An unsigned type would not help at all, as they have to wrap around and
> a < a + 1
> is not necessarily true for unsigned types (they only guarantee: a >= 0 && a + 1 >= 0). So signed types are the recommended type for loops in most cases.
> If one wants to make sure that a value is always positive or in some other range, one needs pre- and post-conditions and possibly test for them.
> Neither using signed nor using unsigned types prevent overflows or underflows or loss of precision for FP types.
> And in most programs it is not acceptable to get wrong arithmetic results, so making those UB conditions returning defined garbage instead (with lower performance) would not really help in those cases.
> -----Urspr√ľngliche Nachricht-----
> Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
> Gesendet:Fr 28.04.2023 12:42
> Betreff:Re: [std-proposals] Reduce undefined behavior of signed integer literal arithmetic operations
> An:std-proposals_at_[hidden];
> CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
> On Fri, Apr 28, 2023 at 8:42 AM Bo Persson via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>>> If that's the only reason why signed overflow is UB,
>> It's not.
>> No wrap around also lets the compiler assume that a < a + 1 is always
>> true. Useful for loop conditions.
> Well then let's make an exhaustive list of all the reasons why signed
> overflow is UB.

Here's reason number one, and which covers by extension all others:

- There's no agreement on what the compiler should do for INT_MAX+1.
   You won't be able to convince everyone to agree with your opinion.

Now, for my list of reasons, I don't think I can give you a complete
one, but can give you some of them.

- I want the compiler to emit diagnostics when I write accidentally
   code that I didn't intend to write. Having UB helps the compiler
   be able to understand that I did a mistake. If the behavior is
   well-defined, then the compiler has no way to know it for sure.
   Of course, there are still warnings about things that are likely
   to be accidents, even if they are well defined, but I prefer when
   redundancy in the compiler for detecting programming mistakes.

   Bottom line: UB is your friend; learn to love it.

- Mathematics should hold as much as possible. When I read some
   expression like `a < a + 1`, I don't want to have to remember
   quirks of C/C++.

- Your proposal is adding even more promotion rules. I would rather
   go the other way around and hereby I propose _removing_ the
   useless "integer promotions". They are just evil. Types narrower
   than int should hold by the same rules as types wider than int.

   Of course, I know this ain't goint to happen soon. Maybe adding
   a flag to compilers to enable/disable this rule would help
   transition. How about -f[no-]integer-promotions?

> I've already proposed a solution to the 'double negative' problem,
> i.e. -(-INT_MIN) == INT_MIN
> With regard to "a < a + 1" being always true, well then in the future
> it can sometimes be negative. If you don't want this to happen then I
> think you're using the wrong tool.

Why am I using the wrong tool? Please justify.

> I do realise that a massive
> proportion of C++ programmers use a signed integer type when an
> unsigned would be adequate, but individual programmers will just have
> to iron out their own bad habits.

Why are my habits wrong? Why should I use unsigned integers when I
explicitly don't want wrap-around behavior? I _do_ want Mathematics
to hold, and `a < a + 1` is a strong Mathematics guarantee.

Why isn't your habit wrong? If you want wrap-around behavior, it
should be you who should be using unsigned variables. If you want
signed wrap-around, you can store your values in unsigned variables,
and then convert to the signed variant for reading the signed value.
Since C23 guarantees 2's complement, you have a guarantee about what
will happen.



Received on 2023-04-28 12:08:12