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