[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: AC_TYPE_UINT64_T produces wrong result with GCC 3.4.4 on Tru64 UNIX
From: |
Eric Blake |
Subject: |
Re: AC_TYPE_UINT64_T produces wrong result with GCC 3.4.4 on Tru64 UNIX V4.0F |
Date: |
Tue, 20 Oct 2009 14:50:58 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Eric Blake <ebb9 <at> byu.net> writes:
> According to Rainer Orth on 10/19/2009 9:23 AM:
> > checking for uint64_t... unsigned int
> > $ gcc-3.4.4 -c conftest.c
> > conftest.c: In function `main':
> > conftest.c:4: warning: right shift count >= width of type
> > $ echo $?
> > 0
>
> Thanks for the report. It is indeed a bug, and we should be able to work
> around it. We need to break x>>63 into the more appropriate
> ((x>>31)>>31)>>1 to work around this.
Like in the attached patch. It's hard for me to test, since most systems these
days already have int64_t, so my for loop wasn't getting that far, but by
inspection, it looks like it will solve your problem.
> But before I work on the necessary
> m4 magic, is it also a problem with smaller types?
On further review, I don't think this is an issue. Checking a wider candidate
(long) against a narrower type (uint8_t) is not the issue, only a narrower
candidate (int) against a wider type (uint64_t), and using a shift width that
works for the wider type but gives undefined behavior for the narrower type.
But since we control the order in which types are checked, and since my patch
breaks things up to never shift more than half the target type (that is, for
uint64_t, my patch never shifts more than 31), we can now safely check for a
half-width type first. That means we don't have to reorder checks, so that we
maintain the current status quo of fewer compilation attempts for uint32_t than
for uint64_t (on the assumption that more configure scripts check for the
former than the latter).
An alternate patch would have been reordering the shell for loop to test long
long, long, then int; that way, the checks are ordered widest to narrowest.
But that has the potential for API changes if the macro selects a different
type (but equivalent width) than what it did before the reordering, and it also
penalizes the time taken for selecting the type to use for uint32_t.
A potential followup optimization would be updating ac_fn_c_find_intX_t to take
an additional parameter of the C type most likely to work, and inserting that
type into the shell for loop between intX_t and int; that way, finding int8_t
can more quickly check for 'signed char' without first cycling through int,
long, long long, and short. But like I said, the number of platforms these
days without pre-defined intX_t is getting smaller, so few people would benefit
from such an optimization.
From: Eric Blake <address@hidden>
Date: Tue, 20 Oct 2009 08:30:03 -0600
Subject: [PATCH] Fix AC_TYPE_UINT64_T on Tru64 with gcc 3.4.4.
* lib/autoconf/types.m4 (_AC_TYPE_UNSIGNED_INT_BODY)
(_AC_TYPE_INT_BODY): Avoid undefined behavior of attempting shift
wider than type.
* NEWS: Document this.
Reported by Rainer Orth.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 9 +++++++++
NEWS | 4 ++++
lib/autoconf/types.m4 | 14 ++++++++++----
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 65b4a91..0470d59 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-10-20 Eric Blake <address@hidden>
+
+ Fix AC_TYPE_UINT64_T on Tru64 with gcc 3.4.4.
+ * lib/autoconf/types.m4 (_AC_TYPE_UNSIGNED_INT_BODY)
+ (_AC_TYPE_INT_BODY): Avoid undefined behavior of attempting shift
+ wider than type.
+ * NEWS: Document this.
+ Reported by Rainer Orth.
+
2009-09-16 Eric Blake <address@hidden>
Optimize AC_REPLACE_FUNCS.
diff --git a/NEWS b/NEWS
index f738426..666cd4f 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,10 @@ GNU Autoconf NEWS - User visible changes.
made it fail with some Fortran compilers (regression introduced in
2.64).
+** The AC_TYPE_UINT64_T and AC_TYPE_INT64_T macros have been fixed to no
+ longer mistakenly select a 32-bit type on some compilers (bug present
+ since macros were introduced in 2.59c).
+
** The following documented autotest macros are new:
AT_CHECK_EUNIT
diff --git a/lib/autoconf/types.m4 b/lib/autoconf/types.m4
index a537967..7a73fc2 100644
--- a/lib/autoconf/types.m4
+++ b/lib/autoconf/types.m4
@@ -629,17 +629,21 @@ m4_define([_AC_TYPE_INT_BODY],
[ AS_LINENO_PUSH([$[]1])
AC_CACHE_CHECK([for int$[]2_t], [$[]3],
[AS_VAR_SET([$[]3], [no])
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
for ac_type in int$[]2_t 'int' 'long int' \
'long long int' 'short int' 'signed char'; do
AC_COMPILE_IFELSE(
[AC_LANG_BOOL_COMPILE_TRY(
[AC_INCLUDES_DEFAULT],
- [0 < ($ac_type) (((($ac_type) 1 << ($[]2 - 2)) - 1) * 2 + 1)])],
+ [enum { N = $[]2 / 2 - 1 };
+ 0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)])],
[AC_COMPILE_IFELSE(
[AC_LANG_BOOL_COMPILE_TRY(
[AC_INCLUDES_DEFAULT],
- [($ac_type) (((($ac_type) 1 << ($[]2 - 2)) - 1) * 2 + 1)
- < ($ac_type) (((($ac_type) 1 << ($[]2 - 2)) - 1) * 2 + 2)])],
+ [enum { N = $[]2 / 2 - 1 };
+ ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+ < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2)])],
[],
[AS_CASE([$ac_type], [int$[]2_t],
[AS_VAR_SET([$[]3], [yes])],
@@ -679,12 +683,14 @@ m4_define([_AC_TYPE_UNSIGNED_INT_BODY],
[ AS_LINENO_PUSH([$[]1])
AC_CACHE_CHECK([for uint$[]2_t], $[]3,
[AS_VAR_SET([$[]3], [no])
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
for ac_type in uint$[]2_t 'unsigned int' 'unsigned long int' \
'unsigned long long int' 'unsigned short int' 'unsigned char'; do
AC_COMPILE_IFELSE(
[AC_LANG_BOOL_COMPILE_TRY(
[AC_INCLUDES_DEFAULT],
- [($ac_type) -1 >> ($[]2 - 1) == 1])],
+ [(($ac_type) -1 >> ($[]2 / 2 - 1)) >> ($[]2 / 2 - 1) == 3])],
[AS_CASE([$ac_type], [uint$[]2_t],
[AS_VAR_SET([$[]3], [yes])],
[AS_VAR_SET([$[]3], [$ac_type])])])
--
1.6.4.2