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