• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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