xref: /aosp_15_r20/external/pytorch/c10/macros/Macros.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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