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