xref: /petsc/include/petscmacros.h (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 #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__
39 
40 #ifndef PETSC_C_VERSION
41   #define PETSC_C_VERSION 0
42 #endif
43 
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
51 
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
61 
62 #if defined(__cplusplus)
63   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
64 #else
65   #define PETSC_RESTRICT restrict
66 #endif
67 
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
70 
71 #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
72   #define PETSC_DLLEXPORT __declspec(dllexport)
73   #define PETSC_DLLIMPORT __declspec(dllimport)
74   #define PETSC_VISIBILITY_INTERNAL
75 #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
76   #define PETSC_DLLEXPORT           __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 PETSC_DLLEXPORT           __attribute__((visibility("default")))
81   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
82   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
83 #else
84   #define PETSC_DLLEXPORT
85   #define PETSC_DLLIMPORT
86   #define PETSC_VISIBILITY_INTERNAL
87 #endif
88 
89 #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
90   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
91 #else /* Win32 users need this to import symbols from petsc.dll */
92   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
93 #endif
94 
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
107 
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
113 
114 /*MC
115   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
116 
117   Synopsis:
118   #include <petscmacros.h>
119   int PetscHasAttribute(name)
120 
121   Input Parameter:
122 . name - The name of the attribute to test
123 
124   Notes:
125   name should be identical to what you might pass to the __attribute__ declaration itself --
126   plain, unbroken text.
127 
128   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
129   exact type and value returned is implementation defined. In practice however, it usually
130   returns `1` if the attribute is supported and `0` if the attribute is not supported.
131 
132   Example Usage:
133   Typical usage is using the preprocessor
134 
135 .vb
136   #if PetscHasAttribute(always_inline)
137   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
138   #else
139   #  define MY_ALWAYS_INLINE
140   #endif
141 
142   void foo(void) MY_ALWAYS_INLINE;
143 .ve
144 
145   but it can also be used in regular code
146 
147 .vb
148   if (PetscHasAttribute(some_attribute)) {
149     foo();
150   } else {
151     bar();
152   }
153 .ve
154 
155   Level: intermediate
156 
157 .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
158 `PETSC_ATTRIBUTE_FORMAT`
159 M*/
160 #if !defined(__has_attribute)
161   #define __has_attribute(x) 0
162 #endif
163 #define PetscHasAttribute(name) __has_attribute(name)
164 
165 /*MC
166   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
167 
168   Synopsis:
169   #include <petscmacros.h>
170   int PetscHasBuiltin(name)
171 
172   Input Parameter:
173 . name - the name of the builtin routine
174 
175   Notes:
176   Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
177   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
178   detector is itself is a compiler extension with implementation-defined return type and
179   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
180   however, all supporting compilers return an integer boolean as described.
181 
182   Example Usage:
183   Typical usage is in preprocessor directives
184 
185 .vb
186   #if PetscHasBuiltin(__builtin_trap)
187   __builtin_trap();
188   #else
189   abort();
190   #endif
191 .ve
192 
193   But it may also be used in regular code
194 
195 .vb
196   if (PetscHasBuiltin(__builtin_alloca)) {
197     foo();
198   } else {
199     bar();
200   }
201 .ve
202 
203   Level: intermediate
204 
205 .seealso: `PetscHasAttribute()`, `PetscAssume()`
206 M*/
207 #if !defined(__has_builtin)
208   #define __has_builtin(x) 0
209 #endif
210 // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
211 // __builtin_types_compatible_p which take types or other non-functiony things as
212 // arguments. The correct way to detect these then is to use __is_identifier (also a clang
213 // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
214 #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
215   #define PetscHasBuiltin(name) __is_identifier(name)
216 #else
217   #define PetscHasBuiltin(name) __has_builtin(name)
218 #endif
219 
220 #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
221   /*
222    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
223    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
224    does not match the actual type of the argument being passed in
225 */
226   #if PetscHasAttribute(pointer_with_type_tag)
227     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
228   #endif
229 
230   #if PetscHasAttribute(type_tag_for_datatype)
231     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
232     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
233   #endif
234 #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
235 
236 #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
237   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
238 #endif
239 
240 #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
241   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
242 #endif
243 
244 #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
245   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
246 #endif
247 
248 /*MC
249   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
250   as format specifiers and checked for validity
251 
252   Synopsis:
253   #include <petscmacros.h>
254   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
255 
256   Input Parameters:
257 + strIdx   - The (1-indexed) location of the format string in the argument list
258 - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
259 
260   Notes:
261   This function attribute causes the compiler to issue warnings when the format specifier does
262   not match the type of the variable that will be formatted, or when there exists a mismatch
263   between the number of format specifiers and variables to be formatted. It is safe to use this
264   macro if your compiler does not support format specifier checking (though this is
265   exceeedingly rare).
266 
267   Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the
268   same value.
269 
270   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
271   the argument list, that is, there is no way to indicate gaps which should not be checked.
272 
273   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
274   header files. In this case the macro will expand empty.
275 
276   Example Usage:
277 .vb
278   // format string is 2nd argument, variable argument list containing args is 3rd argument
279   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
280 
281   int    x = 1;
282   double y = 50.0;
283 
284   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
285   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
286   my_printf(NULL,"%d %g",x,y); // OK
287 .ve
288 
289   Level: developer
290 
291 .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
292 M*/
293 #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
294   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
295 #else
296   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
297 #endif
298 
299 /*MC
300   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
301   executed
302 
303   Notes:
304   The marked function is often optimized for size rather than speed and may be grouped alongside
305   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
306 
307   The paths leading to cold functions are usually automatically marked as unlikely by the
308   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
309   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
310 
311   Example Usage:
312 .vb
313   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
314 
315   if (temperature < 0) {
316     return my_error_handler(...); // chilly!
317   }
318 .ve
319 
320   Level: intermediate
321 
322 .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
323           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
324 M*/
325 #if PetscHasAttribute(__cold__)
326   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
327 #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
328   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
329 #else
330   #define PETSC_ATTRIBUTE_COLD
331 #endif
332 
333 /*MC
334   PETSC_NULLPTR - Standard way of indicating a null value or pointer
335 
336   Notes:
337   Equivalent to NULL in C source, and nullptr in C++ source. Note that for the purposes of
338   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
339   equivalent to setting the same pointer to NULL in C. That is to say that the following
340   expressions are equivalent\:
341 
342 .vb
343   ptr == PETSC_NULLPTR
344   ptr == NULL
345   ptr == 0
346   !ptr
347 
348   ptr = PETSC_NULLPTR
349   ptr = NULL
350   ptr = 0
351 .ve
352 
353   and for completeness' sake\:
354 
355 .vb
356   PETSC_NULLPTR == NULL
357 .ve
358 
359   Fortran Notes:
360   Not available in Fortran
361 
362   Example Usage:
363 .vb
364   // may be used in place of '\0' or other such teminators in the definition of char arrays
365   const char *const MyEnumTypes[] = {
366     "foo",
367     "bar",
368     PETSC_NULLPTR
369   };
370 
371   // may be used to nullify objects
372   PetscObject obj = PETSC_NULLPTR;
373 
374   // may be used in any function expecting NULL
375   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
376 .ve
377 
378   Developer Notes:
379   `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source
380   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
381   resolution and/or compiler warnings.
382 
383   Level: beginner
384 
385 .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
386 M*/
387 
388 /*MC
389   PETSC_CONSTEXPR_14 - C++14 constexpr
390 
391   Notes:
392   Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing
393   if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
394   that this cannot be used in cases where an empty expansion would result in invalid code. It
395   is safe to use this in C source files.
396 
397   Fortran Notes:
398   Not available in Fortran
399 
400   Example Usage:
401 .vb
402   PETSC_CONSTEXPR_14 int factorial(int n)
403   {
404     int r = 1;
405 
406     do {
407       r *= n;
408     } while (--n);
409     return r;
410   }
411 .ve
412 
413   Level: beginner
414 
415 .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
416 M*/
417 
418 /*MC
419   PETSC_NODISCARD - Mark the return value of a function as non-discardable
420 
421   Notes:
422   Hints to the compiler that the return value of a function must be captured. A diagnostic may
423   (but is not required) be emitted if the value is discarded. It is safe to use this in C
424   and C++ source files.
425 
426   Fortran Notes:
427   Not available in Fortran
428 
429   Example Usage:
430 .vb
431   class Foo
432   {
433     int x;
434 
435   public:
436     PETSC_NODISCARD Foo(int y) : x(y) { }
437   };
438 
439   PETSC_NODISCARD int factorial(int n)
440   {
441     return n <= 1 ? 1 : (n * factorial(n - 1));
442   }
443 
444   auto x = factorial(10); // OK, capturing return value
445   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
446 
447   auto f = Foo(x); // OK, capturing constructed object
448   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
449 .ve
450 
451   Developer Notes:
452   It is highly recommended if not downright required that any PETSc routines written in C++
453   returning a PetscErrorCode be marked `PETSC_NODISCARD`. Ignoring the return value of PETSc
454   routines is not supported; unhandled errors may leave PETSc in an unrecoverable state.
455 
456   Level: beginner
457 
458 .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
459 M*/
460 
461 /* C++11 features */
462 #if defined(__cplusplus)
463   #define PETSC_NULLPTR nullptr
464 #else
465   #define PETSC_NULLPTR NULL
466 #endif
467 
468 /* C++14 features */
469 #if PETSC_CPP_VERSION >= 14
470   #define PETSC_CONSTEXPR_14 constexpr
471 #else
472   #define PETSC_CONSTEXPR_14
473 #endif
474 
475 /* C++17 features */
476 #if PETSC_CPP_VERSION >= 17
477   #define PETSC_NODISCARD    [[nodiscard]]
478   #define PETSC_CONSTEXPR_17 constexpr
479 #else
480   #if PetscHasAttribute(warn_unused_result)
481     #define PETSC_NODISCARD __attribute__((warn_unused_result))
482   #endif
483   #define PETSC_CONSTEXPR_17
484 #endif
485 
486 #ifndef PETSC_NODISCARD
487   #define PETSC_NODISCARD
488 #endif
489 
490 #include <petscversion.h>
491 #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
492 
493 /* designated initializers since C99 and C++20, MSVC never supports them though */
494 #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
495   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
496 #else
497   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
498 #endif
499 
500 /*MC
501   PetscUnlikely - Hints the compiler that the given condition is usually false
502 
503   Synopsis:
504   #include <petscmacros.h>
505   bool PetscUnlikely(bool cond)
506 
507   Not Collective
508 
509   Input Parameter:
510 . cond - Boolean expression
511 
512   Notes:
513   Not available from fortran.
514 
515   This returns the same truth value, it is only a hint to compilers that the result of cond is
516   unlikely to be true.
517 
518   Example usage:
519 .vb
520   if (PetscUnlikely(cond)) {
521     foo(); // cold path
522   } else {
523     bar(); // hot path
524   }
525 .ve
526 
527   Level: advanced
528 
529 .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
530           `PETSC_ATTRIBUTE_COLD`
531 M*/
532 
533 /*MC
534   PetscLikely - Hints the compiler that the given condition is usually true
535 
536   Synopsis:
537   #include <petscmacros.h>
538   bool PetscLikely(bool cond)
539 
540   Not Collective
541 
542   Input Parameter:
543 . cond - Boolean expression
544 
545   Notes:
546   Not available from fortran.
547 
548   This returns the same truth value, it is only a hint to compilers that the result of cond is
549   likely to be true.
550 
551   Example usage:
552 .vb
553   if (PetscLikely(cond)) {
554     foo(); // hot path
555   } else {
556     bar(); // cold path
557   }
558 .ve
559 
560   Level: advanced
561 
562 .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
563           `PETSC_ATTRIBUTE_COLD`
564 M*/
565 #if defined(PETSC_HAVE_BUILTIN_EXPECT)
566   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
567   #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
568 #else
569   #define PetscUnlikely(cond) (cond)
570   #define PetscLikely(cond)   (cond)
571 #endif
572 
573 /*MC
574   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
575 
576   Synopsis:
577   #include <petscmacros.h>
578   void PetscUnreachable(void)
579 
580   Notes:
581   Indicates to the compiler (usually via some built-in) that a particular code path is always
582   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
583   unceremonious crash.
584 
585   Example usage:
586   Useful in situations such as switches over enums where not all enumeration values are
587   explicitly covered by the switch
588 
589 .vb
590   typedef enum {RED, GREEN, BLUE} Color;
591 
592   int foo(Color c)
593   {
594     // it is known to programmer (or checked previously) that c is either RED or GREEN
595     // but compiler may not be able to deduce this and/or emit spurious warnings
596     switch (c) {
597       case RED:
598         return bar();
599       case GREEN:
600         return baz();
601       default:
602         PetscUnreachable(); // program is ill-formed if executed
603     }
604   }
605 .ve
606 
607   Level: advanced
608 
609 .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
610 M*/
611 #if defined(__GNUC__)
612   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
613   #define PetscUnreachable() __builtin_unreachable()
614 #elif defined(_MSC_VER) /* MSVC */
615   #define PetscUnreachable() __assume(0)
616 #else /* ??? */
617   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
618 #endif
619 
620 /*MC
621   PetscAssume - Indicate to the compiler a condition that is defined to be true
622 
623   Synopsis:
624   #include <petscmacros.h>
625   void PetscAssume(bool cond)
626 
627   Input Parameter:
628 . cond - Boolean expression
629 
630   Notes:
631   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
632   truth. The argument itself is never evaluated, so any side effects of the expression will be
633   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
634   checks that would be lost in optimized builds. For example\:
635 
636 .vb
637   PetscErrorCode foo(PetscInt x) {
638 
639     PetscAssert(x >= 0, ...);
640   }
641 .ve
642 
643   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
644   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
645   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
646   optimizer cannot deduce any information from them.
647 
648   Due to compiler limitations `PetscAssume()` works best when `cond` involves
649   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
650 
651 .vb
652   int a, b, var_five;
653 
654   // BEST, all supporting compilers will understand a cannot be >= 5
655   PetscAssume(a < 5);
656 
657    // OK, some compilers may understand that a cannot be >= 5
658   PetscAssume(a <= b && b < 5);
659 
660    // WORST, most compilers will not get the memo
661   PetscAssume(a <= b && b < var_five);
662 .ve
663 
664   If the condition is violated at runtime then behavior is wholly undefined. If the
665   condition is violated at compile-time, the condition "supersedes" the compile-time violation
666   and the program is ill-formed, no diagnostic required. For example consider the following\:
667 
668 .vb
669   PetscInt x = 0;
670 
671   PetscAssume(x != 0);
672   if (x == 0) {
673     x += 10;
674   } else {
675     popen("rm -rf /", "w");
676   }
677 .ve
678 
679   Even though `x` is demonstrably `0` the compiler may opt to\:
680 
681   - emit an unconditional `popen("rm -rf /", "w")`
682   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
683   - reformat the primary disk partition
684 
685   Level: advanced
686 
687 .seealso: `PetscAssert()`
688 M*/
689 #if defined(_MSC_VER) // msvc
690   #define PetscAssume(...) __assume(__VA_ARGS__)
691 #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
692   #define PetscAssume(...) \
693     do { \
694       _Pragma("clang diagnostic push"); \
695       _Pragma("clang diagnostic ignored \"-Wassume\""); \
696       __builtin_assume(__VA_ARGS__); \
697       _Pragma("clang diagnostic pop"); \
698     } while (0)
699 #else // gcc (and really old clang)
700   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
701   //
702   // if (PetscUnlikely(!cond)) PetscUnreachable();
703   //
704   // but this it unsavory because the side effects of cond are not guaranteed to be
705   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
706   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
707   // always do so. This is especially the case for opaque or non-inline function calls:
708   //
709   // extern int bar(int);
710   //
711   // int foo(int x) {
712   //   PetscAssume(bar(x) == 2);
713   //   if (bar(x) == 2) {
714   //     return 1;
715   //   } else {
716   //     return 0;
717   //   }
718   // }
719   //
720   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
721   // cond "tested" in the condition, but this is done to silence set-but-unused variable warnings
722   #define PetscAssume(...) \
723     do { \
724       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
725     } while (0)
726 #endif
727 
728 /*MC
729   PetscExpand - Expand macro argument
730 
731   Synopsis:
732   #include <petscmacros.h>
733   <macro-expansion> PetscExpand(x)
734 
735   Input Parameter:
736 . x - The preprocessor token to expand
737 
738   Level: beginner
739 
740 .seealso: `PetscStringize()`, `PetscConcat()`
741 M*/
742 #define PetscExpand_(...) __VA_ARGS__
743 #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
744 
745 /*MC
746   PetscStringize - Stringize a token
747 
748   Synopsis:
749   #include <petscmacros.h>
750   const char* PetscStringize(x)
751 
752   Input Parameter:
753 . x - The token you would like to stringize
754 
755   Output Parameter:
756 . <return-value> - The string representation of x
757 
758   Notes:
759   Not available from Fortran.
760 
761   PetscStringize() expands x before stringizing it, if you do not wish to do so, use
762   PetscStringize_() instead.
763 
764   Example Usage:
765 .vb
766   #define MY_OTHER_VAR hello there
767   #define MY_VAR       MY_OTHER_VAR
768 
769   PetscStringize(MY_VAR)  -> "hello there"
770   PetscStringize_(MY_VAR) -> "MY_VAR"
771 
772   int foo;
773   PetscStringize(foo)  -> "foo"
774   PetscStringize_(foo) -> "foo"
775 .ve
776 
777   Level: beginner
778 
779 .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
780 M*/
781 #define PetscStringize_(...) #__VA_ARGS__
782 #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
783 
784 /*MC
785   PetscConcat - Concatenate two tokens
786 
787   Synopsis:
788   #include <petscmacros.h>
789   <macro-expansion> PetscConcat(x, y)
790 
791   Input Parameters:
792 + x - First token
793 - y - Second token
794 
795   Notes:
796   Not available from Fortran.
797 
798   PetscConcat() will expand both arguments before pasting them together, use PetscConcat_()
799   if you don't want to expand them.
800 
801   Example usage:
802 .vb
803   PetscConcat(hello,there) -> hellothere
804 
805   #define HELLO hello
806   PetscConcat(HELLO,there)  -> hellothere
807   PetscConcat_(HELLO,there) -> HELLOthere
808 .ve
809 
810   Level: beginner
811 
812 .seealso: `PetscStringize()`, `PetscExpand()`
813 M*/
814 #define PetscConcat_(x, y) x##y
815 #define PetscConcat(x, y)  PetscConcat_(x, y)
816 
817 #define PETSC_INTERNAL_COMPL_0 1
818 #define PETSC_INTERNAL_COMPL_1 0
819 
820 /*MC
821   PetscCompl - Expands to the integer complement of its argument
822 
823   Synopsis:
824   #include <petscmacros.h>
825   int PetscCompl(b)
826 
827   Input Parameter:
828 . b - Preprocessor variable, must expand to either integer literal 0 or 1
829 
830   Output Parameter:
831 . <return-value> - Either integer literal 0 or 1
832 
833   Notes:
834   Not available from Fortran.
835 
836   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
837   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
838   argument before returning the complement.
839 
840   This macro can be useful for negating PetscDefined() inside macros e.g.
841 
842 $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
843 
844   Example usage:
845 .vb
846   #define MY_VAR 1
847   PetscCompl(MY_VAR) -> 0
848 
849   #undef  MY_VAR
850   #define MY_VAR 0
851   PetscCompl(MY_VAR) -> 1
852 .ve
853 
854   Level: beginner
855 
856 .seealso: `PetscConcat()`, `PetscDefined()`
857 M*/
858 #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
859 
860 #if !defined(PETSC_SKIP_VARIADIC_MACROS)
861   /*MC
862   PetscDefined - Determine whether a boolean macro is defined
863 
864   Synopsis:
865   #include <petscmacros.h>
866   int PetscDefined(def)
867 
868   Input Parameter:
869 . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
870 
871   Output Parameter:
872 . <return-value> - Either integer literal 0 or 1
873 
874   Notes:
875   Not available from Fortran, requires variadic macro support, definition is disabled by
876   defining `PETSC_SKIP_VARIADIC_MACROS`.
877 
878   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
879   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
880   this macro should not be used if its argument may be defined to a non-empty value other than
881   1.
882 
883   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
884   add custom checks in user code, one should use `PetscDefined_()`.
885 
886 $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d))
887 
888   Developer Notes:
889   Getting something that works in C and CPP for an arg that may or may not be defined is
890   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
891   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
892   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
893   and when the last step cherry picks the 2nd arg, we get a zero.
894 
895   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
896   nonconforming implementation of variadic macros.
897 
898   Example Usage:
899   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
900   is defined then
901 
902 .vb
903   #if PetscDefined(USE_DEBUG)
904     foo();
905   #else
906     bar();
907   #endif
908 
909   // or alternatively within normal code
910   if (PetscDefined(USE_DEBUG)) {
911     foo();
912   } else {
913     bar();
914   }
915 .ve
916 
917   is equivalent to
918 
919 .vb
920   #if defined(PETSC_USE_DEBUG)
921   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
922        foo();
923   #   elif PETSC_USE_DEBUG == 1
924        foo();
925   #   else
926        bar();
927   #  endif
928   #else
929   bar();
930   #endif
931 .ve
932 
933   Level: intermediate
934 
935 .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
936           `PetscExpandToNothing()`, `PetscCompl()`
937 M*/
938   #define PetscDefined_arg_1                                    shift,
939   #define PetscDefined_arg_                                     shift,
940   #define PetscDefined__take_second_expanded(ignored, val, ...) val
941   #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
942   #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
943   #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
944   #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
945   #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
946 
947   /*MC
948   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
949   the check in optimized mode
950 
951   Synopsis:
952   #include <petscmacros.h>
953   bool PetscUnlikelyDebug(bool cond)
954 
955   Not Collective
956 
957   Input Parameters:
958 . cond - Boolean expression
959 
960   Notes:
961   Not available from Fortran, requires variadic macro support, definition is disabled by
962   defining `PETSC_SKIP_VARIADIC_MACROS`.
963 
964   This returns the same truth value, it is only a hint to compilers that the result of cond is
965   likely to be false. When PETSc is compiled in optimized mode this will always return
966   false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in
967   optimized mode.
968 
969   Example usage:
970   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
971   is true. So
972 
973 .vb
974   if (PetscUnlikelyDebug(cond)) {
975     foo();
976   } else {
977     bar();
978   }
979 .ve
980 
981   is equivalent to
982 
983 .vb
984   if (PetscDefined(USE_DEBUG)) {
985     if (PetscUnlikely(cond)) {
986       foo();
987     } else {
988       bar();
989     }
990   } else {
991     bar();
992   }
993 .ve
994 
995   Level: advanced
996 
997 .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
998 M*/
999   #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1000 
1001   #if defined(PETSC_CLANG_STATIC_ANALYZER)
1002     // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1003     // not what ISO C allows
1004     #define PetscMacroReturns_(retexpr, ...) \
1005       __extension__({ \
1006         __VA_ARGS__; \
1007         retexpr; \
1008       })
1009   #else
1010     #define PetscMacroReturns_(retexpr, ...) \
1011       retexpr; \
1012       do { \
1013         __VA_ARGS__; \
1014       } while (0)
1015   #endif
1016 
1017   /*MC
1018   PetscExpandToNothing - Expands to absolutely nothing at all
1019 
1020   Synopsis:
1021   #include <petscmacros.h>
1022   void PetscExpandToNothing(...)
1023 
1024   Input Parameter:
1025 . __VA_ARGS__ - Anything at all
1026 
1027   Notes:
1028   Not available from Fortran, requires variadic macro support, definition is disabled by
1029   defining `PETSC_SKIP_VARIADIC_MACROS`.
1030 
1031   Must have at least 1 parameter.
1032 
1033   Example usage:
1034 .vb
1035   PetscExpandToNothing(a,b,c) -> *nothing*
1036 .ve
1037 
1038   Level: beginner
1039 
1040 .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1041 M*/
1042   #define PetscExpandToNothing(...)
1043 
1044   /*MC
1045   PetscMacroReturns - Define a macro body that returns a value
1046 
1047   Synopsis:
1048   #include <petscmacros.h>
1049   return_type PetscMacroReturns(return_type retexpr, ...)
1050 
1051   Input Parameters:
1052 + retexpr     - The value or expression that the macro should return
1053 - __VA_ARGS__ - The body of the macro
1054 
1055   Notes:
1056   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1057   body of the macro and should not depend on values produced as a result of the expression. The
1058   user should not assume that the result of this macro is equivalent to a single logical source
1059   line. It is not portable to use macros defined using this one in conditional or loop bodies
1060   without enclosing them in curly braces\:
1061 
1062 .vb
1063   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1064 
1065   int err,x = 10;
1066 
1067   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1068   if (...) { err = FOO(x); }  // OK
1069 
1070   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1071   for (...) { err = FOO(x); } // OK
1072 .ve
1073 
1074   It is also not portable to use this macro directly inside function call, conditional, loop,
1075   or switch statements\:
1076 
1077 .vb
1078   extern void bar(int);
1079 
1080   int ret = FOO(x);
1081 
1082   bar(FOO(x)); // ERROR, may not compile
1083   bar(ret);    // OK
1084 
1085   if (FOO(x))  // ERROR, may not compile
1086   if (ret)     // OK
1087 .ve
1088 
1089   Example usage:
1090 .vb
1091   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1092 
1093   int x = 10;
1094   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1095 
1096   // multiline macros allowed, but must declare with line continuation as usual
1097   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1098     if (arg1 > 10) {                                            \
1099       puts("big int!");                                         \
1100     } else {                                                    \
1101       return 7355608;                                           \
1102     }                                                           \
1103   )
1104 
1105   // if retexpr contains commas, must enclose it with braces
1106   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1107   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1108 
1109   int x = 10;
1110   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1111   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1112 .ve
1113 
1114   Level: intermediate
1115 
1116 .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1117 M*/
1118   #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1119 
1120   #define PetscMacroReturnStandard(...) PetscMacroReturns(0, __VA_ARGS__)
1121 
1122 #endif /* !PETSC_SKIP_VARIADIC_MACROS */
1123 
1124 /*MC
1125   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1126 
1127   Level: intermediate
1128 M*/
1129 #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
1130 
1131 /*
1132   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1133 
1134   Example usage:
1135 
1136   #define mymacro(obj,...) {
1137     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1138     f(22 PETSC_REST_ARG(__VA_ARGS__));
1139   }
1140 
1141   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
1142 
1143   Reference:
1144   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1145 */
1146 #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1147 #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1148 #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1149 #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1150 #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1151 #define PETSC_REST_HELPER_ONE(first)
1152 #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1153 #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1154 #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1155 
1156 #endif /* PETSC_PREPROCESSOR_MACROS_H */
1157