xref: /petsc/include/petscmacros.h (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
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   typedef enum {RED, GREEN, BLUE} Color;
621 
622   int foo(Color c)
623   {
624     // it is known to programmer (or checked previously) that c is either RED or GREEN
625     // but compiler may not be able to deduce this and/or emit spurious warnings
626     switch (c) {
627       case RED:
628         return bar();
629       case GREEN:
630         return baz();
631       default:
632         PetscUnreachable(); // program is ill-formed if executed
633     }
634   }
635 .ve
636 
637 .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
638 M*/
639 #if PETSC_CPP_VERSION >= 23
640   #include <utility>
641   #define PetscUnreachable() std::unreachable()
642 #elif defined(__GNUC__)
643   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
644   #define PetscUnreachable() __builtin_unreachable()
645 #elif defined(_MSC_VER) /* MSVC */
646   #define PetscUnreachable() __assume(0)
647 #else /* ??? */
648   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
649 #endif
650 
651 /*MC
652   PetscAssume - Indicate to the compiler a condition that is defined to be true
653 
654   Synopsis:
655   #include <petscmacros.h>
656   void PetscAssume(bool cond)
657 
658   Input Parameter:
659 . cond - Boolean expression
660 
661   Level: advanced
662 
663   Notes:
664   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
665   truth. The argument itself is never evaluated, so any side effects of the expression will be
666   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
667   checks that would be lost in optimized builds. For example\:
668 
669 .vb
670   PetscErrorCode foo(PetscInt x) {
671 
672     PetscAssert(x >= 0, ...);
673   }
674 .ve
675 
676   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
677   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
678   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
679   optimizer cannot deduce any information from them.
680 
681   Due to compiler limitations `PetscAssume()` works best when `cond` involves
682   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
683 
684 .vb
685   int a, b, var_five;
686 
687   // BEST, all supporting compilers will understand a cannot be >= 5
688   PetscAssume(a < 5);
689 
690    // OK, some compilers may understand that a cannot be >= 5
691   PetscAssume(a <= b && b < 5);
692 
693    // WORST, most compilers will not get the memo
694   PetscAssume(a <= b && b < var_five);
695 .ve
696 
697   If the condition is violated at runtime then behavior is wholly undefined. If the
698   condition is violated at compile-time, the condition "supersedes" the compile-time violation
699   and the program is ill-formed, no diagnostic required. For example consider the following\:
700 
701 .vb
702   PetscInt x = 0;
703 
704   PetscAssume(x != 0);
705   if (x == 0) {
706     x += 10;
707   } else {
708     popen("rm -rf /", "w");
709   }
710 .ve
711 
712   Even though `x` is demonstrably `0` the compiler may opt to\:
713 
714   - emit an unconditional `popen("rm -rf /", "w")`
715   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
716   - reformat the primary disk partition
717 
718 .seealso: `PetscAssert()`
719 M*/
720 #if PETSC_CPP_VERSION >= 23
721   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
722 #elif defined(_MSC_VER) // msvc
723   #define PetscAssume(...) __assume(__VA_ARGS__)
724 #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
725   #define PetscAssume(...) \
726     do { \
727       _Pragma("clang diagnostic push"); \
728       _Pragma("clang diagnostic ignored \"-Wassume\""); \
729       __builtin_assume(__VA_ARGS__); \
730       _Pragma("clang diagnostic pop"); \
731     } while (0)
732 #else // gcc (and really old clang)
733   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
734   //
735   // if (PetscUnlikely(!cond)) PetscUnreachable();
736   //
737   // but this it unsavory because the side effects of cond are not guaranteed to be
738   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
739   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
740   // always do so. This is especially the case for opaque or non-inline function calls:
741   //
742   // extern int bar(int);
743   //
744   // int foo(int x) {
745   //   PetscAssume(bar(x) == 2);
746   //   if (bar(x) == 2) {
747   //     return 1;
748   //   } else {
749   //     return 0;
750   //   }
751   // }
752   //
753   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
754   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
755   #define PetscAssume(...) \
756     do { \
757       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
758     } while (0)
759 #endif
760 
761 /*MC
762   PetscExpand - Expand macro argument
763 
764   Synopsis:
765   #include <petscmacros.h>
766   <macro-expansion> PetscExpand(x)
767 
768   Input Parameter:
769 . x - The preprocessor token to expand
770 
771   Level: beginner
772 
773 .seealso: `PetscStringize()`, `PetscConcat()`
774 M*/
775 #define PetscExpand_(...) __VA_ARGS__
776 #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
777 
778 /*MC
779   PetscStringize - Stringize a token
780 
781   Synopsis:
782   #include <petscmacros.h>
783   const char* PetscStringize(x)
784 
785   No Fortran Support
786 
787   Input Parameter:
788 . x - The token you would like to stringize
789 
790   Output Parameter:
791 . <return-value> - The string representation of `x`
792 
793   Level: beginner
794 
795   Note:
796   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
797   `PetscStringize_()` instead.
798 
799   Example Usage:
800 .vb
801   #define MY_OTHER_VAR hello there
802   #define MY_VAR       MY_OTHER_VAR
803 
804   PetscStringize(MY_VAR)  -> "hello there"
805   PetscStringize_(MY_VAR) -> "MY_VAR"
806 
807   int foo;
808   PetscStringize(foo)  -> "foo"
809   PetscStringize_(foo) -> "foo"
810 .ve
811 
812 .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
813 M*/
814 #define PetscStringize_(...) #__VA_ARGS__
815 #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
816 
817 /*MC
818   PetscConcat - Concatenate two tokens
819 
820   Synopsis:
821   #include <petscmacros.h>
822   <macro-expansion> PetscConcat(x, y)
823 
824   No Fortran Support
825 
826   Input Parameters:
827 + x - First token
828 - y - Second token
829 
830   Level: beginner
831 
832   Note:
833   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
834   if you don't want to expand them.
835 
836   Example usage:
837 .vb
838   PetscConcat(hello,there) -> hellothere
839 
840   #define HELLO hello
841   PetscConcat(HELLO,there)  -> hellothere
842   PetscConcat_(HELLO,there) -> HELLOthere
843 .ve
844 
845 .seealso: `PetscStringize()`, `PetscExpand()`
846 M*/
847 #define PetscConcat_(x, y) x##y
848 #define PetscConcat(x, y)  PetscConcat_(x, y)
849 
850 #define PETSC_INTERNAL_COMPL_0 1
851 #define PETSC_INTERNAL_COMPL_1 0
852 
853 /*MC
854   PetscCompl - Expands to the integer complement of its argument
855 
856   Synopsis:
857   #include <petscmacros.h>
858   int PetscCompl(b)
859 
860   No Fortran Support
861 
862   Input Parameter:
863 . b - Preprocessor variable, must expand to either integer literal 0 or 1
864 
865   Output Parameter:
866 . <return-value> - Either integer literal 0 or 1
867 
868   Level: beginner
869 
870   Notes:
871   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
872   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
873   argument before returning the complement.
874 
875   This macro can be useful for negating `PetscDefined()` inside macros e.g.
876 .vb
877   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
878 .ve
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 .vb
920   #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
921 .ve
922 
923   Developer Notes:
924   Getting something that works in C and CPP for an arg that may or may not be defined is
925   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
926   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
927   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
928   and when the last step cherry picks the 2nd arg, we get a zero.
929 
930   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
931   nonconforming implementation of variadic macros.
932 
933   Example Usage:
934   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
935   is defined then
936 
937 .vb
938   #if PetscDefined(USE_DEBUG)
939     foo();
940   #else
941     bar();
942   #endif
943 
944   // or alternatively within normal code
945   if (PetscDefined(USE_DEBUG)) {
946     foo();
947   } else {
948     bar();
949   }
950 .ve
951 
952   is equivalent to
953 
954 .vb
955   #if defined(PETSC_USE_DEBUG)
956   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
957        foo();
958   #   elif PETSC_USE_DEBUG == 1
959        foo();
960   #   else
961        bar();
962   #  endif
963   #else
964   bar();
965   #endif
966 .ve
967 
968 .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
969           `PetscExpandToNothing()`, `PetscCompl()`
970 M*/
971 #define PetscDefined_arg_1                                    shift,
972 #define PetscDefined_arg_                                     shift,
973 #define PetscDefined__take_second_expanded(ignored, val, ...) val
974 #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
975 #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
976 #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
977 #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
978 #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
979 
980 /*MC
981   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
982   the check in optimized mode
983 
984   Synopsis:
985   #include <petscmacros.h>
986   bool PetscUnlikelyDebug(bool cond)
987 
988   Not Collective; No Fortran Support
989 
990   Input Parameter:
991 . cond - Boolean expression
992 
993   Level: advanced
994 
995   Note:
996   This returns the same truth value, it is only a hint to compilers that the result of `cond` is
997   likely to be false. When PETSc is compiled in optimized mode this will always return
998   false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
999   optimized mode.
1000 
1001   Example usage:
1002   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1003   is true. So
1004 
1005 .vb
1006   if (PetscUnlikelyDebug(cond)) {
1007     foo();
1008   } else {
1009     bar();
1010   }
1011 .ve
1012 
1013   is equivalent to
1014 
1015 .vb
1016   if (PetscDefined(USE_DEBUG)) {
1017     if (PetscUnlikely(cond)) {
1018       foo();
1019     } else {
1020       bar();
1021     }
1022   } else {
1023     bar();
1024   }
1025 .ve
1026 
1027 .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1028 M*/
1029 #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1030 
1031 #if defined(PETSC_CLANG_STATIC_ANALYZER)
1032   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1033   // not what ISO C allows
1034   #define PetscMacroReturns_(retexpr, ...) \
1035     __extension__({ \
1036       __VA_ARGS__; \
1037       retexpr; \
1038     })
1039 #else
1040   #define PetscMacroReturns_(retexpr, ...) \
1041     retexpr; \
1042     do { \
1043       __VA_ARGS__; \
1044     } while (0)
1045 #endif
1046 
1047 /*MC
1048   PetscExpandToNothing - Expands to absolutely nothing
1049 
1050   Synopsis:
1051   #include <petscmacros.h>
1052   void PetscExpandToNothing(...)
1053 
1054   No Fortran Support
1055 
1056   Input Parameter:
1057 . __VA_ARGS__ - Anything at all
1058 
1059   Level: beginner
1060 
1061   Note:
1062   Must have at least 1 parameter.
1063 
1064   Example usage:
1065 .vb
1066   PetscExpandToNothing(a,b,c) -> *nothing*
1067 .ve
1068 
1069 .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1070 M*/
1071 #define PetscExpandToNothing(...)
1072 
1073 /*MC
1074   PetscMacroReturns - Define a macro body that returns a value
1075 
1076   Synopsis:
1077   #include <petscmacros.h>
1078   return_type PetscMacroReturns(return_type retexpr, ...)
1079 
1080   Input Parameters:
1081 + retexpr     - The value or expression that the macro should return
1082 - __VA_ARGS__ - The body of the macro
1083 
1084   Level: intermediate
1085 
1086   Notes:
1087   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1088   body of the macro and should not depend on values produced as a result of the expression. The
1089   user should not assume that the result of this macro is equivalent to a single logical source
1090   line. It is not portable to use macros defined using this one in conditional or loop bodies
1091   without enclosing them in curly braces\:
1092 
1093 .vb
1094   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1095 
1096   int err,x = 10;
1097 
1098   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1099   if (...) { err = FOO(x); }  // OK
1100 
1101   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1102   for (...) { err = FOO(x); } // OK
1103 .ve
1104 
1105   It is also not portable to use this macro directly inside function call, conditional, loop,
1106   or switch statements\:
1107 
1108 .vb
1109   extern void bar(int);
1110 
1111   int ret = FOO(x);
1112 
1113   bar(FOO(x)); // ERROR, may not compile
1114   bar(ret);    // OK
1115 
1116   if (FOO(x))  // ERROR, may not compile
1117   if (ret)     // OK
1118 .ve
1119 
1120   Example usage:
1121 .vb
1122   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1123 
1124   int x = 10;
1125   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1126 
1127   // multiline macros allowed, but must declare with line continuation as usual
1128   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1129     if (arg1 > 10) {                                            \
1130       puts("big int!");                                         \
1131     } else {                                                    \
1132       return 7355608;                                           \
1133     }                                                           \
1134   )
1135 
1136   // if retexpr contains commas, must enclose it with braces
1137   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1138   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1139 
1140   int x = 10;
1141   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1142   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1143 .ve
1144 
1145 .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1146 M*/
1147 #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1148 
1149 #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1150 
1151 /*MC
1152   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1153 
1154   Synopsis:
1155   #include <petscmacros.h>
1156   size_t PETSC_STATIC_ARRAY_LENGTH(a)
1157 
1158   Input Parameter:
1159 . a - a static array of any type
1160 
1161   Output Parameter:
1162 . <return-value> -  the length of the array
1163 
1164   Example:
1165 .vb
1166   PetscInt a[22];
1167   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1168 .ve
1169   `sa` will have a value of 22
1170 
1171   Level: intermediate
1172 M*/
1173 #if PETSC_CPP_VERSION >= 14
1174   #include <cstddef>
1175   #include <type_traits>
1176 
1177 template <typename T>
1178 static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1179 {
1180   static_assert(std::is_array<T>::value, "");
1181   return std::extent<T, std::rank<T>::value - 1>::value;
1182 }
1183 #else
1184   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1185 #endif
1186 
1187 /*
1188   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1189 
1190   Example usage:
1191 
1192   #define mymacro(obj,...) {
1193     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1194     f(22 PETSC_REST_ARG(__VA_ARGS__));
1195   }
1196 
1197   Note you add a dummy extra argument to __VA_ARGS__ and enclose them in an extra set of () for PETSC_FIRST_ARG() and PETSC_REST_ARG(__VA_ARGS__) automatically adds a leading comma only if there are additional arguments
1198 
1199   Reference:
1200   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1201 */
1202 #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1203 #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1204 #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1205 #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1206 #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1207 #define PETSC_REST_HELPER_ONE(first)
1208 #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1209 #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1210 #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1211 
1212 #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1213   _Pragma(PetscStringize(name diagnostic push)) \
1214   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
1215 
1216 #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
1217 
1218 #if defined(__clang__)
1219   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1220   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1221 #elif defined(__GNUC__) || defined(__GNUG__)
1222   // gcc >= 4.6.0
1223   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1224     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1225     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1226   #endif
1227 #endif
1228 
1229 #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
1230   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1231   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1232   // only undefine these if they are not used
1233   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1234   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1235 #endif
1236 
1237 /* OpenMP support */
1238 #if defined(_OPENMP)
1239   #if defined(_MSC_VER)
1240     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1241   #else
1242     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1243   #endif
1244 #endif
1245 
1246 #ifndef PetscPragmaOMP
1247   #define PetscPragmaOMP(...)
1248 #endif
1249 
1250 /* PetscPragmaSIMD - from CeedPragmaSIMD */
1251 #if defined(__NEC__)
1252   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1253 #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1254   #define PetscPragmaSIMD _Pragma("vector")
1255 #elif defined(__GNUC__)
1256   #if __GNUC__ >= 5 && !defined(__PGI)
1257     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1258   #endif
1259 #elif defined(_OPENMP) && _OPENMP >= 201307
1260   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1261 #elif defined(PETSC_HAVE_CRAY_VECTOR)
1262   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1263 #endif
1264 
1265 #ifndef PetscPragmaSIMD
1266   #define PetscPragmaSIMD
1267 #endif
1268 
1269 #include <petsc/private/petscadvancedmacros.h>
1270 
1271 #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
1272 #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)
1273 
1274 #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
1275   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
1276                       __PETSC_DEPRECATION_MACRO__)(PetscStringize(Use replacement (since version major.minor.subminor) instead. Silence this warning (as well as all others for this version) by defining PetscConcat_(PETSC_, __SILENCE_MACRO__). __VA_ARGS__))
1277 
1278 #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
1279   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
1280 
1281 #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1282 #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1283 #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1284 #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1285 #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1286