Message ID | 20200225072320.Horde.P83S0y7VfCmyChcsW8RVUF4@ssl.uofr.net |
---|---|
State | New |
Headers | show |
Series | stdint: Use __extension__ on long long constants | expand |
* 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
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) # 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)