Discussion:
WCHAR_WIDTH with HP-UX cc
(too old to reply)
Bruno Haible
2017-03-15 21:04:14 UTC
Permalink
Raw Message
Hi Paul,

With cc on HP-UX 11.31, test-stdint.c fails to compile:

cc -DHAVE_CONFIG_H -I. -I.. -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I. -I.. -I./.. -I../gllib -I./../gllib -g -c -o test-stdint.o test-stdint.c
cc: "test-stdint.c", line 414: error 1511: Bit-field size must be a constant.
cc: "test-stdint.c", line 414: error 1613: Zero-sized struct.
cc: "test-stdint.c", line 414: warning 504: The sizeof operator applied to a zero-sized object.
cc: "test-stdint.c", line 416: error 1511: Bit-field size must be a constant.
cc: "test-stdint.c", line 416: error 1613: Zero-sized struct.
cc: "test-stdint.c", line 416: warning 504: The sizeof operator applied to a zero-sized object.
cc: "test-stdint.c", line 419: error 1511: Bit-field size must be a constant.
cc: "test-stdint.c", line 419: error 1613: Zero-sized struct.
cc: "test-stdint.c", line 419: warning 504: The sizeof operator applied to a zero-sized object.
*** Error exit code 1

The problematic line is:
verify_width (WCHAR_WIDTH, WCHAR_MIN, WCHAR_MAX);

In order to understand which of the three macros introduces the problem, I added
three lines:

int aa = WCHAR_WIDTH;
int ab = WCHAR_MIN;
int ac = WCHAR_MAX;

The initializations of 'ab' and 'ac' were OK, but the first line gives an error:

cc: "test-stdint.c", line 26: error 1521: Incorrect initialization.

Since WCHAR_WIDTH expands to a sequence of ca. 12890 characters, apparently
coming from
gllib/stdint.h:# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX)
I would suggest to simplify _GL_INTEGER_WIDTH by assuming that its value
MUST be one of 8, 16, 32, 64, 128. Gnulib does not attempt portability to
machines with 36-bit words or 3-bit integer types.

The same error appears also at
verify_width (WINT_WIDTH, WINT_MIN, WINT_MAX);
and
verify_width (SIG_ATOMIC_WIDTH, SIG_ATOMIC_MIN, SIG_ATOMIC_MAX);

Bruno
Paul Eggert
2017-03-16 08:10:37 UTC
Permalink
Raw Message
Post by Bruno Haible
I would suggest to simplify _GL_INTEGER_WIDTH by assuming that its value
MUST be one of 8, 16, 32, 64, 128.
We could do that as a special case if __HP_cc is defined, as we know that
particular compiler doesn't work with other-width integers. Does the attached
(untested) patch work for you?

I'd rather keep the generic code with non-buggy compilers. You're right that
much of Gnulib fails to work on unusual machines, but when it's easy to support
the weird ones I'd rather do so, partly because compilers do exist for machines
with non-powers-of-two widths, partly because it's more fun to be portable.
Bruno Haible
2017-03-16 23:05:21 UTC
Permalink
Raw Message
Hi Paul,
Post by Paul Eggert
We could do that as a special case if __HP_cc is defined, as we know that
particular compiler doesn't work with other-width integers. Does the attached
(untested) patch work for you?
With it, the initialization

int aa = WCHAR_WIDTH;

no longer produces an error "Incorrect initialization." That's good.

But the error in the 'verify' line is still there:
cc: "test-stdint.c", line 419: error 1511: Bit-field size must be a constant.
cc: "test-stdint.c", line 419: error 1613: Zero-sized struct.
cc: "test-stdint.c", line 419: warning 504: The sizeof operator applied to a zero-sized object.

I can see from a compilation to .s the following values:
WCHAR_WIDTH = 0x00000020
WCHAR_MIN = 0x00000000
WCHAR_MAX = 0xFFFFFFFF

The following line fails:
extern int (*_gl_verify_function419 (void)) [(!!sizeof (struct { unsigned int _gl_verify_error_if_negative: (((((((0u) + 1) << ((32) ? (32) - 1 - (0) : 0)) - 1) * 2 + 1)) >> (((((((((0u) + 1) << ((32) ? (32) - 1 - (0) : 0)) - 1) * 2 + 1)) >> 31 >> 1 ? 64 : ((((((0u) + 1) << ((32) ? (32) - 1 - (0) : 0)) - 1) * 2 + 1)) >> 16 ? 32 : ((((((0u) + 1) << ((32) ? (32) - 1 - (0) : 0)) - 1) * 2 + 1)) >> 8 ? 16 : 8)) - 1 - ((((0) ? ~ (((((0u) + 1) << ((32) ? (32) - 1 - (0) : 0)) - 1) * 2 + 1) : (0u))) < 0)) == 1) ? 1 : -1; }))] ;

I did successive simplifications:

FAILS:
struct foo { unsigned int _gl_verify_error_if_negative: ((0xffffffffu) >> (((0x0u ? 64 : (0xffffu) ? 32 : (0xffffffu) ? 16 : 8)) - 1 - ((((0) ? ~ 0xffffffffu : (0u))) < 0)) == 1) ? 1 : -1; } ;
SUCCEEDS:
struct foo { unsigned int _gl_verify_error_if_negative: ((0xffffffffu) >> (((0x0u ? 64 : (0xffffu) ? 32 : (0xffffffu) ? 16 : 8)) - 1 - ((((0u))) < 0)) == 1) ? 1 : -1; } ;

FAILS:
struct foo { unsigned int _gl_verify_error_if_negative: (0xffffffffu >> (31 - ((0 ? 0x0u : 0u) < 0)) == 1) ? 1 : -1; } ;
SUCCEEDS:
struct foo { unsigned int _gl_verify_error_if_negative: (0xffffffffu >> (31 - ((0u) < 0)) == 1) ? 1 : -1; } ;

So, conditional expressions inside arithmetic expressions inside bit field sizes
are apparently the problem.

Adding

#undef WCHAR_MIN
#define WCHAR_MIN 0u

makes the error go away. But even a seemingly innocent replacement

#undef WCHAR_MIN
#define WCHAR_MIN (0 * 0u)

produces the error.

It seems that this compiler has problem with type inference inside constant
expressions and that the "Bit-field size must be a constant" message is a
manifestation of some kind of internal compiler error.

I'm pushing this fix. It's a little bit more ugly than the previous code,
but it's still generic.

And with it, no change to _GL_INTEGER_WIDTH is needed. The problem in
# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX)
was apparently due to the WCHAR_MIN macro, not the _GL_INTEGER_WIDTH macro.


2017-03-16 Bruno Haible <***@clisp.org>

stdint: Fix test compilation failure with HP-UX 11 cc.
* lib/stdint.in.h (_STDINT_MIN): Remove macro.
(_STDINT_UNSIGNED_MIN, _STDINT_SIGNED_MIN): New macros.
(PTRDIFF_MIN, SIG_ATOMIC_MIN, WCHAR_MIN, WINT_MIN): Define using
_STDINT_UNSIGNED_MIN, _STDINT_SIGNED_MIN.

diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 7535962..9583fd9 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -128,8 +128,13 @@
Return an unspecified value if BITS == 0, adding a check to pacify
picky compilers. */

-# define _STDINT_MIN(signed, bits, zero) \
- ((signed) ? ~ _STDINT_MAX (signed, bits, zero) : (zero))
+/* These are separate macros, because if you try to merge these macros into
+ a single one, HP-UX cc rejects the resulting expression in constant
+ expressions. */
+# define _STDINT_UNSIGNED_MIN(bits, zero) \
+ (zero)
+# define _STDINT_SIGNED_MIN(bits, zero) \
+ (~ _STDINT_MAX (1, bits, zero))

# define _STDINT_MAX(signed, bits, zero) \
(((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1)
@@ -512,15 +517,15 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
# undef PTRDIFF_MAX
# if @APPLE_UNIVERSAL_BUILD@
# ifdef _LP64
-# define PTRDIFF_MIN _STDINT_MIN (1, 64, 0l)
+# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l)
# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l)
# else
-# define PTRDIFF_MIN _STDINT_MIN (1, 32, 0)
+# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0)
# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0)
# endif
# else
# define PTRDIFF_MIN \
- _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, ***@PTRDIFF_T_SUFFIX@)
+ _STDINT_SIGNED_MIN (@BITSIZEOF_PTRDIFF_T@, ***@PTRDIFF_T_SUFFIX@)
# define PTRDIFF_MAX \
_STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, ***@PTRDIFF_T_SUFFIX@)
# endif
@@ -528,9 +533,13 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
/* sig_atomic_t limits */
# undef SIG_ATOMIC_MIN
# undef SIG_ATOMIC_MAX
-# define SIG_ATOMIC_MIN \
- _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
- ***@SIG_ATOMIC_T_SUFFIX@)
+# if @HAVE_SIGNED_SIG_ATOMIC_T@
+# define SIG_ATOMIC_MIN \
+ _STDINT_SIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, ***@SIG_ATOMIC_T_SUFFIX@)
+# else
+# define SIG_ATOMIC_MIN \
+ _STDINT_UNSIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, ***@SIG_ATOMIC_T_SUFFIX@)
+# endif
# define SIG_ATOMIC_MAX \
_STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
***@SIG_ATOMIC_T_SUFFIX@)
@@ -566,16 +575,26 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
# endif
# undef WCHAR_MIN
# undef WCHAR_MAX
-# define WCHAR_MIN \
- _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, ***@WCHAR_T_SUFFIX@)
+# if @HAVE_SIGNED_WCHAR_T@
+# define WCHAR_MIN \
+ _STDINT_SIGNED_MIN (@BITSIZEOF_WCHAR_T@, ***@WCHAR_T_SUFFIX@)
+# else
+# define WCHAR_MIN \
+ _STDINT_UNSIGNED_MIN (@BITSIZEOF_WCHAR_T@, ***@WCHAR_T_SUFFIX@)
+# endif
# define WCHAR_MAX \
_STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, ***@WCHAR_T_SUFFIX@)

/* wint_t limits */
# undef WINT_MIN
# undef WINT_MAX
-# define WINT_MIN \
- _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, ***@WINT_T_SUFFIX@)
+# if @HAVE_SIGNED_WINT_T@
+# define WINT_MIN \
+ _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, ***@WINT_T_SUFFIX@)
+# else
+# define WINT_MIN \
+ _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, ***@WINT_T_SUFFIX@)
+# endif
# define WINT_MAX \
_STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, ***@WINT_T_SUFFIX@)
Loading...