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 | // MSCV 2017 __cplusplus definition by default does not track the C++ version. |
20 | // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ |
21 | #if !defined(_MSC_VER) || _MSC_VER >= 2000 |
22 | static_assert(__cplusplus >= 201402L, "__cplusplus >= 201402L" ); |
23 | #endif |
24 | |
25 | #if defined(__GNUC__) && !defined(__clang__) |
26 | static_assert(__GNUC__ >= 5, "__GNUC__ >= 5" ); |
27 | #endif |
28 | |
29 | #include <cstddef> |
30 | |
31 | #include <folly/CPortability.h> |
32 | #include <folly/portability/Config.h> |
33 | |
34 | // Unaligned loads and stores |
35 | namespace folly { |
36 | #if FOLLY_HAVE_UNALIGNED_ACCESS |
37 | constexpr bool kHasUnalignedAccess = true; |
38 | #else |
39 | constexpr bool kHasUnalignedAccess = false; |
40 | #endif |
41 | } // namespace folly |
42 | |
43 | // compiler specific attribute translation |
44 | // msvc should come first, so if clang is in msvc mode it gets the right defines |
45 | |
46 | // NOTE: this will only do checking in msvc with versions that support /analyze |
47 | #if _MSC_VER |
48 | #ifdef _USE_ATTRIBUTES_FOR_SAL |
49 | #undef _USE_ATTRIBUTES_FOR_SAL |
50 | #endif |
51 | /* nolint */ |
52 | #define _USE_ATTRIBUTES_FOR_SAL 1 |
53 | #include <sal.h> // @manual |
54 | #define FOLLY_PRINTF_FORMAT _Printf_format_string_ |
55 | #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/ |
56 | #else |
57 | #define FOLLY_PRINTF_FORMAT /**/ |
58 | #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \ |
59 | __attribute__((__format__(__printf__, format_param, dots_param))) |
60 | #endif |
61 | |
62 | // warn unused result |
63 | #if defined(__has_cpp_attribute) |
64 | #if __has_cpp_attribute(nodiscard) |
65 | #define FOLLY_NODISCARD [[nodiscard]] |
66 | #endif |
67 | #endif |
68 | #if !defined FOLLY_NODISCARD |
69 | #if defined(_MSC_VER) && (_MSC_VER >= 1700) |
70 | #define FOLLY_NODISCARD _Check_return_ |
71 | #elif defined(__GNUC__) |
72 | #define FOLLY_NODISCARD __attribute__((__warn_unused_result__)) |
73 | #else |
74 | #define FOLLY_NODISCARD |
75 | #endif |
76 | #endif |
77 | |
78 | // target |
79 | #ifdef _MSC_VER |
80 | #define FOLLY_TARGET_ATTRIBUTE(target) |
81 | #else |
82 | #define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) |
83 | #endif |
84 | |
85 | // detection for 64 bit |
86 | #if defined(__x86_64__) || defined(_M_X64) |
87 | #define FOLLY_X64 1 |
88 | #else |
89 | #define FOLLY_X64 0 |
90 | #endif |
91 | |
92 | #if defined(__arm__) |
93 | #define FOLLY_ARM 1 |
94 | #else |
95 | #define FOLLY_ARM 0 |
96 | #endif |
97 | |
98 | #if defined(__aarch64__) |
99 | #define FOLLY_AARCH64 1 |
100 | #else |
101 | #define FOLLY_AARCH64 0 |
102 | #endif |
103 | |
104 | #if defined(__powerpc64__) |
105 | #define FOLLY_PPC64 1 |
106 | #else |
107 | #define FOLLY_PPC64 0 |
108 | #endif |
109 | |
110 | namespace folly { |
111 | constexpr bool kIsArchArm = FOLLY_ARM == 1; |
112 | constexpr bool kIsArchAmd64 = FOLLY_X64 == 1; |
113 | constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1; |
114 | constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1; |
115 | } // namespace folly |
116 | |
117 | namespace folly { |
118 | |
119 | /** |
120 | * folly::kIsLibrarySanitizeAddress reports if folly was compiled with ASAN |
121 | * enabled. Note that for compilation units outside of folly that include |
122 | * folly/Portability.h, the value of kIsLibrarySanitizeAddress may be different |
123 | * from whether or not the current compilation unit is being compiled with ASAN. |
124 | */ |
125 | #if FOLLY_LIBRARY_SANITIZE_ADDRESS |
126 | constexpr bool kIsLibrarySanitizeAddress = true; |
127 | #else |
128 | constexpr bool kIsLibrarySanitizeAddress = false; |
129 | #endif |
130 | |
131 | #if FOLLY_SANITIZE_ADDRESS |
132 | constexpr bool kIsSanitizeAddress = true; |
133 | #else |
134 | constexpr bool kIsSanitizeAddress = false; |
135 | #endif |
136 | |
137 | #if FOLLY_SANITIZE_THREAD |
138 | constexpr bool kIsSanitizeThread = true; |
139 | #else |
140 | constexpr bool kIsSanitizeThread = false; |
141 | #endif |
142 | |
143 | #if FOLLY_SANITIZE |
144 | constexpr bool kIsSanitize = true; |
145 | #else |
146 | constexpr bool kIsSanitize = false; |
147 | #endif |
148 | } // namespace folly |
149 | |
150 | // packing is very ugly in msvc |
151 | #ifdef _MSC_VER |
152 | #define FOLLY_PACK_ATTR /**/ |
153 | #define FOLLY_PACK_PUSH __pragma(pack(push, 1)) |
154 | #define FOLLY_PACK_POP __pragma(pack(pop)) |
155 | #elif defined(__GNUC__) |
156 | #define FOLLY_PACK_ATTR __attribute__((__packed__)) |
157 | #define FOLLY_PACK_PUSH /**/ |
158 | #define FOLLY_PACK_POP /**/ |
159 | #else |
160 | #define FOLLY_PACK_ATTR /**/ |
161 | #define FOLLY_PACK_PUSH /**/ |
162 | #define FOLLY_PACK_POP /**/ |
163 | #endif |
164 | |
165 | // Generalize warning push/pop. |
166 | #if defined(_MSC_VER) |
167 | #define FOLLY_PUSH_WARNING __pragma(warning(push)) |
168 | #define FOLLY_POP_WARNING __pragma(warning(pop)) |
169 | // Disable the GCC warnings. |
170 | #define FOLLY_GNU_DISABLE_WARNING(warningName) |
171 | #define FOLLY_GCC_DISABLE_WARNING(warningName) |
172 | #define FOLLY_CLANG_DISABLE_WARNING(warningName) |
173 | #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) \ |
174 | __pragma(warning(disable : warningNumber)) |
175 | #elif defined(__GNUC__) |
176 | // Clang & GCC |
177 | #define FOLLY_PUSH_WARNING _Pragma("GCC diagnostic push") |
178 | #define FOLLY_POP_WARNING _Pragma("GCC diagnostic pop") |
179 | #define FOLLY_GNU_DISABLE_WARNING_INTERNAL2(warningName) #warningName |
180 | #define FOLLY_GNU_DISABLE_WARNING(warningName) \ |
181 | _Pragma( \ |
182 | FOLLY_GNU_DISABLE_WARNING_INTERNAL2(GCC diagnostic ignored warningName)) |
183 | #ifdef __clang__ |
184 | #define FOLLY_CLANG_DISABLE_WARNING(warningName) \ |
185 | FOLLY_GNU_DISABLE_WARNING(warningName) |
186 | #define FOLLY_GCC_DISABLE_WARNING(warningName) |
187 | #else |
188 | #define FOLLY_CLANG_DISABLE_WARNING(warningName) |
189 | #define FOLLY_GCC_DISABLE_WARNING(warningName) \ |
190 | FOLLY_GNU_DISABLE_WARNING(warningName) |
191 | #endif |
192 | #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) |
193 | #else |
194 | #define FOLLY_PUSH_WARNING |
195 | #define FOLLY_POP_WARNING |
196 | #define FOLLY_GNU_DISABLE_WARNING(warningName) |
197 | #define FOLLY_GCC_DISABLE_WARNING(warningName) |
198 | #define FOLLY_CLANG_DISABLE_WARNING(warningName) |
199 | #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) |
200 | #endif |
201 | |
202 | #ifdef FOLLY_HAVE_SHADOW_LOCAL_WARNINGS |
203 | #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \ |
204 | FOLLY_GNU_DISABLE_WARNING("-Wshadow-compatible-local") \ |
205 | FOLLY_GNU_DISABLE_WARNING("-Wshadow-local") \ |
206 | FOLLY_GNU_DISABLE_WARNING("-Wshadow") |
207 | #else |
208 | #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */ |
209 | #endif |
210 | |
211 | /* Platform specific TLS support |
212 | * gcc implements __thread |
213 | * msvc implements __declspec(thread) |
214 | * the semantics are the same |
215 | * (but remember __thread has different semantics when using emutls (ex. apple)) |
216 | */ |
217 | #if defined(_MSC_VER) |
218 | #define FOLLY_TLS __declspec(thread) |
219 | #elif defined(__GNUC__) |
220 | #define FOLLY_TLS __thread |
221 | #else |
222 | #error cannot define platform specific thread local storage |
223 | #endif |
224 | |
225 | // disable FOLLY_TLS on 32 bit Apple/iOS |
226 | #if defined(__APPLE__) && FOLLY_MOBILE |
227 | #if (__SIZEOF_POINTER__ == 4) |
228 | #undef FOLLY_TLS |
229 | #endif |
230 | #endif |
231 | |
232 | // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement |
233 | // the 'std' namespace; the latter uses inline namespaces. Wrap this decision |
234 | // up in a macro to make forward-declarations easier. |
235 | #if FOLLY_USE_LIBCPP |
236 | #include <__config> // @manual |
237 | #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD |
238 | #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD |
239 | #else |
240 | #define FOLLY_NAMESPACE_STD_BEGIN namespace std { |
241 | #define FOLLY_NAMESPACE_STD_END } |
242 | #endif |
243 | |
244 | // If the new c++ ABI is used, __cxx11 inline namespace needs to be added to |
245 | // some types, e.g. std::list. |
246 | #if _GLIBCXX_USE_CXX11_ABI |
247 | #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN \ |
248 | inline _GLIBCXX_BEGIN_NAMESPACE_CXX11 |
249 | #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END _GLIBCXX_END_NAMESPACE_CXX11 |
250 | #else |
251 | #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN |
252 | #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END |
253 | #endif |
254 | |
255 | // MSVC specific defines |
256 | // mainly for posix compat |
257 | #ifdef _MSC_VER |
258 | #include <folly/portability/SysTypes.h> |
259 | |
260 | // Hide a GCC specific thing that breaks MSVC if left alone. |
261 | #define __extension__ |
262 | |
263 | // We have compiler support for the newest of the new, but |
264 | // MSVC doesn't tell us that. |
265 | // |
266 | // Clang pretends to be MSVC on Windows, but it refuses to compile |
267 | // SSE4.2 intrinsics unless -march argument is specified. |
268 | // So cannot unconditionally define __SSE4_2__ in clang. |
269 | #ifndef __clang__ |
270 | #define __SSE4_2__ 1 |
271 | // compiler specific to compiler specific |
272 | // nolint |
273 | #define __PRETTY_FUNCTION__ __FUNCSIG__ |
274 | #endif |
275 | |
276 | #endif |
277 | |
278 | // Define FOLLY_HAS_EXCEPTIONS |
279 | #if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions) |
280 | #define FOLLY_HAS_EXCEPTIONS 1 |
281 | #elif __GNUC__ |
282 | #if __EXCEPTIONS |
283 | #define FOLLY_HAS_EXCEPTIONS 1 |
284 | #else // __EXCEPTIONS |
285 | #define FOLLY_HAS_EXCEPTIONS 0 |
286 | #endif // __EXCEPTIONS |
287 | #elif FOLLY_MICROSOFT_ABI_VER |
288 | #if _CPPUNWIND |
289 | #define FOLLY_HAS_EXCEPTIONS 1 |
290 | #else // _CPPUNWIND |
291 | #define FOLLY_HAS_EXCEPTIONS 0 |
292 | #endif // _CPPUNWIND |
293 | #else |
294 | #define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms |
295 | #endif |
296 | |
297 | // Debug |
298 | namespace folly { |
299 | #ifdef NDEBUG |
300 | constexpr auto kIsDebug = false; |
301 | #else |
302 | constexpr auto kIsDebug = true; |
303 | #endif |
304 | } // namespace folly |
305 | |
306 | // Exceptions |
307 | namespace folly { |
308 | #if FOLLY_HAS_EXCEPTIONS |
309 | constexpr auto kHasExceptions = true; |
310 | #else |
311 | constexpr auto kHasExceptions = false; |
312 | #endif |
313 | } // namespace folly |
314 | |
315 | // Endianness |
316 | namespace folly { |
317 | #ifdef _MSC_VER |
318 | // It's MSVC, so we just have to guess ... and allow an override |
319 | #ifdef FOLLY_ENDIAN_BE |
320 | constexpr auto kIsLittleEndian = false; |
321 | #else |
322 | constexpr auto kIsLittleEndian = true; |
323 | #endif |
324 | #else |
325 | constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__; |
326 | #endif |
327 | constexpr auto kIsBigEndian = !kIsLittleEndian; |
328 | } // namespace folly |
329 | |
330 | #ifndef FOLLY_SSE |
331 | #if defined(__SSE4_2__) |
332 | #define FOLLY_SSE 4 |
333 | #define FOLLY_SSE_MINOR 2 |
334 | #elif defined(__SSE4_1__) |
335 | #define FOLLY_SSE 4 |
336 | #define FOLLY_SSE_MINOR 1 |
337 | #elif defined(__SSE4__) |
338 | #define FOLLY_SSE 4 |
339 | #define FOLLY_SSE_MINOR 0 |
340 | #elif defined(__SSE3__) |
341 | #define FOLLY_SSE 3 |
342 | #define FOLLY_SSE_MINOR 0 |
343 | #elif defined(__SSE2__) |
344 | #define FOLLY_SSE 2 |
345 | #define FOLLY_SSE_MINOR 0 |
346 | #elif defined(__SSE__) |
347 | #define FOLLY_SSE 1 |
348 | #define FOLLY_SSE_MINOR 0 |
349 | #else |
350 | #define FOLLY_SSE 0 |
351 | #define FOLLY_SSE_MINOR 0 |
352 | #endif |
353 | #endif |
354 | |
355 | #define FOLLY_SSE_PREREQ(major, minor) \ |
356 | (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor) |
357 | |
358 | #ifndef FOLLY_NEON |
359 | #if defined(__ARM_NEON) || defined(__ARM_NEON__) |
360 | #define FOLLY_NEON 1 |
361 | #endif |
362 | #endif |
363 | |
364 | #if FOLLY_UNUSUAL_GFLAGS_NAMESPACE |
365 | namespace FOLLY_GFLAGS_NAMESPACE {} |
366 | namespace gflags { |
367 | using namespace FOLLY_GFLAGS_NAMESPACE; |
368 | } // namespace gflags |
369 | #endif |
370 | |
371 | // for TARGET_OS_IPHONE |
372 | #ifdef __APPLE__ |
373 | #include <TargetConditionals.h> // @manual |
374 | #endif |
375 | |
376 | // RTTI may not be enabled for this compilation unit. |
377 | #if defined(__GXX_RTTI) || defined(__cpp_rtti) || \ |
378 | (defined(_MSC_VER) && defined(_CPPRTTI)) |
379 | #define FOLLY_HAS_RTTI 1 |
380 | #else |
381 | #define FOLLY_HAS_RTTI 0 |
382 | #endif |
383 | |
384 | namespace folly { |
385 | constexpr bool const kHasRtti = FOLLY_HAS_RTTI; |
386 | } // namespace folly |
387 | |
388 | #if defined(__APPLE__) || defined(_MSC_VER) |
389 | #define FOLLY_STATIC_CTOR_PRIORITY_MAX |
390 | #else |
391 | // 101 is the highest priority allowed by the init_priority attribute. |
392 | // This priority is already used by JEMalloc and other memory allocators so |
393 | // we will take the next one. |
394 | #define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102))) |
395 | #endif |
396 | |
397 | namespace folly { |
398 | |
399 | #if __OBJC__ |
400 | constexpr auto kIsObjC = true; |
401 | #else |
402 | constexpr auto kIsObjC = false; |
403 | #endif |
404 | |
405 | #if FOLLY_MOBILE |
406 | constexpr auto kIsMobile = true; |
407 | #else |
408 | constexpr auto kIsMobile = false; |
409 | #endif |
410 | |
411 | #if defined(__linux__) && !FOLLY_MOBILE |
412 | constexpr auto kIsLinux = true; |
413 | #else |
414 | constexpr auto kIsLinux = false; |
415 | #endif |
416 | |
417 | #if defined(_WIN32) |
418 | constexpr auto kIsWindows = true; |
419 | #else |
420 | constexpr auto kIsWindows = false; |
421 | #endif |
422 | |
423 | #if __GLIBCXX__ |
424 | constexpr auto kIsGlibcxx = true; |
425 | #else |
426 | constexpr auto kIsGlibcxx = false; |
427 | #endif |
428 | |
429 | #if __GLIBCXX__ && _GLIBCXX_RELEASE // major version, 7+ |
430 | constexpr auto kGlibcxxVer = _GLIBCXX_RELEASE; |
431 | #else |
432 | constexpr auto kGlibcxxVer = 0; |
433 | #endif |
434 | |
435 | #if _LIBCPP_VERSION |
436 | constexpr auto kIsLibcpp = true; |
437 | #else |
438 | constexpr auto kIsLibcpp = false; |
439 | #endif |
440 | |
441 | #if FOLLY_USE_LIBSTDCPP |
442 | constexpr auto kIsLibstdcpp = true; |
443 | #else |
444 | constexpr auto kIsLibstdcpp = false; |
445 | #endif |
446 | |
447 | #if _MSC_VER |
448 | constexpr auto kMscVer = _MSC_VER; |
449 | #else |
450 | constexpr auto kMscVer = 0; |
451 | #endif |
452 | |
453 | #if __GNUC__ |
454 | constexpr auto kGnuc = __GNUC__; |
455 | #else |
456 | constexpr auto kGnuc = 0; |
457 | #endif |
458 | |
459 | #if __clang__ |
460 | constexpr auto kIsClang = true; |
461 | #else |
462 | constexpr auto kIsClang = false; |
463 | #endif |
464 | |
465 | #if FOLLY_MICROSOFT_ABI_VER |
466 | constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER; |
467 | #else |
468 | constexpr auto kMicrosoftAbiVer = 0; |
469 | #endif |
470 | |
471 | // cpplib is an implementation of the standard library, and is the one typically |
472 | // used with the msvc compiler |
473 | #if _CPPLIB_VER |
474 | constexpr auto kCpplibVer = _CPPLIB_VER; |
475 | #else |
476 | constexpr auto kCpplibVer = 0; |
477 | #endif |
478 | } // namespace folly |
479 | |
480 | // MSVC does not permit: |
481 | // |
482 | // extern int const num; |
483 | // constexpr int const num = 3; |
484 | // |
485 | // Instead: |
486 | // |
487 | // extern int const num; |
488 | // FOLLY_STORAGE_CONSTEXPR int const num = 3; |
489 | // |
490 | // True as of MSVC 2017. |
491 | #if _MSC_VER |
492 | #define FOLLY_STORAGE_CONSTEXPR |
493 | #else |
494 | #define FOLLY_STORAGE_CONSTEXPR constexpr |
495 | #endif |
496 | |
497 | #if __cplusplus >= 201703L |
498 | // folly::coro requires C++17 support |
499 | #if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>) |
500 | #define FOLLY_HAS_COROUTINES 1 |
501 | // This is mainly to workaround bugs triggered by LTO, when stack allocated |
502 | // variables in await_suspend end up on a coroutine frame. |
503 | #define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE |
504 | #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED |
505 | // NOTE: MSVC 2017 does not currently support the full Coroutines TS since it |
506 | // does not yet support symmetric-transfer. |
507 | #define FOLLY_HAS_COROUTINES 0 |
508 | #else |
509 | #define FOLLY_HAS_COROUTINES 0 |
510 | #endif |
511 | #else |
512 | #define FOLLY_HAS_COROUTINES 0 |
513 | #endif // __cplusplus >= 201703L |
514 | |
515 | // MSVC 2017.5 && C++17 |
516 | #if __cpp_noexcept_function_type >= 201510 || \ |
517 | (_MSC_FULL_VER >= 191225816 && _MSVC_LANG > 201402) |
518 | #define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1 |
519 | #endif |
520 | |
521 | #if __cpp_inline_variables >= 201606L |
522 | #define FOLLY_HAS_INLINE_VARIABLES 1 |
523 | #define FOLLY_INLINE_VARIABLE inline |
524 | #else |
525 | #define FOLLY_HAS_INLINE_VARIABLES 0 |
526 | #define FOLLY_INLINE_VARIABLE |
527 | #endif |
528 | |
529 | // feature test __cpp_lib_string_view is defined in <string>, which is |
530 | // too heavy to include here. MSVC __has_include support arrived later |
531 | // than string_view, so we need an alternate case for it. |
532 | #ifdef __has_include |
533 | #if __has_include(<string_view>) && __cplusplus >= 201703L |
534 | #define FOLLY_HAS_STRING_VIEW 1 |
535 | #else |
536 | #define FOLLY_HAS_STRING_VIEW 0 |
537 | #endif |
538 | #else // __has_include |
539 | #if _MSC_VER >= 1910 && (_MSVC_LANG > 201402 || __cplusplus > 201402) |
540 | #define FOLLY_HAS_STRING_VIEW 1 |
541 | #else |
542 | #define FOLLY_HAS_STRING_VIEW 0 |
543 | #endif |
544 | #endif // __has_include |
545 | |