C++ Logo

sg7

Advanced search

[SG7] Disambiguating constexpr overflow behaviour

From: philippe dunski <dunski.philippe_at_[hidden]>
Date: Mon, 16 Dec 2019 18:32:48 +0100
Hello,

It seems there is some confusion between overflow in a constexpr and
overflow in a runtime behaviour.

Let me explain:

main.cpp tries to define a constexpr with (MIN - 1) and (MAX + 1) for each
of
- std::int8_t
- std::int16_t
- std::int32_t
- std::int64_t
- std::uint8_t
- std::uint16_t
- std::uint32_t
- std::uint64_t

IMO, when specifically speaking about constexpr overflow should, simply,
produce a compile time error, because developer specifically ask to the
compiler to hold a value which doesn't fits in the providen type.

As you can see in error_clang.txt file, clang 9.0.0 only recognize 12 case
on 16 as compile time error.

Depending of its version Gcc's behaviour is more "erratic" and justify the
error in at least two ways (sometime because of overflow, sometimes
because, when microsoft's compiler only produces some warning, but agrees
to compile this code

But they are some rules about promotion
<https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion>that
contradict such behaviour.

I'm in peace with those rules, as far as they apply at runtime. But, at
compile time, and more specifically when dealing with constexpr they are,
IMO, just irrelevant, because compiler should not be able to say "wel, I
know that you asked a (u)intX_t value, but I give you a (u)int2X_t one,
because of the overflow".

In the same time, we have the overflow rules which says that (UINT_MAX + 1)
and (UINT_IN -1) are equal to 0.

Once again, I'm in peace with that ... in a runtime context.

But, once again, in a constexpr context, those rule is IMO irrelevant.

Maybe should you disambiguating such behaviour by explicitly saying that
constexpr should be constrainted to the range allowed by them type. In
other words that
static constexpr (u)intX_t min = std::numeric_limits<(u)intX_t>::min() -1;
and
static constexpr (u)intX_t max = std::numeric_limits<(u)intX_t>::max() +1;
should always produce a compile time error, even if
static constepxr (u)int2X_t = std::numeric_limits<(u)intX_t>::min() -1; is
always a correct conversion / promotion, holding a correct value.

I will not try to express such thing in the standard, but maybe some of you
could do it?

PS: forgive my poor english, but my mother tongue is French

Received on 2019-12-16 10:36:02