operator| for ResultDisposition::Flags triggers clang-analyzer-optin.core.EnumCastOutOfRange (clang-tidy-18)
- Dominant language
- C++
- Stars
- 21.5k
- Forks
- 3.5k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 2
Description
**Describe the bug**
Starting with Catch 3.7.1, `operator|` for `ResultDisposition::Flags` triggers clang-analyzer-optin.core.EnumCastOutOfRange warning because it casts an arbitrary integer into an `enum` value. This results in a warning for my tests.
**Expected behavior**
My tests pass `clang-tidy` without warnings.
**Reproduction steps**
1. Create .clang-tidy with the following contents:
```
---
Checks: 'clang-analyzer-*'
WarningsAsErrors: '*'
...
```
2. Create reproducer.cpp with the following contents:
```c++
#include "catch_amalgamated.hpp"
TEST_CASE("reproducer")
{
REQUIRE_FALSE(0 == 0);
}
```
3. Create empty file compile_flags.txt
4. Run clang-tidy:
```
clang-tidy-18 reproducer.cpp
```
Observe the output:
```
1 warning generated.
/home/builder/src/catch_amalgamated.hpp:843:16: error: The value '5' provided to the cast expression is not in the valid range of values for 'Flags' [clang-analyzer-optin.core.EnumCastOutOfRange,-warnings-as-errors]
843 | return static_cast( static_cast( lhs ) |
| ^
/home/builder/src/catch_amalgamated.hpp:833:37: note: enum declared here
833 | struct ResultDisposition { enum Flags {
| ~~~~~^~~~~~~
834 | Normal = 0x01,
| ~~~~~~~~~~~~~~
835 |
836 | ContinueOnFailure = 0x02, // Failures fail test, but execution continues
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
837 | FalseTest = 0x04, // Prefix expression with !
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
838 | SuppressFail = 0x08 // Failures are reported but do not fail the test
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
839 | }; };
| ~
/home/builder/src/reproducer.cpp:5:5: note: Calling 'operator|'
5 | REQUIRE_FALSE(0 == 0);
| ^
/home/builder/src/catch_amalgamated.hpp:6287:70: note: expanded from macro 'REQUIRE_FALSE'
6287 | #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/builder/src/catch_amalgamated.hpp:5683:142: note: expanded from macro 'INTERNAL_CATCH_TEST'
5683 | Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
| ^~~~~~~~~~~~~~~~~
/home/builder/src/catch_amalgamated.hpp:843:16: note: The value '5' provided to the cast expression is not in the valid range of values for 'Flags'
843 | return static_cast( static_cast( lhs ) |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
844 | static_cast( rhs ) );
| ~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning treated as error
```
**Platform information:**
- OS: **Debian 12 amd64**
- Compiler+version: **clang-tidy 18**
- Catch version: **3.7.1**
**Additional context**
Catch 3.7.0 doesn't exhibit this behaviour because the `operator|` is in .cpp and can't be analysed by clang-tidy.
Apparently [upstream is aware of the problem](https://github.com/llvm/llvm-project/issues/76208) with this lint, and plans to fix it. Until then, would it be possible to add a suppression rule to Catch2?
Contributor guide
Assessment
This issue has not been assessed yet.