|
11 | 11 | /// including <base/defines.h>
|
12 | 12 | /// - it should not have fallback to 0,
|
13 | 13 | /// since this may create false-positive detection (common problem)
|
14 |
| -#if defined(__clang__) && defined(__has_feature) |
| 14 | +#if defined(__has_feature) |
15 | 15 | # define ch_has_feature __has_feature
|
16 | 16 | #endif
|
17 | 17 |
|
|
76 | 76 | /// Explicitly allow undefined behaviour for certain functions. Use it as a function attribute.
|
77 | 77 | /// It is useful in case when compiler cannot see (and exploit) it, but UBSan can.
|
78 | 78 | /// Example: multiplication of signed integers with possibility of overflow when both sides are from user input.
|
79 |
| -#if defined(__clang__) |
80 |
| -# define NO_SANITIZE_UNDEFINED __attribute__((__no_sanitize__("undefined"))) |
81 |
| -# define NO_SANITIZE_ADDRESS __attribute__((__no_sanitize__("address"))) |
82 |
| -# define NO_SANITIZE_THREAD __attribute__((__no_sanitize__("thread"))) |
83 |
| -# define ALWAYS_INLINE_NO_SANITIZE_UNDEFINED __attribute__((__always_inline__, __no_sanitize__("undefined"))) |
84 |
| -#else /// It does not work in GCC. GCC 7 cannot recognize this attribute and GCC 8 simply ignores it. |
85 |
| -# define NO_SANITIZE_UNDEFINED |
86 |
| -# define NO_SANITIZE_ADDRESS |
87 |
| -# define NO_SANITIZE_THREAD |
88 |
| -# define ALWAYS_INLINE_NO_SANITIZE_UNDEFINED ALWAYS_INLINE |
89 |
| -#endif |
90 |
| - |
91 |
| -#if defined(__clang__) && defined(__clang_major__) && __clang_major__ >= 14 |
92 |
| -# define DISABLE_SANITIZER_INSTRUMENTATION __attribute__((disable_sanitizer_instrumentation)) |
93 |
| -#else |
94 |
| -# define DISABLE_SANITIZER_INSTRUMENTATION |
95 |
| -#endif |
96 |
| - |
| 79 | +#define NO_SANITIZE_UNDEFINED __attribute__((__no_sanitize__("undefined"))) |
| 80 | +#define NO_SANITIZE_ADDRESS __attribute__((__no_sanitize__("address"))) |
| 81 | +#define NO_SANITIZE_THREAD __attribute__((__no_sanitize__("thread"))) |
| 82 | +#define ALWAYS_INLINE_NO_SANITIZE_UNDEFINED __attribute__((__always_inline__, __no_sanitize__("undefined"))) |
| 83 | +#define DISABLE_SANITIZER_INSTRUMENTATION __attribute__((disable_sanitizer_instrumentation)) |
97 | 84 |
|
98 | 85 | #if !__has_include(<sanitizer/asan_interface.h>) || !defined(ADDRESS_SANITIZER)
|
99 | 86 | # define ASAN_UNPOISON_MEMORY_REGION(a, b)
|
|
135 | 122 |
|
136 | 123 | /// Macros for Clang Thread Safety Analysis (TSA). They can be safely ignored by other compilers.
|
137 | 124 | /// Feel free to extend, but please stay close to https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutexheader
|
138 |
| -#if defined(__clang__) |
139 |
| -# define TSA_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) /// data is protected by given capability |
140 |
| -# define TSA_PT_GUARDED_BY(...) __attribute__((pt_guarded_by(__VA_ARGS__))) /// pointed-to data is protected by the given capability |
141 |
| -# define TSA_REQUIRES(...) __attribute__((requires_capability(__VA_ARGS__))) /// thread needs exclusive possession of given capability |
142 |
| -# define TSA_REQUIRES_SHARED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) /// thread needs shared possession of given capability |
143 |
| -# define TSA_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) /// annotated lock must be locked after given lock |
144 |
| -# define TSA_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) /// disable TSA for a function |
145 |
| -# define TSA_CAPABILITY(...) __attribute__((capability(__VA_ARGS__))) /// object of a class can be used as capability |
146 |
| -# define TSA_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__))) /// function acquires a capability, but does not release it |
147 |
| -# define TSA_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__))) /// function tries to acquire a capability and returns a boolean value indicating success or failure |
148 |
| -# define TSA_RELEASE(...) __attribute__((release_capability(__VA_ARGS__))) /// function releases the given capability |
149 |
| -# define TSA_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) /// function acquires a shared capability, but does not release it |
150 |
| -# define TSA_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) /// function tries to acquire a shared capability and returns a boolean value indicating success or failure |
151 |
| -# define TSA_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__))) /// function releases the given shared capability |
152 |
| -# define TSA_SCOPED_LOCKABLE __attribute__((scoped_lockable)) /// object of a class has scoped lockable capability |
| 125 | +#define TSA_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) /// data is protected by given capability |
| 126 | +#define TSA_PT_GUARDED_BY(...) __attribute__((pt_guarded_by(__VA_ARGS__))) /// pointed-to data is protected by the given capability |
| 127 | +#define TSA_REQUIRES(...) __attribute__((requires_capability(__VA_ARGS__))) /// thread needs exclusive possession of given capability |
| 128 | +#define TSA_REQUIRES_SHARED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) /// thread needs shared possession of given capability |
| 129 | +#define TSA_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) /// annotated lock must be locked after given lock |
| 130 | +#define TSA_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) /// disable TSA for a function |
| 131 | +#define TSA_CAPABILITY(...) __attribute__((capability(__VA_ARGS__))) /// object of a class can be used as capability |
| 132 | +#define TSA_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__))) /// function acquires a capability, but does not release it |
| 133 | +#define TSA_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__))) /// function tries to acquire a capability and returns a boolean value indicating success or failure |
| 134 | +#define TSA_RELEASE(...) __attribute__((release_capability(__VA_ARGS__))) /// function releases the given capability |
| 135 | +#define TSA_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) /// function acquires a shared capability, but does not release it |
| 136 | +#define TSA_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) /// function tries to acquire a shared capability and returns a boolean value indicating success or failure |
| 137 | +#define TSA_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__))) /// function releases the given shared capability |
| 138 | +#define TSA_SCOPED_LOCKABLE __attribute__((scoped_lockable)) /// object of a class has scoped lockable capability |
153 | 139 |
|
154 | 140 | /// Macros for suppressing TSA warnings for specific reads/writes (instead of suppressing it for the whole function)
|
155 | 141 | /// They use a lambda function to apply function attribute to a single statement. This enable us to suppress warnings locally instead of
|
156 | 142 | /// suppressing them in the whole function
|
157 | 143 | /// Consider adding a comment when using these macros.
|
158 |
| -# define TSA_SUPPRESS_WARNING_FOR_READ(x) ([&]() TSA_NO_THREAD_SAFETY_ANALYSIS -> const auto & { return (x); }()) |
159 |
| -# define TSA_SUPPRESS_WARNING_FOR_WRITE(x) ([&]() TSA_NO_THREAD_SAFETY_ANALYSIS -> auto & { return (x); }()) |
| 144 | +#define TSA_SUPPRESS_WARNING_FOR_READ(x) ([&]() TSA_NO_THREAD_SAFETY_ANALYSIS -> const auto & { return (x); }()) |
| 145 | +#define TSA_SUPPRESS_WARNING_FOR_WRITE(x) ([&]() TSA_NO_THREAD_SAFETY_ANALYSIS -> auto & { return (x); }()) |
160 | 146 |
|
161 | 147 | /// This macro is useful when only one thread writes to a member
|
162 | 148 | /// and you want to read this member from the same thread without locking a mutex.
|
163 | 149 | /// It's safe (because no concurrent writes are possible), but TSA generates a warning.
|
164 | 150 | /// (Seems like there's no way to verify it, but it makes sense to distinguish it from TSA_SUPPRESS_WARNING_FOR_READ for readability)
|
165 |
| -# define TSA_READ_ONE_THREAD(x) TSA_SUPPRESS_WARNING_FOR_READ(x) |
166 |
| - |
167 |
| -#else |
168 |
| -# define TSA_GUARDED_BY(...) |
169 |
| -# define TSA_PT_GUARDED_BY(...) |
170 |
| -# define TSA_REQUIRES(...) |
171 |
| -# define TSA_REQUIRES_SHARED(...) |
172 |
| -# define TSA_NO_THREAD_SAFETY_ANALYSIS |
173 |
| -# define TSA_CAPABILITY(...) |
174 |
| -# define TSA_ACQUIRE(...) |
175 |
| -# define TSA_TRY_ACQUIRE(...) |
176 |
| -# define TSA_RELEASE(...) |
177 |
| -# define TSA_ACQUIRE_SHARED(...) |
178 |
| -# define TSA_TRY_ACQUIRE_SHARED(...) |
179 |
| -# define TSA_RELEASE_SHARED(...) |
180 |
| -# define TSA_SCOPED_LOCKABLE |
181 |
| - |
182 |
| -# define TSA_SUPPRESS_WARNING_FOR_READ(x) (x) |
183 |
| -# define TSA_SUPPRESS_WARNING_FOR_WRITE(x) (x) |
184 |
| -# define TSA_READ_ONE_THREAD(x) TSA_SUPPRESS_WARNING_FOR_READ(x) |
185 |
| -#endif |
| 151 | +#define TSA_READ_ONE_THREAD(x) TSA_SUPPRESS_WARNING_FOR_READ(x) |
186 | 152 |
|
187 | 153 | /// A template function for suppressing warnings about unused variables or function results.
|
188 | 154 | template <typename... Args>
|
|
0 commit comments