]> www.ginac.de Git - cln.git/commitdiff
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)
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

index d7830b0a77d90e51c00578f534f99cf937edde73..7782fc5098b60779c5e91c564d89e5a6bfc319ad 100644 (file)
@@ -258,7 +258,7 @@ AC_DEFUN([CL_INTPARAM_BITSIZE],
 [
   n=1; x="($1)2"
   while true; do
-    AC_TRY_COMPILE([], [static_assert(($1)($x) == 0, "");],
+    AC_TRY_COMPILE([], [typedef int verify[2*(($1)($x) == 0) - 1];],
       [$2=$n; break;],
       [if test $n = 1000; then $2=; break; fi;])
     n=`expr $n + 1`; x="$x * ($1)2"