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