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: /* ========================================================================== */
  8: /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
  9: #if defined(__cplusplus)
 10: #  define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
 11: #else
 12: #  define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
 13: #endif

 15: /* ========================================================================== */
 16: /* Since PETSc manages its own extern "C" handling users should never include PETSc include
 17:  * files within extern "C". This will generate a compiler error if a user does put the include
 18:  * file within an extern "C".
 19:  */
 20: #if defined(__cplusplus)
 21: void assert_never_put_petsc_headers_inside_an_extern_c(int); void assert_never_put_petsc_headers_inside_an_extern_c(double);
 22: #endif

 24: #if defined(__cplusplus)
 25: #  define PETSC_RESTRICT PETSC_CXX_RESTRICT
 26: #else
 27: #  define PETSC_RESTRICT restrict
 28: #endif

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

 33: #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
 34: #  define  __declspec(dllexport)
 35: #  define PETSC_DLLIMPORT __declspec(dllimport)
 36: #  define PETSC_VISIBILITY_INTERNAL
 37: #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
 38: #  define  __attribute__((visibility ("default")))
 39: #  define PETSC_DLLIMPORT __attribute__((visibility ("default")))
 40: #  define PETSC_VISIBILITY_INTERNAL __attribute__((visibility ("hidden")))
 41: #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
 42: #  define  __attribute__((visibility ("default")))
 43: #  define PETSC_DLLIMPORT __attribute__((visibility ("default")))
 44: #  define PETSC_VISIBILITY_INTERNAL __attribute__((visibility ("hidden")))
 45: #else
 46: #  define 
 47: #  define PETSC_DLLIMPORT
 48: #  define PETSC_VISIBILITY_INTERNAL
 49: #endif

 51: #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
 52: #  define PETSC_VISIBILITY_PUBLIC 
 53: #else  /* Win32 users need this to import symbols from petsc.dll */
 54: #  define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
 55: #endif

 57: /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
 58:  * compiled with C++ so they may be used from C and are always visible in the shared libraries
 59:  */
 60: #if defined(__cplusplus)
 61: #  define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
 62: #  define PETSC_EXTERN_TYPEDEF extern "C"
 63: #  define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
 64: #else
 65: #  define PETSC_EXTERN         extern PETSC_VISIBILITY_PUBLIC
 66: #  define PETSC_EXTERN_TYPEDEF
 67: #  define PETSC_INTERN         extern PETSC_VISIBILITY_INTERNAL
 68: #endif

 70: #if defined(PETSC_USE_SINGLE_LIBRARY)
 71: #  define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
 72: #else
 73: #  define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
 74: #endif

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

 79:   Synopsis:
 80: #include <petscmacros.h>
 81:   boolean PetscHasAttribute(name)

 83:   Input Parameter:
 84: . name - The name of the attribute to test

 86:   Notes:
 87:   name should be identical to what you might pass to the __attribute__ declaration itself --
 88:   plain, unbroken text.

 90:   As PetscHasAttribute() is wrapper over the function-like macro __has_attribute(), the exact
 91:   type and value returned is implementation defined. In practice however, it usually returns
 92:   the integer literal 1 if the attribute is supported, and integer literal 0 if the attribute
 93:   is not supported.

 95:   Example Usage:
 96:   Typical usage is using the preprocessor

 98: .vb
 99:   #if PetscHasAttribute(always_inline)
100:   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
101:   #else
102:   #  define MY_ALWAYS_INLINE
103:   #endif

105:   void foo(void) MY_ALWAYS_INLINE;
106: .ve

108:   but it can also be used in regular code

110: .vb
111:   if (PetscHasAttribute(some_attribute)) {
112:     foo();
113:   } else {
114:     bar();
115:   }
116: .ve

118:   Level: intermediate

120: .seealso: PetscDefined(), PetscLikely(), PetscUnlikely()
121: M*/
123: #  define __has_attribute(x) 0
124: #endif
125: #define PetscHasAttribute(name) __has_attribute(name)

127: /*MC
128:   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
129:   executed

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

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

139:   Example Usage:
140: .vb
141:   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;

143:   if (temperature < 0) {
144:     return my_error_handler(...); // chilly!
145:   }
146: .ve

148:   Level: intermediate

150: .seealso: PetscUnlikely(), PetscUnlikelyDebug(), PetscLikely(), PetscLikelyDebug(),
151: PetscUnreachable()
152: M*/
153: #if PetscHasAttribute(__cold__)
154: #  define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
155: #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
156: #  define PETSC_ATTRIBUTE_COLD __attribute__((cold))
157: #else
158: #  define PETSC_ATTRIBUTE_COLD
159: #endif

161: /*MC
162:   PETSC_NULLPTR - Standard way of indicating a null value or pointer

164:   Notes:
165:   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
166:   interoperability between C and C++, setting a pointer to PETSC_NULLPTR in C++ is functonially
167:   equivalent to setting the same pointer to NULL in C. That is to say that the following
168:   expressions are equivalent\:

170: .vb
171:   ptr == PETSC_NULLPTR
172:   ptr == NULL
173:   ptr == 0
174:   !ptr

176:   ptr = PETSC_NULLPTR
177:   ptr = NULL
178:   ptr = 0
179: .ve

181:   and for completeness' sake\:

183: .vb
184:   PETSC_NULLPTR == NULL
185: .ve

187:   Fortran Notes:
188:   Not available in Fortran

190:   Example Usage:
191: .vb
192:   // may be used in place of '\0' or other such teminators in the definition of char arrays
193:   const char *const MyEnumTypes[] = {
194:     "foo",
195:     "bar",
196:     PETSC_NULLPTR
197:   };

199:   // may be used to nullify objects
200:   PetscObject obj = PETSC_NULLPTR;

202:   // may be used in any function expecting NULL
203:   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
204: .ve

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

211:   Level: beginner

213: .seealso: PETSC_CONSTEXPR_14, PETSC_NODISCARD
214: M*/

216: /*MC
217:   PETSC_CONSTEXPR_14 - C++14 constexpr

219:   Notes:
220:   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
221:   if the C++ compiler does not suppport C++14 or when not compiling with a C++ compiler. Note
222:   that this cannot be used in cases where an empty expansion would result in invalid code. It
223:   is safe to use this in C source files.

225:   Fortran Notes:
226:   Not available in Fortran

228:   Example Usage:
229: .vb
230:   PETSC_CONSTEXPR_14 int factorial(int n)
231:   {
232:     int r = 1;

234:     do {
235:       r *= n;
236:     } while (--n);
237:     return r;
238:   }
239: .ve

241:   Level: beginner

243: .seealso: PETSC_NULLPTR, PETSC_NODISCARD
244: M*/

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

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

254:   Fortran Notes:
255:   Not available in Fortran

257:   Example Usage:
258: .vb
259:   class Foo
260:   {
261:     int x;

263:   public:
264:     PETSC_NODISCARD Foo(int y) : x(y) { }
265:   };

267:   PETSC_NODISCARD int factorial(int n)
268:   {
269:     return n <= 1 ? 1 : (n * factorial(n - 1));
270:   }

272:   auto x = factorial(10); // OK, capturing return value
273:   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'

275:   auto f = Foo(x); // OK, capturing constructed object
276:   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
277: .ve

279:   Developer Notes:
280:   It is highly recommended if not downright required that any PETSc routines written in C++
281:   returning a PetscErrorCode be marked PETSC_NODISCARD. Ignoring the return value of PETSc
282:   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.

284:   Level: beginner

286: .seealso: PETSC_NULLPTR, PETSC_CONSTEXPR_14
287: M*/

289: /* C++11 features */
290: #if defined(__cplusplus)
291: #  define PETSC_NULLPTR nullptr
292: #else
293: #  define PETSC_NULLPTR NULL
294: #endif

296: /* C++14 features */
297: #if defined(__cplusplus) && defined(PETSC_HAVE_CXX_DIALECT_CXX14) && __cplusplus >= 201402L
298: #  define PETSC_CONSTEXPR_14 constexpr
299: #else
300: #  define PETSC_CONSTEXPR_14
301: #endif

303: /* C++17 features */
304: /* We met cases that the host CXX compiler (say mpicxx) supports C++17, but nvcc does not
305:  * agree, even with -ccbin mpicxx! */
306: #if defined(__cplusplus) && defined(PETSC_HAVE_CXX_DIALECT_CXX17) && (!defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_CUDA_DIALECT_CXX17))
307: #  define PETSC_NODISCARD [[nodiscard]]
308: #else
309: #  if PetscHasAttribute(warn_unused_result)
310: #    define PETSC_NODISCARD __attribute__((warn_unused_result))
311: #  else
312: #    define PETSC_NODISCARD
313: #  endif
314: #endif

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

319: /* designated initializers since C99 and C++20, MSVC never supports them though */
320: #if defined(_MSC_VER) || (defined(__cplusplus) && (__cplusplus < 202002L))
321: #  define PetscDesignatedInitializer(name,...) __VA_ARGS__
322: #else
323: #  define PetscDesignatedInitializer(name,...) .name = __VA_ARGS__
324: #endif

326: /*MC
327:   PetscUnlikely - Hints the compiler that the given condition is usually FALSE

329:   Synopsis:
330: #include <petscmacros.h>
331:   bool PetscUnlikely(bool cond)

333:   Not Collective

335:   Input Parameter:
336: . cond - Boolean expression

338:   Notes:
339:   Not available from fortran.

341:   This returns the same truth value, it is only a hint to compilers that the result of cond is
342:   unlikely to be true.

344:   Example usage:
345: .vb
346:   if (PetscUnlikely(cond)) {
347:     foo(); // cold path
348:   } else {
349:     bar(); // hot path
350:   }
351: .ve

353:   Level: advanced

355: .seealso: PetscLikely(), PetscUnlikelyDebug(), PetscCall(), PetscDefined(), PetscHasAttribute(),
356: PETSC_ATTRIBUTE_COLD
357: M*/

359: /*MC
360:   PetscLikely - Hints the compiler that the given condition is usually TRUE

362:   Synopsis:
363: #include <petscmacros.h>
364:   bool PetscLikely(bool cond)

366:   Not Collective

368:   Input Parameter:
369: . cond - Boolean expression

371:   Notes:
372:   Not available from fortran.

374:   This returns the same truth value, it is only a hint to compilers that the result of cond is
375:   likely to be true.

377:   Example usage:
378: .vb
379:   if (PetscLikely(cond)) {
380:     foo(); // hot path
381:   } else {
382:     bar(); // cold path
383:   }
384: .ve

386:   Level: advanced

388: .seealso: PetscUnlikely(), PetscDefined(), PetscHasAttribute()
389: PETSC_ATTRIBUTE_COLD
390: M*/
391: #if defined(PETSC_HAVE_BUILTIN_EXPECT)
392: #  define PetscUnlikely(cond) __builtin_expect(!!(cond),0)
393: #  define PetscLikely(cond)   __builtin_expect(!!(cond),1)
394: #else
395: #  define PetscUnlikely(cond) (cond)
396: #  define PetscLikely(cond)   (cond)
397: #endif

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

402:   Synopsis:
403: #include <petscmacros.h>
404:   void PetscUnreachable(void)

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

411:   Example usage:
412:   Useful in situations such as switches over enums where not all enumeration values are
413:   explicitly covered by the switch

415: .vb
416:   typedef enum {RED, GREEN, BLUE} Color;

418:   int foo(Color c)
419:   {
420:     // it is known to programmer (or checked previously) that c is either RED or GREEN
421:     // but compiler may not be able to deduce this and/or emit spurious warnings
422:     switch (c) {
423:       case RED:
424:         return bar();
425:       case GREEN:
426:         return baz();
427:       default:
428:         PetscUnreachable(); // program is ill-formed if executed
429:     }
430:   }
431: .ve

433:   Level: advanced

435: .seealso: SETERRABORT(), PETSCABORT(), PETSC_ATTRIBUTE_COLD
436: M*/
437: #if defined(__GNUC__)
438: /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
439: #  define PetscUnreachable() __builtin_unreachable()
440: #elif defined(_MSC_VER) /* MSVC */
441: #  define PetscUnreachable() __assume(0)
442: #else /* ??? */
443: #  define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Code path explicitly marked as unreachable executed")
444: #endif

446: /*MC
447:   PetscExpand - Expand macro argument

449:   Synopsis:
450: #include <petscmacros.h>
451:   <macro-expansion> PetscExpand(x)

453:   Input Parameter:
454: . x - The preprocessor token to expand

456:   Level: beginner

458: .seealso: PetscStringize(), PetscConcat()
459: M*/
460: #define PetscExpand_(...) __VA_ARGS__
461: #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)

463: /*MC
464:   PetscStringize - Stringize a token

466:   Synopsis:
467: #include <petscmacros.h>
468:   const char* PetscStringize(x)

470:   Input Parameter:
471: . x - The token you would like to stringize

473:   Output Parameter:
474: . <return-value> - The string representation of x

476:   Notes:
477:   Not available from Fortran.

479:   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
480:   PetscStringize_() instead.

482:   Example Usage:
483: .vb
484:   #define MY_OTHER_VAR hello there
485:   #define MY_VAR       MY_OTHER_VAR

487:   PetscStringize(MY_VAR)  -> "hello there"
488:   PetscStringize_(MY_VAR) -> "MY_VAR"

490:   int foo;
491:   PetscStringize(foo)  -> "foo"
492:   PetscStringize_(foo) -> "foo"
493: .ve

495:   Level: beginner

497: .seealso: PetscConcat(), PetscExpandToNothing(), PetscExpand()
498: M*/
499: #define PetscStringize_(x) #x
500: #define PetscStringize(x)  PetscStringize_(x)

502: /*MC
503:   PetscConcat - Concatenate two tokens

505:   Synopsis:
506: #include <petscmacros.h>
507:   <macro-expansion> PetscConcat(x, y)

509:   Input Parameters:
510: + x - First token
511: - y - Second token

513:   Notes:
514:   Not available from Fortran.

516:   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
517:   if you don't want to expand them.

519:   Example usage:
520: .vb
521:   PetscConcat(hello,there) -> hellothere

523:   #define HELLO hello
524:   PetscConcat(HELLO,there)  -> hellothere
525:   PetscConcat_(HELLO,there) -> HELLOthere
526: .ve

528:   Level: beginner

530: .seealso: PetscStringize(), PetscExpand()
531: M*/
532: #define PetscConcat_(x,y) x ## y
533: #define PetscConcat(x,y)  PetscConcat_(x,y)

535: #define PETSC_INTERNAL_COMPL_0 1
536: #define PETSC_INTERNAL_COMPL_1 0

538: /*MC
539:   PetscCompl - Expands to the integer complement of its argument

541:   Synopsis:
542: #include <petscmacros.h>
543:   int PetscCompl(b)

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

548:   Output Parameter:
549: . <return-value> - Either integer literal 0 or 1

551:   Notes:
552:   Not available from Fortran.

554:   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
555:   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
556:   argument before returning the complement.

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

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

562:   Example usage:
563: .vb
564:   #define MY_VAR 1
565:   PetscCompl(MY_VAR) -> 0

567:   #undef  MY_VAR
568:   #define MY_VAR 0
569:   PetscCompl(MY_VAR) -> 1
570: .ve

572:   Level: beginner

574: .seealso: PetscConcat(), PetscDefined()
575: M*/
576: #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_,PetscExpand(b))

578: #if !defined(PETSC_SKIP_VARIADIC_MACROS)
579: /*MC
580:   PetscDefined - Determine whether a boolean macro is defined

582:   Synopsis:
583: #include <petscmacros.h>
584:   int PetscDefined(def)

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

589:   Outut Parameter:
590: . <return-value> - Either integer literal 0 or 1

592:   Notes:
593:   Not available from Fortran, requires variadic macro support, definition is disabled by
594:   defining PETSC_SKIP_VARIADIC_MACROS.

596:   PetscDefined() returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
597:   integer literal 1. In all other cases, PetscDefined() returns integer literal 0. Therefore
598:   this macro should not be used if its argument may be defined to a non-empty value other than
599:   1.

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

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

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

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

616:   Example Usage:
617:   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
618:   is defined then

620: .vb
621:   #if PetscDefined(USE_DEBUG)
622:     foo();
623:   #else
624:     bar();
625:   #endif

627:   // or alternatively within normal code
628:   if (PetscDefined(USE_DEBUG)) {
629:     foo();
630:   } else {
631:     bar();
632:   }
633: .ve

635:   is equivalent to

637: .vb
638:   #if defined(PETSC_USE_DEBUG)
639:   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
640:        foo();
641:   #   elif PETSC_USE_DEBUG == 1
642:        foo();
643:   #   else
644:        bar();
645:   #  endif
646:   #else
647:   bar();
648:   #endif
649: .ve

651:   Level: intermediate

653: .seealso: PetscHasAttribute(), PetscUnlikely(), PetscLikely(), PetscConcat(),
654: PetscExpandToNothing(), PetscCompl()
655: M*/
656: #define PetscDefined_arg_1 shift,
657: #define PetscDefined_arg_  shift,
658: #define PetscDefined__take_second_expanded(ignored, val, ...) val
659: #define PetscDefined__take_second_expand(args) PetscDefined__take_second_expanded args
660: #define PetscDefined__take_second(...) PetscDefined__take_second_expand((__VA_ARGS__))
661: #define PetscDefined__(arg1_or_junk)   PetscDefined__take_second(arg1_or_junk 1, 0, at_)
662: #define PetscDefined_(value)           PetscDefined__(PetscConcat_(PetscDefined_arg_,value))
663: #define PetscDefined(def)              PetscDefined_(PetscConcat(PETSC_,def))

665: /*MC
666:   PetscUnlikelyDebug - Hints the compiler that the given condition is usually FALSE, eliding
667:   the check in optimized mode

669:   Synopsis:
670: #include <petscmacros.h>
671:   bool PetscUnlikelyDebug(bool cond)

673:   Not Collective

675:   Input Parameters:
676: . cond - Boolean expression

678:   Notes:
679:   Not available from Fortran, requires variadic macro support, definition is disabled by
680:   defining PETSC_SKIP_VARIADIC_MACROS.

682:   This returns the same truth value, it is only a hint to compilers that the result of cond is
683:   likely to be false. When PETSc is compiled in optimized mode this will always return
684:   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
685:   optimized mode.

687:   Example usage:
688:   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
689:   is true. So

691: .vb
692:   if (PetscUnlikelyDebug(cond)) {
693:     foo();
694:   } else {
695:     bar();
696:   }
697: .ve

699:   is equivalent to

701: .vb
702:   if (PetscDefined(USE_DEBUG)) {
703:     if (PetscUnlikely(cond)) {
704:       foo();
705:     } else {
706:       bar();
707:     }
708:   } else {
709:     bar();
710:   }
711: .ve

713:   Level: advanced

715: .seealso: PetscUnlikely(), PetscLikely(), PetscCall(), SETERRQ
716: M*/
717: #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))

719: #if defined(PETSC_CLANG_STATIC_ANALYZER)
720: // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
721: // not what ISO C allows
722: #  define PetscMacroReturns_(retexpr,...) __extension__ ({ __VA_ARGS__; retexpr; })
723: #else
724: #  define PetscMacroReturns_(retexpr,...) retexpr; do { __VA_ARGS__; } while (0)
725: #endif

727: /*MC
728:   PetscExpandToNothing - Expands to absolutely nothing at all

730:   Synopsis:
731: #include <petscmacros.h>
732:   void PetscExpandToNothing(...)

734:   Input Parameter:
735: . __VA_ARGS__ - Anything at all

737:   Notes:
738:   Not available from Fortran, requires variadic macro support, definition is disabled by
739:   defining PETSC_SKIP_VARIADIC_MACROS.

741:   Must have at least 1 parameter.

743:   Example usage:
744: .vb
745:   PetscExpandToNothing(a,b,c) -> *nothing*
746: .ve

748:   Level: beginner

750: .seealso: PetscConcat(), PetscDefined(), PetscStringize(), PetscExpand()
751: M*/
752: #define PetscExpandToNothing(...)

754: /*MC
755:   PetscMacroReturns - Define a macro body that returns a value

757:   Synopsis:
758: #include <petscmacros.h>
759:   return_type PetscMacroReturns(return_type retexpr, ...)

761:   Input Parameters:
762: + retexpr     - The value or expression that the macro should return
763: - __VA_ARGS__ - The body of the macro

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

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

775:   int err,x = 10;

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

780:   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
781:   for (...) { err = FOO(x); } // OK
782: .ve

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

787: .vb
788:   extern void bar(int);

790:   int ret = FOO(x);

792:   bar(FOO(x)); // ERROR, may not compile
793:   bar(ret);    // OK

795:   if (FOO(x))  // ERROR, may not compile
796:   if (ret)     // OK
797: .ve

799:   Example usage:
800: .vb
801:   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)

803:   int x = 10;
804:   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20

806:   // multiline macros allowed, but must declare with line continuation as usual
807:   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
808:     if (arg1 > 10) {                                            \
809:       puts("big int!");                                         \
810:     } else {                                                    \
811:       return 7355608;                                           \
812:     }                                                           \
813:   )

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

819:   int x = 10;
820:   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
821:   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
822: .ve

824:   Level: intermediate

826: .seealso: PetscExpand(), PetscConcat(), PetscStringize()
827: M*/
828: #define PetscMacroReturns(retexpr,...) PetscMacroReturns_(retexpr,__VA_ARGS__)

830: #define PetscMacroReturnStandard(...) PetscMacroReturns(0,__VA_ARGS__)

832: #endif /* !PETSC_SKIP_VARIADIC_MACROS */

834: #endif /* PETSC_PREPROCESSOR_MACROS_H */