Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
Assert.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2022, The Eigen authors.
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_CORE_UTIL_ASSERT_H
11#define EIGEN_CORE_UTIL_ASSERT_H
12
13// Eigen custom assert function.
14//
15// The combination of Eigen's relative includes and cassert's `assert` function
16// (or any usage of the __FILE__ macro) can lead to ODR issues:
17// a header included using different relative paths in two different TUs will
18// have two different token-for-token definitions, since __FILE__ is expanded
19// as an in-line string with different values. Normally this would be
20// harmless - the linker would just choose one definition. However, it breaks
21// with C++20 modules when functions in different modules have different
22// definitions.
23//
24// To get around this, we need to use __builtin_FILE() when available, which is
25// considered a single token, and thus satisfies the ODR.
26
27// Only define eigen_plain_assert if we are debugging, and either
28// - we are not compiling for GPU, or
29// - gpu debugging is enabled.
30#if !defined(EIGEN_NO_DEBUG) && (!defined(EIGEN_GPU_COMPILE_PHASE) || !defined(EIGEN_NO_DEBUG_GPU))
31
32#include <cassert>
33
34#ifndef EIGEN_USE_CUSTOM_PLAIN_ASSERT
35// Disable new custom asserts by default for now.
36#define EIGEN_USE_CUSTOM_PLAIN_ASSERT 0
37#endif
38
39#if EIGEN_USE_CUSTOM_PLAIN_ASSERT
40
41#ifndef EIGEN_HAS_BUILTIN_FILE
42// Clang can check if __builtin_FILE() is supported.
43// GCC > 5, MSVC 2019 14.26 (1926) all have __builtin_FILE().
44//
45// For NVCC, it's more complicated. Through trial-and-error:
46// - nvcc+gcc supports __builtin_FILE() on host, and on device after CUDA 11.
47// - nvcc+msvc supports __builtin_FILE() only after CUDA 11.
48#if (EIGEN_HAS_BUILTIN(__builtin_FILE) && (EIGEN_COMP_CLANG || !defined(EIGEN_CUDA_ARCH))) || \
49 (EIGEN_GNUC_STRICT_AT_LEAST(5, 0, 0) && (EIGEN_COMP_NVCC >= 110000 || !defined(EIGEN_CUDA_ARCH))) || \
50 (EIGEN_COMP_MSVC >= 1926 && (!EIGEN_COMP_NVCC || EIGEN_COMP_NVCC >= 110000))
51#define EIGEN_HAS_BUILTIN_FILE 1
52#else
53#define EIGEN_HAS_BUILTIN_FILE 0
54#endif
55#endif // EIGEN_HAS_BUILTIN_FILE
56
57#if EIGEN_HAS_BUILTIN_FILE
58#define EIGEN_BUILTIN_FILE __builtin_FILE()
59#define EIGEN_BUILTIN_LINE __builtin_LINE()
60#else
61// Default (potentially unsafe) values.
62#define EIGEN_BUILTIN_FILE __FILE__
63#define EIGEN_BUILTIN_LINE __LINE__
64#endif
65
66// Use __PRETTY_FUNCTION__ when available, since it is more descriptive, as
67// __builtin_FUNCTION() only returns the undecorated function name.
68// This should still be okay ODR-wise since it is a compiler-specific fixed
69// value. Mixing compilers will likely lead to ODR violations anyways.
70#if EIGEN_COMP_MSVC
71#define EIGEN_BUILTIN_FUNCTION __FUNCSIG__
72#elif EIGEN_COMP_GNUC
73#define EIGEN_BUILTIN_FUNCTION __PRETTY_FUNCTION__
74#else
75#define EIGEN_BUILTIN_FUNCTION __func__
76#endif
77
78namespace Eigen {
79namespace internal {
80
81// Generic default assert handler.
82template <typename EnableIf = void, typename... EmptyArgs>
83struct assert_handler_impl {
84 EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE static inline void run(const char* expression, const char* file, unsigned line,
85 const char* function) {
86#ifdef EIGEN_GPU_COMPILE_PHASE
87 // GPU device code doesn't allow stderr or abort, so use printf and raise an
88 // illegal instruction exception to trigger a kernel failure.
89#ifndef EIGEN_NO_IO
90 printf("Assertion failed at %s:%u in %s: %s\n", file == nullptr ? "<file>" : file, line,
91 function == nullptr ? "<function>" : function, expression);
92#endif
93 __trap();
94
95#else // EIGEN_GPU_COMPILE_PHASE
96
97 // Print to stderr and abort, as specified in <cassert>.
98#ifndef EIGEN_NO_IO
99 fprintf(stderr, "Assertion failed at %s:%u in %s: %s\n", file == nullptr ? "<file>" : file, line,
100 function == nullptr ? "<function>" : function, expression);
101#endif
102 std::abort();
103
104#endif // EIGEN_GPU_COMPILE_PHASE
105 }
106};
107
108// Use POSIX __assert_fail handler when available.
109//
110// This allows us to integrate with systems that have custom handlers.
111//
112// NOTE: this handler is not always available on all POSIX systems (otherwise
113// we could simply test for __unix__ or similar). The handler function name
114// seems to depend on the specific toolchain implementation, and differs between
115// compilers, platforms, OSes, etc. Hence, we detect support via SFINAE.
116template <typename... EmptyArgs>
117struct assert_handler_impl<void_t<decltype(__assert_fail((const char*)nullptr, // expression
118 (const char*)nullptr, // file
119 0, // line
120 (const char*)nullptr, // function
121 std::declval<EmptyArgs>()... // Empty substitution required
122 // for SFINAE.
123 ))>,
124 EmptyArgs...> {
125 EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE static inline void run(const char* expression, const char* file, unsigned line,
126 const char* function) {
127 // GCC requires this call to be dependent on the template parameters.
128 __assert_fail(expression, file, line, function, std::declval<EmptyArgs>()...);
129 }
130};
131
132EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE inline void __assert_handler(const char* expression, const char* file,
133 unsigned line, const char* function) {
134 assert_handler_impl<>::run(expression, file, line, function);
135}
136
137} // namespace internal
138} // namespace Eigen
139
140#define eigen_plain_assert(expression) \
141 (EIGEN_PREDICT_FALSE(!(expression)) ? Eigen::internal::__assert_handler(#expression, EIGEN_BUILTIN_FILE, \
142 EIGEN_BUILTIN_LINE, EIGEN_BUILTIN_FUNCTION) \
143 : (void)0)
144
145#else // EIGEN_USE_CUSTOM_PLAIN_ASSERT
146
147// Use regular assert.
148#define eigen_plain_assert(condition) assert(condition)
149
150#endif // EIGEN_USE_CUSTOM_PLAIN_ASSERT
151
152#else // EIGEN_NO_DEBUG
153
154#define eigen_plain_assert(condition) ((void)0)
155
156#endif // EIGEN_NO_DEBUG
157
158#endif // EIGEN_CORE_UTIL_ASSERT_H
Namespace containing all symbols from the Eigen library.
Definition Core:137