tags:

views:

622

answers:

4

I recently was making a change to to our codebase from float to long for some variables, and discovered that there were no error messages generated by the compiler in areas I knew were still wrong. This led me to add -Wconversion to the compiler flags. But, oops, this leads to some spurious error messages. In the snippet below, I get errors as noted. What can I do to supress this message on a case-by-case basis, or coax gcc into being smarter about this? The -Wconversion flag generates thousands of warnings in our code base. Am I going to have to examine them all? Grrr.

#include <stdio.h>
void
takes_a_float  ( float some_num ) {
    printf("float Hello %f\n", some_num );
}
int
main (int argc, char **argv)  {
    float my_boat = 1.0f;
    takes_a_float (  my_boat );
    exit (0);
}

gcc -Wconversion foo.c
foo.c: In function `main':
foo.c:13: warning: passing arg 1 of `takes_a_float' as `float' rather than `double' due to prototype

 $ gcc -v
Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr   /share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
Thread model: posix
gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)

EDIT

As pointed out by John Millikin, the -Wconversion flag is working 'as designed'. (I had thought it was about type-conversion, but it turns out it's about converting really old C-style programs to ISO-standard C. Darn. A reading of the gcc warning documentation page for my version of gcc doesn't give me hope, but in any event, what I really want is some other warning flag to enable that will warn correctly in the folowing code, and not give spurious warnings.

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


void
takes_a_long  ( long sad_story ) {
    printf("Long %lu\n", sad_story );
}

void
takes_a_float  ( float my_boat ) {
    printf("Float  %f\n", my_boat );
}

int
main (int argc, char **argv)  {

    float   my_boat     = 1.0f;
    long    sad_story   = 1.0L;

    // No warnings wanted
    takes_a_float (my_boat);
    takes_a_long (sad_story);

    // Warnings required
    takes_a_long  (my_boat);
    takes_a_float (sad_story);

    exit (0);
}

Edit 2

The real solution is to upgrade my compiler. Not something the company is willing to do for complicated reasons (sigh).

+1  A: 

Just a guess from the info pages, did you try -Wno-traditional-conversion?

Edit: I checked, and it works, but sadly, this works with gcc 4.3 and newer only. From gcc 4.1 man page, it seems your observed behaviour is what -Wconversion was supposed to do in older versions, and it doesn't warn on a normal double -> float conversion.

jpalecek
I tried it just now. Doesn't help. Thanks for the suggestion.
Leonard
All I have to do now is convince 3 layers of management in a different branch of the company to upgrade our compiler. :-(. Thanks for your help.
Leonard
Couldn't you just compile the code with gcc 4.3 for the sake of the transition, and then continue using your old compiler for production?
jpalecek
Good idea. I'll do that.
Leonard
+3  A: 

From the manpage (also at http://lists.apple.com/archives/xcode-users/2008/Jul/msg00720.html):

-Wconversion

Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed point argument except when the same as the default promotion.

So, the warning is performing exactly as documented. If you'd like to check specifically for some conversions, you could try turning on -Wconversion on a single run, logging that to a file, and searching for long -> float conversions.


This option is apparently intended for use in porting traditional C to ISO/ANSI C.

John Millikin
It's not the same as what the most recent documentation says; http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Warning-Options.html#Warning-Options.
Bastien Léonard
You're using GCC 3.4.6, so you'll want *that* version of the manpage: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Warning-Options.html#Warning-Options
John Millikin
A: 

I don't get this warning, I guess it's because I'm using a more recent version of GCC (4.3.3).

Bastien Léonard
+2  A: 

I believe the flag you are most likely looking for is -Wall which you may wish to combine with -std=XX where XX is one of (c89|gnu89|c99|gnu99|...), and/or possibly -pedantic which is even more annoying pedantic (or more an*lly retentive depending on your mood :)

BTW, you forgot to include stdlib.h (for exit() prototype.


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

void takes_a_float ( float some_num ) {
    printf("float Hello %f\n", some_num );
}

int main (int argc, char **argv)  {
   float my_boat = 1.0;
   takes_a_float (  my_boat );
   exit( 0 );
}

and my console output:


mctaylor@tigger:stackoverflow$ gcc -Wall -pedantic long_float.c -o long_float
mctaylor@tigger:stackoverflow$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
...
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)


Using -Wall -pedantic forces you to write clean, explicit code, and can help you catch a lot of potential silly mistakes. Good luck.

I wonder if the "missing warning" messages might be because of C type promotion rules. (See K&R The C Programming Language, 2nd ed, section 2.7 - Type Conversion). Just food for thought.

I hope this helps.

EDITED to add additional material (which follows):

Another option or approach is splint (Secure Programming Lint) or Gimple Software's PC-lint / FlexLint whuch are lint implementations of a static analysis of C source code that flags suspicious and non-portable constructs.


mctaylor@tigger:stackoverflow$ splint sad_story.c 
Splint 3.1.2 --- 07 May 2008

sad_story.c: (in function takes_a_long)
sad_story.c:5:26: Format argument 1 to printf (%lu) expects unsigned long int
                     gets long int: sad_story
  To ignore signs in type comparisons use +ignoresigns
   sad_story.c:5:20: Corresponding format code
sad_story.c: (in function main)
sad_story.c:21:18: Function takes_a_long expects arg 1 to be long int gets
                      float: my_boat
  To allow all numeric types to match, use +relaxtypes.
sad_story.c:22:19: Function takes_a_float expects arg 1 to be float gets long
                      int: sad_story
sad_story.c:12:15: Parameter argc not used
  A function parameter is not used in the body of the function. If the argument
  is needed for type compatibility or future plans, use /*@unused@*/ in the
  argument declaration. (Use -paramuse to inhibit warning)
sad_story.c:12:28: Parameter argv not used
sad_story.c:4:6: Function exported but not used outside sad_story: takes_a_long
  A declaration is exported, but not used outside this module. Declaration can
  use static qualifier. (Use -exportlocal to inhibit warning)
   sad_story.c:6:1: Definition of takes_a_long
sad_story.c:8:6: Function exported but not used outside sad_story:
                    takes_a_float
   sad_story.c:10:1: Definition of takes_a_float

Finished checking --- 7 code warnings


You can also try the example in FlexLint at Gimpel's Online Testing which is cleaner and pretty output.

mctylr
I like to add -Wextra , also.
John Millikin