This is an archive of the discontinued LLVM Phabricator instance.

[Preprocessor] raise gcc compatibility macros.
AbandonedPublic

Authored by nickdesaulniers on Aug 20 2018, 4:19 PM.

Details

Reviewers
aaron.ballman
Summary

Building the Linux kernel with clang is now broken as of commit
cafa0010cd51 ("Raise the minimum required gcc version to 4.6").

We were getting lucky that Clang previously declared compatibility with
gcc 4.2.1 as the kernel only errored out for gcc < 3.2. The compiler
check in the kernel should be improved as well.

Diff Detail

Event Timeline

rsmith added a subscriber: rsmith.Aug 20 2018, 6:01 PM

We are not fully compatible with any version of GCC later than 4.2, as we do not implement __builtin_va_arg_pack / __builtin_va_arg_pack_len. These builtins are used by the glibc headers if we claim to be GCC >= 4.3 (at least according to http://clang.llvm.org/docs/UsersManual.html#gcc-extensions-not-implemented-yet), so this change will cause Clang to no longer compile (some versions of) the glibc headers.

Can you instead change the kernel to require GCC >= 4.6 or some suitable version of Clang?

Another possibility would be to add a command-line argument to set the version of GCC that clang pretends to be. We have a similar mechanism for our MSVC compatibility mode already.

Richard,
Thanks for the review, context, and suggestions. I appreciate it.

Can you instead change the kernel to require GCC >= 4.6 or some suitable version of Clang?

Can you help me create an accurate C preprocessor check that the compiler in use is actually GCC and not Clang or ICC in emulation?

#if defined(__GNU_C__) && !defined(__clang__)
// we're gcc
#elif defined(__clang__)
// we're clang
#elif defined(__INTEL_COMPILER)
// we're icc
#endif

Or maybe:

#ifdef(__clang__)
// we're clang
#elif defined(__INTEL_COMPILER)
// we're icc
#else
// default to gcc
#endif

Maybe GCC has something better for this case than __GNU_C__?

Regarding the glibc headers, do you know why glibc doesn't just add code for __clang__ rather than Clang (and ICC) claim to be a gcc compatible to a point compiler?

Regarding the command line addition, I'd prefer to fix the kernel's compiler detection, but I will keep your idea in mind. It's good to have a few solutions in our back pockets should the preferred be shown to be faulty.

Thanks again.

I'd suggest something like this, if you really need to detect the compiler:

#if defined(__clang__)
// clang
#elif defined(__INTEL_COMPILER)
// icc
#elif defined(__GNUC__)
// gcc
#else
#error "Unknown compiler"
#endif

Regarding the glibc headers, do you know why glibc doesn't just add code for clang rather than Clang (and ICC) claim to be a gcc compatible to a point compiler?

clang pretends to be gcc 4.2 because that was the simplest way to make a lot of existing code work, at the time clang was written. clang supports almost all the language extensions supported by that version of gcc, so code was more likely to work if clang pretended to be gcc, rather than some unknown compiler. And now, it would break a bunch of code if it changed, so it basically can't be changed. This is similar to the history of web browser user agent strings.

For new code, we encourage users to use the feature checking macros (https://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros ), rather than checking for specific compiler versions, where possible.

Thanks Eli. I wholeheartedly prefer feature detection to explicit version checks. One thing that makes this hard is the lack of __has_attribute in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970.

nickdesaulniers abandoned this revision.Aug 21 2018, 3:40 PM