Actual source code: petscmacros.h

      1: #pragma once

      3: #include <petscconf.h>
      4: #include <petscconf_poison.h> /* for PetscDefined() error checking */

      6: /* SUBMANSEC = Sys */

      8: #if defined(__cplusplus)
      9:   #if __cplusplus <= 201103L
     10:     #define PETSC_CPP_VERSION 11
     11:   #elif __cplusplus <= 201402L
     12:     #define PETSC_CPP_VERSION 14
     13:   #elif __cplusplus <= 201703L
     14:     #define PETSC_CPP_VERSION 17
     15:   #elif __cplusplus <= 202002L
     16:     #define PETSC_CPP_VERSION 20
     17:   #else
     18:     #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
     19:   #endif
     20: #endif // __cplusplus

     22: #ifndef PETSC_CPP_VERSION
     23:   #define PETSC_CPP_VERSION 0
     24: #endif

     26: #if defined(__STDC_VERSION__)
     27:   #if __STDC_VERSION__ <= 199901L
     28:     // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
     29:     #define PETSC_C_VERSION 9
     30:   #elif __STDC_VERSION__ <= 201112L
     31:     #define PETSC_C_VERSION 11
     32:   #elif __STDC_VERSION__ <= 201710L
     33:     #define PETSC_C_VERSION 17
     34:   #else
     35:     #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
     36:   #endif
     37: #endif // __STDC_VERSION__

     39: #ifndef PETSC_C_VERSION
     40:   #define PETSC_C_VERSION 0
     41: #endif

     43: /* ========================================================================== */
     44: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
     45: #if defined(__cplusplus)
     46:   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
     47: #else
     48:   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
     49: #endif

     51: /* ========================================================================== */
     52: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
     53:  * files within extern "C". This will generate a compiler error if a user does put the include
     54:  * file within an extern "C".
     55:  */
     56: #if defined(__cplusplus)
     57: void assert_never_put_petsc_headers_inside_an_extern_c(int);
     58: void assert_never_put_petsc_headers_inside_an_extern_c(double);
     59: #endif

     61: #if defined(__cplusplus)
     62:   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
     63: #else
     64:   #define PETSC_RESTRICT restrict
     65: #endif

     67: #define PETSC_INLINE        PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
     68: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline

     70: #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
     71:   #define  __declspec(dllexport)
     72:   #define PETSC_DLLIMPORT __declspec(dllimport)
     73:   #define PETSC_VISIBILITY_INTERNAL
     74: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
     75:   #define            __attribute__((visibility("default")))
     76:   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
     77:   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
     78: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
     79:   #define            __attribute__((visibility("default")))
     80:   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
     81:   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
     82: #else
     83:   #define
     84:   #define PETSC_DLLIMPORT
     85:   #define PETSC_VISIBILITY_INTERNAL
     86: #endif

     88: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
     89:   #define PETSC_VISIBILITY_PUBLIC
     90: #else /* Win32 users need this to import symbols from petsc.dll */
     91:   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
     92: #endif

     94: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
     95:  * compiled with C++ so they may be used from C and are always visible in the shared libraries
     96:  */
     97: #if defined(__cplusplus)
     98:   #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
     99:   #define PETSC_EXTERN_TYPEDEF extern "C"
    100:   #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
    101: #else
    102:   #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
    103:   #define PETSC_EXTERN_TYPEDEF
    104:   #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
    105: #endif

    107: #if defined(PETSC_USE_SINGLE_LIBRARY)
    108:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
    109:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_INTERN
    110: #else
    111:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
    112:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_EXTERN
    113: #endif

    117: #endif

    119: /*MC
    120:   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler

    122:   Synopsis:
    123: #include <petscmacros.h>
    124:   int PetscHasAttribute(name)

    126:   Input Parameter:
    127: . name - The name of the attribute to test

    129:   Level: intermediate

    131:   Notes:
    132:   name should be identical to what you might pass to the __attribute__ declaration itself --
    133:   plain, unbroken text.

    135:   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
    136:   exact type and value returned is implementation defined. In practice however, it usually
    137:   returns `1` if the attribute is supported and `0` if the attribute is not supported.

    139:   Example Usage:
    140:   Typical usage is using the preprocessor

    142: .vb
    143:   #if PetscHasAttribute(always_inline)
    144:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
    145:   #else
    146:   #  define MY_ALWAYS_INLINE
    147:   #endif

    149:   void foo(void) MY_ALWAYS_INLINE;
    150: .ve

    152:   but it can also be used in regular code

    154: .vb
    155:   if (PetscHasAttribute(some_attribute)) {
    156:     foo();
    157:   } else {
    158:     bar();
    159:   }
    160: .ve

    162: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
    163: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
    164: M*/
    167: #endif
    168: #define PetscHasAttribute(name) __has_attribute(name)

    170: /*MC
    171:   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler

    173:   Synopsis:
    174: #include <petscmacros.h>
    175:   int PetscHasBuiltin(name)

    177:   Input Parameter:
    178: . name - the name of the builtin routine

    180:   Level: intermediate

    182:   Notes:
    183:   Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
    184:   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
    185:   detector is itself is a compiler extension with implementation-defined return type and
    186:   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
    187:   however, all supporting compilers return an integer boolean as described.

    189:   Example Usage:
    190:   Typical usage is in preprocessor directives

    192: .vb
    193:   #if PetscHasBuiltin(__builtin_trap)
    194:   __builtin_trap();
    195:   #else
    196:   abort();
    197:   #endif
    198: .ve

    200:   But it may also be used in regular code

    202: .vb
    203:   if (PetscHasBuiltin(__builtin_alloca)) {
    204:     foo();
    205:   } else {
    206:     bar();
    207:   }
    208: .ve

    210: .seealso: `PetscHasAttribute()`, `PetscAssume()`
    211: M*/
    214: #endif
    215: // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
    216: // __builtin_types_compatible_p which take types or other non-functiony things as
    217: // arguments. The correct way to detect these then is to use __is_identifier (also a clang
    218: // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
    219: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
    220:   #define PetscHasBuiltin(name) __is_identifier(name)
    221: #else
    222:   #define PetscHasBuiltin(name) __has_builtin(name)
    223: #endif

    225: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
    226:   /*
    227:    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
    228:    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
    229:    does not match the actual type of the argument being passed in
    230: */
    231:   #if PetscHasAttribute(pointer_with_type_tag)
    232:     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
    233:   #endif

    235:   #if PetscHasAttribute(type_tag_for_datatype)
    236:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
    237:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
    238:   #endif
    239: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG

    241: #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
    242:   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
    243: #endif

    245: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
    246:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
    247: #endif

    249: #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
    250:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
    251: #endif

    253: /*MC
    254:   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
    255:   as format specifiers and checked for validity

    257:   Synopsis:
    258: #include <petscmacros.h>
    259:   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)

    261:   Input Parameters:
    262: + strIdx   - The (1-indexed) location of the format string in the argument list
    263: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list

    265:   Level: developer

    267:   Notes:
    268:   This function attribute causes the compiler to issue warnings when the format specifier does
    269:   not match the type of the variable that will be formatted, or when there exists a mismatch
    270:   between the number of format specifiers and variables to be formatted. It is safe to use this
    271:   macro if your compiler does not support format specifier checking (though this is
    272:   exceeedingly rare).

    274:   Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
    275:   same value.

    277:   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
    278:   the argument list, that is, there is no way to indicate gaps which should not be checked.

    280:   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
    281:   header files. In this case the macro will expand empty.

    283:   Example Usage:
    284: .vb
    285:   // format string is 2nd argument, variable argument list containing args is 3rd argument
    286:   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)

    288:   int    x = 1;
    289:   double y = 50.0;

    291:   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
    292:   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
    293:   my_printf(NULL,"%d %g",x,y); // OK
    294: .ve

    296: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
    297: M*/
    298: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
    299:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
    300: #else
    301:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
    302: #endif

    304: /*MC
    305:   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
    306:   executed

    308:   Level: intermediate

    310:   Notes:
    311:   The marked function is often optimized for size rather than speed and may be grouped alongside
    312:   other equally frigid routines improving code locality of lukewarm or hotter parts of program.

    314:   The paths leading to cold functions are usually automatically marked as unlikely by the
    315:   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
    316:   as error handlers -- as cold to improve optimization of the surrounding temperate functions.

    318:   Example Usage:
    319: .vb
    320:   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;

    322:   if (temperature < 0) {
    323:     return my_error_handler(...); // chilly!
    324:   }
    325: .ve

    327: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
    328:           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
    329: M*/
    330: #if PetscHasAttribute(__cold__)
    331:   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
    332: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
    333:   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
    334: #else
    335:   #define PETSC_ATTRIBUTE_COLD
    336: #endif

    338: /*MC
    339:   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
    340:   subjected to type-based alias analysis, but is instead assumed to be able to
    341:   alias any other type of objects

    343:   Example Usage:
    344: .vb
    345:   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;

    347:   PetscReal        *pointer;
    348:   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
    349: .ve

    351:   Level: advanced

    353: .seealso: `PetscHasAttribute()`
    354: M*/
    355: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
    356:   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
    357: #else
    358:   #define PETSC_ATTRIBUTE_MAY_ALIAS
    359: #endif

    361: /*MC
    362:   PETSC_NULLPTR - Standard way of indicating a null value or pointer

    364:   No Fortran Support

    366:   Level: beginner

    368:   Notes:
    369:   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
    370:   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
    371:   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
    372:   expressions are equivalent\:

    374: .vb
    375:   ptr == PETSC_NULLPTR
    376:   ptr == NULL
    377:   ptr == 0
    378:   !ptr

    380:   ptr = PETSC_NULLPTR
    381:   ptr = NULL
    382:   ptr = 0
    383: .ve

    385:   and for completeness' sake\:

    387: .vb
    388:   PETSC_NULLPTR == NULL
    389: .ve

    391:   Example Usage:
    392: .vb
    393:   // may be used in place of '\0' or other such terminators in the definition of char arrays
    394:   const char *const MyEnumTypes[] = {
    395:     "foo",
    396:     "bar",
    397:     PETSC_NULLPTR
    398:   };

    400:   // may be used to nullify objects
    401:   PetscObject obj = PETSC_NULLPTR;

    403:   // may be used in any function expecting NULL
    404:   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
    405: .ve

    407:   Developer Notes:
    408:   `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
    409:   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
    410:   resolution and/or compiler warnings.

    412: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
    413: M*/

    415: /*MC
    416:   PETSC_CONSTEXPR_14 - C++14 constexpr

    418:   No Fortran Support

    420:   Level: beginner

    422:   Notes:
    423:   Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
    424:   if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
    425:   that this cannot be used in cases where an empty expansion would result in invalid code. It
    426:   is safe to use this in C source files.

    428:   Example Usage:
    429: .vb
    430:   PETSC_CONSTEXPR_14 int factorial(int n)
    431:   {
    432:     int r = 1;

    434:     do {
    435:       r *= n;
    436:     } while (--n);
    437:     return r;
    438:   }
    439: .ve

    441: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
    442: M*/

    444: /*MC
    445:   PETSC_NODISCARD - Mark the return value of a function as non-discardable

    447:   Not available in Fortran

    449:   Level: beginner

    451:   Notes:
    452:   Hints to the compiler that the return value of a function must be captured. A diagnostic may
    453:   (but is not required to) be emitted if the value is discarded. It is safe to use this in both
    454:   C and C++ source files.

    456:   In this context "captured" means assigning the return value of a function to a named
    457:   variable or casting it to `void`. Between the two, assigning to a named variable is the most
    458:   portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
    459:   `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
    460:   `void`.

    462:   Example Usage:
    463: .vb
    464:   class Foo
    465:   {
    466:     int x;

    468:   public:
    469:     PETSC_NODISCARD Foo(int y) : x(y) { }
    470:   };

    472:   PETSC_NODISCARD int factorial(int n)
    473:   {
    474:     return n <= 1 ? 1 : (n * factorial(n - 1));
    475:   }

    477:   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
    478:   auto x = factorial(10); // OK, capturing return value
    479:   (void)factorial(10);    // Maybe OK, casting to void
    480:   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
    481:   (void)y;                // set-but-not-used warnings)

    483:   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
    484:   auto f = Foo(x); // OK, capturing constructed object
    485:   (void)Foo(x);    // Maybe OK, casting to void
    486:   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
    487:   (void)g;         // warnings)
    488: .ve

    490: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
    491: M*/

    493: /* C++11 features */
    494: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
    495:   #define PETSC_NULLPTR nullptr
    496: #else
    497:   #define PETSC_NULLPTR NULL
    498: #endif

    500: /* C++14 features */
    501: #if PETSC_CPP_VERSION >= 14
    502:   #define PETSC_CONSTEXPR_14 constexpr
    503: #else
    504:   #define PETSC_CONSTEXPR_14
    505: #endif

    507: /* C++17 features */
    508: #if PETSC_CPP_VERSION >= 17
    509:   #define PETSC_CONSTEXPR_17 constexpr
    510: #else
    511:   #define PETSC_CONSTEXPR_17
    512: #endif

    514: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
    515:   #define PETSC_NODISCARD [[nodiscard]]
    516: #elif PetscHasAttribute(warn_unused_result)
    517:   #define PETSC_NODISCARD __attribute__((warn_unused_result))
    518: #else
    519:   #define PETSC_NODISCARD
    520: #endif

    522: #include <petscversion.h>
    523: #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"

    525: /* designated initializers since C99 and C++20, MSVC never supports them though */
    526: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
    527:   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
    528: #else
    529:   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
    530: #endif

    532: /*MC
    533:   PetscUnlikely - Hints the compiler that the given condition is usually false

    535:   Synopsis:
    536: #include <petscmacros.h>
    537:   bool PetscUnlikely(bool cond)

    539:   Not Collective; No Fortran Support

    541:   Input Parameter:
    542: . cond - Boolean expression

    544:   Level: advanced

    546:   Note:
    547:   This returns the same truth value, it is only a hint to compilers that the result of cond is
    548:   unlikely to be true.

    550:   Example usage:
    551: .vb
    552:   if (PetscUnlikely(cond)) {
    553:     foo(); // cold path
    554:   } else {
    555:     bar(); // hot path
    556:   }
    557: .ve

    559: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
    560:           `PETSC_ATTRIBUTE_COLD`
    561: M*/

    563: /*MC
    564:   PetscLikely - Hints the compiler that the given condition is usually true

    566:   Synopsis:
    567: #include <petscmacros.h>
    568:   bool PetscLikely(bool cond)

    570:   Not Collective; No Fortran Support

    572:   Input Parameter:
    573: . cond - Boolean expression

    575:   Level: advanced

    577:   Note:
    578:   This returns the same truth value, it is only a hint to compilers that the result of cond is
    579:   likely to be true.

    581:   Example usage:
    582: .vb
    583:   if (PetscLikely(cond)) {
    584:     foo(); // hot path
    585:   } else {
    586:     bar(); // cold path
    587:   }
    588: .ve

    590: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
    591:           `PETSC_ATTRIBUTE_COLD`
    592: M*/
    593: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
    594:   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
    595:   #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
    596: #else
    597:   #define PetscUnlikely(cond) (cond)
    598:   #define PetscLikely(cond)   (cond)
    599: #endif

    601: /*MC
    602:   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable

    604:   Synopsis:
    605: #include <petscmacros.h>
    606:   void PetscUnreachable(void)

    608:   Level: advanced

    610:   Note:
    611:   Indicates to the compiler (usually via some built-in) that a particular code path is always
    612:   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
    613:   unceremonious crash.

    615:   Example usage:
    616:   Useful in situations such as switches over enums where not all enumeration values are
    617:   explicitly covered by the switch

    619: .vb
    620:   typedef enum {RED, GREEN, BLUE} Color;

    622:   int foo(Color c)
    623:   {
    624:     // it is known to programmer (or checked previously) that c is either RED or GREEN
    625:     // but compiler may not be able to deduce this and/or emit spurious warnings
    626:     switch (c) {
    627:       case RED:
    628:         return bar();
    629:       case GREEN:
    630:         return baz();
    631:       default:
    632:         PetscUnreachable(); // program is ill-formed if executed
    633:     }
    634:   }
    635: .ve

    637: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
    638: M*/
    639: #if PETSC_CPP_VERSION >= 23
    640:   #include <utility>
    641:   #define PetscUnreachable() std::unreachable()
    642: #elif defined(__GNUC__)
    643:   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
    644:   #define PetscUnreachable() __builtin_unreachable()
    645: #elif defined(_MSC_VER) /* MSVC */
    646:   #define PetscUnreachable() __assume(0)
    647: #else /* ??? */
    648:   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
    649: #endif

    651: /*MC
    652:   PetscAssume - Indicate to the compiler a condition that is defined to be true

    654:   Synopsis:
    655: #include <petscmacros.h>
    656:   void PetscAssume(bool cond)

    658:   Input Parameter:
    659: . cond - Boolean expression

    661:   Level: advanced

    663:   Notes:
    664:   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
    665:   truth. The argument itself is never evaluated, so any side effects of the expression will be
    666:   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
    667:   checks that would be lost in optimized builds. For example\:

    669: .vb
    670:   PetscErrorCode foo(PetscInt x) {

    672:     PetscAssert(x >= 0, ...);
    673:   }
    674: .ve

    676:   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
    677:   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
    678:   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
    679:   optimizer cannot deduce any information from them.

    681:   Due to compiler limitations `PetscAssume()` works best when `cond` involves
    682:   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:

    684: .vb
    685:   int a, b, var_five;

    687:   // BEST, all supporting compilers will understand a cannot be >= 5
    688:   PetscAssume(a < 5);

    690:    // OK, some compilers may understand that a cannot be >= 5
    691:   PetscAssume(a <= b && b < 5);

    693:    // WORST, most compilers will not get the memo
    694:   PetscAssume(a <= b && b < var_five);
    695: .ve

    697:   If the condition is violated at runtime then behavior is wholly undefined. If the
    698:   condition is violated at compile-time, the condition "supersedes" the compile-time violation
    699:   and the program is ill-formed, no diagnostic required. For example consider the following\:

    701: .vb
    702:   PetscInt x = 0;

    704:   PetscAssume(x != 0);
    705:   if (x == 0) {
    706:     x += 10;
    707:   } else {
    708:     popen("rm -rf /", "w");
    709:   }
    710: .ve

    712:   Even though `x` is demonstrably `0` the compiler may opt to\:

    714:   - emit an unconditional `popen("rm -rf /", "w")`
    715:   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
    716:   - reformat the primary disk partition

    718: .seealso: `PetscAssert()`
    719: M*/
    720: #if PETSC_CPP_VERSION >= 23
    721:   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
    722: #elif defined(_MSC_VER) // msvc
    723:   #define PetscAssume(...) __assume(__VA_ARGS__)
    724: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
    725:   #define PetscAssume(...) \
    726:     do { \
    727:       _Pragma("clang diagnostic push"); \
    728:       _Pragma("clang diagnostic ignored \"-Wassume\""); \
    729:       __builtin_assume(__VA_ARGS__); \
    730:       _Pragma("clang diagnostic pop"); \
    731:     } while (0)
    732: #else // gcc (and really old clang)
    733:   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
    734:   //
    735:   // if (PetscUnlikely(!cond)) PetscUnreachable();
    736:   //
    737:   // but this it unsavory because the side effects of cond are not guaranteed to be
    738:   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
    739:   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
    740:   // always do so. This is especially the case for opaque or non-inline function calls:
    741:   //
    742:   // extern int bar(int);
    743:   //
    744:   // int foo(int x) {
    745:   //   PetscAssume(bar(x) == 2);
    746:   //   if (bar(x) == 2) {
    747:   //     return 1;
    748:   //   } else {
    749:   //     return 0;
    750:   //   }
    751:   // }
    752:   //
    753:   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
    754:   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
    755:   #define PetscAssume(...) \
    756:     do { \
    757:       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
    758:     } while (0)
    759: #endif

    761: /*MC
    762:   PetscExpand - Expand macro argument

    764:   Synopsis:
    765: #include <petscmacros.h>
    766:   <macro-expansion> PetscExpand(x)

    768:   Input Parameter:
    769: . x - The preprocessor token to expand

    771:   Level: beginner

    773: .seealso: `PetscStringize()`, `PetscConcat()`
    774: M*/
    775: #define PetscExpand_(...) __VA_ARGS__
    776: #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)

    778: /*MC
    779:   PetscStringize - Stringize a token

    781:   Synopsis:
    782: #include <petscmacros.h>
    783:   const char* PetscStringize(x)

    785:   No Fortran Support

    787:   Input Parameter:
    788: . x - The token you would like to stringize

    790:   Output Parameter:
    791: . <return-value> - The string representation of `x`

    793:   Level: beginner

    795:   Note:
    796:   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
    797:   `PetscStringize_()` instead.

    799:   Example Usage:
    800: .vb
    801:   #define MY_OTHER_VAR hello there
    802:   #define MY_VAR       MY_OTHER_VAR

    804:   PetscStringize(MY_VAR)  -> "hello there"
    805:   PetscStringize_(MY_VAR) -> "MY_VAR"

    807:   int foo;
    808:   PetscStringize(foo)  -> "foo"
    809:   PetscStringize_(foo) -> "foo"
    810: .ve

    812: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
    813: M*/
    814: #define PetscStringize_(...) #__VA_ARGS__
    815: #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)

    817: /*MC
    818:   PetscConcat - Concatenate two tokens

    820:   Synopsis:
    821: #include <petscmacros.h>
    822:   <macro-expansion> PetscConcat(x, y)

    824:   No Fortran Support

    826:   Input Parameters:
    827: + x - First token
    828: - y - Second token

    830:   Level: beginner

    832:   Note:
    833:   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
    834:   if you don't want to expand them.

    836:   Example usage:
    837: .vb
    838:   PetscConcat(hello,there) -> hellothere

    840:   #define HELLO hello
    841:   PetscConcat(HELLO,there)  -> hellothere
    842:   PetscConcat_(HELLO,there) -> HELLOthere
    843: .ve

    845: .seealso: `PetscStringize()`, `PetscExpand()`
    846: M*/
    847: #define PetscConcat_(x, y) x##y
    848: #define PetscConcat(x, y)  PetscConcat_(x, y)

    850: #define PETSC_INTERNAL_COMPL_0 1
    851: #define PETSC_INTERNAL_COMPL_1 0

    853: /*MC
    854:   PetscCompl - Expands to the integer complement of its argument

    856:   Synopsis:
    857: #include <petscmacros.h>
    858:   int PetscCompl(b)

    860:   No Fortran Support

    862:   Input Parameter:
    863: . b - Preprocessor variable, must expand to either integer literal 0 or 1

    865:   Output Parameter:
    866: . <return-value> - Either integer literal 0 or 1

    868:   Level: beginner

    870:   Notes:
    871:   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
    872:   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
    873:   argument before returning the complement.

    875:   This macro can be useful for negating `PetscDefined()` inside macros e.g.
    876: .vb
    877:   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
    878: .ve

    880:   Example usage:
    881: .vb
    882:   #define MY_VAR 1
    883:   PetscCompl(MY_VAR) -> 0

    885:   #undef  MY_VAR
    886:   #define MY_VAR 0
    887:   PetscCompl(MY_VAR) -> 1
    888: .ve

    890: .seealso: `PetscConcat()`, `PetscDefined()`
    891: M*/
    892: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))

    894: /*MC
    895:   PetscDefined - Determine whether a boolean macro is defined

    897:   Synopsis:
    898: #include <petscmacros.h>
    899:   int PetscDefined(def)

    901:   No Fortran Support

    903:   Input Parameter:
    904: . def - PETSc-style preprocessor variable (without PETSC_ prepended!)

    906:   Output Parameter:
    907: . <return-value> - Either integer literal 0 or 1

    909:   Level: intermediate

    911:   Notes:
    912:   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
    913:   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
    914:   this macro should not be used if its argument may be defined to a non-empty value other than
    915:   1.

    917:   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
    918:   add custom checks in user code, one should use `PetscDefined_()`.
    919: .vb
    920:   #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
    921: .ve

    923:   Developer Notes:
    924:   Getting something that works in C and CPP for an arg that may or may not be defined is
    925:   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
    926:   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
    927:   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
    928:   and when the last step cherry picks the 2nd arg, we get a zero.

    930:   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
    931:   nonconforming implementation of variadic macros.

    933:   Example Usage:
    934:   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
    935:   is defined then

    937: .vb
    938:   #if PetscDefined(USE_DEBUG)
    939:     foo();
    940:   #else
    941:     bar();
    942:   #endif

    944:   // or alternatively within normal code
    945:   if (PetscDefined(USE_DEBUG)) {
    946:     foo();
    947:   } else {
    948:     bar();
    949:   }
    950: .ve

    952:   is equivalent to

    954: .vb
    955:   #if defined(PETSC_USE_DEBUG)
    956:   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
    957:        foo();
    958:   #   elif PETSC_USE_DEBUG == 1
    959:        foo();
    960:   #   else
    961:        bar();
    962:   #  endif
    963:   #else
    964:   bar();
    965:   #endif
    966: .ve

    968: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
    969:           `PetscExpandToNothing()`, `PetscCompl()`
    970: M*/
    971: #define PetscDefined_arg_1                                    shift,
    972: #define PetscDefined_arg_                                     shift,
    973: #define PetscDefined__take_second_expanded(ignored, val, ...) val
    974: #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
    975: #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
    976: #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
    977: #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
    978: #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))

    980: /*MC
    981:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
    982:   the check in optimized mode

    984:   Synopsis:
    985: #include <petscmacros.h>
    986:   bool PetscUnlikelyDebug(bool cond)

    988:   Not Collective; No Fortran Support

    990:   Input Parameter:
    991: . cond - Boolean expression

    993:   Level: advanced

    995:   Note:
    996:   This returns the same truth value, it is only a hint to compilers that the result of `cond` is
    997:   likely to be false. When PETSc is compiled in optimized mode this will always return
    998:   false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
    999:   optimized mode.

    1001:   Example usage:
    1002:   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
    1003:   is true. So

    1005: .vb
    1006:   if (PetscUnlikelyDebug(cond)) {
    1007:     foo();
    1008:   } else {
    1009:     bar();
    1010:   }
    1011: .ve

    1013:   is equivalent to

    1015: .vb
    1016:   if (PetscDefined(USE_DEBUG)) {
    1017:     if (PetscUnlikely(cond)) {
    1018:       foo();
    1019:     } else {
    1020:       bar();
    1021:     }
    1022:   } else {
    1023:     bar();
    1024:   }
    1025: .ve

    1027: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
    1028: M*/
    1029: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))

    1031: #if defined(PETSC_CLANG_STATIC_ANALYZER)
    1032:   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
    1033:   // not what ISO C allows
    1034:   #define PetscMacroReturns_(retexpr, ...) \
    1035:     __extension__({ \
    1036:       __VA_ARGS__; \
    1037:       retexpr; \
    1038:     })
    1039: #else
    1040:   #define PetscMacroReturns_(retexpr, ...) \
    1041:     retexpr; \
    1042:     do { \
    1043:       __VA_ARGS__; \
    1044:     } while (0)
    1045: #endif

    1047: /*MC
    1048:   PetscExpandToNothing - Expands to absolutely nothing

    1050:   Synopsis:
    1051: #include <petscmacros.h>
    1052:   void PetscExpandToNothing(...)

    1054:   No Fortran Support

    1056:   Input Parameter:
    1057: . __VA_ARGS__ - Anything at all

    1059:   Level: beginner

    1061:   Note:
    1062:   Must have at least 1 parameter.

    1064:   Example usage:
    1065: .vb
    1066:   PetscExpandToNothing(a,b,c) -> *nothing*
    1067: .ve

    1069: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
    1070: M*/
    1071: #define PetscExpandToNothing(...)

    1073: /*MC
    1074:   PetscMacroReturns - Define a macro body that returns a value

    1076:   Synopsis:
    1077: #include <petscmacros.h>
    1078:   return_type PetscMacroReturns(return_type retexpr, ...)

    1080:   Input Parameters:
    1081: + retexpr     - The value or expression that the macro should return
    1082: - __VA_ARGS__ - The body of the macro

    1084:   Level: intermediate

    1086:   Notes:
    1087:   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
    1088:   body of the macro and should not depend on values produced as a result of the expression. The
    1089:   user should not assume that the result of this macro is equivalent to a single logical source
    1090:   line. It is not portable to use macros defined using this one in conditional or loop bodies
    1091:   without enclosing them in curly braces\:

    1093: .vb
    1094:   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0

    1096:   int err,x = 10;

    1098:   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
    1099:   if (...) { err = FOO(x); }  // OK

    1101:   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
    1102:   for (...) { err = FOO(x); } // OK
    1103: .ve

    1105:   It is also not portable to use this macro directly inside function call, conditional, loop,
    1106:   or switch statements\:

    1108: .vb
    1109:   extern void bar(int);

    1111:   int ret = FOO(x);

    1113:   bar(FOO(x)); // ERROR, may not compile
    1114:   bar(ret);    // OK

    1116:   if (FOO(x))  // ERROR, may not compile
    1117:   if (ret)     // OK
    1118: .ve

    1120:   Example usage:
    1121: .vb
    1122:   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)

    1124:   int x = 10;
    1125:   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20

    1127:   // multiline macros allowed, but must declare with line continuation as usual
    1128:   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
    1129:     if (arg1 > 10) {                                            \
    1130:       puts("big int!");                                         \
    1131:     } else {                                                    \
    1132:       return 7355608;                                           \
    1133:     }                                                           \
    1134:   )

    1136:   // if retexpr contains commas, must enclose it with braces
    1137:   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
    1138:   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)

    1140:   int x = 10;
    1141:   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
    1142:   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
    1143: .ve

    1145: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
    1146: M*/
    1147: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)

    1149: #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)

    1151: /*MC
    1152:   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array

    1154:   Synopsis:
    1155: #include <petscmacros.h>
    1156:   size_t PETSC_STATIC_ARRAY_LENGTH(a)

    1158:   Input Parameter:
    1159: . a - a static array of any type

    1161:   Output Parameter:
    1162: . <return-value> -  the length of the array

    1164:   Example:
    1165: .vb
    1166:   PetscInt a[22];
    1167:   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
    1168: .ve
    1169:   `sa` will have a value of 22

    1171:   Level: intermediate
    1172: M*/
    1173: #if PETSC_CPP_VERSION >= 14
    1174:   #include <cstddef>
    1175:   #include <type_traits>

    1177: template <typename T>
    1178: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
    1179: {
    1180:   static_assert(std::is_array<T>::value, "");
    1181:   return std::extent<T, std::rank<T>::value - 1>::value;
    1182: }
    1183: #else
    1184:   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
    1185: #endif

    1187: /*
    1188:   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.

    1190:   Example usage:

    1192:   #define mymacro(obj,...) {
    1193:     PETSC_FIRST_ARG((__VA_ARGS__,unused));
    1194:     f(22 PETSC_REST_ARG(__VA_ARGS__));
    1195:   }

    1197:   Note you add a dummy extra argument to __VA_ARGS__ and enclose them in an extra set of () for PETSC_FIRST_ARG() and PETSC_REST_ARG(__VA_ARGS__) automatically adds a leading comma only if there are additional arguments

    1199:   Reference:
    1200:   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
    1201: */
    1202: #define PETSC_FIRST_ARG_(N, ...)                                                                      N
    1203: #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
    1204: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
    1205: #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
    1206: #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
    1207: #define PETSC_REST_HELPER_ONE(first)
    1208: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
    1209: #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
    1210: #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)

    1212: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
    1213:   _Pragma(PetscStringize(name diagnostic push)) \
    1214:   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))

    1216: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))

    1218: #if defined(__clang__)
    1219:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
    1220:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
    1221: #elif defined(__GNUC__) || defined(__GNUG__)
    1222:   // gcc >= 4.6.0
    1223:   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
    1224:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
    1225:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
    1226:   #endif
    1227: #endif

    1229: #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
    1230:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
    1231:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
    1232:   // only undefine these if they are not used
    1233:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
    1234:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
    1235: #endif

    1237: /*MC
    1238:   PetscPragmaOMP - Sets an OpenMP pragma to affect the next block of code

    1240:   Synopsis:
    1241: #include <petscmacros.h>
    1242:   int PetscPragmaOMP(name)

    1244:   No Fortran Support

    1246:   Input Parameter:
    1247: . name - the OpenMP pragma, for example, `critical` or `parallel for`

    1249:   Level: intermediate

    1251:   Note:
    1252:   The pragma takes effect when PETSc was configured with `--with-openmp`. See `PetscPragmaUseOMPKernels()`
    1253:   for when PETSc was configured to use OpenMP in some of its numerical kernels.

    1255: .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
    1256: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
    1257: M*/
    1258: #if defined(_OPENMP)
    1259:   #if defined(_MSC_VER)
    1260:     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
    1261:   #else
    1262:     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
    1263:   #endif
    1264: #else
    1265:   #define PetscPragmaOMP(...)
    1266: #endif

    1268: /*MC
    1269:   PetscPragmaUseOMPKernels - Sets an OpenMP pragma to affect the next block of code

    1271:   Synopsis:
    1272: #include <petscmacros.h>
    1273:   int PetscPragmaUseOMPKernels(name)

    1275:   No Fortran Support

    1277:   Input Parameter:
    1278: . name - the OpenMP pragma, for example, `critical` or `parallel for`

    1280:   Level: intermediate

    1282:   Note:
    1283:   The pragma takes effect when PETSc was configured with `--with-openmp-kernels`. See `PetscPragmaOMP()`
    1284:   for when PETSc was configured with OpenMP but not to use it in its numerical kernels

    1286: .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
    1287: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
    1288: M*/
    1289: #if defined(PETSC_USE_OPENMP_KERNELS)
    1290:   #if defined(_MSC_VER)
    1291:     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
    1292:   #else
    1293:     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
    1294:   #endif
    1295: #else
    1296:   #define PetscPragmaUseOMPKernels(...)
    1297: #endif

    1299: /* PetscPragmaSIMD - from CeedPragmaSIMD */
    1300: #if defined(__NEC__)
    1301:   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
    1302: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
    1303:   #define PetscPragmaSIMD _Pragma("vector")
    1304: #elif defined(__GNUC__)
    1305:   #if __GNUC__ >= 5 && !defined(__PGI)
    1306:     #define PetscPragmaSIMD _Pragma("GCC ivdep")
    1307:   #endif
    1308: #elif defined(_OPENMP) && _OPENMP >= 201307
    1309:   #define PetscPragmaSIMD PetscPragmaOMP(simd)
    1310: #elif defined(PETSC_HAVE_CRAY_VECTOR)
    1311:   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
    1312: #endif

    1314: #ifndef PetscPragmaSIMD
    1315:   #define PetscPragmaSIMD
    1316: #endif

    1318: #include <petsc/private/petscadvancedmacros.h>

    1320: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
    1321: #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)

    1323: #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
    1324:   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
    1325:                       __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__))

    1327: #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
    1328:   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)

    1330: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
    1331: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
    1332: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
    1333: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
    1334: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)