tags:

views:

212

answers:

6

I've recently set up a MinGW + MSYS environment on my laptop to check how things are with Netbeans C/C++ support. Everything seems to work fine, however, during my testing I have noticed a difference between GCC and Microsoft's cl.exe compiler.

Here's a sample program:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(void) {
    int i_max = INT_MAX;
    char c_max = CHAR_MAX, c;

    c = i_max;
    printf("i_max: %d, c_max: %d, c: %d\n", i_max, c_max, c);
    return EXIT_SUCCESS;
}

The output is:

i_max: 2147483647, c_max: 127, c: -1

As you can see in the code above, I assign an int to a char. Shouldn't this produce a warning that a possible data loss may occur? Microsoft's compiler (which I have configured to be very strict) does issue the warning while GCC doesn't.

Here are the GCC options I use:

-g -Werror -ansi -pedantic -Wall -Wextra

Am I missing some GCC option to make the compile time checks even stricter?

+7  A: 

You're looking for

-Wconversion

You'd have to ask a gcc developer for the specific reasons why some warnings aren't included in -Wall or -Wextra.

Anyway, these are the flags I use:

-Wall -Wextra -Wmissing-prototypes -Wmissing-declarations -Wshadow
-Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Wnested-externs
-Winline -Wno-long-long -Wconversion -Wstrict-prototypes

As other's have pointed out, the behaviour of -Wconversion changed with version 4.3 - the old warning about prototypes forcing a type conversion is now available as -Wtraditional-conversion.

Christoph
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.htmlThis link shows you what _is_ included in Wall and Wextra.Why wconversion isn't it a complete mystery/bug.
Pod
My opinion is that those warnings are a pain in the rear far more often than they catch something, and my sense of gcc policy decisions is that they tend to think like that also. It would be a good idea to have one -W option that meant "check everything, no matter how annoying", of course.
David Thornley
doesn't work for me. using " gcc -g -Werror -ansi -pedantic -Wall -Wextra -Wconversion foo.c" with the above code in foo.c results in no warnings with gcc 4.1.2
Glen
@Glen: strange; mingw-gcc4.4.0 says `warning: conversion to 'char' from 'int' may alter its value`
Christoph
@Christoph, I guess they added it in after 4.1.2 then. I tried it with your updated flags and still get no warnings.
Glen
Yes, it looks like it used to only warn with prototypes, not all assignments.
Adam Goode
@David: -W*all* would be the perfect flag to mean exactly that...
Martinho Fernandes
@Martinho: Yes, one would think that. It's at this point that I fail to understand the gcc crew.
David Thornley
@Martinho - `-W*all*` would be a great option to have on Unix where shells do globbing. I think everybody would have a lot of fun with a compiler option that changes depending on what your current directory is. In keeping with the ever-expanding (in number and size) of GCC options, how about the `-Wall-really-i-mean-all-of-them` option?
Michael Burr
+2  A: 

-Wall doesn't quite mean -Wall, -Wextra is already under fire for being a little overly pedantic.

As Christoph said, you are looking for -Wconversion. Its good to really dig in to what -Wall and -Wextra actually turn on, and just specify the -W flags you want in your make file, especially if treating warnings as errors.

Tim Post
if you don't like the warnings about signedness comparison, disable them; also, strict warnings might be a problem for legacy codebases, but if you start from scratch, it's really not that hard to make your code warning-free - I guess some people are just lazy ;)
Christoph
+1  A: 

In C, assigning an int to a char is legal.

As it's legal (but possibly dodgy) the different compiler vendors do different things when they encounter this code.

I guess MS is just being extra pedantic while the GCC guys have decided that it's not even worth a warning.

Glen
A: 

I think it falls under the "Usual arithmetic conversions" (6.3.1.8) or "integer promotion rules" (5.1.2.3 (?)), but I can't find the specific text that says the behaviour you're seeing is expected.

pmg
+1  A: 

Theres a little nuance in your question that is not immediately obvious to me from the way it is worded.

If you think GCC (specifically GCC) should issue a warning here, then some compiler options might possibly help (see other replies).

If you think any compiler should issue a warning here (and I seem to read that sentiment in your question), then... well, "warnings" are not in any way mandatory or even de-facto unified. There's no "should" here. Assigning a larger-typed integer value to a smaller type without an explicit cast is pefectly legal in C. Overflow on conversion, produces implementation-defined behavior (it is not even UB :))

AndreyT
+2  A: 

I didnt get a warning/error with -Wconversion either. However, if you give a pass with something like splint you get three warnings:

file.c: (in function main)
file.c:9:5: Assignment of int to char: c = i_max
  To make char and int types equivalent, use +charint.
file.c:10:52: Format argument 2 to printf (%d) expects int gets char: c_max
   file.c:10:32: Corresponding format code
file.c:10:59: Format argument 3 to printf (%d) expects int gets char: c
   file.c:10:39: Corresponding format code

Finished checking --- 3 code warnings

If you are serious about catching all errors you should use more than one tool.

ezpz
Bear in mind that, for a variadic function like printf(), a char will be passed as an int, and that %d is the right format specifier to get the numeric value. A %c will print out the value as a character, the difference being that between "65" and "A".
David Thornley
Right (although, a cast would make it explicit and thus remove the warning). My point was more towards the fact that multiple points of view are important when trying to close in on error-/bug-free code.
ezpz