Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REQUIRE macro hides sign compare warnings (gcc/clang) #1880

Closed
danadam opened this issue Mar 6, 2020 · 2 comments
Closed

REQUIRE macro hides sign compare warnings (gcc/clang) #1880

danadam opened this issue Mar 6, 2020 · 2 comments
Labels
Help wanted Issue outside of the maintainers expertise Warnings issue

Comments

@danadam
Copy link

danadam commented Mar 6, 2020

In the following code:

#define CATCH_CONFIG_MAIN
#include <catch.hpp>

TEST_CASE("foo")
{
    uint32_t u = 0;
    int32_t i = -1;
    if (u > i) printf("foo\n");    // line 8
    REQUIRE(u > i);                // line 9
    if (u > i) printf("foo\n");    // line 10
}

When compiled with -Wall (gcc) or -Wextra (clang), it reports warnings on line 8 and 10 but not 9. See https://godbolt.org/z/W9wQqy :

<source>:8:11: error: comparison of integer expressions of different signedness: 'uint32_t' {aka 'unsigned int'} and 'int32_t' {aka 'int'} [-Werror=sign-compare]
    8 |     if (u > i) printf("foo\n");
      |         ~~^~~
<source>:10:11: error: comparison of integer expressions of different signedness: 'uint32_t' {aka 'unsigned int'} and 'int32_t' {aka 'int'} [-Werror=sign-compare]
   10 |     if (u > i) printf("foo\n");
      |         ~~^~~

Looks like msvc reports warnings on all 3 lines, see https://godbolt.org/z/4uBsXT:

<source>(8): warning C4018: '>': signed/unsigned mismatch
<source>(9): warning C4018: '>': signed/unsigned mismatch
<source>(10): warning C4018: '>': signed/unsigned mismatch

When you put parentheses around the expression, i.e., REQUIRE((u > i)), then gcc and clang report warning on that line too.

@horenmar
Copy link
Member

horenmar commented Mar 8, 2020

When you put parentheses around the expression, i.e., REQUIRE((u > i)), then gcc and clang report warning on that line too.

Right, that prevents Catch from decomposing and stringifying the expression...

Internally Catch suppresses warnings when evaluating the captured expression because of literals. In plain C++ code, this will not warn

size_t i = ...;
if (i < 2)

because the literal 2 can be easily converted into size_t without losing information. However, if you add extra indirection like Catch does, then that 2 is inferred to be an int. This means that without warning suppression, using REQUIRE(i < 2); in the above example would cause a warning about mismatched signedness in comparison.

This is obviously not ideal, so Catch2 uses a mitigation: it mentions the expression again in a context that will not be evaluated, like this: while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ), where __VA_ARGS__ is expression inside REQUIRE.

This works for MSVC, and used to work for Clang (but I had to go back to clang 3.4 for the warning to trigger), but apparently does not for current version of Clang or GCC.

Summary: I would like to have some way to force the compiler to check the code as written, without decomposition, but the suppression inside the actual evaluation is required for usability.

@horenmar horenmar added Help wanted Issue outside of the maintainers expertise Warnings issue labels Mar 8, 2020
@horenmar
Copy link
Member

There might be a way to work around this https://godbolt.org/z/vbqmJx

horenmar added a commit that referenced this issue May 1, 2020
The old code caused warnings to fire under MSVC, and Clang <3.8.
I could not find a GCC version where it worked, but I assume that it
did at some point.

This new code causes all of MSVC, GCC, Clang, in current versions,
to emit signed/unsigned comparison warning in test like this:

```cpp
TEST_CASE() {
    int32_t i = -1;
    uint32_t j = 1;
    REQUIRE(i != j);
}
```

Where previously only MSVC would emit the warning.

Fixes #1880
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help wanted Issue outside of the maintainers expertise Warnings issue
Projects
None yet
Development

No branches or pull requests

2 participants