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