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