[libcxx-dev] [libcxx-bugs] Incoherent behaviour on integer overflow

Mikhail Maltsev via libcxx-dev libcxx-dev at lists.llvm.org
Mon Jan 27 10:29:42 PST 2020

On 1/27/20 5:56 PM, Hans Wennborg via libcxx-dev wrote:
> Trying again, with the original attachments.
> On Mon, Jan 27, 2020 at 9:54 AM Hans Wennborg <hans at chromium.org> wrote:
>> +libcxx-dev as I'm not sure how many people read libcxx-bugs.
>> On Mon, Jan 27, 2020 at 9:37 AM phiippe dunski via libcxx-bugs
>> <libcxx-bugs at lists.llvm.org> wrote:
>>> Hello,
>>> I'm not sure that this mail should really have to be sent on this list, Maybe should I report this to specific clang mailing list. But, I hope you put me on the right way...
>>> Here is the overflow_error.cpp which contains what I expected to be 16 error case when using std::integral_constant.
>>> The point was, for me, perfectly clear : for each integer type, if I try to define some constant whose value is  std::numeric_limits<the_type>::min()-1 or std::numeric_limits<the_type>::max() + 1, I should get the same behaviour : at least some compile time warning, or mabe even some compile time error.
>>> Having two error cases for each data type, and eight data types, I was expecting to get ... sixteen error when trying to compile this file.
>>> But, as you can see it in the error_output.txt, they are only fourteen errors:
>>> using std::numeric_limits<uint32_t>::max() +1 and std::numeric_limits<uint64_t>::max() + 1 do not produce the same behaviour than usigne other data types or values.
The behavior is correct. There are 2 different kinds of errors here:

1a. For int8_t, int16_t, uint8_t and uint16_t: when computing e.g.
std::numeric_limits<std::int8_t>::min()-1, the left hand side is promoted to int
according to the standard promotion rules, then the computation is performed,
the result is an integral constant -129 of type int not fitting in int8_t. This
causes the instantiation of std::integral_constant<std::int8_t, ...> to fail.

1b. Same applies to std::integral_constant<std::uint32_t, -1>

2. For int32_t and int64_t: evaluating e.g.
(std::numeric_limits<std::int32_t>::min() - 1) causes signed integer overflow,
i.e., undefined behavior. Since the expression is evaluated as a constant
expression, the UB is diagnosed by the compiler.

For uint32_t and uint64_t neither promotion, nor signed overflow applies. The
result is wrapped, e.g. (std::numeric_limits<std::uint32_t>::max() + 1) is
constant 0 of type uint32_t.

  Mikhail Maltsev
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

More information about the libcxx-dev mailing list