[PATCH] unlock patched C gccs

From: sylvain . bertrand
Date: Mon Dec 14 2020 - 13:12:49 EST


From: Sylvain BERTRAND <sylvain.bertrand@xxxxxxxxxx>

unlock the usage of patched gccs with proper warnings and fix the
blocking usage of c11 _Generic by using builtins available on
much more C and CXX gccs

Signed-off-by: Sylvain BERTRAND <sylvain.bertrand@xxxxxxxxxx>
---
tested on mainline 2c85ebc57b3e1817b6ce1a6b703928e113a90442 building
a running kernel.
include/linux/compiler-gcc.h: unlock blocking macros with warnings.
include/linux/compiler_types.h: use a __generic() wrapper macro
with common builtins instead of c11 _Generic.
include/linux/seqlock.h use the: __generic() macro instead of c11
_Generic.
Makefile: benign blocking gcc option.

--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -10,9 +10,30 @@
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)

+#if GCC_VERSION < 40800
+#define GCC_C
+/* comment out/patch out to acknowledge the following warning message */
+# warning you need to patch gcc:
+# warning "gcc 4.7.x would need:"
+# warning "https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145";
+# warning "https://gcc.gnu.org/legacy-ml/gcc-patches/2012-04/msg00452.html";
+#elif GCC_VERSION < 40900
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */
-#if GCC_VERSION < 40900
-# error Sorry, your version of GCC is too old - please use 4.9 or newer.
+# error Sorry, your version of GCC misses some bug fixes and features - please use 4.9 or patch your GCC.
+#else
+#define GCC_CXX
+#endif
+
+/* help prevent planned obsolescence due to the use of recent c11 _Generic */
+#if GCC_VERSION >= 40900
+#define __generic(expr, t, yes, no) \
+ _Generic(expr, t: yes, default: no)
+#elif GCC_VERSION >= 30100
+#define __generic(expr, t, yes, no) \
+ __builtin_choose_expr( \
+ __builtin_types_compatible_p(__typeof(expr), t), yes, no)
+#else
+# error your gcc compiler cannot support the __generic macro
#endif

/*
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -254,23 +254,19 @@
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
* non-scalar types unchanged.
*/
-/*
- * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
- * is not type-compatible with 'signed char', and we define a separate case.
- */
-#define __scalar_type_to_expr_cases(type) \
- unsigned type: (unsigned type)0, \
- signed type: (signed type)0
-
#define __unqual_scalar_typeof(x) typeof( \
- _Generic((x), \
- char: (char)0, \
- __scalar_type_to_expr_cases(char), \
- __scalar_type_to_expr_cases(short), \
- __scalar_type_to_expr_cases(int), \
- __scalar_type_to_expr_cases(long), \
- __scalar_type_to_expr_cases(long long), \
- default: (x)))
+ __generic((x), char, (char)0, \
+ __generic((x), unsigned char, (unsigned char)0, \
+ __generic((x), signed char, (unsigned char)0, \
+ __generic((x), unsigned short, (unsigned short)0, \
+ __generic((x), signed short, (signed short)0, \
+ __generic((x), unsigned int, (unsigned int)0, \
+ __generic((x), signed int, (signed int)0, \
+ __generic((x), unsigned long, (unsigned long)0, \
+ __generic((x), signed long, (signed long)0, \
+ __generic((x), unsigned long long, (unsigned long long)0, \
+ __generic((x), signed long long, (signed long long)0, \
+ (x)))))))))))))

/* Is this type a native word size -- useful for atomic operations */
#define __native_word(t) \
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -296,17 +296,20 @@
#define SEQCNT_MUTEX_ZERO(name, lock) SEQCOUNT_LOCKNAME_ZERO(name, lock)
#define SEQCNT_WW_MUTEX_ZERO(name, lock) SEQCOUNT_LOCKNAME_ZERO(name, lock)

-#define __seqprop_case(s, lockname, prop) \
- seqcount_##lockname##_t: __seqprop_##lockname##_##prop((void *)(s))
-
-#define __seqprop(s, prop) _Generic(*(s), \
- seqcount_t: __seqprop_##prop((void *)(s)), \
- __seqprop_case((s), raw_spinlock, prop), \
- __seqprop_case((s), spinlock, prop), \
- __seqprop_case((s), rwlock, prop), \
- __seqprop_case((s), mutex, prop), \
- __seqprop_case((s), ww_mutex, prop))
-
+#define __seqprop(s, prop) \
+ __generic(*(s), seqcount_t, __seqprop_##prop((void *)(s)), \
+ __generic(*(s), seqcount_raw_spinlock_t, \
+ __seqprop_raw_spinlock_##prop((void *)(s)), \
+ __generic(*(s), seqcount_spinlock_t, \
+ __seqprop_spinlock_##prop((void *)(s)), \
+ __generic(*(s), seqcount_rwlock_t, \
+ __seqprop_rwlock_##prop((void *)(s)), \
+ __generic(*(s), seqcount_mutex_t, \
+ __seqprop_mutex_##prop((void *)(s)), \
+ __generic(*(s), seqcount_ww_mutex_t, \
+ __seqprop_ww_mutex_##prop((void *)(s)), \
+ panic("seqlock:__seqprop:unsupported type")))))))
+
#define __seqcount_ptr(s) __seqprop(s, ptr)
#define __seqcount_sequence(s) __seqprop(s, sequence)
#define __seqcount_lock_preemptible(s) __seqprop(s, preemptible)
--- a/Makefile
+++ b/Makefile
@@ -936,9 +936,6 @@
# conserve stack if available
KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)

-# Prohibit date/time macros, which would make the build non-deterministic
-KBUILD_CFLAGS += -Werror=date-time
-
# enforce correct pointer usage
KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)