Skip to content

Commit

Permalink
include/linux/compiler*.h: make compiler-*.h mutually exclusive
Browse files Browse the repository at this point in the history
Commit cafa001 ("Raise the minimum required gcc version to 4.6")
recently exposed a brittle part of the build for supporting non-gcc
compilers.

Both Clang and ICC define __GNUC__, __GNUC_MINOR__, and
__GNUC_PATCHLEVEL__ for quick compatibility with code bases that haven't
added compiler specific checks for __clang__ or __INTEL_COMPILER.

This is brittle, as they happened to get compatibility by posing as a
certain version of GCC.  This broke when upgrading the minimal version
of GCC required to build the kernel, to a version above what ICC and
Clang claim to be.

Rather than always including compiler-gcc.h then undefining or
redefining macros in compiler-intel.h or compiler-clang.h, let's
separate out the compiler specific macro definitions into mutually
exclusive headers, do more proper compiler detection, and keep shared
definitions in compiler_types.h.

Fixes: cafa001 ("Raise the minimum required gcc version to 4.6")
Reported-by: Masahiro Yamada <[email protected]>
Suggested-by: Eli Friedman <[email protected]>
Suggested-by: Joe Perches <[email protected]>
Signed-off-by: Nick Desaulniers <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
nickdesaulniers authored and torvalds committed Aug 23, 2018
1 parent 899fbc3 commit 815f0dd
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 253 deletions.
13 changes: 1 addition & 12 deletions arch/arm/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,14 @@
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
#endif
/*
* GCC 3.0, 3.1: general bad code generation.
* GCC 3.2.0: incorrect function argument offset calculation.
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
* (http://gcc.gnu.org/PR8896) and incorrect structure
* initialisation in fs/jffs2/erase.c
* GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
* miscompiles find_get_entry(), and can result in EXT3 and EXT4
* filesystem corruption (possibly other FS too).
*/
#ifdef __GNUC__
#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
#error Your compiler is too buggy; it is known to miscompile kernels.
#error Known good compilers: 3.3, 4.x
#endif
#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
#if defined(GCC_VERSION) && GCC_VERSION >= 40800 && GCC_VERSION < 40803
#error Your compiler is too buggy; it is known to miscompile kernels
#error and result in filesystem corruption and oopses.
#endif
#endif

int main(void)
{
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
__stringify(x), (long)(x))

#if GCC_VERSION >= 70000
#if defined(GCC_VERSION) && GCC_VERSION >= 70000
#define add_overflows(A, B) \
__builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0)
#else
Expand Down
5 changes: 0 additions & 5 deletions drivers/watchdog/kempld_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,7 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
u32 remainder;
u8 stage_cfg;

#if GCC_VERSION < 40400
/* work around a bug compiling do_div() */
prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]);
#else
prescaler = kempld_prescaler[PRESCALER_21];
#endif

if (!stage)
return -EINVAL;
Expand Down
20 changes: 9 additions & 11 deletions include/linux/compiler-clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
/* Some compiler specific definitions are overwritten here
* for Clang compiler
*/

#ifdef uninitialized_var
#undef uninitialized_var
#define uninitialized_var(x) x = *(&(x))
#endif

/* same as gcc, this was present in clang-2.6 so we can assume it works
* with any version that can compile the kernel
Expand All @@ -25,24 +21,26 @@
#define __SANITIZE_ADDRESS__
#endif

#undef __no_sanitize_address
#define __no_sanitize_address __attribute__((no_sanitize("address")))

/* Clang doesn't have a way to turn it off per-function, yet. */
#ifdef __noretpoline
#undef __noretpoline
#endif

/*
* Not all versions of clang implement the the type-generic versions
* of the builtin overflow checkers. Fortunately, clang implements
* __has_builtin allowing us to avoid awkward version
* checks. Unfortunately, we don't know which version of gcc clang
* pretends to be, so the macro may or may not be defined.
*/
#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
#if __has_builtin(__builtin_mul_overflow) && \
__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow)
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif

/* The following are for compatibility with GCC, from compiler-gcc.h,
* and may be redefined here because they should not be shared with other
* compilers, like ICC.
*/
#define barrier() __asm__ __volatile__("" : : : "memory")
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#define __assume_aligned(a, ...) \
__attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
88 changes: 0 additions & 88 deletions include/linux/compiler-gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,48 +75,6 @@
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#endif

/*
* Feature detection for gnu_inline (gnu89 extern inline semantics). Either
* __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
* and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
* defined so the gnu89 semantics are the default.
*/
#ifdef __GNUC_STDC_INLINE__
# define __gnu_inline __attribute__((gnu_inline))
#else
# define __gnu_inline
#endif

/*
* Force always-inline if the user requests it so via the .config,
* or if gcc is too old.
* GCC does not warn about unused static inline functions for
* -Wunused-function. This turns out to avoid the need for complex #ifdef
* directives. Suppress the warning in clang as well by using "unused"
* function attribute, which is redundant but not harmful for gcc.
* Prefer gnu_inline, so that extern inline functions do not emit an
* externally visible function. This makes extern inline behave as per gnu89
* semantics rather than c99. This prevents multiple symbol definition errors
* of extern inline functions at link time.
* A lot of inline functions can cause havoc with function tracing.
*/
#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
!defined(CONFIG_OPTIMIZE_INLINING)
#define inline \
inline __attribute__((always_inline, unused)) notrace __gnu_inline
#else
#define inline inline __attribute__((unused)) notrace __gnu_inline
#endif

#define __inline__ inline
#define __inline inline
#define __always_inline inline __attribute__((always_inline))
#define noinline __attribute__((noinline))

#define __packed __attribute__((packed))
#define __weak __attribute__((weak))
#define __alias(symbol) __attribute__((alias(#symbol)))

#ifdef RETPOLINE
#define __noretpoline __attribute__((indirect_branch("keep")))
#endif
Expand All @@ -135,55 +93,9 @@
*/
#define __naked __attribute__((naked)) noinline __noclone notrace

#define __noreturn __attribute__((noreturn))

/*
* From the GCC manual:
*
* Many functions have no effects except the return value and their
* return value depends only on the parameters and/or global
* variables. Such a function can be subject to common subexpression
* elimination and loop optimization just as an arithmetic operator
* would be.
* [...]
*/
#define __pure __attribute__((pure))
#define __aligned(x) __attribute__((aligned(x)))
#define __aligned_largest __attribute__((aligned))
#define __printf(a, b) __attribute__((format(printf, a, b)))
#define __scanf(a, b) __attribute__((format(scanf, a, b)))
#define __attribute_const__ __attribute__((__const__))
#define __maybe_unused __attribute__((unused))
#define __always_unused __attribute__((unused))
#define __mode(x) __attribute__((mode(x)))

#define __must_check __attribute__((warn_unused_result))
#define __malloc __attribute__((__malloc__))

#define __used __attribute__((__used__))
#define __compiler_offsetof(a, b) \
__builtin_offsetof(a, b)

/* Mark functions as cold. gcc will assume any path leading to a call
* to them will be unlikely. This means a lot of manual unlikely()s
* are unnecessary now for any paths leading to the usual suspects
* like BUG(), printk(), panic() etc. [but let's keep them for now for
* older compilers]
*
* Early snapshots of gcc 4.3 don't support this and we can't detect this
* in the preprocessor, but we can live with this because they're unreleased.
* Maketime probing would be overkill here.
*
* gcc also has a __attribute__((__hot__)) to move hot functions into
* a special section, but I don't see any sense in this right now in
* the kernel context
*/
#define __cold __attribute__((__cold__))

#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)

#define __optimize(level) __attribute__((__optimize__(level)))
#define __nostackprotector __optimize("no-stack-protector")

#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)

Expand Down
13 changes: 4 additions & 9 deletions include/linux/compiler-intel.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
/* Intel ECC compiler doesn't support gcc specific asm stmts.
* It uses intrinsics to do the equivalent things.
*/
#undef barrier
#undef barrier_data
#undef RELOC_HIDE
#undef OPTIMIZER_HIDE_VAR

#define barrier() __memory_barrier()
#define barrier_data(ptr) barrier()
Expand All @@ -38,13 +34,12 @@

#endif

#ifndef __HAVE_BUILTIN_BSWAP16__
/* icc has this, but it's called _bswap16 */
#define __HAVE_BUILTIN_BSWAP16__
#define __builtin_bswap16 _bswap16
#endif

/*
* icc defines __GNUC__, but does not implement the builtin overflow checkers.
/* The following are for compatibility with GCC, from compiler-gcc.h,
* and may be redefined here because they should not be shared with other
* compilers, like clang.
*/
#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
#define __visible __attribute__((externally_visible))
Loading

0 comments on commit 815f0dd

Please sign in to comment.