Actual source code: petscmacros.h
1: #pragma once
3: #include <petscconf.h>
4: #include <petscconf_poison.h> /* for PetscDefined() error checking */
6: /* SUBMANSEC = Sys */
8: #if defined(__cplusplus)
9: #if __cplusplus <= 201103L
10: #define PETSC_CPP_VERSION 11
11: #elif __cplusplus <= 201402L
12: #define PETSC_CPP_VERSION 14
13: #elif __cplusplus <= 201703L
14: #define PETSC_CPP_VERSION 17
15: #elif __cplusplus <= 202002L
16: #define PETSC_CPP_VERSION 20
17: #else
18: #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
19: #endif
20: #endif // __cplusplus
22: #ifndef PETSC_CPP_VERSION
23: #define PETSC_CPP_VERSION 0
24: #endif
26: #if defined(__STDC_VERSION__)
27: #if __STDC_VERSION__ <= 199901L
28: // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
29: #define PETSC_C_VERSION 9
30: #elif __STDC_VERSION__ <= 201112L
31: #define PETSC_C_VERSION 11
32: #elif __STDC_VERSION__ <= 201710L
33: #define PETSC_C_VERSION 17
34: #else
35: #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
36: #endif
37: #endif // __STDC_VERSION__
39: #ifndef PETSC_C_VERSION
40: #define PETSC_C_VERSION 0
41: #endif
43: /* ========================================================================== */
44: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
45: #if defined(__cplusplus)
46: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
47: #else
48: #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
49: #endif
51: /* ========================================================================== */
52: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
53: * files within extern "C". This will generate a compiler error if a user does put the include
54: * file within an extern "C".
55: */
56: #if defined(__cplusplus)
57: void assert_never_put_petsc_headers_inside_an_extern_c(int);
58: void assert_never_put_petsc_headers_inside_an_extern_c(double);
59: #endif
61: #if defined(__cplusplus)
62: #define PETSC_RESTRICT PETSC_CXX_RESTRICT
63: #else
64: #define PETSC_RESTRICT restrict
65: #endif
67: #define PETSC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
68: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline
70: #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
71: #define __declspec(dllexport)
72: #define PETSC_DLLIMPORT __declspec(dllimport)
73: #define PETSC_VISIBILITY_INTERNAL
74: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
75: #define __attribute__((visibility("default")))
76: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
77: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
78: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
79: #define __attribute__((visibility("default")))
80: #define PETSC_DLLIMPORT __attribute__((visibility("default")))
81: #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
82: #else
83: #define
84: #define PETSC_DLLIMPORT
85: #define PETSC_VISIBILITY_INTERNAL
86: #endif
88: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
89: #define PETSC_VISIBILITY_PUBLIC
90: #else /* Win32 users need this to import symbols from petsc.dll */
91: #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
92: #endif
94: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
95: * compiled with C++ so they may be used from C and are always visible in the shared libraries
96: */
97: #if defined(__cplusplus)
98: #define PETSC_EXTERN extern "C" PETSC_VISIBILITY_PUBLIC
99: #define PETSC_EXTERN_TYPEDEF extern "C"
100: #define PETSC_INTERN extern "C" PETSC_VISIBILITY_INTERNAL
101: #else
102: #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
103: #define PETSC_EXTERN_TYPEDEF
104: #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
105: #endif
107: #if defined(PETSC_USE_SINGLE_LIBRARY)
108: #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
109: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110: #else
111: #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
112: #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
113: #endif
117: #endif
119: /*MC
120: PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
122: Synopsis:
123: #include <petscmacros.h>
124: int PetscHasAttribute(name)
126: Input Parameter:
127: . name - The name of the attribute to test
129: Level: intermediate
131: Notes:
132: name should be identical to what you might pass to the __attribute__ declaration itself --
133: plain, unbroken text.
135: As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
136: exact type and value returned is implementation defined. In practice however, it usually
137: returns `1` if the attribute is supported and `0` if the attribute is not supported.
139: Example Usage:
140: Typical usage is using the preprocessor
142: .vb
143: #if PetscHasAttribute(always_inline)
144: # define MY_ALWAYS_INLINE __attribute__((always_inline))
145: #else
146: # define MY_ALWAYS_INLINE
147: #endif
149: void foo(void) MY_ALWAYS_INLINE;
150: .ve
152: but it can also be used in regular code
154: .vb
155: if (PetscHasAttribute(some_attribute)) {
156: foo();
157: } else {
158: bar();
159: }
160: .ve
162: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
163: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
164: M*/
167: #endif
168: #define PetscHasAttribute(name) __has_attribute(name)
170: /*MC
171: PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
173: Synopsis:
174: #include <petscmacros.h>
175: int PetscHasBuiltin(name)
177: Input Parameter:
178: . name - the name of the builtin routine
180: Level: intermediate
182: Notes:
183: Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
184: (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
185: detector is itself is a compiler extension with implementation-defined return type and
186: semantics. Some compilers implement it as a macro, others as a compiler function. In practice
187: however, all supporting compilers return an integer boolean as described.
189: Example Usage:
190: Typical usage is in preprocessor directives
192: .vb
193: #if PetscHasBuiltin(__builtin_trap)
194: __builtin_trap();
195: #else
196: abort();
197: #endif
198: .ve
200: But it may also be used in regular code
202: .vb
203: if (PetscHasBuiltin(__builtin_alloca)) {
204: foo();
205: } else {
206: bar();
207: }
208: .ve
210: .seealso: `PetscHasAttribute()`, `PetscAssume()`
211: M*/
214: #endif
215: // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
216: // __builtin_types_compatible_p which take types or other non-functiony things as
217: // arguments. The correct way to detect these then is to use __is_identifier (also a clang
218: // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
219: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
220: #define PetscHasBuiltin(name) __is_identifier(name)
221: #else
222: #define PetscHasBuiltin(name) __has_builtin(name)
223: #endif
225: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
226: /*
227: Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
228: This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
229: does not match the actual type of the argument being passed in
230: */
231: #if PetscHasAttribute(pointer_with_type_tag)
232: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
233: #endif
235: #if PetscHasAttribute(type_tag_for_datatype)
236: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type) __attribute__((type_tag_for_datatype(MPI, type)))
237: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
238: #endif
239: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
241: #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
242: #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
243: #endif
245: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
246: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
247: #endif
249: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
250: #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
251: #endif
253: /*MC
254: PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
255: as format specifiers and checked for validity
257: Synopsis:
258: #include <petscmacros.h>
259: <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
261: Input Parameters:
262: + strIdx - The (1-indexed) location of the format string in the argument list
263: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
265: Level: developer
267: Notes:
268: This function attribute causes the compiler to issue warnings when the format specifier does
269: not match the type of the variable that will be formatted, or when there exists a mismatch
270: between the number of format specifiers and variables to be formatted. It is safe to use this
271: macro if your compiler does not support format specifier checking (though this is
272: exceeedingly rare).
274: Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
275: same value.
277: The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
278: the argument list, that is, there is no way to indicate gaps which should not be checked.
280: Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
281: header files. In this case the macro will expand empty.
283: Example Usage:
284: .vb
285: // format string is 2nd argument, variable argument list containing args is 3rd argument
286: void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
288: int x = 1;
289: double y = 50.0;
291: my_printf(NULL,"%g",x); // WARNING, format specifier does not match for 'int'!
292: my_printf(NULL,"%d",x,y); // WARNING, more arguments than format specifiers!
293: my_printf(NULL,"%d %g",x,y); // OK
294: .ve
296: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
297: M*/
298: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
299: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
300: #else
301: #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
302: #endif
304: /*MC
305: PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
306: executed
308: Level: intermediate
310: Notes:
311: The marked function is often optimized for size rather than speed and may be grouped alongside
312: other equally frigid routines improving code locality of lukewarm or hotter parts of program.
314: The paths leading to cold functions are usually automatically marked as unlikely by the
315: compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
316: as error handlers -- as cold to improve optimization of the surrounding temperate functions.
318: Example Usage:
319: .vb
320: void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
322: if (temperature < 0) {
323: return my_error_handler(...); // chilly!
324: }
325: .ve
327: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
328: `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
329: M*/
330: #if PetscHasAttribute(__cold__)
331: #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
332: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
333: #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
334: #else
335: #define PETSC_ATTRIBUTE_COLD
336: #endif
338: /*MC
339: PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
340: subjected to type-based alias analysis, but is instead assumed to be able to
341: alias any other type of objects
343: Example Usage:
344: .vb
345: typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
347: PetscReal *pointer;
348: PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
349: .ve
351: Level: advanced
353: .seealso: `PetscHasAttribute()`
354: M*/
355: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
356: #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
357: #else
358: #define PETSC_ATTRIBUTE_MAY_ALIAS
359: #endif
361: /*MC
362: PETSC_NULLPTR - Standard way of indicating a null value or pointer
364: No Fortran Support
366: Level: beginner
368: Notes:
369: Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
370: interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
371: equivalent to setting the same pointer to `NULL` in C. That is to say that the following
372: expressions are equivalent\:
374: .vb
375: ptr == PETSC_NULLPTR
376: ptr == NULL
377: ptr == 0
378: !ptr
380: ptr = PETSC_NULLPTR
381: ptr = NULL
382: ptr = 0
383: .ve
385: and for completeness' sake\:
387: .vb
388: PETSC_NULLPTR == NULL
389: .ve
391: Example Usage:
392: .vb
393: // may be used in place of '\0' or other such terminators in the definition of char arrays
394: const char *const MyEnumTypes[] = {
395: "foo",
396: "bar",
397: PETSC_NULLPTR
398: };
400: // may be used to nullify objects
401: PetscObject obj = PETSC_NULLPTR;
403: // may be used in any function expecting NULL
404: PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
405: .ve
407: Developer Notes:
408: `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
409: files compiled with a C++ compiler may lead to unexpected side-effects in function overload
410: resolution and/or compiler warnings.
412: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
413: M*/
415: /*MC
416: PETSC_CONSTEXPR_14 - C++14 constexpr
418: No Fortran Support
420: Level: beginner
422: Notes:
423: Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
424: if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
425: that this cannot be used in cases where an empty expansion would result in invalid code. It
426: is safe to use this in C source files.
428: Example Usage:
429: .vb
430: PETSC_CONSTEXPR_14 int factorial(int n)
431: {
432: int r = 1;
434: do {
435: r *= n;
436: } while (--n);
437: return r;
438: }
439: .ve
441: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
442: M*/
444: /*MC
445: PETSC_NODISCARD - Mark the return value of a function as non-discardable
447: Not available in Fortran
449: Level: beginner
451: Notes:
452: Hints to the compiler that the return value of a function must be captured. A diagnostic may
453: (but is not required to) be emitted if the value is discarded. It is safe to use this in both
454: C and C++ source files.
456: In this context "captured" means assigning the return value of a function to a named
457: variable or casting it to `void`. Between the two, assigning to a named variable is the most
458: portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
459: `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
460: `void`.
462: Example Usage:
463: .vb
464: class Foo
465: {
466: int x;
468: public:
469: PETSC_NODISCARD Foo(int y) : x(y) { }
470: };
472: PETSC_NODISCARD int factorial(int n)
473: {
474: return n <= 1 ? 1 : (n * factorial(n - 1));
475: }
477: factorial(10); // Warning: ignoring return value of function declared 'nodiscard'
478: auto x = factorial(10); // OK, capturing return value
479: (void)factorial(10); // Maybe OK, casting to void
480: auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
481: (void)y; // set-but-not-used warnings)
483: Foo(x); // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
484: auto f = Foo(x); // OK, capturing constructed object
485: (void)Foo(x); // Maybe OK, casting to void
486: auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
487: (void)g; // warnings)
488: .ve
490: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
491: M*/
493: /* C++11 features */
494: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
495: #define PETSC_NULLPTR nullptr
496: #else
497: #define PETSC_NULLPTR NULL
498: #endif
500: /* C++14 features */
501: #if PETSC_CPP_VERSION >= 14
502: #define PETSC_CONSTEXPR_14 constexpr
503: #else
504: #define PETSC_CONSTEXPR_14
505: #endif
507: /* C++17 features */
508: #if PETSC_CPP_VERSION >= 17
509: #define PETSC_CONSTEXPR_17 constexpr
510: #else
511: #define PETSC_CONSTEXPR_17
512: #endif
514: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
515: #define PETSC_NODISCARD [[nodiscard]]
516: #elif PetscHasAttribute(warn_unused_result)
517: #define PETSC_NODISCARD __attribute__((warn_unused_result))
518: #else
519: #define PETSC_NODISCARD
520: #endif
522: #include <petscversion.h>
523: #define PETSC_AUTHOR_INFO " The PETSc Team\n petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
525: /* designated initializers since C99 and C++20, MSVC never supports them though */
526: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
527: #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
528: #else
529: #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
530: #endif
532: /*MC
533: PetscUnlikely - Hints the compiler that the given condition is usually false
535: Synopsis:
536: #include <petscmacros.h>
537: bool PetscUnlikely(bool cond)
539: Not Collective; No Fortran Support
541: Input Parameter:
542: . cond - Boolean expression
544: Level: advanced
546: Note:
547: This returns the same truth value, it is only a hint to compilers that the result of cond is
548: unlikely to be true.
550: Example usage:
551: .vb
552: if (PetscUnlikely(cond)) {
553: foo(); // cold path
554: } else {
555: bar(); // hot path
556: }
557: .ve
559: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
560: `PETSC_ATTRIBUTE_COLD`
561: M*/
563: /*MC
564: PetscLikely - Hints the compiler that the given condition is usually true
566: Synopsis:
567: #include <petscmacros.h>
568: bool PetscLikely(bool cond)
570: Not Collective; No Fortran Support
572: Input Parameter:
573: . cond - Boolean expression
575: Level: advanced
577: Note:
578: This returns the same truth value, it is only a hint to compilers that the result of cond is
579: likely to be true.
581: Example usage:
582: .vb
583: if (PetscLikely(cond)) {
584: foo(); // hot path
585: } else {
586: bar(); // cold path
587: }
588: .ve
590: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
591: `PETSC_ATTRIBUTE_COLD`
592: M*/
593: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
594: #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
595: #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
596: #else
597: #define PetscUnlikely(cond) (cond)
598: #define PetscLikely(cond) (cond)
599: #endif
601: /*MC
602: PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
604: Synopsis:
605: #include <petscmacros.h>
606: void PetscUnreachable(void)
608: Level: advanced
610: Note:
611: Indicates to the compiler (usually via some built-in) that a particular code path is always
612: unreachable. Behavior is undefined if this function is ever executed, the user can expect an
613: unceremonious crash.
615: Example usage:
616: Useful in situations such as switches over enums where not all enumeration values are
617: explicitly covered by the switch
619: .vb
620: typedef enum {RED, GREEN, BLUE} Color;
622: int foo(Color c)
623: {
624: // it is known to programmer (or checked previously) that c is either RED or GREEN
625: // but compiler may not be able to deduce this and/or emit spurious warnings
626: switch (c) {
627: case RED:
628: return bar();
629: case GREEN:
630: return baz();
631: default:
632: PetscUnreachable(); // program is ill-formed if executed
633: }
634: }
635: .ve
637: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
638: M*/
639: #if PETSC_CPP_VERSION >= 23
640: #include <utility>
641: #define PetscUnreachable() std::unreachable()
642: #elif defined(__GNUC__)
643: /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
644: #define PetscUnreachable() __builtin_unreachable()
645: #elif defined(_MSC_VER) /* MSVC */
646: #define PetscUnreachable() __assume(0)
647: #else /* ??? */
648: #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
649: #endif
651: /*MC
652: PetscAssume - Indicate to the compiler a condition that is defined to be true
654: Synopsis:
655: #include <petscmacros.h>
656: void PetscAssume(bool cond)
658: Input Parameter:
659: . cond - Boolean expression
661: Level: advanced
663: Notes:
664: If supported by the compiler, `cond` is used to inform the optimizer of an invariant
665: truth. The argument itself is never evaluated, so any side effects of the expression will be
666: discarded. This macro is used in `PetscAssert()` to retain information gained from debug
667: checks that would be lost in optimized builds. For example\:
669: .vb
670: PetscErrorCode foo(PetscInt x) {
672: PetscAssert(x >= 0, ...);
673: }
674: .ve
676: The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
677: if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
678: when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
679: optimizer cannot deduce any information from them.
681: Due to compiler limitations `PetscAssume()` works best when `cond` involves
682: constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
684: .vb
685: int a, b, var_five;
687: // BEST, all supporting compilers will understand a cannot be >= 5
688: PetscAssume(a < 5);
690: // OK, some compilers may understand that a cannot be >= 5
691: PetscAssume(a <= b && b < 5);
693: // WORST, most compilers will not get the memo
694: PetscAssume(a <= b && b < var_five);
695: .ve
697: If the condition is violated at runtime then behavior is wholly undefined. If the
698: condition is violated at compile-time, the condition "supersedes" the compile-time violation
699: and the program is ill-formed, no diagnostic required. For example consider the following\:
701: .vb
702: PetscInt x = 0;
704: PetscAssume(x != 0);
705: if (x == 0) {
706: x += 10;
707: } else {
708: popen("rm -rf /", "w");
709: }
710: .ve
712: Even though `x` is demonstrably `0` the compiler may opt to\:
714: - emit an unconditional `popen("rm -rf /", "w")`
715: - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
716: - reformat the primary disk partition
718: .seealso: `PetscAssert()`
719: M*/
720: #if PETSC_CPP_VERSION >= 23
721: #define PetscAssume(...) [[assume(__VA_ARGS__)]]
722: #elif defined(_MSC_VER) // msvc
723: #define PetscAssume(...) __assume(__VA_ARGS__)
724: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
725: #define PetscAssume(...) \
726: do { \
727: _Pragma("clang diagnostic push"); \
728: _Pragma("clang diagnostic ignored \"-Wassume\""); \
729: __builtin_assume(__VA_ARGS__); \
730: _Pragma("clang diagnostic pop"); \
731: } while (0)
732: #else // gcc (and really old clang)
733: // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
734: //
735: // if (PetscUnlikely(!cond)) PetscUnreachable();
736: //
737: // but this it unsavory because the side effects of cond are not guaranteed to be
738: // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
739: // for which cond is false would be undefined results in undefined behavior anyway) it cannot
740: // always do so. This is especially the case for opaque or non-inline function calls:
741: //
742: // extern int bar(int);
743: //
744: // int foo(int x) {
745: // PetscAssume(bar(x) == 2);
746: // if (bar(x) == 2) {
747: // return 1;
748: // } else {
749: // return 0;
750: // }
751: // }
752: //
753: // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
754: // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
755: #define PetscAssume(...) \
756: do { \
757: if (0 && (__VA_ARGS__)) PetscUnreachable(); \
758: } while (0)
759: #endif
761: /*MC
762: PetscExpand - Expand macro argument
764: Synopsis:
765: #include <petscmacros.h>
766: <macro-expansion> PetscExpand(x)
768: Input Parameter:
769: . x - The preprocessor token to expand
771: Level: beginner
773: .seealso: `PetscStringize()`, `PetscConcat()`
774: M*/
775: #define PetscExpand_(...) __VA_ARGS__
776: #define PetscExpand(...) PetscExpand_(__VA_ARGS__)
778: /*MC
779: PetscStringize - Stringize a token
781: Synopsis:
782: #include <petscmacros.h>
783: const char* PetscStringize(x)
785: No Fortran Support
787: Input Parameter:
788: . x - The token you would like to stringize
790: Output Parameter:
791: . <return-value> - The string representation of `x`
793: Level: beginner
795: Note:
796: `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
797: `PetscStringize_()` instead.
799: Example Usage:
800: .vb
801: #define MY_OTHER_VAR hello there
802: #define MY_VAR MY_OTHER_VAR
804: PetscStringize(MY_VAR) -> "hello there"
805: PetscStringize_(MY_VAR) -> "MY_VAR"
807: int foo;
808: PetscStringize(foo) -> "foo"
809: PetscStringize_(foo) -> "foo"
810: .ve
812: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
813: M*/
814: #define PetscStringize_(...) #__VA_ARGS__
815: #define PetscStringize(...) PetscStringize_(__VA_ARGS__)
817: /*MC
818: PetscConcat - Concatenate two tokens
820: Synopsis:
821: #include <petscmacros.h>
822: <macro-expansion> PetscConcat(x, y)
824: No Fortran Support
826: Input Parameters:
827: + x - First token
828: - y - Second token
830: Level: beginner
832: Note:
833: `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
834: if you don't want to expand them.
836: Example usage:
837: .vb
838: PetscConcat(hello,there) -> hellothere
840: #define HELLO hello
841: PetscConcat(HELLO,there) -> hellothere
842: PetscConcat_(HELLO,there) -> HELLOthere
843: .ve
845: .seealso: `PetscStringize()`, `PetscExpand()`
846: M*/
847: #define PetscConcat_(x, y) x##y
848: #define PetscConcat(x, y) PetscConcat_(x, y)
850: #define PETSC_INTERNAL_COMPL_0 1
851: #define PETSC_INTERNAL_COMPL_1 0
853: /*MC
854: PetscCompl - Expands to the integer complement of its argument
856: Synopsis:
857: #include <petscmacros.h>
858: int PetscCompl(b)
860: No Fortran Support
862: Input Parameter:
863: . b - Preprocessor variable, must expand to either integer literal 0 or 1
865: Output Parameter:
866: . <return-value> - Either integer literal 0 or 1
868: Level: beginner
870: Notes:
871: Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
872: 0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
873: argument before returning the complement.
875: This macro can be useful for negating `PetscDefined()` inside macros e.g.
876: .vb
877: #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
878: .ve
880: Example usage:
881: .vb
882: #define MY_VAR 1
883: PetscCompl(MY_VAR) -> 0
885: #undef MY_VAR
886: #define MY_VAR 0
887: PetscCompl(MY_VAR) -> 1
888: .ve
890: .seealso: `PetscConcat()`, `PetscDefined()`
891: M*/
892: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
894: /*MC
895: PetscDefined - Determine whether a boolean macro is defined
897: Synopsis:
898: #include <petscmacros.h>
899: int PetscDefined(def)
901: No Fortran Support
903: Input Parameter:
904: . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
906: Output Parameter:
907: . <return-value> - Either integer literal 0 or 1
909: Level: intermediate
911: Notes:
912: `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
913: integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
914: this macro should not be used if its argument may be defined to a non-empty value other than
915: 1.
917: The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
918: add custom checks in user code, one should use `PetscDefined_()`.
919: .vb
920: #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
921: .ve
923: Developer Notes:
924: Getting something that works in C and CPP for an arg that may or may not be defined is
925: tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
926: insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
927: the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
928: and when the last step cherry picks the 2nd arg, we get a zero.
930: Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
931: nonconforming implementation of variadic macros.
933: Example Usage:
934: Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
935: is defined then
937: .vb
938: #if PetscDefined(USE_DEBUG)
939: foo();
940: #else
941: bar();
942: #endif
944: // or alternatively within normal code
945: if (PetscDefined(USE_DEBUG)) {
946: foo();
947: } else {
948: bar();
949: }
950: .ve
952: is equivalent to
954: .vb
955: #if defined(PETSC_USE_DEBUG)
956: # if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
957: foo();
958: # elif PETSC_USE_DEBUG == 1
959: foo();
960: # else
961: bar();
962: # endif
963: #else
964: bar();
965: #endif
966: .ve
968: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
969: `PetscExpandToNothing()`, `PetscCompl()`
970: M*/
971: #define PetscDefined_arg_1 shift,
972: #define PetscDefined_arg_ shift,
973: #define PetscDefined__take_second_expanded(ignored, val, ...) val
974: #define PetscDefined__take_second_expand(args) PetscDefined__take_second_expanded args
975: #define PetscDefined__take_second(...) PetscDefined__take_second_expand((__VA_ARGS__))
976: #define PetscDefined__(arg1_or_junk) PetscDefined__take_second(arg1_or_junk 1, 0, at_)
977: #define PetscDefined_(value) PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
978: #define PetscDefined(def) PetscDefined_(PetscConcat(PETSC_, def))
980: /*MC
981: PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
982: the check in optimized mode
984: Synopsis:
985: #include <petscmacros.h>
986: bool PetscUnlikelyDebug(bool cond)
988: Not Collective; No Fortran Support
990: Input Parameter:
991: . cond - Boolean expression
993: Level: advanced
995: Note:
996: This returns the same truth value, it is only a hint to compilers that the result of `cond` is
997: likely to be false. When PETSc is compiled in optimized mode this will always return
998: false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
999: optimized mode.
1001: Example usage:
1002: This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1003: is true. So
1005: .vb
1006: if (PetscUnlikelyDebug(cond)) {
1007: foo();
1008: } else {
1009: bar();
1010: }
1011: .ve
1013: is equivalent to
1015: .vb
1016: if (PetscDefined(USE_DEBUG)) {
1017: if (PetscUnlikely(cond)) {
1018: foo();
1019: } else {
1020: bar();
1021: }
1022: } else {
1023: bar();
1024: }
1025: .ve
1027: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1028: M*/
1029: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1031: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1032: // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1033: // not what ISO C allows
1034: #define PetscMacroReturns_(retexpr, ...) \
1035: __extension__({ \
1036: __VA_ARGS__; \
1037: retexpr; \
1038: })
1039: #else
1040: #define PetscMacroReturns_(retexpr, ...) \
1041: retexpr; \
1042: do { \
1043: __VA_ARGS__; \
1044: } while (0)
1045: #endif
1047: /*MC
1048: PetscExpandToNothing - Expands to absolutely nothing
1050: Synopsis:
1051: #include <petscmacros.h>
1052: void PetscExpandToNothing(...)
1054: No Fortran Support
1056: Input Parameter:
1057: . __VA_ARGS__ - Anything at all
1059: Level: beginner
1061: Note:
1062: Must have at least 1 parameter.
1064: Example usage:
1065: .vb
1066: PetscExpandToNothing(a,b,c) -> *nothing*
1067: .ve
1069: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1070: M*/
1071: #define PetscExpandToNothing(...)
1073: /*MC
1074: PetscMacroReturns - Define a macro body that returns a value
1076: Synopsis:
1077: #include <petscmacros.h>
1078: return_type PetscMacroReturns(return_type retexpr, ...)
1080: Input Parameters:
1081: + retexpr - The value or expression that the macro should return
1082: - __VA_ARGS__ - The body of the macro
1084: Level: intermediate
1086: Notes:
1087: Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1088: body of the macro and should not depend on values produced as a result of the expression. The
1089: user should not assume that the result of this macro is equivalent to a single logical source
1090: line. It is not portable to use macros defined using this one in conditional or loop bodies
1091: without enclosing them in curly braces\:
1093: .vb
1094: #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1096: int err,x = 10;
1098: if (...) err = FOO(x); // ERROR, body of FOO() executed outside the if statement
1099: if (...) { err = FOO(x); } // OK
1101: for (...) err = FOO(x); // ERROR, body of FOO() executed outside the loop
1102: for (...) { err = FOO(x); } // OK
1103: .ve
1105: It is also not portable to use this macro directly inside function call, conditional, loop,
1106: or switch statements\:
1108: .vb
1109: extern void bar(int);
1111: int ret = FOO(x);
1113: bar(FOO(x)); // ERROR, may not compile
1114: bar(ret); // OK
1116: if (FOO(x)) // ERROR, may not compile
1117: if (ret) // OK
1118: .ve
1120: Example usage:
1121: .vb
1122: #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1124: int x = 10;
1125: int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1127: // multiline macros allowed, but must declare with line continuation as usual
1128: #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1129: if (arg1 > 10) { \
1130: puts("big int!"); \
1131: } else { \
1132: return 7355608; \
1133: } \
1134: )
1136: // if retexpr contains commas, must enclose it with braces
1137: #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1138: #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1140: int x = 10;
1141: int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1142: int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1143: .ve
1145: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1146: M*/
1147: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1149: #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1151: /*MC
1152: PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1154: Synopsis:
1155: #include <petscmacros.h>
1156: size_t PETSC_STATIC_ARRAY_LENGTH(a)
1158: Input Parameter:
1159: . a - a static array of any type
1161: Output Parameter:
1162: . <return-value> - the length of the array
1164: Example:
1165: .vb
1166: PetscInt a[22];
1167: size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1168: .ve
1169: `sa` will have a value of 22
1171: Level: intermediate
1172: M*/
1173: #if PETSC_CPP_VERSION >= 14
1174: #include <cstddef>
1175: #include <type_traits>
1177: template <typename T>
1178: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1179: {
1180: static_assert(std::is_array<T>::value, "");
1181: return std::extent<T, std::rank<T>::value - 1>::value;
1182: }
1183: #else
1184: #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1185: #endif
1187: /*
1188: These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1190: Example usage:
1192: #define mymacro(obj,...) {
1193: PETSC_FIRST_ARG((__VA_ARGS__,unused));
1194: f(22 PETSC_REST_ARG(__VA_ARGS__));
1195: }
1197: 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
1199: Reference:
1200: https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1201: */
1202: #define PETSC_FIRST_ARG_(N, ...) N
1203: #define PETSC_FIRST_ARG(args) PETSC_FIRST_ARG_ args
1204: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1205: #define PETSC_NUM(...) PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1206: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1207: #define PETSC_REST_HELPER_ONE(first)
1208: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1209: #define PETSC_REST_HELPER(qty, ...) PETSC_REST_HELPER2(qty, __VA_ARGS__)
1210: #define PETSC_REST_ARG(...) PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1212: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1213: _Pragma(PetscStringize(name diagnostic push)) \
1214: _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
1216: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
1218: #if defined(__clang__)
1219: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1220: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1221: #elif defined(__GNUC__) || defined(__GNUG__)
1222: // gcc >= 4.6.0
1223: #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1224: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1225: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1226: #endif
1227: #endif
1229: #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
1230: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1231: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1232: // only undefine these if they are not used
1233: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1234: #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1235: #endif
1237: /* OpenMP support */
1238: #if defined(_OPENMP)
1239: #if defined(_MSC_VER)
1240: #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1241: #else
1242: #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1243: #endif
1244: #endif
1246: #ifndef PetscPragmaOMP
1247: #define PetscPragmaOMP(...)
1248: #endif
1250: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1251: #if defined(__NEC__)
1252: #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1253: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1254: #define PetscPragmaSIMD _Pragma("vector")
1255: #elif defined(__GNUC__)
1256: #if __GNUC__ >= 5 && !defined(__PGI)
1257: #define PetscPragmaSIMD _Pragma("GCC ivdep")
1258: #endif
1259: #elif defined(_OPENMP) && _OPENMP >= 201307
1260: #define PetscPragmaSIMD PetscPragmaOMP(simd)
1261: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1262: #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1263: #endif
1265: #ifndef PetscPragmaSIMD
1266: #define PetscPragmaSIMD
1267: #endif
1269: #include <petsc/private/petscadvancedmacros.h>
1271: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
1272: #define PetscConcat6(a, b, c, d, e, f) PetscConcat6_(a, b, c, d, e, f)
1274: #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
1275: PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
1276: __PETSC_DEPRECATION_MACRO__)(PetscStringize(Use replacement (since version major.minor.subminor) instead. Silence this warning (as well as all others for this version) by defining PetscConcat_(PETSC_, __SILENCE_MACRO__). __VA_ARGS__))
1278: #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
1279: PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
1281: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1282: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1283: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1284: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1285: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)