P99
p99_compiler.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2013 Bobby */
6 /* (C) copyright 2010-2017 Jens Gustedt, INRIA, France */
7 /* (C) copyright 2013 Pierre-Nicolas Clauss */
8 /* (C) copyright 2012 William Morris */
9 /* */
10 /* This file is free software; it is part of the P99 project. */
11 /* */
12 /* Licensed under the Apache License, Version 2.0 (the "License"); */
13 /* you may not use this file except in compliance with the License. */
14 /* You may obtain a copy of the License at */
15 /* */
16 /* http://www.apache.org/licenses/LICENSE-2.0 */
17 /* */
18 /* Unless required by applicable law or agreed to in writing, software */
19 /* distributed under the License is distributed on an "AS IS" BASIS, */
20 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
21 /* See the License for the specific language governing permissions and */
22 /* limitations under the License. */
23 /* */
24 #ifndef P99_COMPILER_H
25 #define P99_COMPILER_H
26 
27 #include "p99_args.h"
28 
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))
105 
109 #define P99_STRINGIFY(...) P00_STRINGIFY(__VA_ARGS__)
110 
111 /* be sure to put all compilers that are faking gcc before gcc itself */
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 \
117  "Apple/clang " \
118  __apple_build_version__ \
119  "pretending clang version " \
120  __clang_version__ \
121  "; gnu " \
122  P99_STRINGIFY(__GNUC__) "." \
123  P99_STRINGIFY(__GNUC_MINOR__) "." \
124  P99_STRINGIFY(__GNUC_PATCHLEVEL__)
125 # define P99_VERSION_NO __apple_build_version__
126 
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 \
132  "clang " \
133  __clang_version__ \
134  "; gnu " \
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__)
139 
140 #elif P99_COMPILER & P99_COMPILER_INTEL
141 # undef P99_COMPILER_VERSION
142 # define P99_COMPILER_VERSION \
143  "intel " P99_STRINGIFY(__INTEL_COMPILER) \
144  "; gnu " \
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)
149 
150 #elif P99_COMPILER & P99_COMPILER_PCC
151 # undef P99_COMPILER_VERSION
152 # define P99_COMPILER_VERSION \
153 "pcc " \
154  P99_STRINGIFY(__PCC__) \
155  "." P99_STRINGIFY(__PCC_MINOR__) \
156  "." P99_STRINGIFY(__PCC_MINORMINOR__) \
157  "; gnu " \
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__)
162 
163 #elif P99_COMPILER & P99_COMPILER_TINYC
164 # undef P99_COMPILER_VERSION
165 # define P99_COMPILER_VERSION \
166  "tinyc " \
167  P99_STRINGIFY(__TINYC__)
168 # define P99_VERSION_NO P00_VERSION_NO(__TINYC__, 0, 0)
169 
170 #elif P99_COMPILER & P99_COMPILER_OPEN64
171 # undef P99_COMPILER_VERSION
172 # define P99_COMPILER_VERSION \
173  "open64 " __OPEN64__ \
174  "; gnu " \
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)
179 
180 #elif P99_COMPILER & P99_COMPILER_GNU
181 # undef P99_COMPILER_VERSION
182 # define P99_COMPILER_VERSION \
183  "gnu " \
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__)
188 #endif
189 
190 /* intel is cheating about the gcc abi they support */
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
197 # endif
198 #endif
199 
200 
201 # ifdef __GNUC__
202 # define p99_extension __extension__
203 # define P99_GCC_VERSION P00_VERSION_NO(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
204 # endif
205 
206 #ifndef p99_extension
207 
210 # define p99_extension
211 #endif
212 
213 
214 #ifndef P00_DOXYGEN
215 #ifdef __cplusplus
216 /* C++ as of 1998 is currently not compatible with the macros here. It
217  is missing:
218  - variate macros
219  - compound literals
220  - trailing commas in initializers
221  - trailing commas in enum declarations
222  we test for some of this to see if we have any chance to pass this
223  through. Otherwise this should error out early.
224  */
225 # define P00_VA_ARGS__(...) __VA_ARGS__
226 enum { p00_trailing_comma_in_enum__ = -1, };
227 inline
228 signed p00_trailing_comma_in_initializer__(void) {
229  signed a[] = { p00_trailing_comma_in_enum__, };
230  return a[0];
231 }
232 #else
233 # if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
234 /* If you come here your compiler is not conforming to C99, since
235  this requires the macro __STDC_VERSION__ to be set to the
236  indicated value (or larger).
237 
238  You still might be able to use P99, but you would have to cheat on
239  that value. You are on your own. */
240 # error "The P99 preprocessor files need a C99 compliant compiler"
241 # endif
242 # if (!P99_TOK_EQ(1, 1) || P99_TOK_EQ(1, 0))
243 /* If you come here your preprocessor is not able to expand P99 macros
244  correctly. Most probably this is a bug in your preprocessor
245  implementation, but it could also be that your implementation just
246  interprets the standard different. In any case, we can't
247  proceed. */
248 # error "The preprocessor is not P99 compatible"
249 # endif
250 #endif
251 #endif
252 
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.
256 # endif
257 # ifndef __has_feature
258 # define __has_feature(X) p00_has_feature_ ## X // Compatibility with non-clang compilers.
259 # endif
260 # ifndef __has_extension
261 # define __has_extension __has_feature // Compatibility with non-clang compilers.
262 # endif
263 # ifndef __has_attribute
264 # define __has_attribute(X) p00_has_attribute_ ## X // Compatibility with non-clang compilers.
265 # endif
266 #endif
267 
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.
273 #endif
274 
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
281 #endif
282 
283 #ifdef _OPENMP
284 # define p00_has_feature_openmp 1
285 #endif
286 
287 #if __GNUC__
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
299 # endif
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
315 # endif
316 # define P99_TYPEOF(X) __typeof__(X)
317 # if P99_GCC_VERSION >= 30000UL
318 # define p00_has_builtin___builtin_expect 1
319 # endif
320 //# if P99_GCC_VERSION >= UNKNOWN
321 //# define p00_has_feature_c_alignas 1
322 //# endif
323 # if P99_GCC_VERSION >= 40300UL
324 # define p00_has_attribute_error 1
325 # endif
326 # if P99_GCC_VERSION >= 40600UL
327 # define p00_has_feature_c_static_assert 1
328 # define p00_has_attribute_externally_visible 1
329 # endif
330 # if defined(__GNUC_STDC_INLINE__) || P99_GCC_VERSION >= 40300UL
331 # define p00_has_feature_c_inline 1
332 # endif
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
344 # endif
345 # endif
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
352 # endif
353 # endif
354 #endif
355 
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
364 #endif
365 
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
369 # endif
370 # ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
371 # define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
372 # endif
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
377 # endif
378 # endif
379 #endif
380 
381 
382 /* Since for the moment C11 support is only very partial, we have to
383  introduce some feature test macros. If a compiler claims to be C11
384  but doesn't implement a required feature, you have to define the
385  corresponding macro to 0 before this point. */
386 #if __STDC_VERSION__ > 201100L
387 # ifndef p00_has_feature_stdnoreturn_h
388 # define p00_has_feature_stdnoreturn_h 1
389 # endif
390 # ifndef p00_has_feature_c_max_align_t
391 # define p00_has_feature_c_max_align_t 1
392 # endif
393 # ifndef p00_has_feature_c_generic_selections
394 # define p00_has_feature_c_generic_selections 1
395 # endif
396 #endif
397 
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
402 #endif
403 
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
409 # endif
410 # else
411 /* Intel now has a file stdatomic.h, but this is still quite
412  incomplete and not yet worth it. */
413 //# define p00_has_feature_stdatomic_h 1
414 # endif
415 
416 #elif P99_COMPILER & P99_COMPILER_PCC
417 /* # error "The P99 preprocessor files can't work with the pcc compiler, yet" */
418 
419 #elif P99_COMPILER & P99_COMPILER_APPLE
420 /* For a start the properties for the apple clang fake are just copied
421  from clang. Adjust once we know more details. */
422 # if p99_has_attribute(always_inline)
423 # define p99_inline __attribute__((__always_inline__)) inline
424 # endif
425 /* clang can't nail a variable to a register, yet */
426 # define P99_FIXED_REGISTER(REG)
427 /* clang has no stdatomic.h, yet */
428 # define __STDC_NO_ATOMICS__ 1
429 
430 #elif P99_COMPILER & P99_COMPILER_CLANG
431 # if p99_has_attribute(always_inline)
432 # define p99_inline __attribute__((__always_inline__)) inline
433 # endif
434 /* clang can't nail a variable to a register, yet */
435 # define P99_FIXED_REGISTER(REG)
436 /* clang has no stdatomic.h, yet. It can't use the one from gcc, since
437  that (gratuously) uses __auto_type. */
438 # if P99_VERSION_NO < 100000UL
439 # define __STDC_NO_ATOMICS__ 1
440 # endif
441 # if P99_VERSION_NO > 30200UL
442 # define p00_has_feature_stdnoreturn_h 1
443 # endif
444 /* stdalign.h exists but is not usable, at least up to 3.2 */
445 //# if P99_VERSION_NO >= 30000UL
446 //# define p00_has_feature_stdalign_h 1
447 //# endif
448 
449 #elif P99_COMPILER & (P99_COMPILER_GNU | P99_COMPILER_OPEN64)
450 # define P99_ATLEAST
451 /* gcc prior to version 4.2.1 has the inline keyword but with slightly
452  different semantics.
453  Be sure to always inline functions in this cases.
454  */
455 # if !p99_has_feature(c_inline)
456 # ifdef inline
457 # undef inline
458 # endif
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__
462 # else
463 # define inline __attribute__((__weak__)) __inline__
464 # define p99_inline __attribute__((__always_inline__,__weak__)) __inline__
465 # endif
466 # define static_inline static __inline__
467 # if p99_has_attribute(externally_visible)
468 # define p00_instantiate __attribute__((__externally_visible__))
469 # else
470 # define p00_instantiate
471 # endif
472 # else
473 # define inline __inline__
474 # if p99_has_attribute(externally_visible)
475 # define p00_instantiate __attribute__((__externally_visible__)) extern __inline__
476 # else
477 # define p00_instantiate extern __inline__
478 # endif
479 # define p99_inline __attribute__((__always_inline__)) __inline__
480 # endif
481 #endif
482 
483 # if !defined(static_inline) || defined(P00_DOXYGEN)
484 # define static_inline static inline
485 # endif
486 # if !defined(p99_inline) || defined(P00_DOXYGEN)
487 
496 # define p99_inline static inline
497 # endif
498 
499 #ifdef P00_FORCE_NOINLINE
500 # undef p99_inline
501 # define p99_inline
502 #endif
503 
504 
505 # ifndef p00_instantiate
506 
514 # if p99_has_attribute(externally_visible)
515 # define p00_instantiate __attribute__((__externally_visible__)) extern __inline__
516 # else
517 # define p00_instantiate extern __inline__
518 # endif
519 # endif
520 
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)
525 #else
526 # define P00_WEAK1(ID) _Pragma(P99_STRINGIFY(weak ID))
527 #endif
528 
529 #if p99_has_attribute(weakref)
530 # define P00_WEAK2(ID, ...) __attribute__((__weakref__(#__VA_ARGS__)))
531 #else
532 # define P00_WEAK2(ID, ...) _Pragma(P99_STRINGIFY(weak ID=__VA_ARGS__))
533 #endif
534 
561 # define P99_WEAK(...) P99_IF_LT(P99_NARG(__VA_ARGS__), 2)(P00_WEAK1(__VA_ARGS__))(P00_WEAK2(__VA_ARGS__))
562 
563 #ifndef P99_TENTATIVE_CAUTION
564 # define P00_TENTATIVE_DEC(NAME) static
565 # define P00_TENTATIVE_DEF(NAME) static
566 #else
567 # define P00_TENTATIVE_DEC(NAME) P99_WEAK(NAME)
568 # define P00_TENTATIVE_DEF(NAME)
569 #endif
570 
587 # define P99_TENTATIVE_DEC(T, NAME) \
588 P00_TENTATIVE_DEC(NAME) T NAME
589 
590 # define P99_TENTATIVE_DEF(T, NAME) \
591 P00_TENTATIVE_DEF(NAME) T NAME
592 
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__))
600 #else
601 # undef P99_WARN_UNUSED_RESULT
602 # define P99_WARN_UNUSED_RESULT
603 #endif
604 
609 #if p99_has_attribute(pure)
610 # define P99_PURE_FUNCTION __attribute__((__pure__))
611 #else
612 # define P99_PURE_FUNCTION
613 #endif
614 
619 #if p99_has_extension(attribute_const)
620 # define P99_CONST_FUNCTION __attribute__((__const__))
621 #else
622 # define P99_CONST_FUNCTION
623 #endif
624 
625 #if p99_has_feature(setjmp_inline)
626 # define P99_SETJMP_INLINE(NAME) p99_inline
627 #else
628 # define P99_SETJMP_INLINE(NAME) P99_WEAK(NAME)
629 #endif
630 
631 
632 #ifndef P99_FIXED_REGISTER
633 # ifdef __GNUC__
634 # define P99_FIXED_REGISTER(REG) __asm__(P99_STRINGIFY(REG))
635 # else
636 
641 # define P99_FIXED_REGISTER(REG)
642 # endif
643 #endif
644 
645 
650 /* Now that feature test macros are set up we may check for the
651  library support. */
652 #include "p99_libc.h"
653 
654 
675 #ifndef static_assert
676 
692 # if p99_has_feature(c_static_assert)
693 # define static_assert _Static_assert
694 # else
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}) \
700 ]
701 extern char const p00_compiletime_assert[sizeof(void const*[2])];
702 # endif
703 #endif
704 
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
712 typedef __uint128_t p99x_uintmax;
713 typedef __int128_t p99x_intmax;
714 typedef __uint128_t p99x_uint128;
715 typedef __int128_t p99x_int128;
716 # endif
717 # endif
718 #endif
719 
728 #ifndef __alignof_is_defined
729 # define alignof _Alignof
730 # if !p99_has_feature(c_alignof)
731 # if p99_has_feature(gnu_alignof)
732 # ifndef _Alignof
733 # define _Alignof(T) __alignof__(T)
734 # endif
735 # else
736 # define _Alignof(T) offsetof(struct { char p00_c; T p00_t; }, p00_t)
737 # endif
738 # endif
739 #endif
740 
748 #ifndef __alignas_is_defined
749 # define alignas _Alignas
750 # if !p99_has_feature(c_alignas)
751 # if p99_has_attribute(aligned)
752 # ifndef _Alignas
753 # define _Alignas(X) __attribute__((__aligned__(X)))
754 # endif
755 # endif
756 # endif
757 #endif
758 
773 #if !p99_has_feature(c_max_align_t) && !p99_has_extension(c_max_align_t)
774 typedef union max_align_t max_align_t;
775 # ifndef P00_DOXYGEN
776 union max_align_t {
777  struct P99_PASTE2(p00_, __LINE__) {
778  unsigned P99_PASTE2(p00_, __LINE__);
779  } P99_PASTE2(p00_, __LINE__);
780  union max_align_t* P99_PASTE2(p00_, __LINE__);
781  void* P99_PASTE2(p00_, __LINE__);
782  void (*P99_PASTE2(p00_, __LINE__))(void);
783  _Bool P99_PASTE2(p00_, __LINE__);
784  char P99_PASTE2(p00_, __LINE__);
785  signed char P99_PASTE2(p00_, __LINE__);
786  unsigned char P99_PASTE2(p00_, __LINE__);
787  short int P99_PASTE2(p00_, __LINE__);
788  unsigned short int P99_PASTE2(p00_, __LINE__);
789  int P99_PASTE2(p00_, __LINE__);
790  unsigned int P99_PASTE2(p00_, __LINE__);
791  long int P99_PASTE2(p00_, __LINE__);
792  unsigned long int P99_PASTE2(p00_, __LINE__);
793  long long int P99_PASTE2(p00_, __LINE__);
794  unsigned long long int P99_PASTE2(p00_, __LINE__);
795  float P99_PASTE2(p00_, __LINE__);
796  double P99_PASTE2(p00_, __LINE__);
797  long double P99_PASTE2(p00_, __LINE__);
798 # ifndef __STDC_NO_COMPLEX__
799  float _Complex P99_PASTE2(p00_, __LINE__);
800  double _Complex P99_PASTE2(p00_, __LINE__);
801  long double _Complex P99_PASTE2(p00_, __LINE__);
802 # endif
803 # ifdef p99x_uint128
804  p99x_uint128 P99_PASTE2(p00_, __LINE__);
805 # endif
806 # ifdef UINT128_MAX
807  uint128_t P99_PASTE2(p00_, __LINE__);
808 # endif
809 }
810 # if p99_has_attribute(aligned)
811 __attribute__((__aligned__))
812 # endif
813 ;
814 # endif
815 #endif
816 
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
821 
822 #ifdef P00_DOXYGEN
823 
835 #define _Noreturn
836 
842 #define noreturn
843 
844 noreturn void p00_f(void);
845 static_assert(1);
846 
847 #elif !defined(noreturn)
848 # define noreturn _Noreturn
849 #endif
850 
851 #ifdef P00_DOXYGEN
852 #elif !p99_has_feature(c_noreturn)
853 # if p99_has_attribute(__noreturn__)
854 # ifndef _Noreturn
855 # define _Noreturn __attribute__((__noreturn__))
856 # endif
857 # elif p99_has_feature(pragma_noreturn)
858 # define _Noreturn _Pragma(NORETURN)
859 # else
860 # define _Noreturn /* noreturn feature is not implemented */
861 # endif
862 #endif
863 
864 /* Patch a flaw in OS X. They use __attribute__((noreturn)) which
865  explodes if noreturn is defined. */
866 #ifdef __APPLE__
867 # undef __dead2
868 # define __dead2 __attribute__((__noreturn__))
869 #endif
870 
871 #ifdef P00_DOXYGEN
872 
879 # define _Thread_local
880 
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)
894 # endif
895 #endif
896 
897 static_assert(1, "test of static assertions");
898 
913 #define P00_HARMLESS_SIZEOF(ID) sizeof(sizeof(ID))
914 
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__))
919 #else
920 # define P00_UNUSED(EXPR) \
921  extern char const p00_harmless_declaration \
922  [P00_HARMLESS_SIZEOF(EXPR)]
923 #endif
924 
925 /* Used inside P99_MACRO_END. The idea that this is an extern
926  declaration, so it doesn't result in any code. On the other hand it
927  uses the address of itself in its own declaration, so the compiler
928  shouldn't issue a warning about an unused variable. */
929 #define P00_HARMLESS_DECLARATION P00_UNUSED(p00_harmless_declaration)
930 
931 /* To be able to refer to it in a sizeof expression this must be
932  forward declared. */
933 P00_UNUSED(1);
934 
941 #define P99_MACRO_END(...) \
942 extern void P99_PASTE(p00_harmless_declaration_, __VA_ARGS__)(void)
943 
944 
957 #if p99_has_feature(openmp)
958 #define P99_PARALLEL_PRAGMA omp parallel for
959 #else
960 #define P99_PARALLEL_PRAGMA
961 #endif
962 
973 #if p99_has_builtin(__builtin_expect)
974 # define P99_EXPECT(EXP, VAL) __builtin_expect((EXP), (VAL))
975 #else
976 # define P99_EXPECT(EXP, VAL) (EXP)
977 #endif
978 
993 #ifndef P99_UNLIKELY
994 # define P99_UNLIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 0)
995 #endif
996 
1009 #ifndef P99_LIKELY
1010 # define P99_LIKELY(...) P99_EXPECT(!!(__VA_ARGS__), 1)
1011 #endif
1012 
1013 
1018 #if p99_has_attribute(deprecated)
1019 # define P99_DEPRECATED(...) __attribute__((__deprecated__))
1020 #else
1021 # define P99_DEPRECATED(...)
1022 #endif
1023 
1031 #ifndef P99_ATLEAST
1032 # define P99_ATLEAST static
1033 #endif
1034 
1035 
1051 P00_DOCUMENT_TYPE_ARGUMENT(P99_VECTOR, 0)
1052 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_VECTOR, 1)
1053 P00_DOCUMENT_NUMBER_ARGUMENT(P99_VECTOR, 2)
1054 #if p99_has_attribute(vector_size)
1055 # define P99_VECTOR(T, NAME, N) T NAME __attribute__((vector_size(sizeof(T)*(N))))
1056 #else
1057 # define P99_VECTOR(T, NAME, N) _Alignas(sizeof(T)*(N)) T NAME[N]
1058 #endif
1059 
1065 #define P99_IF_COMPILER(COMP, ...) P00_COMPILER_PRAGMA_ ## COMP(P99_STRINGIFY(__VA_ARGS__))
1066 
1067 #ifndef P00_DOXYGEN
1068 
1069 /* Disable bogus warnings that are provoked by the code in this file. */
1070 
1071 P99_IF_COMPILER(INTEL, warning(disable: 1418)) /* external function definition with no prior declaration */
1072 P99_IF_COMPILER(INTEL, warning(disable: 1419)) /* external declaration in primary source file */
1073 P99_IF_COMPILER(INTEL, warning(disable: 557)) /* pointless comparison of unsigned integer with a negative constant */
1074 P99_IF_COMPILER(INTEL, warning(disable: 283)) /* duplicate specifier in declaration */
1075 
1076 /* Warnings on initializers are a plague. They are responsible for the
1077  fact that many people don't use default initializers where they
1078  could and should. Shame on gcc and Co that they enable this with
1079  -Wall. */
1080 
1081 P99_IF_COMPILER(GNU, GCC diagnostic ignored "-Wmissing-braces")
1082 P99_IF_COMPILER(GNU, GCC diagnostic ignored "-Wmissing-field-initializers")
1083 P99_IF_COMPILER(GNU, GCC diagnostic ignored "-Wswitch-bool")
1084 
1085 P99_IF_COMPILER(OPEN64, GCC diagnostic ignored "-Wmissing-braces")
1086 P99_IF_COMPILER(OPEN64, GCC diagnostic ignored "-Wmissing-field-initializers")
1087 
1088 /* clang warns about features that are completely ok. */
1089 P99_IF_COMPILER(CLANG, GCC diagnostic ignored "-Wnon-literal-null-conversion")
1090 P99_IF_COMPILER(CLANG, GCC diagnostic ignored "-Wswitch-bool")
1091 
1092 
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)
1113 #endif
1114 
1115 #ifndef P99_WARN_INIT_PUSH
1116 # define P99_WARN_INIT_PUSH
1117 #endif
1118 
1119 #ifndef P99_WARN_INIT_POP
1120 # define P99_WARN_INIT_POP
1121 #endif
1122 
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)
1142 #endif
1143 
1144 #ifndef P99_WARN_REDUNDANT_DECLS_PUSH
1145 # define P99_WARN_REDUNDANT_DECLS_PUSH
1146 #endif
1147 
1148 #ifndef P99_WARN_REDUNDANT_DECLS_POP
1149 # define P99_WARN_REDUNDANT_DECLS_POP
1150 #endif
1151 
1152 #endif
1153 
1161 #endif
void
void void
Definition: p99_bitset.h:84
p99_args.h
Providing macros that handle variadic macro argument lists.
noreturn
#define noreturn
Declare a function that doesn't return to the caller.
Definition: p99_compiler.h:842
p99_libc.h
Group C library dependencies together in one file.
static_assert
#define static_assert(EXPR, DIAGSTR)
Evaluate expression EXPR at compile time and ensure that it is fulfilled.
Definition: p99_compiler.h:695
P99_PASTE2
#define P99_PASTE2(_1, _2)
Paste two token sequences at their junction.
Definition: p99_paste.h:82
p99x_intmax
intmax_t p99x_intmax
A signed integer type of maximal width that exceeds the C99 specifications.
Definition: p99_int.h:134
p99x_uintmax
uintmax_t p99x_uintmax
An unsigned integer type of maximal width that exceeds the C99 specifications.
Definition: p99_int.h:118
P99_IF_COMPILER
#define P99_IF_COMPILER(COMP,...)
Issue the pragma that is given as a supplementary argument iff the actual compiler is COMP.
Definition: p99_compiler.h:1065
max_align_t
union max_align_t max_align_t
A type with the maximum alignment among the standard types.
Definition: p99_compiler.h:774
P99_VECTOR
#define P99_VECTOR(T, NAME, N)
A wrapper for vector type extensions.
Definition: p99_compiler.h:1057
p99x_uint128
extendedInt p99x_uint128
An unsigned integer type of width 128 that exceeds the C99 specifications.
Definition: p99_int.h:149
p99x_int128
extendedInt p99x_int128
A signed integer type of width 128 that exceeds the C99 specifications.
Definition: p99_int.h:162