Skip to content

Commit ccabd4d

Browse files
committed
Add enum types to what is captured by value by default
As it turns out, enums can be used to declare bitfields, and we cannot form a reference to a bitfield in the cpature. Thus, we add `std::is_enum` as a criteria to the default for `capture_by_value`, so that enum-based bitfields are also captured by value and thus decomposable. Closes #3001
1 parent a1c7ee1 commit ccabd4d

20 files changed

+164
-29
lines changed

src/catch2/internal/catch_decomposer.hpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@
7878
*
7979
* 3) If a type has no linkage, we also cannot capture it by reference.
8080
* The solution is once again to capture them by value. We handle
81-
* the common cases by using `std::is_arithmetic` as the default
82-
* for `Catch::capture_by_value`, but that is only a some-effort
83-
* heuristic. But as with 2), users can specialize `capture_by_value`
84-
* for their own types as needed.
81+
* the common cases by using `std::is_arithmetic` and `std::is_enum`
82+
* as the default for `Catch::capture_by_value`, but that is only a
83+
* some-effort heuristic. These combine to capture all possible bitfield
84+
* bases, and also some trait-like types. As with 2), users can
85+
* specialize `capture_by_value` for their own types as needed.
8586
*
8687
* 4) To support C++20 and make the SFINAE on our decomposing operators
8788
* work, the SFINAE has to happen in return type, rather than in
@@ -133,13 +134,22 @@ namespace Catch {
133134
using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
134135
}
135136

136-
// Note: There is nothing that stops us from extending this,
137-
// e.g. to `std::is_scalar`, but the more encompassing
138-
// traits are usually also more expensive. For now we
139-
// keep this as it used to be and it can be changed later.
137+
// Note: This is about as much as we can currently reasonably support.
138+
// In an ideal world, we could capture by value small trivially
139+
// copyable types, but the actual `std::is_trivially_copyable`
140+
// trait is a huge mess with standard-violating results on
141+
// GCC and Clang, which are unlikely to be fixed soon due to ABI
142+
// concerns.
143+
// `std::is_scalar` also causes issues due to the `is_pointer`
144+
// component, which causes ambiguity issues with (references-to)
145+
// function pointer. If those are resolved, we still need to
146+
// disambiguate the overload set for arrays, through explicit
147+
// overload for references to sized arrays.
140148
template <typename T>
141149
struct capture_by_value
142-
: std::integral_constant<bool, std::is_arithmetic<T>{}> {};
150+
: std::integral_constant<bool,
151+
std::is_arithmetic<T>::value ||
152+
std::is_enum<T>::value> {};
143153

144154
#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
145155
template <>

tests/SelfTest/Baselines/automake.sw.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Nor would this
2626
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - double
2727
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - float
2828
:test-result: XFAIL #2615 - Throwing in constructor generator fails test case but does not abort
29+
:test-result: PASS #3001: Enum-based bitfields can be captured
2930
:test-result: XFAIL #748 - captures with unexpected exceptions
3031
:test-result: PASS #809
3132
:test-result: PASS #833

tests/SelfTest/Baselines/automake.sw.multi.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - double
2525
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - float
2626
:test-result: XFAIL #2615 - Throwing in constructor generator fails test case but does not abort
27+
:test-result: PASS #3001: Enum-based bitfields can be captured
2728
:test-result: XFAIL #748 - captures with unexpected exceptions
2829
:test-result: PASS #809
2930
:test-result: PASS #833

tests/SelfTest/Baselines/compact.sw.approved.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smalle
8585
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
8686
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
8787
Generators.tests.cpp:<line number>: failed: unexpected exception with message: 'failure to init'; expression was: {Unknown expression after the reported line}
88+
Compilation.tests.cpp:<line number>: passed: bf.e == 1 for: 1 == 1
89+
Compilation.tests.cpp:<line number>: passed: 1 == bf.e for: 1 == 1
8890
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: {Unknown expression after the reported line}
8991
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
9092
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -2869,7 +2871,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
28692871
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
28702872
Misc.tests.cpp:<line number>: passed:
28712873
Misc.tests.cpp:<line number>: passed:
2872-
test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected
2873-
assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected
2874+
test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected
2875+
assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected
28742876

28752877

tests/SelfTest/Baselines/compact.sw.multi.approved.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smalle
8383
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
8484
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
8585
Generators.tests.cpp:<line number>: failed: unexpected exception with message: 'failure to init'; expression was: {Unknown expression after the reported line}
86+
Compilation.tests.cpp:<line number>: passed: bf.e == 1 for: 1 == 1
87+
Compilation.tests.cpp:<line number>: passed: 1 == bf.e for: 1 == 1
8688
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: {Unknown expression after the reported line}
8789
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
8890
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -2858,7 +2860,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
28582860
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
28592861
Misc.tests.cpp:<line number>: passed:
28602862
Misc.tests.cpp:<line number>: passed:
2861-
test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected
2862-
assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected
2863+
test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected
2864+
assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected
28632865

28642866

tests/SelfTest/Baselines/console.std.approved.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,6 @@ due to unexpected exception with message:
17191719
Why would you throw a std::string?
17201720

17211721
===============================================================================
1722-
test cases: 431 | 331 passed | 76 failed | 7 skipped | 17 failed as expected
1723-
assertions: 2267 | 2090 passed | 136 failed | 41 failed as expected
1722+
test cases: 432 | 332 passed | 76 failed | 7 skipped | 17 failed as expected
1723+
assertions: 2269 | 2092 passed | 136 failed | 41 failed as expected
17241724

tests/SelfTest/Baselines/console.sw.approved.txt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,22 @@ Generators.tests.cpp:<line number>: FAILED:
772772
due to unexpected exception with message:
773773
failure to init
774774

775+
-------------------------------------------------------------------------------
776+
#3001: Enum-based bitfields can be captured
777+
-------------------------------------------------------------------------------
778+
Compilation.tests.cpp:<line number>
779+
...............................................................................
780+
781+
Compilation.tests.cpp:<line number>: PASSED:
782+
REQUIRE( bf.e == 1 )
783+
with expansion:
784+
1 == 1
785+
786+
Compilation.tests.cpp:<line number>: PASSED:
787+
REQUIRE( 1 == bf.e )
788+
with expansion:
789+
1 == 1
790+
775791
-------------------------------------------------------------------------------
776792
#748 - captures with unexpected exceptions
777793
outside assertions
@@ -19184,6 +19200,6 @@ Misc.tests.cpp:<line number>
1918419200
Misc.tests.cpp:<line number>: PASSED:
1918519201

1918619202
===============================================================================
19187-
test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected
19188-
assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected
19203+
test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected
19204+
assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected
1918919205

tests/SelfTest/Baselines/console.sw.multi.approved.txt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,22 @@ Generators.tests.cpp:<line number>: FAILED:
770770
due to unexpected exception with message:
771771
failure to init
772772

773+
-------------------------------------------------------------------------------
774+
#3001: Enum-based bitfields can be captured
775+
-------------------------------------------------------------------------------
776+
Compilation.tests.cpp:<line number>
777+
...............................................................................
778+
779+
Compilation.tests.cpp:<line number>: PASSED:
780+
REQUIRE( bf.e == 1 )
781+
with expansion:
782+
1 == 1
783+
784+
Compilation.tests.cpp:<line number>: PASSED:
785+
REQUIRE( 1 == bf.e )
786+
with expansion:
787+
1 == 1
788+
773789
-------------------------------------------------------------------------------
774790
#748 - captures with unexpected exceptions
775791
outside assertions
@@ -19173,6 +19189,6 @@ Misc.tests.cpp:<line number>
1917319189
Misc.tests.cpp:<line number>: PASSED:
1917419190

1917519191
===============================================================================
19176-
test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected
19177-
assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected
19192+
test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected
19193+
assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected
1917819194

tests/SelfTest/Baselines/console.swa4.approved.txt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,22 @@ Generators.tests.cpp:<line number>: FAILED:
772772
due to unexpected exception with message:
773773
failure to init
774774

775+
-------------------------------------------------------------------------------
776+
#3001: Enum-based bitfields can be captured
777+
-------------------------------------------------------------------------------
778+
Compilation.tests.cpp:<line number>
779+
...............................................................................
780+
781+
Compilation.tests.cpp:<line number>: PASSED:
782+
REQUIRE( bf.e == 1 )
783+
with expansion:
784+
1 == 1
785+
786+
Compilation.tests.cpp:<line number>: PASSED:
787+
REQUIRE( 1 == bf.e )
788+
with expansion:
789+
1 == 1
790+
775791
-------------------------------------------------------------------------------
776792
#748 - captures with unexpected exceptions
777793
outside assertions
@@ -952,6 +968,6 @@ Condition.tests.cpp:<line number>: FAILED:
952968
CHECK( true != true )
953969

954970
===============================================================================
955-
test cases: 33 | 27 passed | 3 failed | 3 failed as expected
956-
assertions: 102 | 94 passed | 4 failed | 4 failed as expected
971+
test cases: 34 | 28 passed | 3 failed | 3 failed as expected
972+
assertions: 104 | 96 passed | 4 failed | 4 failed as expected
957973

tests/SelfTest/Baselines/junit.sw.approved.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<testsuitesloose text artifact
33
>
4-
<testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2300" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
4+
<testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2302" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
55
<properties>
66
<property name="random-seed" value="1"/>
77
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@@ -60,6 +60,7 @@ failure to init
6060
at Generators.tests.cpp:<line number>
6161
</error>
6262
</testcase>
63+
<testcase classname="<exe-name>.global" name="#3001: Enum-based bitfields can be captured" time="{duration}" status="run"/>
6364
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions" time="{duration}" status="run"/>
6465
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}" status="run">
6566
<skipped message="TEST_CASE tagged with !mayfail"/>

0 commit comments

Comments
 (0)