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: #if !defined(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: #if !defined(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: /*MC
108:   PETSC_TLS - Marks a variable as thread-local when PETSc is configured with thread safety

110:   Synopsis:
111: #include <petscmacros.h>
112:   PETSC_TLS type variable;

114:   Level: developer

116:   Notes:
117:   When configured with `--with-threadsafety=1`, each thread has its own instance of the variable, whose lifetime is the lifetime of that thread.
118:   With `--with-threadsafety=0`, `PETSC_TLS` expands to nothing.

120:   In C, this macro uses C11 `_Thread_local`. In C++, it uses C++11 `thread_local`, except with Clang, where it uses `_Thread_local`
121:   to allow C++ code to access thread-local variables defined in C without requiring C++ initialization wrappers.

123:   Use `PETSC_EXTERN PETSC_TLS` for an exported declaration or `PETSC_INTERN PETSC_TLS` for an internal declaration.

125:   Example Usage:
126: .vb
127:   // In a header
128:   PETSC_EXTERN PETSC_TLS int counter;

130:   // In the source file that defines the variable
131:   PETSC_TLS int counter = 0;
132: .ve

134: .seealso: `PetscStack`, `PetscStackView()`
135: M*/
136: #if defined(PETSC_HAVE_THREADSAFETY)
137:   /* Clang's C++ thread_local can require initialization wrappers absent from C definitions. */
138:   #if defined(__cplusplus) && !defined(__clang__)
139:     #define PETSC_TLS thread_local
140:   #else
141:     #define PETSC_TLS _Thread_local
142:   #endif
143: #else
144:   #define PETSC_TLS
145: #endif

147: #if defined(PETSC_USE_SINGLE_LIBRARY)
148:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
149:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_INTERN
150: #else
151:   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
152:   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_EXTERN
153: #endif

157: #endif

161: #endif

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

166:   Synopsis:
167: #include <petscmacros.h>
168:   int PetscHasAttribute(name)

170:   Input Parameter:
171: . name - The name of the attribute to test

173:   Level: intermediate

175:   Notes:
176:   name should be identical to what you might pass to the __attribute__ declaration itself --
177:   plain, unbroken text.

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

183:   Example Usage:
184:   Typical usage is using the preprocessor

186: .vb
187:   #if PetscHasAttribute(always_inline)
188:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
189:   #else
190:   #  define MY_ALWAYS_INLINE
191:   #endif

193:   void foo(void) MY_ALWAYS_INLINE;
194: .ve

196:   but it can also be used in regular code

198: .vb
199:   if (PetscHasAttribute(some_attribute)) {
200:     foo();
201:   } else {
202:     bar();
203:   }
204: .ve

206: .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
207: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
208: M*/
209: #define PetscHasAttribute(name) __has_attribute(name)

213: #endif

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

218:   Synopsis:
219: #include <petscmacros.h>
220:   int PetscHasBuiltin(name)

222:   Input Parameter:
223: . name - the name of the builtin routine

225:   Level: intermediate

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

234:   Example Usage:
235:   Typical usage is in preprocessor directives

237: .vb
238:   #if PetscHasBuiltin(__builtin_trap)
239:   __builtin_trap();
240:   #else
241:   abort();
242:   #endif
243: .ve

245:   But it may also be used in regular code

247: .vb
248:   if (PetscHasBuiltin(__builtin_alloca)) {
249:     foo();
250:   } else {
251:     bar();
252:   }
253: .ve

255:   Developer Note:
256:   Clang's `__has_builtin()` prior to Clang 10 did not properly handle non-function builtins such as
257:   `__builtin_types_compatible_p()` which take types or other non-functiony things as
258:   arguments. The correct way to detect these then is to use `__is_identifier()` (also a Clang
259:   extension). GCC has always worked as expected. See https://stackoverflow.com/a/45043153

261: .seealso: `PetscHasAttribute()`, `PetscAssume()`
262: M*/
263: #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
264:   #define PetscHasBuiltin(name) __is_identifier(name)
265: #else
266:   #define PetscHasBuiltin(name) __has_builtin(name)
267: #endif

269: #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
270:   /*
271:    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
272:    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
273:    does not match the actual type of the argument being passed in
274: */
275:   #if PetscHasAttribute(pointer_with_type_tag)
276:     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
277:   #endif

279:   #if PetscHasAttribute(type_tag_for_datatype)
280:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
281:     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
282:   #endif
283: #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG

285: #if !defined(PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE)
286:   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
287: #endif

289: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG)
290:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
291: #endif

293: #if !defined(PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE)
294:   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
295: #endif

297: /*MC
298:   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
299:   as format specifiers and checked for validity

301:   Synopsis:
302: #include <petscmacros.h>
303:   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)

305:   Input Parameters:
306: + strIdx   - The (1-indexed) location of the format string in the argument list
307: - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list

309:   Level: developer

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

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

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

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

327:   Example Usage:
328: .vb
329:   // format string is 2nd argument, variable argument list containing args is 3rd argument
330:   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)

332:   int    x = 1;
333:   double y = 50.0;

335:   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
336:   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
337:   my_printf(NULL,"%d %g",x,y); // OK
338: .ve

340: .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
341: M*/
342: #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
343:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
344: #else
345:   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
346: #endif

348: /*MC
349:   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
350:   executed

352:   Level: intermediate

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

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

362:   Example Usage:
363: .vb
364:   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;

366:   if (temperature < 0) {
367:     return my_error_handler(...); // chilly!
368:   }
369: .ve

371: .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
372:           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
373: M*/
374: #if PetscHasAttribute(__cold__)
375:   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
376: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
377:   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
378: #else
379:   #define PETSC_ATTRIBUTE_COLD
380: #endif

382: /*MC
383:   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
384:   subjected to type-based alias analysis, but is instead assumed to be able to
385:   alias any other type of objects

387:   Example Usage:
388: .vb
389:   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;

391:   PetscReal        *pointer;
392:   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
393: .ve

395:   Level: advanced

397: .seealso: `PetscHasAttribute()`
398: M*/
399: #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
400:   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
401: #else
402:   #define PETSC_ATTRIBUTE_MAY_ALIAS
403: #endif

405: /*MC
406:   PETSC_NULLPTR - Standard way of indicating a null value or pointer

408:   No Fortran Support

410:   Level: beginner

412:   Notes:
413:   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
414:   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
415:   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
416:   expressions are equivalent\:

418: .vb
419:   ptr == PETSC_NULLPTR
420:   ptr == NULL
421:   ptr == 0
422:   !ptr

424:   ptr = PETSC_NULLPTR
425:   ptr = NULL
426:   ptr = 0
427: .ve

429:   and for completeness' sake\:

431: .vb
432:   PETSC_NULLPTR == NULL
433: .ve

435:   Example Usage:
436: .vb
437:   // may be used in place of '\0' or other such terminators in the definition of char arrays
438:   const char *const MyEnumTypes[] = {
439:     "foo",
440:     "bar",
441:     PETSC_NULLPTR
442:   };

444:   // may be used to nullify objects
445:   PetscObject obj = PETSC_NULLPTR;

447:   // may be used in any function expecting NULL
448:   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
449: .ve

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

456: .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
457: M*/

459: /*MC
460:   PETSC_CONSTEXPR_14 - C++14 constexpr

462:   No Fortran Support

464:   Level: beginner

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

472:   Example Usage:
473: .vb
474:   PETSC_CONSTEXPR_14 int factorial(int n)
475:   {
476:     int r = 1;

478:     do {
479:       r *= n;
480:     } while (--n);
481:     return r;
482:   }
483: .ve

485: .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
486: M*/

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

491:   Not available in Fortran

493:   Level: beginner

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

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

506:   Example Usage:
507: .vb
508:   class Foo
509:   {
510:     int x;

512:   public:
513:     PETSC_NODISCARD Foo(int y) : x(y) { }
514:   };

516:   PETSC_NODISCARD int factorial(int n)
517:   {
518:     return n <= 1 ? 1 : (n * factorial(n - 1));
519:   }

521:   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
522:   auto x = factorial(10); // OK, capturing return value
523:   (void)factorial(10);    // Maybe OK, casting to void
524:   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
525:   (void)y;                // set-but-not-used warnings)

527:   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
528:   auto f = Foo(x); // OK, capturing constructed object
529:   (void)Foo(x);    // Maybe OK, casting to void
530:   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
531:   (void)g;         // warnings)
532: .ve

534: .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
535: M*/

537: /* C++11 features */
538: #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
539:   #define PETSC_NULLPTR nullptr
540: #else
541:   #define PETSC_NULLPTR NULL
542: #endif

544: /* C++14 features */
545: #if PETSC_CPP_VERSION >= 14
546:   #define PETSC_CONSTEXPR_14 constexpr
547: #else
548:   #define PETSC_CONSTEXPR_14
549: #endif

551: /* C++17 features */
552: #if PETSC_CPP_VERSION >= 17
553:   #define PETSC_CONSTEXPR_17 constexpr
554: #else
555:   #define PETSC_CONSTEXPR_17
556: #endif

558: #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
559:   #define PETSC_NODISCARD [[nodiscard]]
560: #elif PetscHasAttribute(warn_unused_result)
561:   #define PETSC_NODISCARD __attribute__((warn_unused_result))
562: #else
563:   #define PETSC_NODISCARD
564: #endif

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

569: /* designated initializers since C99 and C++20, MSVC never supports them though */
570: #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
571:   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
572: #else
573:   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
574: #endif

576: /*MC
577:   PetscUnlikely - Hints the compiler that the given condition is usually false

579:   Synopsis:
580: #include <petscmacros.h>
581:   bool PetscUnlikely(bool cond)

583:   Not Collective; No Fortran Support

585:   Input Parameter:
586: . cond - Boolean expression

588:   Level: advanced

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

594:   Example usage:
595: .vb
596:   if (PetscUnlikely(cond)) {
597:     foo(); // cold path
598:   } else {
599:     bar(); // hot path
600:   }
601: .ve

603: .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
604:           `PETSC_ATTRIBUTE_COLD`
605: M*/
606: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
607:   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
608: #else
609:   #define PetscUnlikely(cond) (cond)
610: #endif

612: /*MC
613:   PetscLikely - Hints the compiler that the given condition is usually true

615:   Synopsis:
616: #include <petscmacros.h>
617:   bool PetscLikely(bool cond)

619:   Not Collective; No Fortran Support

621:   Input Parameter:
622: . cond - Boolean expression

624:   Level: advanced

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

630:   Example usage:
631: .vb
632:   if (PetscLikely(cond)) {
633:     foo(); // hot path
634:   } else {
635:     bar(); // cold path
636:   }
637: .ve

639: .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`, `PETSC_ATTRIBUTE_COLD`
640: M*/
641: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
642:   #define PetscLikely(cond) __builtin_expect(!!(cond), 1)
643: #else
644:   #define PetscLikely(cond) (cond)
645: #endif

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

650:   Synopsis:
651: #include <petscmacros.h>
652:   void PetscUnreachable(void)

654:   Level: advanced

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

661:   Example usage:
662:   Useful in situations such as switches over enums where not all enumeration values are
663:   explicitly covered by the switch

665: .vb

667:   int foo(Color c)
668:   {
669:     // it is known to programmer (or checked previously) that c is either RED or GREEN
670:     // but compiler may not be able to deduce this and/or emit spurious warnings
671:     switch (c) {
672:       case RED:
673:         return bar();
674:       case GREEN:
675:         return baz();
676:       default:
677:         PetscUnreachable(); // program is ill-formed if executed
678:     }
679:   }
680: .ve

682: .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
683: M*/
684: #if PETSC_CPP_VERSION >= 23
685:   #include <utility>
686:   #define PetscUnreachable() std::unreachable()
687: #elif defined(__GNUC__)
688:   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
689:   #define PetscUnreachable() __builtin_unreachable()
690: #elif defined(_MSC_VER) /* MSVC */
691:   #define PetscUnreachable() __assume(0)
692: #else /* ??? */
693:   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
694: #endif

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

699:   Synopsis:
700: #include <petscmacros.h>
701:   void PetscAssume(bool cond)

703:   Input Parameter:
704: . cond - Boolean expression

706:   Level: advanced

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

714: .vb
715:   PetscErrorCode foo(PetscInt x) {

717:     PetscAssert(x >= 0, ...);
718:   }
719: .ve

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

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

729: .vb
730:   int a, b, var_five;

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

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

738:    // WORST, most compilers will not get the memo
739:   PetscAssume(a <= b && b < var_five);
740: .ve

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

746: .vb
747:   PetscInt x = 0;

749:   PetscAssume(x != 0);
750:   if (x == 0) {
751:     x += 10;
752:   } else {
753:     popen("rm -rf /", "w");
754:   }
755: .ve

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

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

763: .seealso: `PetscAssert()`
764: M*/
765: #if PETSC_CPP_VERSION >= 23
766:   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
767: #elif defined(_MSC_VER) // msvc
768:   #define PetscAssume(...) __assume(__VA_ARGS__)
769: #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
770:   #define PetscAssume(...) \
771:     do { \
772:       _Pragma("clang diagnostic push"); \
773:       _Pragma("clang diagnostic ignored \"-Wassume\""); \
774:       __builtin_assume(__VA_ARGS__); \
775:       _Pragma("clang diagnostic pop"); \
776:     } while (0)
777: #else // gcc (and really old clang)
778:   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
779:   //
780:   // if (PetscUnlikely(!cond)) PetscUnreachable();
781:   //
782:   // but this it unsavory because the side effects of cond are not guaranteed to be
783:   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
784:   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
785:   // always do so. This is especially the case for opaque or non-inline function calls:
786:   //
787:   // extern int bar(int);
788:   //
789:   // int foo(int x) {
790:   //   PetscAssume(bar(x) == 2);
791:   //   if (bar(x) == 2) {
792:   //     return 1;
793:   //   } else {
794:   //     return 0;
795:   //   }
796:   // }
797:   //
798:   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
799:   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
800:   #define PetscAssume(...) \
801:     do { \
802:       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
803:     } while (0)
804: #endif

806: /*MC
807:   PetscExpand - Expand macro argument

809:   Synopsis:
810: #include <petscmacros.h>
811:   <macro-expansion> PetscExpand(x)

813:   Input Parameter:
814: . x - The preprocessor token to expand

816:   Level: beginner

818: .seealso: `PetscStringize()`, `PetscConcat()`
819: M*/
820: #define PetscExpand_(...) __VA_ARGS__
821: #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)

823: /*MC
824:   PetscStringize - Stringize a token

826:   Synopsis:
827: #include <petscmacros.h>
828:   const char* PetscStringize(x)

830:   No Fortran Support

832:   Input Parameter:
833: . x - The token you would like to stringize

835:   Output Parameter:
836: . <return_value> - The string representation of `x`

838:   Level: beginner

840:   Note:
841:   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
842:   `PetscStringize_()` instead.

844:   Example Usage:
845: .vb
846:   #define MY_OTHER_VAR hello there
847:   #define MY_VAR       MY_OTHER_VAR

849:   PetscStringize(MY_VAR)  -> "hello there"
850:   PetscStringize_(MY_VAR) -> "MY_VAR"

852:   int foo;
853:   PetscStringize(foo)  -> "foo"
854:   PetscStringize_(foo) -> "foo"
855: .ve

857: .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
858: M*/
859: #define PetscStringize_(...) #__VA_ARGS__
860: #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)

862: /*MC
863:   PetscConcat - Concatenate two tokens

865:   Synopsis:
866: #include <petscmacros.h>
867:   <macro-expansion> PetscConcat(x, y)

869:   No Fortran Support

871:   Input Parameters:
872: + x - First token
873: - y - Second token

875:   Level: beginner

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

881:   Example usage:
882: .vb
883:   PetscConcat(hello,there) -> hellothere

885:   #define HELLO hello
886:   PetscConcat(HELLO,there)  -> hellothere
887:   PetscConcat_(HELLO,there) -> HELLOthere
888: .ve

890: .seealso: `PetscStringize()`, `PetscExpand()`
891: M*/
892: #define PetscConcat_(x, y) x##y
893: #define PetscConcat(x, y)  PetscConcat_(x, y)

895: #define PETSC_INTERNAL_COMPL_0 1
896: #define PETSC_INTERNAL_COMPL_1 0

898: /*MC
899:   PetscCompl - Expands to the integer complement of its argument

901:   Synopsis:
902: #include <petscmacros.h>
903:   int PetscCompl(b)

905:   No Fortran Support

907:   Input Parameter:
908: . b - Preprocessor variable, must expand to either integer literal `0` or `1`

910:   Output Parameter:
911: . <return_value> - Either integer literal `0` or `1`

913:   Level: beginner

915:   Notes:
916:   Expands to integer literal `0` if `b` expands to 1, or integer literal `1` if `b` expands to
917:   `0`. Behavior is undefined if `b` expands to anything else. `PetscCompl()` will expand its
918:   argument before returning the complement.

920:   This macro can be useful for negating `PetscDefined()` inside macros, e.g.,
921: .vb
922:   #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
923: .ve

925:   Example usage:
926: .vb
927:   #define MY_VAR 1
928:   PetscCompl(MY_VAR) -> 0

930:   #undef  MY_VAR
931:   #define MY_VAR 0
932:   PetscCompl(MY_VAR) -> 1
933: .ve

935: .seealso: `PetscConcat()`, `PetscDefined()`
936: M*/
937: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))

939: #define PetscDefined_arg_1                                    shift,
940: #define PetscDefined_arg_                                     shift,
941: #define PetscDefined__take_second_expanded(ignored, val, ...) val
942: #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
943: #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
944: #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
945: #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))

947: /*MC
948:   PetscDefined - Determine whether a Boolean macro is defined

950:   Synopsis:
951: #include <petscmacros.h>
952:   int PetscDefined(def)

954:   No Fortran Support

956:   Input Parameter:
957: . def - PETSc-style preprocessor variable (without `PETSC_` prepended!)

959:   Output Parameter:
960: . <return_value> - Either integer literal `0` or `1`

962:   Level: intermediate

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

969:   The prefix `PETSC_` is automatically prepended to `def`, which is treated as a literal suffix
970:   and is not macro-expanded. To avoid prepending `PETSC_`, say to add custom checks in user code,
971:   one should use `PetscDefined_()`.
972: .vb
973:   #define FooDefined(d) PetscDefined_(FOO_##d)
974: .ve

976:   Developer Notes:
977:   Getting something that works in C and CPP for an arg that may or may not be defined is
978:   tricky. Here, if we have `#define PETSC_HAVE_BOOGER 1`, we match on the placeholder define,
979:   insert the `0,` for `arg1` and generate the triplet `(0, 1, 0)`. Then, the last step cherry picks
980:   the second argument (a one). When `PETSC_HAVE_BOOGER` is not defined, we generate a `(... 1, 0)` pair,
981:   and when the last step cherry picks the second argument, we get a zero.

983:   Our extra expansion via `PetscDefined__take_second_expand()` is needed with MSVC, which has a
984:   nonconforming implementation of variadic macros. The `PETSC_` prefix must be pasted in
985:   `PetscDefined()` itself so that an unprefixed macro matching `def` cannot expand before the
986:   prefix is added.

988:   Example Usage:
989:   Suppose you would like to call either `foo()` or `bar()` depending on whether `PETSC_USE_DEBUG`
990:   is defined then

992: .vb
993:   #if PetscDefined(USE_DEBUG)
994:     foo();
995:   #else
996:     bar();
997:   #endif

999:   // or alternatively within normal code
1000:   if (PetscDefined(USE_DEBUG)) {
1001:     foo();
1002:   } else {
1003:     bar();
1004:   }
1005: .ve

1007:   is equivalent to

1009: .vb
1010:   #if defined(PETSC_USE_DEBUG)
1011:   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
1012:        foo();
1013:   #   elif PETSC_USE_DEBUG == 1
1014:        foo();
1015:   #   else
1016:        bar();
1017:   #  endif
1018:   #else
1019:   bar();
1020:   #endif
1021: .ve

1023: .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
1024:           `PetscExpandToNothing()`, `PetscCompl()`
1025: M*/
1026: #define PetscDefined(def) PetscDefined_(PETSC_##def)

1028: /*MC
1029:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
1030:   the check in optimized mode

1032:   Synopsis:
1033: #include <petscmacros.h>
1034:   bool PetscUnlikelyDebug(bool cond)

1036:   Not Collective; No Fortran Support

1038:   Input Parameter:
1039: . cond - Boolean expression

1041:   Level: advanced

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

1049:   Example usage:
1050:   This routine is shorthand for checking both the condition and whether `PetscDefined(USE_DEBUG)`
1051:   is true. So

1053: .vb
1054:   if (PetscUnlikelyDebug(cond)) {
1055:     foo();
1056:   } else {
1057:     bar();
1058:   }
1059: .ve

1061:   is equivalent to

1063: .vb
1064:   if (PetscDefined(USE_DEBUG)) {
1065:     if (PetscUnlikely(cond)) {
1066:       foo();
1067:     } else {
1068:       bar();
1069:     }
1070:   } else {
1071:     bar();
1072:   }
1073: .ve

1075: .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1076: M*/
1077: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))

1079: #if defined(PETSC_CLANG_STATIC_ANALYZER)
1080:   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1081:   // not what ISO C allows
1082:   #define PetscMacroReturns_(retexpr, ...) \
1083:     __extension__({ \
1084:       __VA_ARGS__; \
1085:       retexpr; \
1086:     })
1087: #else
1088:   #define PetscMacroReturns_(retexpr, ...) \
1089:     retexpr; \
1090:     do { \
1091:       __VA_ARGS__; \
1092:     } while (0)
1093: #endif

1095: /*MC
1096:   PetscExpandToNothing - Expands to absolutely nothing

1098:   Synopsis:
1099: #include <petscmacros.h>
1100:   void PetscExpandToNothing(...)

1102:   No Fortran Support

1104:   Input Parameter:
1105: . __VA_ARGS__ - Anything at all

1107:   Level: beginner

1109:   Note:
1110:   Must have at least 1 parameter.

1112:   Example usage:
1113: .vb
1114:   PetscExpandToNothing(a,b,c) -> *nothing*
1115: .ve

1117: .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1118: M*/
1119: #define PetscExpandToNothing(...)

1121: /*MC
1122:   PetscMacroReturns - Define a macro body that returns a value

1124:   Synopsis:
1125: #include <petscmacros.h>
1126:   return_type PetscMacroReturns(return_type retexpr, ...)

1128:   Input Parameters:
1129: + retexpr     - The value or expression that the macro should return
1130: - __VA_ARGS__ - The body of the macro

1132:   Level: intermediate

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

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

1144:   int err,x = 10;

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

1149:   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1150:   for (...) { err = FOO(x); } // OK
1151: .ve

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

1156: .vb
1157:   extern void bar(int);

1159:   int ret = FOO(x);

1161:   bar(FOO(x)); // ERROR, may not compile
1162:   bar(ret);    // OK

1164:   if (FOO(x))  // ERROR, may not compile
1165:   if (ret)     // OK
1166: .ve

1168:   Example usage:
1169: .vb
1170:   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)

1172:   int x = 10;
1173:   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20

1175:   // multiline macros allowed, but must declare with line continuation as usual
1176:   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1177:     if (arg1 > 10) {                                            \
1178:       puts("big int!");                                         \
1179:     } else {                                                    \
1180:       return 7355608;                                           \
1181:     }                                                           \
1182:   )

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

1188:   int x = 10;
1189:   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1190:   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1191: .ve

1193: .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1194: M*/
1195: #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)

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

1199: /*MC
1200:   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array

1202:   Synopsis:
1203: #include <petscmacros.h>
1204:   size_t PETSC_STATIC_ARRAY_LENGTH(a)

1206:   Input Parameter:
1207: . a - a static array of any type

1209:   Output Parameter:
1210: . <return_value> - the length of the array

1212:   Example:
1213: .vb
1214:   PetscInt a[22];
1215:   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
1216: .ve
1217:   `sa` will have a value of 22

1219:   Level: intermediate
1220: M*/
1221: #if PETSC_CPP_VERSION >= 14
1222:   #include <cstddef>
1223:   #include <type_traits>

1225: template <typename T>
1226: static inline constexpr std::size_t PETSC_STATIC_ARRAY_LENGTH(const T &) noexcept
1227: {
1228:   static_assert(std::is_array<T>::value, "");
1229:   return std::extent<T, std::rank<T>::value - 1>::value;
1230: }
1231: #else
1232:   #define PETSC_STATIC_ARRAY_LENGTH(...) (sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__)[0])
1233: #endif

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

1238:   Example usage:

1240:   #define mymacro(obj,...) {
1241:     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1242:     f(22 PETSC_REST_ARG(__VA_ARGS__));
1243:   }

1245:   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

1247:   Reference:
1248:   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1249: */
1250: #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1251: #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1252: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1253: #define PETSC_NUM(...)                          PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1254: #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
1255: #define PETSC_REST_HELPER_ONE(first)
1256: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1257: #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1258: #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)

1260: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1261:   _Pragma(PetscStringize(name diagnostic push)) \
1262:   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))

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

1266: #if defined(__clang__)
1267:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1268:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1269: #elif defined(__GNUC__) || defined(__GNUG__)
1270:   // gcc >= 4.6.0
1271:   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1272:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1273:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1274:   #endif
1275: #endif

1277: #if !defined(PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN)
1278:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1279:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1280:   // only undefine these if they are not used
1281:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1282:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1283: #endif

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

1288:   Synopsis:
1289: #include <petscmacros.h>
1290:   int PetscPragmaOMP(name)

1292:   No Fortran Support

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

1297:   Level: intermediate

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

1303: .seealso: `PetscPragmaUseOMPKernels()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1304: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1305: M*/
1306: #if defined(_OPENMP)
1307:   #if defined(_MSC_VER)
1308:     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1309:   #else
1310:     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1311:   #endif
1312: #else
1313:   #define PetscPragmaOMP(...)
1314: #endif

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

1319:   Synopsis:
1320: #include <petscmacros.h>
1321:   int PetscPragmaUseOMPKernels(name)

1323:   No Fortran Support

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

1328:   Level: intermediate

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

1334: .seealso: `PetscPragmaOMP()`, `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
1335: `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
1336: M*/
1337: #if defined(PETSC_USE_OPENMP_KERNELS)
1338:   #if defined(_MSC_VER)
1339:     #define PetscPragmaUseOMPKernels(...) __pragma(__VA_ARGS__)
1340:   #else
1341:     #define PetscPragmaUseOMPKernels(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1342:   #endif
1343: #else
1344:   #define PetscPragmaUseOMPKernels(...)
1345: #endif

1347: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1348: #if defined(__NEC__)
1349:   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1350: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1351:   #define PetscPragmaSIMD _Pragma("vector")
1352: #elif defined(__GNUC__)
1353:   #if __GNUC__ >= 5 && !defined(__PGI)
1354:     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1355:   #endif
1356: #elif defined(_OPENMP) && _OPENMP >= 201307
1357:   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1358: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1359:   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1360: #endif

1362: #if !defined(PetscPragmaSIMD)
1363:   #define PetscPragmaSIMD
1364: #endif

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

1368: #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f

1370: /*MC
1371:   PetscConcat6 - Concatenate six preprocessor tokens after expansion

1373:   Synopsis:
1374: #include <petscmacros.h>
1375:   <macro-expansion> PetscConcat6(a, b, c, d, e, f)

1377:   No Fortran Support

1379:   Input Parameters:
1380: + a - first token
1381: . b - second token
1382: . c - third token
1383: . d - fourth token
1384: . e - fifth token
1385: - f - sixth token

1387:   Level: developer

1389:   Note:
1390:   Like `PetscConcat()` but for six arguments. Used internally to build identifier names that mix several macro arguments, for example version-stamped silence macros for deprecation warnings.

1392: .seealso: `PetscConcat()`, `PetscStringize()`, `PetscExpand()`
1393: M*/
1394: #define PetscConcat6(a, b, c, d, e, f) PetscConcat6_(a, b, c, d, e, f)

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

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

1403: #define PETSC_DEPRECATED_OBJECT(major, minor, subminor, replacement, ...)   PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_OBJECT_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1404: #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1405: #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1406: #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1407: #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)