1 #ifndef C10_MACROS_MACROS_H_ 2 #define C10_MACROS_MACROS_H_ 3 #include <cassert> 4 5 /* Main entry for c10/macros. 6 * 7 * In your code, include c10/macros/Macros.h directly, instead of individual 8 * files in this folder. 9 */ 10 11 // For build systems that do not directly depend on CMake and directly build 12 // from the source directory (such as Buck), one may not have a cmake_macros.h 13 // file at all. In this case, the build system is responsible for providing 14 // correct macro definitions corresponding to the cmake_macros.h.in file. 15 // 16 // In such scenarios, one should define the macro 17 // C10_USING_CUSTOM_GENERATED_MACROS 18 // to inform this header that it does not need to include the cmake_macros.h 19 // file. 20 21 #ifndef C10_USING_CUSTOM_GENERATED_MACROS 22 #include <c10/macros/cmake_macros.h> 23 #endif // C10_USING_CUSTOM_GENERATED_MACROS 24 25 #include <c10/macros/Export.h> 26 27 #if defined(__clang__) 28 #define __ubsan_ignore_float_divide_by_zero__ \ 29 __attribute__((no_sanitize("float-divide-by-zero"))) 30 #define __ubsan_ignore_undefined__ __attribute__((no_sanitize("undefined"))) 31 #define __ubsan_ignore_signed_int_overflow__ \ 32 __attribute__((no_sanitize("signed-integer-overflow"))) 33 #define __ubsan_ignore_pointer_overflow__ \ 34 __attribute__((no_sanitize("pointer-overflow"))) 35 #define __ubsan_ignore_function__ __attribute__((no_sanitize("function"))) 36 #else 37 #define __ubsan_ignore_float_divide_by_zero__ 38 #define __ubsan_ignore_undefined__ 39 #define __ubsan_ignore_signed_int_overflow__ 40 #define __ubsan_ignore_pointer_overflow__ 41 #define __ubsan_ignore_function__ 42 #endif 43 44 // Detect address sanitizer as some stuff doesn't work with it 45 #undef C10_ASAN_ENABLED 46 47 // for clang 48 #if defined(__has_feature) 49 #if ((__has_feature(address_sanitizer))) 50 #define C10_ASAN_ENABLED 1 51 #endif 52 #endif 53 54 // for gcc 55 #if defined(__SANITIZE_ADDRESS__) 56 #if __SANITIZE_ADDRESS__ 57 #if !defined(C10_ASAN_ENABLED) 58 #define C10_ASAN_ENABLED 1 59 #endif 60 #endif 61 #endif 62 63 #if !defined(C10_ASAN_ENABLED) 64 #define C10_ASAN_ENABLED 0 65 #endif 66 67 // Detect undefined-behavior sanitizer (UBSAN) 68 #undef C10_UBSAN_ENABLED 69 70 // for clang or gcc >= 14 71 // NB: gcc 14 adds support for Clang's __has_feature 72 // https://gcc.gnu.org/gcc-14/changes.html 73 // gcc < 14 doesn't have a macro for UBSAN 74 // (e.g. __SANITIZE_UNDEFINED__ does not exist in gcc) 75 // https://github.com/google/sanitizers/issues/765 76 #if defined(__has_feature) 77 #if ((__has_feature(undefined_behavior_sanitizer))) 78 #define C10_UBSAN_ENABLED 1 79 #endif 80 #endif 81 82 #if !defined(C10_UBSAN_ENABLED) 83 #define C10_UBSAN_ENABLED 0 84 #endif 85 86 // Disable the copy and assignment operator for a class. Note that this will 87 // disable the usage of the class in std containers. 88 #define C10_DISABLE_COPY_AND_ASSIGN(classname) \ 89 classname(const classname&) = delete; \ 90 classname& operator=(const classname&) = delete 91 92 #define C10_CONCATENATE_IMPL(s1, s2) s1##s2 93 #define C10_CONCATENATE(s1, s2) C10_CONCATENATE_IMPL(s1, s2) 94 95 #define C10_MACRO_EXPAND(args) args 96 97 #define C10_STRINGIZE_IMPL(x) #x 98 #define C10_STRINGIZE(x) C10_STRINGIZE_IMPL(x) 99 100 /** 101 * C10_ANONYMOUS_VARIABLE(str) introduces a new identifier which starts with 102 * str and ends with a unique number. 103 */ 104 #ifdef __COUNTER__ 105 #define C10_UID __COUNTER__ 106 #define C10_ANONYMOUS_VARIABLE(str) C10_CONCATENATE(str, __COUNTER__) 107 #else 108 #define C10_UID __LINE__ 109 #define C10_ANONYMOUS_VARIABLE(str) C10_CONCATENATE(str, __LINE__) 110 #endif 111 112 #ifdef __has_cpp_attribute 113 #define C10_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) 114 #else 115 #define C10_HAS_CPP_ATTRIBUTE(x) (0) 116 #endif 117 118 /// C10_NODISCARD - Warn if a type or return value is discarded. 119 120 // Technically, we should check if __cplusplus > 201402L here, because 121 // [[nodiscard]] is only defined in C++17. However, some compilers 122 // we care about don't advertise being C++17 (e.g., clang), but 123 // support the attribute anyway. In fact, this is not just a good idea, 124 // it's the law: clang::warn_unused_result doesn't work on nvcc + clang 125 // and the best workaround for this case is to use [[nodiscard]] 126 // instead; see https://github.com/pytorch/pytorch/issues/13118 127 // 128 // Note to future editors: if you have noticed that a compiler is 129 // misbehaving (e.g., it advertises support, but the support doesn't 130 // actually work, or it is emitting warnings). Some compilers which 131 // are strict about the matter include MSVC, which will complain: 132 // 133 // error C2429: attribute 'nodiscard' requires compiler flag '/std:c++latest' 134 // 135 // Exhibits: 136 // - MSVC 19.14: https://godbolt.org/z/Dzd7gn (requires /std:c++latest) 137 // - Clang 8.0.0: https://godbolt.org/z/3PYL4Z (always advertises support) 138 // - gcc 8.3: https://godbolt.org/z/4tLMQS (always advertises support) 139 #if C10_HAS_CPP_ATTRIBUTE(nodiscard) 140 #define C10_NODISCARD [[nodiscard]] 141 // Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious 142 // error when __has_cpp_attribute is given a scoped attribute in C mode. 143 #elif __cplusplus && C10_HAS_CPP_ATTRIBUTE(clang::warn_unused_result) 144 // TODO: It's possible this is still triggering 145 // https://github.com/pytorch/pytorch/issues/13118 on Windows; if it is, better 146 // fix it. 147 #define C10_NODISCARD [[clang::warn_unused_result]] 148 #else 149 #define C10_NODISCARD 150 #endif 151 152 // suppress an unused variable. 153 #if defined(_MSC_VER) && !defined(__clang__) 154 #define C10_UNUSED __pragma(warning(suppress : 4100 4101)) 155 #else 156 #define C10_UNUSED __attribute__((__unused__)) 157 #endif //_MSC_VER 158 159 #if !defined(__has_attribute) 160 #define __has_attribute(x) 0 161 #endif 162 163 // Direct port of LLVM_ATTRIBUTE_USED. 164 #if __has_attribute(used) 165 #define C10_USED __attribute__((__used__)) 166 #else 167 #define C10_USED 168 #endif 169 170 #define C10_RESTRICT __restrict 171 172 // Simply define the namespace, in case a dependent library want to refer to 173 // the c10 namespace but not any nontrivial files. 174 namespace c10 {} 175 namespace c10::cuda {} 176 namespace c10::hip {} 177 namespace c10::xpu {} 178 179 // Since C10 is the core library for caffe2 (and aten), we will simply reroute 180 // all abstractions defined in c10 to be available in caffe2 as well. 181 // This is only for backwards compatibility. Please use the symbols from the 182 // c10 namespace where possible. 183 namespace caffe2 { 184 using namespace c10; 185 } 186 namespace at { 187 using namespace c10; 188 } 189 namespace at::cuda { 190 using namespace c10::cuda; 191 } // namespace at::cuda 192 193 // WARNING!!! THIS IS A GIANT HACK!!! 194 // This line means you cannot simultaneously include c10/hip 195 // and c10/cuda and then use them from the at::cuda namespace. 196 // This is true in practice, because HIPIFY works inplace on 197 // files in ATen/cuda, so it assumes that c10::hip is available 198 // from at::cuda. This namespace makes that happen. When 199 // HIPIFY is no longer out-of-place, we can switch the cuda 200 // here to hip and everyone is happy. 201 namespace at::cuda { 202 using namespace c10::hip; 203 } // namespace at::cuda 204 205 namespace at::xpu { 206 using namespace c10::xpu; 207 } // namespace at::xpu 208 209 // C10_LIKELY/C10_UNLIKELY 210 // 211 // These macros provide parentheses, so you can use these macros as: 212 // 213 // if C10_LIKELY(some_expr) { 214 // ... 215 // } 216 // 217 // NB: static_cast to boolean is mandatory in C++, because __builtin_expect 218 // takes a long argument, which means you may trigger the wrong conversion 219 // without it. 220 // 221 #if defined(__GNUC__) || defined(__ICL) || defined(__clang__) 222 #define C10_LIKELY(expr) (__builtin_expect(static_cast<bool>(expr), 1)) 223 #define C10_UNLIKELY(expr) (__builtin_expect(static_cast<bool>(expr), 0)) 224 #else 225 #define C10_LIKELY(expr) (expr) 226 #define C10_UNLIKELY(expr) (expr) 227 #endif 228 229 /// C10_NOINLINE - Functions whose declaration is annotated with this will not 230 /// be inlined. 231 #ifdef __GNUC__ 232 #define C10_NOINLINE __attribute__((noinline)) 233 #elif _MSC_VER 234 #define C10_NOINLINE __declspec(noinline) 235 #else 236 #define C10_NOINLINE 237 #endif 238 239 #if defined(_MSC_VER) 240 #define C10_ALWAYS_INLINE __forceinline 241 #elif __has_attribute(always_inline) || defined(__GNUC__) 242 #define C10_ALWAYS_INLINE __attribute__((__always_inline__)) inline 243 #else 244 #define C10_ALWAYS_INLINE inline 245 #endif 246 247 #if defined(_MSC_VER) 248 #define C10_ATTR_VISIBILITY_HIDDEN 249 #elif defined(__GNUC__) 250 #define C10_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) 251 #else 252 #define C10_ATTR_VISIBILITY_HIDDEN 253 #endif 254 255 #define C10_ERASE C10_ALWAYS_INLINE C10_ATTR_VISIBILITY_HIDDEN 256 257 #include <cstdint> 258 259 #ifdef __HIPCC__ 260 // Unlike CUDA, HIP requires a HIP header to be included for __host__ to work. 261 // We do this #include here so that C10_HOST_DEVICE and friends will Just Work. 262 // See https://github.com/ROCm-Developer-Tools/HIP/issues/441 263 #include <hip/hip_runtime.h> 264 #endif 265 266 #if defined(__CUDACC__) || defined(__HIPCC__) 267 // Designates functions callable from the host (CPU) and the device (GPU) 268 #define C10_HOST_DEVICE __host__ __device__ 269 #define C10_DEVICE __device__ 270 #define C10_HOST __host__ 271 // constants from 272 // (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications) 273 // The maximum number of threads per multiprocessor is 1024 for Turing 274 // architecture (7.5), 1536 for Geforce Ampere (8.6)/Jetson Orin (8.7), and 275 // 2048 for all other architectures. You'll get warnings if you exceed these 276 // constants. Hence, the following macros adjust the input values from the user 277 // to resolve potential warnings. 278 #if __CUDA_ARCH__ == 750 279 constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 1024; 280 #elif __CUDA_ARCH__ == 860 || __CUDA_ARCH__ == 870 || __CUDA_ARCH__ == 890 281 constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 1536; 282 #else 283 constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 2048; 284 #endif 285 // CUDA_MAX_THREADS_PER_BLOCK is same for all architectures currently 286 constexpr uint32_t CUDA_MAX_THREADS_PER_BLOCK = 1024; 287 // CUDA_THREADS_PER_BLOCK_FALLBACK is the "canonical fallback" choice of block 288 // size. 256 is a good number for this fallback and should give good occupancy 289 // and versatility across all architectures. 290 constexpr uint32_t CUDA_THREADS_PER_BLOCK_FALLBACK = 256; 291 // NOTE: if you are thinking of constexpr-ify the inputs to launch bounds, it 292 // turns out that although __launch_bounds__ can take constexpr, it 293 // can't take a constexpr that has anything to do with templates. 294 // Currently we use launch_bounds that depend on template arguments in 295 // Loops.cuh, Reduce.cuh and LossCTC.cuh. Hence, C10_MAX_THREADS_PER_BLOCK 296 // and C10_MIN_BLOCKS_PER_SM are kept as macros. 297 // Suppose you were planning to write __launch_bounds__(a, b), based on your 298 // performance tuning on a modern GPU. Instead, you should write 299 // __launch_bounds__(C10_MAX_THREADS_PER_BLOCK(a), C10_MIN_BLOCKS_PER_SM(a, b)), 300 // which will also properly respect limits on old architectures. 301 #define C10_MAX_THREADS_PER_BLOCK(val) \ 302 (((val) <= CUDA_MAX_THREADS_PER_BLOCK) ? (val) \ 303 : CUDA_THREADS_PER_BLOCK_FALLBACK) 304 #define C10_MIN_BLOCKS_PER_SM(threads_per_block, blocks_per_sm) \ 305 ((((threads_per_block) * (blocks_per_sm) <= CUDA_MAX_THREADS_PER_SM) \ 306 ? (blocks_per_sm) \ 307 : ((CUDA_MAX_THREADS_PER_SM + (threads_per_block)-1) / \ 308 (threads_per_block)))) 309 // C10_LAUNCH_BOUNDS is analogous to __launch_bounds__ 310 #define C10_LAUNCH_BOUNDS_0 \ 311 __launch_bounds__( \ 312 256, 4) // default launch bounds that should give good occupancy and 313 // versatility across all architectures. 314 #define C10_LAUNCH_BOUNDS_1(max_threads_per_block) \ 315 __launch_bounds__((C10_MAX_THREADS_PER_BLOCK((max_threads_per_block)))) 316 #define C10_LAUNCH_BOUNDS_2(max_threads_per_block, min_blocks_per_sm) \ 317 __launch_bounds__( \ 318 (C10_MAX_THREADS_PER_BLOCK((max_threads_per_block))), \ 319 (C10_MIN_BLOCKS_PER_SM((max_threads_per_block), (min_blocks_per_sm)))) 320 #else 321 #define C10_HOST_DEVICE 322 #define C10_HOST 323 #define C10_DEVICE 324 #endif 325 326 #if defined(USE_ROCM) 327 #define C10_HIP_HOST_DEVICE __host__ __device__ 328 #else 329 #define C10_HIP_HOST_DEVICE 330 #endif 331 332 #if defined(USE_ROCM) 333 #define C10_WARP_SIZE warpSize // = 64 or 32 (Defined in hip_runtime.h) 334 #else 335 #define C10_WARP_SIZE 32 336 #endif 337 338 #if defined(_MSC_VER) && _MSC_VER <= 1900 339 #define __func__ __FUNCTION__ 340 #endif 341 342 // CUDA_KERNEL_ASSERT checks the assertion 343 // even when NDEBUG is defined. This is useful for important assertions in CUDA 344 // code that would otherwise be suppressed when building Release. 345 #if defined(__ANDROID__) || defined(__APPLE__) || defined(__FreeBSD__) 346 // Those platforms do not support assert() 347 #define CUDA_KERNEL_ASSERT(cond) 348 #define CUDA_KERNEL_ASSERT_MSG(cond, msg) 349 #define SYCL_KERNEL_ASSERT(cond) 350 #elif defined(_MSC_VER) 351 #if defined(NDEBUG) 352 extern "C" { 353 C10_IMPORT 354 #if defined(__SYCL_DEVICE_ONLY__) 355 extern SYCL_EXTERNAL void _wassert( 356 const wchar_t* wexpr, 357 const wchar_t* wfile, 358 unsigned line); 359 #else 360 #if defined(__CUDA_ARCH__) 361 __host__ __device__ 362 #endif // __CUDA_ARCH__ 363 void 364 _wassert(wchar_t const* _Message, wchar_t const* _File, unsigned _Line); 365 #endif // __SYCL_DEVICE_ONLY__ 366 } 367 #endif // NDEBUG 368 #define CUDA_KERNEL_ASSERT(cond) \ 369 if (C10_UNLIKELY(!(cond))) { \ 370 (void)(_wassert( \ 371 _CRT_WIDE(#cond), \ 372 _CRT_WIDE(__FILE__), \ 373 static_cast<unsigned>(__LINE__)), \ 374 0); \ 375 } 376 // TODO: This doesn't assert the message because I (chilli) couldn't figure out 377 // a nice way to convert a char* to a wchar_t* 378 #define CUDA_KERNEL_ASSERT_MSG(cond, msg) \ 379 if (C10_UNLIKELY(!(cond))) { \ 380 (void)(_wassert( \ 381 _CRT_WIDE(#cond), \ 382 _CRT_WIDE(__FILE__), \ 383 static_cast<unsigned>(__LINE__)), \ 384 0); \ 385 } 386 #define SYCL_KERNEL_ASSERT(cond) \ 387 if (C10_UNLIKELY(!(cond))) { \ 388 (void)(_wassert( \ 389 _CRT_WIDE(#cond), \ 390 _CRT_WIDE(__FILE__), \ 391 static_cast<unsigned>(__LINE__)), \ 392 0); \ 393 } 394 #else // __APPLE__, _MSC_VER 395 #if defined(NDEBUG) 396 extern "C" { 397 #if defined(__SYCL_DEVICE_ONLY__) 398 extern SYCL_EXTERNAL void __assert_fail( 399 const char* expr, 400 const char* file, 401 unsigned int line, 402 const char* func); 403 #else // __SYCL_DEVICE_ONLY__ 404 #if (defined(__CUDA_ARCH__) && !(defined(__clang__) && defined(__CUDA__))) 405 // CUDA supports __assert_fail function which are common for both device 406 // and host side code. 407 __host__ __device__ 408 #endif 409 410 // This forward declaration matching the declaration of __assert_fail 411 // exactly how it is in glibc in case parts of the program are compiled with 412 // different NDEBUG settings. Otherwise we might get 'ambiguous declaration' 413 // error. Note: On ROCm - this declaration serves for host side compilation. 414 void 415 __assert_fail( 416 const char* assertion, 417 const char* file, 418 unsigned int line, 419 const char* function) noexcept __attribute__((__noreturn__)); 420 421 #endif // __SYCL_DEVICE_ONLY__ 422 } 423 #endif // NDEBUG 424 // ROCm disable kernel assert by default 425 #if !defined(C10_USE_ROCM_KERNEL_ASSERT) and defined(USE_ROCM) 426 #define CUDA_KERNEL_ASSERT(cond) 427 #define CUDA_KERNEL_ASSERT_MSG(cond, msg) 428 #define SYCL_KERNEL_ASSERT(cond) 429 #else 430 #define CUDA_KERNEL_ASSERT(cond) \ 431 if (C10_UNLIKELY(!(cond))) { \ 432 __assert_fail( \ 433 #cond, __FILE__, static_cast<unsigned int>(__LINE__), __func__); \ 434 } 435 #define CUDA_KERNEL_ASSERT_MSG(cond, msg) \ 436 if (C10_UNLIKELY(!(cond))) { \ 437 __assert_fail( \ 438 msg, __FILE__, static_cast<unsigned int>(__LINE__), __func__); \ 439 } 440 #define SYCL_KERNEL_ASSERT(cond) \ 441 if (C10_UNLIKELY(!(cond))) { \ 442 __assert_fail( \ 443 #cond, __FILE__, static_cast<unsigned int>(__LINE__), __func__); \ 444 } 445 #endif // C10_USE_ROCM_KERNEL_ASSERT and USE_ROCM 446 #endif // __APPLE__ 447 448 #ifdef __APPLE__ 449 #include <TargetConditionals.h> 450 #endif 451 452 #if defined(__ANDROID__) 453 #define C10_ANDROID 1 454 #define C10_MOBILE 1 455 #elif ( \ 456 defined(__APPLE__) && \ 457 (TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR || TARGET_OS_IPHONE)) 458 #define C10_IOS 1 459 #define C10_MOBILE 1 460 #endif // ANDROID / IOS 461 462 #if defined(C10_MOBILE) && C10_MOBILE 463 #define C10_ALWAYS_INLINE_UNLESS_MOBILE inline 464 #else 465 #define C10_ALWAYS_INLINE_UNLESS_MOBILE C10_ALWAYS_INLINE 466 #endif 467 468 #if defined(__CUDA_ARCH__) 469 #if defined(_MSC_VER) && defined(__CUDACC__) 470 #define CONSTEXPR_EXCEPT_WIN_CUDA const 471 #define C10_HOST_CONSTEXPR_EXCEPT_WIN_CUDA __host__ 472 473 // Note [static constexpr char* members for windows NVCC] 474 // The Windows NVCC compiler doesn't handle static constexpr class members, 475 // although it's fixed in a later version. 476 // (see 477 // https://developercommunity.visualstudio.com/t/intellisense-error-c11-static-constexpr-member-ini/245425) 478 // 479 // If we want to ensure that our field is static under all builds, then we need 480 // to work around it specifically for windows NVCC by making it (a) const, (b) 481 // defined outside of the class definition We need to define it outside of the 482 // class definition because of the C++ standard; char* is not an integral type 483 // (see 484 // https://stackoverflow.com/questions/24278473/intellisense-a-member-of-type-const-char-const-cannot-have-an-in-class-in) 485 // 486 // So instead of this: 487 // struct Foo { 488 // static constexpr const char* name = "foo"; 489 // } 490 // In Windows NVCC, we end up with this: 491 // struct Foo { 492 // static const char* name; 493 // } 494 // const char* Foo::name = "foo"; 495 // 496 // This gives us a small perf hit for any code that wants to access these field 497 // members, but right now it isn't used in any perf-critical code paths. 498 #define STATIC_CONSTEXPR_STR_INL_EXCEPT_WIN_CUDA(field, val) \ 499 static const char* field; 500 #define STATIC_CONST_STR_OUT_OF_LINE_FOR_WIN_CUDA(cls, field, val) \ 501 const char* cls::field = val; 502 #else 503 #define CONSTEXPR_EXCEPT_WIN_CUDA constexpr 504 #define C10_HOST_CONSTEXPR_EXCEPT_WIN_CUDA __host__ 505 506 #define STATIC_CONSTEXPR_STR_INL_EXCEPT_WIN_CUDA(field, val) \ 507 static constexpr const char* field = val; 508 #define STATIC_CONST_STR_OUT_OF_LINE_FOR_WIN_CUDA(cls, field, val) 509 #endif 510 #else 511 #if defined(_MSC_VER) && defined(__CUDACC__) 512 #define CONSTEXPR_EXCEPT_WIN_CUDA const 513 #define C10_HOST_CONSTEXPR_EXCEPT_WIN_CUDA 514 515 #define STATIC_CONSTEXPR_STR_INL_EXCEPT_WIN_CUDA(field, val) \ 516 static const char* field; 517 #define STATIC_CONST_STR_OUT_OF_LINE_FOR_WIN_CUDA(cls, field, val) \ 518 const char* cls::field = val; 519 #else 520 #define CONSTEXPR_EXCEPT_WIN_CUDA constexpr 521 #define C10_HOST_CONSTEXPR_EXCEPT_WIN_CUDA constexpr 522 523 #define STATIC_CONSTEXPR_STR_INL_EXCEPT_WIN_CUDA(field, val) \ 524 static constexpr const char* field = val; 525 #define STATIC_CONST_STR_OUT_OF_LINE_FOR_WIN_CUDA(cls, field, val) 526 #endif 527 #endif 528 529 #ifndef HAS_DEMANGLE 530 #if defined(__ANDROID__) || defined(_WIN32) || defined(__EMSCRIPTEN__) 531 #define HAS_DEMANGLE 0 532 #elif defined(__APPLE__) && \ 533 (TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR || TARGET_OS_IPHONE) 534 #define HAS_DEMANGLE 0 535 #else 536 #define HAS_DEMANGLE 1 537 #endif 538 #endif // HAS_DEMANGLE 539 540 #define _C10_PRAGMA__(string) _Pragma(#string) 541 #define _C10_PRAGMA_(string) _C10_PRAGMA__(string) 542 543 #ifdef __clang__ 544 #define C10_CLANG_DIAGNOSTIC_PUSH() _Pragma("clang diagnostic push") 545 #define C10_CLANG_DIAGNOSTIC_POP() _Pragma("clang diagnostic pop") 546 #define C10_CLANG_DIAGNOSTIC_IGNORE(flag) \ 547 _C10_PRAGMA_(clang diagnostic ignored flag) 548 #define C10_CLANG_HAS_WARNING(flag) __has_warning(flag) 549 #else 550 #define C10_CLANG_DIAGNOSTIC_PUSH() 551 #define C10_CLANG_DIAGNOSTIC_POP() 552 #define C10_CLANG_DIAGNOSTIC_IGNORE(flag) 553 #define C10_CLANG_HAS_WARNING(flag) 0 554 #endif 555 556 #ifdef __clang__ 557 558 #define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) \ 559 _C10_PRAGMA_(clang diagnostic push) \ 560 _C10_PRAGMA_(clang diagnostic ignored "-Wunknown-warning-option") \ 561 _C10_PRAGMA_(clang diagnostic ignored warning) 562 563 #define C10_DIAGNOSTIC_POP() _C10_PRAGMA_(clang diagnostic pop) 564 565 #elif __GNUC__ 566 567 #define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) \ 568 _C10_PRAGMA_(GCC diagnostic push) \ 569 _C10_PRAGMA_(GCC diagnostic ignored "-Wpragmas") \ 570 _C10_PRAGMA_(GCC diagnostic ignored warning) 571 572 #define C10_DIAGNOSTIC_POP() _C10_PRAGMA_(GCC diagnostic pop) 573 574 #else 575 576 #define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) 577 #define C10_DIAGNOSTIC_POP() 578 579 #endif 580 581 #endif // C10_MACROS_MACROS_H_ 582