| 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 | |