Actual source code: petscmacros.h
1: #ifndef PETSC_PREPROCESSOR_MACROS_H
2: #define PETSC_PREPROCESSOR_MACROS_H
4: #include <petscconf.h>
5: #include <petscconf_poison.h> /* for PetscDefined() error checking */
7: /* SUBMANSEC = Sys */
9: #if defined(__cplusplus)
10: #if __cplusplus <= 201103L
11: #define PETSC_CPP_VERSION 11
12: #elif __cplusplus <= 201402L
13: #define PETSC_CPP_VERSION 14
14: #elif __cplusplus <= 201703L
15: #define PETSC_CPP_VERSION 17
16: #elif __cplusplus <= 202002L
17: #define PETSC_CPP_VERSION 20
18: #else
19: #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
20: #endif
21: #endif // __cplusplus
23: #ifndef PETSC_CPP_VERSION
24: #define PETSC_CPP_VERSION 0
25: #endif
27: #if defined(__STDC_VERSION__)
28: #if __STDC_VERSION__ <= 199901L
29: // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
30: #define PETSC_C_VERSION 9
31: #elif __STDC_VERSION__ <= 201112L
32: #define PETSC_C_VERSION 11
33: #elif __STDC_VERSION__ <= 201710L
34: #define PETSC_C_VERSION 17
35: #else
36: #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
37: #endif
38: #endif // __STDC_VERSION__
40: #ifndef PETSC_C_VERSION
41: #define PETSC_C_VERSION 0
42: #endif
44: /* ========================================================================== */
45: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
46: #if defined(__cplusplus)
47: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
48: #else
49: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
50: #endif
52: /* ========================================================================== */
53: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
54: * files within extern "C". This will generate a compiler error if a user does put the include
55: * file within an extern "C".
56: */
57: #if defined(__cplusplus)
58: void assert_never_put_petsc_headers_inside_an_extern_c(int);
59: void assert_never_put_petsc_headers_inside_an_extern_c(double);
60: #endif
62: #if defined(__cplusplus)
63: #define PETSC_RESTRICT PETSC_CXX_RESTRICT
64: #else
65: #define PETSC_RESTRICT restrict
66: #endif
68: #define PETSC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline
69: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline
71: #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
72: #define __declspec(dllexport)
73: #define PETSC_DLLIMPORT __declspec(dllimport)
74: #define PETSC_VISIBILITY_INTERNAL
75: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
76: #define __attribute__((visibility("default")))
77: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
78: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
79: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
80: #define __attribute__((visibility("default")))
81: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
82: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
83: #else
84: #define
85: #define PETSC_DLLIMPORT
86: #define PETSC_VISIBILITY_INTERNAL
87: #endif
89: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
90: #define PETSC_VISIBILITY_PUBLIC
91: #else /* Win32 users need this to import symbols from petsc.dll */
92: #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
93: #endif
95: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
96: * compiled with C++ so they may be used from C and are always visible in the shared libraries
97: */
98: #if defined(__cplusplus)
99: #define PETSC_EXTERN extern "C" PETSC_VISIBILITY_PUBLIC
100: #define PETSC_EXTERN_TYPEDEF extern "C"
101: #define PETSC_INTERN extern "C" PETSC_VISIBILITY_INTERNAL
102: #else
103: #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
104: #define PETSC_EXTERN_TYPEDEF
105: #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
106: #endif
108: #if defined(PETSC_USE_SINGLE_LIBRARY)
109: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110: #else
111: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
112: #endif
116: #endif
118: /*MC
119: PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
121: Synopsis:
122: #include <petscmacros.h>
123: int PetscHasAttribute(name)
125: Input Parameter:
126: . name - The name of the attribute to test
128: Notes:
129: name should be identical to what you might pass to the __attribute__ declaration itself --
130: plain, unbroken text.
132: As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
133: exact type and value returned is implementation defined. In practice however, it usually
134: returns `1` if the attribute is supported and `0` if the attribute is not supported.
136: Example Usage:
137: Typical usage is using the preprocessor
139: .vb
140: #if PetscHasAttribute(always_inline)
141: # define MY_ALWAYS_INLINE __attribute__((always_inline))
142: #else
143: # define MY_ALWAYS_INLINE
144: #endif
146: void foo(void) MY_ALWAYS_INLINE;
147: .ve
149: but it can also be used in regular code
151: .vb
152: if (PetscHasAttribute(some_attribute)) {
153: foo();
154: } else {
155: bar();
156: }
157: .ve
159: Level: intermediate
161: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
162: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
163: M*/
166: #endif
167: #define PetscHasAttribute(name) __has_attribute(name)
169: /*MC
170: PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
172: Synopsis:
173: #include <petscmacros.h>
174: int PetscHasBuiltin(name)
176: Input Parameter:
177: . name - the name of the builtin routine
179: Notes:
180: Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
181: (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
182: detector is itself is a compiler extension with implementation-defined return type and
183: semantics. Some compilers implement it as a macro, others as a compiler function. In practice
184: however, all supporting compilers return an integer boolean as described.
186: Example Usage:
187: Typical usage is in preprocessor directives
189: .vb
190: #if PetscHasBuiltin(__builtin_trap)
191: __builtin_trap();
192: #else
193: abort();
194: #endif
195: .ve
197: But it may also be used in regular code
199: .vb
200: if (PetscHasBuiltin(__builtin_alloca)) {
201: foo();
202: } else {
203: bar();
204: }
205: .ve
207: Level: intermediate
209: .seealso: `PetscHasAttribute()`, `PetscAssume()`
210: M*/
213: #endif
214: // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
215: // __builtin_types_compatible_p which take types or other non-functiony things as
216: // arguments. The correct way to detect these then is to use __is_identifier (also a clang
217: // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
218: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
219: #define PetscHasBuiltin(name) __is_identifier(name)
220: #else
221: #define PetscHasBuiltin(name) __has_builtin(name)
222: #endif
224: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
225: /*
226: Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
227: This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
228: does not match the actual type of the argument being passed in
229: */
230: #if PetscHasAttribute(pointer_with_type_tag)
231: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
232: #endif
234: #if PetscHasAttribute(type_tag_for_datatype)
235: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type) __attribute__((type_tag_for_datatype(MPI, type)))
236: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
237: #endif
238: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
240: #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
241: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
242: #endif
244: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
245: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
246: #endif
248: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
249: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
250: #endif
252: /*MC
253: PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
254: as format specifiers and checked for validity
256: Synopsis:
257: #include <petscmacros.h>
258: <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
260: Input Parameters:
261: + strIdx - The (1-indexed) location of the format string in the argument list
262: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
264: Level: developer
266: Notes:
267: This function attribute causes the compiler to issue warnings when the format specifier does
268: not match the type of the variable that will be formatted, or when there exists a mismatch
269: between the number of format specifiers and variables to be formatted. It is safe to use this
270: macro if your compiler does not support format specifier checking (though this is
271: exceeedingly rare).
273: Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
274: same value.
276: The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
277: the argument list, that is, there is no way to indicate gaps which should not be checked.
279: Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
280: header files. In this case the macro will expand empty.
282: Example Usage:
283: .vb
284: // format string is 2nd argument, variable argument list containing args is 3rd argument
285: void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
287: int x = 1;
288: double y = 50.0;
290: my_printf(NULL,"%g",x); // WARNING, format specifier does not match for 'int'!
291: my_printf(NULL,"%d",x,y); // WARNING, more arguments than format specifiers!
292: my_printf(NULL,"%d %g",x,y); // OK
293: .ve
295: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
296: M*/
297: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
298: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
299: #else
300: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
301: #endif
303: /*MC
304: PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
305: executed
307: Level: intermediate
309: Notes:
310: The marked function is often optimized for size rather than speed and may be grouped alongside
311: other equally frigid routines improving code locality of lukewarm or hotter parts of program.
313: The paths leading to cold functions are usually automatically marked as unlikely by the
314: compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
315: as error handlers -- as cold to improve optimization of the surrounding temperate functions.
317: Example Usage:
318: .vb
319: void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
321: if (temperature < 0) {
322: return my_error_handler(...); // chilly!
323: }
324: .ve
326: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
327: `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
328: M*/
329: #if PetscHasAttribute(__cold__)
330: #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
331: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
332: #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
333: #else
334: #define PETSC_ATTRIBUTE_COLD
335: #endif
337: /*MC
338: PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
339: subjected to type-based alias analysis, but is instead assumed to be able to
340: alias any other type of objects
342: Example Usage:
343: .vb
344: typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
346: PetscReal *pointer;
347: PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
348: .ve
350: Level: advanced
352: .seealso: `PetscHasAttribute()`
353: M*/
354: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
355: #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
356: #else
357: #define PETSC_ATTRIBUTE_MAY_ALIAS
358: #endif
360: /*MC
361: PETSC_NULLPTR - Standard way of indicating a null value or pointer
363: No Fortran Support
365: Level: beginner
367: Notes:
368: Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
369: interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
370: equivalent to setting the same pointer to `NULL` in C. That is to say that the following
371: expressions are equivalent\:
373: .vb
374: ptr == PETSC_NULLPTR
375: ptr == NULL
376: ptr == 0
377: !ptr
379: ptr = PETSC_NULLPTR
380: ptr = NULL
381: ptr = 0
382: .ve
384: and for completeness' sake\:
386: .vb
387: PETSC_NULLPTR == NULL
388: .ve
390: Example Usage:
391: .vb
392: // may be used in place of '\0' or other such teminators in the definition of char arrays
393: const char *const MyEnumTypes[] = {
394: "foo",
395: "bar",
396: PETSC_NULLPTR
397: };
399: // may be used to nullify objects
400: PetscObject obj = PETSC_NULLPTR;
402: // may be used in any function expecting NULL
403: PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
404: .ve
406: Developer Notes:
407: `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
408: files compiled with a C++ compiler may lead to unexpected side-effects in function overload
409: resolution and/or compiler warnings.
411: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
412: M*/
414: /*MC
415: PETSC_CONSTEXPR_14 - C++14 constexpr
417: No Fortran Support
419: Level: beginner
421: Notes:
422: Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
423: if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
424: that this cannot be used in cases where an empty expansion would result in invalid code. It
425: is safe to use this in C source files.
427: Example Usage:
428: .vb
429: PETSC_CONSTEXPR_14 int factorial(int n)
430: {
431: int r = 1;
433: do {
434: r *= n;
435: } while (--n);
436: return r;
437: }
438: .ve
440: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
441: M*/
443: /*MC
444: PETSC_NODISCARD - Mark the return value of a function as non-discardable
446: Not available in Fortran
448: Level: beginner
450: Notes:
451: Hints to the compiler that the return value of a function must be captured. A diagnostic may
452: (but is not required to) be emitted if the value is discarded. It is safe to use this in both
453: C and C++ source files.
455: In this context "captured" means assigning the return value of a function to a named
456: variable or casting it to `void`. Between the two, assigning to a named variable is the most
457: portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
458: `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
459: `void`.
461: Example Usage:
462: .vb
463: class Foo
464: {
465: int x;
467: public:
468: PETSC_NODISCARD Foo(int y) : x(y) { }
469: };
471: PETSC_NODISCARD int factorial(int n)
472: {
473: return n <= 1 ? 1 : (n * factorial(n - 1));
474: }
476: factorial(10); // Warning: ignoring return value of function declared 'nodiscard'
477: auto x = factorial(10); // OK, capturing return value
478: (void)factorial(10); // Maybe OK, casting to void
479: auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
480: (void)y; // set-but-not-used warnings)
482: Foo(x); // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
483: auto f = Foo(x); // OK, capturing constructed object
484: (void)Foo(x); // Maybe OK, casting to void
485: auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
486: (void)g; // warnings)
487: .ve
489: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
490: M*/
492: /* C++11 features */
493: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
494: #define PETSC_NULLPTR nullptr
495: #else
496: #define PETSC_NULLPTR NULL
497: #endif
499: /* C++14 features */
500: #if PETSC_CPP_VERSION >= 14
501: #define PETSC_CONSTEXPR_14 constexpr
502: #else
503: #define PETSC_CONSTEXPR_14
504: #endif
506: /* C++17 features */
507: #if PETSC_CPP_VERSION >= 17
508: #define PETSC_CONSTEXPR_17 constexpr
509: #else
510: #define PETSC_CONSTEXPR_17
511: #endif
513: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
514: #define PETSC_NODISCARD [[nodiscard]]
515: #elif PetscHasAttribute(warn_unused_result)
516: #define PETSC_NODISCARD __attribute__((warn_unused_result))
517: #else
518: #define PETSC_NODISCARD
519: #endif
521: #include <petscversion.h>
522: #define PETSC_AUTHOR_INFO " The PETSc Team\n petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
524: /* designated initializers since C99 and C++20, MSVC never supports them though */
525: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
526: #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
527: #else
528: #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
529: #endif
531: /*MC
532: PetscUnlikely - Hints the compiler that the given condition is usually false
534: Synopsis:
535: #include <petscmacros.h>
536: bool PetscUnlikely(bool cond)
538: Not Collective; No Fortran Support
540: Input Parameter:
541: . cond - Boolean expression
543: Level: advanced
545: Notes:
546: This returns the same truth value, it is only a hint to compilers that the result of cond is
547: unlikely to be true.
549: Example usage:
550: .vb
551: if (PetscUnlikely(cond)) {
552: foo(); // cold path
553: } else {
554: bar(); // hot path
555: }
556: .ve
558: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
559: `PETSC_ATTRIBUTE_COLD`
560: M*/
562: /*MC
563: PetscLikely - Hints the compiler that the given condition is usually true
565: Synopsis:
566: #include <petscmacros.h>
567: bool PetscLikely(bool cond)
569: Not Collective; No Fortran Support
571: Input Parameter:
572: . cond - Boolean expression
574: Level: advanced
576: Notes:
577: This returns the same truth value, it is only a hint to compilers that the result of cond is
578: likely to be true.
580: Example usage:
581: .vb
582: if (PetscLikely(cond)) {
583: foo(); // hot path
584: } else {
585: bar(); // cold path
586: }
587: .ve
589: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
590: `PETSC_ATTRIBUTE_COLD`
591: M*/
592: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
593: #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
594: #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
595: #else
596: #define PetscUnlikely(cond) (cond)
597: #define PetscLikely(cond) (cond)
598: #endif
600: /*MC
601: PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
603: Synopsis:
604: #include <petscmacros.h>
605: void PetscUnreachable(void)
607: Level: advanced
609: Notes:
610: Indicates to the compiler (usually via some built-in) that a particular code path is always
611: unreachable. Behavior is undefined if this function is ever executed, the user can expect an
612: unceremonious crash.
614: Example usage:
615: Useful in situations such as switches over enums where not all enumeration values are
616: explicitly covered by the switch
618: .vb
619: typedef enum {RED, GREEN, BLUE} Color;
621: int foo(Color c)
622: {
623: // it is known to programmer (or checked previously) that c is either RED or GREEN
624: // but compiler may not be able to deduce this and/or emit spurious warnings
625: switch (c) {
626: case RED:
627: return bar();
628: case GREEN:
629: return baz();
630: default:
631: PetscUnreachable(); // program is ill-formed if executed
632: }
633: }
634: .ve
636: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
637: M*/
638: #if PETSC_CPP_VERSION >= 23
639: #include <utility>
640: #define PetscUnreachable() std::unreachable()
641: #elif defined(__GNUC__)
642: /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
643: #define PetscUnreachable() __builtin_unreachable()
644: #elif defined(_MSC_VER) /* MSVC */
645: #define PetscUnreachable() __assume(0)
646: #else /* ??? */
647: #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
648: #endif
650: /*MC
651: PetscAssume - Indicate to the compiler a condition that is defined to be true
653: Synopsis:
654: #include <petscmacros.h>
655: void PetscAssume(bool cond)
657: Input Parameter:
658: . cond - Boolean expression
660: Level: advanced
662: Notes:
663: If supported by the compiler, `cond` is used to inform the optimizer of an invariant
664: truth. The argument itself is never evaluated, so any side effects of the expression will be
665: discarded. This macro is used in `PetscAssert()` to retain information gained from debug
666: checks that would be lost in optimized builds. For example\:
668: .vb
669: PetscErrorCode foo(PetscInt x) {
671: PetscAssert(x >= 0, ...);
672: }
673: .ve
675: The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
676: if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
677: when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
678: optimizer cannot deduce any information from them.
680: Due to compiler limitations `PetscAssume()` works best when `cond` involves
681: constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
683: .vb
684: int a, b, var_five;
686: // BEST, all supporting compilers will understand a cannot be >= 5
687: PetscAssume(a < 5);
689: // OK, some compilers may understand that a cannot be >= 5
690: PetscAssume(a <= b && b < 5);
692: // WORST, most compilers will not get the memo
693: PetscAssume(a <= b && b < var_five);
694: .ve
696: If the condition is violated at runtime then behavior is wholly undefined. If the
697: condition is violated at compile-time, the condition "supersedes" the compile-time violation
698: and the program is ill-formed, no diagnostic required. For example consider the following\:
700: .vb
701: PetscInt x = 0;
703: PetscAssume(x != 0);
704: if (x == 0) {
705: x += 10;
706: } else {
707: popen("rm -rf /", "w");
708: }
709: .ve
711: Even though `x` is demonstrably `0` the compiler may opt to\:
713: - emit an unconditional `popen("rm -rf /", "w")`
714: - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
715: - reformat the primary disk partition
717: .seealso: `PetscAssert()`
718: M*/
719: #if PETSC_CPP_VERSION >= 23
720: #define PetscAssume(...) [[assume(__VA_ARGS__)]]
721: #elif defined(_MSC_VER) // msvc
722: #define PetscAssume(...) __assume(__VA_ARGS__)
723: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
724: #define PetscAssume(...) \
725: do { \
726: _Pragma("clang diagnostic push"); \
727: _Pragma("clang diagnostic ignored \"-Wassume\""); \
728: __builtin_assume(__VA_ARGS__); \
729: _Pragma("clang diagnostic pop"); \
730: } while (0)
731: #else // gcc (and really old clang)
732: // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
733: //
734: // if (PetscUnlikely(!cond)) PetscUnreachable();
735: //
736: // but this it unsavory because the side effects of cond are not guaranteed to be
737: // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
738: // for which cond is false would be undefined results in undefined behavior anyway) it cannot
739: // always do so. This is especially the case for opaque or non-inline function calls:
740: //
741: // extern int bar(int);
742: //
743: // int foo(int x) {
744: // PetscAssume(bar(x) == 2);
745: // if (bar(x) == 2) {
746: // return 1;
747: // } else {
748: // return 0;
749: // }
750: // }
751: //
752: // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
753: // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
754: #define PetscAssume(...) \
755: do { \
756: if (0 && (__VA_ARGS__)) PetscUnreachable(); \
757: } while (0)
758: #endif
760: /*MC
761: PetscExpand - Expand macro argument
763: Synopsis:
764: #include <petscmacros.h>
765: <macro-expansion> PetscExpand(x)
767: Input Parameter:
768: . x - The preprocessor token to expand
770: Level: beginner
772: .seealso: `PetscStringize()`, `PetscConcat()`
773: M*/
774: #define PetscExpand_(...) __VA_ARGS__
775: #define PetscExpand(...) PetscExpand_(__VA_ARGS__)
777: /*MC
778: PetscStringize - Stringize a token
780: Synopsis:
781: #include <petscmacros.h>
782: const char* PetscStringize(x)
784: No Fortran Support
786: Input Parameter:
787: . x - The token you would like to stringize
789: Output Parameter:
790: . <return-value> - The string representation of `x`
792: Level: beginner
794: Note:
795: `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
796: `PetscStringize_()` instead.
798: Example Usage:
799: .vb
800: #define MY_OTHER_VAR hello there
801: #define MY_VAR MY_OTHER_VAR
803: PetscStringize(MY_VAR) -> "hello there"
804: PetscStringize_(MY_VAR) -> "MY_VAR"
806: int foo;
807: PetscStringize(foo) -> "foo"
808: PetscStringize_(foo) -> "foo"
809: .ve
811: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
812: M*/
813: #define PetscStringize_(...) #__VA_ARGS__
814: #define PetscStringize(...) PetscStringize_(__VA_ARGS__)
816: /*MC
817: PetscConcat - Concatenate two tokens
819: Synopsis:
820: #include <petscmacros.h>
821: <macro-expansion> PetscConcat(x, y)
823: No Fortran Support
825: Input Parameters:
826: + x - First token
827: - y - Second token
829: Level: beginner
831: Note:
832: `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
833: if you don't want to expand them.
835: Example usage:
836: .vb
837: PetscConcat(hello,there) -> hellothere
839: #define HELLO hello
840: PetscConcat(HELLO,there) -> hellothere
841: PetscConcat_(HELLO,there) -> HELLOthere
842: .ve
844: .seealso: `PetscStringize()`, `PetscExpand()`
845: M*/
846: #define PetscConcat_(x, y) x##y
847: #define PetscConcat(x, y) PetscConcat_(x, y)
849: #define PETSC_INTERNAL_COMPL_0 1
850: #define PETSC_INTERNAL_COMPL_1 0
852: /*MC
853: PetscCompl - Expands to the integer complement of its argument
855: Synopsis:
856: #include <petscmacros.h>
857: int PetscCompl(b)
859: No Fortran Support
861: Input Parameter:
862: . b - Preprocessor variable, must expand to either integer literal 0 or 1
864: Output Parameter:
865: . <return-value> - Either integer literal 0 or 1
867: Level: beginner
869: Notes:
870: Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
871: 0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
872: argument before returning the complement.
874: This macro can be useful for negating `PetscDefined()` inside macros e.g.
876: $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
878: Example usage:
879: .vb
880: #define MY_VAR 1
881: PetscCompl(MY_VAR) -> 0
883: #undef MY_VAR
884: #define MY_VAR 0
885: PetscCompl(MY_VAR) -> 1
886: .ve
888: .seealso: `PetscConcat()`, `PetscDefined()`
889: M*/
890: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
892: /*MC
893: PetscDefined - Determine whether a boolean macro is defined
895: Synopsis:
896: #include <petscmacros.h>
897: int PetscDefined(def)
899: No Fortran Support
901: Input Parameter:
902: . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
904: Output Parameter:
905: . <return-value> - Either integer literal 0 or 1
907: Level: intermediate
909: Notes:
910: `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
911: integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
912: this macro should not be used if its argument may be defined to a non-empty value other than
913: 1.
915: The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
916: add custom checks in user code, one should use `PetscDefined_()`.
918: $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
920: Developer Notes:
921: Getting something that works in C and CPP for an arg that may or may not be defined is
922: tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
923: insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
924: the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
925: and when the last step cherry picks the 2nd arg, we get a zero.
927: Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
928: nonconforming implementation of variadic macros.
930: Example Usage:
931: Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
932: is defined then
934: .vb
935: #if PetscDefined(USE_DEBUG)
936: foo();
937: #else
938: bar();
939: #endif
941: // or alternatively within normal code
942: if (PetscDefined(USE_DEBUG)) {
943: foo();
944: } else {
945: bar();
946: }
947: .ve
949: is equivalent to
951: .vb
952: #if defined(PETSC_USE_DEBUG)
953: # if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
954: foo();
955: # elif PETSC_USE_DEBUG == 1
956: foo();
957: # else
958: bar();
959: # endif
960: #else
961: bar();
962: #endif
963: .ve
965: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
966: `PetscExpandToNothing()`, `PetscCompl()`
967: M*/
968: #define PetscDefined_arg_1 shift,
969: #define PetscDefined_arg_ shift,
970: #define PetscDefined__take_second_expanded(ignored, val, ...) val
971: #define PetscDefined__take_second_expand(args) PetscDefined__take_second_expanded args
972: #define PetscDefined__take_second(...) PetscDefined__take_second_expand((__VA_ARGS__))
973: #define PetscDefined__(arg1_or_junk) PetscDefined__take_second(arg1_or_junk 1, 0, at_)
974: #define PetscDefined_(value) PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
975: #define PetscDefined(def) PetscDefined_(PetscConcat(PETSC_, def))
977: /*MC
978: PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
979: the check in optimized mode
981: Synopsis:
982: #include <petscmacros.h>
983: bool PetscUnlikelyDebug(bool cond)
985: No Fortran Support
987: Not Collective
989: Input Parameter:
990: . cond - Boolean expression
992: Level: advanced
994: Note:
995: This returns the same truth value, it is only a hint to compilers that the result of `cond` is
996: likely to be false. When PETSc is compiled in optimized mode this will always return
997: false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
998: optimized mode.
1000: Example usage:
1001: This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1002: is true. So
1004: .vb
1005: if (PetscUnlikelyDebug(cond)) {
1006: foo();
1007: } else {
1008: bar();
1009: }
1010: .ve
1012: is equivalent to
1014: .vb
1015: if (PetscDefined(USE_DEBUG)) {
1016: if (PetscUnlikely(cond)) {
1017: foo();
1018: } else {
1019: bar();
1020: }
1021: } else {
1022: bar();
1023: }
1024: .ve
1026: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1027: M*/
1028: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1030: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1031: // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1032: // not what ISO C allows
1033: #define PetscMacroReturns_(retexpr, ...) \
1034: __extension__({ \
1035: __VA_ARGS__; \
1036: retexpr; \
1037: })
1038: #else
1039: #define PetscMacroReturns_(retexpr, ...) \
1040: retexpr; \
1041: do { \
1042: __VA_ARGS__; \
1043: } while (0)
1044: #endif
1046: /*MC
1047: PetscExpandToNothing - Expands to absolutely nothing
1049: Synopsis:
1050: #include <petscmacros.h>
1051: void PetscExpandToNothing(...)
1053: No Fortran Support
1055: Input Parameter:
1056: . __VA_ARGS__ - Anything at all
1058: Level: beginner
1060: Note:
1061: Must have at least 1 parameter.
1063: Example usage:
1064: .vb
1065: PetscExpandToNothing(a,b,c) -> *nothing*
1066: .ve
1068: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1069: M*/
1070: #define PetscExpandToNothing(...)
1072: /*MC
1073: PetscMacroReturns - Define a macro body that returns a value
1075: Synopsis:
1076: #include <petscmacros.h>
1077: return_type PetscMacroReturns(return_type retexpr, ...)
1079: Input Parameters:
1080: + retexpr - The value or expression that the macro should return
1081: - __VA_ARGS__ - The body of the macro
1083: Level: intermediate
1085: Notes:
1086: Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1087: body of the macro and should not depend on values produced as a result of the expression. The
1088: user should not assume that the result of this macro is equivalent to a single logical source
1089: line. It is not portable to use macros defined using this one in conditional or loop bodies
1090: without enclosing them in curly braces\:
1092: .vb
1093: #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1095: int err,x = 10;
1097: if (...) err = FOO(x); // ERROR, body of FOO() executed outside the if statement
1098: if (...) { err = FOO(x); } // OK
1100: for (...) err = FOO(x); // ERROR, body of FOO() executed outside the loop
1101: for (...) { err = FOO(x); } // OK
1102: .ve
1104: It is also not portable to use this macro directly inside function call, conditional, loop,
1105: or switch statements\:
1107: .vb
1108: extern void bar(int);
1110: int ret = FOO(x);
1112: bar(FOO(x)); // ERROR, may not compile
1113: bar(ret); // OK
1115: if (FOO(x)) // ERROR, may not compile
1116: if (ret) // OK
1117: .ve
1119: Example usage:
1120: .vb
1121: #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1123: int x = 10;
1124: int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1126: // multiline macros allowed, but must declare with line continuation as usual
1127: #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1128: if (arg1 > 10) { \
1129: puts("big int!"); \
1130: } else { \
1131: return 7355608; \
1132: } \
1133: )
1135: // if retexpr contains commas, must enclose it with braces
1136: #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1137: #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1139: int x = 10;
1140: int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1141: int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1142: .ve
1144: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1145: M*/
1146: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1148: #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1150: /*MC
1151: PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1153: Synopsis:
1154: #include <petscmacros.h>
1155: size_t PETSC_STATIC_ARRAY_LENGTH(a)
1157: Input Parameter:
1158: . a - a static array of any type
1160: Output Parameter:
1161: . <return-value> - the length of the array
1163: Example:
1164: .vb
1165: PetscInt a[22];
1166: size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1167: .ve
1168: `sa` will have a value of 22
1170: Level: intermediate
1171: M*/
1172: #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
1174: /*
1175: These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1177: Example usage:
1179: #define mymacro(obj,...) {
1180: PETSC_FIRST_ARG((__VA_ARGS__,unused));
1181: f(22 PETSC_REST_ARG(__VA_ARGS__));
1182: }
1184: Note you add a dummy extra argument to __VA_ARGS__ and enclose them in an extra set of () for PETSC_FIRST_ARG() and PETSC_REST_ARG(__VA_ARGS__) automatically adds a leading comma only if there are additional arguments
1186: Reference:
1187: https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1188: */
1189: #define PETSC_FIRST_ARG_(N, ...) N
1190: #define PETSC_FIRST_ARG(args) PETSC_FIRST_ARG_ args
1191: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1192: #define PETSC_NUM(...) PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1193: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1194: #define PETSC_REST_HELPER_ONE(first)
1195: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1196: #define PETSC_REST_HELPER(qty, ...) PETSC_REST_HELPER2(qty, __VA_ARGS__)
1197: #define PETSC_REST_ARG(...) PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1199: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1200: _Pragma(PetscStringize(name diagnostic push)) \
1201: _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
1203: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
1205: #if defined(__clang__)
1206: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1207: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1208: #elif defined(__GNUC__) || defined(__GNUG__)
1209: // gcc >= 4.6.0
1210: #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1211: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1212: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1213: #endif
1214: #endif
1216: #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
1217: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1218: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1219: // only undefine these if they are not used
1220: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1221: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1222: #endif
1224: /* OpenMP support */
1225: #if defined(_OPENMP)
1226: #if defined(_MSC_VER)
1227: #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1228: #else
1229: #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1230: #endif
1231: #endif
1233: #ifndef PetscPragmaOMP
1234: #define PetscPragmaOMP(...)
1235: #endif
1237: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1238: #if defined(__NEC__)
1239: #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1240: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1241: #define PetscPragmaSIMD _Pragma("vector")
1242: #elif defined(__GNUC__)
1243: #if __GNUC__ >= 5 && !defined(__PGI)
1244: #define PetscPragmaSIMD _Pragma("GCC ivdep")
1245: #endif
1246: #elif defined(_OPENMP) && _OPENMP >= 201307
1247: #define PetscPragmaSIMD PetscPragmaOMP(simd)
1248: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1249: #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1250: #endif
1252: #ifndef PetscPragmaSIMD
1253: #define PetscPragmaSIMD
1254: #endif
1256: #endif /* PETSC_PREPROCESSOR_MACROS_H */