stdint: Use __extension__ on long long constants
Commit Message
Most uses of long long in stdint.h are guarded with __extension__ to
prevent them from issuing warnings with -std=c89 -pedantic. However,
on 32-bit platforms the 64-bit integer constant macros append LL or
ULL without marking it as an __extension__.
As a result, GCC issues this warning:
$ gcc -m32 -std=c89 -pedantic -c -o stdintext.o stdintext.c
In file included from stdint.h:9:0,
from stdintext.c:1:
stdintext.c:3:23: warning: use of C99 long long integer constant
[-Wlong-long]
uint64_t i = UINT64_C(0);
Prefix all ## LL and ## ULL macros with __extension__ to suppress
these warnings.
---
stdlib/stdint.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
Comments
* Dennis Lambe, Jr.:
> Most uses of long long in stdint.h are guarded with __extension__ to
> prevent them from issuing warnings with -std=c89 -pedantic. However,
> on 32-bit platforms the 64-bit integer constant macros append LL or
> ULL without marking it as an __extension__.
>
> As a result, GCC issues this warning:
>
> $ gcc -m32 -std=c89 -pedantic -c -o stdintext.o stdintext.c
> In file included from stdint.h:9:0,
> from stdintext.c:1:
> stdintext.c:3:23: warning: use of C99 long long integer constant
> [-Wlong-long]
> uint64_t i = UINT64_C(0);
>
> Prefix all ## LL and ## ULL macros with __extension__ to suppress
> these warnings.
I think users who use <stdint.h> in C89 mode expect such warnings
because such usages cannot be made compatible with C89 compilers
without long long support.
Thanks,
Florian
On Feb 25 2020, Dennis Lambe Jr. wrote:
> diff --git a/stdlib/stdint.h b/stdlib/stdint.h
> index 2df07e485b..9fa45672db 100644
> --- a/stdlib/stdint.h
> +++ b/stdlib/stdint.h
> @@ -106,8 +106,8 @@ typedef __uintmax_t uintmax_t;
> # define __INT64_C(c) c ## L
> # define __UINT64_C(c) c ## UL
> # else
> -# define __INT64_C(c) c ## LL
> -# define __UINT64_C(c) c ## ULL
> +# define __INT64_C(c) (__extension__ c ## LL)
> +# define __UINT64_C(c) (__extension__ c ## ULL)
The expansion must be a preprocessor expression.
Andreas.
Quoting Florian Weimer <fweimer@redhat.com>:
> I think users who use <stdint.h> in C89 mode expect such warnings
> because such usages cannot be made compatible with C89 compilers
> without long long support.
Existing practice suggests differently. Every usage of 'long long' in
the headers under stdlib/ is preceded by an __extention__ keyword to
suppress those warnings. This was the only instance I could find of a
stdlib header not suppressing that warning.
* Dennis Lambe, Jr.:
> Quoting Florian Weimer <fweimer@redhat.com>:
>
>> I think users who use <stdint.h> in C89 mode expect such warnings
>> because such usages cannot be made compatible with C89 compilers
>> without long long support.
>
> Existing practice suggests differently. Every usage of 'long long' in
> the headers under stdlib/ is preceded by an __extention__ keyword to
> suppress those warnings. This was the only instance I could find of a
> stdlib header not suppressing that warning.
None of those are in macros. These macros are special in the sense that
they require the long long extension only on 32-bit targets.
Thanks,
Florian
Quoting Florian Weimer <fweimer@redhat.com>:
>> Quoting Florian Weimer <fweimer@redhat.com>:
>>
>>> I think users who use <stdint.h> in C89 mode expect such warnings
>>> because such usages cannot be made compatible with C89 compilers
>>> without long long support.
>>
>> Existing practice suggests differently. Every usage of 'long long' in
>> the headers under stdlib/ is preceded by an __extention__ keyword to
>> suppress those warnings. This was the only instance I could find of a
>> stdlib header not suppressing that warning.
>
> None of those are in macros. These macros are special in the sense that
> they require the long long extension only on 32-bit targets.
I see your point here. However, the use of __extension__ before the
typedefs for int64 types means that you can get away with a lot of
implicit long long usage via int64 without running into a warning,
though. So if the user expects that, their expectation is only being
met inconsistently: they only get a warning if they use the macros,
not if they use only the typedefs. (this is exactly how I ran into
this).
Technically we're way outside the standard anyway -- there's no reason
to expect stdint.h to exist at all on c89 and any code running with
-pedantic -std=c89 and including stdint.h could be called quirky. I
just thought it'd be nice to standardize on either "warn" or "don't
warn" rather than a mix of the two.
Quoting Andreas Schwab <schwab@suse.de>:
> On Feb 25 2020, Dennis Lambe Jr. wrote:
>> +# define __UINT64_C(c) (__extension__ c ## ULL)
>
> The expansion must be a preprocessor expression.
Oof, yeah, I see what you mean. GCC recognizes the __extension__
keyword at compile-time, but GCC's preprocessor doesn't recognize it
and throws an error. This seems like a bug in GCC to me, and I don't
know how to work around it to accomplish what I'm trying to do with
this patch. Withdrawn until I can figure it out, unless someone else
has an idea.
Thanks for taking the time to consider it
On Feb 25 2020, Dennis Lambe Jr. wrote:
> Existing practice suggests differently. Every usage of 'long long' in the
> headers under stdlib/ is preceded by an __extention__ keyword to suppress
> those warnings. This was the only instance I could find of a stdlib
> header not suppressing that warning.
C89 doesn't have <stdint.h>, so the warning reminds you that you are
doing something invalid.
Andreas.
* Dennis Lambe, Jr.:
> Quoting Andreas Schwab <schwab@suse.de>:
>
>> On Feb 25 2020, Dennis Lambe Jr. wrote:
>>> +# define __UINT64_C(c) (__extension__ c ## ULL)
>>
>> The expansion must be a preprocessor expression.
>
> Oof, yeah, I see what you mean. GCC recognizes the __extension__
> keyword at compile-time, but GCC's preprocessor doesn't recognize it
> and throws an error. This seems like a bug in GCC to me, and I don't
> know how to work around it to accomplish what I'm trying to do with
> this patch. Withdrawn until I can figure it out, unless someone else
> has an idea.
The usual trick is to write (__extension__ + c ## ULL), but this
produces a -Wundef warning even in !C89 modes, so I think we'd be off
worse with that.
Thanks,
Florian
@@ -106,8 +106,8 @@ typedef __uintmax_t uintmax_t;
# define __INT64_C(c) c ## L
# define __UINT64_C(c) c ## UL
# else
-# define __INT64_C(c) c ## LL
-# define __UINT64_C(c) c ## ULL
+# define __INT64_C(c) (__extension__ c ## LL)
+# define __UINT64_C(c) (__extension__ c ## ULL)
# endif
/* Limits of integral types. */
@@ -251,7 +251,7 @@ typedef __uintmax_t uintmax_t;
# if __WORDSIZE == 64
# define INT64_C(c) c ## L
# else
-# define INT64_C(c) c ## LL
+# define INT64_C(c) (__extension__ c ## LL)
# endif
/* Unsigned. */
@@ -261,7 +261,7 @@ typedef __uintmax_t uintmax_t;
# if __WORDSIZE == 64
# define UINT64_C(c) c ## UL
# else
-# define UINT64_C(c) c ## ULL
+# define UINT64_C(c) (__extension__ c ## ULL)
# endif
/* Maximal type. */
@@ -269,8 +269,8 @@ typedef __uintmax_t uintmax_t;
# define INTMAX_C(c) c ## L
# define UINTMAX_C(c) c ## UL
# else
-# define INTMAX_C(c) c ## LL
-# define UINTMAX_C(c) c ## ULL
+# define INTMAX_C(c) (__extension__ c ## LL)
+# define UINTMAX_C(c) (__extension__ c ## ULL)
# endif
#if __GLIBC_USE (IEC_60559_BFP_EXT_C2X)