1 /** @file gsDebug.h
2
3 @brief This file contains the debugging and messaging system of G+Smo.
4
5 This file is part of the G+Smo library.
6
7 This Source Code Form is subject to the terms of the Mozilla Public
8 License, v. 2.0. If a copy of the MPL was not distributed with this
9 file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11 Author(s): A. Mantzaflaris
12 */
13
14
15 // Start DEBUG_GROUP of Doxygen
16 /** @{ */
17
18 #pragma once
19
20 #include <iostream>
21 #include <sstream>
22 #include <iomanip>
23 #include <stdexcept>
24 #include <typeinfo>
25
26 // See also about memory leak detection:
27 // http://msdn.microsoft.com/en-us/library/e5ewb1h3%28v=vs.90%29.aspx
28 #if _MSC_VER //>= 1400
29 #include <crtdbg.h>
30 //#include <errno.h>
31 #endif
32
33 //#ifdef GISMO_EXTRA_DEBUG
34 // #include <misc/gsStackWalker.h>
35 //#endif
36
37 namespace gismo {
38
39 /** Logging messages:
40 * gsInfo is ment to be the standard output stream, like for the output of the
41 * executables. In general, the library should not write to gsInfo.
42 */
43 #define gsInfo std::cout
44
45 /** Logging messages:
46 * gsWarn is for warnings, eg, for missing functionality or problem in the input.
47 *
48 * Note that gsWarn cannot be given as a parameter to another function.
49 */
50 #define gsWarn std::cout<<"Warning: "
51 //#define gsWarn std::cerr
52
53 /** Logging messages:
54 * gsDebug and gsDebugVar(.) are for debugging messages and are enabled in debug
55 * mode only.
56 *
57 * Note that gsDebug cannot be given as a parameter to another function.
58 */
59 #ifndef NDEBUG
60
61 #define gsDebug std::cout<<"GISMO_DEBUG: "
62
63 #define gsDebugVar(variable) gsDebug << (strrchr(__FILE__, '/') ? \
64 strrchr(__FILE__, '/') + 1 : __FILE__) <<":"<< \
65 __LINE__<< ", "#variable": \n"<<(variable)<<"\n"
66 #define gsDebugIf(cond,variable) if (cond) gsDebug <<"[ "#cond" ] -- "<< \
67 (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) \
68 <<":"<<__LINE__<< ", "#variable": \n"<<(variable)<<"\n"
69 #else
70 #define gsDebug if (0) std::cout
71 #define gsDebugVar(variable)
72 #define gsDebugIf(cond,variable)
73 #endif
74
75 /**
76 * Used for optional inclusion of .hpp header files in the .h files.
77 * Allows to drop dependencies on the .hpp files when using
78 * GISMO_BUILD_LIB for compiling a library instance.
79 * When compiling as a pure template library CMake will detect
80 * dependency on .hpp files.
81 */
82 #define GISMO_HPP_HEADER(x) #x
83
84 /**
85 * Runtime assertions which display a message
86 *
87 */
88 #ifndef NDEBUG
89 # define GISMO_ASSERT(cond, message) do if(!(cond)) {std::stringstream _m_;\
90 _m_<<"GISMO_ASSERT `"<<#cond<<"` "<<message<<"\n"<<__FILE__<<", line "\
91 <<__LINE__<<" ("<<__FUNCTION__<<")"; \
92 throw std::logic_error(_m_.str()); } while(false)
93 #else
94 # define GISMO_ASSERT(condition, message)
95 #endif
96
97 /**
98 * Runtime check and display error message. This command is the same as
99 * GISMO_ASSERT but it is executed in release builds as well.
100 *
101 */
102 #define GISMO_ENSURE(cond, message) do if(!(cond)) {std::stringstream _m_; \
103 _m_<<"GISMO_ENSURE `"<<#cond<<"` "<<message<<"\n"<<__FILE__<<", line " \
104 <<__LINE__<<" ("<< __FUNCTION__<< ")"; \
105 throw std::runtime_error(_m_.str());} while(false)
106
107 /**
108 * Denote a variable as unused, used to silence warnings in release
109 * mode builds.
110 *
111 */
112 #define GISMO_UNUSED(x) static_cast<void>(x)
113
114 /**
115 * Runtime error message
116 *
117 */
118 #define GISMO_ERROR(message) do {std::stringstream _m_; _m_<<"GISMO_ERROR " \
119 <<message<<"\n"<<__FILE__<<", line " <<__LINE__<<" ("<<__FUNCTION__<<")";\
120 throw std::runtime_error(_m_.str());} while(false)
121
122 /**
123 * Runtime "no implementation" error happens when the user calls a
124
125 * virtual member function without a default implementation.
126 */
127
128 // TO DO: for GCC __PRETTY_FUNC__ is better
129 #define GISMO_NO_IMPLEMENTATION {std::stringstream _m_; \
130 _m_<<"Virtual member function `"<<__FUNCTION__<<"` has not been implemented\n" \
131 <<__FILE__<<", line "<<__LINE__<<"\n"<<typeid(*this).name(); \
132 throw std::runtime_error(_m_.str());}
133
134 /*
135 #ifdef _MSC_VER
136 #include <float.h>
137 template <typename T> int isnan (T a) {return _isnan(a); }
138 template <typename T> int isfinite(T a){return _finite(a);}
139 template <typename T> bool isinf(T a) {return (_FPCLASS_PINF|_FPCLASS_NINF) & _fpclass(a);}
140 #else
141 #ifdef _INTEL_COMPILER
142 #include <mathimf.h>
143 #else
144 using std::isnan;
145 using std::isfinite;
146 using std::isinf;
147 #endif
148 */
149 /**
150 Check if a floating point number is different than NAN (not a number)
151
152 See https://en.wikipedia.org/wiki/Floating_point#Special_values
153 and https://en.wikipedia.org/wiki/NaN
154 */
gsIsnumber(T a)155 template <typename T> bool gsIsnumber(T a) {return a == a;}
gsIsnan(T a)156 template <typename T> bool gsIsnan (T a) {return a != a;}
157 /**
158 Check if a flaoting point number is different than INF
159
160 See https://en.wikipedia.org/wiki/Floating_point#Special_values
161 */
gsIsfinite(T a)162 template <typename T> bool gsIsfinite(T a) {return (a - a) == (a - a);}
163
164 }//namespace gismo
165
166 /*
167 Disable debug/abort popup windows on MS Windows
168
169 See http://msdn.microsoft.com/en-us/library/1y71x448.aspx
170
171 You might also need to disable "error reporting" on your windows
172 system for popup-free runs.
173 */
174 #if _MSC_VER //>= 1400
175 static const int gismo_CrtSetReportMode = _CrtSetReportMode(
176 _CRT_ASSERT, _CRTDBG_MODE_FILE );
177 static const _HFILE gismo_CrtSetReportFile = _CrtSetReportFile(
178 _CRT_ASSERT, _CRTDBG_FILE_STDERR );
179 static const int gismo_set_abort_behavior = _set_abort_behavior(
180 0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
181 #endif
182
183 /*
184 Disable some Warnings
185 */
186
187 #ifdef _MSC_VER
188 // 4100 - unreferenced formal parameter
189 // 4101 - unreferenced local variable
190 // 4127 - conditional expression is constant (triggered by assertion macros)
191 // 4146 - unary minus operator applied to unsigned type, result still unsigned
192 // 4181 - qualifier applied to reference type ignored
193 // 4211 - nonstandard extension used : redefined extern to static
194 // 4231 - nonstandard extension used: extern before template explicit instantiation
195 // 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data
196 // 4251 - needs to have dll-interface to be used by clients of class
197 // 4273 - QtAlignedMalloc, inconsistent DLL linkage
198 // 4275 - non dll-interface base
199 // 4324 - structure was padded due to declspec(align())
200 // 4428 - universal-character-name encountered in source
201 // 4503 - decorated name length exceeded
202 // 4505 - unreferenced local function has been removed
203 // 4512 - assignment operator could not be generated
204 // 4522 - 'class' : multiple assignment operators specified
205 // 4566 - character represented by universal-character-name cannot be represented in the current code page
206 // 4661 - no definition available
207 // 4700 - uninitialized local variable 'xyz' used
208 // 4702 - unreachable code
209 // 4714 - function marked as __forceinline not inlined
210 // 4717 - 'function' : recursive on all control paths, function will cause runtime stack overflow
211 // 4789 - destination of memory copy is too small (for Eigen)
212 // 4996 - 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
213 // 4510 - default constructor could not be generated
214 // 4610 - user defined constructor required
215 #pragma warning( push )
216 #pragma warning( disable : 4100 4127 4146 4231 4251 4428 4275 4503 4505 4512 4566 4661 4714 4789 4996 4510 4610)
217
218 #elif defined __INTEL_COMPILER
219 // 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
220 // ICC 12 generates this warning even without any inline keyword, when defining class methods 'inline' i.e. inside of class body
221 // typedef that may be a reference type.
222 // 279 - controlling expression is constant
223 // ICC 12 generates this warning on assert(constant_expression_depending_on_template_params) and frankly this is a legitimate use case.
224 // 161 - unrecognized pragma
225 // 175 - subscript out of range
226 // to avoid warnings on #pragma GCC diagnostic
227 #pragma warning push
228 #pragma warning disable 2196 279 161 175
229
230 #elif defined __clang__
231 // -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant
232 // -Wbind-to-temporary-copy - warning: Warn about an unusable copy constructor when binding a reference to a temporary
233 #pragma clang diagnostic push
234 #pragma clang diagnostic ignored "-Wconstant-logical-operand"
235 #pragma clang diagnostic ignored "-Wbind-to-temporary-copy"
236
237 #elif defined __GNUC__ // major version >=4
238 // typedef locally defined but not used [-Wunused-local-typedefs]
239 #if ( __GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>7) )
240 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
241 #endif
242
243 #if (__cplusplus < 201703L && __GNUC__>6)
244 // mangled name will change in C++17 because the exception
245 // specification is part of a function type [-Wnoexcept-type]
246 #pragma GCC diagnostic ignored "-Wnoexcept-type"
247 #endif
248
249 #endif
250
251
252 /*
253 Compile-time assertions:
254
255 - in GISMO_STATIC_ASSERT(CONDITION,MSG) the parameter CONDITION
256 must be a compile time boolean expression, and MSG an error
257 message (string)
258
259 - define GISMO_NO_STATIC_ASSERT to disable them (and save
260 compilation time) in that case, the static assertion is
261 converted to a runtime assertion.
262
263 - GISMO_STATIC_ASSERT can only be used in function scope
264 */
265 #ifndef GISMO_NO_STATIC_ASSERT
266
267 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || _MSC_VER >= 1600
268
269 // Native static_assert is available
270 #define GISMO_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
271
272 #else // not C++11
273
274 namespace gismo {
275 namespace internal {
276
277 template<bool condition> struct static_assertion {};
278 template<> struct static_assertion<true> { enum { STATIC_ASSERTION_FAILED }; };
279
280 } // end namespace internal
281 } // end namespace gismo
282
283 // Specialized implementation for MSVC to avoid "conditional
284 // expression is constant" warnings. This implementation doesn't
285 // appear to work under GCC, hence the multiple implementations.
286 #ifdef _MSC_VER
287
288 #define GISMO_STATIC_ASSERT(CONDITION,MSG) \
289 {gismo::internal::static_assertion<bool(CONDITION)>::STATIC_ASSERTION_FAILED;}
290
291 #else
292
293 #define GISMO_STATIC_ASSERT(CONDITION,MSG) \
294 if (gismo::internal::static_assertion<bool(CONDITION)>::STATIC_ASSERTION_FAILED) {}
295
296 #endif
297
298 #endif // not C++11
299
300 #else // GISMO_NO_STATIC_ASSERT
301
302 #define GISMO_STATIC_ASSERT(CONDITION,MSG) GISMO_ASSERT(CONDITION, #MSG);
303
304 #endif // GISMO_NO_STATIC_ASSERT
305
306
307
308 #ifdef GISMO_WARNINGS
309 //#pragma message("G+Smo Warnings ON")
310 #ifdef __GNUC__
311 #define GISMO_DEPRECATED __attribute__((deprecated))
312 #elif defined(_MSC_VER)
313 #define GISMO_DEPRECATED __declspec(deprecated)
314 #else
315 #define GISMO_DEPRECATED
316 #endif
317 #else
318 #define GISMO_DEPRECATED
319 #endif
320
321
322 // Next line closes the DEBUG_GROUP of Doxygen
323 /** @} */
324