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