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