1 /* 2 * Copyright 2019 The libgav1 Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_ 18 #define LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_ 19 20 // A collection of compiler attribute checks and defines to control for 21 // compatibility across toolchains. 22 23 //------------------------------------------------------------------------------ 24 // Language version, attribute and feature helpers. 25 26 // Detect c++17 support. Visual Studio sets __cplusplus to 199711L by default 27 // unless compiled with /Zc:__cplusplus, use the value controlled by /std 28 // instead. 29 // https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus 30 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 31 #define LIBGAV1_CXX17 1 32 #else 33 #define LIBGAV1_CXX17 0 34 #endif 35 36 #if defined(__has_attribute) 37 #define LIBGAV1_HAS_ATTRIBUTE __has_attribute 38 #else 39 #define LIBGAV1_HAS_ATTRIBUTE(x) 0 40 #endif 41 42 #if defined(__has_feature) 43 #define LIBGAV1_HAS_FEATURE __has_feature 44 #else 45 #define LIBGAV1_HAS_FEATURE(x) 0 46 #endif 47 48 //------------------------------------------------------------------------------ 49 // Sanitizer attributes. 50 51 #if LIBGAV1_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) 52 #define LIBGAV1_ASAN 1 53 #else 54 #define LIBGAV1_ASAN 0 55 #endif 56 57 #if LIBGAV1_HAS_FEATURE(memory_sanitizer) 58 #define LIBGAV1_MSAN 1 59 #else 60 #define LIBGAV1_MSAN 0 61 #endif 62 63 #if LIBGAV1_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__) 64 #define LIBGAV1_TSAN 1 65 #else 66 #define LIBGAV1_TSAN 0 67 #endif 68 69 //------------------------------------------------------------------------------ 70 // AddressSanitizer support. 71 72 // Define the macros for AddressSanitizer manual memory poisoning. See 73 // https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning. 74 #if LIBGAV1_ASAN 75 #include <sanitizer/asan_interface.h> 76 #else 77 #define ASAN_POISON_MEMORY_REGION(addr, size) \ 78 (static_cast<void>(addr), static_cast<void>(size)) 79 #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ 80 (static_cast<void>(addr), static_cast<void>(size)) 81 #endif 82 83 //------------------------------------------------------------------------------ 84 // Function attributes. 85 // GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 86 // Clang: https://clang.llvm.org/docs/AttributeReference.html 87 88 #if defined(__GNUC__) 89 #define LIBGAV1_ALWAYS_INLINE __attribute__((always_inline)) inline 90 #elif defined(_MSC_VER) 91 #define LIBGAV1_ALWAYS_INLINE __forceinline 92 #else 93 #define LIBGAV1_ALWAYS_INLINE inline 94 #endif 95 96 // LIBGAV1_MUST_USE_RESULT 97 // 98 // Tells the compiler to warn about unused results. 99 // 100 // When annotating a function, it must appear as the first part of the 101 // declaration or definition. The compiler will warn if the return value from 102 // such a function is unused: 103 // 104 // LIBGAV1_MUST_USE_RESULT Sprocket* AllocateSprocket(); 105 // AllocateSprocket(); // Triggers a warning. 106 // 107 // When annotating a class, it is equivalent to annotating every function which 108 // returns an instance. 109 // 110 // class LIBGAV1_MUST_USE_RESULT Sprocket {}; 111 // Sprocket(); // Triggers a warning. 112 // 113 // Sprocket MakeSprocket(); 114 // MakeSprocket(); // Triggers a warning. 115 // 116 // Note that references and pointers are not instances: 117 // 118 // Sprocket* SprocketPointer(); 119 // SprocketPointer(); // Does *not* trigger a warning. 120 // 121 // LIBGAV1_MUST_USE_RESULT allows using cast-to-void to suppress the unused 122 // result warning. For that, warn_unused_result is used only for clang but not 123 // for gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 124 #if LIBGAV1_HAS_ATTRIBUTE(nodiscard) 125 #define LIBGAV1_MUST_USE_RESULT [[nodiscard]] 126 #elif defined(__clang__) && LIBGAV1_HAS_ATTRIBUTE(warn_unused_result) 127 #define LIBGAV1_MUST_USE_RESULT __attribute__((warn_unused_result)) 128 #else 129 #define LIBGAV1_MUST_USE_RESULT 130 #endif 131 132 // LIBGAV1_PRINTF_ATTRIBUTE 133 // 134 // Tells the compiler to perform `printf` format string checking if the 135 // compiler supports it; see the 'format' attribute in 136 // <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html>. 137 // 138 // Note: As the GCC manual states, "[s]ince non-static C++ methods 139 // have an implicit 'this' argument, the arguments of such methods 140 // should be counted from two, not one." 141 #if LIBGAV1_HAS_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) 142 #define LIBGAV1_PRINTF_ATTRIBUTE(string_index, first_to_check) \ 143 __attribute__((__format__(__printf__, string_index, first_to_check))) 144 #else 145 #define LIBGAV1_PRINTF_ATTRIBUTE(string_index, first_to_check) 146 #endif 147 148 //------------------------------------------------------------------------------ 149 // Thread annotations. 150 151 // LIBGAV1_GUARDED_BY() 152 // 153 // Documents if a shared field or global variable needs to be protected by a 154 // mutex. LIBGAV1_GUARDED_BY() allows the user to specify a particular mutex 155 // that should be held when accessing the annotated variable. 156 // 157 // Although this annotation cannot be applied to local variables, a local 158 // variable and its associated mutex can often be combined into a small class 159 // or struct, thereby allowing the annotation. 160 // 161 // Example: 162 // 163 // class Foo { 164 // Mutex mu_; 165 // int p1_ LIBGAV1_GUARDED_BY(mu_); 166 // ... 167 // }; 168 // TODO(b/132506370): this can be reenabled after a local MutexLock 169 // implementation is added with proper thread annotations. 170 #if 0 // LIBGAV1_HAS_ATTRIBUTE(guarded_by) 171 #define LIBGAV1_GUARDED_BY(x) __attribute__((guarded_by(x))) 172 #else 173 #define LIBGAV1_GUARDED_BY(x) 174 #endif 175 176 //------------------------------------------------------------------------------ 177 178 #undef LIBGAV1_HAS_ATTRIBUTE 179 #undef LIBGAV1_HAS_FEATURE 180 181 #endif // LIBGAV1_SRC_UTILS_COMPILER_ATTRIBUTES_H_ 182