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