Although it is fully legal and correct C to write something like:
(u64)0x123456789abcdef
.. gcc will issue a warning on 32-bit systems that 0x123456789abcdef
is too big for an "int", and that it has been transparently promoted,
even though it is obvious that that is what the user intended in the
first place. C99 has macros of the form [U]INT#_C() to construct
numbers of an arbitrary size; this patch creates analogous macros for
the kernel s# and u# types.
Signed-off-by: H. Peter Anvin <[email protected]>
---
include/asm-alpha/types.h | 9 +++++++++
include/asm-arm/types.h | 9 +++++++++
include/asm-avr32/types.h | 9 +++++++++
include/asm-blackfin/types.h | 9 +++++++++
include/asm-cris/types.h | 9 +++++++++
include/asm-frv/types.h | 9 +++++++++
include/asm-h8300/types.h | 9 +++++++++
include/asm-ia64/types.h | 9 +++++++++
include/asm-m32r/types.h | 9 +++++++++
include/asm-m68k/types.h | 9 +++++++++
include/asm-mips/types.h | 11 +++++++++++
include/asm-mn10300/types.h | 9 +++++++++
include/asm-parisc/types.h | 9 +++++++++
include/asm-powerpc/types.h | 11 +++++++++++
include/asm-s390/types.h | 11 +++++++++++
include/asm-sh/types.h | 9 +++++++++
include/asm-sparc/types.h | 9 +++++++++
include/asm-sparc64/types.h | 9 +++++++++
include/asm-v850/types.h | 9 +++++++++
include/asm-x86/types.h | 9 +++++++++
include/asm-xtensa/types.h | 8 ++++++++
21 files changed, 194 insertions(+), 0 deletions(-)
diff --git a/include/asm-alpha/types.h b/include/asm-alpha/types.h
index f571613..76bc008 100644
--- a/include/asm-alpha/types.h
+++ b/include/asm-alpha/types.h
@@ -53,6 +53,15 @@ typedef unsigned int u32;
typedef signed long s64;
typedef unsigned long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
+
typedef u64 dma_addr_t;
typedef u64 dma64_addr_t;
diff --git a/include/asm-arm/types.h b/include/asm-arm/types.h
index 3141451..d55e0bf 100644
--- a/include/asm-arm/types.h
+++ b/include/asm-arm/types.h
@@ -47,6 +47,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-avr32/types.h b/include/asm-avr32/types.h
index 8999a38..f8d9c8a 100644
--- a/include/asm-avr32/types.h
+++ b/include/asm-avr32/types.h
@@ -53,6 +53,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-blackfin/types.h b/include/asm-blackfin/types.h
index 9785a6d..57803a9 100644
--- a/include/asm-blackfin/types.h
+++ b/include/asm-blackfin/types.h
@@ -54,6 +54,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-cris/types.h b/include/asm-cris/types.h
index 5a21c42..5e730f1 100644
--- a/include/asm-cris/types.h
+++ b/include/asm-cris/types.h
@@ -47,6 +47,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide, just like our other addresses. */
typedef u32 dma_addr_t;
diff --git a/include/asm-frv/types.h b/include/asm-frv/types.h
index 767e5ed..e903c37 100644
--- a/include/asm-frv/types.h
+++ b/include/asm-frv/types.h
@@ -59,6 +59,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-h8300/types.h b/include/asm-h8300/types.h
index 56566e2..6344ded 100644
--- a/include/asm-h8300/types.h
+++ b/include/asm-h8300/types.h
@@ -49,6 +49,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
#define BITS_PER_LONG 32
/* Dma addresses are 32-bits wide. */
diff --git a/include/asm-ia64/types.h b/include/asm-ia64/types.h
index 902850d..0932c78 100644
--- a/include/asm-ia64/types.h
+++ b/include/asm-ia64/types.h
@@ -61,6 +61,15 @@ typedef __u32 u32;
typedef __s64 s64;
typedef __u64 u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
+
#define BITS_PER_LONG 64
/* DMA addresses are 64-bits wide, in general. */
diff --git a/include/asm-m32r/types.h b/include/asm-m32r/types.h
index b64c166..785b6d9 100644
--- a/include/asm-m32r/types.h
+++ b/include/asm-m32r/types.h
@@ -46,6 +46,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* DMA addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-m68k/types.h b/include/asm-m68k/types.h
index c35c09d..ffb57a1 100644
--- a/include/asm-m68k/types.h
+++ b/include/asm-m68k/types.h
@@ -55,6 +55,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* DMA addresses are always 32-bits wide */
typedef u32 dma_addr_t;
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
index 2dd147f..2f00706 100644
--- a/include/asm-mips/types.h
+++ b/include/asm-mips/types.h
@@ -62,16 +62,27 @@ typedef unsigned short u16;
typedef __signed int s32;
typedef unsigned int u32;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+
#if (_MIPS_SZLONG == 64)
typedef __signed__ long s64;
typedef unsigned long u64;
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
#else
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __signed__ long long s64;
typedef unsigned long long u64;
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
#endif
#endif
diff --git a/include/asm-mn10300/types.h b/include/asm-mn10300/types.h
index d40ea76..7f6c2f0 100644
--- a/include/asm-mn10300/types.h
+++ b/include/asm-mn10300/types.h
@@ -57,6 +57,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-parisc/types.h b/include/asm-parisc/types.h
index 56c8480..08787e0 100644
--- a/include/asm-parisc/types.h
+++ b/include/asm-parisc/types.h
@@ -53,6 +53,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
index 903fd19..7c42717 100644
--- a/include/asm-powerpc/types.h
+++ b/include/asm-powerpc/types.h
@@ -74,12 +74,23 @@ typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+
#ifdef __powerpc64__
typedef signed long s64;
typedef unsigned long u64;
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
#else
typedef signed long long s64;
typedef unsigned long long u64;
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
#endif
typedef __vector128 vector128;
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index 2c5879a..48f771b 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -68,12 +68,23 @@ typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+
#ifndef __s390x__
typedef signed long long s64;
typedef unsigned long long u64;
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
#else /* __s390x__ */
typedef signed long s64;
typedef unsigned long u64;
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
#endif /* __s390x__ */
typedef u32 dma_addr_t;
diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h
index a6e1d41..5f674e9 100644
--- a/include/asm-sh/types.h
+++ b/include/asm-sh/types.h
@@ -48,6 +48,15 @@ typedef unsigned int u32;
typedef __signed__ long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h
index 42fc6ed..b77b145 100644
--- a/include/asm-sparc/types.h
+++ b/include/asm-sparc/types.h
@@ -51,6 +51,15 @@ typedef unsigned int u32;
typedef __signed__ long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
typedef u32 dma_addr_t;
typedef u32 dma64_addr_t;
diff --git a/include/asm-sparc64/types.h b/include/asm-sparc64/types.h
index d0ee7f1..6c0f4ce 100644
--- a/include/asm-sparc64/types.h
+++ b/include/asm-sparc64/types.h
@@ -51,6 +51,15 @@ typedef unsigned int u32;
typedef __signed__ long s64;
typedef unsigned long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## L
+#define U64_C(x) x ## UL
+
/* Dma addresses come in generic and 64-bit flavours. */
typedef u32 dma_addr_t;
diff --git a/include/asm-v850/types.h b/include/asm-v850/types.h
index 284bda8..6f406f7 100644
--- a/include/asm-v850/types.h
+++ b/include/asm-v850/types.h
@@ -55,6 +55,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
diff --git a/include/asm-x86/types.h b/include/asm-x86/types.h
index 63733f3..089c9cd 100644
--- a/include/asm-x86/types.h
+++ b/include/asm-x86/types.h
@@ -56,6 +56,15 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
+
typedef u64 dma64_addr_t;
#if defined(CONFIG_X86_64) || defined(CONFIG_HIGHMEM64G)
/* DMA addresses come in 32-bit and 64-bit flavours. */
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
index b27d841..7e402e6 100644
--- a/include/asm-xtensa/types.h
+++ b/include/asm-xtensa/types.h
@@ -60,6 +60,14 @@ typedef unsigned int u32;
typedef __signed__ long long s64;
typedef unsigned long long u64;
+#define S8_C(x) x
+#define U8_C(x) x ## U
+#define S16_C(x) x
+#define U16_C(x) x ## U
+#define S32_C(x) x
+#define U32_C(x) x ## U
+#define S64_C(x) x ## LL
+#define U64_C(x) x ## ULL
#define BITS_PER_LONG 32
--
1.5.4.1
Use the new U64_C() constructor macro instead of using casts for
constants in kernel/time.c. This avoids warnings with some gcc
versions.
This resolves Bugzilla 10153.
Signed-off-by: H. Peter Anvin <[email protected]>
---
kernel/time.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/time.c b/kernel/time.c
index a5ec013..47b24f4 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -244,7 +244,7 @@ unsigned int inline jiffies_to_msecs(const unsigned long j)
return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
#else
# if BITS_PER_LONG == 32
- return ((u64)HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32;
+ return (U64_C(HZ_TO_MSEC_MUL32) * j) >> HZ_TO_MSEC_SHR32;
# else
return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN;
# endif
@@ -260,7 +260,7 @@ unsigned int inline jiffies_to_usecs(const unsigned long j)
return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
#else
# if BITS_PER_LONG == 32
- return ((u64)HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32;
+ return (U64_C(HZ_TO_USEC_MUL32) * j) >> HZ_TO_USEC_SHR32;
# else
return (j * HZ_TO_USEC_NUM) / HZ_TO_USEC_DEN;
# endif
@@ -469,7 +469,7 @@ unsigned long msecs_to_jiffies(const unsigned int m)
if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
return MAX_JIFFY_OFFSET;
- return ((u64)MSEC_TO_HZ_MUL32 * m + MSEC_TO_HZ_ADJ32)
+ return (U64_C(MSEC_TO_HZ_MUL32) * m + MSEC_TO_HZ_ADJ32)
>> MSEC_TO_HZ_SHR32;
#endif
}
@@ -484,7 +484,7 @@ unsigned long usecs_to_jiffies(const unsigned int u)
#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
return u * (HZ / USEC_PER_SEC);
#else
- return ((u64)USEC_TO_HZ_MUL32 * u + USEC_TO_HZ_ADJ32)
+ return (U64_C(USEC_TO_HZ_MUL32) * u + USEC_TO_HZ_ADJ32)
>> USEC_TO_HZ_SHR32;
#endif
}
--
1.5.4.1
On Sun, Mar 02, 2008 at 04:09:51PM -0800, H. Peter Anvin wrote:
> first place. C99 has macros of the form [U]INT#_C() to construct
> numbers of an arbitrary size; this patch creates analogous macros for
> the kernel s# and u# types.
Why put this in asm/types.h instead of, say, linux/types.h?
I appreciate you have:
> +#define S64_C(x) x ## L
> +#define U64_C(x) x ## UL
and:
> +#define S64_C(x) x ## LL
> +#define U64_C(x) x ## ULL
but can't we use the latter for all arches?
--
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours. We can't possibly take such
a retrograde step."
> Although it is fully legal and correct C to write something like:
>
> (u64)0x123456789abcdef
>
> .. gcc will issue a warning on 32-bit systems that 0x123456789abcdef
> is too big for an "int", and that it has been transparently promoted,
> even though it is obvious that that is what the user intended in the
> first place.
[It says it is too big for 'long', actually].
That's because this is not valid ISO C90. GCC tries to help you out
by using the C99 rules (it has to do something, and terminating with
an error would be a bit rude). Perhaps the kernel should use C99
mode (-std=gnu99, to get the GNU C extensions).
> +#define S8_C(x) x
> +#define U8_C(x) x ## U
> +#define S16_C(x) x
> +#define U16_C(x) x ## U
> +#define S32_C(x) x
> +#define U32_C(x) x ## U
These are unnecessary, Linux requires an int to be at least 32 bits.
> +#define S64_C(x) x ## LL
> +#define U64_C(x) x ## ULL
Here you can use LL resp. ULL on all archs.
Do these new macros really buy anything over just writing LL in the
few places that 64-bit constants are used?
Segher
On Sunday 02 March 2008, Segher Boessenkool wrote:
> Do these new macros really buy anything over just writing LL in the
> few places that 64-bit constants are used?
The original workaround was to make the offending *SEC_TO_HZ_ADJ32
constants use "ULL" suffixes. Certainly making the Perl script emit
those would be less intrusive.
- Dave
Matthew Wilcox wrote:
> On Sun, Mar 02, 2008 at 04:09:51PM -0800, H. Peter Anvin wrote:
>> first place. C99 has macros of the form [U]INT#_C() to construct
>> numbers of an arbitrary size; this patch creates analogous macros for
>> the kernel s# and u# types.
>
> Why put this in asm/types.h instead of, say, linux/types.h?
>
Because that's where the s* and u* types are defined.
Realistically, those probably could/should be folded into a pair of
asm-generic files (for 32 and 64 bits), but that is a separate change.
> I appreciate you have:
>
>> +#define S64_C(x) x ## L
>> +#define U64_C(x) x ## UL
>
> and:
>
>> +#define S64_C(x) x ## LL
>> +#define U64_C(x) x ## ULL
>
> but can't we use the latter for all arches?
>
You really don't want to, as the whole point is that you want it to
match what u64/s64 is defined as, in order to avoid spurious warnings.
-hpa
Segher Boessenkool wrote:
>
> Do these new macros really buy anything over just writing LL in the
> few places that 64-bit constants are used?
>
It gives you macros that matches the s64/u64 et al definitions are, thus
avoiding another class of spurious warnings.
-hpa
David Brownell wrote:
> On Sunday 02 March 2008, Segher Boessenkool wrote:
>
>> Do these new macros really buy anything over just writing LL in the
>> few places that 64-bit constants are used?
>
> The original workaround was to make the offending *SEC_TO_HZ_ADJ32
> constants use "ULL" suffixes. Certainly making the Perl script emit
> those would be less intrusive.
>
"Less intrusive" in the sense of smaller line count for this particular
patch, perhaps, but it makes it less obvious when reading the code
what's going on (a size override in an entirely different file).
Additionally, I'm hoping these kind of things can be used elsewhere; the
C99 <inttypes.h> facilities are really quite nice once you get over the
rather ugly look of them, and I for one definitely miss having access to
the in the kernel.
-hpa
On Sun, Mar 02, 2008 at 08:43:22PM -0800, H. Peter Anvin wrote:
> >>+#define S64_C(x) x ## LL
> >>+#define U64_C(x) x ## ULL
> >
> >but can't we use the latter for all arches?
> >
>
> You really don't want to, as the whole point is that you want it to
> match what u64/s64 is defined as, in order to avoid spurious warnings.
Excuse me, in which contexts? Where does replacement of explicitly long
constant with explicitly long long one generate warnings on a host that has
range(long) equal to range(long long)?
Al Viro wrote:
> On Sun, Mar 02, 2008 at 08:43:22PM -0800, H. Peter Anvin wrote:
>>>> +#define S64_C(x) x ## LL
>>>> +#define U64_C(x) x ## ULL
>>> but can't we use the latter for all arches?
>>>
>> You really don't want to, as the whole point is that you want it to
>> match what u64/s64 is defined as, in order to avoid spurious warnings.
>
> Excuse me, in which contexts? Where does replacement of explicitly long
> constant with explicitly long long one generate warnings on a host that has
> range(long) equal to range(long long)?
printf, for example.
-hpa
On Sun, Mar 02, 2008 at 10:12:37PM -0800, H. Peter Anvin wrote:
> Al Viro wrote:
> >On Sun, Mar 02, 2008 at 08:43:22PM -0800, H. Peter Anvin wrote:
> >>>>+#define S64_C(x) x ## LL
> >>>>+#define U64_C(x) x ## ULL
> >>>but can't we use the latter for all arches?
> >>>
> >>You really don't want to, as the whole point is that you want it to
> >>match what u64/s64 is defined as, in order to avoid spurious warnings.
> >
> >Excuse me, in which contexts? Where does replacement of explicitly long
> >constant with explicitly long long one generate warnings on a host that has
> >range(long) equal to range(long long)?
>
> printf, for example.
Oh, for... It's not as if we _had_ anything better for u64 than %ull and
convert the argument to unsigned long long for that family.
Unless you are seriously suggesting the use of vomit-inducing atrocity of
PRIu64 and constant concatenation in there, that is. I would rather move
typechecking for printk-style functions to sparse and tell gcc to STFU
completely on that class of warnings. Making it extensible, while we are
at it - i.e. telling sparse that this conversion is to be used for dma_addr_t,
etc.
Al Viro wrote:
>
> Oh, for... It's not as if we _had_ anything better for u64 than %ull and
> convert the argument to unsigned long long for that family.
>
> Unless you are seriously suggesting the use of vomit-inducing atrocity of
> PRIu64 and constant concatenation in there, that is. I would rather move
> typechecking for printk-style functions to sparse and tell gcc to STFU
> completely on that class of warnings. Making it extensible, while we are
> at it - i.e. telling sparse that this conversion is to be used for dma_addr_t,
> etc.
No, I'm not suggesting that. I'd rather have the Windoze extension of
%I64u, which of course gcc doesn't recognize.
-hpa
H. Peter Anvin <[email protected]> wrote:
> +#define S8_C(x) x
> +#define U8_C(x) x ## U
> +#define S16_C(x) x
> +#define U16_C(x) x ## U
> +#define S32_C(x) x
> +#define U32_C(x) x ## U
> +#define S64_C(x) x ## LL
> +#define U64_C(x) x ## ULL
And #if defined(__ASSEMBLY__), just splat x through as is.
David
On Mon, Mar 03, 2008 at 10:57:32AM +0000, David Howells wrote:
> H. Peter Anvin <[email protected]> wrote:
>
> > +#define S8_C(x) x
> > +#define U8_C(x) x ## U
> > +#define S16_C(x) x
> > +#define U16_C(x) x ## U
> > +#define S32_C(x) x
> > +#define U32_C(x) x ## U
> > +#define S64_C(x) x ## LL
> > +#define U64_C(x) x ## ULL
>
> And #if defined(__ASSEMBLY__), just splat x through as is.
We already have something like this on ARM - include/asm-arm/memory.h
/*
* Allow for constants defined here to be used from assembly code
* by prepending the UL suffix only with actual C code compilation.
*/
#ifndef __ASSEMBLY__
#define UL(x) (x##UL)
#else
#define UL(x) (x)
#endif
--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of:
Russell King <[email protected]> wrote:
> > And #if defined(__ASSEMBLY__), just splat x through as is.
>
> We already have something like this on ARM - include/asm-arm/memory.h
Which you could perhaps replace.
David
On Mon, Mar 03, 2008 at 11:43:10AM +0000, Russell King wrote:
> On Mon, Mar 03, 2008 at 10:57:32AM +0000, David Howells wrote:
> > H. Peter Anvin <[email protected]> wrote:
> >
> > > +#define S8_C(x) x
> > > +#define U8_C(x) x ## U
> > > +#define S16_C(x) x
> > > +#define U16_C(x) x ## U
> > > +#define S32_C(x) x
> > > +#define U32_C(x) x ## U
> > > +#define S64_C(x) x ## LL
> > > +#define U64_C(x) x ## ULL
> >
> > And #if defined(__ASSEMBLY__), just splat x through as is.
>
> We already have something like this on ARM - include/asm-arm/memory.h
>
> /*
> * Allow for constants defined here to be used from assembly code
> * by prepending the UL suffix only with actual C code compilation.
> */
> #ifndef __ASSEMBLY__
> #define UL(x) (x##UL)
> #else
> #define UL(x) (x)
> #endif
And in linux/const.h we have yet another variant:
/* Some constant macros are used in both assembler and
* C code. Therefore we cannot annotate them always with
* 'UL' and other type specifiers unilaterally. We
* use the following macros to deal with this.
*
* Similarly, _AT() will cast an expression with a type in C, but
* leave it unchanged in asm.
*/
#ifdef __ASSEMBLY__
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define __AC(X,Y) (X##Y)
#define _AC(X,Y) __AC(X,Y)
#define _AT(T,X) ((T)(X))
#endif
Not as typestrict as hpa's and arm's version but
used in a few placed already.
Sam
Sam Ravnborg wrote:
>
> And in linux/const.h we have yet another variant:
> /* Some constant macros are used in both assembler and
> * C code. Therefore we cannot annotate them always with
> * 'UL' and other type specifiers unilaterally. We
> * use the following macros to deal with this.
> *
> * Similarly, _AT() will cast an expression with a type in C, but
> * leave it unchanged in asm.
> */
>
> #ifdef __ASSEMBLY__
> #define _AC(X,Y) X
> #define _AT(T,X) X
> #else
> #define __AC(X,Y) (X##Y)
> #define _AC(X,Y) __AC(X,Y)
> #define _AT(T,X) ((T)(X))
> #endif
>
> Not as typestrict as hpa's and arm's version but
> used in a few placed already.
>
These, unfortunately, don't solve the issue of gcc warnings, and you
don't want to make them paste ULL on before the cast, since I think
they're used with non-simple constants.
-hpa
>> Do these new macros really buy anything over just writing LL in the
>> few places that 64-bit constants are used?
>
> It gives you macros that matches the s64/u64 et al definitions are,
> thus avoiding another class of spurious warnings.
GCC doesn't warn for implicit narrowing that doesn't change value.
The printk() example is a read herring IMHO, since variable arguments
functions are "very speshul" anyway, and require explicit casts in
many cases.
Segher