Compiler Warnings

Having gcc print out some warnings could isolate some problems. Here are a couple of areas where this can help.


Howto

Configure and make Wine like this:

CFLAGS="-Wmissing-declarations -Wwrite-strings" ./configure
make depend
make

Check the warnings that are generated. In the above case, some are from missing prototypes. The most important of these are API functions that are missing from the Wine headers in wine/include. Functions that are local to a dll, but used across many files should be declared in a header included by all those files. Functions that are local to a file, and unused elsewhere should be static.


Incomplete

-Wmissing-declarations

Should point to lots of missing APIs declarations. We cannot always turn this warning on because there are lots of cases where we have global functions without prototypes (more than 2/3 of them are made out of the 16bit entry points)

There are two ways to get rid of these warnings:

  • Change the function to a static function. Compilers can optimize static function better than non-static ones, and the symbol won't polute the global name-space.
  • Add the declaration for the function in the appropriate header, so that it is shared with code that calls it. This a matter of including a header that already has the function declaration, or moving the declaration into a header. At worst, the two function declarations could be different, and create bugs that are hard to find.

-Wcast-qual

This should point out all the casts from a pointer to a constant type to a pointer to a non constant type. We use this quite a bit, and in some cases it would prevent some errors. These are the main cases pointed out by this warning.

   1 /* Case 1: Reading a value from a pointer. However, this is harmless. */
   2 const void* ptr;
   3 WORD wrong = *(WORD*)ptr; /* WRONG !!! */
   4 WORD right = *(const WORD*)ptr; /* RIGHT !!! */
   5 
   6 /* Case 2: Setting to a pointer to another const type */
   7 const void* ptr;
   8 const WORD* wrong = (WORD*)ptr; /* WRONG !!! */
   9 WORD* wrong2 = (WORD*)ptr; /* WRONG !!! and HARMFUL */
  10 const WORD* right = (const WORD*)ptr; /* RIGHT !!! */
  11 /* This warning is harmless if the second pointer is really defined as const,
  12  * in some cases it isn't and this should be fixed.
  13  */
  14 
  15 /* Case 3: Setting it to a pointer to a pointer
  16  * (used a lot for qsort()/bsearch()... callbacks), when dealing with arrays 
  17  * of pointers.
  18  */
  19 const void* ptr;
  20 const foo* f = *(const foo**)ptr; /* WRONG !!! and HARMFUL */
  21 const foo* f = *(const foo* const*)ptr; /* RIGHT */
  22 foo* f = *(foo* const*)ptr; /* DOUBTFUL... 
  23 What's const in the ptr, is the object pointed to.
  24 In the case of a double indirection, the const relates to the slot where the second indirection is stored.
  25 This tells nothing about the object which address is stored there.
  26 However, previous form (cosnt foo* const*) is preferred, especially for qsort, bsearch callbacks */

Unfortunately, we cannot turn this warning on all the time because some C functions implementation would always trigger it (strstr for example), unless we use integral values (not pointer) to cast from the const char* to the returned char*), and this is uglier IMO than the warning we try to avoid.

-Wsign-compare

This turns up a load of warnings, most of which can be fixed by choosing correct variable types. '-Wsign-compare' is included in '-W'.

-Wstrict-prototypes

Warns if a prototype of a function is defined without the types of its arguments (old C style). This mainly covers the declaration of the form

   1 /* WRONG... this is a function for which we don't know the arguments' types */
   2 void foo()
   3 {...}
   4 /* RIGHT */
   5 void foo(void)
   6 {...}

Unfortunately, we cannot turn this always on as there are some Windows definitions which require this (like FARPROC).

-Wpointer-sign

This warning is turned on by default in gcc 4.0. Most of these have been fixed.

   1 
   2 void foo(LPBYTE p);
   3 
   4 void bar(void)
   5 {
   6     CHAR *sp = NULL;
   7     BYTE *up = NULL;
   8 
   9     foo(sp); /* wrong */
  10     foo(up); /* right */
  11 }
  12 

-W

Wine has over 15000 warnings, when compiled with '-W'

  • (~8400): '-W' together with '-Wunused' (included in '-Wall') checks for unused arguments
  • (~3700): '-W' checks for uninitialized struct members
  • (~2800): '-W' also activates '-Wsign-compare'
  • Many more checks are done, but how Wine is affected by this extra checks is currently hard to detect in the flood of warnings.
  • There are about 300 more warnings in the tests


Completed

-Wwrite-strings

There has already been quite some work on this, but we think there's more to do. Here's a simple example:

   1 void foo(void)
   2 {
   3     char *b = "bad";         /* wrong */
   4     const char *g = "good";  /* const reflects that the string is constant */
   5 ...

Most of these can be fixed by inserting a const qualifier, but sometimes the Windows API prevents that.

Worker: AndrewTalbot


Status

This project was suggested by EricPouech and FrancoisGouget. For more information contact them directly or the wine-devel mailing list.

Workers: EricPouech, HansLeidekker, MikeMcCormack, StefanHuehner


CategoryJanitorialProjects CategoryCompilers

CompilerWarnings (last edited 2013-05-03 09:10:53 by KyleAuble)