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