diff options
| author | Mark Rowe <mark@vector35.com> | 2025-12-20 16:30:19 -0800 |
|---|---|---|
| committer | Mark Rowe <mark@vector35.com> | 2026-04-20 12:26:06 -0700 |
| commit | 468028455f5b7d9bf71fc111c078487c6dbf8a73 (patch) | |
| tree | 43821e5d5479b19629283e3fda3ff3e5554bb0e3 /base | |
| parent | 68f04aca3f4e04c1ec2c3b5d54c04ff05e9b0c58 (diff) | |
Add assertion macros to base
Diffstat (limited to 'base')
| -rw-r--r-- | base/assertions.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/base/assertions.h b/base/assertions.h new file mode 100644 index 00000000..30a06661 --- /dev/null +++ b/base/assertions.h @@ -0,0 +1,104 @@ +// Copyright (c) 2026 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +// Assertion macros for internal consistency checks. +// +// There are two categories of assertions: +// 1) BN_ASSERT: These assertions can be enabled or disabled at compile time +// using the BN_ASSERTIONS_ENABLED macro. They are intended for checking +// conditions during development and debugging, but are compiled out of +// production builds, either for performance reasons or because there is +// a recovery path beyond trapping. +// 2) BN_RELEASE_ASSERT: These assertions are always enabled, regardless of +// the BN_ASSERTIONS_ENABLED setting. They are intended for checking +// conditions that must always hold true for the program to function +// correctly, and indicate a serious error if they fail. +// +// By default, BN_ASSERTIONS_ENABLED is enabled in debug builds and disabled +// in release builds. + +#ifndef BN_ASSERTIONS_ENABLED +#ifdef NDEBUG +#define BN_ASSERTIONS_ENABLED 0 +#else +#define BN_ASSERTIONS_ENABLED 1 +#endif +#endif + +#ifdef _MSC_VER +#include <intrin.h> +#define BN_ASSERT_TRAP __fastfail(7 /* FAST_FAIL_FATAL_APP_EXIT */) +#else +#define BN_ASSERT_TRAP __builtin_trap() +#endif + +#if BN_ASSERTIONS_ENABLED + +// When assertions are enabled, reporting an assertion failure logs an error message then traps. +#define BN_REPORT_ASSERTION_FAILURE(message) \ + do \ + { \ + BNLogError("Assertion failed: %s (%s:%d)", message, __FILE__, __LINE__); \ + BN_ASSERT_TRAP; \ + } while (0) + +// BN_ASSERT checks the given condition and reports an assertion failure if the condition is false. +#define BN_ASSERT(condition) \ + do \ + { \ + if (!(condition)) [[unlikely]] \ + { \ + BN_REPORT_ASSERTION_FAILURE(#condition); \ + } \ + } while (0) + +#else + +// When assertions are disabled, reporting an assertion failure traps without logging. +// This is used for release assertions that are always enabled. +#define BN_REPORT_ASSERTION_FAILURE(message) BN_ASSERT_TRAP + +// BN_ASSERT does nothing when assertions are disabled. +// Note that it does not evaluate the condition. +#define BN_ASSERT(condition) (void)0 + +#endif + +// BN_RELEASE_ASSERT checks the given condition and reports an assertion failure +// if the condition is false. +// This assertion is always enabled, regardless of the BN_ASSERTIONS_ENABLED setting. +#define BN_RELEASE_ASSERT(condition) \ + do \ + { \ + if (!(condition)) [[unlikely]] \ + { \ + BN_REPORT_ASSERTION_FAILURE(#condition); \ + } \ + } while (0) + +// Assert that this code path is not reached. +// This assertion is always enabled, regardless of the BN_ASSERTIONS_ENABLED setting. +#define BN_RELEASE_ASSERT_NOT_REACHED() \ + do \ + { \ + BN_REPORT_ASSERTION_FAILURE("Unreachable code reached"); \ + } while (0) |
