3

I have legacy code performing a subtraction of signed int with an unsigned int and a cast of the result to a float. It was giving expected result with Visual Studio 6 to 2013. With Visual Studio 2017 (15.6.3) the result is not the expected one. I have simplified the code to this:

    unsigned int uint = 10;
    signed int sint = 9;
    signed int res = sint - uint;
    float fres = static_cast<float>(sint - uint);

res value is -1 with all the VS I have tested. With VS 2013 and before, fres value is -1. With VS 2017, fres value is 4.29496730e+09, that is to say UINT_MAX. I have found here that the fres result in VS 2017 is the one conforming to the C++11 standard (if I correctly understand). VS 2017 compiler is not issuing any warning on this.

How can I detect all the occurrences of such a bad subtraction in my code base?

Frédéric
  • 9,364
  • 3
  • 62
  • 112
Nicolas D.
  • 83
  • 5
  • The subtraction itself is defined behavior governed by [implicit type promotion rules](https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules) specifically see the part under arithmetic conversions related to one signed and one unsigned integer type. That being said, since it is well defined behavior there is no MSVC warning to enable to catch promotions here. – Cory Kramer Jan 12 '21 at 15:16
  • 1
    Are you allowed to use other tools or do you have to stick with Visual Studio? `clang-tidy` is detecting this, and other linters probably can as well. – Stephen Newell Jan 12 '21 at 15:17
  • Clang is available in my company. I will give it a try, thanks. – Nicolas D. Jan 12 '21 at 17:23
  • Unfortunately I can not generate my project for this target (I'm using cmake) as many dependencies are not available for it. – Nicolas D. Jan 13 '21 at 13:04
  • @NicolasD. You don't have to compile it with clang, it suffice to use `clang-tidy` linter (tool to check your code for common mistakes) and then compile it with msvc as you are used to. See here: https://learn.microsoft.com/en-us/cpp/code-quality/clang-tidy?view=msvc-160 – Roman Pavelka Jan 14 '21 at 14:36

1 Answers1

4

MSVC is not able to detect this even with /W4 /c or /Wall and additional linter is required, e.g. clang-tidy is detecting this (courtesy to Stephen Newell).

When using g++ compiler, you are looking for -Wsign-conversion compiler option.

Roman Pavelka
  • 3,736
  • 2
  • 11
  • 28
  • Thanks, but /W4 /c is not issuing any warning on this line: float fres = static_cast(sint - uint); – Nicolas D. Jan 12 '21 at 17:20
  • I see, I made a mistake and the linked document is only about "signed const type that has a negative value". I googled it a lit bit more and it seems that @cory-kramer is right and there is no MSVC equivalent of g++'s `-Wsign-conversion` :-( I will update my answer. – Roman Pavelka Jan 13 '21 at 11:00
  • @NicolasD.: I have found these two sources below, may you try `/Wall`? https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level?view=msvc-160 https://learn.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=msvc-160 – Roman Pavelka Jan 13 '21 at 11:05
  • No warning on this either with /Wall. I tried to generate my project for g++, but it has too many dependencies not available for this target (I'm using cmake). So I will just fix the already identified line of code with this issue and will keep it in mind if I encounter other weird new bugs with the version compiled under VS 2017. Can you please remove of your answer the VC++ part as it is not working? I will then accept your answer as it should still be useful for people able to use g++. – Nicolas D. Jan 13 '21 at 13:01
  • Regarding "I tried to generate my project for g++, but it has too many dependencies not available for this target (I'm using cmake)" That is strange because if you have dependencies using one compiler, all others should be able to use them as well. Maybe just linker path or include path is not correctly set when using these other compilers... BTW "Target" is the binary you are producing: https://softwareengineering.stackexchange.com/questions/344599/what-exactly-is-a-compile-target – Roman Pavelka Jan 14 '21 at 16:13