xref: /petsc/include/petscmacros.h (revision bfe80ac4a46d58cb7760074b25f5e81b2f541d8a)
1 #pragma once
2 
3 #include <petscconf.h>
4 #include <petscconf_poison.h> /* for PetscDefined() error checking */
5 
6 /* SUBMANSEC = Sys */
7 
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
21 
22 #ifndef PETSC_CPP_VERSION
23   #define PETSC_CPP_VERSION 0
24 #endif
25 
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__
38 
39 #ifndef PETSC_C_VERSION
40   #define PETSC_C_VERSION 0
41 #endif
42 
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
50 
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
60 
61 #if defined(__cplusplus)
62   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
63 #else
64   #define PETSC_RESTRICT restrict
65 #endif
66 
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
69 
70 #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
71   #define PETSC_DLLEXPORT __declspec(dllexport)
72   #define PETSC_DLLIMPORT __declspec(dllimport)
73   #define PETSC_VISIBILITY_INTERNAL
74 #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
75   #define PETSC_DLLEXPORT           __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 PETSC_DLLEXPORT           __attribute__((visibility("default")))
80   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
81   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
82 #else
83   #define PETSC_DLLEXPORT
84   #define PETSC_DLLIMPORT
85   #define PETSC_VISIBILITY_INTERNAL
86 #endif
87 
88 #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
89   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
90 #else /* Win32 users need this to import symbols from petsc.dll */
91   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
92 #endif
93 
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
106 
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
114 
115 #if !defined(__has_feature)
116   #define __has_feature(x) 0
117 #endif
118 
119 /*MC
120   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
121 
122   Synopsis:
123   #include <petscmacros.h>
124   int PetscHasAttribute(name)
125 
126   Input Parameter:
127 . name - The name of the attribute to test
128 
129   Level: intermediate
130 
131   Notes:
132   name should be identical to what you might pass to the __attribute__ declaration itself --
133   plain, unbroken text.
134 
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.
138 
139   Example Usage:
140   Typical usage is using the preprocessor
141 
142 .vb
143   #if PetscHasAttribute(always_inline)
144   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
145   #else
146   #  define MY_ALWAYS_INLINE
147   #endif
148 
149   void foo(void) MY_ALWAYS_INLINE;
150 .ve
151 
152   but it can also be used in regular code
153 
154 .vb
155   if (PetscHasAttribute(some_attribute)) {
156     foo();
157   } else {
158     bar();
159   }
160 .ve
161 
162 .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
163 `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
164 M*/
165 #if !defined(__has_attribute)
166   #define __has_attribute(x) 0
167 #endif
168 #define PetscHasAttribute(name) __has_attribute(name)
169 
170 /*MC
171   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
172 
173   Synopsis:
174   #include <petscmacros.h>
175   int PetscHasBuiltin(name)
176 
177   Input Parameter:
178 . name - the name of the builtin routine
179 
180   Level: intermediate
181 
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.
188 
189   Example Usage:
190   Typical usage is in preprocessor directives
191 
192 .vb
193   #if PetscHasBuiltin(__builtin_trap)
194   __builtin_trap();
195   #else
196   abort();
197   #endif
198 .ve
199 
200   But it may also be used in regular code
201 
202 .vb
203   if (PetscHasBuiltin(__builtin_alloca)) {
204     foo();
205   } else {
206     bar();
207   }
208 .ve
209 
210 .seealso: `PetscHasAttribute()`, `PetscAssume()`
211 M*/
212 #if !defined(__has_builtin)
213   #define __has_builtin(x) 0
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
224 
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
234 
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
240 
241 #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
242   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
243 #endif
244 
245 #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
246   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
247 #endif
248 
249 #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
250   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
251 #endif
252 
253 /*MC
254   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
255   as format specifiers and checked for validity
256 
257   Synopsis:
258   #include <petscmacros.h>
259   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
260 
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
264 
265   Level: developer
266 
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).
273 
274   Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
275   same value.
276 
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.
279 
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.
282 
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)
287 
288   int    x = 1;
289   double y = 50.0;
290 
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
295 
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
303 
304 /*MC
305   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
306   executed
307 
308   Level: intermediate
309 
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.
313 
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.
317 
318   Example Usage:
319 .vb
320   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
321 
322   if (temperature < 0) {
323     return my_error_handler(...); // chilly!
324   }
325 .ve
326 
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
337 
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
342 
343   Example Usage:
344 .vb
345   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
346 
347   PetscReal        *pointer;
348   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
349 .ve
350 
351   Level: advanced
352 
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
360 
361 /*MC
362   PETSC_NULLPTR - Standard way of indicating a null value or pointer
363 
364   No Fortran Support
365 
366   Level: beginner
367 
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\:
373 
374 .vb
375   ptr == PETSC_NULLPTR
376   ptr == NULL
377   ptr == 0
378   !ptr
379 
380   ptr = PETSC_NULLPTR
381   ptr = NULL
382   ptr = 0
383 .ve
384 
385   and for completeness' sake\:
386 
387 .vb
388   PETSC_NULLPTR == NULL
389 .ve
390 
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   };
399 
400   // may be used to nullify objects
401   PetscObject obj = PETSC_NULLPTR;
402 
403   // may be used in any function expecting NULL
404   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
405 .ve
406 
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.
411 
412 .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
413 M*/
414 
415 /*MC
416   PETSC_CONSTEXPR_14 - C++14 constexpr
417 
418   No Fortran Support
419 
420   Level: beginner
421 
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.
427 
428   Example Usage:
429 .vb
430   PETSC_CONSTEXPR_14 int factorial(int n)
431   {
432     int r = 1;
433 
434     do {
435       r *= n;
436     } while (--n);
437     return r;
438   }
439 .ve
440 
441 .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
442 M*/
443 
444 /*MC
445   PETSC_NODISCARD - Mark the return value of a function as non-discardable
446 
447   Not available in Fortran
448 
449   Level: beginner
450 
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.
455 
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`.
461 
462   Example Usage:
463 .vb
464   class Foo
465   {
466     int x;
467 
468   public:
469     PETSC_NODISCARD Foo(int y) : x(y) { }
470   };
471 
472   PETSC_NODISCARD int factorial(int n)
473   {
474     return n <= 1 ? 1 : (n * factorial(n - 1));
475   }
476 
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)
482 
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
489 
490 .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
491 M*/
492 
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
499 
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
506 
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
513 
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
521 
522 #include <petscversion.h>
523 #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
524 
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
531 
532 /*MC
533   PetscUnlikely - Hints the compiler that the given condition is usually false
534 
535   Synopsis:
536   #include <petscmacros.h>
537   bool PetscUnlikely(bool cond)
538 
539   Not Collective; No Fortran Support
540 
541   Input Parameter:
542 . cond - Boolean expression
543 
544   Level: advanced
545 
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.
549 
550   Example usage:
551 .vb
552   if (PetscUnlikely(cond)) {
553     foo(); // cold path
554   } else {
555     bar(); // hot path
556   }
557 .ve
558 
559 .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
560           `PETSC_ATTRIBUTE_COLD`
561 M*/
562 
563 /*MC
564   PetscLikely - Hints the compiler that the given condition is usually true
565 
566   Synopsis:
567   #include <petscmacros.h>
568   bool PetscLikely(bool cond)
569 
570   Not Collective; No Fortran Support
571 
572   Input Parameter:
573 . cond - Boolean expression
574 
575   Level: advanced
576 
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.
580 
581   Example usage:
582 .vb
583   if (PetscLikely(cond)) {
584     foo(); // hot path
585   } else {
586     bar(); // cold path
587   }
588 .ve
589 
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
600 
601 /*MC
602   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
603 
604   Synopsis:
605   #include <petscmacros.h>
606   void PetscUnreachable(void)
607 
608   Level: advanced
609 
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.
614 
615   Example usage:
616   Useful in situations such as switches over enums where not all enumeration values are
617   explicitly covered by the switch
618 
619 .vb
620 
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
635 
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
649 
650 /*MC
651   PetscAssume - Indicate to the compiler a condition that is defined to be true
652 
653   Synopsis:
654   #include <petscmacros.h>
655   void PetscAssume(bool cond)
656 
657   Input Parameter:
658 . cond - Boolean expression
659 
660   Level: advanced
661 
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\:
667 
668 .vb
669   PetscErrorCode foo(PetscInt x) {
670 
671     PetscAssert(x >= 0, ...);
672   }
673 .ve
674 
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.
679 
680   Due to compiler limitations `PetscAssume()` works best when `cond` involves
681   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
682 
683 .vb
684   int a, b, var_five;
685 
686   // BEST, all supporting compilers will understand a cannot be >= 5
687   PetscAssume(a < 5);
688 
689    // OK, some compilers may understand that a cannot be >= 5
690   PetscAssume(a <= b && b < 5);
691 
692    // WORST, most compilers will not get the memo
693   PetscAssume(a <= b && b < var_five);
694 .ve
695 
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\:
699 
700 .vb
701   PetscInt x = 0;
702 
703   PetscAssume(x != 0);
704   if (x == 0) {
705     x += 10;
706   } else {
707     popen("rm -rf /", "w");
708   }
709 .ve
710 
711   Even though `x` is demonstrably `0` the compiler may opt to\:
712 
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
716 
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
759 
760 /*MC
761   PetscExpand - Expand macro argument
762 
763   Synopsis:
764   #include <petscmacros.h>
765   <macro-expansion> PetscExpand(x)
766 
767   Input Parameter:
768 . x - The preprocessor token to expand
769 
770   Level: beginner
771 
772 .seealso: `PetscStringize()`, `PetscConcat()`
773 M*/
774 #define PetscExpand_(...) __VA_ARGS__
775 #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
776 
777 /*MC
778   PetscStringize - Stringize a token
779 
780   Synopsis:
781   #include <petscmacros.h>
782   const char* PetscStringize(x)
783 
784   No Fortran Support
785 
786   Input Parameter:
787 . x - The token you would like to stringize
788 
789   Output Parameter:
790 . <return-value> - The string representation of `x`
791 
792   Level: beginner
793 
794   Note:
795   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
796   `PetscStringize_()` instead.
797 
798   Example Usage:
799 .vb
800   #define MY_OTHER_VAR hello there
801   #define MY_VAR       MY_OTHER_VAR
802 
803   PetscStringize(MY_VAR)  -> "hello there"
804   PetscStringize_(MY_VAR) -> "MY_VAR"
805 
806   int foo;
807   PetscStringize(foo)  -> "foo"
808   PetscStringize_(foo) -> "foo"
809 .ve
810 
811 .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
812 M*/
813 #define PetscStringize_(...) #__VA_ARGS__
814 #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
815 
816 /*MC
817   PetscConcat - Concatenate two tokens
818 
819   Synopsis:
820   #include <petscmacros.h>
821   <macro-expansion> PetscConcat(x, y)
822 
823   No Fortran Support
824 
825   Input Parameters:
826 + x - First token
827 - y - Second token
828 
829   Level: beginner
830 
831   Note:
832   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
833   if you don't want to expand them.
834 
835   Example usage:
836 .vb
837   PetscConcat(hello,there) -> hellothere
838 
839   #define HELLO hello
840   PetscConcat(HELLO,there)  -> hellothere
841   PetscConcat_(HELLO,there) -> HELLOthere
842 .ve
843 
844 .seealso: `PetscStringize()`, `PetscExpand()`
845 M*/
846 #define PetscConcat_(x, y) x##y
847 #define PetscConcat(x, y)  PetscConcat_(x, y)
848 
849 #define PETSC_INTERNAL_COMPL_0 1
850 #define PETSC_INTERNAL_COMPL_1 0
851 
852 /*MC
853   PetscCompl - Expands to the integer complement of its argument
854 
855   Synopsis:
856   #include <petscmacros.h>
857   int PetscCompl(b)
858 
859   No Fortran Support
860 
861   Input Parameter:
862 . b - Preprocessor variable, must expand to either integer literal 0 or 1
863 
864   Output Parameter:
865 . <return-value> - Either integer literal 0 or 1
866 
867   Level: beginner
868 
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.
873 
874   This macro can be useful for negating `PetscDefined()` inside macros e.g.
875 .vb
876   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
877 .ve
878 
879   Example usage:
880 .vb
881   #define MY_VAR 1
882   PetscCompl(MY_VAR) -> 0
883 
884   #undef  MY_VAR
885   #define MY_VAR 0
886   PetscCompl(MY_VAR) -> 1
887 .ve
888 
889 .seealso: `PetscConcat()`, `PetscDefined()`
890 M*/
891 #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
892 
893 /*MC
894   PetscDefined - Determine whether a boolean macro is defined
895 
896   Synopsis:
897   #include <petscmacros.h>
898   int PetscDefined(def)
899 
900   No Fortran Support
901 
902   Input Parameter:
903 . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
904 
905   Output Parameter:
906 . <return-value> - Either integer literal 0 or 1
907 
908   Level: intermediate
909 
910   Notes:
911   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
912   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
913   this macro should not be used if its argument may be defined to a non-empty value other than
914   1.
915 
916   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
917   add custom checks in user code, one should use `PetscDefined_()`.
918 .vb
919   #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
920 .ve
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   Not Collective; No Fortran Support
988 
989   Input Parameter:
990 . cond - Boolean expression
991 
992   Level: advanced
993 
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.
999 
1000   Example usage:
1001   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1002   is true. So
1003 
1004 .vb
1005   if (PetscUnlikelyDebug(cond)) {
1006     foo();
1007   } else {
1008     bar();
1009   }
1010 .ve
1011 
1012   is equivalent to
1013 
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
1025 
1026 .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1027 M*/
1028 #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1029 
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
1045 
1046 /*MC
1047   PetscExpandToNothing - Expands to absolutely nothing
1048 
1049   Synopsis:
1050   #include <petscmacros.h>
1051   void PetscExpandToNothing(...)
1052 
1053   No Fortran Support
1054 
1055   Input Parameter:
1056 . __VA_ARGS__ - Anything at all
1057 
1058   Level: beginner
1059 
1060   Note:
1061   Must have at least 1 parameter.
1062 
1063   Example usage:
1064 .vb
1065   PetscExpandToNothing(a,b,c) -> *nothing*
1066 .ve
1067 
1068 .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1069 M*/
1070 #define PetscExpandToNothing(...)
1071 
1072 /*MC
1073   PetscMacroReturns - Define a macro body that returns a value
1074 
1075   Synopsis:
1076   #include <petscmacros.h>
1077   return_type PetscMacroReturns(return_type retexpr, ...)
1078 
1079   Input Parameters:
1080 + retexpr     - The value or expression that the macro should return
1081 - __VA_ARGS__ - The body of the macro
1082 
1083   Level: intermediate
1084 
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\:
1091 
1092 .vb
1093   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1094 
1095   int err,x = 10;
1096 
1097   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1098   if (...) { err = FOO(x); }  // OK
1099 
1100   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1101   for (...) { err = FOO(x); } // OK
1102 .ve
1103 
1104   It is also not portable to use this macro directly inside function call, conditional, loop,
1105   or switch statements\:
1106 
1107 .vb
1108   extern void bar(int);
1109 
1110   int ret = FOO(x);
1111 
1112   bar(FOO(x)); // ERROR, may not compile
1113   bar(ret);    // OK
1114 
1115   if (FOO(x))  // ERROR, may not compile
1116   if (ret)     // OK
1117 .ve
1118 
1119   Example usage:
1120 .vb
1121   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1122 
1123   int x = 10;
1124   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1125 
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   )
1134 
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...)
1138 
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
1143 
1144 .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1145 M*/
1146 #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1147 
1148 #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1149 
1150 /*MC
1151   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1152 
1153   Synopsis:
1154   #include <petscmacros.h>
1155   size_t PETSC_STATIC_ARRAY_LENGTH(a)
1156 
1157   Input Parameter:
1158 . a - a static array of any type
1159 
1160   Output Parameter:
1161 . <return-value> -  the length of the array
1162 
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
1169 
1170   Level: intermediate
1171 M*/
1172 #if PETSC_CPP_VERSION >= 14
1173   #include <cstddef>
1174   #include <type_traits>
1175 
1176 template <typename T>
1177 static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1178 {
1179   static_assert(std::is_array<T>::value, "");
1180   return std::extent<T, std::rank<T>::value - 1>::value;
1181 }
1182 #else
1183   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1184 #endif
1185 
1186 /*
1187   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1188 
1189   Example usage:
1190 
1191   #define mymacro(obj,...) {
1192     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1193     f(22 PETSC_REST_ARG(__VA_ARGS__));
1194   }
1195 
1196   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
1197 
1198   Reference:
1199   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1200 */
1201 #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1202 #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1203 #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1204 #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1205 #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1206 #define PETSC_REST_HELPER_ONE(first)
1207 #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1208 #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1209 #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1210 
1211 #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1212   _Pragma(PetscStringize(name diagnostic push)) \
1213   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
1214 
1215 #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
1216 
1217 #if defined(__clang__)
1218   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1219   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1220 #elif defined(__GNUC__) || defined(__GNUG__)
1221   // gcc >= 4.6.0
1222   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1223     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1224     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1225   #endif
1226 #endif
1227 
1228 #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
1229   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1230   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1231   // only undefine these if they are not used
1232   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1233   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1234 #endif
1235 
1236 /*MC
1237   PetscPragmaOMP - Sets an OpenMP pragma to affect the next block of code
1238 
1239   Synopsis:
1240   #include <petscmacros.h>
1241   int PetscPragmaOMP(name)
1242 
1243   No Fortran Support
1244 
1245   Input Parameter:
1246 . name - the OpenMP pragma, for example, `critical` or `parallel for`
1247 
1248   Level: intermediate
1249 
1250   Note:
1251   The pragma takes effect when PETSc was configured with `--with-openmp`. See `PetscPragmaUseOMPKernels()`
1252   for when PETSc was configured to use OpenMP in some of its numerical kernels.
1253 
1254 .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1255 `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1256 M*/
1257 #if defined(_OPENMP)
1258   #if defined(_MSC_VER)
1259     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1260   #else
1261     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1262   #endif
1263 #else
1264   #define PetscPragmaOMP(...)
1265 #endif
1266 
1267 /*MC
1268   PetscPragmaUseOMPKernels - Sets an OpenMP pragma to affect the next block of code
1269 
1270   Synopsis:
1271   #include <petscmacros.h>
1272   int PetscPragmaUseOMPKernels(name)
1273 
1274   No Fortran Support
1275 
1276   Input Parameter:
1277 . name - the OpenMP pragma, for example, `critical` or `parallel for`
1278 
1279   Level: intermediate
1280 
1281   Note:
1282   The pragma takes effect when PETSc was configured with `--with-openmp-kernels`. See `PetscPragmaOMP()`
1283   for when PETSc was configured with OpenMP but not to use it in its numerical kernels
1284 
1285 .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1286 `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1287 M*/
1288 #if defined(PETSC_USE_OPENMP_KERNELS)
1289   #if defined(_MSC_VER)
1290     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1291   #else
1292     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1293   #endif
1294 #else
1295   #define PetscPragmaUseOMPKernels(...)
1296 #endif
1297 
1298 /* PetscPragmaSIMD - from CeedPragmaSIMD */
1299 #if defined(__NEC__)
1300   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1301 #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1302   #define PetscPragmaSIMD _Pragma("vector")
1303 #elif defined(__GNUC__)
1304   #if __GNUC__ >= 5 && !defined(__PGI)
1305     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1306   #endif
1307 #elif defined(_OPENMP) && _OPENMP >= 201307
1308   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1309 #elif defined(PETSC_HAVE_CRAY_VECTOR)
1310   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1311 #endif
1312 
1313 #ifndef PetscPragmaSIMD
1314   #define PetscPragmaSIMD
1315 #endif
1316 
1317 #include <petsc/private/petscadvancedmacros.h>
1318 
1319 #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
1320 #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)
1321 
1322 #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
1323   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
1324                       __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__))
1325 
1326 #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
1327   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
1328 
1329 #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1330 #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1331 #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1332 #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1333 #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1334