/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkAssert_DEFINED #define SkAssert_DEFINED #include "include/private/base/SkAPI.h" #include "include/private/base/SkDebug.h" // IWYU pragma: keep /** Called internally if we hit an unrecoverable error. The platform implementation must not return, but should either throw an exception or otherwise exit. */ [[noreturn]] SK_API extern void sk_abort_no_print(void); #if defined(SK_BUILD_FOR_GOOGLE3) void SkDebugfForDumpStackTrace(const char* data, void* unused); namespace base { void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg); } # define SK_DUMP_GOOGLE3_STACK() ::base::DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr) #else # define SK_DUMP_GOOGLE3_STACK() #endif #if !defined(SK_ABORT) # if defined(SK_BUILD_FOR_WIN) // This style lets Visual Studio follow errors back to the source file. # define SK_DUMP_LINE_FORMAT "%s(%d)" # else # define SK_DUMP_LINE_FORMAT "%s:%d" # endif # define SK_ABORT(message, ...) \ do { \ SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \ __FILE__, __LINE__, ##__VA_ARGS__); \ SK_DUMP_GOOGLE3_STACK(); \ sk_abort_no_print(); \ } while (false) #endif #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) # define SK_ABORT_IN_ANDROID_FRAMEWORK(message, ...) SK_ABORT(message, ##__VA_ARGS__) #else # define SK_ABORT_IN_ANDROID_FRAMEWORK(message, ...) #endif // SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g. // uint32_t foo(int x) { // SkASSERT(x > 4); // return x - 4; // } // and are also written to be compatible with constexpr functions: // constexpr uint32_t foo(int x) { // return SkASSERT(x > 4), // x - 4; // } #define SkASSERT_RELEASE(cond) \ static_cast( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() ) #if defined(SK_DEBUG) #define SkASSERT(cond) SkASSERT_RELEASE(cond) #define SkASSERTF(cond, fmt, ...) static_cast( (cond) ? (void)0 : [&]{ \ SkDebugf(fmt"\n", ##__VA_ARGS__); \ SK_ABORT("assert(%s)", #cond); \ }() ) #define SkDEBUGFAIL(message) SK_ABORT("%s", message) #define SkDEBUGFAILF(fmt, ...) SK_ABORT(fmt, ##__VA_ARGS__) #define SkAssertResult(cond) SkASSERT(cond) #else #define SkASSERT(cond) static_cast(0) #define SkASSERTF(cond, fmt, ...) static_cast(0) #define SkDEBUGFAIL(message) #define SkDEBUGFAILF(fmt, ...) // unlike SkASSERT, this macro executes its condition in the non-debug build. // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT. #define SkAssertResult(cond) if (cond) {} do {} while(false) #endif #if !defined(SkUNREACHABLE) # if defined(_MSC_VER) && !defined(__clang__) # include # define FAST_FAIL_INVALID_ARG 5 // See https://developercommunity.visualstudio.com/content/problem/1128631/code-flow-doesnt-see-noreturn-with-extern-c.html // for why this is wrapped. Hopefully removable after msvc++ 19.27 is no longer supported. [[noreturn]] static inline void sk_fast_fail() { __fastfail(FAST_FAIL_INVALID_ARG); } # define SkUNREACHABLE sk_fast_fail() # else # define SkUNREACHABLE __builtin_trap() # endif #endif #endif