xref: /aosp_15_r20/external/libgav1/src/utils/compiler_attributes.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
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