Bug 95148 - -Wtype-limits always-false warning triggered despite comparison being avoided
Summary: -Wtype-limits always-false warning triggered despite comparison being avoided
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wtype-limits
  Show dependency treegraph
 
Reported: 2020-05-15 09:25 UTC by Eyal Rozenberg
Modified: 2024-01-27 22:16 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eyal Rozenberg 2020-05-15 09:25:18 UTC
Consider the following program:

  #include <type_traits>

  int main() {
          unsigned x { 5 };
          return (std::is_signed<decltype(x)>::value and (x < 0)) ? 1 : 0;
  }

when compiling it with GCC versions 11.0 20200511, 10.1, 9.2.1, 8.3.0, I get the warning:

  a.cpp:5:52: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]

I should not be getting this warning, because when x is unsigned, the comparison is never performed, due to the short-circuit semantics of `and`. This can be easily determined by the compiler - and probably is. No less importantly, the author of such a line in a program clearly specified his/her intent here with this check. 

clang doesn't seem to issue a warn inf does come to pass.
Comment 1 Eric Gallager 2022-10-26 02:18:56 UTC
I think this counts as an example of bug 4210
Comment 2 Vincent Lefèvre 2022-10-26 08:47:46 UTC
Simpler code, also for C:

int f (void)
{
  unsigned int x = 5;
  return 0 && x < 0 ? 1 : 0;
}

Alternatively:

int f (void)
{
  unsigned int x = 5;
  if (0)
    return x < 0 ? 1 : 0;
  return 0;
}

With -Wtype-limits, GCC 12.2.0 warns on both.
Comment 3 Jonathan Wakely 2022-10-26 09:49:06 UTC
(In reply to Eyal Rozenberg from comment #0)
>   a.cpp:5:52: warning: comparison of unsigned expression < 0 is always false
> [-Wtype-limits]

Both branches of the condition must be instantiated by the compiler, and so this warning (which happens in the front-end, not after optimizing the AST) gets triggered.


> I should not be getting this warning, because when x is unsigned, the
> comparison is never performed, due to the short-circuit semantics of `and`.

Those semantics only apply at runtime.

> This can be easily determined by the compiler - and probably is.

Not in the compiler front end.

> No less
> importantly, the author of such a line in a program clearly specified
> his/her intent here with this check. 

But `x && y` doesn't prevent y being instantiated, it only prevents it being evaluated at runtime. This is a compile-time warning based on the types involved in the expression, and the expression is being compiled.  This is analogous to false && func(x) which requires a definition of func(x) in the program even if it will never get called at runtime.

If you want the comparison to be completely elided based on the type, then the language provides a solution:

  if constexpr (is_signed_v<decltype(x)>)
    return x < 1;
  return false;

(This feature only makes sense in template code, but then so does testing is_signed.) 

I think to avoid this warning the front end would have to disable this particular warning for branches that depend on a compile-time constant. I don't know if that's currently possible in GCC.
Comment 4 Eyal Rozenberg 2022-10-26 19:09:29 UTC
(In reply to Jonathan Wakely from comment #3)

> > I should not be getting this warning, because when x is unsigned, the
> > comparison is never performed, due to the short-circuit semantics of `and`.
> 
> Those semantics only apply at runtime.

But the semantics are known at compile time, and so are the argument values.

> > No less
> > importantly, the author of such a line in a program clearly specified
> > his/her intent here with this check. 
> 
> But `x && y` doesn't prevent y being instantiated, it only prevents it being
> evaluated at runtime.

You mean, it only prevents a comparison of an unsigned and signed values to actually ever being carried out? Yeah :-)


> >   a.cpp:5:52: warning: comparison of unsigned expression < 0 is always false
> > [-Wtype-limits]
> 
> Both branches of the condition must be instantiated by the compiler, and so
> this warning (which happens in the front-end, not after optimizing the AST)
> gets triggered.

Well, that's a bug. If you're saying that the front-end produces the warning, then delay it to a later stage, in which you can figure out whether the warning is called for. 

clang doesn't produce this warning.

> I think to avoid this warning the front end would have to disable this
> particular warning for branches that depend on a compile-time constant. I
> don't know if that's currently possible in GCC.

Ok, I didn't say that the solution would be easy...