3

I am checking numeric value range with type traits, and unsigned types generate warning.

Comparison of unsigned expression >= 0 is always true

How to disable some warning at specific code range? I used GCC style #pragma with Clang but this doesn't work. Here's my code.

template<typename originT, typename destinationT>
void
assertForNumericRange(const originT value)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored  "-Wtype-limits"
    assertWithReason(value >= std::numeric_limits<destinationT>::min());
    assertWithReason(value <= std::numeric_limits<destinationT>::max());
#pragma GCC diagnostic pop
}

Note

Currently, I divided the assertion into three groups, floating-point, unsigned int, signed int. But I wish to integrate them into one if possible.

I am using Xcode 5.0 beta. In command-line, it reports this: Apple LLVM version

5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
eonil
  • 83,476
  • 81
  • 317
  • 516
  • I think you should change the title of your question, as now you are looking for a different answer (how to check if the value of a variable can fit in another variable possibly of different type without generating compiling warning) – Antonio Jun 20 '13 at 13:28
  • @Antonio I still looking for a method to suppress warnings. If I have to ask for it, I will post a new question. Thanks. – eonil Jun 20 '13 at 13:47
  • The warning you are getting is correct, allowed you to discover some nasty problems, and shouldn't be removed through some pragma definition. In you, I would try to add more logic (if statements) to your function, not sure if it removes warning if within some code that the compiler knows will never be executed. – Antonio Jun 20 '13 at 14:12
  • @Antonio Actually, I tried to put some `if (std::is_signed::value) ... `, but compiler still generates warnings based on subexpressions. As suppressing warning cannot be a good design. so maybe I will just use separated assertion methods. – eonil Jun 20 '13 at 16:29

3 Answers3

1

Wich version of Clang are you using? From the Clang User Manual it should work exaclty the way you did. But your range assertions won't work the way you probably want them to work:

That first assertion itself does not make much sense, if destinationT is unsigned, so min gives 0. Either originT is unsigned as well, then it's clearly not negative, wich is what the compiler warns you about. Or originT is signed, the comparison will convert one or both of the operand to other types, e.g. possibly converting value to an unsigned (and thus positive) representation.

Consider for example

 assertForNumericRange<signed char, unsigned long>( (signed char)-1);  

The comparisons between (signed char)-1 and unsigned long will promote the -1 to unsigned long, effectively giving following assertions for 32bit long:

assertWithReason((unsigned long)0xFFFFFFFF >= std::numeric_limits<destinationT>::min());
assertWithReason((unsigned long)0xFFFFFFFF <= std::numeric_limits<destinationT>::max());

Both comparisons will give true, while -1 is clearly not in the range of unsigned long's values.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • Thanks, this is the only answer that actually answers the question, but only because it links to the answer in the Clang User Manual. – Harvey Mar 08 '15 at 22:14
0

First of all, be aware that for floating point types, e.g.

std::numeric_limits<float>::min()

returns the minimum positive normalized value (>0), while for integer types

std::numeric_limits<T>::min()

returns the smallest non positive number (<=0).

Minimum negative number for a floating point type is:

-std::numeric_limits<T>::max()

I think you have to combine different numeric_limits methods/members (like is_integer and is_signed) and if statements, also to get rid of your warnings. (From the efficiency point of view) You do not have to worry of getting a too complicated function, as most of the checks will be evaluated at compile time and will have no influence on the execution time. In fact, if you can avoid some unnecessary checks at running time because of some checks done at compile time, your program will be faster.

You should also use std::is_same<T,U>::value, and avoid any further check if that is true.

Antonio
  • 19,451
  • 13
  • 99
  • 197
  • Thanks for picking this up! I didn't know this stuff. Now I think I should use `std::numeric_limits::lowest()`. – eonil Jun 20 '13 at 08:03
  • 1
    It's said to be implementation dependent, I wouldn't trust. Safest is using `-std::numeric_limits::max()` when `std::numeric_limits::is_integer` is false. – Antonio Jun 20 '13 at 13:27
0

Check this Q&A I just posted. For me it compiles without warnings, you should check it on Clang. Extension to floating point types is possible.

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197