24 #ifndef P99_COMPILER_H
25 #define P99_COMPILER_H
101 #define P00_PREFIX0(N) P00_PREFIX0_(N)
102 #define P00_PREFIX0_(N) 0 ## N
103 #define P00_STRINGIFY(...) #__VA_ARGS__
104 #define P00_VERSION_NO(A, B, C) (((A)*10000UL)+(B)*100UL+(C))
109 #define P99_STRINGIFY(...) P00_STRINGIFY(__VA_ARGS__)
112 #if P99_COMPILER & P99_COMPILER_APPLE
113 # undef P00_COMPILER_PRAGMA_APPLE
114 # define P00_COMPILER_PRAGMA_APPLE(STR) _Pragma(STR)
115 # undef P99_COMPILER_VERSION
116 # define P99_COMPILER_VERSION \
118 __apple_build_version__ \
119 "pretending clang version " \
122 P99_STRINGIFY(__GNUC__) "." \
123 P99_STRINGIFY(__GNUC_MINOR__) "." \
124 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
125 # define P99_VERSION_NO __apple_build_version__
127 #elif P99_COMPILER & P99_COMPILER_CLANG
128 # undef P00_COMPILER_PRAGMA_CLANG
129 # define P00_COMPILER_PRAGMA_CLANG(STR) _Pragma(STR)
130 # undef P99_COMPILER_VERSION
131 # define P99_COMPILER_VERSION \
135 P99_STRINGIFY(__GNUC__) "." \
136 P99_STRINGIFY(__GNUC_MINOR__) "." \
137 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
138 # define P99_VERSION_NO P00_VERSION_NO(__clang_major__, __clang_minor__, __clang_patchlevel__)
140 #elif P99_COMPILER & P99_COMPILER_INTEL
141 # undef P99_COMPILER_VERSION
142 # define P99_COMPILER_VERSION \
143 "intel " P99_STRINGIFY(__INTEL_COMPILER) \
145 P99_STRINGIFY(__GNUC__) "." \
146 P99_STRINGIFY(__GNUC_MINOR__) "." \
147 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
148 # define P99_VERSION_NO P00_VERSION_NO(__INTEL_COMPILER, 0, 0)
150 #elif P99_COMPILER & P99_COMPILER_PCC
151 # undef P99_COMPILER_VERSION
152 # define P99_COMPILER_VERSION \
154 P99_STRINGIFY(__PCC__) \
155 "." P99_STRINGIFY(__PCC_MINOR__) \
156 "." P99_STRINGIFY(__PCC_MINORMINOR__) \
158 P99_STRINGIFY(__GNUC__) "." \
159 P99_STRINGIFY(__GNUC_MINOR__) "." \
160 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
161 # define P99_VERSION_NO P00_VERSION_NO(__PCC__, __PCC_MINOR__, __PCC_MINORMINOR__)
163 #elif P99_COMPILER & P99_COMPILER_TINYC
164 # undef P99_COMPILER_VERSION
165 # define P99_COMPILER_VERSION \
167 P99_STRINGIFY(__TINYC__)
168 # define P99_VERSION_NO P00_VERSION_NO(__TINYC__, 0, 0)
170 #elif P99_COMPILER & P99_COMPILER_OPEN64
171 # undef P99_COMPILER_VERSION
172 # define P99_COMPILER_VERSION \
173 "open64 " __OPEN64__ \
175 P99_STRINGIFY(__GNUC__) "." \
176 P99_STRINGIFY(__GNUC_MINOR__) "." \
177 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
178 # define P99_VERSION_NO P00_VERSION_NO(__TINYC__, 0, 0)
180 #elif P99_COMPILER & P99_COMPILER_GNU
181 # undef P99_COMPILER_VERSION
182 # define P99_COMPILER_VERSION \
184 P99_STRINGIFY(__GNUC__) "." \
185 P99_STRINGIFY(__GNUC_MINOR__) "." \
186 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
187 # define P99_VERSION_NO P00_VERSION_NO(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
191 #if P99_COMPILER & P99_COMPILER_INTEL
192 # if (__ICC < 1400) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 2)
193 # undef __GNUC_MINOR__
194 # define __GNUC_MINOR__ 2
195 # undef __GNUC_PATCHLEVEL__
196 # define __GNUC_PATCHLEVEL__ 0
202 # define p99_extension __extension__
203 # define P99_GCC_VERSION P00_VERSION_NO(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
206 #ifndef p99_extension
210 # define p99_extension
225 # define P00_VA_ARGS__(...) __VA_ARGS__
226 enum { p00_trailing_comma_in_enum__ = -1, };
228 signed p00_trailing_comma_in_initializer__(
void) {
229 signed a[] = { p00_trailing_comma_in_enum__, };
233 # if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
240 # error "The P99 preprocessor files need a C99 compliant compiler"
242 # if (!P99_TOK_EQ(1, 1) || P99_TOK_EQ(1, 0))
248 # error "The preprocessor is not P99 compatible"
253 #if !(P99_COMPILER & (P99_COMPILER_CLANG | P99_COMPILER_APPLE))
254 # ifndef __has_builtin
255 # define __has_builtin(X) p00_has_builtin_ ## X // Compatibility with non-clang compilers.
257 # ifndef __has_feature
258 # define __has_feature(X) p00_has_feature_ ## X // Compatibility with non-clang compilers.
260 # ifndef __has_extension
261 # define __has_extension __has_feature // Compatibility with non-clang compilers.
263 # ifndef __has_attribute
264 # define __has_attribute(X) p00_has_attribute_ ## X // Compatibility with non-clang compilers.
268 #ifndef p99_has_builtin
269 # define p99_has_builtin(X) (__has_builtin(X) || p00_has_builtin_ ## X) // Compatibility with non-clang compilers.
270 # define p99_has_feature(X) (__has_feature(X) || p00_has_feature_ ## X) // Compatibility with non-clang compilers.
271 # define p99_has_extension(X) (__has_extension(X) || p00_has_extension_ ## X) // Compatibility with non-clang compilers.
272 # define p99_has_attribute(X) (__has_attribute(X) || p00_has_attribute_ ## X) // Compatibility with non-clang compilers.
275 #if P99_COMPILER & P99_COMPILER_OPEN64
276 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
277 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
278 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
279 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
280 # define __GNUC_NO_TLS__ 1
284 # define p00_has_feature_openmp 1
288 # define p00_has_attribute_always_inline 1
289 # define p00_has_attribute_weak 1
290 # define p00_has_attribute_weakref 1
291 # define p00_has_attribute_constructor 1
292 # define p00_has_attribute_destructor 1
293 # define p00_has_attribute_vector_size 1
294 # define p00_has_attribute_warn_unused_result 1
295 # define p00_has_extension_attribute_const 1
296 # define p00_has_attribute_pure 1
297 # if defined(__GNUC_GNU_INLINE__) || (P99_GCC_VERSION < 40300UL)
298 # define p00_has_attribute_gnu_inline 1
300 # define p00_has_attribute_aligned 1
301 # define p00_has_attribute_noreturn 1
302 # define p00_has_attribute___noreturn__ 1
303 # define p00_has_attribute_deprecated 1
304 # define p00_has_attribute_unused 1
305 # ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
306 # define p00_has_builtin___sync_val_compare_and_swap 1
307 # define p00_has_builtin___sync_lock_test_and_set 1
308 # define p00_has_builtin___sync_lock_release 1
309 # define p00_has_builtin___sync_synchronize 1
310 # define p00_has_builtin___sync_fetch_and_add 1
311 # define p00_has_builtin___sync_fetch_and_sub 1
312 # define p00_has_builtin___sync_fetch_and_or 1
313 # define p00_has_builtin___sync_fetch_and_and 1
314 # define p00_has_builtin___sync_fetch_and_xor 1
316 # define P99_TYPEOF(X) __typeof__(X)
317 # if P99_GCC_VERSION >= 30000UL
318 # define p00_has_builtin___builtin_expect 1
323 # if P99_GCC_VERSION >= 40300UL
324 # define p00_has_attribute_error 1
326 # if P99_GCC_VERSION >= 40600UL
327 # define p00_has_feature_c_static_assert 1
328 # define p00_has_attribute_externally_visible 1
330 # if defined(__GNUC_STDC_INLINE__) || P99_GCC_VERSION >= 40300UL
331 # define p00_has_feature_c_inline 1
333 # define p00_has_feature_gnu_thread_local 1
334 # define p00_has_feature_gnu_alignof 1
335 # define p00_has_feature_statement_expression 1
336 # define p00_has_feature_tgmath_h 1
337 # if (P99_GCC_VERSION >= 40700UL) && (P99_GCC_VERSION < 40900UL)
338 # define p00_has_feature_stdnoreturn_h 1
339 # define p00_has_feature_stdalign_h 1
340 # if __STDC_VERSION__ > 201100L
341 # define p00_has_feature_c_max_align_t 1
342 # define __STDC_NO_ATOMICS__ 1
343 # define p00_has_feature_c_generic_selections 0
346 # if (P99_GCC_VERSION >= 40900UL) && (P99_GCC_VERSION < 41000UL)
347 # define p00_has_feature_stdnoreturn_h 1
348 # define p00_has_feature_stdalign_h 1
349 # if __STDC_VERSION__ > 201100L
350 # define p00_has_feature_c_max_align_t 1
351 # define p00_has_feature_c_generic_selections 1
356 #if P99_COMPILER & P99_COMPILER_ARMCC
357 # define p00_has_attribute_always_inline 1
358 # define p00_has_attribute_weak 1
359 # define p00_has_attribute_weakref 1
360 # define p00_has_attribute_deprecated 1
361 # define p00_has_attribute_aligned 1
362 # define p00_has_attribute_noreturn 1
363 # define p00_has_attribute___noreturn__ 1
366 #if p99_has_builtin(__sync_val_compare_and_swap)
367 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
368 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
370 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
371 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
373 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
374 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
375 # if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) && (UINTPTR_MAX >= UINT64_MAX)
376 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
386 #if __STDC_VERSION__ > 201100L
387 # ifndef p00_has_feature_stdnoreturn_h
388 # define p00_has_feature_stdnoreturn_h 1
390 # ifndef p00_has_feature_c_max_align_t
391 # define p00_has_feature_c_max_align_t 1
393 # ifndef p00_has_feature_c_generic_selections
394 # define p00_has_feature_c_generic_selections 1
398 #if P99_COMPILER & (P99_COMPILER_IBM | P99_COMPILER_SUN)
399 # define p00_has_feature_gnu_thread 1
400 #elif P99_COMPILER & (P99_COMPILER_MICROSOFT | P99_COMPILER_BORLAND)
401 # define p00_has_feature_declspec_thread 1
404 #if P99_COMPILER & P99_COMPILER_INTEL
405 # define p99_inline __attribute__((__weak__,__always_inline__))
406 # if __INTEL_COMPILER < 1310
407 # if defined(__GNUC__) && defined(p00_has_feature_tgmath_h)
408 # undef p00_has_feature_tgmath_h
416 #elif P99_COMPILER & P99_COMPILER_PCC
419 #elif P99_COMPILER & P99_COMPILER_APPLE
422 # if p99_has_attribute(always_inline)
423 # define p99_inline __attribute__((__always_inline__)) inline
426 # define P99_FIXED_REGISTER(REG)
428 # define __STDC_NO_ATOMICS__ 1
430 #elif P99_COMPILER & P99_COMPILER_CLANG
431 # if p99_has_attribute(always_inline)
432 # define p99_inline __attribute__((__always_inline__)) inline
435 # define P99_FIXED_REGISTER(REG)
438 # if P99_VERSION_NO < 100000UL
439 # define __STDC_NO_ATOMICS__ 1
441 # if P99_VERSION_NO > 30200UL
442 # define p00_has_feature_stdnoreturn_h 1
449 #elif P99_COMPILER & (P99_COMPILER_GNU | P99_COMPILER_OPEN64)
455 # if !p99_has_feature(c_inline)
459 # if p99_has_attribute(gnu_inline)
460 # define inline __attribute__((__gnu_inline__,__weak__)) __inline__
461 # define p99_inline __attribute__((__always_inline__,__gnu_inline__,__weak__)) __inline__
463 # define inline __attribute__((__weak__)) __inline__
464 # define p99_inline __attribute__((__always_inline__,__weak__)) __inline__
466 # define static_inline static __inline__
467 # if p99_has_attribute(externally_visible)
468 # define p00_instantiate __attribute__((__externally_visible__))
470 # define p00_instantiate
473 # define inline __inline__
474 # if p99_has_attribute(externally_visible)
475 # define p00_instantiate __attribute__((__externally_visible__)) extern __inline__
477 # define p00_instantiate extern __inline__
479 # define p99_inline __attribute__((__always_inline__)) __inline__
483 # if !defined(static_inline) || defined(P00_DOXYGEN)
484 # define static_inline static inline
486 # if !defined(p99_inline) || defined(P00_DOXYGEN)
496 # define p99_inline static inline
499 #ifdef P00_FORCE_NOINLINE
505 # ifndef p00_instantiate
514 # if p99_has_attribute(externally_visible)
515 # define p00_instantiate __attribute__((__externally_visible__)) extern __inline__
517 # define p00_instantiate extern __inline__
521 #if p99_has_attribute(weak)
522 # define P00_WEAK1(ID) __attribute__((__weak__))
523 #elif P99_COMPILER & P99_COMPILER_MICROSOFT
524 # define P00_WEAK1(ID) __declspec(selectany)
526 # define P00_WEAK1(ID) _Pragma(P99_STRINGIFY(weak ID))
529 #if p99_has_attribute(weakref)
530 # define P00_WEAK2(ID, ...) __attribute__((__weakref__(#__VA_ARGS__)))
532 # define P00_WEAK2(ID, ...) _Pragma(P99_STRINGIFY(weak ID=__VA_ARGS__))
561 # define P99_WEAK(...) P99_IF_LT(P99_NARG(__VA_ARGS__), 2)(P00_WEAK1(__VA_ARGS__))(P00_WEAK2(__VA_ARGS__))
563 #ifndef P99_TENTATIVE_CAUTION
564 # define P00_TENTATIVE_DEC(NAME) static
565 # define P00_TENTATIVE_DEF(NAME) static
567 # define P00_TENTATIVE_DEC(NAME) P99_WEAK(NAME)
568 # define P00_TENTATIVE_DEF(NAME)
587 # define P99_TENTATIVE_DEC(T, NAME) \
588 P00_TENTATIVE_DEC(NAME) T NAME
590 # define P99_TENTATIVE_DEF(T, NAME) \
591 P00_TENTATIVE_DEF(NAME) T NAME
597 #if p99_has_attribute(warn_unused_result) && defined(P99_WARN_UNUSED_RESULT)
598 # undef P99_WARN_UNUSED_RESULT
599 # define P99_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
601 # undef P99_WARN_UNUSED_RESULT
602 # define P99_WARN_UNUSED_RESULT
609 #if p99_has_attribute(pure)
610 # define P99_PURE_FUNCTION __attribute__((__pure__))
612 # define P99_PURE_FUNCTION
619 #if p99_has_extension(attribute_const)
620 # define P99_CONST_FUNCTION __attribute__((__const__))
622 # define P99_CONST_FUNCTION
625 #if p99_has_feature(setjmp_inline)
626 # define P99_SETJMP_INLINE(NAME) p99_inline
628 # define P99_SETJMP_INLINE(NAME) P99_WEAK(NAME)
632 #ifndef P99_FIXED_REGISTER
634 # define P99_FIXED_REGISTER(REG) __asm__(P99_STRINGIFY(REG))
641 # define P99_FIXED_REGISTER(REG)
675 #ifndef static_assert
692 # if p99_has_feature(c_static_assert)
693 # define static_assert _Static_assert
695 # define static_assert(EXPR, DIAGSTR) \
696 extern char const p00_compiletime_assert[ \
697 sizeof((void const*[3*(!!(EXPR)) - 1]){ \
698 &p00_compiletime_assert, \
699 "static assertion failed: " P99_STRINGIFY(EXPR) ", " DIAGSTR}) \
701 extern char const p00_compiletime_assert[
sizeof(
void const*[2])];
705 #if P99_COMPILER & (P99_COMPILER_CLANG | P99_COMPILER_GNU | P99_COMPILER_OPEN64)
706 # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) && (P99_GCC_VERSION >= 30000UL)
707 # if defined(__SIZEOF_INT128__)
708 # define p99x_uintmax p99x_uintmax
709 # define p99x_intmax p99x_intmax
710 # define p99x_uint128 p99x_uint128
711 # define p99x_int128 p99x_int128
728 #ifndef __alignof_is_defined
729 # define alignof _Alignof
730 # if !p99_has_feature(c_alignof)
731 # if p99_has_feature(gnu_alignof)
733 # define _Alignof(T) __alignof__(T)
736 # define _Alignof(T) offsetof(struct { char p00_c; T p00_t; }, p00_t)
748 #ifndef __alignas_is_defined
749 # define alignas _Alignas
750 # if !p99_has_feature(c_alignas)
751 # if p99_has_attribute(aligned)
753 # define _Alignas(X) __attribute__((__aligned__(X)))
773 #if !p99_has_feature(c_max_align_t) && !p99_has_extension(c_max_align_t)
788 unsigned short int P99_PASTE2(p00_, __LINE__);
794 unsigned long long int P99_PASTE2(p00_, __LINE__);
798 # ifndef __STDC_NO_COMPLEX__
801 long double _Complex
P99_PASTE2(p00_, __LINE__);
810 # if p99_has_attribute(aligned)
811 __attribute__((__aligned__))
817 #undef p00_has_feature_c_max_align_t
818 #define p00_has_feature_c_max_align_t 1
819 #undef p00_has_extension_c_max_align_t
820 #define p00_has_extension_c_max_align_t 1
847 #elif !defined(noreturn)
848 # define noreturn _Noreturn
852 #elif !p99_has_feature(c_noreturn)
853 # if p99_has_attribute(__noreturn__)
855 # define _Noreturn __attribute__((__noreturn__))
857 # elif p99_has_feature(pragma_noreturn)
858 # define _Noreturn _Pragma(NORETURN)
868 # define __dead2 __attribute__((__noreturn__))
879 # define _Thread_local
887 # define thread_local
888 #elif !defined(thread_local)
889 # define thread_local _Thread_local
890 # if p99_has_feature(gnu_thread_local)
891 # define _Thread_local __thread
892 # elif p99_has_feature(declspec_thread)
893 # define _Thread_local __declspec(thread)
913 #define P00_HARMLESS_SIZEOF(ID) sizeof(sizeof(ID))
915 #if p99_has_attribute(unused)
916 # define P00_UNUSED(EXPR) \
917 extern char const p00_harmless_declaration \
918 [P00_HARMLESS_SIZEOF(EXPR)] __attribute__((__unused__))
920 # define P00_UNUSED(EXPR) \
921 extern char const p00_harmless_declaration \
922 [P00_HARMLESS_SIZEOF(EXPR)]
929 #define P00_HARMLESS_DECLARATION P00_UNUSED(p00_harmless_declaration)
941 #define P99_MACRO_END(...) \
942 extern void P99_PASTE(p00_harmless_declaration_, __VA_ARGS__)(void)
957 #if p99_has_feature(openmp)
958 #define P99_PARALLEL_PRAGMA omp parallel for
960 #define P99_PARALLEL_PRAGMA
973 #if p99_has_builtin(__builtin_expect)
974 # define P99_EXPECT(EXP, VAL) __builtin_expect((EXP), (VAL))
976 # define P99_EXPECT(EXP, VAL) (EXP)
994 # define P99_UNLIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 0)
1010 # define P99_LIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 1)
1018 #if p99_has_attribute(deprecated)
1019 # define P99_DEPRECATED(...) __attribute__((__deprecated__))
1021 # define P99_DEPRECATED(...)
1032 # define P99_ATLEAST static
1052 P00_DOCUMENT_IDENTIFIER_ARGUMENT(
P99_VECTOR, 1)
1054 #if p99_has_attribute(vector_size)
1055 # define P99_VECTOR(T, NAME, N) T NAME __attribute__((vector_size(sizeof(T)*(N))))
1057 # define P99_VECTOR(T, NAME, N) _Alignas(sizeof(T)*(N)) T NAME[N]
1065 #define P99_IF_COMPILER(COMP, ...) P00_COMPILER_PRAGMA_ ## COMP(P99_STRINGIFY(__VA_ARGS__))
1082 P99_IF_COMPILER(GNU, GCC diagnostic ignored
"-Wmissing-field-initializers")
1086 P99_IF_COMPILER(OPEN64, GCC diagnostic ignored
"-Wmissing-field-initializers")
1089 P99_IF_COMPILER(CLANG, GCC diagnostic ignored
"-Wnon-literal-null-conversion")
1106 #if P99_COMPILER & P99_COMPILER_CLANG
1107 #define P99_WARN_INIT_PUSH \
1108 P99_PRAGMA(GCC diagnostic push) \
1109 P99_PRAGMA(GCC diagnostic ignored "-Wmissing-braces") \
1110 P99_PRAGMA(GCC diagnostic ignored "-Wmissing-field-initializers") \
1111 P99_PRAGMA(GCC diagnostic ignored "-Winitializer-overrides")
1112 #define P99_WARN_INIT_POP P99_PRAGMA(GCC diagnostic pop)
1115 #ifndef P99_WARN_INIT_PUSH
1116 # define P99_WARN_INIT_PUSH
1119 #ifndef P99_WARN_INIT_POP
1120 # define P99_WARN_INIT_POP
1137 #if P99_COMPILER & (P99_COMPILER_GNU | P99_COMPILER_CLANG)
1138 #define P99_WARN_REDUNDANT_DECLS_PUSH \
1139 P99_PRAGMA(GCC diagnostic push) \
1140 P99_PRAGMA(GCC diagnostic ignored "-Wredundant-decls")
1141 #define P99_WARN_REDUNDANT_DECLS_POP P99_PRAGMA(GCC diagnostic pop)
1144 #ifndef P99_WARN_REDUNDANT_DECLS_PUSH
1145 # define P99_WARN_REDUNDANT_DECLS_PUSH
1148 #ifndef P99_WARN_REDUNDANT_DECLS_POP
1149 # define P99_WARN_REDUNDANT_DECLS_POP