xref: /petsc/include/petscmacros.h (revision edd03b47ed9fa9b7ef9dd67df42d5194593a501d)
1bde483f2SJacob Faibussowitsch #ifndef PETSC_PREPROCESSOR_MACROS_H
2bde483f2SJacob Faibussowitsch #define PETSC_PREPROCESSOR_MACROS_H
3bde483f2SJacob Faibussowitsch 
4bde483f2SJacob Faibussowitsch #include <petscconf.h>
5bde483f2SJacob Faibussowitsch #include <petscconf_poison.h> /* for PetscDefined() error checking */
6bde483f2SJacob Faibussowitsch 
7ac09b921SBarry Smith /* SUBMANSEC = Sys */
8ac09b921SBarry Smith 
90e6b6b59SJacob Faibussowitsch #if defined(__cplusplus)
100e6b6b59SJacob Faibussowitsch   #if __cplusplus <= 201103L
110e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 11
120e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 201402L
130e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 14
140e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 201703L
150e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 17
160e6b6b59SJacob Faibussowitsch   #elif __cplusplus <= 202002L
170e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 20
180e6b6b59SJacob Faibussowitsch   #else
190e6b6b59SJacob Faibussowitsch     #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification
200e6b6b59SJacob Faibussowitsch   #endif
210e6b6b59SJacob Faibussowitsch #endif // __cplusplus
220e6b6b59SJacob Faibussowitsch 
230e6b6b59SJacob Faibussowitsch #ifndef PETSC_CPP_VERSION
240e6b6b59SJacob Faibussowitsch   #define PETSC_CPP_VERSION 0
250e6b6b59SJacob Faibussowitsch #endif
260e6b6b59SJacob Faibussowitsch 
276797ed33SJacob Faibussowitsch #if defined(__STDC_VERSION__)
286797ed33SJacob Faibussowitsch   #if __STDC_VERSION__ <= 199901L
296797ed33SJacob Faibussowitsch     // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead
306797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 9
316797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201112L
326797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 11
336797ed33SJacob Faibussowitsch   #elif __STDC_VERSION__ <= 201710L
346797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 17
356797ed33SJacob Faibussowitsch   #else
366797ed33SJacob Faibussowitsch     #define PETSC_C_VERSION 22 // current year, or date of c2b ratification
376797ed33SJacob Faibussowitsch   #endif
386797ed33SJacob Faibussowitsch #endif // __STDC_VERSION__
396797ed33SJacob Faibussowitsch 
406797ed33SJacob Faibussowitsch #ifndef PETSC_C_VERSION
416797ed33SJacob Faibussowitsch   #define PETSC_C_VERSION 0
426797ed33SJacob Faibussowitsch #endif
436797ed33SJacob Faibussowitsch 
44bde483f2SJacob Faibussowitsch /* ========================================================================== */
45bde483f2SJacob Faibussowitsch /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */
46bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
47bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX
48bde483f2SJacob Faibussowitsch #else
49bde483f2SJacob Faibussowitsch   #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C
50bde483f2SJacob Faibussowitsch #endif
51bde483f2SJacob Faibussowitsch 
52bde483f2SJacob Faibussowitsch /* ========================================================================== */
53bde483f2SJacob Faibussowitsch /* Since PETSc manages its own extern "C" handling users should never include PETSc include
54bde483f2SJacob Faibussowitsch  * files within extern "C". This will generate a compiler error if a user does put the include
55bde483f2SJacob Faibussowitsch  * file within an extern "C".
56bde483f2SJacob Faibussowitsch  */
57bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
589371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(int);
599371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(double);
60bde483f2SJacob Faibussowitsch #endif
61bde483f2SJacob Faibussowitsch 
62bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
63bde483f2SJacob Faibussowitsch   #define PETSC_RESTRICT PETSC_CXX_RESTRICT
64bde483f2SJacob Faibussowitsch #else
656ee8c794SJacob Faibussowitsch   #define PETSC_RESTRICT restrict
66bde483f2SJacob Faibussowitsch #endif
67bde483f2SJacob Faibussowitsch 
68*edd03b47SJacob Faibussowitsch #define PETSC_INLINE        PETSC_DEPRECATED_MACRO(3, 17, 0, "inline", ) inline
69*edd03b47SJacob Faibussowitsch #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO(3, 17, 0, "static inline", ) static inline
70bde483f2SJacob Faibussowitsch 
71bde483f2SJacob Faibussowitsch #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */
72bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT __declspec(dllexport)
73bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT __declspec(dllimport)
74bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
75bde483f2SJacob Faibussowitsch #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX)
76bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
77bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
78bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
79bde483f2SJacob Faibussowitsch #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C)
80bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT           __attribute__((visibility("default")))
81bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT           __attribute__((visibility("default")))
82bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden")))
83bde483f2SJacob Faibussowitsch #else
84bde483f2SJacob Faibussowitsch   #define PETSC_DLLEXPORT
85bde483f2SJacob Faibussowitsch   #define PETSC_DLLIMPORT
86bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_INTERNAL
87bde483f2SJacob Faibussowitsch #endif
88bde483f2SJacob Faibussowitsch 
89bde483f2SJacob Faibussowitsch #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */
90bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT
91bde483f2SJacob Faibussowitsch #else /* Win32 users need this to import symbols from petsc.dll */
92bde483f2SJacob Faibussowitsch   #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT
93bde483f2SJacob Faibussowitsch #endif
94bde483f2SJacob Faibussowitsch 
95bde483f2SJacob Faibussowitsch /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when
96bde483f2SJacob Faibussowitsch  * compiled with C++ so they may be used from C and are always visible in the shared libraries
97bde483f2SJacob Faibussowitsch  */
98bde483f2SJacob Faibussowitsch #if defined(__cplusplus)
99bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN         extern "C" PETSC_VISIBILITY_PUBLIC
100bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF extern "C"
101bde483f2SJacob Faibussowitsch   #define PETSC_INTERN         extern "C" PETSC_VISIBILITY_INTERNAL
102bde483f2SJacob Faibussowitsch #else
103bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC
104bde483f2SJacob Faibussowitsch   #define PETSC_EXTERN_TYPEDEF
105bde483f2SJacob Faibussowitsch   #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL
106bde483f2SJacob Faibussowitsch #endif
107bde483f2SJacob Faibussowitsch 
108bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_SINGLE_LIBRARY)
10947f8145dSJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_INTERNAL
110bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_INTERN
111bde483f2SJacob Faibussowitsch #else
11247f8145dSJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL PETSC_VISIBILITY_PUBLIC
113bde483f2SJacob Faibussowitsch   #define PETSC_SINGLE_LIBRARY_INTERN              PETSC_EXTERN
114bde483f2SJacob Faibussowitsch #endif
115bde483f2SJacob Faibussowitsch 
1161cf396e4SJacob Faibussowitsch #if !defined(__has_feature)
1171cf396e4SJacob Faibussowitsch   #define __has_feature(x) 0
1181cf396e4SJacob Faibussowitsch #endif
1191cf396e4SJacob Faibussowitsch 
120bde483f2SJacob Faibussowitsch /*MC
121bde483f2SJacob Faibussowitsch   PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler
122bde483f2SJacob Faibussowitsch 
123bde483f2SJacob Faibussowitsch   Synopsis:
124bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
125c7481402SJacob Faibussowitsch   int PetscHasAttribute(name)
126bde483f2SJacob Faibussowitsch 
127bde483f2SJacob Faibussowitsch   Input Parameter:
128bde483f2SJacob Faibussowitsch . name - The name of the attribute to test
129bde483f2SJacob Faibussowitsch 
130bde483f2SJacob Faibussowitsch   Notes:
131bde483f2SJacob Faibussowitsch   name should be identical to what you might pass to the __attribute__ declaration itself --
132bde483f2SJacob Faibussowitsch   plain, unbroken text.
133bde483f2SJacob Faibussowitsch 
134c7481402SJacob Faibussowitsch   As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the
135c7481402SJacob Faibussowitsch   exact type and value returned is implementation defined. In practice however, it usually
136c7481402SJacob Faibussowitsch   returns `1` if the attribute is supported and `0` if the attribute is not supported.
137bde483f2SJacob Faibussowitsch 
138bde483f2SJacob Faibussowitsch   Example Usage:
139bde483f2SJacob Faibussowitsch   Typical usage is using the preprocessor
140bde483f2SJacob Faibussowitsch 
141bde483f2SJacob Faibussowitsch .vb
142bde483f2SJacob Faibussowitsch   #if PetscHasAttribute(always_inline)
143bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE __attribute__((always_inline))
144bde483f2SJacob Faibussowitsch   #else
145bde483f2SJacob Faibussowitsch   #  define MY_ALWAYS_INLINE
146bde483f2SJacob Faibussowitsch   #endif
147bde483f2SJacob Faibussowitsch 
148bde483f2SJacob Faibussowitsch   void foo(void) MY_ALWAYS_INLINE;
149bde483f2SJacob Faibussowitsch .ve
150bde483f2SJacob Faibussowitsch 
151bde483f2SJacob Faibussowitsch   but it can also be used in regular code
152bde483f2SJacob Faibussowitsch 
153bde483f2SJacob Faibussowitsch .vb
154bde483f2SJacob Faibussowitsch   if (PetscHasAttribute(some_attribute)) {
155bde483f2SJacob Faibussowitsch     foo();
156bde483f2SJacob Faibussowitsch   } else {
157bde483f2SJacob Faibussowitsch     bar();
158bde483f2SJacob Faibussowitsch   }
159bde483f2SJacob Faibussowitsch .ve
160bde483f2SJacob Faibussowitsch 
161bde483f2SJacob Faibussowitsch   Level: intermediate
162bde483f2SJacob Faibussowitsch 
163c7481402SJacob Faibussowitsch .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`,
164f7b5d04fSPierre Jolivet `PETSC_ATTRIBUTE_FORMAT`, `PETSC_ATTRIBUTE_MAY_ALIAS`
165bde483f2SJacob Faibussowitsch M*/
166bde483f2SJacob Faibussowitsch #if !defined(__has_attribute)
167bde483f2SJacob Faibussowitsch   #define __has_attribute(x) 0
168bde483f2SJacob Faibussowitsch #endif
169bde483f2SJacob Faibussowitsch #define PetscHasAttribute(name) __has_attribute(name)
170bde483f2SJacob Faibussowitsch 
171c7481402SJacob Faibussowitsch /*MC
172c7481402SJacob Faibussowitsch   PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler
173c7481402SJacob Faibussowitsch 
174c7481402SJacob Faibussowitsch   Synopsis:
175c7481402SJacob Faibussowitsch   #include <petscmacros.h>
176c7481402SJacob Faibussowitsch   int PetscHasBuiltin(name)
177c7481402SJacob Faibussowitsch 
178c7481402SJacob Faibussowitsch   Input Parameter:
179c7481402SJacob Faibussowitsch . name - the name of the builtin routine
180c7481402SJacob Faibussowitsch 
181c7481402SJacob Faibussowitsch   Notes:
182d5b43468SJose E. Roman   Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates"
183c7481402SJacob Faibussowitsch   (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying
184c7481402SJacob Faibussowitsch   detector is itself is a compiler extension with implementation-defined return type and
185c7481402SJacob Faibussowitsch   semantics. Some compilers implement it as a macro, others as a compiler function. In practice
186c7481402SJacob Faibussowitsch   however, all supporting compilers return an integer boolean as described.
187c7481402SJacob Faibussowitsch 
188c7481402SJacob Faibussowitsch   Example Usage:
189c7481402SJacob Faibussowitsch   Typical usage is in preprocessor directives
190c7481402SJacob Faibussowitsch 
191c7481402SJacob Faibussowitsch .vb
192c7481402SJacob Faibussowitsch   #if PetscHasBuiltin(__builtin_trap)
193c7481402SJacob Faibussowitsch   __builtin_trap();
194c7481402SJacob Faibussowitsch   #else
195c7481402SJacob Faibussowitsch   abort();
196c7481402SJacob Faibussowitsch   #endif
197c7481402SJacob Faibussowitsch .ve
198c7481402SJacob Faibussowitsch 
199c7481402SJacob Faibussowitsch   But it may also be used in regular code
200c7481402SJacob Faibussowitsch 
201c7481402SJacob Faibussowitsch .vb
202c7481402SJacob Faibussowitsch   if (PetscHasBuiltin(__builtin_alloca)) {
203c7481402SJacob Faibussowitsch     foo();
204c7481402SJacob Faibussowitsch   } else {
205c7481402SJacob Faibussowitsch     bar();
206c7481402SJacob Faibussowitsch   }
207c7481402SJacob Faibussowitsch .ve
208c7481402SJacob Faibussowitsch 
209c7481402SJacob Faibussowitsch   Level: intermediate
210c7481402SJacob Faibussowitsch 
211c7481402SJacob Faibussowitsch .seealso: `PetscHasAttribute()`, `PetscAssume()`
212c7481402SJacob Faibussowitsch M*/
213c7481402SJacob Faibussowitsch #if !defined(__has_builtin)
214c7481402SJacob Faibussowitsch   #define __has_builtin(x) 0
215c7481402SJacob Faibussowitsch #endif
216c7481402SJacob Faibussowitsch // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as
217c7481402SJacob Faibussowitsch // __builtin_types_compatible_p which take types or other non-functiony things as
218c7481402SJacob Faibussowitsch // arguments. The correct way to detect these then is to use __is_identifier (also a clang
219c7481402SJacob Faibussowitsch // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153
220c7481402SJacob Faibussowitsch #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier)
221c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __is_identifier(name)
222c7481402SJacob Faibussowitsch #else
223c7481402SJacob Faibussowitsch   #define PetscHasBuiltin(name) __has_builtin(name)
224c7481402SJacob Faibussowitsch #endif
225c7481402SJacob Faibussowitsch 
22693d501b3SJacob Faibussowitsch #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG)
22793d501b3SJacob Faibussowitsch   /*
22893d501b3SJacob Faibussowitsch    Support for Clang (>=3.2) matching type tag arguments with void* buffer types.
22993d501b3SJacob Faibussowitsch    This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine
23093d501b3SJacob Faibussowitsch    does not match the actual type of the argument being passed in
23193d501b3SJacob Faibussowitsch */
23293d501b3SJacob Faibussowitsch   #if PetscHasAttribute(pointer_with_type_tag)
23393d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno)))
23493d501b3SJacob Faibussowitsch   #endif
23593d501b3SJacob Faibussowitsch 
23693d501b3SJacob Faibussowitsch   #if PetscHasAttribute(type_tag_for_datatype)
23793d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)                   __attribute__((type_tag_for_datatype(MPI, type)))
23893d501b3SJacob Faibussowitsch     #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible)))
23993d501b3SJacob Faibussowitsch   #endif
24093d501b3SJacob Faibussowitsch #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG
24193d501b3SJacob Faibussowitsch 
24293d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE
24393d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno)
24493d501b3SJacob Faibussowitsch #endif
24593d501b3SJacob Faibussowitsch 
24693d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG
24793d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type)
24893d501b3SJacob Faibussowitsch #endif
24993d501b3SJacob Faibussowitsch 
25093d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE
25193d501b3SJacob Faibussowitsch   #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type)
25293d501b3SJacob Faibussowitsch #endif
25393d501b3SJacob Faibussowitsch 
254bde483f2SJacob Faibussowitsch /*MC
25563a3b9bcSJacob Faibussowitsch   PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated
25663a3b9bcSJacob Faibussowitsch   as format specifiers and checked for validity
25763a3b9bcSJacob Faibussowitsch 
25863a3b9bcSJacob Faibussowitsch   Synopsis:
25963a3b9bcSJacob Faibussowitsch   #include <petscmacros.h>
26063a3b9bcSJacob Faibussowitsch   <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx)
26163a3b9bcSJacob Faibussowitsch 
26263a3b9bcSJacob Faibussowitsch   Input Parameters:
26363a3b9bcSJacob Faibussowitsch + strIdx   - The (1-indexed) location of the format string in the argument list
26463a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list
26563a3b9bcSJacob Faibussowitsch 
26616a05f60SBarry Smith   Level: developer
26716a05f60SBarry Smith 
26863a3b9bcSJacob Faibussowitsch   Notes:
26963a3b9bcSJacob Faibussowitsch   This function attribute causes the compiler to issue warnings when the format specifier does
27063a3b9bcSJacob Faibussowitsch   not match the type of the variable that will be formatted, or when there exists a mismatch
27163a3b9bcSJacob Faibussowitsch   between the number of format specifiers and variables to be formatted. It is safe to use this
27263a3b9bcSJacob Faibussowitsch   macro if your compiler does not support format specifier checking (though this is
27363a3b9bcSJacob Faibussowitsch   exceeedingly rare).
27463a3b9bcSJacob Faibussowitsch 
27516a05f60SBarry Smith   Both `strIdx` and `vaArgIdx` must be compile-time constant integer literals and cannot have the
27663a3b9bcSJacob Faibussowitsch   same value.
27763a3b9bcSJacob Faibussowitsch 
27863a3b9bcSJacob Faibussowitsch   The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in
27963a3b9bcSJacob Faibussowitsch   the argument list, that is, there is no way to indicate gaps which should not be checked.
28063a3b9bcSJacob Faibussowitsch 
28187497f52SBarry Smith   Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc
28263a3b9bcSJacob Faibussowitsch   header files. In this case the macro will expand empty.
28363a3b9bcSJacob Faibussowitsch 
28463a3b9bcSJacob Faibussowitsch   Example Usage:
28563a3b9bcSJacob Faibussowitsch .vb
28663a3b9bcSJacob Faibussowitsch   // format string is 2nd argument, variable argument list containing args is 3rd argument
28763a3b9bcSJacob Faibussowitsch   void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3)
28863a3b9bcSJacob Faibussowitsch 
28963a3b9bcSJacob Faibussowitsch   int    x = 1;
29063a3b9bcSJacob Faibussowitsch   double y = 50.0;
29163a3b9bcSJacob Faibussowitsch 
29263a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%g",x);      // WARNING, format specifier does not match for 'int'!
29363a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d",x,y);    // WARNING, more arguments than format specifiers!
29463a3b9bcSJacob Faibussowitsch   my_printf(NULL,"%d %g",x,y); // OK
29563a3b9bcSJacob Faibussowitsch .ve
29663a3b9bcSJacob Faibussowitsch 
297db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()`
29863a3b9bcSJacob Faibussowitsch M*/
29963a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT)
30063a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx)))
30163a3b9bcSJacob Faibussowitsch #else
30263a3b9bcSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx)
30363a3b9bcSJacob Faibussowitsch #endif
30463a3b9bcSJacob Faibussowitsch 
30563a3b9bcSJacob Faibussowitsch /*MC
306d8e4614bSJacob Faibussowitsch   PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be
307d8e4614bSJacob Faibussowitsch   executed
308d8e4614bSJacob Faibussowitsch 
30916a05f60SBarry Smith   Level: intermediate
31016a05f60SBarry Smith 
311d8e4614bSJacob Faibussowitsch   Notes:
312d8e4614bSJacob Faibussowitsch   The marked function is often optimized for size rather than speed and may be grouped alongside
313d8e4614bSJacob Faibussowitsch   other equally frigid routines improving code locality of lukewarm or hotter parts of program.
314d8e4614bSJacob Faibussowitsch 
315d8e4614bSJacob Faibussowitsch   The paths leading to cold functions are usually automatically marked as unlikely by the
316d8e4614bSJacob Faibussowitsch   compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such
317d8e4614bSJacob Faibussowitsch   as error handlers -- as cold to improve optimization of the surrounding temperate functions.
318d8e4614bSJacob Faibussowitsch 
319d8e4614bSJacob Faibussowitsch   Example Usage:
320d8e4614bSJacob Faibussowitsch .vb
321d8e4614bSJacob Faibussowitsch   void my_error_handler(...) PETSC_ATTRIBUTE_COLD;
322d8e4614bSJacob Faibussowitsch 
323d8e4614bSJacob Faibussowitsch   if (temperature < 0) {
324d8e4614bSJacob Faibussowitsch     return my_error_handler(...); // chilly!
325d8e4614bSJacob Faibussowitsch   }
326d8e4614bSJacob Faibussowitsch .ve
327d8e4614bSJacob Faibussowitsch 
328db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`,
329db781477SPatrick Sanan           `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT`
330d8e4614bSJacob Faibussowitsch M*/
331d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__)
332d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__))
333d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */
334d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD __attribute__((cold))
335d8e4614bSJacob Faibussowitsch #else
336d8e4614bSJacob Faibussowitsch   #define PETSC_ATTRIBUTE_COLD
337d8e4614bSJacob Faibussowitsch #endif
338d8e4614bSJacob Faibussowitsch 
339d8e4614bSJacob Faibussowitsch /*MC
340f7b5d04fSPierre Jolivet   PETSC_ATTRIBUTE_MAY_ALIAS - Indicate to the compiler that a type is not
341f7b5d04fSPierre Jolivet   subjected to type-based alias analysis, but is instead assumed to be able to
342f7b5d04fSPierre Jolivet   alias any other type of objects
343f7b5d04fSPierre Jolivet 
344752b9880SPierre Jolivet   Example Usage:
345752b9880SPierre Jolivet .vb
346752b9880SPierre Jolivet   typedef PetscScalar PetscScalarAlias PETSC_ATTRIBUTE_MAY_ALIAS;
347752b9880SPierre Jolivet 
348752b9880SPierre Jolivet   PetscReal        *pointer;
349752b9880SPierre Jolivet   PetscScalarAlias *other_pointer = reinterpret_cast<PetscScalarAlias *>(pointer);
350752b9880SPierre Jolivet .ve
351752b9880SPierre Jolivet 
352f7b5d04fSPierre Jolivet   Level: advanced
353f7b5d04fSPierre Jolivet 
354f7b5d04fSPierre Jolivet .seealso: `PetscHasAttribute()`
355f7b5d04fSPierre Jolivet M*/
356f7b5d04fSPierre Jolivet #if PetscHasAttribute(may_alias) && !defined(PETSC_SKIP_ATTRIBUTE_MAY_ALIAS)
357f7b5d04fSPierre Jolivet   #define PETSC_ATTRIBUTE_MAY_ALIAS __attribute__((may_alias))
358f7b5d04fSPierre Jolivet #else
359f7b5d04fSPierre Jolivet   #define PETSC_ATTRIBUTE_MAY_ALIAS
360f7b5d04fSPierre Jolivet #endif
361f7b5d04fSPierre Jolivet 
362f7b5d04fSPierre Jolivet /*MC
363bde483f2SJacob Faibussowitsch   PETSC_NULLPTR - Standard way of indicating a null value or pointer
364bde483f2SJacob Faibussowitsch 
36520f4b53cSBarry Smith   No Fortran Support
36620f4b53cSBarry Smith 
36720f4b53cSBarry Smith   Level: beginner
36820f4b53cSBarry Smith 
369bde483f2SJacob Faibussowitsch   Notes:
37016a05f60SBarry Smith   Equivalent to `NULL` in C source, and `nullptr` in C++ source. Note that for the purposes of
37116a05f60SBarry Smith   interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially
37220f4b53cSBarry Smith   equivalent to setting the same pointer to `NULL` in C. That is to say that the following
373bde483f2SJacob Faibussowitsch   expressions are equivalent\:
374bde483f2SJacob Faibussowitsch 
375bde483f2SJacob Faibussowitsch .vb
376bde483f2SJacob Faibussowitsch   ptr == PETSC_NULLPTR
377bde483f2SJacob Faibussowitsch   ptr == NULL
378bde483f2SJacob Faibussowitsch   ptr == 0
379bde483f2SJacob Faibussowitsch   !ptr
380bde483f2SJacob Faibussowitsch 
381bde483f2SJacob Faibussowitsch   ptr = PETSC_NULLPTR
382bde483f2SJacob Faibussowitsch   ptr = NULL
383bde483f2SJacob Faibussowitsch   ptr = 0
384bde483f2SJacob Faibussowitsch .ve
385bde483f2SJacob Faibussowitsch 
386bde483f2SJacob Faibussowitsch   and for completeness' sake\:
387bde483f2SJacob Faibussowitsch 
388bde483f2SJacob Faibussowitsch .vb
389bde483f2SJacob Faibussowitsch   PETSC_NULLPTR == NULL
390bde483f2SJacob Faibussowitsch .ve
391bde483f2SJacob Faibussowitsch 
392bde483f2SJacob Faibussowitsch   Example Usage:
393bde483f2SJacob Faibussowitsch .vb
394bde483f2SJacob Faibussowitsch   // may be used in place of '\0' or other such teminators in the definition of char arrays
395bde483f2SJacob Faibussowitsch   const char *const MyEnumTypes[] = {
396bde483f2SJacob Faibussowitsch     "foo",
397bde483f2SJacob Faibussowitsch     "bar",
398bde483f2SJacob Faibussowitsch     PETSC_NULLPTR
399bde483f2SJacob Faibussowitsch   };
400bde483f2SJacob Faibussowitsch 
401bde483f2SJacob Faibussowitsch   // may be used to nullify objects
402bde483f2SJacob Faibussowitsch   PetscObject obj = PETSC_NULLPTR;
403bde483f2SJacob Faibussowitsch 
404bde483f2SJacob Faibussowitsch   // may be used in any function expecting NULL
405bde483f2SJacob Faibussowitsch   PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor");
406bde483f2SJacob Faibussowitsch .ve
407bde483f2SJacob Faibussowitsch 
408bde483f2SJacob Faibussowitsch   Developer Notes:
40916a05f60SBarry Smith   `PETSC_NULLPTR` must be used in place of `NULL` in all C++ source files. Using `NULL` in source
410bde483f2SJacob Faibussowitsch   files compiled with a C++ compiler may lead to unexpected side-effects in function overload
411bde483f2SJacob Faibussowitsch   resolution and/or compiler warnings.
412bde483f2SJacob Faibussowitsch 
413db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD`
414817da375SSatish Balay M*/
415bde483f2SJacob Faibussowitsch 
416bde483f2SJacob Faibussowitsch /*MC
417bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 - C++14 constexpr
418bde483f2SJacob Faibussowitsch 
41920f4b53cSBarry Smith   No Fortran Support
42020f4b53cSBarry Smith 
42120f4b53cSBarry Smith   Level: beginner
42220f4b53cSBarry Smith 
423bde483f2SJacob Faibussowitsch   Notes:
42416a05f60SBarry Smith   Equivalent to `constexpr` when using a C++ compiler that supports C++14. Expands to nothing
425d5b43468SJose E. Roman   if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note
426bde483f2SJacob Faibussowitsch   that this cannot be used in cases where an empty expansion would result in invalid code. It
427bde483f2SJacob Faibussowitsch   is safe to use this in C source files.
428bde483f2SJacob Faibussowitsch 
429bde483f2SJacob Faibussowitsch   Example Usage:
430bde483f2SJacob Faibussowitsch .vb
431bde483f2SJacob Faibussowitsch   PETSC_CONSTEXPR_14 int factorial(int n)
432bde483f2SJacob Faibussowitsch   {
433bde483f2SJacob Faibussowitsch     int r = 1;
434bde483f2SJacob Faibussowitsch 
435bde483f2SJacob Faibussowitsch     do {
436bde483f2SJacob Faibussowitsch       r *= n;
437bde483f2SJacob Faibussowitsch     } while (--n);
438bde483f2SJacob Faibussowitsch     return r;
439bde483f2SJacob Faibussowitsch   }
440bde483f2SJacob Faibussowitsch .ve
441bde483f2SJacob Faibussowitsch 
442db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD`
443817da375SSatish Balay M*/
444bde483f2SJacob Faibussowitsch 
445bde483f2SJacob Faibussowitsch /*MC
446bde483f2SJacob Faibussowitsch   PETSC_NODISCARD - Mark the return value of a function as non-discardable
447bde483f2SJacob Faibussowitsch 
448089fb57cSJacob Faibussowitsch   Not available in Fortran
449089fb57cSJacob Faibussowitsch 
450089fb57cSJacob Faibussowitsch   Level: beginner
451089fb57cSJacob Faibussowitsch 
452bde483f2SJacob Faibussowitsch   Notes:
453bde483f2SJacob Faibussowitsch   Hints to the compiler that the return value of a function must be captured. A diagnostic may
454089fb57cSJacob Faibussowitsch   (but is not required to) be emitted if the value is discarded. It is safe to use this in both
455089fb57cSJacob Faibussowitsch   C and C++ source files.
456bde483f2SJacob Faibussowitsch 
457d571e81cSJacob Faibussowitsch   In this context "captured" means assigning the return value of a function to a named
458d571e81cSJacob Faibussowitsch   variable or casting it to `void`. Between the two, assigning to a named variable is the most
459d571e81cSJacob Faibussowitsch   portable way of silencing any warnings, since `PETSC_NODISCARD` may expand to GCC's
460d571e81cSJacob Faibussowitsch   `__attribute__((warn_unused_result))` which will still emit warnings when casting results to
461d571e81cSJacob Faibussowitsch   `void`.
462d571e81cSJacob Faibussowitsch 
463bde483f2SJacob Faibussowitsch   Example Usage:
464bde483f2SJacob Faibussowitsch .vb
465bde483f2SJacob Faibussowitsch   class Foo
466bde483f2SJacob Faibussowitsch   {
467bde483f2SJacob Faibussowitsch     int x;
468bde483f2SJacob Faibussowitsch 
469bde483f2SJacob Faibussowitsch   public:
470bde483f2SJacob Faibussowitsch     PETSC_NODISCARD Foo(int y) : x(y) { }
471bde483f2SJacob Faibussowitsch   };
472bde483f2SJacob Faibussowitsch 
473bde483f2SJacob Faibussowitsch   PETSC_NODISCARD int factorial(int n)
474bde483f2SJacob Faibussowitsch   {
475bde483f2SJacob Faibussowitsch     return n <= 1 ? 1 : (n * factorial(n - 1));
476bde483f2SJacob Faibussowitsch   }
477bde483f2SJacob Faibussowitsch 
478bde483f2SJacob Faibussowitsch   factorial(10);          // Warning: ignoring return value of function declared 'nodiscard'
479d571e81cSJacob Faibussowitsch   auto x = factorial(10); // OK, capturing return value
480d571e81cSJacob Faibussowitsch   (void)factorial(10);    // Maybe OK, casting to void
481d571e81cSJacob Faibussowitsch   auto y = factorial(10); // OK, capturing in y (and casting y to void to silence
482d571e81cSJacob Faibussowitsch   (void)y;                // set-but-not-used warnings)
483bde483f2SJacob Faibussowitsch 
484bde483f2SJacob Faibussowitsch   Foo(x);          // Warning: Ignoring temporary created by a constructor declared 'nodiscard'
485d571e81cSJacob Faibussowitsch   auto f = Foo(x); // OK, capturing constructed object
486d571e81cSJacob Faibussowitsch   (void)Foo(x);    // Maybe OK, casting to void
487d571e81cSJacob Faibussowitsch   auto g = Foo(x); // OK, capturing in g (and casting g to void to silence set-but-not-used
488d571e81cSJacob Faibussowitsch   (void)g;         // warnings)
489bde483f2SJacob Faibussowitsch .ve
490bde483f2SJacob Faibussowitsch 
491db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14`
492817da375SSatish Balay M*/
493bde483f2SJacob Faibussowitsch 
494bde483f2SJacob Faibussowitsch /* C++11 features */
495089fb57cSJacob Faibussowitsch #if defined(__cplusplus) || (PETSC_C_VERSION >= 23)
496bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR nullptr
497bde483f2SJacob Faibussowitsch #else
498bde483f2SJacob Faibussowitsch   #define PETSC_NULLPTR NULL
499bde483f2SJacob Faibussowitsch #endif
500bde483f2SJacob Faibussowitsch 
501bde483f2SJacob Faibussowitsch /* C++14 features */
5020e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14
5036ee8c794SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14 constexpr
504bde483f2SJacob Faibussowitsch #else
505bde483f2SJacob Faibussowitsch   #define PETSC_CONSTEXPR_14
506bde483f2SJacob Faibussowitsch #endif
507bde483f2SJacob Faibussowitsch 
508bde483f2SJacob Faibussowitsch /* C++17 features */
5090e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17
5100e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17 constexpr
511bde483f2SJacob Faibussowitsch #else
5120e6b6b59SJacob Faibussowitsch   #define PETSC_CONSTEXPR_17
5130e6b6b59SJacob Faibussowitsch #endif
5140e6b6b59SJacob Faibussowitsch 
515089fb57cSJacob Faibussowitsch #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23)
516089fb57cSJacob Faibussowitsch   #define PETSC_NODISCARD [[nodiscard]]
517089fb57cSJacob Faibussowitsch #elif PetscHasAttribute(warn_unused_result)
518089fb57cSJacob Faibussowitsch   #define PETSC_NODISCARD __attribute__((warn_unused_result))
519089fb57cSJacob Faibussowitsch #else
5200e6b6b59SJacob Faibussowitsch   #define PETSC_NODISCARD
521bde483f2SJacob Faibussowitsch #endif
522bde483f2SJacob Faibussowitsch 
523bde483f2SJacob Faibussowitsch #include <petscversion.h>
524bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO "       The PETSc Team\n    petsc-maint@mcs.anl.gov\n https://petsc.org/\n"
525bde483f2SJacob Faibussowitsch 
526267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */
5270e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20))
528267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) __VA_ARGS__
529267267bdSJacob Faibussowitsch #else
530267267bdSJacob Faibussowitsch   #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__
531267267bdSJacob Faibussowitsch #endif
532267267bdSJacob Faibussowitsch 
533bde483f2SJacob Faibussowitsch /*MC
53487497f52SBarry Smith   PetscUnlikely - Hints the compiler that the given condition is usually false
535bde483f2SJacob Faibussowitsch 
536bde483f2SJacob Faibussowitsch   Synopsis:
537bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
538bde483f2SJacob Faibussowitsch   bool PetscUnlikely(bool cond)
539bde483f2SJacob Faibussowitsch 
54016a05f60SBarry Smith   Not Collective; No Fortran Support
541bde483f2SJacob Faibussowitsch 
542bde483f2SJacob Faibussowitsch   Input Parameter:
543bde483f2SJacob Faibussowitsch . cond - Boolean expression
544bde483f2SJacob Faibussowitsch 
54516a05f60SBarry Smith   Level: advanced
546bde483f2SJacob Faibussowitsch 
54716a05f60SBarry Smith   Notes:
548bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
549bde483f2SJacob Faibussowitsch   unlikely to be true.
550bde483f2SJacob Faibussowitsch 
551bde483f2SJacob Faibussowitsch   Example usage:
552bde483f2SJacob Faibussowitsch .vb
553bde483f2SJacob Faibussowitsch   if (PetscUnlikely(cond)) {
554bde483f2SJacob Faibussowitsch     foo(); // cold path
555bde483f2SJacob Faibussowitsch   } else {
556bde483f2SJacob Faibussowitsch     bar(); // hot path
557bde483f2SJacob Faibussowitsch   }
558bde483f2SJacob Faibussowitsch .ve
559bde483f2SJacob Faibussowitsch 
560db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`,
561db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
562bde483f2SJacob Faibussowitsch M*/
563bde483f2SJacob Faibussowitsch 
564bde483f2SJacob Faibussowitsch /*MC
56587497f52SBarry Smith   PetscLikely - Hints the compiler that the given condition is usually true
566bde483f2SJacob Faibussowitsch 
567bde483f2SJacob Faibussowitsch   Synopsis:
568bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
569bde483f2SJacob Faibussowitsch   bool PetscLikely(bool cond)
570bde483f2SJacob Faibussowitsch 
57116a05f60SBarry Smith   Not Collective; No Fortran Support
572bde483f2SJacob Faibussowitsch 
573bde483f2SJacob Faibussowitsch   Input Parameter:
574bde483f2SJacob Faibussowitsch . cond - Boolean expression
575bde483f2SJacob Faibussowitsch 
57616a05f60SBarry Smith   Level: advanced
577bde483f2SJacob Faibussowitsch 
57816a05f60SBarry Smith   Notes:
579bde483f2SJacob Faibussowitsch   This returns the same truth value, it is only a hint to compilers that the result of cond is
580bde483f2SJacob Faibussowitsch   likely to be true.
581bde483f2SJacob Faibussowitsch 
582bde483f2SJacob Faibussowitsch   Example usage:
583bde483f2SJacob Faibussowitsch .vb
584bde483f2SJacob Faibussowitsch   if (PetscLikely(cond)) {
585bde483f2SJacob Faibussowitsch     foo(); // hot path
586bde483f2SJacob Faibussowitsch   } else {
587bde483f2SJacob Faibussowitsch     bar(); // cold path
588bde483f2SJacob Faibussowitsch   }
589bde483f2SJacob Faibussowitsch .ve
590bde483f2SJacob Faibussowitsch 
591db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()`
592db781477SPatrick Sanan           `PETSC_ATTRIBUTE_COLD`
593bde483f2SJacob Faibussowitsch M*/
594bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT)
595bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0)
596bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   __builtin_expect(!!(cond), 1)
597bde483f2SJacob Faibussowitsch #else
598bde483f2SJacob Faibussowitsch   #define PetscUnlikely(cond) (cond)
599bde483f2SJacob Faibussowitsch   #define PetscLikely(cond)   (cond)
600bde483f2SJacob Faibussowitsch #endif
601bde483f2SJacob Faibussowitsch 
602bde483f2SJacob Faibussowitsch /*MC
603817da375SSatish Balay   PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable
604bde483f2SJacob Faibussowitsch 
605bde483f2SJacob Faibussowitsch   Synopsis:
606bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
607bde483f2SJacob Faibussowitsch   void PetscUnreachable(void)
608bde483f2SJacob Faibussowitsch 
60916a05f60SBarry Smith   Level: advanced
61016a05f60SBarry Smith 
611bde483f2SJacob Faibussowitsch   Notes:
612bde483f2SJacob Faibussowitsch   Indicates to the compiler (usually via some built-in) that a particular code path is always
613bde483f2SJacob Faibussowitsch   unreachable. Behavior is undefined if this function is ever executed, the user can expect an
614bde483f2SJacob Faibussowitsch   unceremonious crash.
615bde483f2SJacob Faibussowitsch 
616bde483f2SJacob Faibussowitsch   Example usage:
617bde483f2SJacob Faibussowitsch   Useful in situations such as switches over enums where not all enumeration values are
618bde483f2SJacob Faibussowitsch   explicitly covered by the switch
619bde483f2SJacob Faibussowitsch 
620bde483f2SJacob Faibussowitsch .vb
621bde483f2SJacob Faibussowitsch   typedef enum {RED, GREEN, BLUE} Color;
622bde483f2SJacob Faibussowitsch 
623bde483f2SJacob Faibussowitsch   int foo(Color c)
624bde483f2SJacob Faibussowitsch   {
625bde483f2SJacob Faibussowitsch     // it is known to programmer (or checked previously) that c is either RED or GREEN
626bde483f2SJacob Faibussowitsch     // but compiler may not be able to deduce this and/or emit spurious warnings
627bde483f2SJacob Faibussowitsch     switch (c) {
628bde483f2SJacob Faibussowitsch       case RED:
629bde483f2SJacob Faibussowitsch         return bar();
630bde483f2SJacob Faibussowitsch       case GREEN:
631bde483f2SJacob Faibussowitsch         return baz();
632bde483f2SJacob Faibussowitsch       default:
633bde483f2SJacob Faibussowitsch         PetscUnreachable(); // program is ill-formed if executed
634bde483f2SJacob Faibussowitsch     }
635bde483f2SJacob Faibussowitsch   }
636bde483f2SJacob Faibussowitsch .ve
637bde483f2SJacob Faibussowitsch 
638c7481402SJacob Faibussowitsch .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()`
639817da375SSatish Balay M*/
640563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23
641563b2f50SJacob Faibussowitsch   #include <utility>
642563b2f50SJacob Faibussowitsch   #define PetscUnreachable() std::unreachable()
643563b2f50SJacob Faibussowitsch #elif defined(__GNUC__)
644e58a63e1SJacob Faibussowitsch   /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */
645e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __builtin_unreachable()
646e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */
647e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() __assume(0)
648e58a63e1SJacob Faibussowitsch #else /* ??? */
649e58a63e1SJacob Faibussowitsch   #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed")
650e58a63e1SJacob Faibussowitsch #endif
651bde483f2SJacob Faibussowitsch 
652bde483f2SJacob Faibussowitsch /*MC
653c7481402SJacob Faibussowitsch   PetscAssume - Indicate to the compiler a condition that is defined to be true
654c7481402SJacob Faibussowitsch 
655c7481402SJacob Faibussowitsch   Synopsis:
656c7481402SJacob Faibussowitsch   #include <petscmacros.h>
657c7481402SJacob Faibussowitsch   void PetscAssume(bool cond)
658c7481402SJacob Faibussowitsch 
659c7481402SJacob Faibussowitsch   Input Parameter:
660c7481402SJacob Faibussowitsch . cond - Boolean expression
661c7481402SJacob Faibussowitsch 
66216a05f60SBarry Smith   Level: advanced
66316a05f60SBarry Smith 
664c7481402SJacob Faibussowitsch   Notes:
665c7481402SJacob Faibussowitsch   If supported by the compiler, `cond` is used to inform the optimizer of an invariant
666c7481402SJacob Faibussowitsch   truth. The argument itself is never evaluated, so any side effects of the expression will be
667c7481402SJacob Faibussowitsch   discarded. This macro is used in `PetscAssert()` to retain information gained from debug
668c7481402SJacob Faibussowitsch   checks that would be lost in optimized builds. For example\:
669c7481402SJacob Faibussowitsch 
670c7481402SJacob Faibussowitsch .vb
671c7481402SJacob Faibussowitsch   PetscErrorCode foo(PetscInt x) {
672c7481402SJacob Faibussowitsch 
673c7481402SJacob Faibussowitsch     PetscAssert(x >= 0, ...);
674c7481402SJacob Faibussowitsch   }
675c7481402SJacob Faibussowitsch .ve
676c7481402SJacob Faibussowitsch 
677c7481402SJacob Faibussowitsch   The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()`
678c7481402SJacob Faibussowitsch   if it is not). This implicitly informs the optimizer that `x` cannot be negative. However,
679c7481402SJacob Faibussowitsch   when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the
680c7481402SJacob Faibussowitsch   optimizer cannot deduce any information from them.
681c7481402SJacob Faibussowitsch 
682c7481402SJacob Faibussowitsch   Due to compiler limitations `PetscAssume()` works best when `cond` involves
683d5b43468SJose E. Roman   constants. Certain compilers do not yet propagate symbolic inequalities i.e.\:
684c7481402SJacob Faibussowitsch 
685c7481402SJacob Faibussowitsch .vb
686c7481402SJacob Faibussowitsch   int a, b, var_five;
687c7481402SJacob Faibussowitsch 
688c7481402SJacob Faibussowitsch   // BEST, all supporting compilers will understand a cannot be >= 5
689c7481402SJacob Faibussowitsch   PetscAssume(a < 5);
690c7481402SJacob Faibussowitsch 
691c7481402SJacob Faibussowitsch    // OK, some compilers may understand that a cannot be >= 5
692c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < 5);
693c7481402SJacob Faibussowitsch 
694c7481402SJacob Faibussowitsch    // WORST, most compilers will not get the memo
695c7481402SJacob Faibussowitsch   PetscAssume(a <= b && b < var_five);
696c7481402SJacob Faibussowitsch .ve
697c7481402SJacob Faibussowitsch 
698c7481402SJacob Faibussowitsch   If the condition is violated at runtime then behavior is wholly undefined. If the
699c7481402SJacob Faibussowitsch   condition is violated at compile-time, the condition "supersedes" the compile-time violation
700c7481402SJacob Faibussowitsch   and the program is ill-formed, no diagnostic required. For example consider the following\:
701c7481402SJacob Faibussowitsch 
702c7481402SJacob Faibussowitsch .vb
703c7481402SJacob Faibussowitsch   PetscInt x = 0;
704c7481402SJacob Faibussowitsch 
705c7481402SJacob Faibussowitsch   PetscAssume(x != 0);
706c7481402SJacob Faibussowitsch   if (x == 0) {
707c7481402SJacob Faibussowitsch     x += 10;
708c7481402SJacob Faibussowitsch   } else {
709c7481402SJacob Faibussowitsch     popen("rm -rf /", "w");
710c7481402SJacob Faibussowitsch   }
711c7481402SJacob Faibussowitsch .ve
712c7481402SJacob Faibussowitsch 
713c7481402SJacob Faibussowitsch   Even though `x` is demonstrably `0` the compiler may opt to\:
714c7481402SJacob Faibussowitsch 
715c7481402SJacob Faibussowitsch   - emit an unconditional `popen("rm -rf /", "w")`
716c7481402SJacob Faibussowitsch   - ignore `PetscAssume()` altogether and emit the correct path of `x += 10`
717c7481402SJacob Faibussowitsch   - reformat the primary disk partition
718c7481402SJacob Faibussowitsch 
719c7481402SJacob Faibussowitsch .seealso: `PetscAssert()`
720c7481402SJacob Faibussowitsch M*/
721563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23
722563b2f50SJacob Faibussowitsch   #define PetscAssume(...) [[assume(__VA_ARGS__)]]
723563b2f50SJacob Faibussowitsch #elif defined(_MSC_VER) // msvc
724c7481402SJacob Faibussowitsch   #define PetscAssume(...) __assume(__VA_ARGS__)
725c7481402SJacob Faibussowitsch #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang
726c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
727c7481402SJacob Faibussowitsch     do { \
728c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic push"); \
729c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic ignored \"-Wassume\""); \
730c7481402SJacob Faibussowitsch       __builtin_assume(__VA_ARGS__); \
731c7481402SJacob Faibussowitsch       _Pragma("clang diagnostic pop"); \
732c7481402SJacob Faibussowitsch     } while (0)
733c7481402SJacob Faibussowitsch #else // gcc (and really old clang)
734c7481402SJacob Faibussowitsch   // gcc does not have its own __builtin_assume() intrinsic. One could fake it via
735c7481402SJacob Faibussowitsch   //
736c7481402SJacob Faibussowitsch   // if (PetscUnlikely(!cond)) PetscUnreachable();
737c7481402SJacob Faibussowitsch   //
738c7481402SJacob Faibussowitsch   // but this it unsavory because the side effects of cond are not guaranteed to be
739c7481402SJacob Faibussowitsch   // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation
740c7481402SJacob Faibussowitsch   // for which cond is false would be undefined results in undefined behavior anyway) it cannot
741c7481402SJacob Faibussowitsch   // always do so. This is especially the case for opaque or non-inline function calls:
742c7481402SJacob Faibussowitsch   //
743c7481402SJacob Faibussowitsch   // extern int bar(int);
744c7481402SJacob Faibussowitsch   //
745c7481402SJacob Faibussowitsch   // int foo(int x) {
746c7481402SJacob Faibussowitsch   //   PetscAssume(bar(x) == 2);
747c7481402SJacob Faibussowitsch   //   if (bar(x) == 2) {
748c7481402SJacob Faibussowitsch   //     return 1;
749c7481402SJacob Faibussowitsch   //   } else {
750c7481402SJacob Faibussowitsch   //     return 0;
751c7481402SJacob Faibussowitsch   //   }
752c7481402SJacob Faibussowitsch   // }
753c7481402SJacob Faibussowitsch   //
754c7481402SJacob Faibussowitsch   // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have
7552f181314SPierre Jolivet   // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings
756c7481402SJacob Faibussowitsch   #define PetscAssume(...) \
757c7481402SJacob Faibussowitsch     do { \
758c7481402SJacob Faibussowitsch       if (0 && (__VA_ARGS__)) PetscUnreachable(); \
759c7481402SJacob Faibussowitsch     } while (0)
760c7481402SJacob Faibussowitsch #endif
761c7481402SJacob Faibussowitsch 
762c7481402SJacob Faibussowitsch /*MC
763bde483f2SJacob Faibussowitsch   PetscExpand - Expand macro argument
764bde483f2SJacob Faibussowitsch 
765bde483f2SJacob Faibussowitsch   Synopsis:
766bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
767bde483f2SJacob Faibussowitsch   <macro-expansion> PetscExpand(x)
768bde483f2SJacob Faibussowitsch 
7696aad120cSJose E. Roman   Input Parameter:
770bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand
771bde483f2SJacob Faibussowitsch 
77249762cbcSSatish Balay   Level: beginner
77349762cbcSSatish Balay 
774db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()`
775817da375SSatish Balay M*/
776e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__
777e58a63e1SJacob Faibussowitsch #define PetscExpand(...)  PetscExpand_(__VA_ARGS__)
778bde483f2SJacob Faibussowitsch 
779bde483f2SJacob Faibussowitsch /*MC
780bde483f2SJacob Faibussowitsch   PetscStringize - Stringize a token
781bde483f2SJacob Faibussowitsch 
782bde483f2SJacob Faibussowitsch   Synopsis:
783bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
784bde483f2SJacob Faibussowitsch   const char* PetscStringize(x)
785bde483f2SJacob Faibussowitsch 
78616a05f60SBarry Smith   No Fortran Support
78716a05f60SBarry Smith 
788bde483f2SJacob Faibussowitsch   Input Parameter:
789bde483f2SJacob Faibussowitsch . x - The token you would like to stringize
790bde483f2SJacob Faibussowitsch 
791bde483f2SJacob Faibussowitsch   Output Parameter:
79216a05f60SBarry Smith . <return-value> - The string representation of `x`
793bde483f2SJacob Faibussowitsch 
79416a05f60SBarry Smith   Level: beginner
795bde483f2SJacob Faibussowitsch 
79616a05f60SBarry Smith   Note:
79716a05f60SBarry Smith   `PetscStringize()` expands `x` before stringizing it, if you do not wish to do so, use
79816a05f60SBarry Smith   `PetscStringize_()` instead.
799bde483f2SJacob Faibussowitsch 
800bde483f2SJacob Faibussowitsch   Example Usage:
801bde483f2SJacob Faibussowitsch .vb
802bde483f2SJacob Faibussowitsch   #define MY_OTHER_VAR hello there
803bde483f2SJacob Faibussowitsch   #define MY_VAR       MY_OTHER_VAR
804bde483f2SJacob Faibussowitsch 
805bde483f2SJacob Faibussowitsch   PetscStringize(MY_VAR)  -> "hello there"
806bde483f2SJacob Faibussowitsch   PetscStringize_(MY_VAR) -> "MY_VAR"
807bde483f2SJacob Faibussowitsch 
808bde483f2SJacob Faibussowitsch   int foo;
809bde483f2SJacob Faibussowitsch   PetscStringize(foo)  -> "foo"
810bde483f2SJacob Faibussowitsch   PetscStringize_(foo) -> "foo"
811bde483f2SJacob Faibussowitsch .ve
812bde483f2SJacob Faibussowitsch 
813db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()`
814817da375SSatish Balay M*/
8150e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__
8160e6b6b59SJacob Faibussowitsch #define PetscStringize(...)  PetscStringize_(__VA_ARGS__)
817bde483f2SJacob Faibussowitsch 
818bde483f2SJacob Faibussowitsch /*MC
819bde483f2SJacob Faibussowitsch   PetscConcat - Concatenate two tokens
820bde483f2SJacob Faibussowitsch 
821bde483f2SJacob Faibussowitsch   Synopsis:
822bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
823bde483f2SJacob Faibussowitsch   <macro-expansion> PetscConcat(x, y)
824bde483f2SJacob Faibussowitsch 
82516a05f60SBarry Smith   No Fortran Support
82616a05f60SBarry Smith 
827bde483f2SJacob Faibussowitsch   Input Parameters:
828bde483f2SJacob Faibussowitsch + x - First token
829bde483f2SJacob Faibussowitsch - y - Second token
830bde483f2SJacob Faibussowitsch 
83116a05f60SBarry Smith   Level: beginner
832bde483f2SJacob Faibussowitsch 
83316a05f60SBarry Smith   Note:
83416a05f60SBarry Smith   `PetscConcat()` will expand both arguments before pasting them together, use `PetscConcat_()`
835bde483f2SJacob Faibussowitsch   if you don't want to expand them.
836bde483f2SJacob Faibussowitsch 
837bde483f2SJacob Faibussowitsch   Example usage:
838bde483f2SJacob Faibussowitsch .vb
839bde483f2SJacob Faibussowitsch   PetscConcat(hello,there) -> hellothere
840bde483f2SJacob Faibussowitsch 
841bde483f2SJacob Faibussowitsch   #define HELLO hello
842bde483f2SJacob Faibussowitsch   PetscConcat(HELLO,there)  -> hellothere
843bde483f2SJacob Faibussowitsch   PetscConcat_(HELLO,there) -> HELLOthere
844bde483f2SJacob Faibussowitsch .ve
845bde483f2SJacob Faibussowitsch 
846db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()`
847817da375SSatish Balay M*/
848bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y
849bde483f2SJacob Faibussowitsch #define PetscConcat(x, y)  PetscConcat_(x, y)
850bde483f2SJacob Faibussowitsch 
851bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1
852bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0
853bde483f2SJacob Faibussowitsch 
854bde483f2SJacob Faibussowitsch /*MC
855bde483f2SJacob Faibussowitsch   PetscCompl - Expands to the integer complement of its argument
856bde483f2SJacob Faibussowitsch 
857bde483f2SJacob Faibussowitsch   Synopsis:
858bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
859bde483f2SJacob Faibussowitsch   int PetscCompl(b)
860bde483f2SJacob Faibussowitsch 
86116a05f60SBarry Smith   No Fortran Support
86216a05f60SBarry Smith 
863bde483f2SJacob Faibussowitsch   Input Parameter:
864bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1
865bde483f2SJacob Faibussowitsch 
8666aad120cSJose E. Roman   Output Parameter:
867bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
868bde483f2SJacob Faibussowitsch 
86916a05f60SBarry Smith   Level: beginner
870bde483f2SJacob Faibussowitsch 
87116a05f60SBarry Smith   Notes:
872bde483f2SJacob Faibussowitsch   Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to
873bde483f2SJacob Faibussowitsch   0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its
874bde483f2SJacob Faibussowitsch   argument before returning the complement.
875bde483f2SJacob Faibussowitsch 
87616a05f60SBarry Smith   This macro can be useful for negating `PetscDefined()` inside macros e.g.
877bde483f2SJacob Faibussowitsch 
878bde483f2SJacob Faibussowitsch $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO))
879bde483f2SJacob Faibussowitsch 
880bde483f2SJacob Faibussowitsch   Example usage:
881bde483f2SJacob Faibussowitsch .vb
882bde483f2SJacob Faibussowitsch   #define MY_VAR 1
883bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 0
884bde483f2SJacob Faibussowitsch 
885bde483f2SJacob Faibussowitsch   #undef  MY_VAR
886bde483f2SJacob Faibussowitsch   #define MY_VAR 0
887bde483f2SJacob Faibussowitsch   PetscCompl(MY_VAR) -> 1
888bde483f2SJacob Faibussowitsch .ve
889bde483f2SJacob Faibussowitsch 
890db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`
891817da375SSatish Balay M*/
892bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b))
893bde483f2SJacob Faibussowitsch 
894bde483f2SJacob Faibussowitsch /*MC
895bde483f2SJacob Faibussowitsch   PetscDefined - Determine whether a boolean macro is defined
896bde483f2SJacob Faibussowitsch 
897bde483f2SJacob Faibussowitsch   Synopsis:
898bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
899bde483f2SJacob Faibussowitsch   int PetscDefined(def)
900bde483f2SJacob Faibussowitsch 
9017cdbe19fSJose E. Roman   No Fortran Support
9027cdbe19fSJose E. Roman 
903bde483f2SJacob Faibussowitsch   Input Parameter:
904bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!)
905bde483f2SJacob Faibussowitsch 
906d5b43468SJose E. Roman   Output Parameter:
907bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1
908bde483f2SJacob Faibussowitsch 
90916a05f60SBarry Smith   Level: intermediate
91016a05f60SBarry Smith 
911bde483f2SJacob Faibussowitsch   Notes:
91287497f52SBarry Smith   `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to
91387497f52SBarry Smith   integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore
914bde483f2SJacob Faibussowitsch   this macro should not be used if its argument may be defined to a non-empty value other than
915bde483f2SJacob Faibussowitsch   1.
916bde483f2SJacob Faibussowitsch 
917bde483f2SJacob Faibussowitsch   The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to
91887497f52SBarry Smith   add custom checks in user code, one should use `PetscDefined_()`.
919bde483f2SJacob Faibussowitsch 
920bde483f2SJacob Faibussowitsch $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_, d))
921bde483f2SJacob Faibussowitsch 
922bde483f2SJacob Faibussowitsch   Developer Notes:
923bde483f2SJacob Faibussowitsch   Getting something that works in C and CPP for an arg that may or may not be defined is
924bde483f2SJacob Faibussowitsch   tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define,
925bde483f2SJacob Faibussowitsch   insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks
926bde483f2SJacob Faibussowitsch   the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair,
927bde483f2SJacob Faibussowitsch   and when the last step cherry picks the 2nd arg, we get a zero.
928bde483f2SJacob Faibussowitsch 
929bde483f2SJacob Faibussowitsch   Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a
930bde483f2SJacob Faibussowitsch   nonconforming implementation of variadic macros.
931bde483f2SJacob Faibussowitsch 
932bde483f2SJacob Faibussowitsch   Example Usage:
933bde483f2SJacob Faibussowitsch   Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG
934bde483f2SJacob Faibussowitsch   is defined then
935bde483f2SJacob Faibussowitsch 
936bde483f2SJacob Faibussowitsch .vb
937bde483f2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
938bde483f2SJacob Faibussowitsch     foo();
939bde483f2SJacob Faibussowitsch   #else
940bde483f2SJacob Faibussowitsch     bar();
941bde483f2SJacob Faibussowitsch   #endif
942bde483f2SJacob Faibussowitsch 
943bde483f2SJacob Faibussowitsch   // or alternatively within normal code
944bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
945bde483f2SJacob Faibussowitsch     foo();
946bde483f2SJacob Faibussowitsch   } else {
947bde483f2SJacob Faibussowitsch     bar();
948bde483f2SJacob Faibussowitsch   }
949bde483f2SJacob Faibussowitsch .ve
950bde483f2SJacob Faibussowitsch 
951bde483f2SJacob Faibussowitsch   is equivalent to
952bde483f2SJacob Faibussowitsch 
953bde483f2SJacob Faibussowitsch .vb
954bde483f2SJacob Faibussowitsch   #if defined(PETSC_USE_DEBUG)
955bde483f2SJacob Faibussowitsch   #  if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro
956bde483f2SJacob Faibussowitsch        foo();
957bde483f2SJacob Faibussowitsch   #   elif PETSC_USE_DEBUG == 1
958bde483f2SJacob Faibussowitsch        foo();
959bde483f2SJacob Faibussowitsch   #   else
960bde483f2SJacob Faibussowitsch        bar();
961bde483f2SJacob Faibussowitsch   #  endif
962bde483f2SJacob Faibussowitsch   #else
963bde483f2SJacob Faibussowitsch   bar();
964bde483f2SJacob Faibussowitsch   #endif
965bde483f2SJacob Faibussowitsch .ve
966bde483f2SJacob Faibussowitsch 
967db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`,
968db781477SPatrick Sanan           `PetscExpandToNothing()`, `PetscCompl()`
969817da375SSatish Balay M*/
970bde483f2SJacob Faibussowitsch #define PetscDefined_arg_1                                    shift,
971bde483f2SJacob Faibussowitsch #define PetscDefined_arg_                                     shift,
972bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expanded(ignored, val, ...) val
973bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expand(args)                PetscDefined__take_second_expanded args
974bde483f2SJacob Faibussowitsch #define PetscDefined__take_second(...)                        PetscDefined__take_second_expand((__VA_ARGS__))
975bde483f2SJacob Faibussowitsch #define PetscDefined__(arg1_or_junk)                          PetscDefined__take_second(arg1_or_junk 1, 0, at_)
976bde483f2SJacob Faibussowitsch #define PetscDefined_(value)                                  PetscDefined__(PetscConcat_(PetscDefined_arg_, value))
977bde483f2SJacob Faibussowitsch #define PetscDefined(def)                                     PetscDefined_(PetscConcat(PETSC_, def))
978bde483f2SJacob Faibussowitsch 
979bde483f2SJacob Faibussowitsch /*MC
98087497f52SBarry Smith   PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding
981bde483f2SJacob Faibussowitsch   the check in optimized mode
982bde483f2SJacob Faibussowitsch 
983bde483f2SJacob Faibussowitsch   Synopsis:
984bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
985bde483f2SJacob Faibussowitsch   bool PetscUnlikelyDebug(bool cond)
986bde483f2SJacob Faibussowitsch 
9877cdbe19fSJose E. Roman   No Fortran Support
9887cdbe19fSJose E. Roman 
989bde483f2SJacob Faibussowitsch   Not Collective
990bde483f2SJacob Faibussowitsch 
9912fe279fdSBarry Smith   Input Parameter:
992bde483f2SJacob Faibussowitsch . cond - Boolean expression
993bde483f2SJacob Faibussowitsch 
99416a05f60SBarry Smith   Level: advanced
99516a05f60SBarry Smith 
99616a05f60SBarry Smith   Note:
99716a05f60SBarry Smith   This returns the same truth value, it is only a hint to compilers that the result of `cond` is
998bde483f2SJacob Faibussowitsch   likely to be false. When PETSc is compiled in optimized mode this will always return
99916a05f60SBarry Smith   false. Additionally, `cond` is guaranteed to not be evaluated when PETSc is compiled in
1000bde483f2SJacob Faibussowitsch   optimized mode.
1001bde483f2SJacob Faibussowitsch 
1002bde483f2SJacob Faibussowitsch   Example usage:
1003bde483f2SJacob Faibussowitsch   This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG)
1004bde483f2SJacob Faibussowitsch   is true. So
1005bde483f2SJacob Faibussowitsch 
1006bde483f2SJacob Faibussowitsch .vb
1007bde483f2SJacob Faibussowitsch   if (PetscUnlikelyDebug(cond)) {
1008bde483f2SJacob Faibussowitsch     foo();
1009bde483f2SJacob Faibussowitsch   } else {
1010bde483f2SJacob Faibussowitsch     bar();
1011bde483f2SJacob Faibussowitsch   }
1012bde483f2SJacob Faibussowitsch .ve
1013bde483f2SJacob Faibussowitsch 
1014bde483f2SJacob Faibussowitsch   is equivalent to
1015bde483f2SJacob Faibussowitsch 
1016bde483f2SJacob Faibussowitsch .vb
1017bde483f2SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
1018bde483f2SJacob Faibussowitsch     if (PetscUnlikely(cond)) {
1019bde483f2SJacob Faibussowitsch       foo();
1020bde483f2SJacob Faibussowitsch     } else {
1021bde483f2SJacob Faibussowitsch       bar();
1022bde483f2SJacob Faibussowitsch     }
1023bde483f2SJacob Faibussowitsch   } else {
1024bde483f2SJacob Faibussowitsch     bar();
1025bde483f2SJacob Faibussowitsch   }
1026bde483f2SJacob Faibussowitsch .ve
1027bde483f2SJacob Faibussowitsch 
1028db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ`
1029bde483f2SJacob Faibussowitsch M*/
1030bde483f2SJacob Faibussowitsch #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond))
1031bde483f2SJacob Faibussowitsch 
1032f7e3c444SJacob Faibussowitsch #if defined(PETSC_CLANG_STATIC_ANALYZER)
1033f7e3c444SJacob Faibussowitsch   // silence compiler warnings when using -pedantic, this is only used by the linter and it cares
1034f7e3c444SJacob Faibussowitsch   // not what ISO C allows
10359371c9d4SSatish Balay   #define PetscMacroReturns_(retexpr, ...) \
10369371c9d4SSatish Balay     __extension__({ \
10379371c9d4SSatish Balay       __VA_ARGS__; \
10389371c9d4SSatish Balay       retexpr; \
10399371c9d4SSatish Balay     })
1040f7e3c444SJacob Faibussowitsch #else
10419371c9d4SSatish Balay   #define PetscMacroReturns_(retexpr, ...) \
10429371c9d4SSatish Balay     retexpr; \
1043d71ae5a4SJacob Faibussowitsch     do { \
1044d71ae5a4SJacob Faibussowitsch       __VA_ARGS__; \
1045d71ae5a4SJacob Faibussowitsch     } while (0)
1046f7e3c444SJacob Faibussowitsch #endif
1047f7e3c444SJacob Faibussowitsch 
1048bde483f2SJacob Faibussowitsch /*MC
104916a05f60SBarry Smith   PetscExpandToNothing - Expands to absolutely nothing
1050bde483f2SJacob Faibussowitsch 
1051bde483f2SJacob Faibussowitsch   Synopsis:
1052bde483f2SJacob Faibussowitsch   #include <petscmacros.h>
1053bde483f2SJacob Faibussowitsch   void PetscExpandToNothing(...)
1054bde483f2SJacob Faibussowitsch 
10557cdbe19fSJose E. Roman   No Fortran Support
10567cdbe19fSJose E. Roman 
1057bde483f2SJacob Faibussowitsch   Input Parameter:
1058bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all
1059bde483f2SJacob Faibussowitsch 
106016a05f60SBarry Smith   Level: beginner
106116a05f60SBarry Smith 
106216a05f60SBarry Smith   Note:
1063bde483f2SJacob Faibussowitsch   Must have at least 1 parameter.
1064bde483f2SJacob Faibussowitsch 
1065bde483f2SJacob Faibussowitsch   Example usage:
1066bde483f2SJacob Faibussowitsch .vb
1067bde483f2SJacob Faibussowitsch   PetscExpandToNothing(a,b,c) -> *nothing*
1068bde483f2SJacob Faibussowitsch .ve
1069bde483f2SJacob Faibussowitsch 
1070db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()`
1071817da375SSatish Balay M*/
1072bde483f2SJacob Faibussowitsch #define PetscExpandToNothing(...)
1073f7e3c444SJacob Faibussowitsch 
1074f7e3c444SJacob Faibussowitsch /*MC
1075f7e3c444SJacob Faibussowitsch   PetscMacroReturns - Define a macro body that returns a value
1076f7e3c444SJacob Faibussowitsch 
1077f7e3c444SJacob Faibussowitsch   Synopsis:
1078f7e3c444SJacob Faibussowitsch   #include <petscmacros.h>
1079f7e3c444SJacob Faibussowitsch   return_type PetscMacroReturns(return_type retexpr, ...)
1080f7e3c444SJacob Faibussowitsch 
1081f7e3c444SJacob Faibussowitsch   Input Parameters:
1082f7e3c444SJacob Faibussowitsch + retexpr     - The value or expression that the macro should return
1083f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro
1084f7e3c444SJacob Faibussowitsch 
108516a05f60SBarry Smith   Level: intermediate
108616a05f60SBarry Smith 
1087f7e3c444SJacob Faibussowitsch   Notes:
1088f7e3c444SJacob Faibussowitsch   Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the
1089f7e3c444SJacob Faibussowitsch   body of the macro and should not depend on values produced as a result of the expression. The
1090f7e3c444SJacob Faibussowitsch   user should not assume that the result of this macro is equivalent to a single logical source
1091f7e3c444SJacob Faibussowitsch   line. It is not portable to use macros defined using this one in conditional or loop bodies
1092f7e3c444SJacob Faibussowitsch   without enclosing them in curly braces\:
1093f7e3c444SJacob Faibussowitsch 
1094f7e3c444SJacob Faibussowitsch .vb
1095f7e3c444SJacob Faibussowitsch   #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0
1096f7e3c444SJacob Faibussowitsch 
1097f7e3c444SJacob Faibussowitsch   int err,x = 10;
1098f7e3c444SJacob Faibussowitsch 
1099f7e3c444SJacob Faibussowitsch   if (...) err = FOO(x);      // ERROR, body of FOO() executed outside the if statement
1100f7e3c444SJacob Faibussowitsch   if (...) { err = FOO(x); }  // OK
1101f7e3c444SJacob Faibussowitsch 
1102f7e3c444SJacob Faibussowitsch   for (...) err = FOO(x);     // ERROR, body of FOO() executed outside the loop
1103f7e3c444SJacob Faibussowitsch   for (...) { err = FOO(x); } // OK
1104f7e3c444SJacob Faibussowitsch .ve
1105f7e3c444SJacob Faibussowitsch 
1106f7e3c444SJacob Faibussowitsch   It is also not portable to use this macro directly inside function call, conditional, loop,
1107f7e3c444SJacob Faibussowitsch   or switch statements\:
1108f7e3c444SJacob Faibussowitsch 
1109f7e3c444SJacob Faibussowitsch .vb
1110f7e3c444SJacob Faibussowitsch   extern void bar(int);
1111f7e3c444SJacob Faibussowitsch 
1112f7e3c444SJacob Faibussowitsch   int ret = FOO(x);
1113f7e3c444SJacob Faibussowitsch 
1114f7e3c444SJacob Faibussowitsch   bar(FOO(x)); // ERROR, may not compile
1115f7e3c444SJacob Faibussowitsch   bar(ret);    // OK
1116f7e3c444SJacob Faibussowitsch 
1117f7e3c444SJacob Faibussowitsch   if (FOO(x))  // ERROR, may not compile
1118f7e3c444SJacob Faibussowitsch   if (ret)     // OK
1119f7e3c444SJacob Faibussowitsch .ve
1120f7e3c444SJacob Faibussowitsch 
1121f7e3c444SJacob Faibussowitsch   Example usage:
1122f7e3c444SJacob Faibussowitsch .vb
1123f7e3c444SJacob Faibussowitsch   #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10)
1124f7e3c444SJacob Faibussowitsch 
1125f7e3c444SJacob Faibussowitsch   int x = 10;
1126f7e3c444SJacob Faibussowitsch   int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20
1127f7e3c444SJacob Faibussowitsch 
1128f7e3c444SJacob Faibussowitsch   // multiline macros allowed, but must declare with line continuation as usual
1129f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \
1130f7e3c444SJacob Faibussowitsch     if (arg1 > 10) {                                            \
1131f7e3c444SJacob Faibussowitsch       puts("big int!");                                         \
1132f7e3c444SJacob Faibussowitsch     } else {                                                    \
1133f7e3c444SJacob Faibussowitsch       return 7355608;                                           \
1134f7e3c444SJacob Faibussowitsch     }                                                           \
1135f7e3c444SJacob Faibussowitsch   )
1136f7e3c444SJacob Faibussowitsch 
1137f7e3c444SJacob Faibussowitsch   // if retexpr contains commas, must enclose it with braces
1138f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...)
1139f7e3c444SJacob Faibussowitsch   #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...)
1140f7e3c444SJacob Faibussowitsch 
1141f7e3c444SJacob Faibussowitsch   int x = 10;
1142f7e3c444SJacob Faibussowitsch   int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0
1143f7e3c444SJacob Faibussowitsch   int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20
1144f7e3c444SJacob Faibussowitsch .ve
1145f7e3c444SJacob Faibussowitsch 
1146db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()`
1147f7e3c444SJacob Faibussowitsch M*/
1148f7e3c444SJacob Faibussowitsch #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__)
1149f7e3c444SJacob Faibussowitsch 
11503ba16761SJacob Faibussowitsch #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__)
1151f7e3c444SJacob Faibussowitsch 
1152dd39110bSPierre Jolivet /*MC
1153dd39110bSPierre Jolivet   PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array
1154dd39110bSPierre Jolivet 
115516a05f60SBarry Smith   Synopsis:
115616a05f60SBarry Smith   #include <petscmacros.h>
115716a05f60SBarry Smith   size_t PETSC_STATIC_ARRAY_LENGTH(a)
115816a05f60SBarry Smith 
115916a05f60SBarry Smith   Input Parameter:
116016a05f60SBarry Smith . a - a static array of any type
116116a05f60SBarry Smith 
116216a05f60SBarry Smith   Output Parameter:
116316a05f60SBarry Smith . <return-value> -  the length of the array
116416a05f60SBarry Smith 
116516a05f60SBarry Smith   Example:
116616a05f60SBarry Smith .vb
116716a05f60SBarry Smith   PetscInt a[22];
116816a05f60SBarry Smith   size_t sa = PETSC_STATIC_ARRAY_LENGTH(a)
116916a05f60SBarry Smith .ve
117016a05f60SBarry Smith   `sa` will have a value of 22
117116a05f60SBarry Smith 
1172dd39110bSPierre Jolivet   Level: intermediate
1173dd39110bSPierre Jolivet M*/
1174dd39110bSPierre Jolivet #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
1175dd39110bSPierre Jolivet 
1176296d8154SBarry Smith /*
1177296d8154SBarry Smith   These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro.
1178296d8154SBarry Smith 
1179296d8154SBarry Smith   Example usage:
1180296d8154SBarry Smith 
1181296d8154SBarry Smith   #define mymacro(obj,...) {
1182296d8154SBarry Smith     PETSC_FIRST_ARG((__VA_ARGS__,unused));
1183296d8154SBarry Smith     f(22 PETSC_REST_ARG(__VA_ARGS__));
1184296d8154SBarry Smith   }
1185296d8154SBarry Smith 
1186296d8154SBarry Smith   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
1187296d8154SBarry Smith 
1188296d8154SBarry Smith   Reference:
1189296d8154SBarry Smith   https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
1190296d8154SBarry Smith */
1191296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...)                                                                      N
1192296d8154SBarry Smith #define PETSC_FIRST_ARG(args)                                                                         PETSC_FIRST_ARG_ args
1193296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16
1194296d8154SBarry Smith #define PETSC_NUM(...)                                                                                PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
1195296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...)                                                       , __VA_ARGS__
1196296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first)
1197296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__)
1198296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...)  PETSC_REST_HELPER2(qty, __VA_ARGS__)
1199296d8154SBarry Smith #define PETSC_REST_ARG(...)          PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__)
1200296d8154SBarry Smith 
12011c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \
12021c7e414eSJacob Faibussowitsch   _Pragma(PetscStringize(name diagnostic push)) \
12031c7e414eSJacob Faibussowitsch   _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__))
12041c7e414eSJacob Faibussowitsch 
12051c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop))
12061c7e414eSJacob Faibussowitsch 
12071c7e414eSJacob Faibussowitsch #if defined(__clang__)
12081c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__)
12091c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang)
12101c7e414eSJacob Faibussowitsch #elif defined(__GNUC__) || defined(__GNUG__)
12119bab7813SJacob Faibussowitsch   // gcc >= 4.6.0
12129bab7813SJacob Faibussowitsch   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600
12131c7e414eSJacob Faibussowitsch     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__)
12141c7e414eSJacob Faibussowitsch     #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()      PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC)
12151c7e414eSJacob Faibussowitsch   #endif
12169bab7813SJacob Faibussowitsch #endif
12171c7e414eSJacob Faibussowitsch 
12181c7e414eSJacob Faibussowitsch #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN
12191c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...)
12201c7e414eSJacob Faibussowitsch   #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...)
12211c7e414eSJacob Faibussowitsch   // only undefine these if they are not used
12221c7e414eSJacob Faibussowitsch   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_
12231c7e414eSJacob Faibussowitsch   #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_
12241c7e414eSJacob Faibussowitsch #endif
12251c7e414eSJacob Faibussowitsch 
12262e327cfbSJacob Faibussowitsch /* OpenMP support */
12272e327cfbSJacob Faibussowitsch #if defined(_OPENMP)
12282e327cfbSJacob Faibussowitsch   #if defined(_MSC_VER)
12292e327cfbSJacob Faibussowitsch     #define PetscPragmaOMP(...) __pragma(__VA_ARGS__)
12302e327cfbSJacob Faibussowitsch   #else
12312e327cfbSJacob Faibussowitsch     #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__))
12322e327cfbSJacob Faibussowitsch   #endif
12332e327cfbSJacob Faibussowitsch #endif
12342e327cfbSJacob Faibussowitsch 
12352e327cfbSJacob Faibussowitsch #ifndef PetscPragmaOMP
12362e327cfbSJacob Faibussowitsch   #define PetscPragmaOMP(...)
12372e327cfbSJacob Faibussowitsch #endif
12382e327cfbSJacob Faibussowitsch 
12392e327cfbSJacob Faibussowitsch /* PetscPragmaSIMD - from CeedPragmaSIMD */
12402e327cfbSJacob Faibussowitsch #if defined(__NEC__)
12412e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("_NEC ivdep")
12422e327cfbSJacob Faibussowitsch #elif defined(__INTEL_COMPILER) && !defined(_WIN32)
12432e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("vector")
12442e327cfbSJacob Faibussowitsch #elif defined(__GNUC__)
12452e327cfbSJacob Faibussowitsch   #if __GNUC__ >= 5 && !defined(__PGI)
12462e327cfbSJacob Faibussowitsch     #define PetscPragmaSIMD _Pragma("GCC ivdep")
12472e327cfbSJacob Faibussowitsch   #endif
12482e327cfbSJacob Faibussowitsch #elif defined(_OPENMP) && _OPENMP >= 201307
12492e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD PetscPragmaOMP(simd)
12502e327cfbSJacob Faibussowitsch #elif defined(PETSC_HAVE_CRAY_VECTOR)
12512e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD _Pragma("_CRI ivdep")
12522e327cfbSJacob Faibussowitsch #endif
12532e327cfbSJacob Faibussowitsch 
12542e327cfbSJacob Faibussowitsch #ifndef PetscPragmaSIMD
12552e327cfbSJacob Faibussowitsch   #define PetscPragmaSIMD
12562e327cfbSJacob Faibussowitsch #endif
12572e327cfbSJacob Faibussowitsch 
12585029be03SJacob Faibussowitsch #include <petsc/private/petscadvancedmacros.h>
12595029be03SJacob Faibussowitsch 
12605029be03SJacob Faibussowitsch #define PetscConcat6_(a, b, c, d, e, f) a##b##c##d##e##f
12615029be03SJacob Faibussowitsch #define PetscConcat6(a, b, c, d, e, f)  PetscConcat6_(a, b, c, d, e, f)
12625029be03SJacob Faibussowitsch 
12635029be03SJacob Faibussowitsch #define PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, __SILENCE_MACRO__, major, minor, subminor, replacement, ...) \
12645029be03SJacob Faibussowitsch   PetscIfPetscDefined(__SILENCE_MACRO__, PetscExpandToNothing, \
12655029be03SJacob Faibussowitsch                       __PETSC_DEPRECATION_MACRO__)(PetscStringize(Use replacement (since version major.minor.subminor) instead. Silence this warning (and all others for this version) by defining PetscConcat_(PETSC_, __SILENCE_MACRO__). __VA_ARGS__))
12665029be03SJacob Faibussowitsch 
12675029be03SJacob Faibussowitsch #define PETSC_DEPRECATED_IDENTIFIER(__PETSC_DEPRECATION_MACRO__, major, minor, subminor, ...) \
12685029be03SJacob Faibussowitsch   PETSC_DEPRECATED_IDENTIFIER_(__PETSC_DEPRECATION_MACRO__, PetscConcat6(SILENCE_DEPRECATION_WARNINGS_, major, _, minor, _, subminor), major, minor, subminor, __VA_ARGS__)
12695029be03SJacob Faibussowitsch 
1270*edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_FUNCTION(major, minor, subminor, replacement, ...) PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_FUNCTION_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1271*edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_TYPEDEF(major, minor, subminor, replacement, ...)  PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_TYPEDEF_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1272*edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_ENUM(major, minor, subminor, replacement, ...)     PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_ENUM_BASE, major, minor, subminor, replacement, __VA_ARGS__)
1273*edd03b47SJacob Faibussowitsch #define PETSC_DEPRECATED_MACRO(major, minor, subminor, replacement, ...)    PETSC_DEPRECATED_IDENTIFIER(PETSC_DEPRECATED_MACRO_BASE, major, minor, subminor, replacement, __VA_ARGS__)
12745029be03SJacob Faibussowitsch 
1275bde483f2SJacob Faibussowitsch #endif /* PETSC_PREPROCESSOR_MACROS_H */
1276