]> www.ginac.de Git - cln.git/commit
Commit 2f799401454292 (`Replace typedef int[<negative>] trick with static_assert.`)
authorAlexey Sheplyakov <asheplyakov@altlinux.org>
Wed, 4 Dec 2019 22:57:14 +0000 (23:57 +0100)
committerRichard Kreckel <kreckel@ginac.de>
Wed, 4 Dec 2019 22:57:14 +0000 (23:57 +0100)
commit8f1a04a1139eecee3922a49dfce5b453eb6cef5a
tree88149d474afaf86a4dc58c06d512fc7a1cff93df
parent9f59becf9642ca3ec6446aa9c49cea2abb99275c
Commit 2f799401454292 (`Replace typedef int[<negative>] trick with static_assert.`)
breaks cross compilation due to invalid `include/cln/intparam.h` header
produced by the configure script.

CL_INTPARAM_BITSIZE relies on integer multiplication overflow to find out
the bit size of various integer types. However singed integer overflow
is an undefined behavior. Apparently in some contexts GCC uses mod 2^N
arithmetics to evaluate the signed integer expressions. As a result
`typedef int[2*((T)((T)2 * ... * (T)2) == 0) - 1]` trick works with both
signed and unsigned integers (and gives the correct result).

Howerver GCC considers an expression involving an integer overflow as
a non-constant, and refuses to use it in `static_assert`:

$ cat signed_overflow.cc

void f() {
static_assert((int)((int)(1 << 30) * (int)2 * (int)2) == 0, "");
}

$ g++ -c signed_overflow.cc

signed_overflow.cc: In function ‘void f()’:
signed_overflow.cc:2:37: warning: integer overflow in expression [-Woverflow]
  static_assert((int)((int)(1 << 30) * (int)2 * (int)2) == 0, "");
                      ~~~~~~~~~~~~~~~^~~~~~~~
signed_overflow.cc:2:2: error: non-constant condition for static assertion
  static_assert((int)((int)(1 << 30) * (int)2 * (int)2) == 0, "");
  ^~~~~~~~~~~~~

As a result `static_assert((T)((T)2 * ... * (T)2) == 0, "")` never holds
since either 1) the condition can't possibly hold without an overflow,
or 2) GCC rejects the expression when the overflow occurs.

Keep using the old good `typedef int[negative]` in CL_INTPARAM_BITSIZE
to avoid the problem.
m4/intparam.m4