bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: proposed new module intprops-test


From: Bruno Haible
Subject: Re: proposed new module intprops-test
Date: Thu, 19 May 2011 15:07:35 +0200
User-agent: KMail/1.9.9

Hi Paul,

>  2011-05-19  Paul Eggert  <address@hidden>
>  
> +     intprops: work around C compiler bugs
> +     * lib/intprops.h (INT_MULTIPLY_RANGE_OVERFLOW): Work around compiler
> +     bug in Sun C 5.11 2010/08/13 and other compilers; see
> +     <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>.

Thanks, this patch fixed the errors on OSF/1 5.1 and reduced the errors on
Solaris 9 to only one:

cc -O -DHAVE_CONFIG_H -I.  -DGNULIB_STRICT_CHECKING=1  -I. -I.  -I.. -I./..  -I.
./gllib -I./../gllib    -g -c test-intprops.c
"test-intprops.c", line 40: non-constant bit-field size
"test-intprops.c", line 40: bit-field size < 0: _gl_verify_error_if_negative
cc: acomp failed for test-intprops.c
*** Error code 2

It has no effect on HP-UX and IRIX. So that bug with && and || is specific
to OSF/1 and Solaris.

> From e9d47071a68819604a698a9ad5f188472e1c3792 Mon Sep 17 00:00:00 2001
> From: Paul Eggert <address@hidden>
> Date: Thu, 19 May 2011 01:43:17 -0700
> Subject: [PATCH 3/3] intprop-tests: port to older and more-pedantic compilers
> 
> * modules/intprops-tests (Files): Add tests/macros.h.
> * tests/test-intprops.c: Include macros.h.
> (TYPE_IS_INTEGER): Use ASSERT, not verify, to test this macro, as
> it's no longer documented to expand to an integer constant expression.
> (TYPE_SIGNED): Use ASSERT, not verify, to test this macro when the
> argument is floating point, as it's no longer documented to expand
> to an integer constant expression in that case.

This part of the patch fixed the build on Solaris 9.

> (UINT_MAX, ULONG_MAX, UINTMAX_MAX): Redefine to work around
> compiler bugs reported by Bruno Haible.  See
> <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>.
> (U0, U1): New constants, to work around the same bugs.  Also,
> in tests, use e.g., "(unsigned int) 39" rather than "39u".

This part of the patch has no effect on HP-UX, IRIX, and neither on
OSF/1 and Solaris where the test already compiles fine. You could just as
well revert it.

Analysis of the HP-UX cc bug: Here are successive simplifications of the
expressions. I annotated them with the "cc -c" result.

===============================================================================
#include <config.h>

#include "intprops.h"
#include "verify.h"

#include <stdbool.h>
#include <inttypes.h>

#define check_binop(op, a, b, min, max, overflow)                      \
  (INT_##op##_RANGE_OVERFLOW (a, b, min, max) == (overflow)            \
   && INT_##op##_OVERFLOW (a, b) == (overflow))

/* Error */
verify (check_binop (ADD, UINT_MAX, 1u, 0u, UINT_MAX, true));

/* Error */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, 0u, UINT_MAX) == true && 
INT_ADD_OVERFLOW (UINT_MAX, 1u) == true);

/* OK */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, 0u, UINT_MAX) == true);

/* Error */
verify (INT_ADD_OVERFLOW (UINT_MAX, 1u) == true);

/* Error */
verify (_GL_BINARY_OP_OVERFLOW (UINT_MAX, 1u, _GL_ADD_OVERFLOW) == true);

/* Error */
verify (_GL_ADD_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)) == true);

/* Error */
verify ((_GL_INT_MINIMUM (UINT_MAX | 1u) < 0 ? INT_ADD_RANGE_OVERFLOW 
(UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), _GL_INT_MAXIMUM (UINT_MAX | 
1u)) : UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u 
: UINT_MAX + 1u < 1u) == true);

/* Error */
verify (_GL_INT_MINIMUM (UINT_MAX | 1u) < 0 ? INT_ADD_RANGE_OVERFLOW (UINT_MAX, 
1u, _GL_INT_MINIMUM (UINT_MAX | 1u), _GL_INT_MAXIMUM (UINT_MAX | 1u)) : 
UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u : 
UINT_MAX + 1u < 1u);

/* OK */
verify (UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u 
: UINT_MAX + 1u < 1u);

/* Error */
verify (_GL_INT_MINIMUM (UINT_MAX | 1u) >= 0);

/* Error */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)));

/* Error */
verify (!INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)));

/* Error */
verify (_GL_INT_MINIMUM (UINT_MAX) >= 0);

/* Error */
verify (_GL_INT_MINIMUM (1u) >= 0);

/* Error */
verify (!_GL_INT_SIGNED (1u));

/* Error */
verify (_GL_INT_CONVERT (1u, 0) >= 0);

/* Error */
verify (1u - 1u + 0 >= 0);

/* Error */
verify (1u - 1u >= 0);

/* Error */
verify (1u + 0 >= 0);

/* OK */
verify (1u >= 0);
===============================================================================

As you can see, plus and minus expressions of which one operand is unsigned are
not understood by this compiler. It yells
"error 1511: Bit-field size must be a constant."

Writing  (unsigned int) 1  instead of  1u  does not help.

So I think, you will have to use ASSERT here instead of verify.

Analysis of the IRIX cc bug:
===============================================================================
#include <config.h>

#include "intprops.h"
#include "verify.h"

#include <stdbool.h>
#include <inttypes.h>

#define check_binop(op, a, b, min, max, overflow)                      \
  (INT_##op##_RANGE_OVERFLOW (a, b, min, max) == (overflow)            \
   && INT_##op##_OVERFLOW (a, b) == (overflow))

/* Error */
verify (check_binop (ADD, UINT_MAX, 1u, 0u, UINT_MAX, true));

/* Error */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, 0u, UINT_MAX) == true && 
INT_ADD_OVERFLOW (UINT_MAX, 1u) == true);

/* OK */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, 0u, UINT_MAX) == true);

/* Error */
verify (INT_ADD_OVERFLOW (UINT_MAX, 1u) == true);

/* Error */
verify (_GL_BINARY_OP_OVERFLOW (UINT_MAX, 1u, _GL_ADD_OVERFLOW) == true);

/* Error */
verify (_GL_ADD_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)) == true);

/* Error */
verify ((_GL_INT_MINIMUM (UINT_MAX | 1u) < 0 ? INT_ADD_RANGE_OVERFLOW 
(UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), _GL_INT_MAXIMUM (UINT_MAX | 
1u)) : UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u 
: UINT_MAX + 1u < 1u) == true);

/* Error */
verify (_GL_INT_MINIMUM (UINT_MAX | 1u) < 0 ? INT_ADD_RANGE_OVERFLOW (UINT_MAX, 
1u, _GL_INT_MINIMUM (UINT_MAX | 1u), _GL_INT_MAXIMUM (UINT_MAX | 1u)) : 
UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u : 
UINT_MAX + 1u < 1u);

/* OK */
verify (UINT_MAX < 0 ? 1u <= UINT_MAX + 1u : 1u < 0 ? UINT_MAX <= UINT_MAX + 1u 
: UINT_MAX + 1u < 1u);

/* OK */
verify (_GL_INT_MINIMUM (UINT_MAX | 1u) >= 0);

/* Error */
verify (INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)));

/* Error */
verify (!INT_ADD_RANGE_OVERFLOW (UINT_MAX, 1u, _GL_INT_MINIMUM (UINT_MAX | 1u), 
_GL_INT_MAXIMUM (UINT_MAX | 1u)));

/* Error */
verify (1u < 0 ? UINT_MAX < _GL_INT_MINIMUM (UINT_MAX | 1u) - 1u : 
_GL_INT_MAXIMUM (UINT_MAX | 1u) - 1u < UINT_MAX);

/* OK */
verify (_GL_INT_MAXIMUM (UINT_MAX | 1u) - 1u < UINT_MAX);

/* Error */
verify (0 ? UINT_MAX < _GL_INT_MINIMUM (UINT_MAX | 1u) - 1u : 1);

/* Error */
verify (0 ? _GL_INT_MINIMUM (UINT_MAX | 1u) >= 0 : 1);

/* Error */
verify (0 ? _GL_INT_MINIMUM (1u) >= 0 : 1);

/* Error */
verify (0 ? (_GL_INT_SIGNED (1u) ? - _GL_INT_TWOS_COMPLEMENT (1u) - 
_GL_SIGNED_INT_MAXIMUM (1u) : _GL_INT_CONVERT (1u, 0)) : 1);

/* OK */
verify (0 ? _GL_INT_SIGNED (1u) : 1);

/* OK */
verify (!_GL_INT_SIGNED (1u));

verify (0 ? - _GL_INT_TWOS_COMPLEMENT (1u) - _GL_SIGNED_INT_MAXIMUM (1u) : 1);

/* OK */
verify (0 ? _GL_INT_CONVERT (1u, 0) : 1);

/* OK */
verify (!_GL_INT_CONVERT (1u, 0));

/* OK */
verify (0 ? (0 ? - _GL_INT_TWOS_COMPLEMENT (1u) - _GL_SIGNED_INT_MAXIMUM (1u) : 
_GL_INT_CONVERT (1u, 0)) : 1);

/* Error */
verify (0 ? (_GL_INT_SIGNED (1u) ? - 1 - _GL_SIGNED_INT_MAXIMUM (1u) : 
_GL_INT_CONVERT (1u, 0)) : 1);

/* Error */
verify (0 ? (_GL_INT_SIGNED (1u) ? - 1 - _GL_SIGNED_INT_MAXIMUM (1u) : 0u) : 1);

/* Error */
verify (0 ? (_GL_INT_SIGNED (1u) ? - 1 - 0x7fff : 0u) : 1);

/* OK */
verify (0 ? 0u : 1);

/* Error */
verify (0 ? (1u - 1u + -1 < 0 ? - 1 - 0x7fff : 0u) : 1);

/* Error */
verify (0 ? (0u + -1 < 0 ? - 1 - 0x7fff : 0u) : 1);

/* OK */
verify (0 ? (0u - 1 < 0 ? - 1 - 0x7fff : 0u) : 1);
===============================================================================

So here apparently the problem is adding an unsigned value and -1. The following
change fixes this error for me:

#define _GL_INT_SIGNED(e) (_GL_INT_CONVERT (e, -1) < 0)
#undef _GL_INT_SIGNED
#define _GL_INT_SIGNED(e) ((e) - (e) - 1 < 0)

Other errors still remain; to be investigated in the next round.

Bruno
-- 
In memoriam Anne Boleyn <http://en.wikipedia.org/wiki/Anne_Boleyn>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]