https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109882
--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Libstdc++ itself does this:
#if __SANITIZE_THREAD__
# define _GLIBCXX_TSAN 1
#elif defined __has_feature
# if __has_feature(thread_sanitizer)
# define _GLIBCXX_TSAN 1
# endif
#endif
The sanitizers could do something similar, although it looks like they don't
actually need to. The only use of __has_feature in the public API is in
asan_interface.h and that could easily be replaced. Then __has_feature can be
redefined in the internal headers, which (I assume) aren't meant to be included
by user code.
Something like this (untested):
diff --git a/libsanitizer/include/sanitizer/asan_interface.h
b/libsanitizer/include/sanitizer/asan_interface.h
index 9bff21c117b..186269ad694 100644
--- a/libsanitizer/include/sanitizer/asan_interface.h
+++ b/libsanitizer/include/sanitizer/asan_interface.h
@@ -48,7 +48,15 @@ void __asan_poison_memory_region(void const volatile *addr,
size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
// Macros provided for convenience.
-#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#ifdef __has_feature
+#if __has_feature(address_sanitizer)
+#define ASAN_DEFINE_REGION_MACROS
+#endif
+#elif defined(__SANITIZE_ADDRESS__)
+#define ASAN_DEFINE_REGION_MACROS
+#endif
+
+#ifdef ASAN_DEFINE_REGION_MACROS
/// Marks a memory region as unaddressable.
///
/// \note Macro provided for convenience; defined as a no-op if ASan is not
@@ -74,6 +82,7 @@ void __asan_unpoison_memory_region(void const volatile *addr,
size_t size);
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
((void)(addr), (void)(size))
#endif
+#undef ASAN_DEFINE_REGION_MACROS
/// Checks if an address is poisoned.
///
diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h
b/libsanitizer/include/sanitizer/common_interface_defs.h
index 2f415bd9e85..2f9c83ef74e 100644
--- a/libsanitizer/include/sanitizer/common_interface_defs.h
+++ b/libsanitizer/include/sanitizer/common_interface_defs.h
@@ -15,11 +15,6 @@
#include <stddef.h>
#include <stdint.h>
-// GCC does not understand __has_feature.
-#if !defined(__has_feature)
-#define __has_feature(x) 0
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index 98186c429e9..7574dce7f4a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -14,6 +14,11 @@
#include "sanitizer_platform.h"
+// GCC does not understand __has_feature.
+#if !defined(__has_feature)
+#define __has_feature(x) 0
+#endif
+
#ifndef SANITIZER_DEBUG
# define SANITIZER_DEBUG 0
#endif