1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // --------------------------------------------------------------------------- |
5 | // Check.h |
6 | // |
7 | |
8 | // |
9 | // Assertion checking infrastructure |
10 | // --------------------------------------------------------------------------- |
11 | |
12 | |
13 | #ifndef CHECK_H_ |
14 | #define CHECK_H_ |
15 | |
16 | #include "static_assert.h" |
17 | #include "daccess.h" |
18 | |
19 | #ifdef _DEBUG |
20 | |
21 | #ifdef _MSC_VER |
22 | // Make sure we can recurse deep enough for FORCEINLINE |
23 | #pragma inline_recursion(on) |
24 | #pragma inline_depth(16) |
25 | #pragma warning(disable:4714) |
26 | #endif // _MSC_VER |
27 | |
28 | #if !defined(DISABLE_CONTRACTS) |
29 | #define CHECK_INVARIANTS 1 |
30 | #define VALIDATE_OBJECTS 1 |
31 | #endif |
32 | |
33 | #endif // _DEBUG |
34 | |
35 | #if defined(_DEBUG) && !defined(DACCESS_COMPILE) |
36 | #define _DEBUG_IMPL 1 |
37 | #endif |
38 | |
39 | #ifdef _DEBUG |
40 | #define DEBUG_ARG(x) , x |
41 | #else |
42 | #define DEBUG_ARG(x) |
43 | #endif |
44 | |
45 | #define CHECK_STRESS 1 |
46 | |
47 | //-------------------------------------------------------------------------------- |
48 | // A CHECK is an object which encapsulates a potential assertion |
49 | // failure. It not only contains the result of the check, but if the check fails, |
50 | // also records information about the condition and call site. |
51 | // |
52 | // CHECK also serves as a holder to prevent recursive CHECKS. These can be |
53 | // particularly common when putting preconditions inside predicates, especially |
54 | // routines called by an invariant. |
55 | // |
56 | // Note that using CHECK is perfectly efficient in a free build - the CHECK becomes |
57 | // a simple string constant pointer (typically either NULL or (LPCSTR)1, although some |
58 | // check failures may include messages) |
59 | // |
60 | // NOTE: you should NEVER use the CHECK class API directly - use the macros below. |
61 | //-------------------------------------------------------------------------------- |
62 | |
63 | class SString; |
64 | |
65 | class CHECK |
66 | { |
67 | protected: |
68 | // On retail, this is a pointer to a string literal, null or (LPCSTR)1. |
69 | // On debug, this is a pointer to dynamically allocated memory - that |
70 | // lets us have formatted strings in debug builds. |
71 | LPCSTR m_message; |
72 | |
73 | #ifdef _DEBUG |
74 | LPCSTR m_condition; |
75 | LPCSTR m_file; |
76 | INT m_line; |
77 | LONG *m_pCount; |
78 | |
79 | // Keep leakage counters. |
80 | static size_t s_cLeakedBytes; |
81 | static size_t s_cNumFailures; |
82 | #endif |
83 | |
84 | static BOOL s_neverEnforceAsserts; |
85 | |
86 | public: // !!! NOTE: Called from macros only!!! |
87 | |
88 | // If we are not in a check, return TRUE and PushCheck; otherwise return FALSE |
89 | BOOL EnterAssert(); |
90 | |
91 | // Pops check count |
92 | void LeaveAssert(); |
93 | |
94 | // Just return if we are in a check |
95 | BOOL IsInAssert(); |
96 | |
97 | // Should we skip enforcing asserts |
98 | static BOOL EnforceAssert(); |
99 | |
100 | static BOOL EnforceAssert_StaticCheckOnly(); |
101 | |
102 | static void ResetAssert(); |
103 | |
104 | #ifdef _MSC_VER |
105 | #pragma warning(push) |
106 | #pragma warning(disable:4702) // Disable bogus unreachable code warning |
107 | #endif // _MSC_VER |
108 | CHECK() : m_message(NULL) |
109 | #ifdef _DEBUG |
110 | , m_condition (NULL) |
111 | , m_file(NULL) |
112 | , m_line(NULL) |
113 | , m_pCount(NULL) |
114 | #endif |
115 | {} |
116 | #ifdef _MSC_VER |
117 | #pragma warning(pop) |
118 | #endif // _MSC_VER |
119 | |
120 | // Fail records the result of a condition check. Can take either a |
121 | // boolean value or another check result |
122 | BOOL Fail(BOOL condition); |
123 | BOOL Fail(const CHECK &check); |
124 | |
125 | // Setup records context info after a failure. |
126 | void Setup(LPCSTR message DEBUG_ARG(LPCSTR condition) DEBUG_ARG(LPCSTR file) DEBUG_ARG(INT line)); |
127 | static LPCSTR FormatMessage(LPCSTR messageFormat, ...); |
128 | |
129 | // Trigger triggers the actual check failure. The trigger may provide a reason |
130 | // to include in the failure message. |
131 | void Trigger(LPCSTR reason); |
132 | |
133 | // Finally, convert to a BOOL to allow just testing the result of a Check function |
134 | operator BOOL(); |
135 | |
136 | BOOL operator!(); |
137 | |
138 | CHECK &operator()() { return *this; } |
139 | |
140 | static inline const CHECK OK() { |
141 | return CHECK(); |
142 | } |
143 | |
144 | static void SetAssertEnforcement(BOOL value); |
145 | |
146 | static void ReleaseTls(void* pCountTLS); |
147 | |
148 | private: |
149 | static LONG* InitTls(); |
150 | #ifdef _DEBUG |
151 | static LPCSTR AllocateDynamicMessage(const SString &s); |
152 | #endif |
153 | }; |
154 | |
155 | |
156 | //-------------------------------------------------------------------------------- |
157 | // These CHECK macros are the correct way to propagate an assertion. These |
158 | // routines are designed for use inside "Check" routines. Such routines may |
159 | // be Invariants, Validate routines, or any other assertional predicates. |
160 | // |
161 | // A Check routine should return a value of type CHECK. |
162 | // |
163 | // It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate |
164 | // control flow) and should end with CHECK_OK() if all other checks pass. |
165 | // |
166 | // It may contain a CONTRACT_CHECK contract, but this is only appropriate if the |
167 | // check is used for non-assertional purposes (otherwise the contract will never execute). |
168 | // Note that CONTRACT_CHECK contracts do not support postconditions. |
169 | // |
170 | // CHECK: Check the given condition, return a CHECK failure if FALSE |
171 | // CHECK_MSG: Same, but include a message paramter if the check fails |
172 | // CHECK_OK: Return a successful check value; |
173 | //-------------------------------------------------------------------------------- |
174 | |
175 | #ifdef _DEBUG |
176 | #define DEBUG_ONLY_MESSAGE(msg) msg |
177 | #else |
178 | // On retail, we don't want to add a bunch of string literals to the image, |
179 | // so we just use the same one everywhere. |
180 | #define DEBUG_ONLY_MESSAGE(msg) ((LPCSTR)1) |
181 | #endif |
182 | |
183 | #define CHECK_MSG_EX(_condition, _message, _RESULT) \ |
184 | do \ |
185 | { \ |
186 | CHECK _check; \ |
187 | if (_check.Fail(_condition)) \ |
188 | { \ |
189 | ENTER_DEBUG_ONLY_CODE; \ |
190 | _check.Setup(DEBUG_ONLY_MESSAGE(_message) \ |
191 | DEBUG_ARG(#_condition) \ |
192 | DEBUG_ARG(__FILE__) \ |
193 | DEBUG_ARG(__LINE__)); \ |
194 | _RESULT(_check); \ |
195 | LEAVE_DEBUG_ONLY_CODE; \ |
196 | } \ |
197 | } while (0) |
198 | |
199 | #define RETURN_RESULT(r) return r |
200 | |
201 | #define CHECK_MSG(_condition, _message) \ |
202 | CHECK_MSG_EX(_condition, _message, RETURN_RESULT) |
203 | |
204 | #define CHECK(_condition) \ |
205 | CHECK_MSG(_condition, "") |
206 | |
207 | #define CHECK_MSGF(_condition, _args) \ |
208 | CHECK_MSG(_condition, CHECK::FormatMessage _args) |
209 | |
210 | #define CHECK_FAIL(_message) \ |
211 | CHECK_MSG(FALSE, _message); UNREACHABLE() |
212 | |
213 | #define CHECK_FAILF(_args) \ |
214 | CHECK_MSGF(FALSE, _args); UNREACHABLE() |
215 | |
216 | #define CHECK_OK \ |
217 | return CHECK::OK() |
218 | |
219 | //-------------------------------------------------------------------------------- |
220 | // ASSERT_CHECK is the proper way to trigger a check result. If the CHECK |
221 | // has failed, the diagnostic assertion routines will fire with appropriate |
222 | // context information. |
223 | // |
224 | // Note that the condition may either be a raw boolean expression or a CHECK result |
225 | // returned from a Check routine. |
226 | // |
227 | // Recursion note: ASSERT_CHECKs are only performed if there is no current check in |
228 | // progress. |
229 | //-------------------------------------------------------------------------------- |
230 | |
231 | #ifndef ENTER_DEBUG_ONLY_CODE |
232 | #define ENTER_DEBUG_ONLY_CODE |
233 | #endif |
234 | |
235 | #ifndef LEAVE_DEBUG_ONLY_CODE |
236 | #define LEAVE_DEBUG_ONLY_CODE |
237 | #endif |
238 | |
239 | #define ASSERT_CHECK(_condition, _message, _reason) \ |
240 | do \ |
241 | { \ |
242 | CHECK _check; \ |
243 | if (_check.EnterAssert()) \ |
244 | { \ |
245 | ENTER_DEBUG_ONLY_CODE; \ |
246 | if (_check.Fail(_condition)) \ |
247 | { \ |
248 | _check.Setup(_message \ |
249 | DEBUG_ARG(#_condition) \ |
250 | DEBUG_ARG(__FILE__) \ |
251 | DEBUG_ARG(__LINE__)); \ |
252 | _check.Trigger(_reason); \ |
253 | } \ |
254 | LEAVE_DEBUG_ONLY_CODE; \ |
255 | _check.LeaveAssert(); \ |
256 | } \ |
257 | } while (0) |
258 | |
259 | // ex: ASSERT_CHECKF(1+2==4, "my reason", ("Woah %d", 1+3)); |
260 | // note that the double parenthesis, the 'args' param below will include one pair of parens. |
261 | #define ASSERT_CHECKF(_condition, _reason, _args) \ |
262 | ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason) |
263 | |
264 | //-------------------------------------------------------------------------------- |
265 | // INVARIANTS are descriptions of conditions which are always true at well defined |
266 | // points of execution. Invariants may be checked by the caller or callee at any |
267 | // time as paranoia requires. |
268 | // |
269 | // There are really two flavors of invariant. The "public invariant" describes |
270 | // to the caller invariant behavior about the abstraction which is visible from |
271 | // the public API (and of course it should be expressible in that public API). |
272 | // |
273 | // The "internal invariant" (or representation invariant), on the other hand, is |
274 | // a description of the private implementation of the abstraction, which may examine |
275 | // internal state of the abstraction or use private entry points. |
276 | // |
277 | // Classes with invariants should introduce methods called |
278 | // void Invariant(); |
279 | // and |
280 | // void InternalInvariant(); |
281 | // to allow invariant checks. |
282 | //-------------------------------------------------------------------------------- |
283 | |
284 | #if CHECK_INVARIANTS |
285 | |
286 | template <typename TYPENAME> |
287 | CHECK CheckInvariant(TYPENAME &obj) |
288 | { |
289 | __if_exists(TYPENAME::Invariant) |
290 | { |
291 | CHECK(obj.Invariant()); |
292 | } |
293 | __if_exists(TYPENAME::InternalInvariant) |
294 | { |
295 | CHECK(obj.InternalInvariant()); |
296 | } |
297 | |
298 | CHECK_OK; |
299 | } |
300 | |
301 | #define CHECK_INVARIANT(o) \ |
302 | ASSERT_CHECK(CheckInvariant(o), NULL, "Invariant failure") |
303 | |
304 | #else |
305 | |
306 | #define CHECK_INVARIANT(o) do { } while (0) |
307 | |
308 | #endif |
309 | |
310 | //-------------------------------------------------------------------------------- |
311 | // VALIDATE is a check to be made on an object type which identifies a pointer as |
312 | // a valid instance of the object, by calling CheckPointer on it. Normally a null |
313 | // pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK)) |
314 | // may be used when a null pointer is acceptible. |
315 | // |
316 | // In addition to the null/non-null check, a type may provide a specific Check method |
317 | // for more sophisticated identification. In general, the Check method |
318 | // should answer the question |
319 | // "Is this a valid instance of its declared compile-time type?". For instance, if |
320 | // runtype type identification were supported for the type, it should be invoked here. |
321 | // |
322 | // Note that CheckPointer will also check the invariant(s) if appropriate, so the |
323 | // invariants should NOT be explicitly invoked from the Check method. |
324 | //-------------------------------------------------------------------------------- |
325 | |
326 | enum IsNullOK |
327 | { |
328 | NULL_NOT_OK = 0, |
329 | NULL_OK = 1 |
330 | }; |
331 | |
332 | #if CHECK_INVARIANTS |
333 | template <typename TYPENAME> |
334 | CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) |
335 | { |
336 | if (o == NULL) |
337 | { |
338 | CHECK_MSG(ok, "Illegal null pointer" ); |
339 | } |
340 | else |
341 | { |
342 | __if_exists(TYPENAME::Check) |
343 | { |
344 | CHECK(o->Check()); |
345 | } |
346 | } |
347 | |
348 | CHECK_OK; |
349 | } |
350 | |
351 | template <typename TYPENAME> |
352 | CHECK CheckValue(TYPENAME &val) |
353 | { |
354 | __if_exists(TYPENAME::Check) |
355 | { |
356 | CHECK(val.Check()); |
357 | } |
358 | |
359 | CHECK(CheckInvariant(val)); |
360 | |
361 | CHECK_OK; |
362 | } |
363 | #else // CHECK_INVARIANTS |
364 | |
365 | #ifdef _DEBUG_IMPL |
366 | // Don't defined these functions to be nops for the non-debug |
367 | // build as it may hide important checks |
368 | template <typename TYPENAME> |
369 | CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) |
370 | { |
371 | if (o == NULL) |
372 | { |
373 | CHECK_MSG(ok, "Illegal null pointer" ); |
374 | } |
375 | |
376 | CHECK_OK; |
377 | } |
378 | |
379 | template <typename TYPENAME> |
380 | CHECK CheckValue(TYPENAME &val) |
381 | { |
382 | CHECK_OK; |
383 | } |
384 | #endif |
385 | |
386 | #endif // CHECK_INVARIANTS |
387 | |
388 | #if VALIDATE_OBJECTS |
389 | |
390 | #define VALIDATE(o) \ |
391 | ASSERT_CHECK(CheckPointer(o), "Validation failure") |
392 | #define VALIDATE_NULL(o) \ |
393 | ASSERT_CHECK(CheckPointer(o, NULL_OK), "Validation failure") |
394 | |
395 | #else |
396 | |
397 | #define VALIDATE(o) do { } while (0) |
398 | #define VALIDATE_NULL(o) do { } while (0) |
399 | |
400 | #endif |
401 | |
402 | //-------------------------------------------------------------------------------- |
403 | // CONSISTENCY_CHECKS are ad-hoc assertions about the expected state of the program |
404 | // at a given time. A failure in one of these indicates a bug in the code. |
405 | // |
406 | // Note that the condition may either be a raw boolean expression or a CHECK result |
407 | // returned from a Check routine. |
408 | //-------------------------------------------------------------------------------- |
409 | |
410 | #define CONSISTENCY_CHECK(_condition) \ |
411 | CONSISTENCY_CHECK_MSG(_condition, "") |
412 | |
413 | #ifdef _DEBUG_IMPL |
414 | |
415 | #define CONSISTENCY_CHECK_MSG(_condition, _message) \ |
416 | ASSERT_CHECK(_condition, _message, "Consistency check failed") |
417 | |
418 | #define CONSISTENCY_CHECK_MSGF(_condition, args) \ |
419 | ASSERT_CHECKF(_condition, "Consistency check failed", args) |
420 | |
421 | #else |
422 | |
423 | #define CONSISTENCY_CHECK_MSG(_condition, _message) do { } while (0) |
424 | #define CONSISTENCY_CHECK_MSGF(_condition, args) do { } while (0) |
425 | |
426 | #endif |
427 | |
428 | //-------------------------------------------------------------------------------- |
429 | // SIMPLIFYING_ASSUMPTIONS are workarounds which are placed in the code to allow progress |
430 | // to be made in the case of difficult corner cases. These should NOT be left in the |
431 | // code; they are really just markers of things which need to be fixed. |
432 | // |
433 | // Note that the condition may either be a raw boolean expression or a CHECK result |
434 | // returned from a Check routine. |
435 | //-------------------------------------------------------------------------------- |
436 | |
437 | // Ex usage: |
438 | // SIMPLIFYING_ASSUMPTION(SomeExpression()); |
439 | #define SIMPLIFYING_ASSUMPTION(_condition) \ |
440 | SIMPLIFYING_ASSUMPTION_MSG(_condition, "") |
441 | |
442 | |
443 | // Helper for HRs. Will provide formatted message showing the failure code. |
444 | #define SIMPLIFYING_ASSUMPTION_SUCCEEDED(__hr) \ |
445 | { \ |
446 | HRESULT __hr2 = (__hr); \ |
447 | (void)__hr2; \ |
448 | SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(__hr2), ("HRESULT failed.\n Expected success.\n Actual=0x%x\n", __hr2)); \ |
449 | } |
450 | |
451 | #ifdef _DEBUG_IMPL |
452 | |
453 | // Ex usage: |
454 | // SIMPLIFYING_ASSUMPTION_MSG(SUCCEEDED(hr), "It failed!"); |
455 | #define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) \ |
456 | ASSERT_CHECK(_condition, _message, "Unhandled special case detected") |
457 | |
458 | // use a formatted string. Ex usage: |
459 | // SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(hr), ("Woah it failed! 0x%08x", hr)); |
460 | #define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) \ |
461 | ASSERT_CHECKF(_condition, "Unhandled special case detected", args) |
462 | |
463 | #else // !_DEBUG_IMPL |
464 | |
465 | #define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) do { } while (0) |
466 | #define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) do { } while (0) |
467 | |
468 | #endif // !_DEBUG_IMPL |
469 | |
470 | //-------------------------------------------------------------------------------- |
471 | // COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the |
472 | // condition is true. In a checked build these turn into asserts; |
473 | // in a free build they are passed through to the compiler to use in optimization. |
474 | //-------------------------------------------------------------------------------- |
475 | |
476 | #if defined(_PREFAST_) || defined(_PREFIX_) |
477 | #define COMPILER_ASSUME_MSG(_condition, _message) if (!(_condition)) __UNREACHABLE(); |
478 | #define COMPILER_ASSUME_MSGF(_condition, args) if (!(_condition)) __UNREACHABLE(); |
479 | #else |
480 | |
481 | #if defined(DACCESS_COMPILE) |
482 | #define COMPILER_ASSUME_MSG(_condition, _message) do { } while (0) |
483 | #define COMPILER_ASSUME_MSGF(_condition, args) do { } while (0) |
484 | #else |
485 | |
486 | #if defined(_DEBUG) |
487 | #define COMPILER_ASSUME_MSG(_condition, _message) \ |
488 | ASSERT_CHECK(_condition, _message, "Compiler optimization assumption invalid") |
489 | #define COMPILER_ASSUME_MSGF(_condition, args) \ |
490 | ASSERT_CHECKF(_condition, "Compiler optimization assumption invalid", args) |
491 | #else |
492 | #define COMPILER_ASSUME_MSG(_condition, _message) __assume(_condition) |
493 | #define COMPILER_ASSUME_MSGF(_condition, args) __assume(_condition) |
494 | #endif // _DEBUG |
495 | |
496 | #endif // DACCESS_COMPILE |
497 | |
498 | #endif // _PREFAST_ || _PREFIX_ |
499 | |
500 | |
501 | #define COMPILER_ASSUME(_condition) \ |
502 | COMPILER_ASSUME_MSG(_condition, "") |
503 | |
504 | |
505 | //-------------------------------------------------------------------------------- |
506 | // PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name |
507 | // for COMPILER_ASSUME_MSG |
508 | // In a checked build these turn into asserts; in a free build |
509 | // they are passed through to the compiler to use in optimization; |
510 | // via an __assume(_condition) optimization hint. |
511 | //-------------------------------------------------------------------------------- |
512 | |
513 | #define PREFIX_ASSUME_MSG(_condition, _message) \ |
514 | COMPILER_ASSUME_MSG(_condition, _message) |
515 | |
516 | #define PREFIX_ASSUME_MSGF(_condition, args) \ |
517 | COMPILER_ASSUME_MSGF(_condition, args) |
518 | |
519 | #define PREFIX_ASSUME(_condition) \ |
520 | COMPILER_ASSUME_MSG(_condition, "") |
521 | |
522 | #define PREFAST_ASSUME_MSG(_condition, _message) \ |
523 | COMPILER_ASSUME_MSG(_condition, _message) |
524 | |
525 | #define PREFAST_ASSUME_MSGF(_condition, args) \ |
526 | COMPILER_ASSUME_MSGF(_condition, args) |
527 | |
528 | #define PREFAST_ASSUME(_condition) \ |
529 | COMPILER_ASSUME_MSG(_condition, "") |
530 | |
531 | //-------------------------------------------------------------------------------- |
532 | // UNREACHABLE points are locations in the code which should not be able to be |
533 | // reached under any circumstances (e.g. a default in a switch which is supposed to |
534 | // cover all cases.). This macro tells the compiler this, and also embeds a check |
535 | // to make sure it is always true. |
536 | //-------------------------------------------------------------------------------- |
537 | |
538 | #define UNREACHABLE() \ |
539 | UNREACHABLE_MSG("") |
540 | |
541 | #ifdef __llvm__ |
542 | |
543 | // LLVM complains if a function does not return what it says. |
544 | #define UNREACHABLE_RET() do { UNREACHABLE(); return 0; } while (0) |
545 | #define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message); return 0; |
546 | |
547 | #else // __llvm__ |
548 | |
549 | #define UNREACHABLE_RET() UNREACHABLE() |
550 | #define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message) |
551 | |
552 | #endif // __llvm__ else |
553 | |
554 | #if defined(_MSC_VER) || defined(_PREFIX_) |
555 | #if defined(_TARGET_AMD64_) |
556 | // Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method |
557 | // which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT |
558 | // Remove when we get a VC compiler that fixes VSW 449170 |
559 | # define __UNREACHABLE() DebugBreak(); __assume(0); |
560 | #else |
561 | # define __UNREACHABLE() __assume(0) |
562 | #endif |
563 | #else |
564 | #define __UNREACHABLE() do { } while(true) |
565 | #endif |
566 | |
567 | #ifdef _DEBUG_IMPL |
568 | |
569 | // Note that the "do { } while (0)" syntax trick here doesn't work, as the compiler |
570 | // gives an error that the while(0) is unreachable code |
571 | #define UNREACHABLE_MSG(_message) \ |
572 | { \ |
573 | CHECK _check; \ |
574 | _check.Setup(_message, "<unreachable>", __FILE__, __LINE__); \ |
575 | _check.Trigger("Reached the \"unreachable\""); \ |
576 | } __UNREACHABLE() |
577 | |
578 | #else |
579 | |
580 | #define UNREACHABLE_MSG(_message) __UNREACHABLE() |
581 | |
582 | #endif |
583 | |
584 | |
585 | //-------------------------------------------------------------------------------- |
586 | // STRESS_CHECK represents a check which is included in a free build |
587 | // @todo: behavior on trigger |
588 | // |
589 | // Note that the condition may either be a raw boolean expression or a CHECK result |
590 | // returned from a Check routine. |
591 | // |
592 | // Since Retail builds don't allow formatted checks, there's no STRESS_CHECK_MSGF. |
593 | //-------------------------------------------------------------------------------- |
594 | |
595 | #if CHECK_STRESS |
596 | |
597 | #define STRESS_CHECK(_condition, _message) \ |
598 | ASSERT_CHECK(_condition, _message, "Stress Assertion Failure") |
599 | |
600 | #else |
601 | |
602 | #define STRESS_CHECK(_condition, _message) do { } while (0) |
603 | |
604 | #endif |
605 | |
606 | //-------------------------------------------------------------------------------- |
607 | // CONTRACT_CHECK is used to put contracts on Check function. Note that it does |
608 | // not support postconditions. |
609 | //-------------------------------------------------------------------------------- |
610 | |
611 | #define CONTRACT_CHECK CONTRACTL |
612 | #define CONTRACT_CHECK_END CONTRACTL_END |
613 | |
614 | //-------------------------------------------------------------------------------- |
615 | // CCHECK is used for Check functions which may fail due to out of memory |
616 | // or other transient failures. These failures should be ignored when doing |
617 | // assertions, but they cannot be ignored when the Check function is used in |
618 | // normal code. |
619 | // @todo: really crufty to have 2 sets of CHECK macros |
620 | //-------------------------------------------------------------------------------- |
621 | |
622 | #ifdef _DEBUG |
623 | |
624 | #define CCHECK_START \ |
625 | { \ |
626 | BOOL ___exception = FALSE; \ |
627 | BOOL ___transient = FALSE; \ |
628 | CHECK ___result = CHECK::OK(); \ |
629 | EX_TRY { |
630 | |
631 | #define CCHECK_END \ |
632 | } EX_CATCH { \ |
633 | if (___result.IsInAssert()) \ |
634 | { \ |
635 | ___exception = TRUE; \ |
636 | ___transient = GET_EXCEPTION()->IsTransient(); \ |
637 | } \ |
638 | else \ |
639 | EX_RETHROW; \ |
640 | } EX_END_CATCH(RethrowTerminalExceptions); \ |
641 | \ |
642 | if (___exception) \ |
643 | { \ |
644 | if (___transient) \ |
645 | CHECK_OK; \ |
646 | else \ |
647 | CHECK_FAIL("Nontransient exception occurred during check"); \ |
648 | } \ |
649 | CHECK(___result); \ |
650 | } |
651 | |
652 | #define CRETURN_RESULT(r) ___result = r |
653 | |
654 | #define CCHECK_MSG(_condition, _message) \ |
655 | CHECK_MSG_EX(_condition, _message, CRETURN_RESULT) |
656 | |
657 | #define CCHECK(_condition) \ |
658 | CCHECK_MSG(_condition, "") |
659 | |
660 | #define CCHECK_MSGF(_condition, _args) \ |
661 | CCHECK_MSG(_condition, CHECK::FormatMessage _args) |
662 | |
663 | #define CCHECK_FAIL(_message) \ |
664 | CCHECK_MSG(FALSE, _message); UNREACHABLE() |
665 | |
666 | #define CCHECK_FAILF(_args) \ |
667 | CCHECK_MSGF(FALSE, _args); UNREACHABLE() |
668 | |
669 | #else // _DEBUG |
670 | |
671 | #define CCHECK_START |
672 | #define CCHECK_END |
673 | |
674 | #define CCHECK CHECK |
675 | #define CCHECK_MSG CHECK_MSG |
676 | #define CCHECK_MSGF CHECK_MSGF |
677 | #define CCHECK_FAIL CHECK_FAIL |
678 | #define CCHECK_FAILF CHECK_FAILF |
679 | |
680 | #endif |
681 | |
682 | |
683 | |
684 | //-------------------------------------------------------------------------------- |
685 | // Common base level checks |
686 | //-------------------------------------------------------------------------------- |
687 | |
688 | CHECK CheckAlignment(UINT alignment); |
689 | |
690 | CHECK CheckAligned(UINT value, UINT alignment); |
691 | #if defined(_MSC_VER) |
692 | CHECK CheckAligned(ULONG value, UINT alignment); |
693 | #endif |
694 | CHECK CheckAligned(UINT64 value, UINT alignment); |
695 | CHECK CheckAligned(const void *address, UINT alignment); |
696 | |
697 | CHECK CheckOverflow(UINT value1, UINT value2); |
698 | #if defined(_MSC_VER) |
699 | CHECK CheckOverflow(ULONG value1, ULONG value2); |
700 | #endif |
701 | CHECK CheckOverflow(UINT64 value1, UINT64 value2); |
702 | CHECK CheckOverflow(PTR_CVOID address, UINT offset); |
703 | #if defined(_MSC_VER) |
704 | CHECK CheckOverflow(const void *address, ULONG offset); |
705 | #endif |
706 | CHECK CheckOverflow(const void *address, UINT64 offset); |
707 | |
708 | CHECK CheckUnderflow(UINT value1, UINT value2); |
709 | #if defined(_MSC_VER) |
710 | CHECK CheckUnderflow(ULONG value1, ULONG value2); |
711 | #endif |
712 | CHECK CheckUnderflow(UINT64 value1, UINT64 value2); |
713 | CHECK CheckUnderflow(const void *address, UINT offset); |
714 | #if defined(_MSC_VER) |
715 | CHECK CheckUnderflow(const void *address, ULONG offset); |
716 | #endif |
717 | CHECK CheckUnderflow(const void *address, UINT64 offset); |
718 | CHECK CheckUnderflow(const void *address, void *address2); |
719 | |
720 | CHECK CheckZeroedMemory(const void *memory, SIZE_T size); |
721 | |
722 | // These include overflow checks |
723 | CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset); |
724 | CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size); |
725 | |
726 | void WINAPI ReleaseCheckTls(LPVOID pTlsData); |
727 | |
728 | // ================================================================================ |
729 | // Inline definitions |
730 | // ================================================================================ |
731 | |
732 | #include "check.inl" |
733 | |
734 | #endif // CHECK_H_ |
735 | |