Assert.h
Go to the documentation of this file.
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 
78 namespace Eigen {
79 namespace internal {
80 
81 // Generic default assert handler.
82 template<typename EnableIf = void, typename... EmptyArgs>
83 struct assert_handler_impl {
85  static inline void run(const char* expression, const char* file, unsigned line, 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",
91  file == nullptr ? "<file>" : file,
92  line,
93  function == nullptr ? "<function>" : function,
94  expression);
95 #endif
96  __trap();
97 
98 #else // EIGEN_GPU_COMPILE_PHASE
99 
100  // Print to stderr and abort, as specified in <cassert>.
101 #ifndef EIGEN_NO_IO
102  fprintf(stderr, "Assertion failed at %s:%u in %s: %s\n",
103  file == nullptr ? "<file>" : file,
104  line,
105  function == nullptr ? "<function>" : function,
106  expression);
107 #endif
108  std::abort();
109 
110 #endif // EIGEN_GPU_COMPILE_PHASE
111  }
112 };
113 
114 // Use POSIX __assert_fail handler when available.
115 //
116 // This allows us to integrate with systems that have custom handlers.
117 //
118 // NOTE: this handler is not always available on all POSIX systems (otherwise
119 // we could simply test for __unix__ or similar). The handler function name
120 // seems to depend on the specific toolchain implementation, and differs between
121 // compilers, platforms, OSes, etc. Hence, we detect support via SFINAE.
122 template<typename... EmptyArgs>
123 struct assert_handler_impl<
124  void_t<decltype(__assert_fail(
125  (const char*)nullptr, // expression
126  (const char*)nullptr, // file
127  0, // line
128  (const char*)nullptr, // function
129  std::declval<EmptyArgs>()... // Empty substitution required for SFINAE.
130  ))>, EmptyArgs... > {
132  static inline void run(const char* expression, const char* file, unsigned line, const char* function) {
133  // GCC requires this call to be dependent on the template parameters.
134  __assert_fail(expression, file, line, function, std::declval<EmptyArgs>()...);
135  }
136 };
137 
139 inline void __assert_handler(const char* expression, const char* file, unsigned line, const char* function) {
140  assert_handler_impl<>::run(expression, file, line, function);
141 }
142 
143 } // namespace internal
144 } // namespace Eigen
145 
146 #define eigen_plain_assert(expression) \
147  (EIGEN_PREDICT_FALSE(!(expression)) ? \
148  Eigen::internal::__assert_handler(#expression, \
149  EIGEN_BUILTIN_FILE, \
150  EIGEN_BUILTIN_LINE, \
151  EIGEN_BUILTIN_FUNCTION) : (void)0)
152 
153 #else // EIGEN_USE_CUSTOM_PLAIN_ASSERT
154 
155 // Use regular assert.
156 #define eigen_plain_assert(condition) assert(condition)
157 
158 #endif // EIGEN_USE_CUSTOM_PLAIN_ASSERT
159 
160 #else // EIGEN_NO_DEBUG
161 
162 #define eigen_plain_assert(condition) ((void)0)
163 
164 #endif // EIGEN_NO_DEBUG
165 
166 #endif // EIGEN_CORE_UTIL_ASSERT_H
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define EIGEN_DONT_INLINE
Definition: Macros.h:844
void void_t
Definition: Meta.h:157
: InteropHeaders
Definition: Core:139