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