Actual source code: petscmacros.h

  1: #ifndef PETSC_PREPROCESSOR_MACROS_H
  2: #define PETSC_PREPROCESSOR_MACROS_H

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

  7: /* SUBMANSEC = Sys */

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

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

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

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

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

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

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

 68: #define PETSC_INLINE        PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline
 69: #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline

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

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

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

108: #if defined(PETSC_USE_SINGLE_LIBRARY)
109:   #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
110: #else
111:   #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
112: #endif

116: #endif

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

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

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

128:   Notes:
129:   name should be identical to what you might pass to the __attribute__ declaration itself --
130:   plain, unbroken text.

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

136:   Example Usage:
137:   Typical usage is using the preprocessor

139: .vb
140:   #if PetscHasAttribute(always_inline)
141:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
142:   #else
143:   #  define MY_ALWAYS_INLINE
144:   #endif

146:   void foo(void) MY_ALWAYS_INLINE;
147: .ve

149:   but it can also be used in regular code

151: .vb
152:   if (PetscHasAttribute(some_attribute)) {
153:     foo();
154:   } else {
155:     bar();
156:   }
157: .ve

159:   Level: intermediate

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

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

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

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

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

186:   Example Usage:
187:   Typical usage is in preprocessor directives

189: .vb
190:   #if PetscHasBuiltin(__builtin_trap)
191:   __builtin_trap();
192:   #else
193:   abort();
194:   #endif
195: .ve

197:   But it may also be used in regular code

199: .vb
200:   if (PetscHasBuiltin(__builtin_alloca)) {
201:     foo();
202:   } else {
203:     bar();
204:   }
205: .ve

207:   Level: intermediate

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

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

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

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

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

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

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

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

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

264:   Level: developer

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

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

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

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

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

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

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

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

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

307:   Level: intermediate

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

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

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

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

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

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

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

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

350:   Level: advanced

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

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

363:   No Fortran Support

365:   Level: beginner

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

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

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

384:   and for completeness' sake\:

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

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

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

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

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

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

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

417:   No Fortran Support

419:   Level: beginner

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

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

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

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

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

446:   Not available in Fortran

448:   Level: beginner

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

538:   Not Collective; No Fortran Support

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

543:   Level: advanced

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

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

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

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

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

569:   Not Collective; No Fortran Support

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

574:   Level: advanced

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

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

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

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

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

607:   Level: advanced

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

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

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

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

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

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

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

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

660:   Level: advanced

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

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

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

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

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

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

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

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

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

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

700: .vb
701:   PetscInt x = 0;

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

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

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

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

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

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

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

770:   Level: beginner

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

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

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

784:   No Fortran Support

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

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

792:   Level: beginner

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

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

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

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

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

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

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

823:   No Fortran Support

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

829:   Level: beginner

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

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

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

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

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

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

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

859:   No Fortran Support

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

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

867:   Level: beginner

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

874:   This macro can be useful for negating `PetscDefined()` inside macros e.g.

876: $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))

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

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

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

892: /*MC
893:   PetscDefined - Determine whether a boolean macro is defined

895:   Synopsis:
896: #include <petscmacros.h>
897:   int PetscDefined(def)

899:   No Fortran Support

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

904:   Output Parameter:
905: . <return-value> - Either integer literal 0 or 1

907:   Level: intermediate

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

915:   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
916:   add custom checks in user code, one should use `PetscDefined_()`.

918: $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))

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

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

930:   Example Usage:
931:   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
932:   is defined then

934: .vb
935:   #if PetscDefined(USE_DEBUG)
936:     foo();
937:   #else
938:     bar();
939:   #endif

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

949:   is equivalent to

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

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

977: /*MC
978:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
979:   the check in optimized mode

981:   Synopsis:
982: #include <petscmacros.h>
983:   bool PetscUnlikelyDebug(bool cond)

985:   No Fortran Support

987:   Not Collective

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

992:   Level: advanced

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

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

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

1012:   is equivalent to

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

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

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

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

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

1053:   No Fortran Support

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

1058:   Level: beginner

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

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

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

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

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

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

1083:   Level: intermediate

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

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

1095:   int err,x = 10;

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

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

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

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

1110:   int ret = FOO(x);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1170:   Level: intermediate
1171: M*/
1172: #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))

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

1177:   Example usage:

1179:   #define mymacro(obj,...) {
1180:     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1181:     f(22 PETSC_REST_ARG(__VA_ARGS__));
1182:   }

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

1186:   Reference:
1187:   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1188: */
1189: #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1190: #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1191: #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1192: #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1193: #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1194: #define PETSC_REST_HELPER_ONE(first)
1195: #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1196: #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1197: #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)

1199: #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
1200:   _Pragma(PetscStringize(name diagnostic push)) \
1201:   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))

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

1205: #if defined(__clang__)
1206:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
1207:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
1208: #elif defined(__GNUC__) || defined(__GNUG__)
1209:   // gcc >= 4.6.0
1210:   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
1211:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
1212:     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
1213:   #endif
1214: #endif

1216: #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
1217:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
1218:   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
1219:   // only undefine these if they are not used
1220:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
1221:   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
1222: #endif

1224: /* OpenMP support */
1225: #if defined(_OPENMP)
1226:   #if defined(_MSC_VER)
1227:     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
1228:   #else
1229:     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
1230:   #endif
1231: #endif

1233: #ifndef PetscPragmaOMP
1234:   #define PetscPragmaOMP(...)
1235: #endif

1237: /* PetscPragmaSIMD - from CeedPragmaSIMD */
1238: #if defined(__NEC__)
1239:   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
1240: #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
1241:   #define PetscPragmaSIMD _Pragma("vector")
1242: #elif defined(__GNUC__)
1243:   #if __GNUC__ >= 5 && !defined(__PGI)
1244:     #define PetscPragmaSIMD _Pragma("GCC ivdep")
1245:   #endif
1246: #elif defined(_OPENMP) && _OPENMP >= 201307
1247:   #define PetscPragmaSIMD PetscPragmaOMP(simd)
1248: #elif defined(PETSC_HAVE_CRAY_VECTOR)
1249:   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
1250: #endif

1252: #ifndef PetscPragmaSIMD
1253:   #define PetscPragmaSIMD
1254: #endif

1256: #endif /* PETSC_PREPROCESSOR_MACROS_H */