On 8/23/20 7:28 AM, Bruno Haible wrote:
Thanks for the report. I didn't know that __typeof__ does not work for all kinds of expressions. (intprops uses __typeof__ as well.)
Almost all the places intprops.h uses __typeof__ are safe since they can't or shouldn't be bitfields. (Pretty much anything that uses sizeof will fail on bit-fields at compile-time.)
There was one place where the __typeof__ would have caused an unnecessary compile-time error, and I fixed that in the first attached patch, which also adds comments about arguments that shouldn't use bit-fields. The second attached patch is a minor cleanup.
>From 5d4cdc813c6751a833047ece3dbcf38d976270a6 Mon Sep 17 00:00:00 2001 From: Paul Eggert <[email protected]> Date: Sun, 23 Aug 2020 13:14:13 -0700 Subject: [PATCH 1/2] intprops: fix INT_MULTIPLY_WRAPV bit-field bug The bug occurs when using INT_MULTIPLY_WRAPV (a, b, c) where B is a bit-field, on older GCC or non-GCC compilers where we do things ourselves instead of using __builtin_mul_overflow. Without this fix, INT_MULTIPLY_WRAPV would not compile, due to applying sizeof to a bit-field. * lib/intprops.h (_GL_INT_MULTIPLY_RANGE_OVERFLOW): Promote B before giving it to TYPE_WIDTH, in case B is a bit-field. --- ChangeLog | 11 +++++++++++ lib/intprops.h | 13 ++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ab706ac4..a6caef9b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2020-08-23 Paul Eggert <[email protected]> + + intprops: fix INT_MULTIPLY_WRAPV bit-field bug + The bug occurs when using INT_MULTIPLY_WRAPV (a, b, c) where B + is a bit-field, on older GCC or non-GCC compilers where we do + things ourselves instead of using __builtin_mul_overflow. + Without this fix, INT_MULTIPLY_WRAPV would not compile, due + to applying sizeof to a bit-field. + * lib/intprops.h (_GL_INT_MULTIPLY_RANGE_OVERFLOW): + Promote B before giving it to TYPE_WIDTH, in case B is a bit-field. + 2020-08-23 Bruno Haible <[email protected]> supersede: Avoid a failure when writing to /dev/null in Solaris zones. diff --git a/lib/intprops.h b/lib/intprops.h index 6ee63244a..1bd93d11f 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -48,7 +48,7 @@ /* Minimum and maximum values for integer types and expressions. */ /* The width in bits of the integer type or expression T. - Do not evaluate T. + Do not evaluate T. T must not be a bit-field expression. Padding bits are not supported; this is checked at compile-time below. */ #define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) @@ -95,8 +95,9 @@ #endif /* Return 1 if the integer type or expression T might be signed. Return 0 - if it is definitely unsigned. This macro does not evaluate its argument, - and expands to an integer constant expression. */ + if it is definitely unsigned. T must not be a bit-field expression. + This macro does not evaluate its argument, and expands to an + integer constant expression. */ #if _GL_HAVE___TYPEOF__ # define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) #else @@ -109,6 +110,8 @@ #define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) /* Bound on length of the string representing an integer type or expression T. + T must not be a bit-field expression. + Subtract 1 for the sign bit if T is signed, and then add 1 more for a minus sign if needed. @@ -120,7 +123,7 @@ + _GL_SIGNED_TYPE_OR_EXPR (t)) /* Bound on buffer size needed to represent an integer type or expression T, - including the terminating null. */ + including the terminating null. T must not be a bit-field expression. */ #define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) @@ -566,7 +569,7 @@ ? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ ? (a) < (tmax) / (b) \ : ((INT_NEGATE_OVERFLOW (b) \ - ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \ + ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (+ (b)) - 1) \ : (tmax) / -(b)) \ <= -1 - (a))) \ : INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \ -- 2.17.1
>From 01405116164d46c58497fb3cf0fb8aae3955cf86 Mon Sep 17 00:00:00 2001 From: Paul Eggert <[email protected]> Date: Sun, 23 Aug 2020 13:14:14 -0700 Subject: [PATCH 2/2] intprops: be consistent about +X vs X+0 * lib/intprops.h (_GL_SIGNED_INT_MAXIMUM): Simplify. --- ChangeLog | 3 +++ lib/intprops.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a6caef9b0..e51ea41e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-08-23 Paul Eggert <[email protected]> + intprops: be consistent about +X vs X+0 + * lib/intprops.h (_GL_SIGNED_INT_MAXIMUM): Simplify. + intprops: fix INT_MULTIPLY_WRAPV bit-field bug The bug occurs when using INT_MULTIPLY_WRAPV (a, b, c) where B is a bit-field, on older GCC or non-GCC compilers where we do diff --git a/lib/intprops.h b/lib/intprops.h index 1bd93d11f..df66a3877 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -70,7 +70,7 @@ ? _GL_SIGNED_INT_MAXIMUM (e) \ : _GL_INT_NEGATE_CONVERT (e, 1)) #define _GL_SIGNED_INT_MAXIMUM(e) \ - (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1) + (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1) /* Work around OpenVMS incompatibility with C99. */ #if !defined LLONG_MAX && defined __INT64_MAX -- 2.17.1
