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

Reply via email to