[PATCH 4/5 ver2] rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON

Previous thread: [patch][rfc] bitops: remove volatile by Nick Piggin on Monday, September 1, 2008 - 5:51 am. (1 message)

Next thread: [RFC] Unify asm/statfs.h by David Woodhouse on Monday, September 1, 2008 - 6:21 am. (10 messages)
From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:00 am

Submitted a patchset to fix BUILD_BUG_ON to no longer let through
none compile-time constant expressions. This was debated a few
times on LKML. The final solution is as proposed by Rusty Russell,
which produces all expected results in my tests.
[see: http://www.spinics.net/lists/kernel/msg772904.html]

[PATCH 1/5] debug, x86: move BUILD_BUG_ON() ARRAY_SIZE and __FUNCTION__
  Ingo this is your patch. Please verify?

[PATCH 2/5] net/niu: Fix none-const BUILD_BUG_ON usage
[PATCH 3/5] virtio: Fix none-const BUILD_BUG_ON usage
[PATCH 4/5] rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON
  These three need maintainers approval. I hope I did not forget
  anyone

[PATCH 5/5] debug: BUILD_BUG_ON: error on none-const expressions
  Finally after all call sites are fixed this can go in.
  (Rusty this one is From: you)

I have only compiled ARCH=x86 (64/32) allmodconfig. So this might
break on other ARCHs. It should spend a night in Linux-Next to expose
these places.

Thanks
Boaz

--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:07 am

From: Ingo Molnar <mingo@elte.hu>

move BUILD_BUG_ON variants, ARRAY_SIZE and __FUNCTION__
definitions from kernel.h to compiler.h.

Besides being the correct location for such trivial wrappers around
compiler functionality, this also allows the removal of duplicate
definitions from arch/x86/boot/boot.h.

[ boot.h cannot just include kernel.h to pick up the new definitions,
  as it is also built into user-space utilities on the host system. ]

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 arch/x86/boot/boot.h     |    5 -----
 include/linux/compiler.h |   14 ++++++++++++++
 include/linux/kernel.h   |   14 --------------
 3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index cc0ef13..f09b79a 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -27,11 +27,6 @@
 #include "bitops.h"
 #include <asm/cpufeature.h>
 
-/* Useful macros */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
-
 extern struct setup_header hdr;
 extern struct boot_params boot_params;
 
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index c8bd2da..90fa975 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -194,4 +194,18 @@ extern void __chk_io_ptr(const volatile void __iomem *);
  */
 #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
 
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+/* Force a compilation error if condition is true, but also produce a
+   result (of value 0 and type size_t), so the expression can be used
+   e.g. in a structure initializer (or where-ever else comma expressions
+   aren't permitted). */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
+
+/* Trap pasters of __FUNCTION__ at compile-time */
+#define __FUNCTION__ ...
From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:11 am

It would be easy to constify the expression but I have removed
the BUILD_BUG_ON. (Left the useful comment though). Since
it has no point here, a BUILD_BUG_ON is used when two
inter-dependent but separate pieces of code must match. which
is not the case here.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: David S. Miller <davem@davemloft.net>
---
 drivers/net/niu.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index e4765b7..b517d0c 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -5135,17 +5135,15 @@ static void niu_init_tx_mac(struct niu *np)
 {
 	u64 min, max;
 
+	/* NOTE: XMAC_MIN register only accepts values for TX min which
+	 * have the low 3 bits cleared.
+	 */
 	min = 64;
 	if (np->dev->mtu > ETH_DATA_LEN)
 		max = 9216;
 	else
 		max = 1522;
 
-	/* The XMAC_MIN register only accepts values for TX min which
-	 * have the low 3 bits cleared.
-	 */
-	BUILD_BUG_ON(min & 0x7);
-
 	if (np->flags & NIU_FLAGS_XMAC)
 		niu_init_tx_xmac(np, min, max);
 	else
-- 
1.5.6.rc1.5.gadf6


--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:13 am

BUILD_BUG_ON can not be used cross inline parametrization boundary.
I've put the BUILD_BUG_ON(_ZERO) in a macro outside of the inline
definition. (So it is in the caller scope).

NOTE to Rusty:
  If I remove the "__builtin_constant_p ?" part then code compiles
  just fine, because all call sights of virtio_has_feature() use
  constants for fbit. But it seems like it was not intended to be
  forced.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 include/linux/virtio_config.h |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index bf8ec28..d9402d8 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -92,17 +92,19 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
  * @vdev: the device
  * @fbit: the feature bit
  */
-static inline bool virtio_has_feature(const struct virtio_device *vdev,
+static inline bool __virtio_has_feature(const struct virtio_device *vdev,
 				      unsigned int fbit)
 {
-	/* Did you forget to fix assumptions on max features? */
-	if (__builtin_constant_p(fbit))
-		BUILD_BUG_ON(fbit >= 32);
-
 	virtio_check_driver_offered_feature(vdev, fbit);
 	return test_bit(fbit, vdev->features);
 }
 
+/* Did you forget to fix assumptions on max features? */
+#define virtio_has_feature(vdev, fbit) \
+	((__builtin_constant_p(fbit) ? BUILD_BUG_ON_ZERO(fbit >= 32) : 0) + \
+	__virtio_has_feature(vdev, fbit))
+	
+
 /**
  * virtio_config_val - look for a feature and get a virtio config entry.
  * @vdev: the virtio device
-- 
1.5.6.rc1.5.gadf6


--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 8:53 am

In virtio_has_feature() BUILD_BUG_ON can not be used cross inline
parametrization boundary. I've put the BUILD_BUG_ON(_ZERO) in a
macro outside of the inline definition. (So it is in the caller scope).

However It is no longer legal to pass BUILD_BUG_ON a non-const
expression so users like virtio_config_buf() should caller
__virtio_has_feature() which does the actual code minus the
check.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 include/linux/virtio_config.h |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index bf8ec28..7accb1d 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -92,17 +92,18 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
  * @vdev: the device
  * @fbit: the feature bit
  */
-static inline bool virtio_has_feature(const struct virtio_device *vdev,
+static inline bool __virtio_has_feature(const struct virtio_device *vdev,
 				      unsigned int fbit)
 {
-	/* Did you forget to fix assumptions on max features? */
-	if (__builtin_constant_p(fbit))
-		BUILD_BUG_ON(fbit >= 32);
-
 	virtio_check_driver_offered_feature(vdev, fbit);
 	return test_bit(fbit, vdev->features);
 }
 
+/* Did you forget to fix assumptions on max features? */
+#define virtio_has_feature(vdev, fbit) \
+	(BUILD_BUG_ON_ZERO(fbit >= 32) + __virtio_has_feature(vdev, fbit))
+	
+
 /**
  * virtio_config_val - look for a feature and get a virtio config entry.
  * @vdev: the virtio device
@@ -120,7 +121,7 @@ static inline int virtio_config_buf(struct virtio_device *vdev,
 				    unsigned int offset,
 				    void *buf, unsigned len)
 {
-	if (!virtio_has_feature(vdev, fbit))
+	if (!__virtio_has_feature(vdev, fbit))
 		return -ENOENT;
 
 	vdev->config->get(vdev, offset, buf, len);
-- 
1.5.6.rc1.5.gadf6


--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:21 am

A "Set" of the sign-bit in an "&" operation causes a compiler warning.
Make calculations unsigned.

[ The warning was masked by the use of (void)() cast in the old
  BUILD_BUG_ON() ]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
TO: Ivo van Doorn <IvDoorn@gmail.com>
TO: John W. Linville <linville@tuxdriver.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/net/wireless/rt2x00/rt2x00reg.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5..c0e8706 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -134,8 +134,8 @@ struct rt2x00_field32 {
  * Note that we cannot use the is_power_of_2() function since this
  * check must be done at compile-time.
  */
-#define is_power_of_two(x)	( !((x) & ((x)-1)) )
-#define low_bit_mask(x)		( ((x)-1) & ~(x) )
+#define is_power_of_two(x)	( !((unsigned)(x) & ((x)-1)) )
+#define low_bit_mask(x)		( ((unsigned)(x)-1) & ~(x) )
 #define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
 
 /*
--

From: Ivo Van Doorn
Date: Monday, September 1, 2008 - 6:27 am

Could the patch not become a lot easier (and perhaps cleaner) when the
only change is:
#define is_valid_mask(x)       is_power_of_two(1 + (x) +
low_bit_mask((unsigned)x))
that way all instances of x will be cast to unsigned...

Ivo
--

From: Benny Halevy
Date: Monday, September 1, 2008 - 6:27 am

Why not unsigned long?


--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:44 am

A "Set" of a sign-bit in an "&" operation causes a compiler warning.
Make calculations unsigned.

[ The warning was masked by the use of (void)() cast in the old
  BUILD_BUG_ON() ]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
TO: Ivo van Doorn <IvDoorn@gmail.com>
TO: John W. Linville <linville@tuxdriver.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/net/wireless/rt2x00/rt2x00reg.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5..e71b793 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -136,8 +136,8 @@ struct rt2x00_field32 {
  */
 #define is_power_of_two(x)	( !((x) & ((x)-1)) )
 #define low_bit_mask(x)		( ((x)-1) & ~(x) )
-#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
-
+#define is_valid_mask(x)	is_power_of_two(1 + (x) + \
+					low_bit_mask((unsigned long)x))
 /*
  * Macro's to find first set bit in a variable.
  * These macro's behaves the same as the __ffs() function with
-- 
1.5.6.rc1.5.gadf6


--

From: Ivo Van Doorn
Date: Monday, September 1, 2008 - 7:01 am

I know I typed it wrong, but you are missing the unsigned long cast for the
is_power_of_two argument here (Which could also be done in the
--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 8:17 am

I thought you suggested that on purpose. Since at the end it is all
one expression, the compiler propagates the cast to all participants.


Is below what you mean? but if so then perhaps my original one is
clearer. Note that it compiles and works as is.

---
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5..e71b793 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -136,8 +136,8 @@ struct rt2x00_field32 {
  */
 #define is_power_of_two(x)	( !((x) & ((x)-1)) )
 #define low_bit_mask(x)		( ((x)-1) & ~(x) )
-#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
-
+#define is_valid_mask(x)	is_power_of_two(1LU + (unsigned long)(x) + \
+					low_bit_mask((unsigned long)x))
 /*
  * Macro's to find first set bit in a variable.
  * These macro's behaves the same as the __ffs() function with
-- 1.5.6.rc1.5.gadf6 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ 

--

From: Ivo van Doorn
Date: Monday, September 1, 2008 - 9:34 am

Below patch is good. Your original one would have had the same comment
as the original one, where the cast was only done on 1 x instead of both usages.

I think the below version is the most clear solution. :)



--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 7:20 am

BTW
doing only:
-#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
+#define is_valid_mask(x)	is_power_of_two(1LU (x) + low_bit_mask(x))

Also fixes the problem. (By definition of C type promotion rules)


This is my suggested new patch:
---
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Mon, 1 Sep 2008 14:47:19 +0300
Subject: [PATCH] rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON

A "Set" to a sign-bit in an "&" operation causes a compiler warning.
Make calculations unsigned.

[ The warning was masked by the old definition of BUILD_BUG_ON() ]

Also remove __builtin_constant_p from FIELD_CHECK since BUILD_BUG_ON
no longer permits non-const values.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
TO: Ivo van Doorn <IvDoorn@gmail.com>
TO: John W. Linville <linville@tuxdriver.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/net/wireless/rt2x00/rt2x00reg.h |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5..2ea7866 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -136,7 +136,7 @@ struct rt2x00_field32 {
  */
 #define is_power_of_two(x)	( !((x) & ((x)-1)) )
 #define low_bit_mask(x)		( ((x)-1) & ~(x) )
-#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
+#define is_valid_mask(x)	is_power_of_two(1LU + (x) + low_bit_mask(x))
 
 /*
  * Macro's to find first set bit in a variable.
@@ -173,8 +173,7 @@ struct rt2x00_field32 {
  * does not exceed the given typelimit.
  */
 #define FIELD_CHECK(__mask, __type)			\
-	BUILD_BUG_ON(!__builtin_constant_p(__mask) ||	\
-		     !(__mask) ||			\
+	BUILD_BUG_ON(!(__mask) ||			\
 		     !is_valid_mask(__mask) ||		\
 		     (__mask) != (__type)(__mask))	\
 
-- 
1.5.6.rc1.5.gadf6


--

From: Ivo van Doorn
Date: Tuesday, September 2, 2008 - 7:27 am

Thanks.



--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 8:55 am

A "Set" to a sign-bit in an "&" operation causes a compiler warning.
Make calculations unsigned.

[ The warning was masked by the old definition of BUILD_BUG_ON() ]

Also remove __builtin_constant_p from FIELD_CHECK since BUILD_BUG_ON
no longer permits non-const values.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
---
 drivers/net/wireless/rt2x00/rt2x00reg.h |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 7e88ce5..2ea7866 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -136,7 +136,7 @@ struct rt2x00_field32 {
  */
 #define is_power_of_two(x)	( !((x) & ((x)-1)) )
 #define low_bit_mask(x)		( ((x)-1) & ~(x) )
-#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
+#define is_valid_mask(x)	is_power_of_two(1LU + (x) + low_bit_mask(x))
 
 /*
  * Macro's to find first set bit in a variable.
@@ -173,8 +173,7 @@ struct rt2x00_field32 {
  * does not exceed the given typelimit.
  */
 #define FIELD_CHECK(__mask, __type)			\
-	BUILD_BUG_ON(!__builtin_constant_p(__mask) ||	\
-		     !(__mask) ||			\
+	BUILD_BUG_ON(!(__mask) ||			\
 		     !is_valid_mask(__mask) ||		\
 		     (__mask) != (__type)(__mask))	\
 
-- 
1.5.6.rc1.5.gadf6


--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 6:28 am

From: Rusty Russell <rusty@rustcorp.com.au>

Fix BUILD_BUG_ON to not silently drop non-compile-time
visible expressions.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Alexey Dobriyan <adobriyan@gmail.com>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Theodore Tso <tytso@mit.edu>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Jan Beulich <jbeulich@novell.com>
CC: David S. Miller <davem@davemloft.net>
CC: Ivo van Doorn <IvDoorn@gmail.com>
CC: John W. Linville <linville@tuxdriver.com>
---
 include/linux/compiler.h |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 90fa975..f677ab9 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -195,7 +195,10 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
 
 /* Force a compilation error if condition is true */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define BUILD_BUG_ON(condition)					  \
+do {									  \
+	static struct { char arr[1 - 2*!!(condition)]; } x __maybe_unused;\
+} while(0)
 
 /* Force a compilation error if condition is true, but also produce a
    result (of value 0 and type size_t), so the expression can be used
-- 
1.5.6.rc1.5.gadf6


--

From: Jan Beulich
Date: Monday, September 1, 2008 - 6:55 am

I have to admit that I'm surprise this compiles: You replace an expression
with a statement, and hence you reduce the places where BUILD_BUG_ON()
can validly be used. Of course you could wrap the whole thing in ({}),
but I can't see why not to use a bit-field to achieve the intended effect.

Also, are you sure the compiler will eliminate the dead variable in all
cases?

Finally, using as common a variable as 'x' here seems dangerous, too:
What if somewhere x is #define-d to something more complex than a
simple identifier?

Jan

--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 7:21 am

it is only an expression because of the (void)() cast, which is what

"do{}while(0)" is effectively an "{}" plus the added bonus

Sure, I can also use my suggested enum construct.
(http://www.spinics.net/lists/kernel/msg772904.html)

But the thing I'm avoiding most is the (void)() cast, which makes the
optimizer very lazy. See:
[PATCH 4/5] rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON

No it is scoped in a dead do{}while(0). What gets optimized out most

I will test for your approach, give me a sec ...

Boaz
 
--

From: Jan Beulich
Date: Monday, September 1, 2008 - 7:36 am

No, sizeof() alone is an expression, too. Also, by using a statement you'll
have more problems with fixing BUILD_BUG_ON_ZERO(), which must be

An expression likewise demands a terminating ; (or a continuation of the

I don't think compilers in general and gcc in particular work this way
(i.e. automatically throwing away everything included in a dead block).

Jan

--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 8:00 am

Using only sizeof() produces tons of "expression has no effect" warning

What is broken with my BUILD_BUG_ON_ZERO(). I tried all tests and
it works fine. Do you have a test with unwanted results?

I was not criticizing your approach, I was commenting on:

I've tested and nothing is produced, even without any optimization.

Boaz
--

From: Jan Beulich
Date: Monday, September 1, 2008 - 8:29 am

That's the problem - it uses the same sizeof(char[]) approach, and hence

I think we're having some mis-understanding here: What I'm concerned
about is that you can't use statements where-ever expressions can be
used (the opposite is true, because expressions are statements). My
main concern is the limitation of its use inside macros, where one could
try to use comma expressions to combine multiple BUILD_BUG_ON()-s.

Jan

--

From: Boaz Harrosh
Date: Monday, September 1, 2008 - 9:41 am

No it does not have this problem. Have you tested it? 
I have! It works fine. (Complains on non-const expressions)

The problem with the original BUILD_BUG_ON was the 

So it has not been used and it will not in the future.
In macros just use multiple statements separated by ";"
and surrounded by do{}while(0). To reach the same effect.

Note that BUG_ON is a statement and now BUILD_BUG_ON() is also.

OK I have tested with your version of BUILD_BUG_ON{,_ZERO} and I have
two problems with it.

[1] Problem number one is with this sequence of code:

(a)
static inline bool __virtio_has_feature(const struct virtio_device *vdev,
				      unsigned int fbit)
{
	virtio_check_driver_offered_feature(vdev, fbit);
	return test_bit(fbit, vdev->features);
}

/* Did you forget to fix assumptions on max features? */
#define virtio_has_feature(vdev, fbit) \
	((__builtin_constant_p(fbit) ? BUILD_BUG_ON_ZERO(fbit >= 32) : 0) + \
	__virtio_has_feature(vdev, fbit))

...
(b)
static inline int virtio_config_buf(struct virtio_device *vdev,
				    unsigned int fbit,
				    unsigned int offset,
				    void *buf, unsigned len)
{
	if (!virtio_has_feature(vdev, fbit))
		return -ENOENT;
...
(c)
	if (data && !virtio_has_feature(vdev, VIRTIO_NET_F_CSUM))
		return -ENOSYS;

I have not fount a way to code (a) in a way that actually works
for both (b) and (c). That is, good with const expressions and
bypassed with non-const. (See explanations below)


The MAYBE_BUILD_BUG_ON just gets ignored in all cases and
coding (c) as:

	if (data && !virtio_has_feature(vdev, 717))
		return -ENOSYS;

Will not complain at all.

[2] Problem number two is with this sequence of code:

#define is_power_of_two(x)	( !((x) & ((x)-1)) )
#define low_bit_mask(x)		( ((x)-1) & ~(x) )
#define is_valid_mask(x)	is_power_of_two(1 + (x) + \
					low_bit_mask(x))

#define FIELD_CHECK(__mask, __type)			\
	BUILD_BUG_ON(!__builtin_constant_p(__mask) ||	\
		     !(__mask) ||			\
		     !is_valid_mask(__mask) ...
From: Jan Beulich
Date: Tuesday, September 2, 2008 - 12:47 am

For static variables, yes. But not for automatic variables and the like:

#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)

int test(int i) {
	int x = BUILD_BUG_ON_ZERO(i);

	return x;
}

You could argue that I could place a simple BUILD_BUG_ON() later in
the code, but that easily defeats the documentation purposes the
construct also has (my general position on this is that the check should
be in or immediately before the statement that depends on the
enforced restriction).

Jan

--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 8:19 am

I was able to reproduce your problem now. 

I have made new patchset the final BUILD_BUG_ON_ZERO() I took from you.
But in BUILD_BUG_ON I use a slight variation that satisfies my wishes
and makes BUILD_BUG_ON more like BUG_ON in syntax.

I had to change virtio_has_feature() semantics, though, but I believe it's
not that bad.

Jan maybe you want to put your Signed-off-by: on the last patch?
Please review?

[ I'll post new version of patches that change as reply to the original
 patches ]

Boaz
--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 8:57 am

Fix BUILD_BUG_ON to not silently drop non-compile-time
visible expressions. It will now produce a compilation
error if so.

The code to BUILD_BUG_ON_ZERO was done by:
Jan Beulich <jbeulich@novell.com>

The code to BUILD_BUG_ON is a small variation to Jan's
code inspired by Rusty Russell. Which gives me better
compilation semantics, and makes BUILD_BUG_ON behave
more like BUG_ON.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
TO: Jan Beulich <jbeulich@novell.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: Alexey Dobriyan <adobriyan@gmail.com>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Theodore Tso <tytso@mit.edu>
CC: David S. Miller <davem@davemloft.net>
---
 include/linux/compiler.h |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 90fa975..23dc269 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -194,14 +194,15 @@ extern void __chk_io_ptr(const volatile void __iomem *);
  */
 #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
 
-/* Force a compilation error if condition is true */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
 /* Force a compilation error if condition is true, but also produce a
    result (of value 0 and type size_t), so the expression can be used
-   e.g. in a structure initializer (or where-ever else comma expressions
+   e.g. in a structure initializer (or where-ever full statements
    aren't permitted). */
-#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(e) \
+	do { struct {int:-!!(e); } x __maybe_unused;} while(0)
 
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
-- 
1.5.6.rc1.5.gadf6


--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 9:06 am

oops some checkpatch love missing see new patch

Boaz

--

From: Jan Beulich
Date: Tuesday, September 2, 2008 - 9:11 am

As indicated before, you should at the very least use __x as the variable
name.

But didn't you have reservations against using a bitfield here? Or was it
really just the void cast on the sizeof() that you disliked?

Jan

--

From: Boaz Harrosh
Date: Wednesday, September 3, 2008 - 1:57 am

The name does not matter. The scope of x is confined to the do {} while()

I like it it's fine. Also an added bonus is that on the good case it compiles
to a size-less structure in a code-less block so even the most stupid 
non-optimizing compiler will get it right. OK that could be done with 0-length

I would like it if you sent your Signed-off-by: (or something) on this patch.
Thanks for your help
Boaz
--

From: Jan Beulich
Date: Wednesday, September 3, 2008 - 3:19 am

I'm sorry to repeat this: If x is #define-d to anything but a simple identifier,
this will break no matter that it's in a private scope. The absence of any
identifier was a benefit of the sizeof() approach here.

Jan

--

From: Boaz Harrosh
Date: Wednesday, September 3, 2008 - 3:52 am

#defines are a shoot-in-the-leg, they should be CAPITAL letters and very
long and unique. If any one wants to #define x, they are welcome, it will
break the kernel even before my macro. No x in a private scope is fine
#define x is not, sorry ...

OK, I would change it, but I'm too lazy to do a new post just for that.

Boaz
--

From: Rusty Russell
Date: Wednesday, October 1, 2008 - 10:35 pm

Why did you hate the void cast again?  Simplest should 
be "(void)BUILD_BUG_ON_ZERO(e)".  But if not, it seems to me that it's 
cleaner to do:

#define BUILD_BUG_ON(e) \
	do { } while(BUILD_BUG_ON_ZERO(e))

No chance of the compiler emitting unused vars.

Cheers,
Rusty.

--

From: Boaz Harrosh
Date: Sunday, October 5, 2008 - 2:34 am

I have not checked this exact variant, but the problems I had
is that wrong or non-const code was ignored by the compiler,

There is no unused vars because the result is a zero-sized

Is it that important? the code submitted does what is required
to the letter, should we spend more effort on this?

Boaz
 
--

From: Boaz Harrosh
Date: Tuesday, September 2, 2008 - 9:07 am

Fix BUILD_BUG_ON to not silently drop non-compile-time
visible expressions. It will now produce a compilation
error if so.

The code to BUILD_BUG_ON_ZERO was done by:
Jan Beulich <jbeulich@novell.com>

The code to BUILD_BUG_ON is a small variation to Jan's
code inspired by Rusty Russell. Which gives me better
compilations semantics, and makes BUILD_BUG_ON behave
more like BUG_ON.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
TO: Jan Beulich <jbeulich@novell.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: Alexey Dobriyan <adobriyan@gmail.com>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Theodore Tso <tytso@mit.edu>
CC: David S. Miller <davem@davemloft.net>
---
 include/linux/compiler.h |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 90fa975..f882410 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -194,14 +194,15 @@ extern void __chk_io_ptr(const volatile void __iomem *);
  */
 #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
 
-/* Force a compilation error if condition is true */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
 /* Force a compilation error if condition is true, but also produce a
    result (of value 0 and type size_t), so the expression can be used
-   e.g. in a structure initializer (or where-ever else comma expressions
+   e.g. in a structure initializer (or where-ever full statements
    aren't permitted). */
-#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int: -!!(e); }))
+
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(e) \
+	do { struct {int: -!!(e); } x __maybe_unused; } while (0)
 
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
-- 
1.5.6.rc1.5.gadf6


--

From: Ingo Molnar
Date: Saturday, September 6, 2008 - 9:01 am

yeah.


v3 looks good to me.

Andrew, are you picking this up? Looks like the perfect fit for -mm to 
me. I can drop the previous version from -tip so that there's no 
linux-next conflict.

	Ingo
--

Previous thread: [patch][rfc] bitops: remove volatile by Nick Piggin on Monday, September 1, 2008 - 5:51 am. (1 message)

Next thread: [RFC] Unify asm/statfs.h by David Woodhouse on Monday, September 1, 2008 - 6:21 am. (10 messages)