1bde483f2SJacob Faibussowitsch #ifndef PETSC_PREPROCESSOR_MACROS_H 2bde483f2SJacob Faibussowitsch #define PETSC_PREPROCESSOR_MACROS_H 3bde483f2SJacob Faibussowitsch 4bde483f2SJacob Faibussowitsch #include <petscconf.h> 5bde483f2SJacob Faibussowitsch #include <petscconf_poison.h> /* for PetscDefined() error checking */ 6bde483f2SJacob Faibussowitsch 7ac09b921SBarry Smith /* SUBMANSEC = Sys */ 8ac09b921SBarry Smith 90e6b6b59SJacob Faibussowitsch #if defined(__cplusplus) 100e6b6b59SJacob Faibussowitsch #if __cplusplus <= 201103L 110e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 11 120e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201402L 130e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 14 140e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 201703L 150e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 17 160e6b6b59SJacob Faibussowitsch #elif __cplusplus <= 202002L 170e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 20 180e6b6b59SJacob Faibussowitsch #else 190e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 22 // current year, or date of c++2b ratification 200e6b6b59SJacob Faibussowitsch #endif 210e6b6b59SJacob Faibussowitsch #endif // __cplusplus 220e6b6b59SJacob Faibussowitsch 230e6b6b59SJacob Faibussowitsch #ifndef PETSC_CPP_VERSION 240e6b6b59SJacob Faibussowitsch #define PETSC_CPP_VERSION 0 250e6b6b59SJacob Faibussowitsch #endif 260e6b6b59SJacob Faibussowitsch 276797ed33SJacob Faibussowitsch #if defined(__STDC_VERSION__) 286797ed33SJacob Faibussowitsch #if __STDC_VERSION__ <= 199901L 296797ed33SJacob Faibussowitsch // C99 except that 99 is >= 11 or 17 so we shorten it to 9 instead 306797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 9 316797ed33SJacob Faibussowitsch #elif __STDC_VERSION__ <= 201112L 326797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 11 336797ed33SJacob Faibussowitsch #elif __STDC_VERSION__ <= 201710L 346797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 17 356797ed33SJacob Faibussowitsch #else 366797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 22 // current year, or date of c2b ratification 376797ed33SJacob Faibussowitsch #endif 386797ed33SJacob Faibussowitsch #endif // __STDC_VERSION__ 396797ed33SJacob Faibussowitsch 406797ed33SJacob Faibussowitsch #ifndef PETSC_C_VERSION 416797ed33SJacob Faibussowitsch #define PETSC_C_VERSION 0 426797ed33SJacob Faibussowitsch #endif 436797ed33SJacob Faibussowitsch 44bde483f2SJacob Faibussowitsch /* ========================================================================== */ 45bde483f2SJacob Faibussowitsch /* This facilitates using the C version of PETSc from C++ and the C++ version from C. */ 46bde483f2SJacob Faibussowitsch #if defined(__cplusplus) 47bde483f2SJacob Faibussowitsch #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_CXX 48bde483f2SJacob Faibussowitsch #else 49bde483f2SJacob Faibussowitsch #define PETSC_FUNCTION_NAME PETSC_FUNCTION_NAME_C 50bde483f2SJacob Faibussowitsch #endif 51bde483f2SJacob Faibussowitsch 52bde483f2SJacob Faibussowitsch /* ========================================================================== */ 53bde483f2SJacob Faibussowitsch /* Since PETSc manages its own extern "C" handling users should never include PETSc include 54bde483f2SJacob Faibussowitsch * files within extern "C". This will generate a compiler error if a user does put the include 55bde483f2SJacob Faibussowitsch * file within an extern "C". 56bde483f2SJacob Faibussowitsch */ 57bde483f2SJacob Faibussowitsch #if defined(__cplusplus) 589371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(int); 599371c9d4SSatish Balay void assert_never_put_petsc_headers_inside_an_extern_c(double); 60bde483f2SJacob Faibussowitsch #endif 61bde483f2SJacob Faibussowitsch 62bde483f2SJacob Faibussowitsch #if defined(__cplusplus) 63bde483f2SJacob Faibussowitsch #define PETSC_RESTRICT PETSC_CXX_RESTRICT 64bde483f2SJacob Faibussowitsch #else 656ee8c794SJacob Faibussowitsch #define PETSC_RESTRICT restrict 66bde483f2SJacob Faibussowitsch #endif 67bde483f2SJacob Faibussowitsch 686ee8c794SJacob Faibussowitsch #define PETSC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_INLINE is deprecated (since version 3.17)\"") inline 699fbee547SJacob Faibussowitsch #define PETSC_STATIC_INLINE PETSC_DEPRECATED_MACRO("GCC warning \"PETSC_STATIC_INLINE is deprecated (since version 3.17)\"") static inline 70bde483f2SJacob Faibussowitsch 71bde483f2SJacob Faibussowitsch #if defined(_WIN32) && defined(PETSC_USE_SHARED_LIBRARIES) /* For Win32 shared libraries */ 72bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT __declspec(dllexport) 73bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT __declspec(dllimport) 74bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL 75bde483f2SJacob Faibussowitsch #elif defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_CXX) 76bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT __attribute__((visibility("default"))) 77bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT __attribute__((visibility("default"))) 78bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden"))) 79bde483f2SJacob Faibussowitsch #elif !defined(__cplusplus) && defined(PETSC_USE_VISIBILITY_C) 80bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT __attribute__((visibility("default"))) 81bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT __attribute__((visibility("default"))) 82bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL __attribute__((visibility("hidden"))) 83bde483f2SJacob Faibussowitsch #else 84bde483f2SJacob Faibussowitsch #define PETSC_DLLEXPORT 85bde483f2SJacob Faibussowitsch #define PETSC_DLLIMPORT 86bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_INTERNAL 87bde483f2SJacob Faibussowitsch #endif 88bde483f2SJacob Faibussowitsch 89bde483f2SJacob Faibussowitsch #if defined(petsc_EXPORTS) /* CMake defines this when building the shared library */ 90bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_PUBLIC PETSC_DLLEXPORT 91bde483f2SJacob Faibussowitsch #else /* Win32 users need this to import symbols from petsc.dll */ 92bde483f2SJacob Faibussowitsch #define PETSC_VISIBILITY_PUBLIC PETSC_DLLIMPORT 93bde483f2SJacob Faibussowitsch #endif 94bde483f2SJacob Faibussowitsch 95bde483f2SJacob Faibussowitsch /* Functions tagged with PETSC_EXTERN in the header files are always defined as extern "C" when 96bde483f2SJacob Faibussowitsch * compiled with C++ so they may be used from C and are always visible in the shared libraries 97bde483f2SJacob Faibussowitsch */ 98bde483f2SJacob Faibussowitsch #if defined(__cplusplus) 99bde483f2SJacob Faibussowitsch #define PETSC_EXTERN extern "C" PETSC_VISIBILITY_PUBLIC 100bde483f2SJacob Faibussowitsch #define PETSC_EXTERN_TYPEDEF extern "C" 101bde483f2SJacob Faibussowitsch #define PETSC_INTERN extern "C" PETSC_VISIBILITY_INTERNAL 102bde483f2SJacob Faibussowitsch #else 103bde483f2SJacob Faibussowitsch #define PETSC_EXTERN extern PETSC_VISIBILITY_PUBLIC 104bde483f2SJacob Faibussowitsch #define PETSC_EXTERN_TYPEDEF 105bde483f2SJacob Faibussowitsch #define PETSC_INTERN extern PETSC_VISIBILITY_INTERNAL 106bde483f2SJacob Faibussowitsch #endif 107bde483f2SJacob Faibussowitsch 108bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_SINGLE_LIBRARY) 109bde483f2SJacob Faibussowitsch #define PETSC_SINGLE_LIBRARY_INTERN PETSC_INTERN 110bde483f2SJacob Faibussowitsch #else 111bde483f2SJacob Faibussowitsch #define PETSC_SINGLE_LIBRARY_INTERN PETSC_EXTERN 112bde483f2SJacob Faibussowitsch #endif 113bde483f2SJacob Faibussowitsch 1141cf396e4SJacob Faibussowitsch #if !defined(__has_feature) 1151cf396e4SJacob Faibussowitsch #define __has_feature(x) 0 1161cf396e4SJacob Faibussowitsch #endif 1171cf396e4SJacob Faibussowitsch 118bde483f2SJacob Faibussowitsch /*MC 119bde483f2SJacob Faibussowitsch PetscHasAttribute - Determine whether a particular __attribute__ is supported by the compiler 120bde483f2SJacob Faibussowitsch 121bde483f2SJacob Faibussowitsch Synopsis: 122bde483f2SJacob Faibussowitsch #include <petscmacros.h> 123c7481402SJacob Faibussowitsch int PetscHasAttribute(name) 124bde483f2SJacob Faibussowitsch 125bde483f2SJacob Faibussowitsch Input Parameter: 126bde483f2SJacob Faibussowitsch . name - The name of the attribute to test 127bde483f2SJacob Faibussowitsch 128bde483f2SJacob Faibussowitsch Notes: 129bde483f2SJacob Faibussowitsch name should be identical to what you might pass to the __attribute__ declaration itself -- 130bde483f2SJacob Faibussowitsch plain, unbroken text. 131bde483f2SJacob Faibussowitsch 132c7481402SJacob Faibussowitsch As `PetscHasAttribute()` is wrapper over the function-like macro `__has_attribute()`, the 133c7481402SJacob Faibussowitsch exact type and value returned is implementation defined. In practice however, it usually 134c7481402SJacob Faibussowitsch returns `1` if the attribute is supported and `0` if the attribute is not supported. 135bde483f2SJacob Faibussowitsch 136bde483f2SJacob Faibussowitsch Example Usage: 137bde483f2SJacob Faibussowitsch Typical usage is using the preprocessor 138bde483f2SJacob Faibussowitsch 139bde483f2SJacob Faibussowitsch .vb 140bde483f2SJacob Faibussowitsch #if PetscHasAttribute(always_inline) 141bde483f2SJacob Faibussowitsch # define MY_ALWAYS_INLINE __attribute__((always_inline)) 142bde483f2SJacob Faibussowitsch #else 143bde483f2SJacob Faibussowitsch # define MY_ALWAYS_INLINE 144bde483f2SJacob Faibussowitsch #endif 145bde483f2SJacob Faibussowitsch 146bde483f2SJacob Faibussowitsch void foo(void) MY_ALWAYS_INLINE; 147bde483f2SJacob Faibussowitsch .ve 148bde483f2SJacob Faibussowitsch 149bde483f2SJacob Faibussowitsch but it can also be used in regular code 150bde483f2SJacob Faibussowitsch 151bde483f2SJacob Faibussowitsch .vb 152bde483f2SJacob Faibussowitsch if (PetscHasAttribute(some_attribute)) { 153bde483f2SJacob Faibussowitsch foo(); 154bde483f2SJacob Faibussowitsch } else { 155bde483f2SJacob Faibussowitsch bar(); 156bde483f2SJacob Faibussowitsch } 157bde483f2SJacob Faibussowitsch .ve 158bde483f2SJacob Faibussowitsch 159bde483f2SJacob Faibussowitsch Level: intermediate 160bde483f2SJacob Faibussowitsch 161c7481402SJacob Faibussowitsch .seealso: `PetscHasBuiltin()`, `PetscDefined()`, `PetscLikely()`, `PetscUnlikely()`, 162c7481402SJacob Faibussowitsch `PETSC_ATTRIBUTE_FORMAT` 163bde483f2SJacob Faibussowitsch M*/ 164bde483f2SJacob Faibussowitsch #if !defined(__has_attribute) 165bde483f2SJacob Faibussowitsch #define __has_attribute(x) 0 166bde483f2SJacob Faibussowitsch #endif 167bde483f2SJacob Faibussowitsch #define PetscHasAttribute(name) __has_attribute(name) 168bde483f2SJacob Faibussowitsch 169c7481402SJacob Faibussowitsch /*MC 170c7481402SJacob Faibussowitsch PetscHasBuiltin - Determine whether a particular builtin method is supported by the compiler 171c7481402SJacob Faibussowitsch 172c7481402SJacob Faibussowitsch Synopsis: 173c7481402SJacob Faibussowitsch #include <petscmacros.h> 174c7481402SJacob Faibussowitsch int PetscHasBuiltin(name) 175c7481402SJacob Faibussowitsch 176c7481402SJacob Faibussowitsch Input Parameter: 177c7481402SJacob Faibussowitsch . name - the name of the builtin routine 178c7481402SJacob Faibussowitsch 179c7481402SJacob Faibussowitsch Notes: 180d5b43468SJose E. Roman Evaluates to `1` if the builtin is supported and `0` otherwise. Note the term "evaluates" 181c7481402SJacob Faibussowitsch (vs "expands") is deliberate; even though `PetscHasBuiltin()` is a macro the underlying 182c7481402SJacob Faibussowitsch detector is itself is a compiler extension with implementation-defined return type and 183c7481402SJacob Faibussowitsch semantics. Some compilers implement it as a macro, others as a compiler function. In practice 184c7481402SJacob Faibussowitsch however, all supporting compilers return an integer boolean as described. 185c7481402SJacob Faibussowitsch 186c7481402SJacob Faibussowitsch Example Usage: 187c7481402SJacob Faibussowitsch Typical usage is in preprocessor directives 188c7481402SJacob Faibussowitsch 189c7481402SJacob Faibussowitsch .vb 190c7481402SJacob Faibussowitsch #if PetscHasBuiltin(__builtin_trap) 191c7481402SJacob Faibussowitsch __builtin_trap(); 192c7481402SJacob Faibussowitsch #else 193c7481402SJacob Faibussowitsch abort(); 194c7481402SJacob Faibussowitsch #endif 195c7481402SJacob Faibussowitsch .ve 196c7481402SJacob Faibussowitsch 197c7481402SJacob Faibussowitsch But it may also be used in regular code 198c7481402SJacob Faibussowitsch 199c7481402SJacob Faibussowitsch .vb 200c7481402SJacob Faibussowitsch if (PetscHasBuiltin(__builtin_alloca)) { 201c7481402SJacob Faibussowitsch foo(); 202c7481402SJacob Faibussowitsch } else { 203c7481402SJacob Faibussowitsch bar(); 204c7481402SJacob Faibussowitsch } 205c7481402SJacob Faibussowitsch .ve 206c7481402SJacob Faibussowitsch 207c7481402SJacob Faibussowitsch Level: intermediate 208c7481402SJacob Faibussowitsch 209c7481402SJacob Faibussowitsch .seealso: `PetscHasAttribute()`, `PetscAssume()` 210c7481402SJacob Faibussowitsch M*/ 211c7481402SJacob Faibussowitsch #if !defined(__has_builtin) 212c7481402SJacob Faibussowitsch #define __has_builtin(x) 0 213c7481402SJacob Faibussowitsch #endif 214c7481402SJacob Faibussowitsch // clangs __has_builtin prior to clang 10 did not properly handle non-function builtins such as 215c7481402SJacob Faibussowitsch // __builtin_types_compatible_p which take types or other non-functiony things as 216c7481402SJacob Faibussowitsch // arguments. The correct way to detect these then is to use __is_identifier (also a clang 217c7481402SJacob Faibussowitsch // extension). GCC has always worked as expected. see https://stackoverflow.com/a/45043153 218c7481402SJacob Faibussowitsch #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 10) && defined(__is_identifier) 219c7481402SJacob Faibussowitsch #define PetscHasBuiltin(name) __is_identifier(name) 220c7481402SJacob Faibussowitsch #else 221c7481402SJacob Faibussowitsch #define PetscHasBuiltin(name) __has_builtin(name) 222c7481402SJacob Faibussowitsch #endif 223c7481402SJacob Faibussowitsch 22493d501b3SJacob Faibussowitsch #if !defined(PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG) 22593d501b3SJacob Faibussowitsch /* 22693d501b3SJacob Faibussowitsch Support for Clang (>=3.2) matching type tag arguments with void* buffer types. 22793d501b3SJacob Faibussowitsch This allows the compiler to detect cases where the MPI datatype argument passed to a MPI routine 22893d501b3SJacob Faibussowitsch does not match the actual type of the argument being passed in 22993d501b3SJacob Faibussowitsch */ 23093d501b3SJacob Faibussowitsch #if PetscHasAttribute(pointer_with_type_tag) 23193d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) __attribute__((pointer_with_type_tag(MPI, bufno, typeno))) 23293d501b3SJacob Faibussowitsch #endif 23393d501b3SJacob Faibussowitsch 23493d501b3SJacob Faibussowitsch #if PetscHasAttribute(type_tag_for_datatype) 23593d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type) __attribute__((type_tag_for_datatype(MPI, type))) 23693d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) __attribute__((type_tag_for_datatype(MPI, type, layout_compatible))) 23793d501b3SJacob Faibussowitsch #endif 23893d501b3SJacob Faibussowitsch #endif // PETSC_SKIP_ATTRIBUTE_MPI_TYPE_TAG 23993d501b3SJacob Faibussowitsch 24093d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE 24193d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_POINTER_WITH_TYPE(bufno, typeno) 24293d501b3SJacob Faibussowitsch #endif 24393d501b3SJacob Faibussowitsch 24493d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG 24593d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG(type) 24693d501b3SJacob Faibussowitsch #endif 24793d501b3SJacob Faibussowitsch 24893d501b3SJacob Faibussowitsch #ifndef PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE 24993d501b3SJacob Faibussowitsch #define PETSC_ATTRIBUTE_MPI_TYPE_TAG_LAYOUT_COMPATIBLE(type) 25093d501b3SJacob Faibussowitsch #endif 25193d501b3SJacob Faibussowitsch 252bde483f2SJacob Faibussowitsch /*MC 25363a3b9bcSJacob Faibussowitsch PETSC_ATTRIBUTE_FORMAT - Indicate to the compiler that specified arguments should be treated 25463a3b9bcSJacob Faibussowitsch as format specifiers and checked for validity 25563a3b9bcSJacob Faibussowitsch 25663a3b9bcSJacob Faibussowitsch Synopsis: 25763a3b9bcSJacob Faibussowitsch #include <petscmacros.h> 25863a3b9bcSJacob Faibussowitsch <attribute declaration> PETSC_ATTRIBUTE_FORMAT(int strIdx, int vaArgIdx) 25963a3b9bcSJacob Faibussowitsch 26063a3b9bcSJacob Faibussowitsch Input Parameters: 26163a3b9bcSJacob Faibussowitsch + strIdx - The (1-indexed) location of the format string in the argument list 26263a3b9bcSJacob Faibussowitsch - vaArgIdx - The (1-indexed) location of the first formattable argument in the argument list 26363a3b9bcSJacob Faibussowitsch 26463a3b9bcSJacob Faibussowitsch Notes: 26563a3b9bcSJacob Faibussowitsch This function attribute causes the compiler to issue warnings when the format specifier does 26663a3b9bcSJacob Faibussowitsch not match the type of the variable that will be formatted, or when there exists a mismatch 26763a3b9bcSJacob Faibussowitsch between the number of format specifiers and variables to be formatted. It is safe to use this 26863a3b9bcSJacob Faibussowitsch macro if your compiler does not support format specifier checking (though this is 26963a3b9bcSJacob Faibussowitsch exceeedingly rare). 27063a3b9bcSJacob Faibussowitsch 27163a3b9bcSJacob Faibussowitsch Both strIdx and vaArgIdx must be compile-time constant integer literals and cannot have the 27263a3b9bcSJacob Faibussowitsch same value. 27363a3b9bcSJacob Faibussowitsch 27463a3b9bcSJacob Faibussowitsch The arguments to be formatted (and therefore checked by the compiler) must be "contiguous" in 27563a3b9bcSJacob Faibussowitsch the argument list, that is, there is no way to indicate gaps which should not be checked. 27663a3b9bcSJacob Faibussowitsch 27787497f52SBarry Smith Definition is suppressed by defining `PETSC_SKIP_ATTRIBUTE_FORMAT` prior to including PETSc 27863a3b9bcSJacob Faibussowitsch header files. In this case the macro will expand empty. 27963a3b9bcSJacob Faibussowitsch 28063a3b9bcSJacob Faibussowitsch Example Usage: 28163a3b9bcSJacob Faibussowitsch .vb 28263a3b9bcSJacob Faibussowitsch // format string is 2nd argument, variable argument list containing args is 3rd argument 28363a3b9bcSJacob Faibussowitsch void my_printf(void *obj, const char *fmt_string, ...) PETSC_ATTRIBUTE_FORMAT(2,3) 28463a3b9bcSJacob Faibussowitsch 28563a3b9bcSJacob Faibussowitsch int x = 1; 28663a3b9bcSJacob Faibussowitsch double y = 50.0; 28763a3b9bcSJacob Faibussowitsch 28863a3b9bcSJacob Faibussowitsch my_printf(NULL,"%g",x); // WARNING, format specifier does not match for 'int'! 28963a3b9bcSJacob Faibussowitsch my_printf(NULL,"%d",x,y); // WARNING, more arguments than format specifiers! 29063a3b9bcSJacob Faibussowitsch my_printf(NULL,"%d %g",x,y); // OK 29163a3b9bcSJacob Faibussowitsch .ve 29263a3b9bcSJacob Faibussowitsch 29363a3b9bcSJacob Faibussowitsch Level: developer 29463a3b9bcSJacob Faibussowitsch 295db781477SPatrick Sanan .seealso: `PETSC_ATTRIBUTE_COLD`, `PetscHasAttribute()` 29663a3b9bcSJacob Faibussowitsch M*/ 29763a3b9bcSJacob Faibussowitsch #if PetscHasAttribute(format) && !defined(PETSC_SKIP_ATTRIBUTE_FORMAT) 29863a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) __attribute__((format(printf, strIdx, vaArgIdx))) 29963a3b9bcSJacob Faibussowitsch #else 30063a3b9bcSJacob Faibussowitsch #define PETSC_ATTRIBUTE_FORMAT(strIdx, vaArgIdx) 30163a3b9bcSJacob Faibussowitsch #endif 30263a3b9bcSJacob Faibussowitsch 30363a3b9bcSJacob Faibussowitsch /*MC 304d8e4614bSJacob Faibussowitsch PETSC_ATTRIBUTE_COLD - Indicate to the compiler that a function is very unlikely to be 305d8e4614bSJacob Faibussowitsch executed 306d8e4614bSJacob Faibussowitsch 307d8e4614bSJacob Faibussowitsch Notes: 308d8e4614bSJacob Faibussowitsch The marked function is often optimized for size rather than speed and may be grouped alongside 309d8e4614bSJacob Faibussowitsch other equally frigid routines improving code locality of lukewarm or hotter parts of program. 310d8e4614bSJacob Faibussowitsch 311d8e4614bSJacob Faibussowitsch The paths leading to cold functions are usually automatically marked as unlikely by the 312d8e4614bSJacob Faibussowitsch compiler. It may thus be useful to mark functions used to handle unlikely conditions -- such 313d8e4614bSJacob Faibussowitsch as error handlers -- as cold to improve optimization of the surrounding temperate functions. 314d8e4614bSJacob Faibussowitsch 315d8e4614bSJacob Faibussowitsch Example Usage: 316d8e4614bSJacob Faibussowitsch .vb 317d8e4614bSJacob Faibussowitsch void my_error_handler(...) PETSC_ATTRIBUTE_COLD; 318d8e4614bSJacob Faibussowitsch 319d8e4614bSJacob Faibussowitsch if (temperature < 0) { 320d8e4614bSJacob Faibussowitsch return my_error_handler(...); // chilly! 321d8e4614bSJacob Faibussowitsch } 322d8e4614bSJacob Faibussowitsch .ve 323d8e4614bSJacob Faibussowitsch 324d8e4614bSJacob Faibussowitsch Level: intermediate 325d8e4614bSJacob Faibussowitsch 326db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscUnlikelyDebug()`, `PetscLikely()`, `PetscLikelyDebug()`, 327db781477SPatrick Sanan `PetscUnreachable()`, `PETSC_ATTRIBUTE_FORMAT` 328d8e4614bSJacob Faibussowitsch M*/ 329d8e4614bSJacob Faibussowitsch #if PetscHasAttribute(__cold__) 330d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((__cold__)) 331d8e4614bSJacob Faibussowitsch #elif PetscHasAttribute(cold) /* some implementations (old gcc) use no underscores */ 332d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD __attribute__((cold)) 333d8e4614bSJacob Faibussowitsch #else 334d8e4614bSJacob Faibussowitsch #define PETSC_ATTRIBUTE_COLD 335d8e4614bSJacob Faibussowitsch #endif 336d8e4614bSJacob Faibussowitsch 337d8e4614bSJacob Faibussowitsch /*MC 338bde483f2SJacob Faibussowitsch PETSC_NULLPTR - Standard way of indicating a null value or pointer 339bde483f2SJacob Faibussowitsch 340*20f4b53cSBarry Smith No Fortran Support 341*20f4b53cSBarry Smith 342*20f4b53cSBarry Smith Level: beginner 343*20f4b53cSBarry Smith 344bde483f2SJacob Faibussowitsch Notes: 345*20f4b53cSBarry Smith Equivalent to `NULL` in C source, and nullptr in C++ source. Note that for the purposes of 34687497f52SBarry Smith interoperability between C and C++, setting a pointer to `PETSC_NULLPTR` in C++ is functonially 347*20f4b53cSBarry Smith equivalent to setting the same pointer to `NULL` in C. That is to say that the following 348bde483f2SJacob Faibussowitsch expressions are equivalent\: 349bde483f2SJacob Faibussowitsch 350bde483f2SJacob Faibussowitsch .vb 351bde483f2SJacob Faibussowitsch ptr == PETSC_NULLPTR 352bde483f2SJacob Faibussowitsch ptr == NULL 353bde483f2SJacob Faibussowitsch ptr == 0 354bde483f2SJacob Faibussowitsch !ptr 355bde483f2SJacob Faibussowitsch 356bde483f2SJacob Faibussowitsch ptr = PETSC_NULLPTR 357bde483f2SJacob Faibussowitsch ptr = NULL 358bde483f2SJacob Faibussowitsch ptr = 0 359bde483f2SJacob Faibussowitsch .ve 360bde483f2SJacob Faibussowitsch 361bde483f2SJacob Faibussowitsch and for completeness' sake\: 362bde483f2SJacob Faibussowitsch 363bde483f2SJacob Faibussowitsch .vb 364bde483f2SJacob Faibussowitsch PETSC_NULLPTR == NULL 365bde483f2SJacob Faibussowitsch .ve 366bde483f2SJacob Faibussowitsch 367bde483f2SJacob Faibussowitsch Example Usage: 368bde483f2SJacob Faibussowitsch .vb 369bde483f2SJacob Faibussowitsch // may be used in place of '\0' or other such teminators in the definition of char arrays 370bde483f2SJacob Faibussowitsch const char *const MyEnumTypes[] = { 371bde483f2SJacob Faibussowitsch "foo", 372bde483f2SJacob Faibussowitsch "bar", 373bde483f2SJacob Faibussowitsch PETSC_NULLPTR 374bde483f2SJacob Faibussowitsch }; 375bde483f2SJacob Faibussowitsch 376bde483f2SJacob Faibussowitsch // may be used to nullify objects 377bde483f2SJacob Faibussowitsch PetscObject obj = PETSC_NULLPTR; 378bde483f2SJacob Faibussowitsch 379bde483f2SJacob Faibussowitsch // may be used in any function expecting NULL 380bde483f2SJacob Faibussowitsch PetscInfo(PETSC_NULLPTR,"Lorem Ipsum Dolor"); 381bde483f2SJacob Faibussowitsch .ve 382bde483f2SJacob Faibussowitsch 383bde483f2SJacob Faibussowitsch Developer Notes: 38487497f52SBarry Smith `PETSC_NULLPTR` must be used in place of NULL in all C++ source files. Using NULL in source 385bde483f2SJacob Faibussowitsch files compiled with a C++ compiler may lead to unexpected side-effects in function overload 386bde483f2SJacob Faibussowitsch resolution and/or compiler warnings. 387bde483f2SJacob Faibussowitsch 388db781477SPatrick Sanan .seealso: `PETSC_CONSTEXPR_14`, `PETSC_NODISCARD` 389817da375SSatish Balay M*/ 390bde483f2SJacob Faibussowitsch 391bde483f2SJacob Faibussowitsch /*MC 392bde483f2SJacob Faibussowitsch PETSC_CONSTEXPR_14 - C++14 constexpr 393bde483f2SJacob Faibussowitsch 394*20f4b53cSBarry Smith No Fortran Support 395*20f4b53cSBarry Smith 396*20f4b53cSBarry Smith Level: beginner 397*20f4b53cSBarry Smith 398bde483f2SJacob Faibussowitsch Notes: 399bde483f2SJacob Faibussowitsch Equivalent to constexpr when using a C++ compiler that supports C++14. Expands to nothing 400d5b43468SJose E. Roman if the C++ compiler does not support C++14 or when not compiling with a C++ compiler. Note 401bde483f2SJacob Faibussowitsch that this cannot be used in cases where an empty expansion would result in invalid code. It 402bde483f2SJacob Faibussowitsch is safe to use this in C source files. 403bde483f2SJacob Faibussowitsch 404bde483f2SJacob Faibussowitsch Example Usage: 405bde483f2SJacob Faibussowitsch .vb 406bde483f2SJacob Faibussowitsch PETSC_CONSTEXPR_14 int factorial(int n) 407bde483f2SJacob Faibussowitsch { 408bde483f2SJacob Faibussowitsch int r = 1; 409bde483f2SJacob Faibussowitsch 410bde483f2SJacob Faibussowitsch do { 411bde483f2SJacob Faibussowitsch r *= n; 412bde483f2SJacob Faibussowitsch } while (--n); 413bde483f2SJacob Faibussowitsch return r; 414bde483f2SJacob Faibussowitsch } 415bde483f2SJacob Faibussowitsch .ve 416bde483f2SJacob Faibussowitsch 417db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_NODISCARD` 418817da375SSatish Balay M*/ 419bde483f2SJacob Faibussowitsch 420bde483f2SJacob Faibussowitsch /*MC 421bde483f2SJacob Faibussowitsch PETSC_NODISCARD - Mark the return value of a function as non-discardable 422bde483f2SJacob Faibussowitsch 423089fb57cSJacob Faibussowitsch Not available in Fortran 424089fb57cSJacob Faibussowitsch 425089fb57cSJacob Faibussowitsch Level: beginner 426089fb57cSJacob Faibussowitsch 427bde483f2SJacob Faibussowitsch Notes: 428bde483f2SJacob Faibussowitsch Hints to the compiler that the return value of a function must be captured. A diagnostic may 429089fb57cSJacob Faibussowitsch (but is not required to) be emitted if the value is discarded. It is safe to use this in both 430089fb57cSJacob Faibussowitsch C and C++ source files. 431bde483f2SJacob Faibussowitsch 432bde483f2SJacob Faibussowitsch Example Usage: 433bde483f2SJacob Faibussowitsch .vb 434bde483f2SJacob Faibussowitsch class Foo 435bde483f2SJacob Faibussowitsch { 436bde483f2SJacob Faibussowitsch int x; 437bde483f2SJacob Faibussowitsch 438bde483f2SJacob Faibussowitsch public: 439bde483f2SJacob Faibussowitsch PETSC_NODISCARD Foo(int y) : x(y) { } 440bde483f2SJacob Faibussowitsch }; 441bde483f2SJacob Faibussowitsch 442bde483f2SJacob Faibussowitsch PETSC_NODISCARD int factorial(int n) 443bde483f2SJacob Faibussowitsch { 444bde483f2SJacob Faibussowitsch return n <= 1 ? 1 : (n * factorial(n - 1)); 445bde483f2SJacob Faibussowitsch } 446bde483f2SJacob Faibussowitsch 447bde483f2SJacob Faibussowitsch auto x = factorial(10); // OK, capturing return value 448bde483f2SJacob Faibussowitsch factorial(10); // Warning: ignoring return value of function declared 'nodiscard' 449bde483f2SJacob Faibussowitsch 450bde483f2SJacob Faibussowitsch auto f = Foo(x); // OK, capturing constructed object 451bde483f2SJacob Faibussowitsch Foo(x); // Warning: Ignoring temporary created by a constructor declared 'nodiscard' 452bde483f2SJacob Faibussowitsch .ve 453bde483f2SJacob Faibussowitsch 454db781477SPatrick Sanan .seealso: `PETSC_NULLPTR`, `PETSC_CONSTEXPR_14` 455817da375SSatish Balay M*/ 456bde483f2SJacob Faibussowitsch 457bde483f2SJacob Faibussowitsch /* C++11 features */ 458089fb57cSJacob Faibussowitsch #if defined(__cplusplus) || (PETSC_C_VERSION >= 23) 459bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR nullptr 460bde483f2SJacob Faibussowitsch #else 461bde483f2SJacob Faibussowitsch #define PETSC_NULLPTR NULL 462bde483f2SJacob Faibussowitsch #endif 463bde483f2SJacob Faibussowitsch 464bde483f2SJacob Faibussowitsch /* C++14 features */ 4650e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 14 4666ee8c794SJacob Faibussowitsch #define PETSC_CONSTEXPR_14 constexpr 467bde483f2SJacob Faibussowitsch #else 468bde483f2SJacob Faibussowitsch #define PETSC_CONSTEXPR_14 469bde483f2SJacob Faibussowitsch #endif 470bde483f2SJacob Faibussowitsch 471bde483f2SJacob Faibussowitsch /* C++17 features */ 4720e6b6b59SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 17 4730e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17 constexpr 474bde483f2SJacob Faibussowitsch #else 4750e6b6b59SJacob Faibussowitsch #define PETSC_CONSTEXPR_17 4760e6b6b59SJacob Faibussowitsch #endif 4770e6b6b59SJacob Faibussowitsch 478089fb57cSJacob Faibussowitsch #if (PETSC_CPP_VERSION >= 17) || (PETSC_C_VERSION >= 23) 479089fb57cSJacob Faibussowitsch #define PETSC_NODISCARD [[nodiscard]] 480089fb57cSJacob Faibussowitsch #elif PetscHasAttribute(warn_unused_result) 481089fb57cSJacob Faibussowitsch #define PETSC_NODISCARD __attribute__((warn_unused_result)) 482089fb57cSJacob Faibussowitsch #else 4830e6b6b59SJacob Faibussowitsch #define PETSC_NODISCARD 484bde483f2SJacob Faibussowitsch #endif 485bde483f2SJacob Faibussowitsch 486bde483f2SJacob Faibussowitsch #include <petscversion.h> 487bde483f2SJacob Faibussowitsch #define PETSC_AUTHOR_INFO " The PETSc Team\n petsc-maint@mcs.anl.gov\n https://petsc.org/\n" 488bde483f2SJacob Faibussowitsch 489267267bdSJacob Faibussowitsch /* designated initializers since C99 and C++20, MSVC never supports them though */ 4900e6b6b59SJacob Faibussowitsch #if defined(_MSC_VER) || (defined(__cplusplus) && (PETSC_CPP_VERSION < 20)) 491267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) __VA_ARGS__ 492267267bdSJacob Faibussowitsch #else 493267267bdSJacob Faibussowitsch #define PetscDesignatedInitializer(name, ...) .name = __VA_ARGS__ 494267267bdSJacob Faibussowitsch #endif 495267267bdSJacob Faibussowitsch 496bde483f2SJacob Faibussowitsch /*MC 49787497f52SBarry Smith PetscUnlikely - Hints the compiler that the given condition is usually false 498bde483f2SJacob Faibussowitsch 499bde483f2SJacob Faibussowitsch Synopsis: 500bde483f2SJacob Faibussowitsch #include <petscmacros.h> 501bde483f2SJacob Faibussowitsch bool PetscUnlikely(bool cond) 502bde483f2SJacob Faibussowitsch 503bde483f2SJacob Faibussowitsch Not Collective 504bde483f2SJacob Faibussowitsch 505bde483f2SJacob Faibussowitsch Input Parameter: 506bde483f2SJacob Faibussowitsch . cond - Boolean expression 507bde483f2SJacob Faibussowitsch 508bde483f2SJacob Faibussowitsch Notes: 509bde483f2SJacob Faibussowitsch Not available from fortran. 510bde483f2SJacob Faibussowitsch 511bde483f2SJacob Faibussowitsch This returns the same truth value, it is only a hint to compilers that the result of cond is 512bde483f2SJacob Faibussowitsch unlikely to be true. 513bde483f2SJacob Faibussowitsch 514bde483f2SJacob Faibussowitsch Example usage: 515bde483f2SJacob Faibussowitsch .vb 516bde483f2SJacob Faibussowitsch if (PetscUnlikely(cond)) { 517bde483f2SJacob Faibussowitsch foo(); // cold path 518bde483f2SJacob Faibussowitsch } else { 519bde483f2SJacob Faibussowitsch bar(); // hot path 520bde483f2SJacob Faibussowitsch } 521bde483f2SJacob Faibussowitsch .ve 522bde483f2SJacob Faibussowitsch 523bde483f2SJacob Faibussowitsch Level: advanced 524bde483f2SJacob Faibussowitsch 525db781477SPatrick Sanan .seealso: `PetscLikely()`, `PetscUnlikelyDebug()`, `PetscCall()`, `PetscDefined()`, `PetscHasAttribute()`, 526db781477SPatrick Sanan `PETSC_ATTRIBUTE_COLD` 527bde483f2SJacob Faibussowitsch M*/ 528bde483f2SJacob Faibussowitsch 529bde483f2SJacob Faibussowitsch /*MC 53087497f52SBarry Smith PetscLikely - Hints the compiler that the given condition is usually true 531bde483f2SJacob Faibussowitsch 532bde483f2SJacob Faibussowitsch Synopsis: 533bde483f2SJacob Faibussowitsch #include <petscmacros.h> 534bde483f2SJacob Faibussowitsch bool PetscLikely(bool cond) 535bde483f2SJacob Faibussowitsch 536bde483f2SJacob Faibussowitsch Not Collective 537bde483f2SJacob Faibussowitsch 538bde483f2SJacob Faibussowitsch Input Parameter: 539bde483f2SJacob Faibussowitsch . cond - Boolean expression 540bde483f2SJacob Faibussowitsch 541bde483f2SJacob Faibussowitsch Notes: 542bde483f2SJacob Faibussowitsch Not available from fortran. 543bde483f2SJacob Faibussowitsch 544bde483f2SJacob Faibussowitsch This returns the same truth value, it is only a hint to compilers that the result of cond is 545bde483f2SJacob Faibussowitsch likely to be true. 546bde483f2SJacob Faibussowitsch 547bde483f2SJacob Faibussowitsch Example usage: 548bde483f2SJacob Faibussowitsch .vb 549bde483f2SJacob Faibussowitsch if (PetscLikely(cond)) { 550bde483f2SJacob Faibussowitsch foo(); // hot path 551bde483f2SJacob Faibussowitsch } else { 552bde483f2SJacob Faibussowitsch bar(); // cold path 553bde483f2SJacob Faibussowitsch } 554bde483f2SJacob Faibussowitsch .ve 555bde483f2SJacob Faibussowitsch 556bde483f2SJacob Faibussowitsch Level: advanced 557bde483f2SJacob Faibussowitsch 558db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscDefined()`, `PetscHasAttribute()` 559db781477SPatrick Sanan `PETSC_ATTRIBUTE_COLD` 560bde483f2SJacob Faibussowitsch M*/ 561bde483f2SJacob Faibussowitsch #if defined(PETSC_HAVE_BUILTIN_EXPECT) 562bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) __builtin_expect(!!(cond), 0) 563bde483f2SJacob Faibussowitsch #define PetscLikely(cond) __builtin_expect(!!(cond), 1) 564bde483f2SJacob Faibussowitsch #else 565bde483f2SJacob Faibussowitsch #define PetscUnlikely(cond) (cond) 566bde483f2SJacob Faibussowitsch #define PetscLikely(cond) (cond) 567bde483f2SJacob Faibussowitsch #endif 568bde483f2SJacob Faibussowitsch 569bde483f2SJacob Faibussowitsch /*MC 570817da375SSatish Balay PetscUnreachable - Indicate to the compiler that a code-path is logically unreachable 571bde483f2SJacob Faibussowitsch 572bde483f2SJacob Faibussowitsch Synopsis: 573bde483f2SJacob Faibussowitsch #include <petscmacros.h> 574bde483f2SJacob Faibussowitsch void PetscUnreachable(void) 575bde483f2SJacob Faibussowitsch 576bde483f2SJacob Faibussowitsch Notes: 577bde483f2SJacob Faibussowitsch Indicates to the compiler (usually via some built-in) that a particular code path is always 578bde483f2SJacob Faibussowitsch unreachable. Behavior is undefined if this function is ever executed, the user can expect an 579bde483f2SJacob Faibussowitsch unceremonious crash. 580bde483f2SJacob Faibussowitsch 581bde483f2SJacob Faibussowitsch Example usage: 582bde483f2SJacob Faibussowitsch Useful in situations such as switches over enums where not all enumeration values are 583bde483f2SJacob Faibussowitsch explicitly covered by the switch 584bde483f2SJacob Faibussowitsch 585bde483f2SJacob Faibussowitsch .vb 586bde483f2SJacob Faibussowitsch typedef enum {RED, GREEN, BLUE} Color; 587bde483f2SJacob Faibussowitsch 588bde483f2SJacob Faibussowitsch int foo(Color c) 589bde483f2SJacob Faibussowitsch { 590bde483f2SJacob Faibussowitsch // it is known to programmer (or checked previously) that c is either RED or GREEN 591bde483f2SJacob Faibussowitsch // but compiler may not be able to deduce this and/or emit spurious warnings 592bde483f2SJacob Faibussowitsch switch (c) { 593bde483f2SJacob Faibussowitsch case RED: 594bde483f2SJacob Faibussowitsch return bar(); 595bde483f2SJacob Faibussowitsch case GREEN: 596bde483f2SJacob Faibussowitsch return baz(); 597bde483f2SJacob Faibussowitsch default: 598bde483f2SJacob Faibussowitsch PetscUnreachable(); // program is ill-formed if executed 599bde483f2SJacob Faibussowitsch } 600bde483f2SJacob Faibussowitsch } 601bde483f2SJacob Faibussowitsch .ve 602bde483f2SJacob Faibussowitsch 603bde483f2SJacob Faibussowitsch Level: advanced 604bde483f2SJacob Faibussowitsch 605c7481402SJacob Faibussowitsch .seealso: `SETERRABORT()`, `PETSCABORT()`, `PETSC_ATTRIBUTE_COLD`, `PetscAssume()` 606817da375SSatish Balay M*/ 607563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23 608563b2f50SJacob Faibussowitsch #include <utility> 609563b2f50SJacob Faibussowitsch #define PetscUnreachable() std::unreachable() 610563b2f50SJacob Faibussowitsch #elif defined(__GNUC__) 611e58a63e1SJacob Faibussowitsch /* GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) */ 612e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __builtin_unreachable() 613e58a63e1SJacob Faibussowitsch #elif defined(_MSC_VER) /* MSVC */ 614e58a63e1SJacob Faibussowitsch #define PetscUnreachable() __assume(0) 615e58a63e1SJacob Faibussowitsch #else /* ??? */ 616e58a63e1SJacob Faibussowitsch #define PetscUnreachable() SETERRABORT(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Code path explicitly marked as unreachable executed") 617e58a63e1SJacob Faibussowitsch #endif 618bde483f2SJacob Faibussowitsch 619bde483f2SJacob Faibussowitsch /*MC 620c7481402SJacob Faibussowitsch PetscAssume - Indicate to the compiler a condition that is defined to be true 621c7481402SJacob Faibussowitsch 622c7481402SJacob Faibussowitsch Synopsis: 623c7481402SJacob Faibussowitsch #include <petscmacros.h> 624c7481402SJacob Faibussowitsch void PetscAssume(bool cond) 625c7481402SJacob Faibussowitsch 626c7481402SJacob Faibussowitsch Input Parameter: 627c7481402SJacob Faibussowitsch . cond - Boolean expression 628c7481402SJacob Faibussowitsch 629c7481402SJacob Faibussowitsch Notes: 630c7481402SJacob Faibussowitsch If supported by the compiler, `cond` is used to inform the optimizer of an invariant 631c7481402SJacob Faibussowitsch truth. The argument itself is never evaluated, so any side effects of the expression will be 632c7481402SJacob Faibussowitsch discarded. This macro is used in `PetscAssert()` to retain information gained from debug 633c7481402SJacob Faibussowitsch checks that would be lost in optimized builds. For example\: 634c7481402SJacob Faibussowitsch 635c7481402SJacob Faibussowitsch .vb 636c7481402SJacob Faibussowitsch PetscErrorCode foo(PetscInt x) { 637c7481402SJacob Faibussowitsch 638c7481402SJacob Faibussowitsch PetscAssert(x >= 0, ...); 639c7481402SJacob Faibussowitsch } 640c7481402SJacob Faibussowitsch .ve 641c7481402SJacob Faibussowitsch 642c7481402SJacob Faibussowitsch The assertion checks that `x` is positive when debugging is enabled (and returns from `foo()` 643c7481402SJacob Faibussowitsch if it is not). This implicitly informs the optimizer that `x` cannot be negative. However, 644c7481402SJacob Faibussowitsch when debugging is disabled any `PetscAssert()` checks are tautologically false, and hence the 645c7481402SJacob Faibussowitsch optimizer cannot deduce any information from them. 646c7481402SJacob Faibussowitsch 647c7481402SJacob Faibussowitsch Due to compiler limitations `PetscAssume()` works best when `cond` involves 648d5b43468SJose E. Roman constants. Certain compilers do not yet propagate symbolic inequalities i.e.\: 649c7481402SJacob Faibussowitsch 650c7481402SJacob Faibussowitsch .vb 651c7481402SJacob Faibussowitsch int a, b, var_five; 652c7481402SJacob Faibussowitsch 653c7481402SJacob Faibussowitsch // BEST, all supporting compilers will understand a cannot be >= 5 654c7481402SJacob Faibussowitsch PetscAssume(a < 5); 655c7481402SJacob Faibussowitsch 656c7481402SJacob Faibussowitsch // OK, some compilers may understand that a cannot be >= 5 657c7481402SJacob Faibussowitsch PetscAssume(a <= b && b < 5); 658c7481402SJacob Faibussowitsch 659c7481402SJacob Faibussowitsch // WORST, most compilers will not get the memo 660c7481402SJacob Faibussowitsch PetscAssume(a <= b && b < var_five); 661c7481402SJacob Faibussowitsch .ve 662c7481402SJacob Faibussowitsch 663c7481402SJacob Faibussowitsch If the condition is violated at runtime then behavior is wholly undefined. If the 664c7481402SJacob Faibussowitsch condition is violated at compile-time, the condition "supersedes" the compile-time violation 665c7481402SJacob Faibussowitsch and the program is ill-formed, no diagnostic required. For example consider the following\: 666c7481402SJacob Faibussowitsch 667c7481402SJacob Faibussowitsch .vb 668c7481402SJacob Faibussowitsch PetscInt x = 0; 669c7481402SJacob Faibussowitsch 670c7481402SJacob Faibussowitsch PetscAssume(x != 0); 671c7481402SJacob Faibussowitsch if (x == 0) { 672c7481402SJacob Faibussowitsch x += 10; 673c7481402SJacob Faibussowitsch } else { 674c7481402SJacob Faibussowitsch popen("rm -rf /", "w"); 675c7481402SJacob Faibussowitsch } 676c7481402SJacob Faibussowitsch .ve 677c7481402SJacob Faibussowitsch 678c7481402SJacob Faibussowitsch Even though `x` is demonstrably `0` the compiler may opt to\: 679c7481402SJacob Faibussowitsch 680c7481402SJacob Faibussowitsch - emit an unconditional `popen("rm -rf /", "w")` 681c7481402SJacob Faibussowitsch - ignore `PetscAssume()` altogether and emit the correct path of `x += 10` 682c7481402SJacob Faibussowitsch - reformat the primary disk partition 683c7481402SJacob Faibussowitsch 684c7481402SJacob Faibussowitsch Level: advanced 685c7481402SJacob Faibussowitsch 686c7481402SJacob Faibussowitsch .seealso: `PetscAssert()` 687c7481402SJacob Faibussowitsch M*/ 688563b2f50SJacob Faibussowitsch #if PETSC_CPP_VERSION >= 23 689563b2f50SJacob Faibussowitsch #define PetscAssume(...) [[assume(__VA_ARGS__)]] 690563b2f50SJacob Faibussowitsch #elif defined(_MSC_VER) // msvc 691c7481402SJacob Faibussowitsch #define PetscAssume(...) __assume(__VA_ARGS__) 692c7481402SJacob Faibussowitsch #elif defined(__clang__) && PetscHasBuiltin(__builtin_assume) // clang 693c7481402SJacob Faibussowitsch #define PetscAssume(...) \ 694c7481402SJacob Faibussowitsch do { \ 695c7481402SJacob Faibussowitsch _Pragma("clang diagnostic push"); \ 696c7481402SJacob Faibussowitsch _Pragma("clang diagnostic ignored \"-Wassume\""); \ 697c7481402SJacob Faibussowitsch __builtin_assume(__VA_ARGS__); \ 698c7481402SJacob Faibussowitsch _Pragma("clang diagnostic pop"); \ 699c7481402SJacob Faibussowitsch } while (0) 700c7481402SJacob Faibussowitsch #else // gcc (and really old clang) 701c7481402SJacob Faibussowitsch // gcc does not have its own __builtin_assume() intrinsic. One could fake it via 702c7481402SJacob Faibussowitsch // 703c7481402SJacob Faibussowitsch // if (PetscUnlikely(!cond)) PetscUnreachable(); 704c7481402SJacob Faibussowitsch // 705c7481402SJacob Faibussowitsch // but this it unsavory because the side effects of cond are not guaranteed to be 706c7481402SJacob Faibussowitsch // discarded. Though in most circumstances gcc will optimize out the if (because any evaluation 707c7481402SJacob Faibussowitsch // for which cond is false would be undefined results in undefined behavior anyway) it cannot 708c7481402SJacob Faibussowitsch // always do so. This is especially the case for opaque or non-inline function calls: 709c7481402SJacob Faibussowitsch // 710c7481402SJacob Faibussowitsch // extern int bar(int); 711c7481402SJacob Faibussowitsch // 712c7481402SJacob Faibussowitsch // int foo(int x) { 713c7481402SJacob Faibussowitsch // PetscAssume(bar(x) == 2); 714c7481402SJacob Faibussowitsch // if (bar(x) == 2) { 715c7481402SJacob Faibussowitsch // return 1; 716c7481402SJacob Faibussowitsch // } else { 717c7481402SJacob Faibussowitsch // return 0; 718c7481402SJacob Faibussowitsch // } 719c7481402SJacob Faibussowitsch // } 720c7481402SJacob Faibussowitsch // 721c7481402SJacob Faibussowitsch // Here gcc would (if just using builtin_expect()) emit 2 calls to bar(). Note we still have 7222f181314SPierre Jolivet // cond "tested" in the condition, but this is done to silence unused-but-set variable warnings 723c7481402SJacob Faibussowitsch #define PetscAssume(...) \ 724c7481402SJacob Faibussowitsch do { \ 725c7481402SJacob Faibussowitsch if (0 && (__VA_ARGS__)) PetscUnreachable(); \ 726c7481402SJacob Faibussowitsch } while (0) 727c7481402SJacob Faibussowitsch #endif 728c7481402SJacob Faibussowitsch 729c7481402SJacob Faibussowitsch /*MC 730bde483f2SJacob Faibussowitsch PetscExpand - Expand macro argument 731bde483f2SJacob Faibussowitsch 732bde483f2SJacob Faibussowitsch Synopsis: 733bde483f2SJacob Faibussowitsch #include <petscmacros.h> 734bde483f2SJacob Faibussowitsch <macro-expansion> PetscExpand(x) 735bde483f2SJacob Faibussowitsch 7366aad120cSJose E. Roman Input Parameter: 737bde483f2SJacob Faibussowitsch . x - The preprocessor token to expand 738bde483f2SJacob Faibussowitsch 73949762cbcSSatish Balay Level: beginner 74049762cbcSSatish Balay 741db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscConcat()` 742817da375SSatish Balay M*/ 743e58a63e1SJacob Faibussowitsch #define PetscExpand_(...) __VA_ARGS__ 744e58a63e1SJacob Faibussowitsch #define PetscExpand(...) PetscExpand_(__VA_ARGS__) 745bde483f2SJacob Faibussowitsch 746bde483f2SJacob Faibussowitsch /*MC 747bde483f2SJacob Faibussowitsch PetscStringize - Stringize a token 748bde483f2SJacob Faibussowitsch 749bde483f2SJacob Faibussowitsch Synopsis: 750bde483f2SJacob Faibussowitsch #include <petscmacros.h> 751bde483f2SJacob Faibussowitsch const char* PetscStringize(x) 752bde483f2SJacob Faibussowitsch 753bde483f2SJacob Faibussowitsch Input Parameter: 754bde483f2SJacob Faibussowitsch . x - The token you would like to stringize 755bde483f2SJacob Faibussowitsch 756bde483f2SJacob Faibussowitsch Output Parameter: 757bde483f2SJacob Faibussowitsch . <return-value> - The string representation of x 758bde483f2SJacob Faibussowitsch 759bde483f2SJacob Faibussowitsch Notes: 760bde483f2SJacob Faibussowitsch Not available from Fortran. 761bde483f2SJacob Faibussowitsch 762bde483f2SJacob Faibussowitsch PetscStringize() expands x before stringizing it, if you do not wish to do so, use 763bde483f2SJacob Faibussowitsch PetscStringize_() instead. 764bde483f2SJacob Faibussowitsch 765bde483f2SJacob Faibussowitsch Example Usage: 766bde483f2SJacob Faibussowitsch .vb 767bde483f2SJacob Faibussowitsch #define MY_OTHER_VAR hello there 768bde483f2SJacob Faibussowitsch #define MY_VAR MY_OTHER_VAR 769bde483f2SJacob Faibussowitsch 770bde483f2SJacob Faibussowitsch PetscStringize(MY_VAR) -> "hello there" 771bde483f2SJacob Faibussowitsch PetscStringize_(MY_VAR) -> "MY_VAR" 772bde483f2SJacob Faibussowitsch 773bde483f2SJacob Faibussowitsch int foo; 774bde483f2SJacob Faibussowitsch PetscStringize(foo) -> "foo" 775bde483f2SJacob Faibussowitsch PetscStringize_(foo) -> "foo" 776bde483f2SJacob Faibussowitsch .ve 777bde483f2SJacob Faibussowitsch 778bde483f2SJacob Faibussowitsch Level: beginner 779bde483f2SJacob Faibussowitsch 780db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscExpandToNothing()`, `PetscExpand()` 781817da375SSatish Balay M*/ 7820e6b6b59SJacob Faibussowitsch #define PetscStringize_(...) #__VA_ARGS__ 7830e6b6b59SJacob Faibussowitsch #define PetscStringize(...) PetscStringize_(__VA_ARGS__) 784bde483f2SJacob Faibussowitsch 785bde483f2SJacob Faibussowitsch /*MC 786bde483f2SJacob Faibussowitsch PetscConcat - Concatenate two tokens 787bde483f2SJacob Faibussowitsch 788bde483f2SJacob Faibussowitsch Synopsis: 789bde483f2SJacob Faibussowitsch #include <petscmacros.h> 790bde483f2SJacob Faibussowitsch <macro-expansion> PetscConcat(x, y) 791bde483f2SJacob Faibussowitsch 792bde483f2SJacob Faibussowitsch Input Parameters: 793bde483f2SJacob Faibussowitsch + x - First token 794bde483f2SJacob Faibussowitsch - y - Second token 795bde483f2SJacob Faibussowitsch 796bde483f2SJacob Faibussowitsch Notes: 797bde483f2SJacob Faibussowitsch Not available from Fortran. 798bde483f2SJacob Faibussowitsch 799bde483f2SJacob Faibussowitsch PetscConcat() will expand both arguments before pasting them together, use PetscConcat_() 800bde483f2SJacob Faibussowitsch if you don't want to expand them. 801bde483f2SJacob Faibussowitsch 802bde483f2SJacob Faibussowitsch Example usage: 803bde483f2SJacob Faibussowitsch .vb 804bde483f2SJacob Faibussowitsch PetscConcat(hello,there) -> hellothere 805bde483f2SJacob Faibussowitsch 806bde483f2SJacob Faibussowitsch #define HELLO hello 807bde483f2SJacob Faibussowitsch PetscConcat(HELLO,there) -> hellothere 808bde483f2SJacob Faibussowitsch PetscConcat_(HELLO,there) -> HELLOthere 809bde483f2SJacob Faibussowitsch .ve 810bde483f2SJacob Faibussowitsch 811bde483f2SJacob Faibussowitsch Level: beginner 812bde483f2SJacob Faibussowitsch 813db781477SPatrick Sanan .seealso: `PetscStringize()`, `PetscExpand()` 814817da375SSatish Balay M*/ 815bde483f2SJacob Faibussowitsch #define PetscConcat_(x, y) x##y 816bde483f2SJacob Faibussowitsch #define PetscConcat(x, y) PetscConcat_(x, y) 817bde483f2SJacob Faibussowitsch 818bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_0 1 819bde483f2SJacob Faibussowitsch #define PETSC_INTERNAL_COMPL_1 0 820bde483f2SJacob Faibussowitsch 821bde483f2SJacob Faibussowitsch /*MC 822bde483f2SJacob Faibussowitsch PetscCompl - Expands to the integer complement of its argument 823bde483f2SJacob Faibussowitsch 824bde483f2SJacob Faibussowitsch Synopsis: 825bde483f2SJacob Faibussowitsch #include <petscmacros.h> 826bde483f2SJacob Faibussowitsch int PetscCompl(b) 827bde483f2SJacob Faibussowitsch 828bde483f2SJacob Faibussowitsch Input Parameter: 829bde483f2SJacob Faibussowitsch . b - Preprocessor variable, must expand to either integer literal 0 or 1 830bde483f2SJacob Faibussowitsch 8316aad120cSJose E. Roman Output Parameter: 832bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1 833bde483f2SJacob Faibussowitsch 834bde483f2SJacob Faibussowitsch Notes: 835bde483f2SJacob Faibussowitsch Not available from Fortran. 836bde483f2SJacob Faibussowitsch 837bde483f2SJacob Faibussowitsch Expands to integer literal 0 if b expands to 1, or integer literal 1 if b expands to 838bde483f2SJacob Faibussowitsch 0. Behaviour is undefined if b expands to anything else. PetscCompl() will expand its 839bde483f2SJacob Faibussowitsch argument before returning the complement. 840bde483f2SJacob Faibussowitsch 841bde483f2SJacob Faibussowitsch This macro can be useful for negating PetscDefined() inside macros e.g. 842bde483f2SJacob Faibussowitsch 843bde483f2SJacob Faibussowitsch $ #define PETSC_DONT_HAVE_FOO PetscCompl(PetscDefined(HAVE_FOO)) 844bde483f2SJacob Faibussowitsch 845bde483f2SJacob Faibussowitsch Example usage: 846bde483f2SJacob Faibussowitsch .vb 847bde483f2SJacob Faibussowitsch #define MY_VAR 1 848bde483f2SJacob Faibussowitsch PetscCompl(MY_VAR) -> 0 849bde483f2SJacob Faibussowitsch 850bde483f2SJacob Faibussowitsch #undef MY_VAR 851bde483f2SJacob Faibussowitsch #define MY_VAR 0 852bde483f2SJacob Faibussowitsch PetscCompl(MY_VAR) -> 1 853bde483f2SJacob Faibussowitsch .ve 854bde483f2SJacob Faibussowitsch 855bde483f2SJacob Faibussowitsch Level: beginner 856bde483f2SJacob Faibussowitsch 857db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()` 858817da375SSatish Balay M*/ 859bde483f2SJacob Faibussowitsch #define PetscCompl(b) PetscConcat_(PETSC_INTERNAL_COMPL_, PetscExpand(b)) 860bde483f2SJacob Faibussowitsch 861bde483f2SJacob Faibussowitsch /*MC 862bde483f2SJacob Faibussowitsch PetscDefined - Determine whether a boolean macro is defined 863bde483f2SJacob Faibussowitsch 864f5713a85SJacob Faibussowitsch No Fortran Support 865f5713a85SJacob Faibussowitsch 866bde483f2SJacob Faibussowitsch Synopsis: 867bde483f2SJacob Faibussowitsch #include <petscmacros.h> 868bde483f2SJacob Faibussowitsch int PetscDefined(def) 869bde483f2SJacob Faibussowitsch 870bde483f2SJacob Faibussowitsch Input Parameter: 871bde483f2SJacob Faibussowitsch . def - PETSc-style preprocessor variable (without PETSC_ prepended!) 872bde483f2SJacob Faibussowitsch 873d5b43468SJose E. Roman Output Parameter: 874bde483f2SJacob Faibussowitsch . <return-value> - Either integer literal 0 or 1 875bde483f2SJacob Faibussowitsch 876bde483f2SJacob Faibussowitsch Notes: 87787497f52SBarry Smith `PetscDefined()` returns 1 if and only if "PETSC_ ## def" is defined (but empty) or defined to 87887497f52SBarry Smith integer literal 1. In all other cases, `PetscDefined()` returns integer literal 0. Therefore 879bde483f2SJacob Faibussowitsch this macro should not be used if its argument may be defined to a non-empty value other than 880bde483f2SJacob Faibussowitsch 1. 881bde483f2SJacob Faibussowitsch 882bde483f2SJacob Faibussowitsch The prefix "PETSC_" is automatically prepended to def. To avoid prepending "PETSC_", say to 88387497f52SBarry Smith add custom checks in user code, one should use `PetscDefined_()`. 884bde483f2SJacob Faibussowitsch 885bde483f2SJacob Faibussowitsch $ #define FooDefined(d) PetscDefined_(PetscConcat(FOO_,d)) 886bde483f2SJacob Faibussowitsch 887bde483f2SJacob Faibussowitsch Developer Notes: 888bde483f2SJacob Faibussowitsch Getting something that works in C and CPP for an arg that may or may not be defined is 889bde483f2SJacob Faibussowitsch tricky. Here, if we have "#define PETSC_HAVE_BOOGER 1" we match on the placeholder define, 890bde483f2SJacob Faibussowitsch insert the "0," for arg1 and generate the triplet (0, 1, 0). Then the last step cherry picks 891bde483f2SJacob Faibussowitsch the 2nd arg (a one). When PETSC_HAVE_BOOGER is not defined, we generate a (... 1, 0) pair, 892bde483f2SJacob Faibussowitsch and when the last step cherry picks the 2nd arg, we get a zero. 893bde483f2SJacob Faibussowitsch 894bde483f2SJacob Faibussowitsch Our extra expansion via PetscDefined__take_second_expand() is needed with MSVC, which has a 895bde483f2SJacob Faibussowitsch nonconforming implementation of variadic macros. 896bde483f2SJacob Faibussowitsch 897bde483f2SJacob Faibussowitsch Example Usage: 898bde483f2SJacob Faibussowitsch Suppose you would like to call either "foo()" or "bar()" depending on whether PETSC_USE_DEBUG 899bde483f2SJacob Faibussowitsch is defined then 900bde483f2SJacob Faibussowitsch 901bde483f2SJacob Faibussowitsch .vb 902bde483f2SJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 903bde483f2SJacob Faibussowitsch foo(); 904bde483f2SJacob Faibussowitsch #else 905bde483f2SJacob Faibussowitsch bar(); 906bde483f2SJacob Faibussowitsch #endif 907bde483f2SJacob Faibussowitsch 908bde483f2SJacob Faibussowitsch // or alternatively within normal code 909bde483f2SJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 910bde483f2SJacob Faibussowitsch foo(); 911bde483f2SJacob Faibussowitsch } else { 912bde483f2SJacob Faibussowitsch bar(); 913bde483f2SJacob Faibussowitsch } 914bde483f2SJacob Faibussowitsch .ve 915bde483f2SJacob Faibussowitsch 916bde483f2SJacob Faibussowitsch is equivalent to 917bde483f2SJacob Faibussowitsch 918bde483f2SJacob Faibussowitsch .vb 919bde483f2SJacob Faibussowitsch #if defined(PETSC_USE_DEBUG) 920bde483f2SJacob Faibussowitsch # if MY_DETECT_EMPTY_MACRO(PETSC_USE_DEBUG) // assuming you have such a macro 921bde483f2SJacob Faibussowitsch foo(); 922bde483f2SJacob Faibussowitsch # elif PETSC_USE_DEBUG == 1 923bde483f2SJacob Faibussowitsch foo(); 924bde483f2SJacob Faibussowitsch # else 925bde483f2SJacob Faibussowitsch bar(); 926bde483f2SJacob Faibussowitsch # endif 927bde483f2SJacob Faibussowitsch #else 928bde483f2SJacob Faibussowitsch bar(); 929bde483f2SJacob Faibussowitsch #endif 930bde483f2SJacob Faibussowitsch .ve 931bde483f2SJacob Faibussowitsch 932bde483f2SJacob Faibussowitsch Level: intermediate 933bde483f2SJacob Faibussowitsch 934db781477SPatrick Sanan .seealso: `PetscHasAttribute()`, `PetscUnlikely()`, `PetscLikely()`, `PetscConcat()`, 935db781477SPatrick Sanan `PetscExpandToNothing()`, `PetscCompl()` 936817da375SSatish Balay M*/ 937bde483f2SJacob Faibussowitsch #define PetscDefined_arg_1 shift, 938bde483f2SJacob Faibussowitsch #define PetscDefined_arg_ shift, 939bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expanded(ignored, val, ...) val 940bde483f2SJacob Faibussowitsch #define PetscDefined__take_second_expand(args) PetscDefined__take_second_expanded args 941bde483f2SJacob Faibussowitsch #define PetscDefined__take_second(...) PetscDefined__take_second_expand((__VA_ARGS__)) 942bde483f2SJacob Faibussowitsch #define PetscDefined__(arg1_or_junk) PetscDefined__take_second(arg1_or_junk 1, 0, at_) 943bde483f2SJacob Faibussowitsch #define PetscDefined_(value) PetscDefined__(PetscConcat_(PetscDefined_arg_, value)) 944bde483f2SJacob Faibussowitsch #define PetscDefined(def) PetscDefined_(PetscConcat(PETSC_, def)) 945bde483f2SJacob Faibussowitsch 946bde483f2SJacob Faibussowitsch /*MC 94787497f52SBarry Smith PetscUnlikelyDebug - Hints the compiler that the given condition is usually false, eliding 948bde483f2SJacob Faibussowitsch the check in optimized mode 949bde483f2SJacob Faibussowitsch 950f5713a85SJacob Faibussowitsch No Fortran Support 951f5713a85SJacob Faibussowitsch 952bde483f2SJacob Faibussowitsch Synopsis: 953bde483f2SJacob Faibussowitsch #include <petscmacros.h> 954bde483f2SJacob Faibussowitsch bool PetscUnlikelyDebug(bool cond) 955bde483f2SJacob Faibussowitsch 956bde483f2SJacob Faibussowitsch Not Collective 957bde483f2SJacob Faibussowitsch 958bde483f2SJacob Faibussowitsch Input Parameters: 959bde483f2SJacob Faibussowitsch . cond - Boolean expression 960bde483f2SJacob Faibussowitsch 961bde483f2SJacob Faibussowitsch This returns the same truth value, it is only a hint to compilers that the result of cond is 962bde483f2SJacob Faibussowitsch likely to be false. When PETSc is compiled in optimized mode this will always return 963bde483f2SJacob Faibussowitsch false. Additionally, cond is guaranteed to not be evaluated when PETSc is compiled in 964bde483f2SJacob Faibussowitsch optimized mode. 965bde483f2SJacob Faibussowitsch 966bde483f2SJacob Faibussowitsch Example usage: 967bde483f2SJacob Faibussowitsch This routine is shorthand for checking both the condition and whether PetscDefined(USE_DEBUG) 968bde483f2SJacob Faibussowitsch is true. So 969bde483f2SJacob Faibussowitsch 970bde483f2SJacob Faibussowitsch .vb 971bde483f2SJacob Faibussowitsch if (PetscUnlikelyDebug(cond)) { 972bde483f2SJacob Faibussowitsch foo(); 973bde483f2SJacob Faibussowitsch } else { 974bde483f2SJacob Faibussowitsch bar(); 975bde483f2SJacob Faibussowitsch } 976bde483f2SJacob Faibussowitsch .ve 977bde483f2SJacob Faibussowitsch 978bde483f2SJacob Faibussowitsch is equivalent to 979bde483f2SJacob Faibussowitsch 980bde483f2SJacob Faibussowitsch .vb 981bde483f2SJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 982bde483f2SJacob Faibussowitsch if (PetscUnlikely(cond)) { 983bde483f2SJacob Faibussowitsch foo(); 984bde483f2SJacob Faibussowitsch } else { 985bde483f2SJacob Faibussowitsch bar(); 986bde483f2SJacob Faibussowitsch } 987bde483f2SJacob Faibussowitsch } else { 988bde483f2SJacob Faibussowitsch bar(); 989bde483f2SJacob Faibussowitsch } 990bde483f2SJacob Faibussowitsch .ve 991bde483f2SJacob Faibussowitsch 992bde483f2SJacob Faibussowitsch Level: advanced 993bde483f2SJacob Faibussowitsch 994db781477SPatrick Sanan .seealso: `PetscUnlikely()`, `PetscLikely()`, `PetscCall()`, `SETERRQ` 995bde483f2SJacob Faibussowitsch M*/ 996bde483f2SJacob Faibussowitsch #define PetscUnlikelyDebug(cond) (PetscDefined(USE_DEBUG) && PetscUnlikely(cond)) 997bde483f2SJacob Faibussowitsch 998f7e3c444SJacob Faibussowitsch #if defined(PETSC_CLANG_STATIC_ANALYZER) 999f7e3c444SJacob Faibussowitsch // silence compiler warnings when using -pedantic, this is only used by the linter and it cares 1000f7e3c444SJacob Faibussowitsch // not what ISO C allows 10019371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \ 10029371c9d4SSatish Balay __extension__({ \ 10039371c9d4SSatish Balay __VA_ARGS__; \ 10049371c9d4SSatish Balay retexpr; \ 10059371c9d4SSatish Balay }) 1006f7e3c444SJacob Faibussowitsch #else 10079371c9d4SSatish Balay #define PetscMacroReturns_(retexpr, ...) \ 10089371c9d4SSatish Balay retexpr; \ 1009d71ae5a4SJacob Faibussowitsch do { \ 1010d71ae5a4SJacob Faibussowitsch __VA_ARGS__; \ 1011d71ae5a4SJacob Faibussowitsch } while (0) 1012f7e3c444SJacob Faibussowitsch #endif 1013f7e3c444SJacob Faibussowitsch 1014bde483f2SJacob Faibussowitsch /*MC 1015bde483f2SJacob Faibussowitsch PetscExpandToNothing - Expands to absolutely nothing at all 1016bde483f2SJacob Faibussowitsch 1017f5713a85SJacob Faibussowitsch No Fortran Support 1018f5713a85SJacob Faibussowitsch 1019bde483f2SJacob Faibussowitsch Synopsis: 1020bde483f2SJacob Faibussowitsch #include <petscmacros.h> 1021bde483f2SJacob Faibussowitsch void PetscExpandToNothing(...) 1022bde483f2SJacob Faibussowitsch 1023bde483f2SJacob Faibussowitsch Input Parameter: 1024bde483f2SJacob Faibussowitsch . __VA_ARGS__ - Anything at all 1025bde483f2SJacob Faibussowitsch 1026bde483f2SJacob Faibussowitsch Notes: 1027bde483f2SJacob Faibussowitsch Must have at least 1 parameter. 1028bde483f2SJacob Faibussowitsch 1029bde483f2SJacob Faibussowitsch Example usage: 1030bde483f2SJacob Faibussowitsch .vb 1031bde483f2SJacob Faibussowitsch PetscExpandToNothing(a,b,c) -> *nothing* 1032bde483f2SJacob Faibussowitsch .ve 1033bde483f2SJacob Faibussowitsch 1034bde483f2SJacob Faibussowitsch Level: beginner 1035bde483f2SJacob Faibussowitsch 1036db781477SPatrick Sanan .seealso: `PetscConcat()`, `PetscDefined()`, `PetscStringize()`, `PetscExpand()` 1037817da375SSatish Balay M*/ 1038bde483f2SJacob Faibussowitsch #define PetscExpandToNothing(...) 1039f7e3c444SJacob Faibussowitsch 1040f7e3c444SJacob Faibussowitsch /*MC 1041f7e3c444SJacob Faibussowitsch PetscMacroReturns - Define a macro body that returns a value 1042f7e3c444SJacob Faibussowitsch 1043f7e3c444SJacob Faibussowitsch Synopsis: 1044f7e3c444SJacob Faibussowitsch #include <petscmacros.h> 1045f7e3c444SJacob Faibussowitsch return_type PetscMacroReturns(return_type retexpr, ...) 1046f7e3c444SJacob Faibussowitsch 1047f7e3c444SJacob Faibussowitsch Input Parameters: 1048f7e3c444SJacob Faibussowitsch + retexpr - The value or expression that the macro should return 1049f7e3c444SJacob Faibussowitsch - __VA_ARGS__ - The body of the macro 1050f7e3c444SJacob Faibussowitsch 1051f7e3c444SJacob Faibussowitsch Notes: 1052f7e3c444SJacob Faibussowitsch Due to limitations of the C-preprocessor retexpr cannot depend on symbols declared in the 1053f7e3c444SJacob Faibussowitsch body of the macro and should not depend on values produced as a result of the expression. The 1054f7e3c444SJacob Faibussowitsch user should not assume that the result of this macro is equivalent to a single logical source 1055f7e3c444SJacob Faibussowitsch line. It is not portable to use macros defined using this one in conditional or loop bodies 1056f7e3c444SJacob Faibussowitsch without enclosing them in curly braces\: 1057f7e3c444SJacob Faibussowitsch 1058f7e3c444SJacob Faibussowitsch .vb 1059f7e3c444SJacob Faibussowitsch #define FOO(arg1) PetscMacroReturns(0,arg1+=10) // returns 0 1060f7e3c444SJacob Faibussowitsch 1061f7e3c444SJacob Faibussowitsch int err,x = 10; 1062f7e3c444SJacob Faibussowitsch 1063f7e3c444SJacob Faibussowitsch if (...) err = FOO(x); // ERROR, body of FOO() executed outside the if statement 1064f7e3c444SJacob Faibussowitsch if (...) { err = FOO(x); } // OK 1065f7e3c444SJacob Faibussowitsch 1066f7e3c444SJacob Faibussowitsch for (...) err = FOO(x); // ERROR, body of FOO() executed outside the loop 1067f7e3c444SJacob Faibussowitsch for (...) { err = FOO(x); } // OK 1068f7e3c444SJacob Faibussowitsch .ve 1069f7e3c444SJacob Faibussowitsch 1070f7e3c444SJacob Faibussowitsch It is also not portable to use this macro directly inside function call, conditional, loop, 1071f7e3c444SJacob Faibussowitsch or switch statements\: 1072f7e3c444SJacob Faibussowitsch 1073f7e3c444SJacob Faibussowitsch .vb 1074f7e3c444SJacob Faibussowitsch extern void bar(int); 1075f7e3c444SJacob Faibussowitsch 1076f7e3c444SJacob Faibussowitsch int ret = FOO(x); 1077f7e3c444SJacob Faibussowitsch 1078f7e3c444SJacob Faibussowitsch bar(FOO(x)); // ERROR, may not compile 1079f7e3c444SJacob Faibussowitsch bar(ret); // OK 1080f7e3c444SJacob Faibussowitsch 1081f7e3c444SJacob Faibussowitsch if (FOO(x)) // ERROR, may not compile 1082f7e3c444SJacob Faibussowitsch if (ret) // OK 1083f7e3c444SJacob Faibussowitsch .ve 1084f7e3c444SJacob Faibussowitsch 1085f7e3c444SJacob Faibussowitsch Example usage: 1086f7e3c444SJacob Faibussowitsch .vb 1087f7e3c444SJacob Faibussowitsch #define MY_SIMPLE_RETURNING_MACRO(arg1) PetscMacroReturns(0,arg1+=10) 1088f7e3c444SJacob Faibussowitsch 1089f7e3c444SJacob Faibussowitsch int x = 10; 1090f7e3c444SJacob Faibussowitsch int err = MY_SIMPLE_RETURNING_MACRO(x); // err = 0, x = 20 1091f7e3c444SJacob Faibussowitsch 1092f7e3c444SJacob Faibussowitsch // multiline macros allowed, but must declare with line continuation as usual 1093f7e3c444SJacob Faibussowitsch #define MY_COMPLEX_RETURNING_MACRO(arg1) PetscMacroReturns(0, \ 1094f7e3c444SJacob Faibussowitsch if (arg1 > 10) { \ 1095f7e3c444SJacob Faibussowitsch puts("big int!"); \ 1096f7e3c444SJacob Faibussowitsch } else { \ 1097f7e3c444SJacob Faibussowitsch return 7355608; \ 1098f7e3c444SJacob Faibussowitsch } \ 1099f7e3c444SJacob Faibussowitsch ) 1100f7e3c444SJacob Faibussowitsch 1101f7e3c444SJacob Faibussowitsch // if retexpr contains commas, must enclose it with braces 1102f7e3c444SJacob Faibussowitsch #define MY_COMPLEX_RETEXPR_MACRO_1() PetscMacroReturns(x+=10,0,body...) 1103f7e3c444SJacob Faibussowitsch #define MY_COMPLEX_RETEXPR_MACRO_2() PetscMacroReturns((x+=10,0),body...) 1104f7e3c444SJacob Faibussowitsch 1105f7e3c444SJacob Faibussowitsch int x = 10; 1106f7e3c444SJacob Faibussowitsch int y = MY_COMPLEX_RETEXPR_MACRO_1(); // ERROR, y = x = 20 not 0 1107f7e3c444SJacob Faibussowitsch int z = MY_COMPLEX_RETEXPR_MACRO_2(); // OK, y = 0, x = 20 1108f7e3c444SJacob Faibussowitsch .ve 1109f7e3c444SJacob Faibussowitsch 1110f7e3c444SJacob Faibussowitsch Level: intermediate 1111f7e3c444SJacob Faibussowitsch 1112db781477SPatrick Sanan .seealso: `PetscExpand()`, `PetscConcat()`, `PetscStringize()` 1113f7e3c444SJacob Faibussowitsch M*/ 1114f7e3c444SJacob Faibussowitsch #define PetscMacroReturns(retexpr, ...) PetscMacroReturns_(retexpr, __VA_ARGS__) 1115f7e3c444SJacob Faibussowitsch 11163ba16761SJacob Faibussowitsch #define PetscMacroReturnStandard(...) PetscMacroReturns(PETSC_SUCCESS, __VA_ARGS__) 1117f7e3c444SJacob Faibussowitsch 1118dd39110bSPierre Jolivet /*MC 1119dd39110bSPierre Jolivet PETSC_STATIC_ARRAY_LENGTH - Return the length of a static array 1120dd39110bSPierre Jolivet 1121dd39110bSPierre Jolivet Level: intermediate 1122dd39110bSPierre Jolivet M*/ 1123dd39110bSPierre Jolivet #define PETSC_STATIC_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) 1124dd39110bSPierre Jolivet 1125296d8154SBarry Smith /* 1126296d8154SBarry Smith These macros allow extracting out the first argument or all but the first argument from a macro __VAR_ARGS__ INSIDE another macro. 1127296d8154SBarry Smith 1128296d8154SBarry Smith Example usage: 1129296d8154SBarry Smith 1130296d8154SBarry Smith #define mymacro(obj,...) { 1131296d8154SBarry Smith PETSC_FIRST_ARG((__VA_ARGS__,unused)); 1132296d8154SBarry Smith f(22 PETSC_REST_ARG(__VA_ARGS__)); 1133296d8154SBarry Smith } 1134296d8154SBarry Smith 1135296d8154SBarry Smith 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 1136296d8154SBarry Smith 1137296d8154SBarry Smith Reference: 1138296d8154SBarry Smith https://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick 1139296d8154SBarry Smith */ 1140296d8154SBarry Smith #define PETSC_FIRST_ARG_(N, ...) N 1141296d8154SBarry Smith #define PETSC_FIRST_ARG(args) PETSC_FIRST_ARG_ args 1142296d8154SBarry Smith #define PETSC_SELECT_16TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, ...) a16 1143296d8154SBarry Smith #define PETSC_NUM(...) PETSC_SELECT_16TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) 1144296d8154SBarry Smith #define PETSC_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ 1145296d8154SBarry Smith #define PETSC_REST_HELPER_ONE(first) 1146296d8154SBarry Smith #define PETSC_REST_HELPER2(qty, ...) PETSC_REST_HELPER_##qty(__VA_ARGS__) 1147296d8154SBarry Smith #define PETSC_REST_HELPER(qty, ...) PETSC_REST_HELPER2(qty, __VA_ARGS__) 1148296d8154SBarry Smith #define PETSC_REST_ARG(...) PETSC_REST_HELPER(PETSC_NUM(__VA_ARGS__), __VA_ARGS__) 1149296d8154SBarry Smith 11501c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(name, ...) \ 11511c7e414eSJacob Faibussowitsch _Pragma(PetscStringize(name diagnostic push)) \ 11521c7e414eSJacob Faibussowitsch _Pragma(PetscStringize(name diagnostic ignored __VA_ARGS__)) 11531c7e414eSJacob Faibussowitsch 11541c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(name) _Pragma(PetscStringize(name diagnostic pop)) 11551c7e414eSJacob Faibussowitsch 11561c7e414eSJacob Faibussowitsch #if defined(__clang__) 11571c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(clang, __VA_ARGS__) 11581c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(clang) 11591c7e414eSJacob Faibussowitsch #elif defined(__GNUC__) || defined(__GNUG__) 11601c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_(GCC, __VA_ARGS__) 11611c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_(GCC) 11621c7e414eSJacob Faibussowitsch #endif 11631c7e414eSJacob Faibussowitsch 11641c7e414eSJacob Faibussowitsch #ifndef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN 11651c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN(...) 11661c7e414eSJacob Faibussowitsch #define PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(...) 11671c7e414eSJacob Faibussowitsch // only undefine these if they are not used 11681c7e414eSJacob Faibussowitsch #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN_ 11691c7e414eSJacob Faibussowitsch #undef PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END_ 11701c7e414eSJacob Faibussowitsch #endif 11711c7e414eSJacob Faibussowitsch 11722e327cfbSJacob Faibussowitsch /* OpenMP support */ 11732e327cfbSJacob Faibussowitsch #if defined(_OPENMP) 11742e327cfbSJacob Faibussowitsch #if defined(_MSC_VER) 11752e327cfbSJacob Faibussowitsch #define PetscPragmaOMP(...) __pragma(__VA_ARGS__) 11762e327cfbSJacob Faibussowitsch #else 11772e327cfbSJacob Faibussowitsch #define PetscPragmaOMP(...) _Pragma(PetscStringize(omp __VA_ARGS__)) 11782e327cfbSJacob Faibussowitsch #endif 11792e327cfbSJacob Faibussowitsch #endif 11802e327cfbSJacob Faibussowitsch 11812e327cfbSJacob Faibussowitsch #ifndef PetscPragmaOMP 11822e327cfbSJacob Faibussowitsch #define PetscPragmaOMP(...) 11832e327cfbSJacob Faibussowitsch #endif 11842e327cfbSJacob Faibussowitsch 11852e327cfbSJacob Faibussowitsch /* PetscPragmaSIMD - from CeedPragmaSIMD */ 11862e327cfbSJacob Faibussowitsch #if defined(__NEC__) 11872e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD _Pragma("_NEC ivdep") 11882e327cfbSJacob Faibussowitsch #elif defined(__INTEL_COMPILER) && !defined(_WIN32) 11892e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD _Pragma("vector") 11902e327cfbSJacob Faibussowitsch #elif defined(__GNUC__) 11912e327cfbSJacob Faibussowitsch #if __GNUC__ >= 5 && !defined(__PGI) 11922e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD _Pragma("GCC ivdep") 11932e327cfbSJacob Faibussowitsch #endif 11942e327cfbSJacob Faibussowitsch #elif defined(_OPENMP) && _OPENMP >= 201307 11952e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD PetscPragmaOMP(simd) 11962e327cfbSJacob Faibussowitsch #elif defined(PETSC_HAVE_CRAY_VECTOR) 11972e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD _Pragma("_CRI ivdep") 11982e327cfbSJacob Faibussowitsch #endif 11992e327cfbSJacob Faibussowitsch 12002e327cfbSJacob Faibussowitsch #ifndef PetscPragmaSIMD 12012e327cfbSJacob Faibussowitsch #define PetscPragmaSIMD 12022e327cfbSJacob Faibussowitsch #endif 12032e327cfbSJacob Faibussowitsch 1204bde483f2SJacob Faibussowitsch #endif /* PETSC_PREPROCESSOR_MACROS_H */ 1205