00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef P99_COMPILER_H
00014 #define P99_COMPILER_H
00015
00016 #include "p99_args.h"
00017 #include <float.h>
00018 #ifndef P00_NO_HAVE_ISO646_H
00019 # include <iso646.h>
00020 #endif
00021 #include <limits.h>
00022 #include <stdarg.h>
00023 #include <stdbool.h>
00024 #include <stddef.h>
00025 #include <stdint.h>
00026
00027 #if __STDC_HOSTED__
00028 # include <assert.h>
00029 # include <wchar.h>
00030 # include <wctype.h>
00031 #endif
00032
00105 #define P00_PREFIX0(N) P00_PREFIX0_(N)
00106 #define P00_PREFIX0_(N) 0 ## N
00107 #define P00_STRINGIFY(...) #__VA_ARGS__
00108 #define P00_VERSION_NO(A, B, C) (((A)*10000UL)+(B)*100UL+(C))
00109
00113 #define P99_STRINGIFY(...) P00_STRINGIFY(__VA_ARGS__)
00114
00115
00116 #if P99_COMPILER & P99_COMPILER_CLANG
00117 # undef P00_COMPILER_PRAGMA_CLANG
00118 # define P00_COMPILER_PRAGMA_CLANG(STR) _Pragma(STR)
00119 # undef P99_COMPILER_VERSION
00120 # define P99_COMPILER_VERSION \
00121 "clang " \
00122 __clang_version__ \
00123 "; gnu " \
00124 P99_STRINGIFY(__GNUC__) "." \
00125 P99_STRINGIFY(__GNUC_MINOR__) "." \
00126 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
00127 # define P99_VERSION_NO P00_VERSION_NO(__clang_major__, __clang_minor__, __clang_patchlevel__)
00128
00129 #elif P99_COMPILER & P99_COMPILER_INTEL
00130 # undef P99_COMPILER_VERSION
00131 # define P99_COMPILER_VERSION \
00132 "intel " P99_STRINGIFY(__INTEL_COMPILER) \
00133 "; gnu " \
00134 P99_STRINGIFY(__GNUC__) "." \
00135 P99_STRINGIFY(__GNUC_MINOR__) "." \
00136 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
00137 # define P99_VERSION_NO P00_VERSION_NO(__INTEL_COMPILER, 0, 0)
00138
00139 #elif P99_COMPILER & P99_COMPILER_PCC
00140 # undef P99_COMPILER_VERSION
00141 # define P99_COMPILER_VERSION \
00142 "pcc " \
00143 P99_STRINGIFY(__PCC__) \
00144 "." P99_STRINGIFY(__PCC_MINOR__) \
00145 "." P99_STRINGIFY(__PCC_MINORMINOR__) \
00146 "; gnu " \
00147 P99_STRINGIFY(__GNUC__) "." \
00148 P99_STRINGIFY(__GNUC_MINOR__) "." \
00149 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
00150 # define P99_VERSION_NO P00_VERSION_NO(__PCC__, __PCC_MINOR__, __PCC_MINORMINOR__)
00151
00152 #elif P99_COMPILER & P99_COMPILER_TINYC
00153 # undef P99_COMPILER_VERSION
00154 # define P99_COMPILER_VERSION \
00155 "tinyc " \
00156 P99_STRINGIFY(__TINYC__)
00157 # define P99_VERSION_NO P00_VERSION_NO(__TINYC__, 0, 0)
00158
00159 #elif P99_COMPILER & P99_COMPILER_OPEN64
00160 # undef P99_COMPILER_VERSION
00161 # define P99_COMPILER_VERSION \
00162 "open64 " __OPEN64__ \
00163 "; gnu " \
00164 P99_STRINGIFY(__GNUC__) "." \
00165 P99_STRINGIFY(__GNUC_MINOR__) "." \
00166 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
00167 # define P99_VERSION_NO P00_VERSION_NO(__TINYC__, 0, 0)
00168
00169 #elif P99_COMPILER & P99_COMPILER_GNU
00170 # undef P99_COMPILER_VERSION
00171 # define P99_COMPILER_VERSION \
00172 "gnu " \
00173 P99_STRINGIFY(__GNUC__) "." \
00174 P99_STRINGIFY(__GNUC_MINOR__) "." \
00175 P99_STRINGIFY(__GNUC_PATCHLEVEL__)
00176 # define P99_VERSION_NO P00_VERSION_NO(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
00177 #endif
00178
00179
00180 #if P99_COMPILER & P99_COMPILER_INTEL
00181 # if (__ICC < 1300) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 2)
00182 # undef __GNUC_MINOR__
00183 # define __GNUC_MINOR__ 2
00184 # undef __GNUC_PATCHLEVEL__
00185 # define __GNUC_PATCHLEVEL__ 0
00186 # endif
00187 #endif
00188
00189
00190 # ifdef __GNUC__
00191 # define p99_extension __extension__
00192 # define P99_GCC_VERSION P00_VERSION_NO(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
00193 # endif
00194
00195 #ifndef p99_extension
00196
00199 # define p99_extension
00200 #endif
00201
00202
00203 #ifndef P00_DOXYGEN
00204 #ifdef __cplusplus
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 # define P00_VA_ARGS__(...) __VA_ARGS__
00215 enum { p00_trailing_comma_in_enum__ = -1, };
00216 inline
00217 signed p00_trailing_comma_in_initializer__(void) {
00218 signed a[] = { p00_trailing_comma_in_enum__ , };
00219 return a[0];
00220 }
00221 #else
00222 # if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
00223
00224
00225
00226
00227
00228
00229 # error "The P99 preprocessor files need a C99 compliant compiler"
00230 # endif
00231 # if (!P99_TOK_EQ(1, 1) || P99_TOK_EQ(1, 0))
00232
00233
00234
00235
00236
00237 # error "The preprocessor is not P99 compatible"
00238 # endif
00239 #endif
00240 #endif
00241
00242 #ifndef __has_builtin
00243 # define __has_builtin(X) p00_has_builtin_ ## X // Compatibility with non-clang compilers.
00244 #endif
00245 #ifndef __has_feature
00246 # define __has_feature(X) p00_has_feature_ ## X // Compatibility with non-clang compilers.
00247 #endif
00248 #ifndef __has_extension
00249 # define __has_extension __has_feature // Compatibility with non-clang compilers.
00250 #endif
00251 #ifndef __has_attribute
00252 # define __has_attribute(X) p00_has_attribute_ ## X // Compatibility with non-clang compilers.
00253 #endif
00254
00255 #ifndef p99_has_builtin
00256 # define p99_has_builtin(X) (__has_builtin(X) || p00_has_builtin_ ## X) // Compatibility with non-clang compilers.
00257 # define p99_has_feature(X) (__has_feature(X) || p00_has_feature_ ## X) // Compatibility with non-clang compilers.
00258 # define p99_has_extension(X) (__has_extension(X) || p00_has_extension_ ## X) // Compatibility with non-clang compilers.
00259 # define p99_has_attribute(X) (__has_attribute(X) || p00_has_attribute_ ## X) // Compatibility with non-clang compilers.
00260 #endif
00261
00262 #if P99_COMPILER & P99_COMPILER_OPEN64
00263 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
00264 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
00265 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
00266 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
00267 # define __GNUC_NO_TLS__ 1
00268 #endif
00269
00270 #ifdef _OPENMP
00271 # define p00_has_feature_openmp 1
00272 #endif
00273
00274 #if __GNUC__
00275 # define p00_has_attribute_always_inline 1
00276 # define p00_has_attribute_weak 1
00277 # define p00_has_attribute_weakref 1
00278 # if defined(__GNUC_GNU_INLINE__) || (P99_GCC_VERSION < 40300UL)
00279 # define p00_has_attribute_gnu_inline 1
00280 # endif
00281 # define p00_has_attribute_aligned 1
00282 # define p00_has_attribute_noreturn 1
00283 # define p00_has_attribute_deprecated 1
00284 # ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
00285 # define p00_has_builtin___sync_val_compare_and_swap 1
00286 # define p00_has_builtin___sync_lock_test_and_set 1
00287 # define p00_has_builtin___sync_lock_release 1
00288 # define p00_has_builtin___sync_synchronize 1
00289 # define p00_has_builtin___sync_fetch_and_add 1
00290 # define p00_has_builtin___sync_fetch_and_sub 1
00291 # define p00_has_builtin___sync_fetch_and_or 1
00292 # define p00_has_builtin___sync_fetch_and_and 1
00293 # define p00_has_builtin___sync_fetch_and_xor 1
00294 # endif
00295 # if P99_GCC_VERSION >= 30000UL
00296 # define p00_has_builtin___builtin_expect 1
00297 # endif
00298
00299
00300
00301 # if P99_GCC_VERSION >= 40600UL
00302 # define p00_has_feature_c_static_assert 1
00303 # endif
00304 # if defined(__GNUC_STDC_INLINE__) || P99_GCC_VERSION >= 40300UL
00305 # define p00_has_feature_c_inline 1
00306 # endif
00307 # define p00_has_feature_gnu_thread_local 1
00308 # define p00_has_feature_gnu_alignof 1
00309 # define p00_has_feature_statement_expression 1
00310 # define p00_has_feature_typeof 1
00311 # if (P99_GCC_VERSION >= 40700UL) && (P99_GCC_VERSION < 40800UL)
00312 # if __STDC_VERSION__ > 201100L
00313 # define p00_has_feature_uchar_h 0
00314 # define p00_has_feature_stdnoreturn_h 1
00315 # define __STDC_NO_ATOMICS__ 1
00316 # define __STDC_NO_THREADS__ 1
00317 # define p00_has_feature_c_max_align_t 1
00318 # define p00_has_feature_c_generic_selections 0
00319 # endif
00320 # endif
00321 #endif
00322
00323 #if p99_has_builtin(__sync_val_compare_and_swap)
00324 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
00325 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
00326 # endif
00327 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
00328 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
00329 # endif
00330 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
00331 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
00332 # if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) && (UINTPTR_MAX >= UINT64_MAX)
00333 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
00334 # endif
00335 # endif
00336 #endif
00337
00338
00339
00340
00341
00342
00343 #if __STDC_VERSION__ > 201100L
00344 # ifndef p00_has_feature_uchar_h
00345 # define p00_has_feature_uchar_h 1
00346 # endif
00347 # ifndef p00_has_feature_stdnoreturn_h
00348 # define p00_has_feature_stdnoreturn_h 1
00349 # endif
00350 # ifndef p00_has_feature_c_max_align_t
00351 # define p00_has_feature_c_max_align_t 1
00352 # endif
00353 # ifndef p00_has_feature_c_generic_selections
00354 # define p00_has_feature_c_generic_selections 1
00355 # endif
00356 #endif
00357
00358 #if P99_COMPILER & (P99_COMPILER_IBM | P99_COMPILER_SUN)
00359 # define p00_has_feature_gnu_thread 1
00360 #elif P99_COMPILER & (P99_COMPILER_MICROSOFT | P99_COMPILER_BORLAND)
00361 # define p00_has_feature_declspec_thread 1
00362 #endif
00363
00364 #if P99_COMPILER & P99_COMPILER_INTEL
00365 # define p99_inline __attribute__((__always_inline__)) inline
00366 # ifndef __GNUC__
00367 # define P00_NO_HAVE_TGMATH_H
00368 # endif
00369 #elif P99_COMPILER & P99_COMPILER_PCC
00370
00371 #elif P99_COMPILER & P99_COMPILER_CLANG
00372 # if p99_has_attribute(always_inline)
00373 # define p99_inline __attribute__((__always_inline__)) inline
00374 # endif
00375
00376 # define P99_FIXED_REGISTER(REG)
00377 # if P99_VERSION_NO < 30200UL
00378
00379 # define __STDC_NO_ATOMICS__ 1
00380
00381 # define __STDC_NO_THREADS__ 1
00382 # endif
00383 #elif P99_COMPILER & (P99_COMPILER_GNU | P99_COMPILER_OPEN64)
00384 # define P99_ATLEAST
00385
00386
00387
00388
00389 # if !p99_has_feature(c_inline)
00390 # ifdef inline
00391 # undef inline
00392 # endif
00393 # if p99_has_attribute(gnu_inline)
00394 # define inline __attribute__((__gnu_inline__,__weak__)) __inline__
00395 # define p99_inline __attribute__((__always_inline__,__gnu_inline__,__weak__)) __inline__
00396 # else
00397 # define inline __attribute__((__weak__)) __inline__
00398 # define p99_inline __attribute__((__always_inline__,__weak__)) __inline__
00399 # endif
00400 # define p00_instantiate
00401 # else
00402 # define inline __inline__
00403 # define p00_instantiate extern __inline__
00404 # define p99_inline __attribute__((__always_inline__)) __inline__
00405 # endif
00406 #endif
00407
00408 # if !defined(p99_inline) || defined(P00_DOXYGEN)
00409
00418 # define p99_inline static inline
00419 # endif
00420
00421 # ifndef p00_instantiate
00422
00430 # define p00_instantiate extern inline
00431 # endif
00432
00433 #if p99_has_attribute(weak)
00434 # define P00_WEAK1(ID) __attribute__((__weak__))
00435 #elif P99_COMPILER & P99_COMPILER_MICROSOFT
00436 # define P00_WEAK1(ID) __declspec(selectany)
00437 #else
00438 # define P00_WEAK1(ID) _Pragma(P99_STRINGIFY(weak ID))
00439 #endif
00440
00441 #if p99_has_attribute(weakref)
00442 # define P00_WEAK2(ID, ...) __attribute__((__weakref__(#__VA_ARGS__)))
00443 #else
00444 # define P00_WEAK2(ID, ...) _Pragma(P99_STRINGIFY(weak ID=__VA_ARGS__))
00445 #endif
00446
00473 # define P99_WEAK(...) P99_IF_LT(P99_NARG(__VA_ARGS__), 2)(P00_WEAK1(__VA_ARGS__))(P00_WEAK2(__VA_ARGS__))
00474
00475 #if p99_has_feature(setjmp_inline)
00476 # define P99_SETJMP_INLINE(NAME) p99_inline
00477 #else
00478 # define P99_SETJMP_INLINE(NAME) P99_WEAK(NAME)
00479 #endif
00480
00481
00482 #ifndef P99_FIXED_REGISTER
00483 # ifdef __GNUC__
00484 # define P99_FIXED_REGISTER(REG) __asm__(P99_STRINGIFY(REG))
00485 # else
00486
00491 # define P99_FIXED_REGISTER(REG)
00492 # endif
00493 #endif
00494
00495
00519
00520 #if __STDC_VERSION__ > 201100L
00521 # include <stdalign.h>
00522 # if p99_has_feature(stdnoreturn_h)
00523 # include <stdnoreturn.h>
00524 # endif
00525 #endif
00526
00527 #if __STDC_HOSTED__
00528 # if p99_has_feature(uchar_h)
00529 # include <uchar.h>
00530 # else
00531
00532 typedef uint_least16_t char16_t;
00533 typedef uint_least32_t char32_t;
00534 # endif
00535 #endif
00536
00537 #ifndef static_assert
00538
00554 # if p99_has_feature(c_static_assert)
00555 # define static_assert _Static_assert
00556 # else
00557 # define static_assert(EXPR, DIAGSTR) \
00558 extern char const p00_compiletime_assert[ \
00559 sizeof((void const*[3*(!!(EXPR)) - 1]){ \
00560 &p00_compiletime_assert, \
00561 "static assertion failed: " P99_STRINGIFY(EXPR) ", " DIAGSTR}) \
00562 ]
00563 extern char const p00_compiletime_assert[sizeof(void const*[2])];
00564 # endif
00565 #endif
00566
00575 #ifndef __alignof_is_defined
00576 # define alignof _Alignof
00577 # if !p99_has_feature(c_alignof)
00578 # if p99_has_feature(gnu_alignof)
00579 # define _Alignof(T) __alignof__(T)
00580 # else
00581 # define _Alignof(T) offsetof(struct { char p00_c; T p00_t; }, p00_t)
00582 # endif
00583 # endif
00584 #endif
00585
00593 #ifndef __alignas_is_defined
00594 # define alignas _Alignas
00595 # if !p99_has_feature(c_alignas)
00596 # if p99_has_attribute(aligned)
00597 # define _Alignas(X) __attribute__((__aligned__(X)))
00598 # endif
00599 # endif
00600 #endif
00601
00616 #if !p99_has_feature(c_max_align_t) && !p99_has_extension(c_max_align_t)
00617 typedef union max_align_t max_align_t;
00618 # ifndef P00_DOXYGEN
00619 union max_align_t {
00620 struct P99_PASTE2(p00_, __LINE__) {
00621 unsigned P99_PASTE2(p00_, __LINE__);
00622 } P99_PASTE2(p00_, __LINE__);
00623 union max_align_t* P99_PASTE2(p00_, __LINE__);
00624 void* P99_PASTE2(p00_, __LINE__);
00625 void (*P99_PASTE2(p00_, __LINE__))(void);
00626 _Bool P99_PASTE2(p00_, __LINE__);
00627 char P99_PASTE2(p00_, __LINE__);
00628 signed char P99_PASTE2(p00_, __LINE__);
00629 unsigned char P99_PASTE2(p00_, __LINE__);
00630 short int P99_PASTE2(p00_, __LINE__);
00631 unsigned short int P99_PASTE2(p00_, __LINE__);
00632 int P99_PASTE2(p00_, __LINE__);
00633 unsigned int P99_PASTE2(p00_, __LINE__);
00634 long int P99_PASTE2(p00_, __LINE__);
00635 unsigned long int P99_PASTE2(p00_, __LINE__);
00636 long long int P99_PASTE2(p00_, __LINE__);
00637 unsigned long long int P99_PASTE2(p00_, __LINE__);
00638 float P99_PASTE2(p00_, __LINE__);
00639 double P99_PASTE2(p00_, __LINE__);
00640 long double P99_PASTE2(p00_, __LINE__);
00641 # ifndef __STDC_NO_COMPLEX__
00642 float _Complex P99_PASTE2(p00_, __LINE__);
00643 double _Complex P99_PASTE2(p00_, __LINE__);
00644 long double _Complex P99_PASTE2(p00_, __LINE__);
00645 # endif
00646 }
00647 # if p99_has_attribute(aligned)
00648 __attribute__((__aligned__))
00649 # endif
00650 ;
00651 # endif
00652 #endif
00653
00654 #undef p00_has_feature_c_max_align_t
00655 #define p00_has_feature_c_max_align_t 1
00656 #undef p00_has_extension_c_max_align_t
00657 #define p00_has_extension_c_max_align_t 1
00658
00659 #ifdef P00_DOXYGEN
00660
00672 #define _Noreturn
00673
00679 #define noreturn
00680
00681 noreturn void p00_f(void);
00682 static_assert(1);
00683
00684 #elif !defined(noreturn)
00685 # define noreturn _Noreturn
00686 # if !p99_has_feature(c_noreturn)
00687 # if p99_has_attribute(noreturn)
00688 # define _Noreturn __attribute__((__noreturn__))
00689 # elif !defined(P00_DOXYGEN)
00690 # define _Noreturn _Pragma(NORETURN)
00691 # endif
00692 # endif
00693 #endif
00694
00695 #ifdef P00_DOXYGEN
00696
00703 # define _Thread_local
00704
00711 # define thread_local
00712 #elif !defined(thread_local)
00713 # define thread_local _Thread_local
00714 # if p99_has_feature(gnu_thread_local)
00715 # define _Thread_local __thread
00716 # elif p99_has_feature(declspec_thread)
00717 # define _Thread_local __declspec(thread)
00718 # endif
00719 #endif
00720
00721 static_assert(1, "test of static assertions");
00722
00737
00738
00739
00740
00741 #define P00_HARMLESS_DECLARATION \
00742 extern char const p00_harmless_declaration[ \
00743 sizeof((void const*[1]){ &p00_harmless_declaration }) \
00744 ]
00745
00746 extern char const p00_harmless_declaration[sizeof(void const*[1])];
00747
00754 #define P99_MACRO_END(...) P00_HARMLESS_DECLARATION
00755
00756
00769 #if p99_has_feature(openmp)
00770 #define P99_PARALLEL_PRAGMA omp parallel for
00771 #else
00772 #define P99_PARALLEL_PRAGMA
00773 #endif
00774
00785 #if p99_has_builtin(__builtin_expect)
00786 # define P99_EXPECT(EXP, VAL) __builtin_expect((EXP), (VAL))
00787 #else
00788 # define P99_EXPECT(EXP, VAL) (EXP)
00789 #endif
00790
00805 #ifndef P99_UNLIKELY
00806 # define P99_UNLIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 0)
00807 #endif
00808
00821 #ifndef P99_LIKELY
00822 # define P99_LIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 1)
00823 #endif
00824
00825
00830 #if p99_has_attribute(deprecated)
00831 # define P99_DEPRECATED(...) __attribute__((__deprecated__))
00832 #else
00833 # define P99_DEPRECATED(...)
00834 #endif
00835
00843 #ifndef P99_ATLEAST
00844 # define P99_ATLEAST static
00845 #endif
00846
00847
00848 #if P99_COMPILER & (P99_COMPILER_CLANG | P99_COMPILER_GNU | P99_COMPILER_OPEN64)
00849 # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) && (P99_GCC_VERSION >= 30000UL)
00850 # if (__LONG_MAX__ == 9223372036854775807) && (__LONG_LONG_MAX__ == 9223372036854775807)
00851 # define p99x_uintmax p99x_uintmax
00852 # define p99x_intmax p99x_intmax
00853 # define p99x_uint128 p99x_uint128
00854 # define p99x_int128 p99x_int128
00855 typedef __uint128_t p99x_uintmax;
00856 typedef __int128_t p99x_intmax;
00857 typedef __uint128_t p99x_uint128;
00858 typedef __int128_t p99x_int128;
00859 # endif
00860 # endif
00861 #endif
00862
00863
00864 #if P99_COMPILER & P99_COMPILER_INTEL
00865 # ifndef __GNUC__
00866 # define P00_NO_HAVE_TGMATH_H
00867 # endif
00868 #endif
00869
00875 #define P99_IF_COMPILER(COMP, ...) P00_COMPILER_PRAGMA_ ## COMP(P99_STRINGIFY(__VA_ARGS__))
00876
00877 #ifndef P00_DOXYGEN
00878
00879
00880
00881 P99_IF_COMPILER(INTEL, warning(disable: 1418))
00882 P99_IF_COMPILER(INTEL, warning(disable: 1419))
00883
00884 #endif
00885
00893 #endif