<div dir="ltr">This actually needs more testing. But feel free to comment on the direction.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 2, 2013 at 2:21 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">When targetting Windows, clang does not define __GNUC__, and as a result<br>
we don't use our attributes with it. This leads to warnings about<br>
unused functions that are already annotated with LLVM_ATTRIBUTE_UNUSED.<br>
<br>
While I'm here, conditionally define and use __GNUC_PREREQ for gcc<br>
version checks. Spelling the check out with three comparisons is<br>
verbose and error prone.<br>
<br>
<a href="http://llvm-reviews.chandlerc.com/D1080" target="_blank">http://llvm-reviews.chandlerc.com/D1080</a><br>
<br>
Files:<br>
include/llvm/Support/Compiler.h<br>
<br>
Index: include/llvm/Support/Compiler.h<br>
===================================================================<br>
--- include/llvm/Support/Compiler.h<br>
+++ include/llvm/Support/Compiler.h<br>
@@ -21,6 +21,21 @@<br>
# define __has_feature(x) 0<br>
#endif<br>
<br>
+#ifndef __has_attribute<br>
+# define __has_attribute(x) 0<br>
+#endif<br>
+<br>
+/// \macro __GNUC_PREREQ<br>
+/// \brief Defines __GNUC_PREREQ if glibc's features.h isn't available.<br>
+#ifndef __GNUC_PREREQ<br>
+# if defined(__GNUC__) && defined(__GNUC_MINOR__)<br>
+# define __GNUC_PREREQ(maj, min) \<br>
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))<br>
+# else<br>
+# define __GNUC_PREREQ(maj, min) 0<br>
+# endif<br>
+#endif<br>
+<br>
/// \brief Does the compiler support r-value references?<br>
/// This implies that <utility> provides the one-argument std::move; it<br>
/// does not imply the existence of any other C++ library features.<br>
@@ -146,13 +161,13 @@<br>
/// into a shared library, then the class should be private to the library and<br>
/// not accessible from outside it. Can also be used to mark variables and<br>
/// functions, making them private to any shared library they are linked into.<br>
-#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__)<br>
+#if __GNUC_PREREQ(4, 0) && !defined(__MINGW32__) && !defined(__CYGWIN__)<br>
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))<br>
#else<br>
#define LLVM_LIBRARY_VISIBILITY<br>
#endif<br>
<br>
-#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))<br>
+#if __has_attribute(used) || __GNUC_PREREQ(3, 1)<br>
#define LLVM_ATTRIBUTE_USED __attribute__((__used__))<br>
#else<br>
#define LLVM_ATTRIBUTE_USED<br>
@@ -166,31 +181,33 @@<br>
// more portable solution:<br>
// (void)unused_var_name;<br>
// Prefer cast-to-void wherever it is sufficient.<br>
-#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))<br>
+#if __has_attribute(unused) || __GNUC_PREREQ(3, 1)<br>
#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))<br>
#else<br>
#define LLVM_ATTRIBUTE_UNUSED<br>
#endif<br>
<br>
-#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__)<br>
+#if __GNUC_PREREQ(4, 0) && !defined(__MINGW32__) && !defined(__CYGWIN__)<br>
#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))<br>
#else<br>
#define LLVM_ATTRIBUTE_WEAK<br>
#endif<br>
<br>
-#ifdef __GNUC__ // aka 'CONST' but following LLVM Conventions.<br>
+#if __has_attribute(const) || defined(__GNUC__)<br>
+// aka 'CONST' but following LLVM Conventions.<br>
#define LLVM_READNONE __attribute__((__const__))<br>
#else<br>
#define LLVM_READNONE<br>
#endif<br>
<br>
-#ifdef __GNUC__ // aka 'PURE' but following LLVM Conventions.<br>
+#if __has_attribute(pure) || defined(__GNUC__)<br>
+// aka 'PURE' but following LLVM Conventions.<br>
#define LLVM_READONLY __attribute__((__pure__))<br>
#else<br>
#define LLVM_READONLY<br>
#endif<br>
<br>
-#if (__GNUC__ >= 4)<br>
+#if __has_builtin(__builtin_expect) || __GNUC_PREREQ(4, 0)<br>
#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)<br>
#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)<br>
#else<br>
@@ -213,7 +230,7 @@<br>
<br>
/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,<br>
/// mark a method "not for inlining".<br>
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))<br>
+#if __GNUC_PREREQ(3, 4)<br>
#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))<br>
#elif defined(_MSC_VER)<br>
#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)<br>
@@ -225,7 +242,7 @@<br>
/// so, mark a method "always inline" because it is performance sensitive. GCC<br>
/// 3.4 supported this but is buggy in various cases and produces unimplemented<br>
/// errors, just use it in GCC 4.0 and later.<br>
-#if __GNUC__ > 3<br>
+#if __GNUC_PREREQ(3, 0)<br>
#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))<br>
#elif defined(_MSC_VER)<br>
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline<br>
@@ -267,27 +284,23 @@<br>
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands<br>
/// to an expression which states that it is undefined behavior for the<br>
/// compiler to reach this point. Otherwise is not defined.<br>
-#if defined(__clang__) || (__GNUC__ > 4) \<br>
- || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)<br>
+#if __has_builtin(__builtin_unreachable) || __GNUC_PREREQ(4, 5)<br>
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()<br>
#elif defined(_MSC_VER)<br>
# define LLVM_BUILTIN_UNREACHABLE __assume(false)<br>
#endif<br>
<br>
/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression<br>
/// which causes the program to exit abnormally.<br>
-#if defined(__clang__) || (__GNUC__ > 4) \<br>
- || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)<br>
+#if __has_builtin(__builtin_trap) || __GNUC_PREREQ(4, 3)<br>
# define LLVM_BUILTIN_TRAP __builtin_trap()<br>
#else<br>
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0<br>
#endif<br>
<br>
/// \macro LLVM_ASSUME_ALIGNED<br>
/// \brief Returns a pointer with an assumed alignment.<br>
-#if !defined(__clang__) && ((__GNUC__ > 4) \<br>
- || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))<br>
-// FIXME: Enable on clang when it supports it.<br>
+#if __has_builtin(__builtin_assume_aligned) && __GNUC_PREREQ(4, 7)<br>
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)<br>
#elif defined(LLVM_BUILTIN_UNREACHABLE)<br>
# define LLVM_ASSUME_ALIGNED(p, a) \<br>
</blockquote></div><br></div>