From: Alexey Sheplyakov Date: Wed, 4 Dec 2019 22:57:14 +0000 (+0100) Subject: Commit 2f799401454292 (`Replace typedef int[] trick with static_assert.`) X-Git-Tag: cln_1-3-6~1 X-Git-Url: https://www.ginac.de/CLN/cln.git//cln.git?a=commitdiff_plain;h=8f1a04a1139eecee3922a49dfce5b453eb6cef5a;p=cln.git Commit 2f799401454292 (`Replace typedef int[] 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. --- diff --git a/m4/intparam.m4 b/m4/intparam.m4 index d7830b0..7782fc5 100644 --- a/m4/intparam.m4 +++ b/m4/intparam.m4 @@ -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"