6

Consider:

unsigned foo(unsigned u) {
    return u;
}

int main() {
    foo(-1);
    return 0;
}

Here, the function foo is called with u equal to 4294967295 (or a similar large value.) If the programmer wasn't paying attention, this might be quite unexpected.

For instance, maybe you are implementing pow to raise your Polynomial class to a power. Since only positive powers are possible, you decide on the signature

Polynomial pow(const Polynomial& p, unsigned exp);

Then a careless programmer calls pow(p, -1) to get an inverse and, rather than a warning or error, it appears to work, but probably uses an extreme amount of memory and time to produce a totally wrong answer.

g++ 5.3.0, and gcc 5.3.0, compile this without complaint with -Wall -Wextra.

They will warn about it with the option -Wsign-conversion, but this warns about every conversion from int to unsigned and is rapidly too annoying (it warns every time you index into a vector with an int, vec[i], for example.)

Can gcc warn just about passing a negative literal, or other negative compile-time constant, as an unsigned parameter?

Nick Matteo
  • 4,453
  • 1
  • 24
  • 35
  • Given that unsigned integer types implement arithmetic in Z/2^NumBit, warning about this does not make sense as -1 == 4294967295 in Z/2^32 (more precisely, they are representatives of the same equivalence class). If you don't want this kind of arithmetic, use signed types. Opinions of some experts: https://channel9.msdn.com/Events/GoingNative/2013/Interactive-Panel-Ask-Us-Anything 9:50, 42:40, 1:02:50 – Baum mit Augen Apr 29 '16 at 15:33
  • 1
    BTW, the irony is that the `pow` function takes floating point parameters, not integral. – Thomas Matthews Apr 29 '16 at 15:34
  • related: http://stackoverflow.com/questions/21243076/c-how-to-block-negative-numbers-being-passed-as-argument-where-unsigned-is-exp – NathanOliver Apr 29 '16 at 15:35
  • To make my first comment more concrete: Just use `Polynomial pow(const Polynomial& p, int exp);` and assert that `exp` is positive (or non-negative, whatever fits). – Baum mit Augen Apr 29 '16 at 15:36
  • `pow()` has no problem with negative powers. The only restriction is that if the base is negative _and_ the exponent is negative, then the exponent must be an integer value. – vacuumhead Apr 29 '16 at 15:46
  • @BaummitAugen: Yes, I agree that would be best in this situation. – Nick Matteo Apr 29 '16 at 16:05
  • @vacuumhead: Not for polynomials. – Nick Matteo Apr 29 '16 at 16:05
  • 1
    Detail: As post is tagged C, there are no _negative literals_ in C - just _string literals_ and _compound literals_. There are _integer constants_ with a negative value. – chux - Reinstate Monica Apr 29 '16 at 19:50
  • @chux: Ah geez. By "literal" I mean _when I literally write down a value_ like 321 or 77ul or 0x3b or "Hello", as opposed to a "constant" which is a named variable whose value doesn't change. It would be nice if terminology for this was really consistent across languages. – Nick Matteo Apr 29 '16 at 20:32

1 Answers1

0

The -Wconversion will warn you of the implicit conversion in the passed argument. Add -Werror if you want to treat the warning as an error.

Here is my test and its results.

Source code file temp.c:

unsigned foo(unsigned u) {
    return u;
}

int main() {
  foo(-1);
}

And the compilation,

$ gcc -o temp temp.c -Wconversion
temp.c: In function ‘main’:
temp.c:6:7: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]
   foo(-1);
       ^

If you change the argument to 1, and compile again, the warning will go away.

(Aside, it's a good idea to always use -Wall, as well).

DrM
  • 2,404
  • 15
  • 29