mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-13 20:26:03 +08:00
Add custom ODR-safe assert.
This commit is contained in:
parent
3fe8c51104
commit
08c961e837
@ -82,9 +82,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#ifndef __SYCL_DEVICE_ONLY__
|
|
||||||
#include <cassert>
|
|
||||||
#endif
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#ifndef EIGEN_NO_IO
|
#ifndef EIGEN_NO_IO
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -160,6 +157,7 @@ using std::ptrdiff_t;
|
|||||||
|
|
||||||
#include "src/Core/util/Constants.h"
|
#include "src/Core/util/Constants.h"
|
||||||
#include "src/Core/util/Meta.h"
|
#include "src/Core/util/Meta.h"
|
||||||
|
#include "src/Core/util/Assert.h"
|
||||||
#include "src/Core/util/ForwardDeclarations.h"
|
#include "src/Core/util/ForwardDeclarations.h"
|
||||||
#include "src/Core/util/StaticAssert.h"
|
#include "src/Core/util/StaticAssert.h"
|
||||||
#include "src/Core/util/XprHelper.h"
|
#include "src/Core/util/XprHelper.h"
|
||||||
|
166
Eigen/src/Core/util/Assert.h
Normal file
166
Eigen/src/Core/util/Assert.h
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022, The Eigen authors.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla
|
||||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#ifndef EIGEN_CORE_UTIL_ASSERT_H
|
||||||
|
#define EIGEN_CORE_UTIL_ASSERT_H
|
||||||
|
|
||||||
|
// Eigen custom assert function.
|
||||||
|
//
|
||||||
|
// The combination of Eigen's relative includes and cassert's `assert` function
|
||||||
|
// (or any usage of the __FILE__ macro) can lead to ODR issues:
|
||||||
|
// a header included using different relative paths in two different TUs will
|
||||||
|
// have two different token-for-token definitions, since __FILE__ is expanded
|
||||||
|
// as an in-line string with different values. Normally this would be
|
||||||
|
// harmless - the linker would just choose one definition. However, it breaks
|
||||||
|
// with C++20 modules when functions in different modules have different
|
||||||
|
// definitions.
|
||||||
|
//
|
||||||
|
// To get around this, we need to use __builtin_FILE() when available, which is
|
||||||
|
// considered a single token, and thus satisfies the ODR.
|
||||||
|
|
||||||
|
// Only define eigen_plain_assert if we are debugging, and either
|
||||||
|
// - we are not compiling for GPU, or
|
||||||
|
// - gpu debugging is enabled.
|
||||||
|
#if !defined(EIGEN_NO_DEBUG) && (!defined(EIGEN_GPU_COMPILE_PHASE) || !defined(EIGEN_NO_DEBUG_GPU))
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#ifndef EIGEN_USE_CUSTOM_PLAIN_ASSERT
|
||||||
|
// Disable new custom asserts by default for now.
|
||||||
|
#define EIGEN_USE_CUSTOM_PLAIN_ASSERT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EIGEN_USE_CUSTOM_PLAIN_ASSERT
|
||||||
|
|
||||||
|
#ifndef EIGEN_HAS_BUILTIN_FILE
|
||||||
|
// Clang can check if __builtin_FILE() is supported.
|
||||||
|
// GCC > 5, MSVC 2019 14.26 (1926) all have __builtin_FILE().
|
||||||
|
//
|
||||||
|
// For NVCC, it's more complicated. Through trial-and-error:
|
||||||
|
// - nvcc+gcc supports __builtin_FILE() on host, and on device after CUDA 11.
|
||||||
|
// - nvcc+msvc supports __builtin_FILE() only after CUDA 11.
|
||||||
|
#if (EIGEN_HAS_BUILTIN(__builtin_FILE) && (EIGEN_COMP_CLANG || !defined(EIGEN_CUDA_ARCH))) || \
|
||||||
|
(EIGEN_GNUC_STRICT_AT_LEAST(5, 0, 0) && (EIGEN_COMP_NVCC >= 110000 || !defined(EIGEN_CUDA_ARCH))) || \
|
||||||
|
(EIGEN_COMP_MSVC >= 1926 && (!EIGEN_COMP_NVCC || EIGEN_COMP_NVCC >= 110000))
|
||||||
|
#define EIGEN_HAS_BUILTIN_FILE 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_HAS_BUILTIN_FILE 0
|
||||||
|
#endif
|
||||||
|
#endif // EIGEN_HAS_BUILTIN_FILE
|
||||||
|
|
||||||
|
#if EIGEN_HAS_BUILTIN_FILE
|
||||||
|
# define EIGEN_BUILTIN_FILE __builtin_FILE()
|
||||||
|
# define EIGEN_BUILTIN_LINE __builtin_LINE()
|
||||||
|
#else
|
||||||
|
// Default (potentially unsafe) values.
|
||||||
|
# define EIGEN_BUILTIN_FILE __FILE__
|
||||||
|
# define EIGEN_BUILTIN_LINE __LINE__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use __PRETTY_FUNCTION__ when available, since it is more descriptive, as
|
||||||
|
// __builtin_FUNCTION() only returns the undecorated function name.
|
||||||
|
// This should still be okay ODR-wise since it is a compiler-specific fixed
|
||||||
|
// value. Mixing compilers will likely lead to ODR violations anyways.
|
||||||
|
#if EIGEN_COMP_MSVC
|
||||||
|
# define EIGEN_BUILTIN_FUNCTION __FUNCSIG__
|
||||||
|
#elif EIGEN_COMP_GNUC
|
||||||
|
# define EIGEN_BUILTIN_FUNCTION __PRETTY_FUNCTION__
|
||||||
|
#else
|
||||||
|
# define EIGEN_BUILTIN_FUNCTION __func__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Generic default assert handler.
|
||||||
|
template<typename EnableIf = void, typename... EmptyArgs>
|
||||||
|
struct assert_handler_impl {
|
||||||
|
EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE
|
||||||
|
static inline void run(const char* expression, const char* file, unsigned line, const char* function) {
|
||||||
|
#ifdef EIGEN_GPU_COMPILE_PHASE
|
||||||
|
// GPU device code doesn't allow stderr or abort, so use printf and raise an
|
||||||
|
// illegal instruction exception to trigger a kernel failure.
|
||||||
|
#ifndef EIGEN_NO_IO
|
||||||
|
printf("Assertion failed at %s:%u in %s: %s\n",
|
||||||
|
file == nullptr ? "<file>" : file,
|
||||||
|
line,
|
||||||
|
function == nullptr ? "<function>" : function,
|
||||||
|
expression);
|
||||||
|
#endif
|
||||||
|
__trap();
|
||||||
|
|
||||||
|
#else // EIGEN_GPU_COMPILE_PHASE
|
||||||
|
|
||||||
|
// Print to stderr and abort, as specified in <cassert>.
|
||||||
|
#ifndef EIGEN_NO_IO
|
||||||
|
fprintf(stderr, "Assertion failed at %s:%u in %s: %s\n",
|
||||||
|
file == nullptr ? "<file>" : file,
|
||||||
|
line,
|
||||||
|
function == nullptr ? "<function>" : function,
|
||||||
|
expression);
|
||||||
|
#endif
|
||||||
|
std::abort();
|
||||||
|
|
||||||
|
#endif // EIGEN_GPU_COMPILE_PHASE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use POSIX __assert_fail handler when available.
|
||||||
|
//
|
||||||
|
// This allows us to integrate with systems that have custom handlers.
|
||||||
|
//
|
||||||
|
// NOTE: this handler is not always available on all POSIX systems (otherwise
|
||||||
|
// we could simply test for __unix__ or similar). The handler function name
|
||||||
|
// seems to depend on the specific toolchain implementation, and differs between
|
||||||
|
// compilers, platforms, OSes, etc. Hence, we detect support via SFINAE.
|
||||||
|
template<typename... EmptyArgs>
|
||||||
|
struct assert_handler_impl<
|
||||||
|
void_t<decltype(__assert_fail(
|
||||||
|
(const char*)nullptr, // expression
|
||||||
|
(const char*)nullptr, // file
|
||||||
|
0, // line
|
||||||
|
(const char*)nullptr, // function
|
||||||
|
std::declval<EmptyArgs>()... // Empty substitution required for SFINAE.
|
||||||
|
))>, EmptyArgs... > {
|
||||||
|
EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE
|
||||||
|
static inline void run(const char* expression, const char* file, unsigned line, const char* function) {
|
||||||
|
// GCC requires this call to be dependent on the template parameters.
|
||||||
|
__assert_fail(expression, file, line, function, std::declval<EmptyArgs>()...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE
|
||||||
|
inline void __assert_handler(const char* expression, const char* file, unsigned line, const char* function) {
|
||||||
|
assert_handler_impl<>::run(expression, file, line, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace Eigen
|
||||||
|
|
||||||
|
#define eigen_plain_assert(expression) \
|
||||||
|
(EIGEN_PREDICT_FALSE(!(expression)) ? \
|
||||||
|
Eigen::internal::__assert_handler(#expression, \
|
||||||
|
EIGEN_BUILTIN_FILE, \
|
||||||
|
EIGEN_BUILTIN_LINE, \
|
||||||
|
EIGEN_BUILTIN_FUNCTION) : (void)0)
|
||||||
|
|
||||||
|
#else // EIGEN_USE_CUSTOM_PLAIN_ASSERT
|
||||||
|
|
||||||
|
// Use regular assert.
|
||||||
|
#define eigen_plain_assert(condition) assert(condition)
|
||||||
|
|
||||||
|
#endif // EIGEN_USE_CUSTOM_PLAIN_ASSERT
|
||||||
|
|
||||||
|
#else // EIGEN_NO_DEBUG
|
||||||
|
|
||||||
|
#define eigen_plain_assert(condition) ((void)0)
|
||||||
|
|
||||||
|
#endif // EIGEN_NO_DEBUG
|
||||||
|
|
||||||
|
#endif // EIGEN_CORE_UTIL_ASSERT_H
|
@ -848,8 +848,8 @@
|
|||||||
|
|
||||||
// GPU stuff
|
// GPU stuff
|
||||||
|
|
||||||
// Disable some features when compiling with GPU compilers (NVCC/clang-cuda/SYCL/HIPCC)
|
// Disable some features when compiling with GPU compilers (SYCL/HIPCC)
|
||||||
#if defined(EIGEN_CUDACC) || defined(SYCL_DEVICE_ONLY) || defined(EIGEN_HIPCC)
|
#if defined(SYCL_DEVICE_ONLY) || defined(EIGEN_HIP_DEVICE_COMPILE)
|
||||||
// Do not try asserts on device code
|
// Do not try asserts on device code
|
||||||
#ifndef EIGEN_NO_DEBUG
|
#ifndef EIGEN_NO_DEBUG
|
||||||
#define EIGEN_NO_DEBUG
|
#define EIGEN_NO_DEBUG
|
||||||
@ -858,7 +858,10 @@
|
|||||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||||
#undef EIGEN_INTERNAL_DEBUGGING
|
#undef EIGEN_INTERNAL_DEBUGGING
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// No exceptions on device.
|
||||||
|
#if defined(SYCL_DEVICE_ONLY) || defined(EIGEN_GPU_COMPILE_PHASE)
|
||||||
#ifdef EIGEN_EXCEPTIONS
|
#ifdef EIGEN_EXCEPTIONS
|
||||||
#undef EIGEN_EXCEPTIONS
|
#undef EIGEN_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
@ -890,17 +893,6 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// eigen_plain_assert is where we implement the workaround for the assert() bug in GCC <= 4.3, see bug 89
|
|
||||||
#ifdef EIGEN_NO_DEBUG
|
|
||||||
#ifdef SYCL_DEVICE_ONLY // used to silence the warning on SYCL device
|
|
||||||
#define eigen_plain_assert(x) EIGEN_UNUSED_VARIABLE(x)
|
|
||||||
#else
|
|
||||||
#define eigen_plain_assert(x)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define eigen_plain_assert(x) assert(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// eigen_assert can be overridden
|
// eigen_assert can be overridden
|
||||||
#ifndef eigen_assert
|
#ifndef eigen_assert
|
||||||
#define eigen_assert(x) eigen_plain_assert(x)
|
#define eigen_assert(x) eigen_plain_assert(x)
|
||||||
@ -912,7 +904,7 @@
|
|||||||
#define eigen_internal_assert(x) ((void)0)
|
#define eigen_internal_assert(x) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EIGEN_NO_DEBUG
|
#if defined(EIGEN_NO_DEBUG) || (defined(EIGEN_GPU_COMPILE_PHASE) && defined(EIGEN_NO_DEBUG_GPU))
|
||||||
#define EIGEN_ONLY_USED_FOR_DEBUG(x) EIGEN_UNUSED_VARIABLE(x)
|
#define EIGEN_ONLY_USED_FOR_DEBUG(x) EIGEN_UNUSED_VARIABLE(x)
|
||||||
#else
|
#else
|
||||||
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
|
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
|
||||||
|
@ -153,6 +153,21 @@ template<typename T> struct is_same<T,T> { enum { value = 1 }; };
|
|||||||
template< class T >
|
template< class T >
|
||||||
struct is_void : is_same<void, std::remove_const_t<T>> {};
|
struct is_void : is_same<void, std::remove_const_t<T>> {};
|
||||||
|
|
||||||
|
/** \internal
|
||||||
|
* Implementation of std::void_t for SFINAE.
|
||||||
|
*
|
||||||
|
* Pre C++17:
|
||||||
|
* Custom implementation.
|
||||||
|
*
|
||||||
|
* Post C++17: Uses std::void_t
|
||||||
|
*/
|
||||||
|
#if EIGEN_COMP_CXXVER >= 17
|
||||||
|
using std::void_t;
|
||||||
|
#else
|
||||||
|
template<typename...>
|
||||||
|
using void_t = void;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<> struct is_arithmetic<signed long long> { enum { value = true }; };
|
template<> struct is_arithmetic<signed long long> { enum { value = true }; };
|
||||||
template<> struct is_arithmetic<unsigned long long> { enum { value = true }; };
|
template<> struct is_arithmetic<unsigned long long> { enum { value = true }; };
|
||||||
using std::is_integral;
|
using std::is_integral;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user