Use attribute testing to simplify portable attribute macros
Fixes #4025 PiperOrigin-RevId: 481186097 Change-Id: Id7d09e4626e5ccf564e8cfaa65581c1cd827918d
This commit is contained in:
parent
137b6e2770
commit
a9b2f0495c
@ -642,6 +642,22 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
default: // NOLINT
|
||||
#endif
|
||||
|
||||
// GTEST_HAVE_ATTRIBUTE_
|
||||
//
|
||||
// A function-like feature checking macro that is a wrapper around
|
||||
// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
|
||||
// nonzero constant integer if the attribute is supported or 0 if not.
|
||||
//
|
||||
// It evaluates to zero if `__has_attribute` is not defined by the compiler.
|
||||
//
|
||||
// GCC: https://gcc.gnu.org/gcc-5/changes.html
|
||||
// Clang: https://clang.llvm.org/docs/LanguageExtensions.html
|
||||
#ifdef __has_attribute
|
||||
#define GTEST_HAVE_ATTRIBUTE_(x) __has_attribute(x)
|
||||
#else
|
||||
#define GTEST_HAVE_ATTRIBUTE_(x) 0
|
||||
#endif
|
||||
|
||||
// Use this annotation at the end of a struct/class definition to
|
||||
// prevent the compiler from optimizing away instances that are never
|
||||
// used. This is useful when all interesting logic happens inside the
|
||||
@ -653,30 +669,22 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
//
|
||||
// Also use it after a variable or parameter declaration to tell the
|
||||
// compiler the variable/parameter does not have to be used.
|
||||
#if defined(__GNUC__) && !defined(COMPILER_ICC)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(unused)
|
||||
#define GTEST_ATTRIBUTE_UNUSED_ __attribute__((unused))
|
||||
#elif defined(__clang__)
|
||||
#if __has_attribute(unused)
|
||||
#define GTEST_ATTRIBUTE_UNUSED_ __attribute__((unused))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GTEST_ATTRIBUTE_UNUSED_
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_UNUSED_
|
||||
#endif
|
||||
|
||||
// Use this annotation before a function that takes a printf format string.
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC)
|
||||
#if defined(__MINGW_PRINTF_FORMAT)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
|
||||
// MinGW has two different printf implementations. Ensure the format macro
|
||||
// matches the selected implementation. See
|
||||
// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
|
||||
__attribute__(( \
|
||||
__format__(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
|
||||
__attribute__((__format__(__printf__, string_index, first_to_check)))
|
||||
#endif
|
||||
__attribute__((format(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
|
||||
#elif GTEST_HAVE_ATTRIBUTE_(format)
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
|
||||
__attribute__((format(printf, string_index, first_to_check)))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
|
||||
#endif
|
||||
@ -686,11 +694,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
// following the argument list:
|
||||
//
|
||||
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
|
||||
#if defined(__GNUC__) && !defined(COMPILER_ICC)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
|
||||
#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define GTEST_MUST_USE_RESULT_
|
||||
#endif // __GNUC__ && !COMPILER_ICC
|
||||
#endif
|
||||
|
||||
// MS C++ compiler emits warning when a conditional expression is compile time
|
||||
// constant. In some contexts this warning is false positive and needs to be
|
||||
@ -746,7 +754,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#elif GTEST_CREATE_SHARED_LIBRARY
|
||||
#define GTEST_API_ __declspec(dllexport)
|
||||
#endif
|
||||
#elif __GNUC__ >= 4 || defined(__clang__)
|
||||
#elif GTEST_HAVE_ATTRIBUTE_(visibility)
|
||||
#define GTEST_API_ __attribute__((visibility("default")))
|
||||
#endif // _MSC_VER
|
||||
|
||||
@ -760,20 +768,17 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#define GTEST_DEFAULT_DEATH_TEST_STYLE "fast"
|
||||
#endif // GTEST_DEFAULT_DEATH_TEST_STYLE
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if GTEST_HAVE_ATTRIBUTE_(noinline)
|
||||
// Ask the compiler to never inline a given function.
|
||||
#define GTEST_NO_INLINE_ __attribute__((noinline))
|
||||
#else
|
||||
#define GTEST_NO_INLINE_
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
// Nested ifs to avoid triggering MSVC warning.
|
||||
#if __has_attribute(disable_tail_calls)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(disable_tail_calls)
|
||||
// Ask the compiler not to perform tail call optimization inside
|
||||
// the marked function.
|
||||
#define GTEST_NO_TAIL_CALL_ __attribute__((disable_tail_calls))
|
||||
#endif
|
||||
#elif __GNUC__
|
||||
#define GTEST_NO_TAIL_CALL_ \
|
||||
__attribute__((optimize("no-optimize-sibling-calls")))
|
||||
@ -792,50 +797,34 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
|
||||
// A function level attribute to disable checking for use of uninitialized
|
||||
// memory when built with MemorySanitizer.
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_memory)
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ __attribute__((no_sanitize_memory))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
#endif // __has_feature(memory_sanitizer)
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
#endif // __clang__
|
||||
#endif
|
||||
|
||||
// A function level attribute to disable AddressSanitizer instrumentation.
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(address_sanitizer)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_address)
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
|
||||
__attribute__((no_sanitize_address))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
#endif // __has_feature(address_sanitizer)
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
#endif // __clang__
|
||||
#endif
|
||||
|
||||
// A function level attribute to disable HWAddressSanitizer instrumentation.
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(hwaddress_sanitizer)
|
||||
#if GTEST_HAVE_ATTRIBUTE_(no_sanitize)
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \
|
||||
__attribute__((no_sanitize("hwaddress")))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
#endif // __has_feature(hwaddress_sanitizer)
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
#endif // __clang__
|
||||
#endif
|
||||
|
||||
// A function level attribute to disable ThreadSanitizer instrumentation.
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(thread_sanitizer)
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ __attribute__((no_sanitize_thread))
|
||||
#if GTEST_HAVE_ATTRIBUTE_(no_sanitize_thread)
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ __attribute((no_sanitize_thread))
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
#endif // __has_feature(thread_sanitizer)
|
||||
#else
|
||||
#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
#endif // __clang__
|
||||
#endif
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user