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