Catch2 icon indicating copy to clipboard operation
Catch2 copied to clipboard

operator| for ResultDisposition::Flags triggers clang-analyzer-optin.core.EnumCastOutOfRange (clang-tidy-18)

Open Minoru opened this issue 1 year ago • 0 comments

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: '*'
...
  1. Create reproducer.cpp with the following contents:
#include "catch_amalgamated.hpp"

TEST_CASE("reproducer")
{
    REQUIRE_FALSE(0 == 0);
}
  1. Create empty file compile_flags.txt
  2. 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<ResultDisposition::Flags>( static_cast<int>( 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<ResultDisposition::Flags>( static_cast<int>( lhs ) |
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  844 |                                                       static_cast<int>( 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 with this lint, and plans to fix it. Until then, would it be possible to add a suppression rule to Catch2?

Minoru avatar Sep 20 '24 17:09 Minoru