Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-Wsign-compare warning in g++

Tags:

c++

c++11

g++

I have a code which uses comparison of 64-bit integers. It looks similar to the following:

#include <cstdio>

long long getResult()
{
    return 123456LL;
}

int main()
{
    long long result = getResult();

    if (result > 0x000FFFFFFFFFFFFFLL
        || result < 0xFFF0000000000000LL)
    {
        printf("Something is wrong.\n");

        if (result > 0x000FFFFFFFFFFFFFLL
            || result < -4503599627370496LL)
        {
            printf("Additional check failed too.\n");
        }
        else
        {
            printf("Additional check went fine.\n");
        }
    }
    else
    {
        printf("Everything is fine.\n");
    }

    return 0;
}

When this code is compiled in g++ (tried different versions on Ubuntu 12.04 x64: 4.6.3, 4.6.4, 4.7.3, 4.8.0) with flags -Wall -pedantic -std=c++0x test.cpp -o test I get -Wsign-compare warning for second line of the first if statement (output from g++-4.8):

test.cpp:13:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 || result < 0xFFF0000000000000LL)
             ^

And when the test program is run I get two lines of text:

Something is wrong.
Additional check went fine.

When compiling same code on Windows using MS Visual Studio 11 Express Update 2 with default project options for either x86 or x64 architecture I don't get neither the warning nor this output, instead the output is:

Everything is fine.

Is it a problem in the code? If yes, could you point it? Or is it a problem with the compiler used?

Adding additional type cast for the second constant in the first if statement removes the warning in g++.

like image 277
alerion Avatar asked May 30 '13 11:05

alerion


People also ask

How do I supress a warning in GCC?

To suppress this warning use the unused attribute (see Variable Attributes). This warning is also enabled by -Wunused , which is enabled by -Wall . Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is enabled by -Wall .

How do I compile without warnings?

You can make all warnings being treated as such using -Wno-error. You can make specific warnings being treated as such by using -Wno-error=<warning name> where <warning name> is the name of the warning you don't want treated as an error. If you want to entirely disable all warnings, use -w (not recommended).

How do I turn off clang warning?

Passing -fno-diagnostics-show-option will prevent Clang from printing the [-Wextra-tokens] information in the diagnostic. This information tells you the flag needed to enable or disable the diagnostic, either from the command line or through #pragma GCC diagnostic.

How do I disable GCC?

To answer your question about disabling specific warnings in GCC, you can enable specific warnings in GCC with -Wxxxx and disable them with -Wno-xxxx. From the GCC Warning Options: You can request many specific warnings with options beginning -W , for example -Wimplicit to request warnings on implicit declarations.


1 Answers

According to [lex.icon] in the standard, the hexadecimal-literal 0xFFF0000000000000LL has type unsigned long long, because the value doesn't fit in a long long (see Unsigned hexadecimal constant in C? and C interpretation of hexadecimal long integer literal "L" for more information on this.)

This means G++'s warning is correct, you are comparing long long result to an unsigned long long literal.

Clearly as an unsigned value, 123456LL is less than 0xFFF0000000000000LL, so G++'s result is also correct.

MSVC seems to have a bug [Edit: or behaves differently for compatibility reasons, see comments], because this assertion fails:

static_assert(0xFFF0000000000000LL > 0, "big number is big");

MSVC gives the literal 0xFFF0000000000000LL type long long, as shown by this invalid code that is accepted by MSVC:

auto i = 0xFFF0000000000000LL;
long long& l = i;

A C++03 example that should compile without errors is:

template<typename T>
void f(T t)
{
    unsigned long long& l = t;
}

int main()
{
    f(0xFFF0000000000000LL);
}

GCC, Clang, Intel and Solaris CC all get this example right, VC++ gets it wrong.

like image 109
Jonathan Wakely Avatar answered Nov 15 '22 21:11

Jonathan Wakely