//===--- Assertions.h - Assertion macros ----===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file provides three alternatives to the C/C++ standard `assert()` macro // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_ASSERTIONS_H #define SWIFT_BASIC_ASSERTIONS_H #include "swift/Basic/LLVM.h" // Only for use in this header #if __has_builtin(__builtin_expect) #define ASSERT_UNLIKELY(expression) (__builtin_expect(!!(expression), 0)) #else #define ASSERT_UNLIKELY(expression) ((expression)) #endif // Visual Studio doesn't have __FILE_NAME__ #ifdef __FILE_NAME__ #define _FILENAME_FOR_ASSERT __FILE_NAME__ #else #define _FILENAME_FOR_ASSERT __FILE__ #endif // ================================ Mandatory Asserts ================================ // `ASSERT(expr)`: // * is always compiled into the executable and // * always checks the condition, regardless of build or runtime settings. // This should be used for most assertions, which is why it // deserves the short name. In particular, for simple checks // (e.g., validating that something is non-null), this is just as // fast as a disabled `CONDITIONAL_ASSERT`, so there's no point in // using the conditional form. // // You can globally replace `assert` with `ASSERT` in a piece of code // to have all your assertions enabled in all builds. If you do this, // please do a little profiling first, just in case you have some checks // that are more expensive than you think. You can switch those to // `CONDITIONAL_ASSERT` or `DEBUG_ASSERT` as needed. #define ASSERT(expr) \ do { \ if (ASSERT_UNLIKELY(!(expr))) { \ ASSERT_failure(#expr, _FILENAME_FOR_ASSERT, __LINE__, __func__); \ } \ } while (0) // Function that reports the actual failure when it occurs. void ASSERT_failure(const char *expr, const char *file, int line, const char *func); // ================================ Conditional Asserts ================================ // `CONDITIONAL_ASSERT(expr)`: // * is always compiled into the executable, but // * only checks the condition if a runtime flag is defined. // That runtime flag is disabled by default in release builds // but can be enabled with the command-line flag `-compiler-assertions` // // Use this for asserts that are comparatively expensive to check. // // You can globally change `assert` to `CONDITIONAL_ASSERT` to make all your // assertions _optionally_ available in release builds. Anyone can then add // `-compiler-assertions` to their build flags to get more information about a // compiler problem. Before you check it in, do a little checking for // assertions that might be checked huge numbers of times (e.g., invariants // for inner loops or core utilities); those may need to become `DEBUG_ASSERT` // or else refactored to be checked more selectively. // // Over time, plan to change most of the resulting `CONDITIONAL_ASSERT` into // plain `ASSERT` to enable them by default. #define CONDITIONAL_ASSERT(expr) \ do { \ if (ASSERT_UNLIKELY(CONDITIONAL_ASSERT_enabled())) { \ ASSERT(expr); \ } \ } while (0) // Use `CONDITIONAL_ASSERT_enabled()` to guard complex, expensive code that // should only run when assertions are enabled. This is exactly the // same check that's used to enable `CONDITIONAL_ASSERT()` at runtime. // This is not often used -- if you are just setting a flag or updating // a counter, it's likely cheaper just to do it than to test whether or not // to do it. Only use this for relatively complex operations. // // if (CONDITIONAL_ASSERT_enabled()) { // ... stuff ... // } // Declare a callable function version of this runtime test. int CONDITIONAL_ASSERT_enabled(); // Define a macro version of this test extern int CONDITIONAL_ASSERT_Global_enable_flag; #define CONDITIONAL_ASSERT_enabled() \ (CONDITIONAL_ASSERT_Global_enable_flag != 0) // Profiling note: If you uncomment the line below to #undef the macro, then // we'll always call the function, which lets you profile assertions by // counting calls to this function. // #undef CONDITIONAL_ASSERT_enabled // ================================ Debug Asserts ================================ // `DEBUG_ASSERT(expr)`: // * is only compiled into the executable in debug or "asserts enabled" builds, and // * always performs the check (whenever it is compiled in). // // This basically makes it a synonym for the Standard C `assert(expr)`. // // You should mostly avoid this except for occasional experiments in your // local tree. It can be useful in two situations: // // * Assertions that are known to mis-fire. // Such assertions should not be `ASSERT` (since that will cause unnecessary // broken compiles) and `CONDITIONAL_ASSERT` gets enabled a lot by people who // are not compiler experts. So `DEBUG_ASSERT` is appropriate there until the // check can be fixed so it doesn't mis-fire. // // * Inner loops that can run billions of times. // For these, even the cost of testing whether `CONDITIONAL_ASSERT` is enabled // can be prohibitive. Use `DEBUG_ASSERT`, but also look for ways to refactor // so you can verify correctness without having an assertion in an inner loop. // // P.S. Please do not bulk replace `assert` with `DEBUG_ASSERT`. The whole // point of this package is to move us toward having assertions always compiled // in and always enabled. #ifdef NDEBUG #define DEBUG_ASSERT(expr) do { } while (0) #undef DEBUG_ASSERT_enabled #else #define DEBUG_ASSERT(expr) ASSERT(expr) #define DEBUG_ASSERT_enabled 1 #endif // Code that's only needed within `DEBUG_ASSERT` can be guarded as follows: // // #ifndef NDEBUG // ... code that's only needed for DEBUG_ASSERT ... // #endif // // or with the equivalent // // #ifdef DEBUG_ASSERT_enabled // ... code that's only needed for DEBUG_ASSERT ... // #endif // // For example, you may need this for variables or functions that // are only used within DEBUG_ASSERT statements. // A common case is to declare a variable or perform a simple // expression. These can be used to avoid some boilerplate: // // void doThings() { // DEBUG_ASSERT_DECL(std::vector thingsToVerify;); // while (!done) { // // ... do each thing ... // DEBUG_ASSERT_EXPR(thingsToVerify.append(item)); // } // DEBUG_ASSERT(verifyAllThe(thingsToVerify)); // } #ifdef DEBUG_ASSERT_enabled #define DEBUG_ASSERT_DECL(...) __VA_ARGS__ #define DEBUG_ASSERT_EXPR(...) do { __VA_ARGS__; } while (false) #else #define DEBUG_ASSERT_DECL(...) #define DEBUG_ASSERT_EXPR(...) do { } while (false) #endif // Older version of the same idea: #define SWIFT_ASSERT_ONLY_DECL DEBUG_ASSERT_DECL #define SWIFT_ASSERT_ONLY DEBUG_ASSERT_EXPR // ================================ Abort ====================================== /// Implementation for \c ABORT, not to be used directly. [[noreturn]] void _ABORT(const char *file, int line, const char *func, llvm::function_ref message); /// Implementation for \c ABORT, not to be used directly. [[noreturn]] void _ABORT(const char *file, int line, const char *func, llvm::StringRef message); // Aborts the program, printing a given message to a PrettyStackTrace frame // before exiting. This should be preferred over manually logging to stderr and // `abort()`'ing since that won't be picked up by the crash reporter. // // There are two different forms of ABORT: // // ``` // ABORT("abort with string"); // // ABORT([&](auto &out) { // out << "abort with arbitrary stream"; // node.dump(out); // }); // ``` // #define ABORT(arg) _ABORT(_FILENAME_FOR_ASSERT, __LINE__, __func__, (arg)) #endif // SWIFT_BASIC_ASSERTIONS_H