Program Listing for File macros.hpp¶
↰ Return to documentation for file (SeQuant/core/utility/macros.hpp)
//
// Created by Eduard Valeyev on 7/31/23
//
#ifndef SEQUANT_CORE_UTILITY_MACROS_H
#define SEQUANT_CORE_UTILITY_MACROS_H
#include <SeQuant/core/utility/exception.hpp>
#include <cstdlib>
#include <source_location>
#include <string>
/* detect C++ compiler id:
- ids taken from CMake
- macros are discussed at https://sourceforge.net/p/predef/wiki/Compilers/
*/
#define SEQUANT_CXX_COMPILER_ID_GNU 0
#define SEQUANT_CXX_COMPILER_ID_Clang 1
#define SEQUANT_CXX_COMPILER_ID_AppleClang 2
#define SEQUANT_CXX_COMPILER_ID_XLClang 3
#define SEQUANT_CXX_COMPILER_ID_Intel 4
#if defined(__INTEL_COMPILER_BUILD_DATE) /* macros like __ICC and even \
__INTEL_COMPILER can be affected \
by command options like -no-icc */
#define SEQUANT_CXX_COMPILER_ID SEQUANT_CXX_COMPILER_ID_Intel
#define SEQUANT_CXX_COMPILER_IS_ICC 1
#endif
#if defined(__clang__) && !defined(SEQUANT_CXX_COMPILER_IS_ICC)
#define SEQUANT_CXX_COMPILER_IS_CLANG 1
#if defined(__apple_build_version__)
#define SEQUANT_CXX_COMPILER_ID SEQUANT_CXX_COMPILER_ID_AppleClang
#elif defined(__ibmxl__)
#define SEQUANT_CXX_COMPILER_ID SEQUANT_CXX_COMPILER_ID_XLClang
#else
#define SEQUANT_CXX_COMPILER_ID SEQUANT_CXX_COMPILER_ID_Clang
#endif
#endif
#if defined(__GNUG__) && !defined(SEQUANT_CXX_COMPILER_IS_ICC) && \
!defined(SEQUANT_CXX_COMPILER_IS_CLANG)
#define SEQUANT_CXX_COMPILER_ID SEQUANT_CXX_COMPILER_ID_GNU
#define SEQUANT_CXX_COMPILER_IS_GCC 1
#endif
/* ----------- pragma helpers ---------------*/
#define SEQUANT_PRAGMA(x) _Pragma(#x)
/* same as SEQUANT_PRAGMA(x), but expands x */
#define SEQUANT_XPRAGMA(x) SEQUANT_PRAGMA(x)
#define SEQUANT_CONCAT_IMPL(x, y) x##y
/* "concats" a and b without a space in between */
#define SEQUANT_CONCAT(x, y) SEQUANT_CONCAT_IMPL(x, y)
/* "concats" a and b with a space in between */
#define SEQUANT_CONCAT_W_SPACE(a, b) a b
#if defined(SEQUANT_CXX_COMPILER_IS_CLANG)
#define SEQUANT_PRAGMA_CLANG(x) \
SEQUANT_XPRAGMA(SEQUANT_CONCAT_W_SPACE(clang, x))
#else
#define SEQUANT_PRAGMA_CLANG(x)
#endif
#if defined(SEQUANT_CXX_COMPILER_IS_GCC)
#define SEQUANT_PRAGMA_GCC(x) SEQUANT_XPRAGMA(SEQUANT_CONCAT_W_SPACE(GCC, x))
#else
#define SEQUANT_PRAGMA_GCC(x)
#endif
/* Defines the default error checking behavior */
#define SEQUANT_ASSERT_THROW 2
#define SEQUANT_ASSERT_ABORT 3
#define SEQUANT_ASSERT_IGNORE 4
#define SEQUANT_STRINGIFY(x) #x
#define SEQUANT_ASSERT_BEHAVIOR \
SEQUANT_CONCAT(SEQUANT_ASSERT_, SEQUANT_ASSERT_BEHAVIOR_)
namespace sequant {
enum class AssertBehavior : int {
Throw = SEQUANT_ASSERT_THROW,
Abort = SEQUANT_ASSERT_ABORT,
Ignore = SEQUANT_ASSERT_IGNORE
};
constexpr bool assert_enabled() {
#ifdef SEQUANT_ASSERT_ENABLED
return true;
#else
return false;
#endif
}
constexpr AssertBehavior assert_behavior() {
return static_cast<AssertBehavior>(SEQUANT_ASSERT_BEHAVIOR);
}
#ifdef SEQUANT_ASSERT_ENABLED
[[noreturn]]
#endif
void assert_failed(
const std::string &errmsg,
std::source_location location = std::source_location::current());
} // namespace sequant
#ifdef SEQUANT_ASSERT_ENABLED
#define SEQUANT_ASSERT_MESSAGE(EXPR, ...) \
"SEQUANT_ASSERT(" SEQUANT_STRINGIFY(EXPR) ") failed" __VA_OPT__( \
" with message '" __VA_ARGS__ "'")
#define SEQUANT_ASSERT(EXPR, ...) \
do { \
if (!(EXPR)) { \
sequant::assert_failed(SEQUANT_ASSERT_MESSAGE(EXPR, __VA_ARGS__)); \
} \
} while (0)
#else
#define SEQUANT_ASSERT(...) \
do { \
} while (0)
#endif
namespace sequant {
[[noreturn]] void abort_msg(
const std::string &errmsg,
std::source_location location = std::source_location::current());
} // namespace sequant
#define SEQUANT_ABORT(msg) sequant::abort_msg(msg)
#if defined(__cpp_lib_unreachable)
#define SEQUANT_UNREACHABLE_TOKEN std::unreachable()
#elif defined(SEQUANT_CXX_COMPILER_IS_GCC) || \
defined(SEQUANT_CXX_COMPILER_IS_CLANG)
#define SEQUANT_UNREACHABLE_TOKEN __builtin_unreachable()
#else
// Compiler-independent fallback
#define SEQUANT_UNREACHABLE_TOKEN std::abort()
#endif
#define SEQUANT_UNREACHABLE \
do { \
SEQUANT_ASSERT(false && "reached unreachable code"); \
SEQUANT_UNREACHABLE_TOKEN; \
} while (0)
#endif // SEQUANT_CORE_UTILITY_MACROS_H