summaryrefslogtreecommitdiff
path: root/src/inc/check.h
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/inc/check.h
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/inc/check.h')
-rw-r--r--src/inc/check.h734
1 files changed, 734 insertions, 0 deletions
diff --git a/src/inc/check.h b/src/inc/check.h
new file mode 100644
index 0000000000..b1fdba9211
--- /dev/null
+++ b/src/inc/check.h
@@ -0,0 +1,734 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ---------------------------------------------------------------------------
+// Check.h
+//
+
+//
+// Assertion checking infrastructure
+// ---------------------------------------------------------------------------
+
+
+#ifndef CHECK_H_
+#define CHECK_H_
+
+#include "static_assert.h"
+#include "daccess.h"
+
+#ifdef _DEBUG
+
+#ifdef _MSC_VER
+// Make sure we can recurse deep enough for FORCEINLINE
+#pragma inline_recursion(on)
+#pragma inline_depth(16)
+#pragma warning(disable:4714)
+#endif // _MSC_VER
+
+#if !defined(DISABLE_CONTRACTS)
+#define CHECK_INVARIANTS 1
+#define VALIDATE_OBJECTS 1
+#endif
+
+#endif // _DEBUG
+
+#if defined(_DEBUG) && !defined(DACCESS_COMPILE)
+#define _DEBUG_IMPL 1
+#endif
+
+#ifdef _DEBUG
+#define DEBUG_ARG(x) , x
+#else
+#define DEBUG_ARG(x)
+#endif
+
+#define CHECK_STRESS 1
+
+//--------------------------------------------------------------------------------
+// A CHECK is an object which encapsulates a potential assertion
+// failure. It not only contains the result of the check, but if the check fails,
+// also records information about the condition and call site.
+//
+// CHECK also serves as a holder to prevent recursive CHECKS. These can be
+// particularly common when putting preconditions inside predicates, especially
+// routines called by an invariant.
+//
+// Note that using CHECK is perfectly efficient in a free build - the CHECK becomes
+// a simple string constant pointer (typically either NULL or (LPCSTR)1, although some
+// check failures may include messages)
+//
+// NOTE: you should NEVER use the CHECK class API directly - use the macros below.
+//--------------------------------------------------------------------------------
+
+class SString;
+
+class CHECK
+{
+protected:
+ // On retail, this is a pointer to a string literal, null or (LPCSTR)1.
+ // On debug, this is a pointer to dynamically allocated memory - that
+ // lets us have formatted strings in debug builds.
+ LPCSTR m_message;
+
+#ifdef _DEBUG
+ LPCSTR m_condition;
+ LPCSTR m_file;
+ INT m_line;
+ LONG *m_pCount;
+
+ // Keep leakage counters.
+ static size_t s_cLeakedBytes;
+ static size_t s_cNumFailures;
+#endif
+
+ static BOOL s_neverEnforceAsserts;
+
+public: // !!! NOTE: Called from macros only!!!
+
+ // If we are not in a check, return TRUE and PushCheck; otherwise return FALSE
+ BOOL EnterAssert();
+
+ // Pops check count
+ void LeaveAssert();
+
+ // Just return if we are in a check
+ BOOL IsInAssert();
+
+ // Should we skip enforcing asserts
+ static BOOL EnforceAssert();
+
+ static BOOL EnforceAssert_StaticCheckOnly();
+
+ static void ResetAssert();
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4702) // Disable bogus unreachable code warning
+#endif // _MSC_VER
+ CHECK() : m_message(NULL)
+#ifdef _DEBUG
+ , m_condition (NULL)
+ , m_file(NULL)
+ , m_line(NULL)
+ , m_pCount(NULL)
+#endif
+ {}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+ // Fail records the result of a condition check. Can take either a
+ // boolean value or another check result
+ BOOL Fail(BOOL condition);
+ BOOL Fail(const CHECK &check);
+
+ // Setup records context info after a failure.
+ void Setup(LPCSTR message DEBUG_ARG(LPCSTR condition) DEBUG_ARG(LPCSTR file) DEBUG_ARG(INT line));
+ static LPCSTR FormatMessage(LPCSTR messageFormat, ...);
+
+ // Trigger triggers the actual check failure. The trigger may provide a reason
+ // to include in the failure message.
+ void Trigger(LPCSTR reason);
+
+ // Finally, convert to a BOOL to allow just testing the result of a Check function
+ operator BOOL();
+
+ BOOL operator!();
+
+ CHECK &operator()() { return *this; }
+
+ static inline const CHECK OK() {
+ return CHECK();
+ }
+
+ static void SetAssertEnforcement(BOOL value);
+
+ static void ReleaseTls(void* pCountTLS);
+
+ private:
+ static LONG* InitTls();
+#ifdef _DEBUG
+ static LPCSTR AllocateDynamicMessage(const SString &s);
+#endif
+};
+
+
+//--------------------------------------------------------------------------------
+// These CHECK macros are the correct way to propagate an assertion. These
+// routines are designed for use inside "Check" routines. Such routines may
+// be Invariants, Validate routines, or any other assertional predicates.
+//
+// A Check routine should return a value of type CHECK.
+//
+// It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate
+// control flow) and should end with CHECK_OK() if all other checks pass.
+//
+// It may contain a CONTRACT_CHECK contract, but this is only appropriate if the
+// check is used for non-assertional purposes (otherwise the contract will never execute).
+// Note that CONTRACT_CHECK contracts do not support postconditions.
+//
+// CHECK: Check the given condition, return a CHECK failure if FALSE
+// CHECK_MSG: Same, but include a message paramter if the check fails
+// CHECK_OK: Return a successful check value;
+//--------------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define DEBUG_ONLY_MESSAGE(msg) msg
+#else
+// On retail, we don't want to add a bunch of string literals to the image,
+// so we just use the same one everywhere.
+#define DEBUG_ONLY_MESSAGE(msg) ((LPCSTR)1)
+#endif
+
+#define CHECK_MSG_EX(_condition, _message, _RESULT) \
+do \
+{ \
+ CHECK _check; \
+ if (_check.Fail(_condition)) \
+ { \
+ ENTER_DEBUG_ONLY_CODE; \
+ _check.Setup(DEBUG_ONLY_MESSAGE(_message) \
+ DEBUG_ARG(#_condition) \
+ DEBUG_ARG(__FILE__) \
+ DEBUG_ARG(__LINE__)); \
+ _RESULT(_check); \
+ LEAVE_DEBUG_ONLY_CODE; \
+ } \
+} while (0)
+
+#define RETURN_RESULT(r) return r
+
+#define CHECK_MSG(_condition, _message) \
+ CHECK_MSG_EX(_condition, _message, RETURN_RESULT)
+
+#define CHECK(_condition) \
+ CHECK_MSG(_condition, "")
+
+#define CHECK_MSGF(_condition, _args) \
+ CHECK_MSG(_condition, CHECK::FormatMessage _args)
+
+#define CHECK_FAIL(_message) \
+ CHECK_MSG(FALSE, _message); UNREACHABLE()
+
+#define CHECK_FAILF(_args) \
+ CHECK_MSGF(FALSE, _args); UNREACHABLE()
+
+#define CHECK_OK \
+ return CHECK::OK()
+
+//--------------------------------------------------------------------------------
+// ASSERT_CHECK is the proper way to trigger a check result. If the CHECK
+// has failed, the diagnostic assertion routines will fire with appropriate
+// context information.
+//
+// Note that the condition may either be a raw boolean expression or a CHECK result
+// returned from a Check routine.
+//
+// Recursion note: ASSERT_CHECKs are only performed if there is no current check in
+// progress.
+//--------------------------------------------------------------------------------
+
+#ifndef ENTER_DEBUG_ONLY_CODE
+#define ENTER_DEBUG_ONLY_CODE
+#endif
+
+#ifndef LEAVE_DEBUG_ONLY_CODE
+#define LEAVE_DEBUG_ONLY_CODE
+#endif
+
+#define ASSERT_CHECK(_condition, _message, _reason) \
+do \
+{ \
+ CHECK _check; \
+ if (_check.EnterAssert()) \
+ { \
+ ENTER_DEBUG_ONLY_CODE; \
+ if (_check.Fail(_condition)) \
+ { \
+ _check.Setup(_message \
+ DEBUG_ARG(#_condition) \
+ DEBUG_ARG(__FILE__) \
+ DEBUG_ARG(__LINE__)); \
+ _check.Trigger(_reason); \
+ } \
+ LEAVE_DEBUG_ONLY_CODE; \
+ _check.LeaveAssert(); \
+ } \
+} while (0)
+
+// ex: ASSERT_CHECKF(1+2==4, "my reason", ("Woah %d", 1+3));
+// note that the double parenthesis, the 'args' param below will include one pair of parens.
+#define ASSERT_CHECKF(_condition, _reason, _args) \
+ ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason)
+
+//--------------------------------------------------------------------------------
+// INVARIANTS are descriptions of conditions which are always true at well defined
+// points of execution. Invariants may be checked by the caller or callee at any
+// time as paranoia requires.
+//
+// There are really two flavors of invariant. The "public invariant" describes
+// to the caller invariant behavior about the abstraction which is visible from
+// the public API (and of course it should be expressible in that public API).
+//
+// The "internal invariant" (or representation invariant), on the other hand, is
+// a description of the private implementation of the abstraction, which may examine
+// internal state of the abstraction or use private entry points.
+//
+// Classes with invariants should introduce methods called
+// void Invariant();
+// and
+// void InternalInvariant();
+// to allow invariant checks.
+//--------------------------------------------------------------------------------
+
+#if CHECK_INVARIANTS
+
+template <typename TYPENAME>
+CHECK CheckInvariant(TYPENAME &obj)
+{
+ __if_exists(TYPENAME::Invariant)
+ {
+ CHECK(obj.Invariant());
+ }
+ __if_exists(TYPENAME::InternalInvariant)
+ {
+ CHECK(obj.InternalInvariant());
+ }
+
+ CHECK_OK;
+}
+
+#define CHECK_INVARIANT(o) \
+ ASSERT_CHECK(CheckInvariant(o), NULL, "Invariant failure")
+
+#else
+
+#define CHECK_INVARIANT(o) do { } while (0)
+
+#endif
+
+//--------------------------------------------------------------------------------
+// VALIDATE is a check to be made on an object type which identifies a pointer as
+// a valid instance of the object, by calling CheckPointer on it. Normally a null
+// pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK))
+// may be used when a null pointer is acceptible.
+//
+// In addition to the null/non-null check, a type may provide a specific Check method
+// for more sophisticated identification. In general, the Check method
+// should answer the question
+// "Is this a valid instance of its declared compile-time type?". For instance, if
+// runtype type identification were supported for the type, it should be invoked here.
+//
+// Note that CheckPointer will also check the invariant(s) if appropriate, so the
+// invariants should NOT be explicitly invoked from the Check method.
+//--------------------------------------------------------------------------------
+
+enum IsNullOK
+{
+ NULL_NOT_OK = 0,
+ NULL_OK = 1
+};
+
+#if CHECK_INVARIANTS
+template <typename TYPENAME>
+CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK)
+{
+ if (o == NULL)
+ {
+ CHECK_MSG(ok, "Illegal null pointer");
+ }
+ else
+ {
+ __if_exists(TYPENAME::Check)
+ {
+ CHECK(o->Check());
+ }
+ }
+
+ CHECK_OK;
+}
+
+template <typename TYPENAME>
+CHECK CheckValue(TYPENAME &val)
+{
+ __if_exists(TYPENAME::Check)
+ {
+ CHECK(val.Check());
+ }
+
+ CHECK(CheckInvariant(val));
+
+ CHECK_OK;
+}
+#else // CHECK_INVARIANTS
+
+#ifdef _DEBUG_IMPL
+// Don't defined these functions to be nops for the non-debug
+// build as it may hide important checks
+template <typename TYPENAME>
+CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK)
+{
+ if (o == NULL)
+ {
+ CHECK_MSG(ok, "Illegal null pointer");
+ }
+
+ CHECK_OK;
+}
+
+template <typename TYPENAME>
+CHECK CheckValue(TYPENAME &val)
+{
+ CHECK_OK;
+}
+#endif
+
+#endif // CHECK_INVARIANTS
+
+#if VALIDATE_OBJECTS
+
+#define VALIDATE(o) \
+ ASSERT_CHECK(CheckPointer(o), "Validation failure")
+#define VALIDATE_NULL(o) \
+ ASSERT_CHECK(CheckPointer(o, NULL_OK), "Validation failure")
+
+#else
+
+#define VALIDATE(o) do { } while (0)
+#define VALIDATE_NULL(o) do { } while (0)
+
+#endif
+
+//--------------------------------------------------------------------------------
+// CONSISTENCY_CHECKS are ad-hoc assertions about the expected state of the program
+// at a given time. A failure in one of these indicates a bug in the code.
+//
+// Note that the condition may either be a raw boolean expression or a CHECK result
+// returned from a Check routine.
+//--------------------------------------------------------------------------------
+
+#define CONSISTENCY_CHECK(_condition) \
+ CONSISTENCY_CHECK_MSG(_condition, "")
+
+#ifdef _DEBUG_IMPL
+
+#define CONSISTENCY_CHECK_MSG(_condition, _message) \
+ ASSERT_CHECK(_condition, _message, "Consistency check failed")
+
+#define CONSISTENCY_CHECK_MSGF(_condition, args) \
+ ASSERT_CHECKF(_condition, "Consistency check failed", args)
+
+#else
+
+#define CONSISTENCY_CHECK_MSG(_condition, _message) do { } while (0)
+#define CONSISTENCY_CHECK_MSGF(_condition, args) do { } while (0)
+
+#endif
+
+//--------------------------------------------------------------------------------
+// SIMPLIFYING_ASSUMPTIONS are workarounds which are placed in the code to allow progress
+// to be made in the case of difficult corner cases. These should NOT be left in the
+// code; they are really just markers of things which need to be fixed.
+//
+// Note that the condition may either be a raw boolean expression or a CHECK result
+// returned from a Check routine.
+//--------------------------------------------------------------------------------
+
+// Ex usage:
+// SIMPLIFYING_ASSUMPTION(SomeExpression());
+#define SIMPLIFYING_ASSUMPTION(_condition) \
+ SIMPLIFYING_ASSUMPTION_MSG(_condition, "")
+
+
+// Helper for HRs. Will provide formatted message showing the failure code.
+#define SIMPLIFYING_ASSUMPTION_SUCCEEDED(__hr) \
+ { \
+ HRESULT __hr2 = (__hr); \
+ (void)__hr2; \
+ SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(__hr2), ("HRESULT failed.\n Expected success.\n Actual=0x%x\n", __hr2)); \
+ }
+
+#ifdef _DEBUG_IMPL
+
+// Ex usage:
+// SIMPLIFYING_ASSUMPTION_MSG(SUCCEEDED(hr), "It failed!");
+#define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) \
+ ASSERT_CHECK(_condition, _message, "Unhandled special case detected")
+
+// use a formatted string. Ex usage:
+// SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(hr), ("Woah it failed! 0x%08x", hr));
+#define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) \
+ ASSERT_CHECKF(_condition, "Unhandled special case detected", args)
+
+#else // !_DEBUG_IMPL
+
+#define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) do { } while (0)
+#define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) do { } while (0)
+
+#endif // !_DEBUG_IMPL
+
+//--------------------------------------------------------------------------------
+// COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the
+// condition is true. In a checked build these turn into asserts;
+// in a free build they are passed through to the compiler to use in optimization.
+//--------------------------------------------------------------------------------
+
+#if defined(_PREFAST_) || defined(_PREFIX_)
+#define COMPILER_ASSUME_MSG(_condition, _message) if (!(_condition)) __UNREACHABLE();
+#define COMPILER_ASSUME_MSGF(_condition, args) if (!(_condition)) __UNREACHABLE();
+#else
+
+#if defined(DACCESS_COMPILE)
+#define COMPILER_ASSUME_MSG(_condition, _message) do { } while (0)
+#define COMPILER_ASSUME_MSGF(_condition, args) do { } while (0)
+#else
+
+#if defined(_DEBUG)
+#define COMPILER_ASSUME_MSG(_condition, _message) \
+ ASSERT_CHECK(_condition, _message, "Compiler optimization assumption invalid")
+#define COMPILER_ASSUME_MSGF(_condition, args) \
+ ASSERT_CHECKF(_condition, "Compiler optimization assumption invalid", args)
+#else
+#define COMPILER_ASSUME_MSG(_condition, _message) __assume(_condition)
+#define COMPILER_ASSUME_MSGF(_condition, args) __assume(_condition)
+#endif // _DEBUG
+
+#endif // DACCESS_COMPILE
+
+#endif // _PREFAST_ || _PREFIX_
+
+
+#define COMPILER_ASSUME(_condition) \
+ COMPILER_ASSUME_MSG(_condition, "")
+
+
+//--------------------------------------------------------------------------------
+// PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name
+// for COMPILER_ASSUME_MSG
+// In a checked build these turn into asserts; in a free build
+// they are passed through to the compiler to use in optimization;
+// via an __assume(_condition) optimization hint.
+//--------------------------------------------------------------------------------
+
+#define PREFIX_ASSUME_MSG(_condition, _message) \
+ COMPILER_ASSUME_MSG(_condition, _message)
+
+#define PREFIX_ASSUME_MSGF(_condition, args) \
+ COMPILER_ASSUME_MSGF(_condition, args)
+
+#define PREFIX_ASSUME(_condition) \
+ COMPILER_ASSUME_MSG(_condition, "")
+
+#define PREFAST_ASSUME_MSG(_condition, _message) \
+ COMPILER_ASSUME_MSG(_condition, _message)
+
+#define PREFAST_ASSUME_MSGF(_condition, args) \
+ COMPILER_ASSUME_MSGF(_condition, args)
+
+#define PREFAST_ASSUME(_condition) \
+ COMPILER_ASSUME_MSG(_condition, "")
+
+//--------------------------------------------------------------------------------
+// UNREACHABLE points are locations in the code which should not be able to be
+// reached under any circumstances (e.g. a default in a switch which is supposed to
+// cover all cases.). This macro tells the compiler this, and also embeds a check
+// to make sure it is always true.
+//--------------------------------------------------------------------------------
+
+#define UNREACHABLE() \
+ UNREACHABLE_MSG("")
+
+#ifdef __llvm__
+
+// LLVM complains if a function does not return what it says.
+#define UNREACHABLE_RET() do { UNREACHABLE(); return 0; } while (0)
+#define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message); return 0;
+
+#else // __llvm__
+
+#define UNREACHABLE_RET() UNREACHABLE()
+#define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message)
+
+#endif // __llvm__ else
+
+#if defined(_MSC_VER) || defined(_PREFIX_)
+#if defined(_TARGET_AMD64_)
+// Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method
+// which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT
+// Remove when we get a VC compiler that fixes VSW 449170
+# define __UNREACHABLE() DebugBreak(); __assume(0);
+#else
+# define __UNREACHABLE() __assume(0)
+#endif
+#else
+#define __UNREACHABLE() do { } while(true)
+#endif
+
+#ifdef _DEBUG_IMPL
+
+// Note that the "do { } while (0)" syntax trick here doesn't work, as the compiler
+// gives an error that the while(0) is unreachable code
+#define UNREACHABLE_MSG(_message) \
+{ \
+ CHECK _check; \
+ _check.Setup(_message, "<unreachable>", __FILE__, __LINE__); \
+ _check.Trigger("Reached the \"unreachable\""); \
+} __UNREACHABLE()
+
+#else
+
+#define UNREACHABLE_MSG(_message) __UNREACHABLE()
+
+#endif
+
+
+//--------------------------------------------------------------------------------
+// STRESS_CHECK represents a check which is included in a free build
+// @todo: behavior on trigger
+//
+// Note that the condition may either be a raw boolean expression or a CHECK result
+// returned from a Check routine.
+//
+// Since Retail builds don't allow formatted checks, there's no STRESS_CHECK_MSGF.
+//--------------------------------------------------------------------------------
+
+#if CHECK_STRESS
+
+#define STRESS_CHECK(_condition, _message) \
+ ASSERT_CHECK(_condition, _message, "Stress Assertion Failure")
+
+#else
+
+#define STRESS_CHECK(_condition, _message) do { } while (0)
+
+#endif
+
+//--------------------------------------------------------------------------------
+// CONTRACT_CHECK is used to put contracts on Check function. Note that it does
+// not support postconditions.
+//--------------------------------------------------------------------------------
+
+#define CONTRACT_CHECK CONTRACTL
+#define CONTRACT_CHECK_END CONTRACTL_END
+
+//--------------------------------------------------------------------------------
+// CCHECK is used for Check functions which may fail due to out of memory
+// or other transient failures. These failures should be ignored when doing
+// assertions, but they cannot be ignored when the Check function is used in
+// normal code.
+// @todo: really crufty to have 2 sets of CHECK macros
+//--------------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+#define CCHECK_START \
+ { \
+ BOOL ___exception = FALSE; \
+ BOOL ___transient = FALSE; \
+ CHECK ___result = CHECK::OK(); \
+ EX_TRY {
+
+#define CCHECK_END \
+ } EX_CATCH { \
+ if (___result.IsInAssert()) \
+ { \
+ ___exception = TRUE; \
+ ___transient = GET_EXCEPTION()->IsTransient(); \
+ } \
+ else \
+ EX_RETHROW; \
+ } EX_END_CATCH(RethrowTerminalExceptions); \
+ \
+ if (___exception) \
+ { \
+ if (___transient) \
+ CHECK_OK; \
+ else \
+ CHECK_FAIL("Nontransient exception occurred during check"); \
+ } \
+ CHECK(___result); \
+ }
+
+#define CRETURN_RESULT(r) ___result = r
+
+#define CCHECK_MSG(_condition, _message) \
+ CHECK_MSG_EX(_condition, _message, CRETURN_RESULT)
+
+#define CCHECK(_condition) \
+ CCHECK_MSG(_condition, "")
+
+#define CCHECK_MSGF(_condition, _args) \
+ CCHECK_MSG(_condition, CHECK::FormatMessage _args)
+
+#define CCHECK_FAIL(_message) \
+ CCHECK_MSG(FALSE, _message); UNREACHABLE()
+
+#define CCHECK_FAILF(_args) \
+ CCHECK_MSGF(FALSE, _args); UNREACHABLE()
+
+#else // _DEBUG
+
+#define CCHECK_START
+#define CCHECK_END
+
+#define CCHECK CHECK
+#define CCHECK_MSG CHECK_MSG
+#define CCHECK_MSGF CHECK_MSGF
+#define CCHECK_FAIL CHECK_FAIL
+#define CCHECK_FAILF CHECK_FAILF
+
+#endif
+
+
+
+//--------------------------------------------------------------------------------
+// Common base level checks
+//--------------------------------------------------------------------------------
+
+CHECK CheckAlignment(UINT alignment);
+
+CHECK CheckAligned(UINT value, UINT alignment);
+#if defined(_MSC_VER)
+CHECK CheckAligned(ULONG value, UINT alignment);
+#endif
+CHECK CheckAligned(UINT64 value, UINT alignment);
+CHECK CheckAligned(const void *address, UINT alignment);
+
+CHECK CheckOverflow(UINT value1, UINT value2);
+#if defined(_MSC_VER)
+CHECK CheckOverflow(ULONG value1, ULONG value2);
+#endif
+CHECK CheckOverflow(UINT64 value1, UINT64 value2);
+CHECK CheckOverflow(PTR_CVOID address, UINT offset);
+#if defined(_MSC_VER)
+CHECK CheckOverflow(const void *address, ULONG offset);
+#endif
+CHECK CheckOverflow(const void *address, UINT64 offset);
+
+CHECK CheckUnderflow(UINT value1, UINT value2);
+#if defined(_MSC_VER)
+CHECK CheckUnderflow(ULONG value1, ULONG value2);
+#endif
+CHECK CheckUnderflow(UINT64 value1, UINT64 value2);
+CHECK CheckUnderflow(const void *address, UINT offset);
+#if defined(_MSC_VER)
+CHECK CheckUnderflow(const void *address, ULONG offset);
+#endif
+CHECK CheckUnderflow(const void *address, UINT64 offset);
+CHECK CheckUnderflow(const void *address, void *address2);
+
+CHECK CheckZeroedMemory(const void *memory, SIZE_T size);
+
+// These include overflow checks
+CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset);
+CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size);
+
+void WINAPI ReleaseCheckTls(LPVOID pTlsData);
+
+// ================================================================================
+// Inline definitions
+// ================================================================================
+
+#include "check.inl"
+
+#endif // CHECK_H_