Make SkASSERT and co. constexpr compatible.

One of the nice bits of constexpr is that an expression is constexpr if
there exists any set of argument values that make it constant.  It
doesn't have to be constant for _all_ argument values.

This means that this expression is constexpr:

   condition ? constexpr_value
             : []{ arbitrary non-constexpr code; }();

... it's constant when condition is true.

We can use this to rewrite SkASSERT(condition) as

    ( (condition) ? (void)0
                  : []{ SK_ABORT(#condition); }() )

Both sides of the ?: are void, and when condition is true at compile
time the right hand side disappears completely.  In C++11 constexpr
functions we just have to use the comma operator to jam SkASSERT()
into the order of evaluation:

    constexpr uint32_t foo(int x, int y) {
        return SkASSERT(x > y),
               x - y;
    }

Change-Id: I21878d14fb2af76d93591d2ae229460ee825cfde
Reviewed-on: https://skia-review.googlesource.com/52663
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Trent Apted <tapted@chromium.org>
Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Mike Klein 2017-09-28 09:47:45 -04:00 committed by Skia Commit-Bot
parent fdd2cb52b7
commit 37bbfe3ea4
2 changed files with 24 additions and 34 deletions

View File

@ -28,29 +28,13 @@ typedef uint32_t SkColor;
/** Return a SkColor value from 8 bit component values
*/
static inline SkColor SkColorSetARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
{
SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255);
return (a << 24) | (r << 16) | (g << 8) | (b << 0);
static constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
return SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255),
(a << 24) | (r << 16) | (g << 8) | (b << 0);
}
#define SkColorSetARGBMacro(a, r, g, b) \
static_cast<SkColor>( \
(static_cast<U8CPU>(a) << 24) | \
(static_cast<U8CPU>(r) << 16) | \
(static_cast<U8CPU>(g) << 8) | \
(static_cast<U8CPU>(b) << 0))
/** gcc will generate static initializers for code of this form:
* static const SkColor kMyColor = SkColorSetARGB(0xFF, 0x01, 0x02, 0x03)
* if SkColorSetARGB() is a static inline, but not if it's a macro.
*/
#if defined(NDEBUG)
#define SkColorSetARGB(a, r, g, b) SkColorSetARGBMacro(a, r, g, b)
#else
#define SkColorSetARGB(a, r, g, b) SkColorSetARGBInline(a, r, g, b)
#endif
// Legacy aliases.
#define SkColorSetARGBInline SkColorSetARGB
#define SkColorSetARGBMacro SkColorSetARGB
/** Return a SkColor value from 8 bit component values, with an implied value
of 0xFF for alpha (fully opaque)

View File

@ -79,27 +79,33 @@ inline void operator delete(void* p) {
SK_API void SkDebugf(const char format[], ...);
#endif
#define SkREQUIRE_SEMICOLON_AFTER(code) do { code } while (false)
// 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) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { SK_ABORT(#cond); } )
static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(" #cond ")"); }() )
#ifdef SK_DEBUG
#define SkASSERT(cond) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { SK_ABORT("assert(" #cond ")"); })
#define SkASSERTF(cond, fmt, ...) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { \
#define SkASSERT(cond) SkASSERT_RELEASE(cond)
#define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
SkDebugf(fmt"\n", __VA_ARGS__); \
SK_ABORT("assert(" #cond ")"); \
})
}() )
#define SkDEBUGFAIL(message) SK_ABORT(message)
#define SkDEBUGFAILF(fmt, ...) SkASSERTF(false, fmt, ##__VA_ARGS__)
#define SkDEBUGCODE(...) __VA_ARGS__
#define SkDEBUGF(args ) SkDebugf args
#define SkAssertResult(cond) SkASSERT(cond)
#else
#define SkASSERT(cond)
#define SkASSERTF(cond, fmt, ...)
#define SkASSERT(cond) static_cast<void>(0)
#define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
#define SkDEBUGFAIL(message)
#define SkDEBUGFAILF(fmt, ...)
#define SkDEBUGCODE(...)