1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qassert.h" |
5 | |
6 | #include <QtCore/qlogging.h> |
7 | |
8 | #include <cstdio> |
9 | #include <exception> |
10 | #ifndef QT_NO_EXCEPTIONS |
11 | #include <new> |
12 | #endif |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | /*! |
17 | \macro void Q_ASSERT(bool test) |
18 | \relates <QtAssert> |
19 | |
20 | Prints a warning message containing the source code file name and |
21 | line number if \a test is \c false. |
22 | |
23 | Q_ASSERT() is useful for testing pre- and post-conditions |
24 | during development. It does nothing if \c QT_NO_DEBUG was defined |
25 | during compilation. |
26 | |
27 | Example: |
28 | |
29 | \snippet code/src_corelib_global_qglobal.cpp 17 |
30 | |
31 | If \c b is zero, the Q_ASSERT statement will output the following |
32 | message using the qFatal() function: |
33 | |
34 | \snippet code/src_corelib_global_qglobal.cpp 18 |
35 | |
36 | \sa Q_ASSERT_X(), qFatal(), {Debugging Techniques} |
37 | */ |
38 | |
39 | /*! |
40 | \macro void Q_ASSERT_X(bool test, const char *where, const char *what) |
41 | \relates <QtAssert> |
42 | |
43 | Prints the message \a what together with the location \a where, |
44 | the source file name and line number if \a test is \c false. |
45 | |
46 | Q_ASSERT_X is useful for testing pre- and post-conditions during |
47 | development. It does nothing if \c QT_NO_DEBUG was defined during |
48 | compilation. |
49 | |
50 | Example: |
51 | |
52 | \snippet code/src_corelib_global_qglobal.cpp 19 |
53 | |
54 | If \c b is zero, the Q_ASSERT_X statement will output the following |
55 | message using the qFatal() function: |
56 | |
57 | \snippet code/src_corelib_global_qglobal.cpp 20 |
58 | |
59 | \sa Q_ASSERT(), qFatal(), {Debugging Techniques} |
60 | */ |
61 | |
62 | /* |
63 | The Q_ASSERT macro calls this function when the test fails. |
64 | */ |
65 | void qt_assert(const char *assertion, const char *file, int line) noexcept |
66 | { |
67 | QMessageLogger(file, line, nullptr) |
68 | .fatal(msg: "ASSERT: \"%s\" in file %s, line %d" , assertion, file, line); |
69 | } |
70 | |
71 | /* |
72 | The Q_ASSERT_X macro calls this function when the test fails. |
73 | */ |
74 | void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept |
75 | { |
76 | QMessageLogger(file, line, nullptr) |
77 | .fatal(msg: "ASSERT failure in %s: \"%s\", file %s, line %d" , where, what, file, line); |
78 | } |
79 | |
80 | /*! |
81 | \macro void Q_CHECK_PTR(void *pointer) |
82 | \relates <QtAssert> |
83 | |
84 | If \a pointer is \nullptr, prints a message containing the source |
85 | code's file name and line number, saying that the program ran out |
86 | of memory and aborts program execution. It throws \c std::bad_alloc instead |
87 | if exceptions are enabled. |
88 | |
89 | Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were |
90 | defined during compilation. Therefore you must not use Q_CHECK_PTR to check |
91 | for successful memory allocations because the check will be disabled in |
92 | some cases. |
93 | |
94 | Example: |
95 | |
96 | \snippet code/src_corelib_global_qglobal.cpp 21 |
97 | |
98 | \sa qWarning(), {Debugging Techniques} |
99 | */ |
100 | |
101 | /*! |
102 | \fn template <typename T> T *q_check_ptr(T *p) |
103 | \relates <QtAssert> |
104 | |
105 | Uses Q_CHECK_PTR on \a p, then returns \a p. |
106 | |
107 | This can be used as an inline version of Q_CHECK_PTR. |
108 | */ |
109 | |
110 | /*! |
111 | \internal |
112 | The Q_CHECK_PTR macro calls this function if an allocation check |
113 | fails. |
114 | */ |
115 | void qt_check_pointer(const char *n, int l) noexcept |
116 | { |
117 | // make separate printing calls so that the first one may flush; |
118 | // the second one could want to allocate memory (fputs prints a |
119 | // newline and stderr auto-flushes). |
120 | fputs(s: "Out of memory" , stderr); |
121 | fprintf(stderr, format: " in %s, line %d\n" , n, l); |
122 | |
123 | std::terminate(); |
124 | } |
125 | |
126 | /* |
127 | \internal |
128 | Allows you to throw an exception without including <new> |
129 | Called internally from Q_CHECK_PTR on certain OS combinations |
130 | */ |
131 | void qBadAlloc() |
132 | { |
133 | #ifndef QT_NO_EXCEPTIONS |
134 | throw std::bad_alloc(); |
135 | #else |
136 | std::terminate(); |
137 | #endif |
138 | } |
139 | |
140 | /*! |
141 | \macro void Q_ASSUME(bool expr) |
142 | \deprecated |
143 | \relates <QtAssert> |
144 | \since 5.0 |
145 | |
146 | Causes the compiler to assume that \a expr is \c true. |
147 | |
148 | This macro is known to produce worse code than when no assumption was |
149 | inserted in the code, with some compiler versions. The arguments passed to |
150 | it are always evaluated, even in release mode, with some compilers and not |
151 | others, so application code needs to be aware of those possible differences |
152 | in behavior. |
153 | |
154 | Do not use it in new code. It is retained as-is for compatibility with old |
155 | code and will likely be removed in the next major version Qt. |
156 | |
157 | \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY() |
158 | */ |
159 | |
160 | /*! |
161 | \macro void Q_UNREACHABLE() |
162 | \relates <QtAssert> |
163 | \since 5.0 |
164 | |
165 | Tells the compiler that the current point cannot be reached by any |
166 | execution, so it may optimize any code paths leading here as dead code, as |
167 | well as code continuing from here. |
168 | |
169 | This macro is useful to mark impossible conditions. For example, given the |
170 | following enum: |
171 | |
172 | \snippet code/src_corelib_global_qglobal.cpp qunreachable-enum |
173 | |
174 | One can write a switch table like so: |
175 | |
176 | \snippet code/src_corelib_global_qglobal.cpp qunreachable-switch |
177 | |
178 | The advantage of inserting Q_UNREACHABLE() at that point is that the |
179 | compiler is told not to generate code for a shape variable containing that |
180 | value. If the macro is missing, the compiler will still generate the |
181 | necessary comparisons for that value. If the case label were removed, some |
182 | compilers could produce a warning that some enum values were not checked. |
183 | |
184 | By using this macro in impossible conditions, code coverage may be improved |
185 | as dead code paths may be eliminated. |
186 | |
187 | In debug builds the condition is enforced by an assert to facilitate debugging. |
188 | |
189 | \note Use the macro Q_UNREACHABLE_RETURN() to insert return statements for |
190 | compilers that need them, without causing warnings for compilers that |
191 | complain about its presence. |
192 | |
193 | \sa Q_ASSERT(), qFatal(), Q_UNREACHABLE_RETURN() |
194 | */ |
195 | |
196 | /*! |
197 | \macro void Q_UNREACHABLE_RETURN(...) |
198 | \relates <QtAssert> |
199 | \since 6.5 |
200 | |
201 | This is equivalent to |
202 | \code |
203 | Q_UNREACHABLE(); |
204 | return __VA_ARGS__; |
205 | \endcode |
206 | except it omits the return on compilers that would warn about it. |
207 | |
208 | \sa Q_UNREACHABLE() |
209 | */ |
210 | QT_END_NAMESPACE |
211 | |