blob: 068eeb058a4bec4942d913b6e33604fd6abd906e [file] [log] [blame]
#ifndef LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_
#define LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_
// A collection of compiler attribute checks and defines to control for
// compatibility across toolchains.
#if defined(__has_attribute)
#define LIBGAV1_HAS_ATTRIBUTE __has_attribute
#else
#define LIBGAV1_HAS_ATTRIBUTE(x) 0
#endif
#if defined(__has_feature)
#define LIBGAV1_HAS_FEATURE __has_feature
#else
#define LIBGAV1_HAS_FEATURE(x) 0
#endif
//------------------------------------------------------------------------------
// Sanitizer attributes.
#if LIBGAV1_HAS_FEATURE(memory_sanitizer)
#define LIBGAV1_MSAN 1
#else
#define LIBGAV1_MSAN 0
#endif
#if LIBGAV1_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
#define LIBGAV1_TSAN 1
#else
#define LIBGAV1_TSAN 0
#endif
//------------------------------------------------------------------------------
// Function attributes.
// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
// Clang: https://clang.llvm.org/docs/AttributeReference.html
#if defined(__GNUC__)
#define LIBGAV1_ALWAYS_INLINE __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
#define LIBGAV1_ALWAYS_INLINE __forceinline
#else
#define LIBGAV1_ALWAYS_INLINE inline
#endif
// LIBGAV1_MUST_USE_RESULT
//
// Tells the compiler to warn about unused results.
//
// When annotating a function, it must appear as the first part of the
// declaration or definition. The compiler will warn if the return value from
// such a function is unused:
//
// LIBGAV1_MUST_USE_RESULT Sprocket* AllocateSprocket();
// AllocateSprocket(); // Triggers a warning.
//
// When annotating a class, it is equivalent to annotating every function which
// returns an instance.
//
// class LIBGAV1_MUST_USE_RESULT Sprocket {};
// Sprocket(); // Triggers a warning.
//
// Sprocket MakeSprocket();
// MakeSprocket(); // Triggers a warning.
//
// Note that references and pointers are not instances:
//
// Sprocket* SprocketPointer();
// SprocketPointer(); // Does *not* trigger a warning.
//
// LIBGAV1_MUST_USE_RESULT allows using cast-to-void to suppress the unused
// result warning. For that, warn_unused_result is used only for clang but not
// for gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
#if LIBGAV1_HAS_ATTRIBUTE(nodiscard)
#define LIBGAV1_MUST_USE_RESULT [[nodiscard]]
#elif defined(__clang__) && LIBGAV1_HAS_ATTRIBUTE(warn_unused_result)
#define LIBGAV1_MUST_USE_RESULT __attribute__((warn_unused_result))
#else
#define LIBGAV1_MUST_USE_RESULT
#endif
// LIBGAV1_PRINTF_ATTRIBUTE
//
// Tells the compiler to perform `printf` format string checking if the
// compiler supports it; see the 'format' attribute in
// <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html>.
//
// Note: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
// should be counted from two, not one."
#if LIBGAV1_HAS_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))
#define LIBGAV1_PRINTF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((__format__(__printf__, string_index, first_to_check)))
#else
#define LIBGAV1_PRINTF_ATTRIBUTE(string_index, first_to_check)
#endif
//------------------------------------------------------------------------------
// Thread annotations.
// LIBGAV1_GUARDED_BY()
//
// Documents if a shared field or global variable needs to be protected by a
// mutex. LIBGAV1_GUARDED_BY() allows the user to specify a particular mutex
// that should be held when accessing the annotated variable.
//
// Although this annotation cannot be applied to local variables, a local
// variable and its associated mutex can often be combined into a small class
// or struct, thereby allowing the annotation.
//
// Example:
//
// class Foo {
// Mutex mu_;
// int p1_ LIBGAV1_GUARDED_BY(mu_);
// ...
// };
// TODO(b/132506370): this can be reenabled after a local MutexLock
// implementation is added with proper thread annotations.
#if 0 // LIBGAV1_HAS_ATTRIBUTE(guarded_by)
#define LIBGAV1_GUARDED_BY(x) __attribute__((guarded_by(x)))
#else
#define LIBGAV1_GUARDED_BY(x)
#endif
//------------------------------------------------------------------------------
#undef LIBGAV1_HAS_ATTRIBUTE
#undef LIBGAV1_HAS_FEATURE
#endif // LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_