xref: /petsc/include/petscmacros.h (revision a44be8dc6eeccc8754dbff0bc56030e29894a2e1)
1 #ifndef PETSC_PREPROCESSOR_MACROS_H
2 #define PETSC_PREPROCESSOR_MACROS_H
3 
4 #include <petscconf.h>
5 #include <petscconf_poison.h> /* for PetscDefined() error checking */
6 
7 /* SUBMANSEC = Sys */
8 
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
22 
23 #ifndef PETSC_CPP_VERSION
24 #define PETSC_CPP_VERSION 0
25 #endif
26 
27 /* ========================================================================== */
28 /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
29 #if defined(__cplusplus)
30 #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
31 #else
32 #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
33 #endif
34 
35 /* ========================================================================== */
36 /* Since PETSc manages its own extern "C" handling users should never include PETSc include
37  * files within extern "C". This will generate a compiler error if a user does put the include
38  * file within an extern "C".
39  */
40 #if defined(__cplusplus)
41 void assert_never_put_petsc_headers_inside_an_extern_c(int);
42 void assert_never_put_petsc_headers_inside_an_extern_c(double);
43 #endif
44 
45 #if defined(__cplusplus)
46 #define PETSC_RESTRICT PETSC_CXX_RESTRICT
47 #else
48 #define PETSC_RESTRICT restrict
49 #endif
50 
51 #define PETSC_INLINE        PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline
52 #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline
53 
54 #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
55 #define PETSC_DLLEXPORT __declspec(dllexport)
56 #define PETSC_DLLIMPORT __declspec(dllimport)
57 #define PETSC_VISIBILITY_INTERNAL
58 #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
59 #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
60 #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
61 #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
62 #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
63 #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
64 #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
65 #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
66 #else
67 #define PETSC_DLLEXPORT
68 #define PETSC_DLLIMPORT
69 #define PETSC_VISIBILITY_INTERNAL
70 #endif
71 
72 #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
73 #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
74 #else /* Win32 users need this to import symbols from petsc.dll */
75 #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
76 #endif
77 
78 /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
79  * compiled with C++ so they may be used from C and are always visible in the shared libraries
80  */
81 #if defined(__cplusplus)
82 #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
83 #define PETSC_EXTERN_TYPEDEF extern "C"
84 #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
85 #else
86 #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
87 #define PETSC_EXTERN_TYPEDEF
88 #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
89 #endif
90 
91 #if defined(PETSC_USE_SINGLE_LIBRARY)
92 #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN
93 #else
94 #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN
95 #endif
96 
97 /*MC
98   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
99 
100   Synopsis:
101   #include <petscmacros.h>
102   boolean PetscHasAttribute(name)
103 
104   Input Parameter:
105 . name - The name of the attribute to test
106 
107   Notes:
108   name should be identical to what you might pass to the __attribute__ declaration itself --
109   plain, unbroken text.
110 
111   As `PetscHasAttribute()` is wrapper over the function-like macro __has_attribute(), the exact
112   type and value returned is implementation defined. In practice however, it usually returns
113   the integer literal 1 if the attribute is supported, and integer literal 0 if the attribute
114   is not supported.
115 
116   Example Usage:
117   Typical usage is using the preprocessor
118 
119 .vb
120   #if PetscHasAttribute(always_inline)
121   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
122   #else
123   #  define MY_ALWAYS_INLINE
124   #endif
125 
126   void foo(void) MY_ALWAYS_INLINE;
127 .ve
128 
129   but it can also be used in regular code
130 
131 .vb
132   if (PetscHasAttribute(some_attribute)) {
133     foo();
134   } else {
135     bar();
136   }
137 .ve
138 
139   Level: intermediate
140 
141 .seealso: `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`, `PETSC_ATTRIBUTE_FORMAT`
142 M*/
143 #if !defined(__has_attribute)
144 #define __has_attribute(x) 0
145 #endif
146 #define PetscHasAttribute(name) __has_attribute(name)
147 
148 /*MC
149   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
150   as format specifiers and checked for validity
151 
152   Synopsis:
153   #include <petscmacros.h>
154   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
155 
156   Input Parameters:
157 + strIdx   - The (1-indexed) location of the format string in the argument list
158 - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
159 
160   Notes:
161   This function attribute causes the compiler to issue warnings when the format specifier does
162   not match the type of the variable that will be formatted, or when there exists a mismatch
163   between the number of format specifiers and variables to be formatted. It is safe to use this
164   macro if your compiler does not support format specifier checking (though this is
165   exceeedingly rare).
166 
167   Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the
168   same value.
169 
170   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
171   the argument list, that is, there is no way to indicate gaps which should not be checked.
172 
173   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
174   header files. In this case the macro will expand empty.
175 
176   Example Usage:
177 .vb
178   // format string is 2nd argument, variable argument list containing args is 3rd argument
179   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
180 
181   int    x = 1;
182   double y = 50.0;
183 
184   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
185   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
186   my_printf(NULL,"%d %g",x,y); // OK
187 .ve
188 
189   Level: developer
190 
191 .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
192 M*/
193 #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
194 #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
195 #else
196 #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
197 #endif
198 
199 /*MC
200   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
201   executed
202 
203   Notes:
204   The marked function is often optimized for size rather than speed and may be grouped alongside
205   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
206 
207   The paths leading to cold functions are usually automatically marked as unlikely by the
208   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
209   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
210 
211   Example Usage:
212 .vb
213   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
214 
215   if (temperature < 0) {
216     return my_error_handler(...); // chilly!
217   }
218 .ve
219 
220   Level: intermediate
221 
222 .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
223           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
224 M*/
225 #if PetscHasAttribute(__cold__)
226 #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
227 #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
228 #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
229 #else
230 #define PETSC_ATTRIBUTE_COLD
231 #endif
232 
233 /*MC
234   PETSC_NULLPTR - Standard way of indicating a null value or pointer
235 
236   Notes:
237   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
238   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
239   equivalent to setting the same pointer to NULL in C. That is to say that the following
240   expressions are equivalent\:
241 
242 .vb
243   ptr == PETSC_NULLPTR
244   ptr == NULL
245   ptr == 0
246   !ptr
247 
248   ptr = PETSC_NULLPTR
249   ptr = NULL
250   ptr = 0
251 .ve
252 
253   and for completeness' sake\:
254 
255 .vb
256   PETSC_NULLPTR == NULL
257 .ve
258 
259   Fortran Notes:
260   Not available in Fortran
261 
262   Example Usage:
263 .vb
264   // may be used in place of '\0' or other such teminators in the definition of char arrays
265   const char *const MyEnumTypes[] = {
266     "foo",
267     "bar",
268     PETSC_NULLPTR
269   };
270 
271   // may be used to nullify objects
272   PetscObject obj = PETSC_NULLPTR;
273 
274   // may be used in any function expecting NULL
275   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
276 .ve
277 
278   Developer Notes:
279   `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source
280   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
281   resolution and/or compiler warnings.
282 
283   Level: beginner
284 
285 .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
286 M*/
287 
288 /*MC
289   PETSC_CONSTEXPR_14 - C++14 constexpr
290 
291   Notes:
292   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
293   if the C++ compiler does not suppport C++14 or when not compiling with a C++ compiler. Note
294   that this cannot be used in cases where an empty expansion would result in invalid code. It
295   is safe to use this in C source files.
296 
297   Fortran Notes:
298   Not available in Fortran
299 
300   Example Usage:
301 .vb
302   PETSC_CONSTEXPR_14 int factorial(int n)
303   {
304     int r = 1;
305 
306     do {
307       r *= n;
308     } while (--n);
309     return r;
310   }
311 .ve
312 
313   Level: beginner
314 
315 .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
316 M*/
317 
318 /*MC
319   PETSC_NODISCARD - Mark the return value of a function as non-discardable
320 
321   Notes:
322   Hints to the compiler that the return value of a function must be captured. A diagnostic may
323   (but is not required) be emitted if the value is discarded. It is safe to use this in C
324   and C++ source files.
325 
326   Fortran Notes:
327   Not available in Fortran
328 
329   Example Usage:
330 .vb
331   class Foo
332   {
333     int x;
334 
335   public:
336     PETSC_NODISCARD Foo(int y) : x(y) { }
337   };
338 
339   PETSC_NODISCARD int factorial(int n)
340   {
341     return n <= 1 ? 1 : (n * factorial(n - 1));
342   }
343 
344   auto x = factorial(10); // OK, capturing return value
345   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
346 
347   auto f = Foo(x); // OK, capturing constructed object
348   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
349 .ve
350 
351   Developer Notes:
352   It is highly recommended if not downright required that any PETSc routines written in C++
353   returning a PetscErrorCode be marked `PETSC_NODISCARD`. Ignoring the return value of PETSc
354   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.
355 
356   Level: beginner
357 
358 .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
359 M*/
360 
361 /* C++11 features */
362 #if defined(__cplusplus)
363 #define PETSC_NULLPTR nullptr
364 #else
365 #define PETSC_NULLPTR NULL
366 #endif
367 
368 /* C++14 features */
369 #if PETSC_CPP_VERSION >= 14
370 #define PETSC_CONSTEXPR_14 constexpr
371 #else
372 #define PETSC_CONSTEXPR_14
373 #endif
374 
375 /* C++17 features */
376 #if PETSC_CPP_VERSION >= 17
377 #define PETSC_NODISCARD    [[nodiscard]]
378 #define PETSC_CONSTEXPR_17 constexpr
379 #else
380 #if PetscHasAttribute(warn_unused_result)
381 #define PETSC_NODISCARD __attribute__((warn_unused_result))
382 #endif
383 #define PETSC_CONSTEXPR_17
384 #endif
385 
386 #ifndef PETSC_NODISCARD
387 #define PETSC_NODISCARD
388 #endif
389 
390 #include <petscversion.h>
391 #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
392 
393 /* designated initializers since C99 and C++20, MSVC never supports them though */
394 #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
395 #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
396 #else
397 #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
398 #endif
399 
400 /*MC
401   PetscUnlikely - Hints the compiler that the given condition is usually false
402 
403   Synopsis:
404   #include <petscmacros.h>
405   bool PetscUnlikely(bool cond)
406 
407   Not Collective
408 
409   Input Parameter:
410 . cond - Boolean expression
411 
412   Notes:
413   Not available from fortran.
414 
415   This returns the same truth value, it is only a hint to compilers that the result of cond is
416   unlikely to be true.
417 
418   Example usage:
419 .vb
420   if (PetscUnlikely(cond)) {
421     foo(); // cold path
422   } else {
423     bar(); // hot path
424   }
425 .ve
426 
427   Level: advanced
428 
429 .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
430           `PETSC_ATTRIBUTE_COLD`
431 M*/
432 
433 /*MC
434   PetscLikely - Hints the compiler that the given condition is usually true
435 
436   Synopsis:
437   #include <petscmacros.h>
438   bool PetscLikely(bool cond)
439 
440   Not Collective
441 
442   Input Parameter:
443 . cond - Boolean expression
444 
445   Notes:
446   Not available from fortran.
447 
448   This returns the same truth value, it is only a hint to compilers that the result of cond is
449   likely to be true.
450 
451   Example usage:
452 .vb
453   if (PetscLikely(cond)) {
454     foo(); // hot path
455   } else {
456     bar(); // cold path
457   }
458 .ve
459 
460   Level: advanced
461 
462 .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
463           `PETSC_ATTRIBUTE_COLD`
464 M*/
465 #if defined(PETSC_HAVE_BUILTIN_EXPECT)
466 #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
467 #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
468 #else
469 #define PetscUnlikely(cond) (cond)
470 #define PetscLikely(cond)   (cond)
471 #endif
472 
473 /*MC
474   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
475 
476   Synopsis:
477   #include <petscmacros.h>
478   void PetscUnreachable(void)
479 
480   Notes:
481   Indicates to the compiler (usually via some built-in) that a particular code path is always
482   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
483   unceremonious crash.
484 
485   Example usage:
486   Useful in situations such as switches over enums where not all enumeration values are
487   explicitly covered by the switch
488 
489 .vb
490   typedef enum {RED, GREEN, BLUE} Color;
491 
492   int foo(Color c)
493   {
494     // it is known to programmer (or checked previously) that c is either RED or GREEN
495     // but compiler may not be able to deduce this and/or emit spurious warnings
496     switch (c) {
497       case RED:
498         return bar();
499       case GREEN:
500         return baz();
501       default:
502         PetscUnreachable(); // program is ill-formed if executed
503     }
504   }
505 .ve
506 
507   Level: advanced
508 
509 .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`
510 M*/
511 #if defined(__GNUC__)
512 /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
513 #define PetscUnreachable() __builtin_unreachable()
514 #elif defined(_MSC_VER) /* MSVC */
515 #define PetscUnreachable() __assume(0)
516 #else /* ??? */
517 #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
518 #endif
519 
520 /*MC
521   PetscExpand - Expand macro argument
522 
523   Synopsis:
524   #include <petscmacros.h>
525   <macro-expansion> PetscExpand(x)
526 
527   Input Parameter:
528 . x - The preprocessor token to expand
529 
530   Level: beginner
531 
532 .seealso: `PetscStringize()`, `PetscConcat()`
533 M*/
534 #define PetscExpand_(...) __VA_ARGS__
535 #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
536 
537 /*MC
538   PetscStringize - Stringize a token
539 
540   Synopsis:
541   #include <petscmacros.h>
542   const char* PetscStringize(x)
543 
544   Input Parameter:
545 . x - The token you would like to stringize
546 
547   Output Parameter:
548 . <return-value> - The string representation of x
549 
550   Notes:
551   Not available from Fortran.
552 
553   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
554   PetscStringize_() instead.
555 
556   Example Usage:
557 .vb
558   #define MY_OTHER_VAR hello there
559   #define MY_VAR       MY_OTHER_VAR
560 
561   PetscStringize(MY_VAR)  -> "hello there"
562   PetscStringize_(MY_VAR) -> "MY_VAR"
563 
564   int foo;
565   PetscStringize(foo)  -> "foo"
566   PetscStringize_(foo) -> "foo"
567 .ve
568 
569   Level: beginner
570 
571 .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
572 M*/
573 #define PetscStringize_(...) #__VA_ARGS__
574 #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
575 
576 /*MC
577   PetscConcat - Concatenate two tokens
578 
579   Synopsis:
580   #include <petscmacros.h>
581   <macro-expansion> PetscConcat(x, y)
582 
583   Input Parameters:
584 + x - First token
585 - y - Second token
586 
587   Notes:
588   Not available from Fortran.
589 
590   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
591   if you don't want to expand them.
592 
593   Example usage:
594 .vb
595   PetscConcat(hello,there) -> hellothere
596 
597   #define HELLO hello
598   PetscConcat(HELLO,there)  -> hellothere
599   PetscConcat_(HELLO,there) -> HELLOthere
600 .ve
601 
602   Level: beginner
603 
604 .seealso: `PetscStringize()`, `PetscExpand()`
605 M*/
606 #define PetscConcat_(x, y) x##y
607 #define PetscConcat(x, y)  PetscConcat_(x, y)
608 
609 #define PETSC_INTERNAL_COMPL_0 1
610 #define PETSC_INTERNAL_COMPL_1 0
611 
612 /*MC
613   PetscCompl - Expands to the integer complement of its argument
614 
615   Synopsis:
616   #include <petscmacros.h>
617   int PetscCompl(b)
618 
619   Input Parameter:
620 . b - Preprocessor variable, must expand to either integer literal 0 or 1
621 
622   Output Parameter:
623 . <return-value> - Either integer literal 0 or 1
624 
625   Notes:
626   Not available from Fortran.
627 
628   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
629   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
630   argument before returning the complement.
631 
632   This macro can be useful for negating PetscDefined() inside macros e.g.
633 
634 $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
635 
636   Example usage:
637 .vb
638   #define MY_VAR 1
639   PetscCompl(MY_VAR) -> 0
640 
641   #undef  MY_VAR
642   #define MY_VAR 0
643   PetscCompl(MY_VAR) -> 1
644 .ve
645 
646   Level: beginner
647 
648 .seealso: `PetscConcat()`, `PetscDefined()`
649 M*/
650 #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
651 
652 #if !defined(PETSC_SKIP_VARIADIC_MACROS)
653 /*MC
654   PetscDefined - Determine whether a boolean macro is defined
655 
656   Synopsis:
657   #include <petscmacros.h>
658   int PetscDefined(def)
659 
660   Input Parameter:
661 . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
662 
663   Outut Parameter:
664 . <return-value> - Either integer literal 0 or 1
665 
666   Notes:
667   Not available from Fortran, requires variadic macro support, definition is disabled by
668   defining `PETSC_SKIP_VARIADIC_MACROS`.
669 
670   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
671   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
672   this macro should not be used if its argument may be defined to a non-empty value other than
673   1.
674 
675   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
676   add custom checks in user code, one should use `PetscDefined_()`.
677 
678 $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d))
679 
680   Developer Notes:
681   Getting something that works in C and CPP for an arg that may or may not be defined is
682   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
683   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
684   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
685   and when the last step cherry picks the 2nd arg, we get a zero.
686 
687   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
688   nonconforming implementation of variadic macros.
689 
690   Example Usage:
691   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
692   is defined then
693 
694 .vb
695   #if PetscDefined(USE_DEBUG)
696     foo();
697   #else
698     bar();
699   #endif
700 
701   // or alternatively within normal code
702   if (PetscDefined(USE_DEBUG)) {
703     foo();
704   } else {
705     bar();
706   }
707 .ve
708 
709   is equivalent to
710 
711 .vb
712   #if defined(PETSC_USE_DEBUG)
713   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
714        foo();
715   #   elif PETSC_USE_DEBUG == 1
716        foo();
717   #   else
718        bar();
719   #  endif
720   #else
721   bar();
722   #endif
723 .ve
724 
725   Level: intermediate
726 
727 .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
728           `PetscExpandToNothing()`, `PetscCompl()`
729 M*/
730 #define PetscDefined_arg_1                                    shift,
731 #define PetscDefined_arg_                                     shift,
732 #define PetscDefined__take_second_expanded(ignored, val, ...) val
733 #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
734 #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
735 #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
736 #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
737 #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
738 
739 /*MC
740   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
741   the check in optimized mode
742 
743   Synopsis:
744   #include <petscmacros.h>
745   bool PetscUnlikelyDebug(bool cond)
746 
747   Not Collective
748 
749   Input Parameters:
750 . cond - Boolean expression
751 
752   Notes:
753   Not available from Fortran, requires variadic macro support, definition is disabled by
754   defining `PETSC_SKIP_VARIADIC_MACROS`.
755 
756   This returns the same truth value, it is only a hint to compilers that the result of cond is
757   likely to be false. When PETSc is compiled in optimized mode this will always return
758   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
759   optimized mode.
760 
761   Example usage:
762   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
763   is true. So
764 
765 .vb
766   if (PetscUnlikelyDebug(cond)) {
767     foo();
768   } else {
769     bar();
770   }
771 .ve
772 
773   is equivalent to
774 
775 .vb
776   if (PetscDefined(USE_DEBUG)) {
777     if (PetscUnlikely(cond)) {
778       foo();
779     } else {
780       bar();
781     }
782   } else {
783     bar();
784   }
785 .ve
786 
787   Level: advanced
788 
789 .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
790 M*/
791 #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
792 
793 #if defined(PETSC_CLANG_STATIC_ANALYZER)
794 // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
795 // not what ISO C allows
796 #define PetscMacroReturns_(retexpr, ...) \
797   __extension__({ \
798     __VA_ARGS__; \
799     retexpr; \
800   })
801 #else
802 #define PetscMacroReturns_(retexpr, ...) \
803   retexpr; \
804   do { __VA_ARGS__; } while (0)
805 #endif
806 
807 /*MC
808   PetscExpandToNothing - Expands to absolutely nothing at all
809 
810   Synopsis:
811   #include <petscmacros.h>
812   void PetscExpandToNothing(...)
813 
814   Input Parameter:
815 . __VA_ARGS__ - Anything at all
816 
817   Notes:
818   Not available from Fortran, requires variadic macro support, definition is disabled by
819   defining `PETSC_SKIP_VARIADIC_MACROS`.
820 
821   Must have at least 1 parameter.
822 
823   Example usage:
824 .vb
825   PetscExpandToNothing(a,b,c) -> *nothing*
826 .ve
827 
828   Level: beginner
829 
830 .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
831 M*/
832 #define PetscExpandToNothing(...)
833 
834 /*MC
835   PetscMacroReturns - Define a macro body that returns a value
836 
837   Synopsis:
838   #include <petscmacros.h>
839   return_type PetscMacroReturns(return_type retexpr, ...)
840 
841   Input Parameters:
842 + retexpr     - The value or expression that the macro should return
843 - __VA_ARGS__ - The body of the macro
844 
845   Notes:
846   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
847   body of the macro and should not depend on values produced as a result of the expression. The
848   user should not assume that the result of this macro is equivalent to a single logical source
849   line. It is not portable to use macros defined using this one in conditional or loop bodies
850   without enclosing them in curly braces\:
851 
852 .vb
853   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
854 
855   int err,x = 10;
856 
857   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
858   if (...) { err = FOO(x); }  // OK
859 
860   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
861   for (...) { err = FOO(x); } // OK
862 .ve
863 
864   It is also not portable to use this macro directly inside function call, conditional, loop,
865   or switch statements\:
866 
867 .vb
868   extern void bar(int);
869 
870   int ret = FOO(x);
871 
872   bar(FOO(x)); // ERROR, may not compile
873   bar(ret);    // OK
874 
875   if (FOO(x))  // ERROR, may not compile
876   if (ret)     // OK
877 .ve
878 
879   Example usage:
880 .vb
881   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
882 
883   int x = 10;
884   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
885 
886   // multiline macros allowed, but must declare with line continuation as usual
887   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
888     if (arg1 > 10) {                                            \
889       puts("big int!");                                         \
890     } else {                                                    \
891       return 7355608;                                           \
892     }                                                           \
893   )
894 
895   // if retexpr contains commas, must enclose it with braces
896   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
897   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
898 
899   int x = 10;
900   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
901   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
902 .ve
903 
904   Level: intermediate
905 
906 .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
907 M*/
908 #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
909 
910 #define PetscMacroReturnStandard(...) PetscMacroReturns(0, __VA_ARGS__)
911 
912 #endif /* !PETSC_SKIP_VARIADIC_MACROS */
913 
914 /*MC
915   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
916 
917   Level: intermediate
918 M*/
919 #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
920 
921 /*
922   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
923 
924   Example usage:
925 
926   #define mymacro(obj,...) {
927     PETSC_FIRST_ARG((__VA_ARGS__,unused));
928     f(22 PETSC_REST_ARG(__VA_ARGS__));
929   }
930 
931   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
932 
933   Reference:
934   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
935 */
936 #define PETSC_FIRST_ARG_(N, ...)                                                                      N
937 #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
938 #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
939 #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
940 #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
941 #define PETSC_REST_HELPER_ONE(first)
942 #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
943 #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
944 #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
945 
946 #endif /* PETSC_PREPROCESSOR_MACROS_H */
947