0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / Standard / Standard_Assert.hxx
1 // Created on: 2001-03-20
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef Standard_Assert_HeaderFile
17 #define Standard_Assert_HeaderFile
18
19 #include <Standard_ProgramError.hxx>
20
21 //!@file
22 //! This header file defines a set of ASSERT macros intended for use
23 //! in algorithms for debugging purposes and as a tool to organise
24 //! checks for abnormal situations in the uniform way.
25 //!
26 //! In contrast to C assert() function that terminates the process, these
27 //! macros provide choice of the action to be performed if assert failed,
28 //! thus allowing execution to continue when possible.
29 //! Except for the message for developer that appears only in Debug mode,
30 //! the macros behave in the same way in both Release and Debug modes.
31 //!
32 //!
33 //! The ASSERT macros differ in the way they react on a wrong situation:
34 //! - Standard_ASSERT_RAISE:  raises exception Standard_ProgramError
35 //! - Standard_ASSERT_RETURN: returns specified value (last argument may
36 //!                           be left empty to return void)
37 //! - Standard_ASSERT_SKIP:   does nothing
38 //! - Standard_ASSERT_VOID:   does nothing; even does not evaluate first arg
39 //!                           when in Release mode
40 //! - Standard_ASSERT_INVOKE: causes unconditional assert
41 //! - Standard_ASSERT:        base macro (used by other macros);
42 //!                           does operation indicated in argument "todo"
43 //!
44 //! The assertion is assumed to fail if the first argument is
45 //! evaluated to zero (false).
46 //! The first argument is evaluated by all macros except Standard_ASSERT_VOID
47 //! which does not evaluate first argument when in Release mode.
48 //! The mode is triggered by preprocessor macro _DEBUG: if it is defined,
49 //! Debug mode is assumed, Release otherwise.
50 //!
51 //! In debug mode, if condition is not satisfied the macros call 
52 //! Standard_ASSERT_INVOKE_ which:
53 //! - on Windows (under VC++), stops code execution and prompts to attach 
54 //!   debugger to the process immediately.
55 //! - on POSIX systems, prints message to cerr and raises signal SIGTRAP to stop 
56 //!   execution when under debugger (may terminate the process if not under debugger).
57 //!
58 //! The second argument (message) should be string constant ("...").
59 //!
60 //! The Standard_STATIC_ASSERT macro is to be used for compile time checks.
61 //! To use this macro, write:
62 //!
63 //!   Standard_STATIC_ASSERT(const_expression);
64 //!
65 //! If const_expression is false, a compiler error occurs.
66 //!
67 //! The macros are formed as functions and require semicolon at the end.
68
69 // Stub function used to make macros complete C++ operator 
70 inline void Standard_ASSERT_DO_NOTHING() {}
71
72 // User messages are activated in debug mode only
73 #ifdef _DEBUG
74   #if (defined(_WIN32) || defined(__WIN32__))
75     #if defined(_MSC_VER) || defined(__MINGW64__)
76       // VS-specific intrinsic
77       #define Standard_ASSERT_DBGBREAK_() __debugbreak()
78     #else
79       // WinAPI function
80       #include <windows.h>
81       #define Standard_ASSERT_DBGBREAK_() DebugBreak()
82     #endif
83   #else
84     // POSIX systems
85     #include <signal.h>
86     #define Standard_ASSERT_DBGBREAK_() raise(SIGTRAP)
87   #endif
88
89   #if defined(_MSC_VER)
90     #include <crtdbg.h>
91     // use debug CRT built-in function that show up message box to user
92     // with formatted assert description and 3 possible actions
93     inline Standard_Boolean Standard_ASSERT_REPORT_ (const char* theFile,
94                                                      const int   theLine,
95                                                      const char* theExpr,
96                                                      const char* theDesc)
97     {
98       // 1 means user pressed Retry button
99       return _CrtDbgReport (_CRT_ASSERT, theFile, theLine, NULL,
100                             "%s\n(Condition: \"%s\")\n", theDesc, theExpr) == 1;
101     }
102   #else
103     // just log assertion description into standard error stream
104     inline Standard_Boolean Standard_ASSERT_REPORT_ (const char* theFile,
105                                                      const int   theLine,
106                                                      const char* theExpr,
107                                                      const char* theDesc)
108     {
109       std::cerr << "ERROR: statement '" << theExpr << "' is not TRUE!\n"
110                 << "\nFile: '"   << theFile << "'"
111                 << "\nLine: "    << theLine << "\n";
112       if (theDesc != NULL && *theDesc != '\0')
113         std::cerr << "Description: " << theDesc << "\n";
114
115       std::cerr << std::flush;
116       return Standard_True;
117     }
118   #endif
119
120   // report issue and add debug breakpoint or abort execution
121   #define Standard_ASSERT_INVOKE_(theExpr, theDesc) \
122     if (Standard_ASSERT_REPORT_ (__FILE__, __LINE__, #theExpr, theDesc)) { Standard_ASSERT_DBGBREAK_(); } \
123     else Standard_ASSERT_DO_NOTHING()
124
125   // Basic ASSERT macros
126   #define Standard_ASSERT(theExpr, theDesc, theAction)                        \
127     if (!(theExpr)) { Standard_ASSERT_INVOKE_(theExpr, theDesc); theAction; } \
128     else Standard_ASSERT_DO_NOTHING()
129   #define Standard_ASSERT_SKIP(theExpr, theDesc) \
130     Standard_ASSERT(theExpr, theDesc,)
131   #define Standard_ASSERT_VOID(theExpr, theDesc) \
132     Standard_ASSERT(theExpr, theDesc,)
133 #else
134
135   // dummy block
136   #define Standard_ASSERT_INVOKE_(theExpr, theDesc) Standard_ASSERT_DO_NOTHING()
137
138   // Basic ASSERT macros
139   #define Standard_ASSERT(theExpr, theDesc, theAction) \
140     if (!(theExpr)) { theAction; }                     \
141     else Standard_ASSERT_DO_NOTHING()
142   #define Standard_ASSERT_SKIP(theExpr, theDesc) theExpr
143   #define Standard_ASSERT_VOID(theExpr, theDesc) Standard_ASSERT_DO_NOTHING()
144
145 #endif
146
147 //! Raise exception (Standard_ProgramError) with the provided message
148 #define Standard_ASSERT_RAISE(theExpr, theDesc)                                  \
149   Standard_ASSERT(theExpr, theDesc, throw Standard_ProgramError(                \
150       "*** ERROR: ASSERT in file '" __FILE__ "': \n" theDesc " (" #theExpr ")" ) )
151
152 //! Return from the current function with specified value (empty
153 //! if the function returns void)
154 #define Standard_ASSERT_RETURN(theExpr, theDesc, theReturnValue) \
155   Standard_ASSERT(theExpr, theDesc, return theReturnValue)
156
157 //! Raise debug message
158 #define Standard_ASSERT_INVOKE(theDesc) Standard_ASSERT_INVOKE_(always, theDesc)
159
160 //! Static assert --
161 //! empty default template
162 template <bool condition> 
163 struct Standard_Static_Assert { };
164
165 //! Static assert -- specialization for condition being true
166 template <>
167 struct Standard_Static_Assert<true>
168 {
169   static void assert_ok() {}
170 };
171
172 //! Cause compiler error if argument is not constant expression or
173 //! evaluates to false
174 #define Standard_STATIC_ASSERT(theExpr)     \
175         Standard_Static_Assert<theExpr>::assert_ok();
176
177 #endif // Standard_Assert_HeaderFile
178
179 #ifdef _MSC_VER
180   #pragma once
181 #endif