• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkAssert_DEFINED
9 #define SkAssert_DEFINED
10 
11 #include "include/private/base/SkAPI.h"
12 #include "include/private/base/SkDebug.h" // IWYU pragma: keep
13 
14 /** Called internally if we hit an unrecoverable error.
15     The platform implementation must not return, but should either throw
16     an exception or otherwise exit.
17 */
18 [[noreturn]] SK_API extern void sk_abort_no_print(void);
19 
20 #if defined(SK_BUILD_FOR_GOOGLE3)
21     void SkDebugfForDumpStackTrace(const char* data, void* unused);
22     namespace base {
23         void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
24     }
25 #  define SK_DUMP_GOOGLE3_STACK() ::base::DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
26 #else
27 #  define SK_DUMP_GOOGLE3_STACK()
28 #endif
29 
30 #if !defined(SK_ABORT)
31 #  if defined(SK_BUILD_FOR_WIN)
32      // This style lets Visual Studio follow errors back to the source file.
33 #    define SK_DUMP_LINE_FORMAT "%s(%d)"
34 #  else
35 #    define SK_DUMP_LINE_FORMAT "%s:%d"
36 #  endif
37 #  define SK_ABORT(message, ...) \
38     do { \
39         SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \
40                  __FILE__, __LINE__, ##__VA_ARGS__); \
41         SK_DUMP_GOOGLE3_STACK(); \
42         sk_abort_no_print(); \
43     } while (false)
44 #endif
45 
46 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
47 #  define SK_ABORT_IN_ANDROID_FRAMEWORK(message, ...) SK_ABORT(message, ##__VA_ARGS__)
48 #else
49 #  define SK_ABORT_IN_ANDROID_FRAMEWORK(message, ...)
50 #endif
51 
52 // SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
53 //    uint32_t foo(int x) {
54 //        SkASSERT(x > 4);
55 //        return x - 4;
56 //    }
57 // and are also written to be compatible with constexpr functions:
58 //    constexpr uint32_t foo(int x) {
59 //        return SkASSERT(x > 4),
60 //               x - 4;
61 //    }
62 #define SkASSERT_RELEASE(cond) \
63         static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
64 
65 #if defined(SK_DEBUG)
66     #define SkASSERT(cond) SkASSERT_RELEASE(cond)
67     #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
68                                           SkDebugf(fmt"\n", ##__VA_ARGS__);      \
69                                           SK_ABORT("assert(%s)", #cond);         \
70                                       }() )
71     #define SkDEBUGFAIL(message)        SK_ABORT("%s", message)
72     #define SkDEBUGFAILF(fmt, ...)      SK_ABORT(fmt, ##__VA_ARGS__)
73     #define SkAssertResult(cond)        SkASSERT(cond)
74 #else
75     #define SkASSERT(cond)            static_cast<void>(0)
76     #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
77     #define SkDEBUGFAIL(message)
78     #define SkDEBUGFAILF(fmt, ...)
79 
80     // unlike SkASSERT, this macro executes its condition in the non-debug build.
81     // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
82     #define SkAssertResult(cond)         if (cond) {} do {} while(false)
83 #endif
84 
85 #if !defined(SkUNREACHABLE)
86 #  if defined(_MSC_VER) && !defined(__clang__)
87 #    include <intrin.h>
88 #    define FAST_FAIL_INVALID_ARG                 5
89 // See https://developercommunity.visualstudio.com/content/problem/1128631/code-flow-doesnt-see-noreturn-with-extern-c.html
90 // for why this is wrapped. Hopefully removable after msvc++ 19.27 is no longer supported.
sk_fast_fail()91 [[noreturn]] static inline void sk_fast_fail() { __fastfail(FAST_FAIL_INVALID_ARG); }
92 #    define SkUNREACHABLE sk_fast_fail()
93 #  else
94 #    define SkUNREACHABLE __builtin_trap()
95 #  endif
96 #endif
97 
98 #endif
99