[PATCH RFC 00/13] improve constexpr handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 59915ea..00eb776 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -736,7 +736,7 @@ void init_cpu_online(const struct cpumask *src);
  */
 #define to_cpumask(bitmap)						\
 	((struct cpumask *)(1 ? (bitmap)				\
-			    : (void *)sizeof(__check_is_bitmap(bitmap))))
+			    : (void *)0 + sizeof(__check_is_bitmap(bitmap))))
 
 static inline int __check_is_bitmap(const unsigned long *bitmap)
 {
diff --git a/include/linux/log2.h b/include/linux/log2.h
index fd7ff3d..384d6e5 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -82,80 +82,80 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
  *
  * selects the appropriately-sized optimised version depending on sizeof(n)
  */
-#define ilog2(n)				\
-(						\
-	__builtin_constant_p(n) ? (		\
-		(n) < 1 ? ____ilog2_NaN() :	\
-		(n) & (1ULL << 63) ? 63 :	\
-		(n) & (1ULL << 62) ? 62 :	\
-		(n) & (1ULL << 61) ? 61 :	\
-		(n) & (1ULL << 60) ? 60 :	\
-		(n) & (1ULL << 59) ? 59 :	\
-		(n) & (1ULL << 58) ? 58 :	\
-		(n) & (1ULL << 57) ? 57 :	\
-		(n) & (1ULL << 56) ? 56 :	\
-		(n) & (1ULL << 55) ? 55 :	\
-		(n) & (1ULL << 54) ? 54 :	\
-		(n) & (1ULL << 53) ? 53 :	\
-		(n) & (1ULL << 52) ? 52 :	\
-		(n) & (1ULL << 51) ? 51 :	\
-		(n) & (1ULL << 50) ? 50 :	\
-		(n) & (1ULL << 49) ? 49 :	\
-		(n) & (1ULL << 48) ? 48 :	\
-		(n) & (1ULL << 47) ? 47 :	\
-		(n) & (1ULL << 46) ? 46 :	\
-		(n) & (1ULL << 45) ? 45 :	\
-		(n) & (1ULL << 44) ? 44 :	\
-		(n) & (1ULL << 43) ? 43 :	\
-		(n) & (1ULL << 42) ? 42 :	\
-		(n) & (1ULL << 41) ? 41 :	\
-		(n) & (1ULL << 40) ? 40 :	\
-		(n) & (1ULL << 39) ? 39 :	\
-		(n) & (1ULL << 38) ? 38 :	\
-		(n) & (1ULL << 37) ? 37 :	\
-		(n) & (1ULL << 36) ? 36 :	\
-		(n) & (1ULL << 35) ? 35 :	\
-		(n) & (1ULL << 34) ? 34 :	\
-		(n) & (1ULL << 33) ? 33 :	\
-		(n) & (1ULL << 32) ? 32 :	\
-		(n) & (1ULL << 31) ? 31 :	\
-		(n) & (1ULL << 30) ? 30 :	\
-		(n) & (1ULL << 29) ? 29 :	\
-		(n) & (1ULL << 28) ? 28 :	\
-		(n) & (1ULL << 27) ? 27 :	\
-		(n) & (1ULL << 26) ? 26 :	\
-		(n) & (1ULL << 25) ? 25 :	\
-		(n) & (1ULL << 24) ? 24 :	\
-		(n) & (1ULL << 23) ? 23 :	\
-		(n) & (1ULL << 22) ? 22 :	\
-		(n) & (1ULL << 21) ? 21 :	\
-		(n) & (1ULL << 20) ? 20 :	\
-		(n) & (1ULL << 19) ? 19 :	\
-		(n) & (1ULL << 18) ? 18 :	\
-		(n) & (1ULL << 17) ? 17 :	\
-		(n) & (1ULL << 16) ? 16 :	\
-		(n) & (1ULL << 15) ? 15 :	\
-		(n) & (1ULL << 14) ? 14 :	\
-		(n) & (1ULL << 13) ? 13 :	\
-		(n) & (1ULL << 12) ? 12 :	\
-		(n) & (1ULL << 11) ? 11 :	\
-		(n) & (1ULL << 10) ? 10 :	\
-		(n) & (1ULL <<  9) ?  9 :	\
-		(n) & (1ULL <<  8) ?  8 :	\
-		(n) & (1ULL <<  7) ?  7 :	\
-		(n) & (1ULL <<  6) ?  6 :	\
-		(n) & (1ULL <<  5) ?  5 :	\
-		(n) & (1ULL <<  4) ?  4 :	\
-		(n) & (1ULL <<  3) ?  3 :	\
-		(n) & (1ULL <<  2) ?  2 :	\
-		(n) & (1ULL <<  1) ?  1 :	\
-		(n) & (1ULL <<  0) ?  0 :	\
-		____ilog2_NaN()			\
-				   ) :		\
-	(sizeof(n) <= 4) ?			\
-	__ilog2_u32(n) :			\
-	__ilog2_u64(n)				\
- )
+#define ilog2(n)							\
+	__builtin_choose_expr(						\
+		__builtin_constant_p(n),				\
+		(							\
+			(n) & (1ULL << 63) ? 63 :			\
+			(n) & (1ULL << 62) ? 62 :			\
+			(n) & (1ULL << 61) ? 61 :			\
+			(n) & (1ULL << 60) ? 60 :			\
+			(n) & (1ULL << 59) ? 59 :			\
+			(n) & (1ULL << 58) ? 58 :			\
+			(n) & (1ULL << 57) ? 57 :			\
+			(n) & (1ULL << 56) ? 56 :			\
+			(n) & (1ULL << 55) ? 55 :			\
+			(n) & (1ULL << 54) ? 54 :			\
+			(n) & (1ULL << 53) ? 53 :			\
+			(n) & (1ULL << 52) ? 52 :			\
+			(n) & (1ULL << 51) ? 51 :			\
+			(n) & (1ULL << 50) ? 50 :			\
+			(n) & (1ULL << 49) ? 49 :			\
+			(n) & (1ULL << 48) ? 48 :			\
+			(n) & (1ULL << 47) ? 47 :			\
+			(n) & (1ULL << 46) ? 46 :			\
+			(n) & (1ULL << 45) ? 45 :			\
+			(n) & (1ULL << 44) ? 44 :			\
+			(n) & (1ULL << 43) ? 43 :			\
+			(n) & (1ULL << 42) ? 42 :			\
+			(n) & (1ULL << 41) ? 41 :			\
+			(n) & (1ULL << 40) ? 40 :			\
+			(n) & (1ULL << 39) ? 39 :			\
+			(n) & (1ULL << 38) ? 38 :			\
+			(n) & (1ULL << 37) ? 37 :			\
+			(n) & (1ULL << 36) ? 36 :			\
+			(n) & (1ULL << 35) ? 35 :			\
+			(n) & (1ULL << 34) ? 34 :			\
+			(n) & (1ULL << 33) ? 33 :			\
+			(n) & (1ULL << 32) ? 32 :			\
+			(n) & (1ULL << 31) ? 31 :			\
+			(n) & (1ULL << 30) ? 30 :			\
+			(n) & (1ULL << 29) ? 29 :			\
+			(n) & (1ULL << 28) ? 28 :			\
+			(n) & (1ULL << 27) ? 27 :			\
+			(n) & (1ULL << 26) ? 26 :			\
+			(n) & (1ULL << 25) ? 25 :			\
+			(n) & (1ULL << 24) ? 24 :			\
+			(n) & (1ULL << 23) ? 23 :			\
+			(n) & (1ULL << 22) ? 22 :			\
+			(n) & (1ULL << 21) ? 21 :			\
+			(n) & (1ULL << 20) ? 20 :			\
+			(n) & (1ULL << 19) ? 19 :			\
+			(n) & (1ULL << 18) ? 18 :			\
+			(n) & (1ULL << 17) ? 17 :			\
+			(n) & (1ULL << 16) ? 16 :			\
+			(n) & (1ULL << 15) ? 15 :			\
+			(n) & (1ULL << 14) ? 14 :			\
+			(n) & (1ULL << 13) ? 13 :			\
+			(n) & (1ULL << 12) ? 12 :			\
+			(n) & (1ULL << 11) ? 11 :			\
+			(n) & (1ULL << 10) ? 10 :			\
+			(n) & (1ULL <<  9) ?  9 :			\
+			(n) & (1ULL <<  8) ?  8 :			\
+			(n) & (1ULL <<  7) ?  7 :			\
+			(n) & (1ULL <<  6) ?  6 :			\
+			(n) & (1ULL <<  5) ?  5 :			\
+			(n) & (1ULL <<  4) ?  4 :			\
+			(n) & (1ULL <<  3) ?  3 :			\
+			(n) & (1ULL <<  2) ?  2 :			\
+			(n) & (1ULL <<  1) ?  1 :			\
+			(n) == 1 ? 0 :					\
+			__builtin_warning(1, "log2 gives NaN") ? 0 : 0	\
+			),						\
+		(sizeof(n) <= 4) ?					\
+		__ilog2_u32(n) :					\
+		__ilog2_u64(n)						\
+		)
 
 /**
  * roundup_pow_of_two - round the given value up to nearest power of two
@@ -165,14 +165,14 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
  * - the result is undefined when n == 0
  * - this can be used to initialise global variables from constant data
  */
-#define roundup_pow_of_two(n)			\
-(						\
-	__builtin_constant_p(n) ? (		\
-		(n == 1) ? 1 :			\
-		(1UL << (ilog2((n) - 1) + 1))	\
-				   ) :		\
-	__roundup_pow_of_two(n)			\
- )
+#define roundup_pow_of_two(n)				\
+	__builtin_choose_expr(				\
+		__builtin_constant_p(n),		\
+		(					\
+			(n == 1) ? 1 :			\
+			(1UL << (ilog2((n) - 1) + 1))	\
+			),				\
+		__roundup_pow_of_two(n))
 
 /**
  * rounddown_pow_of_two - round the given value down to nearest power of two
@@ -182,12 +182,8 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
  * - the result is undefined when n == 0
  * - this can be used to initialise global variables from constant data
  */
-#define rounddown_pow_of_two(n)			\
-(						\
-	__builtin_constant_p(n) ? (		\
-		(1UL << ilog2(n))) :		\
-	__rounddown_pow_of_two(n)		\
- )
+#define rounddown_pow_of_two(n)		\
+	(1UL << ilog2(n))
 
 /**
  * order_base_2 - calculate the (rounded up) base 2 order of the argument
diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h
index 0e011eb..d44773e 100644
--- a/include/uapi/linux/swab.h
+++ b/include/uapi/linux/swab.h
@@ -102,28 +102,28 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val)
  * __swab16 - return a byteswapped 16-bit value
  * @x: value to byteswap
  */
-#define __swab16(x)				\
-	(__builtin_constant_p((__u16)(x)) ?	\
-	___constant_swab16(x) :			\
-	__fswab16(x))
+#define __swab16(x)							\
+	__builtin_choose_expr(__builtin_constant_p((__u16)(x)),	\
+			___constant_swab16(x),				\
+			__fswab16(x))
 
 /**
  * __swab32 - return a byteswapped 32-bit value
  * @x: value to byteswap
  */
-#define __swab32(x)				\
-	(__builtin_constant_p((__u32)(x)) ?	\
-	___constant_swab32(x) :			\
-	__fswab32(x))
+#define __swab32(x)							\
+	__builtin_choose_expr(__builtin_constant_p((__u32)(x)),	\
+			___constant_swab32(x),				\
+			__fswab32(x))
 
 /**
  * __swab64 - return a byteswapped 64-bit value
  * @x: value to byteswap
  */
-#define __swab64(x)				\
-	(__builtin_constant_p((__u64)(x)) ?	\
-	___constant_swab64(x) :			\
-	__fswab64(x))
+#define __swab64(x)							\
+	__builtin_choose_expr(__builtin_constant_p((__u64)(x)),	\
+			___constant_swab64(x),				\
+			__fswab64(x))
 
 /**
  * __swahw32 - return a word-swapped 32-bit value
This patch series is split into four parts:
- The first part deals with the refactorization of the current integer
  constant expression handling and introduces some support for
  recognizing arithmetic expressions. [1-5/13]
- The second part introduces support for recognizing address constants.
  [6/13]
- The third part introduces a check for the constness of static storage
  duration objects' initializers. [7/13]
- The last part stems from my tests with the kernel. It contains things
  I missed in the first [9-10/13] and second [8,12/13] parts and
  relaxes some of the constraints on constant expressions [11/13].
  For the last patch [13/13], please see below.

My initial intent was to rework the current integer constant expression
handling in order to allow for the recognition of constant subexpressions
built up by means of __builtin_choose_expr(). Hence the first part.

However, since I had to touch the whole constant expression handling
code anyways, I decided to experimentally extend it to support
arithmetic constant expressions and address constants as well. Hence
the second part.

Since the additional information on expressions obtained through the
first two parts is rather pointless without making any use of it, I
implemented part three, the checking of static storage duration
objects' initializers for constness.
This part is the reason why there is a 'RFC' tag in the subject.
It is up to you to decide whether letting sparse check for C99
conformity is a valuable thing to have or whether being stricter than
GCC is counter-productive/completely idiotic.

Although the patches of the fourth part, the fixup part, fit very well
into the first two categories, their associated testcases, if any,
depend on [7/13]. Thus, I dediced to keep the order as is.

If you decide that you do not want to have the third part, I will
resend a stripped version of the first one only, together with
[9-10/13].


Random notes:

- [1/13] is basically a renaming patch only. It introduces additional
  flags used in later patches. It should not alter any behaviour.

- I am not very confident about [13/13]. It could introduce some
  new issues as well as just fix symptoms, not the problem.
  Please double check when reviewing.

- This series introduces two new testsuite failers, namely
  validation/choose_expr.c and validation/builtin_bswap.c.
  These testcases really violate the constexpr constraints. However,
  for the moment, I left them as is.


Results from running sparse on the kernel:

For testing, I ran sparse without and with this series applied on an
allmodconfig kernel on x86_64.
Beforehand, I fixed commonly used macros, namely log2- and
swab-related ones and to_cpumask() to qualify as constexprs,
if possible. See the attached diff (and blame me for attaching diffs).
Especially log2() needs this fixing anyways since it is used all over
the place where only integer constant expressions are allowed (in array
designators).

sparse now finds 519 occurences of non-const initializers of static
storage duration objects, 474 of which are located in drivers/acpi
and stem from this subsystem's custom offsetof macro implemented by
means of taking pointer differences.

The remaining hits are distributed as follows
14 drivers/net/ethernet/sfc/
13 drivers/isdn/hardware/mISDN/
 8 drivers/usb/core/
 2 drivers/net/wireless/libertas_tf/
 1 drivers/infiniband/hw/qib/
 1 drivers/misc/genwqe/
 1 drivers/net/ethernet/qlogic/qlcnic/
 1 drivers/net/wireless/ath/ath6kl/
 1 drivers/scsi/snic/
 1 drivers/staging/comedi/drivers/
 1 drivers/tty/ipwireless/
 1 net/wireless/

OTOH, 40 errors due to non-integer constant expressions in array
designators formerly spit out by sparse have vanished. This is because
the attached diff on log2() relies on __builtin_warning() getting
recognized as an integer constant, i.e. on [10/13].



Nicolai Stange (13):
  expression: introduce additional expression constness tracking flags
  expression: examine constness of casts at evaluation only
  expression: examine constness of binops and alike at evaluation only
  expression: examine constness of preops at evaluation only
  expression: examine constness of conditionals at evaluation only
  expression, evaluate: add support for recognizing address constants
  evaluate: check static storage duration objects' intializers'
    constness
  expression: recognize references to labels as address constants
  expression: examine constness of __builtin_offsetof at evaluation only
  symbol: flag builtins constant_p, safe_p and warning as constexprs
  evaluate: relax some constant expression rules for pointer expressions
  expression, evaluate: support compound literals as address constants
  symbol: do not inherit storage modifiers from base types at
    examination

 evaluate.c                              | 191 +++++++++++++++++++++++++-------
 expand.c                                |   2 +-
 expression.c                            |  54 +++++----
 expression.h                            | 133 +++++++++++++++++++++-
 symbol.c                                |  12 +-
 validation/constexpr-binop.c            |  33 ++++++
 validation/constexpr-cast.c             |  25 +++++
 validation/constexpr-compound-literal.c |  18 +++
 validation/constexpr-conditional.c      |  34 ++++++
 validation/constexpr-init.c             | 109 ++++++++++++++++++
 validation/constexpr-offsetof.c         |  21 ++++
 validation/constexpr-preop.c            |  29 +++++
 12 files changed, 578 insertions(+), 83 deletions(-)
 create mode 100644 validation/constexpr-binop.c
 create mode 100644 validation/constexpr-cast.c
 create mode 100644 validation/constexpr-compound-literal.c
 create mode 100644 validation/constexpr-conditional.c
 create mode 100644 validation/constexpr-init.c
 create mode 100644 validation/constexpr-offsetof.c
 create mode 100644 validation/constexpr-preop.c

-- 
2.4.5

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux