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