Skip to content

Commit 7c01351

Browse files
committed
Add bitfield support
1 parent 6db8c48 commit 7c01351

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

include/libassert/assert-macros.hpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,42 @@
55
// https://github.com/jeremy-rifkin/libassert
66

77
#include <libassert/platform.hpp>
8-
8+
#include <libassert/expression-decomposition.hpp>
99
#include <string_view>
1010

11+
LIBASSERT_BEGIN_NAMESPACE
12+
namespace detail {
13+
14+
std::false_type is_referencable_expression(...);
15+
16+
template <typename Concept>
17+
auto is_referencable_expression(Concept c)
18+
-> decltype(c(detail::expression_decomposer<>{}), std::true_type{});
19+
20+
// A macro that checks whether an expression can be decomposed by the
21+
// decomposer. An expression that fails is a bitfield for example.
22+
#define LIBASSERT_IS_DECOMPOSABLE_EXPR(expr) \
23+
decltype(libassert::detail::is_referencable_expression( \
24+
[](auto expr_decomposer) -> decltype(std::move(expr_decomposer) \
25+
<< expr) {}))::value
26+
27+
// The decomposer is passed as a template parameter to not evaluate the other
28+
// path and cause a hard error
29+
#define LIBASSERT_DECOMPOSER(expr) \
30+
[&](auto decomposer) { \
31+
if constexpr (sizeof(decomposer) && \
32+
LIBASSERT_IS_DECOMPOSABLE_EXPR(expr)) { \
33+
return libassert::detail::expression_decomposer(std::move(decomposer) \
34+
<< expr); \
35+
} else { \
36+
return std::move(decomposer) << (expr); \
37+
} \
38+
}(libassert::detail::expression_decomposer{})
39+
40+
} // namespace detail
41+
LIBASSERT_END_NAMESPACE
42+
43+
1144
#if LIBASSERT_IS_CLANG || LIBASSERT_IS_GCC || !LIBASSERT_NON_CONFORMANT_MSVC_PREPROCESSOR
1245
// Macro mapping utility by William Swanson https://github.com/swansontec/map-macro/blob/master/map.h
1346
#define LIBASSERT_EVAL0(...) __VA_ARGS__
@@ -208,9 +241,7 @@ LIBASSERT_END_NAMESPACE
208241
if constexpr(false) { (void)(expr);} \
209242
LIBASSERT_WARNING_PRAGMA_PUSH \
210243
LIBASSERT_EXPRESSION_DECOMP_WARNING_PRAGMA \
211-
auto libassert_decomposer = libassert::detail::expression_decomposer( \
212-
libassert::detail::expression_decomposer{} << expr \
213-
); \
244+
auto libassert_decomposer = LIBASSERT_DECOMPOSER(expr);\
214245
LIBASSERT_WARNING_PRAGMA_POP \
215246
LIBASSERT_ASSERT_MAIN_BODY( \
216247
expr, \

tests/unit/assertion_tests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,27 @@ TEST(LibassertBasic, NULLMacroComparison) {
275275
);
276276
}
277277

278+
TEST(LibassertBasic, Bitfields) {
279+
struct Bit {
280+
int bit : 1;
281+
};
282+
Bit bit{1};
283+
ASSERT_VAL(bit.bit == 1);
284+
CHECK(
285+
ASSERT(bit.bit == 1),
286+
R"XX(
287+
|Assertion failed at <LOCATION>:
288+
| ASSERT(bit.bit == 1);
289+
)XX"
290+
);
291+
292+
CHECK(ASSERT(1 == bit.bit),
293+
R"XX(
294+
|Assertion failed at <LOCATION>:
295+
| ASSERT(1 == bit.bit);
296+
)XX");
297+
}
298+
278299

279300
TEST(LibassertBasic, LiteralFormatting) {
280301
const uint16_t flags = 0b000101010;
@@ -700,6 +721,7 @@ TEST(LibassertBasic, ExpressionDecomposition) {
700721
| x -= x -= 1 => 0
701722
)XX"
702723
);
724+
703725
CHECK(
704726
ASSERT(true ? false : true, "pffft"),
705727
R"XX(

0 commit comments

Comments
 (0)