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 {
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.
116 template <typename... EmptyArgs>
117 struct 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 
132 EIGEN_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
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:892
#define EIGEN_DONT_INLINE
Definition: Macros.h:853
void void_t
Definition: Meta.h:228
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
auto run(Kernel kernel, Args &&... args) -> decltype(kernel(args...))
Definition: gpu_test_helper.h:414
line
Definition: calibrate.py:103
Definition: Eigen_Colamd.h:49
void run(const string &dir_name, LinearSolver *linear_solver_pt, const unsigned nel_1d, bool mess_up_order)
Definition: two_d_poisson_compare_solvers.cc:317