1 | /* |
2 | * Copyright (c) Facebook, Inc. and its affiliates. |
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 | #pragma once |
18 | |
19 | /* These definitions are in a separate file so that they |
20 | * may be included from C- as well as C++-based projects. */ |
21 | |
22 | #include <folly/portability/Config.h> |
23 | |
24 | /** |
25 | * Portable version check. |
26 | */ |
27 | #ifndef __GNUC_PREREQ |
28 | #if defined __GNUC__ && defined __GNUC_MINOR__ |
29 | /* nolint */ |
30 | #define __GNUC_PREREQ(maj, min) \ |
31 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) |
32 | #else |
33 | /* nolint */ |
34 | #define __GNUC_PREREQ(maj, min) 0 |
35 | #endif |
36 | #endif |
37 | |
38 | // portable version check for clang |
39 | #ifndef __CLANG_PREREQ |
40 | #if defined __clang__ && defined __clang_major__ && defined __clang_minor__ |
41 | /* nolint */ |
42 | #define __CLANG_PREREQ(maj, min) \ |
43 | ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) |
44 | #else |
45 | /* nolint */ |
46 | #define __CLANG_PREREQ(maj, min) 0 |
47 | #endif |
48 | #endif |
49 | |
50 | #if defined(__has_builtin) |
51 | #define FOLLY_HAS_BUILTIN(...) __has_builtin(__VA_ARGS__) |
52 | #else |
53 | #define FOLLY_HAS_BUILTIN(...) 0 |
54 | #endif |
55 | |
56 | #if defined(__has_feature) |
57 | #define FOLLY_HAS_FEATURE(...) __has_feature(__VA_ARGS__) |
58 | #else |
59 | #define FOLLY_HAS_FEATURE(...) 0 |
60 | #endif |
61 | |
62 | /* FOLLY_SANITIZE_ADDRESS is defined to 1 if the current compilation unit |
63 | * is being compiled with ASAN enabled. |
64 | * |
65 | * Beware when using this macro in a header file: this macro may change values |
66 | * across compilation units if some libraries are built with ASAN enabled |
67 | * and some built with ASAN disabled. For instance, this may occur, if folly |
68 | * itself was compiled without ASAN but a downstream project that uses folly is |
69 | * compiling with ASAN enabled. |
70 | * |
71 | * Use FOLLY_LIBRARY_SANITIZE_ADDRESS (defined in folly-config.h) to check if |
72 | * folly itself was compiled with ASAN enabled. |
73 | */ |
74 | #ifndef FOLLY_SANITIZE_ADDRESS |
75 | #if FOLLY_HAS_FEATURE(address_sanitizer) || __SANITIZE_ADDRESS__ |
76 | #define FOLLY_SANITIZE_ADDRESS 1 |
77 | #endif |
78 | #endif |
79 | |
80 | /* Define attribute wrapper for function attribute used to disable |
81 | * address sanitizer instrumentation. Unfortunately, this attribute |
82 | * has issues when inlining is used, so disable that as well. */ |
83 | #ifdef FOLLY_SANITIZE_ADDRESS |
84 | #if defined(__clang__) |
85 | #if __has_attribute(__no_sanitize__) |
86 | #define FOLLY_DISABLE_ADDRESS_SANITIZER \ |
87 | __attribute__((__no_sanitize__("address"), __noinline__)) |
88 | #elif __has_attribute(__no_address_safety_analysis__) |
89 | #define FOLLY_DISABLE_ADDRESS_SANITIZER \ |
90 | __attribute__((__no_address_safety_analysis__, __noinline__)) |
91 | #elif __has_attribute(__no_sanitize_address__) |
92 | #define FOLLY_DISABLE_ADDRESS_SANITIZER \ |
93 | __attribute__((__no_sanitize_address__, __noinline__)) |
94 | #endif |
95 | #elif defined(__GNUC__) |
96 | #define FOLLY_DISABLE_ADDRESS_SANITIZER \ |
97 | __attribute__((__no_address_safety_analysis__, __noinline__)) |
98 | #endif |
99 | #endif |
100 | #ifndef FOLLY_DISABLE_ADDRESS_SANITIZER |
101 | #define FOLLY_DISABLE_ADDRESS_SANITIZER |
102 | #endif |
103 | |
104 | /* Define a convenience macro to test when thread sanitizer is being used |
105 | * across the different compilers (e.g. clang, gcc) */ |
106 | #ifndef FOLLY_SANITIZE_THREAD |
107 | #if FOLLY_HAS_FEATURE(thread_sanitizer) || __SANITIZE_THREAD__ |
108 | #define FOLLY_SANITIZE_THREAD 1 |
109 | #endif |
110 | #endif |
111 | |
112 | #if FOLLY_SANITIZE_THREAD |
113 | #define FOLLY_DISABLE_THREAD_SANITIZER \ |
114 | __attribute__((no_sanitize_thread, noinline)) |
115 | #else |
116 | #define FOLLY_DISABLE_THREAD_SANITIZER |
117 | #endif |
118 | |
119 | /** |
120 | * Define a convenience macro to test when memory sanitizer is being used |
121 | * across the different compilers (e.g. clang, gcc) |
122 | */ |
123 | #ifndef FOLLY_SANITIZE_MEMORY |
124 | #if FOLLY_HAS_FEATURE(memory_sanitizer) || __SANITIZE_MEMORY__ |
125 | #define FOLLY_SANITIZE_MEMORY 1 |
126 | #endif |
127 | #endif |
128 | |
129 | #if FOLLY_SANITIZE_MEMORY |
130 | #define FOLLY_DISABLE_MEMORY_SANITIZER \ |
131 | __attribute__((no_sanitize_memory, noinline)) |
132 | #else |
133 | #define FOLLY_DISABLE_MEMORY_SANITIZER |
134 | #endif |
135 | |
136 | /** |
137 | * Define a convenience macro to test when ASAN, UBSAN, TSAN or MSAN sanitizer |
138 | * are being used |
139 | */ |
140 | #ifndef FOLLY_SANITIZE |
141 | #if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD) || \ |
142 | defined(FOLLY_SANITIZE_MEMORY) |
143 | #define FOLLY_SANITIZE 1 |
144 | #endif |
145 | #endif |
146 | |
147 | #if FOLLY_SANITIZE |
148 | #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) \ |
149 | __attribute__((no_sanitize(__VA_ARGS__))) |
150 | #else |
151 | #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) |
152 | #endif // FOLLY_SANITIZE |
153 | |
154 | #define FOLLY_DISABLE_SANITIZERS \ |
155 | FOLLY_DISABLE_ADDRESS_SANITIZER FOLLY_DISABLE_THREAD_SANITIZER \ |
156 | FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("undefined") |
157 | |
158 | /** |
159 | * Macro for marking functions as having public visibility. |
160 | */ |
161 | #if defined(__GNUC__) |
162 | #define FOLLY_EXPORT __attribute__((__visibility__("default"))) |
163 | #else |
164 | #define FOLLY_EXPORT |
165 | #endif |
166 | |
167 | // noinline |
168 | #ifdef _MSC_VER |
169 | #define FOLLY_NOINLINE __declspec(noinline) |
170 | #elif defined(__GNUC__) |
171 | #define FOLLY_NOINLINE __attribute__((__noinline__)) |
172 | #else |
173 | #define FOLLY_NOINLINE |
174 | #endif |
175 | |
176 | // always inline |
177 | #ifdef _MSC_VER |
178 | #define FOLLY_ALWAYS_INLINE __forceinline |
179 | #elif defined(__GNUC__) |
180 | #define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__)) |
181 | #else |
182 | #define FOLLY_ALWAYS_INLINE inline |
183 | #endif |
184 | |
185 | // attribute hidden |
186 | #if defined(_MSC_VER) |
187 | #define FOLLY_ATTR_VISIBILITY_HIDDEN |
188 | #elif defined(__GNUC__) |
189 | #define FOLLY_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) |
190 | #else |
191 | #define FOLLY_ATTR_VISIBILITY_HIDDEN |
192 | #endif |
193 | |
194 | // An attribute for marking symbols as weak, if supported |
195 | #if FOLLY_HAVE_WEAK_SYMBOLS |
196 | #define FOLLY_ATTR_WEAK __attribute__((__weak__)) |
197 | #else |
198 | #define FOLLY_ATTR_WEAK |
199 | #endif |
200 | |
201 | // Microsoft ABI version (can be overridden manually if necessary) |
202 | #ifndef FOLLY_MICROSOFT_ABI_VER |
203 | #ifdef _MSC_VER |
204 | #define FOLLY_MICROSOFT_ABI_VER _MSC_VER |
205 | #endif |
206 | #endif |
207 | |
208 | // FOLLY_ERASE |
209 | // |
210 | // A conceptual attribute/syntax combo for erasing a function from the build |
211 | // artifacts and forcing all call-sites to inline the callee, at least as far |
212 | // as each compiler supports. |
213 | // |
214 | // Semantically includes the inline specifier. |
215 | #define FOLLY_ERASE FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN |
216 | |
217 | // FOLLY_ERASE_HACK_GCC |
218 | // |
219 | // Equivalent to FOLLY_ERASE, but without hiding under gcc. Useful when applied |
220 | // to a function which may sometimes be hidden separately, for example by being |
221 | // declared in an anonymous namespace, since in such cases with -Wattributes |
222 | // enabled, gcc would emit: 'visibility' attribute ignored. |
223 | // |
224 | // Semantically includes the inline specifier. |
225 | #if defined(__GNUC__) && !defined(__clang__) |
226 | #define FOLLY_ERASE_HACK_GCC FOLLY_ALWAYS_INLINE |
227 | #else |
228 | #define FOLLY_ERASE_HACK_GCC FOLLY_ERASE |
229 | #endif |
230 | |
231 | // FOLLY_ERASE_TRYCATCH |
232 | // |
233 | // Equivalent to FOLLY_ERASE, but for code which might contain explicit |
234 | // exception handling. Has the effect of FOLLY_ERASE, except under MSVC which |
235 | // warns about __forceinline when functions contain exception handling. |
236 | // |
237 | // Semantically includes the inline specifier. |
238 | #ifdef _MSC_VER |
239 | #define FOLLY_ERASE_TRYCATCH inline |
240 | #else |
241 | #define FOLLY_ERASE_TRYCATCH FOLLY_ERASE |
242 | #endif |
243 | |