How to disable implicit conversion changes signedness warning in CMAKE - c++

Does anybody know if there is a way to disable this kind of warning given by clang in CMAKE please ?
std::vector<float> v{1.f, 2.f, 1.f};
int i = 1;
float foo = v[i]; // Here we get the warning, variable i should be a size_t
...
Implicit conversion changes signedness: 'int' to 'std::__1::vector<float>::size_type' (aka 'unsigned long')
Clang compiler gives me a warning on v[i] as it wants me to cast it as a size_t which is quite verbose if I do explicit casting everywhere.
Also, I don't want to use size_t. For me this type it is error prone as it breaks the standard substraction when getting negative results. (my vectors will never exceed 2^31 btw)

Related

Clang-Tidy Narrowing Conversion from uint8_t to float

I'm getting a clang-tidy warning that reads narrowing conversion from 'int' to 'float' when I convert from a uint8_t to a float, which to my understanding is not a narrowing conversion since float can represent every integer that a uint8_t can.
Code example:
uint8_t testVar = 8;
float test2 = 2.0f * testVar;
clang-tidy flags the second line of that with the warning cppcoreguidelines-narrowing-conversions: narrowing conversion from 'int' to 'float'. In my IDE, the squiggle shows up under the testVar.
According to the reference, this warning should be flagged if we convert from an integer to a narrower floating-point (e.g. uint64_t to float), but to the best of my knowledge, float is not narrower than uint8_t.
Am I fundamentally misunderstanding these data types, or is something else going on here?
I'm on LLVM version 11.0.0 if that matters.

Clang gives me a warning of signedness change, however the code still produces correct output

I was analyzing some warnings in a codebase and got puzzled by this one generated by Clang
Consider the following C++ code:
#include <iostream>
int main(int , char *[])
{
uint32_t val1 = 10;
int32_t val2 = -20;
int32_t result = val1 + val2;
std::cout << "Result is " << result << "\n";
return 0;
}
Clang gives me the following warning when compiling this code with -Wconversion
<source>:9:25: warning: implicit conversion changes signedness:
'unsigned int' to 'int32_t' (aka 'int') [-Wsign-conversion]
int32_t result = val1 + val2;
~~~~~~ ~~~~~^~~~~~
<source>:9:27: warning: implicit conversion changes signedness:
'int32_t' (aka 'int') to 'unsigned int' [-Wsign-conversion]
int32_t result = val1 + val2;
~ ^~~~
2 warnings generated.
GCC also gives me this warning, however I need to provide -Wsign-conversion to trigger it.
The warning says that val2 will be cast to an unsigned int and therefore will loose it's sign. So far so good. However I was expecting that the code above would produce incorrect output, to my surprise it works perfectly fine.
Result is -10
See the program running on both compilers on godbolt.
The cast does not happen in the compiled code and val2 keep its original value. The result of the computation is correct. What is the actual danger that this warning is warning me against? How can I trigger this behaviour? Is the warning bogus?
The second conversion is where things become implementation dependent.
The first (evaluation of expression val1+val2) triggers conversion of val2 to unsigned from signed, which is standard-compliant and documented. The result of the expression is therefore unsigned.
The second (conversion of the resulting unsigned back to signed) is where potential problems ensue. If the unsigned value is not within the defined domain of the target signed type (and in this case, it isn't), implementation behavior ensues, which you cannot assume is portable across the known universe.
What is the actual danger that this warning is warning me against?
The potential danger is that you may have been unaware of the implicit sign conversion, and have made it by accident. If it is intentional and behaves as desired, then there is no danger).
How can I trigger this behaviour?
You already have triggered an implicit sign conversion.
That said, if you want to see some output which may be surprising to you, try this instead:
std::cout << val1 + val2;
Is the warning bogus?
Depends on your definition of bogus.
There definitely is an implicit sign conversion in the program, and therefore if you ask the compiler to warn about implicit sign conversions, then it is entirely correct for the compiler to warn about the implicit sign conversion that is in the program.
There is a reason why this warning option is not enabled by default, nor when enabling "all" warnings using -Wall, nor even when enabling "extra" warnings with -Wextra. These sign conversion warnings warn about a program with well defined behaviour, but which may be surprising to someone who is not paying close attention. A program can be meaningful and correct despite this warning.

Warning narrowing conversion (uint32 to uint8)

i have this warning. Can u help me ?
warning: narrowing conversion of ‘action’ from ‘uint32 {aka unsigned int}’ to ‘uint8 {aka unsigned char}’
How to convert uint32 to uint8 securely ?
Thanks
The warning is correct, such a conversion is potentially dangerous (it loses 24 higher bits).
You can tell the compiler that you really want this [unsafe] conversion by using explicit cast:
uint8_t my_byte_var = static_cast<uint8_t>(my_int32_var);
This should suppress the warning.
The narrowing warning/error should only arise if you use list-initialization, e.g.:
uint32_t action = 12345;
uint8_t val{action};
You could instead just use normal assignment:
uint8_t val = action;
The narrowing is still going to happen though, as there is no way for 12345 to fit in a uint8_t, so you'll be left with 9. If you're OK with that, then there's your solution. If not, then it's a good thing there's a warning because you're using the wrong type!

Compiler error C4244: 'initializing' : conversion from '__int64' to 'int', possible loss of data

I am trying to use std::count over std::vector as following:
int count = std::count( stdVector.begin(), stdVector.end(), "element" );
On windows, it gives the following compiler error.
error C4244: 'initializing' : conversion from '__int64' to 'int', possible loss of data
If I change the code as following on Windows compiler does not appear.
auto count = std::count( stdVector.begin(), stdVector.end(), "element" );
However, now I face the following error on linux for the above change.
error: ISO C++ forbids declaration of 'count' with no type
How would I use std::count which will get build on both the platform without any error?
There are two things that can conflict differently in different environments:
The first is auto as a deduced type is a C++11 feature. May be the linux compiler does not have it as a default (just use -std=c++11, and if it does not have it, upgrade!)
The other is that the return type of std::count is size_t, not int, and size_t to int conversion may lose data depending on on how size_t is defined (there is at least a signed / unsigned mismatch and eventually a different in size of the two types, like 32 bit for int and 64 bit for size_t).
The reason you get this warning is that on a 64 bit build, the standard containers use 64 bit values for size types, and implicitly converting a 64 bit value (e.g. size_t) to a 32 bit value (e.g. int) can lose data.
The actual data type returned by the count function, which in this case would be std::vector<T>::difference_type, is probably the best type to use if your compiler doesn't support auto. Using size_t would probably work without warning as well, and is a lot shorter to type.
Alternatively, if you're not bothered by the risk of data loss (e.g. are never planning to have more than 2^32-1 objects in the container) you can simply cast the warning away:
int count = static_cast<int>( std::count(stdVector.begin(), stdVector.end(), "element") );

Implicit conversion while using += operator?

Conside the following code:
int main()
{
signed char a = 10;
a += a; // Line 5
a = a + a;
return 0;
}
I am getting this warning at Line 5:
d:\codes\operator cast\operator
cast\test.cpp(5) : warning C4244: '+='
: conversion from 'int' to 'signed
char', possible loss of data
Does this mean that += operator makes an implicit cast of the right hand operator to int?
P.S: I am using Visual studio 2005
Edit: This issue occurs only when the warning level is set to 4
What you are seeing is the result of integral promotion.
Integral promotion is applied to both arguments to most binary expressions involving integer types. This means that anything of integer type that is narrower than an int is promoted to an int (or possibly unsigned int) before the operation is performed.
This means that a += a is performed as an int calculation but because the result is stored back into a which is a char the result has to undergo a narrowing conversion, hence the warning.
Really, there shouldn't be any warning for this line. the operator += is very well defined for all basic types. I would place that as a small bug of VC++ 2005.