Changes between Version 12 and Version 13 of Guidelines/WarningsGuidelines


Ignore:
Timestamp:
Jan 14, 2011, 9:52:24 PM (12 years ago)
Author:
phorgan1
Comment:

Finish section on suppressing warnings in gcc

Legend:

Unmodified
Added
Removed
Modified
  • Guidelines/WarningsGuidelines

    v12 v13  
    285285== Warnings for '''GCC''' ==
    286286
    287 With older versions of GCC, it is more difficult to deal with warnings because there is no way to '''locally''' silence individual warnings.  As of GCC version '''4.2''' they allowed suppression via pragma (actually you can choose whether a particular problem is a warning, error, or ignored).  Initially they didn't allow you to save the current state of affairs, so after suppressing the warning, you wouldn't know whether the user had it on, off, or causing an error.  You can imagine that this would be quite annoying for users who care about these things.  Also, the pragmas had to be at file scope rather than inside your code.  As of version '''4.6''' a pragma was added to push or to pop the state of diagnostics, and the pragmas now affect from the line they are specified in forward.  It is considered important not to leave warnings switched off when meeting user code. This is an unresolved difficulty when using GCC versions prior to '''4.6'''.
     287With older versions of GCC, it is more difficult to deal with warnings because there is no way to ''locally'' silence individual warnings.  As of GCC version ''4.2'' they allowed suppression via pragma (actually you can choose whether a particular problem is a warning, error, or ignored).  Initially they didn't allow you to save the current state of affairs, so after suppressing the warning, you wouldn't know whether the user had it on, off, or causing an error.  You can imagine that this would be quite annoying for users who care about these things.  Also, the pragmas had to be at file scope rather than inside your code.  As of version ''4.6'' a pragma was added to push or to pop the state of diagnostics, and the pragmas now affect from the line they are specified in forward.  It is considered important not to leave warnings switched off when meeting user code. This is an unresolved difficulty when using GCC versions prior to ''4.6''.
    288288
    289289On the other hand, the number of unhelpful warnings seems fewer.
     
    291291So more emphasis should be placed on fixing warnings, for example using static_cast, or providing missing items.
    292292
    293 === Suppressing Warnings ===
    294 ==== Supressing Warnings For A File By Making GCC See It As A System Header ====
    295 For a particular file, you can turn off all warnings including most warnings generated by the expansion of macros specified in a file by putting the following in a file
    296 
    297 #pragma GCC system_header // File considered a system header.
    298 
    299 Note that this works differently depending on the version of GCC prior to version 4.6 it needed to be put near the beginning of the file and before any code. All code in the file after the pragma is seen will be considered system code.  Since 4.6, it can be specified anywhere in the file, and code that precedes the pragma in the file will be unaffected.  The intent of declaring a file a system header, is for operating system specific code that can't be strictly conforming C or C++.  This should not be seen as a handy way of turning off bothersome warnings.  Many ('''most?''') warnings point to real issues and should be dealt with appropriately.
    300 
    301 You can also turn off warnings for all files in a directory, by putting the directory into the include search path with -i instead of -I
    302 
    303 The -idirectoryName command line option adds its argument to the list of directories to search for headers, just like -I. Any headers found in that directory will be considered system headers. It also has the side effect of changing the inclusion order, in that all files included from directories specified with -i are included '''after''' files included from directories specified via -I.  If the directory is specified with both -I and -i it is still only searched after normal includes as part of the system include directories.  This may be appropriate if you have to deal with other's spotty code that generates a lot of warnings that you can't fix.
    304 
    305 If you turn off warnings for files that are shared with your users, you need to be able to see the warnings yourself so that as new problems arise you will see them.  You can turn on warnings back on for system headers with:
    306 
    307 -Wsystem-headers
    308 
    309 Print warning messages for constructs found in system header files that would normally not be seen. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read. Using this command line option tells GCC to emit warnings from system headers as if they occurred in user code. However, note that using -Wall in conjunction with this option will not warn about unknown pragmas in system headers—for that, -Wunknown-pragmas must also be used.
    310 
    311 ==== Turning off warnings locally ====
    312 So.  Suppose you are getting a warning and have checked the code and are '''sure''' that it's a spurious warning.  There's nothing wrong.  '''If''' the warning is controllable via a command line -W option, then you can (if you have GCC version '''4.2.4''' or newer) turn it off temporarily.  First you need to find out what the option might be, then if it exists turn it off via a pragma.  How you do this varies a bit with GCC version.
    313 
    314  -fdiagnostics-show-option::
    315   In GCC, for versions 4.2.4 and higher, this option instructs the diagnostic machinery to add text to each diagnostic emitted, which indicates which command line option directly controls that diagnostic, when such an option is known to the diagnostic machinery.
    316  #pragma GCC diagnostic push::
    317   Available since GCC version 4.6, this pragma lets you remember diagnostic options in place at a particular time.  This pragma can occur on any line of a file.
    318  #pragma GCC diagnostic pop::
    319   Available since GCC version 4.6, this pragma lets you restore diagnostic options that were remembered by a diagnostic push. This pragma can occur on any line of a file.
    320  #pragma GCC diagnostic [warning|error|ignored] OPTION::
    321   From GCC version 4.2.4 and before GCC version 4.6 this could be specified at file scope outside of any functions, classes, unions, structs, or methods, to change the behavior when a particular class of error was seen.  For GCC version 4.6 and later, it can be put in any line of a file, and affects from that position forward.  For any supported version, it only works with warnings that have explicit -W arguments, use -fdiagnostic-show-option to find out which one to use.  An example: #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    322 
    323 So starting from 4.2.4 but before 4.6, just put near the top of the file something like:
    324 
    325 #pragma GCC diagnostic ignored "-Wdeprecated-declarations
    326 
    327 For version 4.6 or later, you can insert this around the line that causes the spurious warning:
    328 
    329 #pragma GCC diagnostic push
    330 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    331 
    332 // Next you would have your code that generates the spurious warning
    333 
    334 #pragma GCC diagnostic pop
     293
    335294
    336295=== Turning on Warnings ===
    337296
    338 -Wall
     297'''-Wall'''
    339298    This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.  For specific information on any of these warnings please see http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
    340299
     
    372331    Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra but many of them must be enabled individually.
    373332
    374 -Wextra
     333'''-Wextra'''
    375334
    376335    This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
     
    398357        * (C++ only) A base class is not initialized in a derived class' copy constructor.
    399358
    400 
    401 More information needed here!
    402 
    403359=== Specific Warnings and Suggested Actions ===
    404360'''comparison between signed and unsigned integer expressions'''
     
    416372    ||=That means:=||=signed char=||=unsigned char=||
    417373    ||0 to 127|| + || + ||
    418     ||128 to 255|| \- || /+ ||
     374    ||128 to 255|| - || + ||
    419375   
    420376    In the range from 128 to 255 a comparison from one to the other makes no
     
    478434
    479435'''deprecated conversion from string constant to ‘char*’'''
    480     '''-Wwrite-strings''' - enable this warning (disabled by default for C and enabled by default for C++)
     436    '''-Wwrite-strings''' - enable this warning (disabled by default for C and enabled by default for C++)[[BR]]
    481437    '''-Wno-write-strings''' - disable this warning
    482438
     
    564520        }}}
    565521
    566         Annoying, yet more correct than before.
     522        Annoying, yet more correct than before, and your code maintains type correctness.  You just cast away the correct constness for the brain damaged external routine.
    567523
    568524'''dereferencing type-punned pointer will break strict-aliasing rules'''
     
    574530        Level 2: Agressive, quick, not too precise.  Less false positives than Level 1, but more false negatives.  Only warns if pointer is dereferenced.[[BR]]
    575531        Level 3: Very few false positives and very few false negatives--the default.[[BR]]
    576     '''-fstrict-aliasing''' - also turned on by -O2, -O3 and -Os.  Tells the compiler that it's ok to do a certain class of optimization based on the type of expressions.  In particular you're promising by using this flag that an object of one type won't reside at the same address as an object of an incompatible type.
     532    '''-fstrict-aliasing''' - also turned on by -O2, -O3 and -Os.  Tells the compiler that it's ok to do a certain class of optimization based on the type of expressions.  In particular you're promising by using this flag that an object of one type won't reside at the same address as an object of an incompatible type.[[BR]]
    577533    '''-fno-strict-aliasing''' - turns off this optimization.  If this changes the behavior of your code, you have a problem in your code.
    578534
     
    681637
    682638
    683 
    684 ||?||class does not have a  virtual destructor||Suppress or provide a virtual destructor.||??||
    685 
     639=== Suppressing Warnings in GCC ===
     640With GCC there are a couple of options when you want to supress warnings.  First, beginning with version 3.1, since GCC won't report warnings for files that GCC considers ''system'' files, you can make GCC consider the problematic files system files.  This is heavy handed, makes it easy for problems to creep in unnoticed, but effective.  Second, beginning with version 4.2, you can suppress a particular class of warning either for an entire file, or (beginning at version 4.6), for a section of a file.
     641==== Supressing Warnings For A File By Making GCC See It As A System Header ====
     642===== Using a pragma to make GCC think a file or part of a file is a system header =====
     643Beginning with GCC 3.1, for a particular file, you can turn off all warnings including most warnings generated by the expansion of macros specified in a file by putting the following in a file
     644
     645#pragma GCC system_header // File considered a system header.
     646
     647It can be specified anywhere in the file, and code that precedes the pragma in the file will be unaffected.  The intent of declaring a file a system header, is for operating system specific code that can't be strictly conforming C or C++.  This should not be seen as a handy way of turning off bothersome warnings.  Many (''most?'') warnings point to real issues and should be dealt with appropriately.
     648===== Using -i to make GCC think all files in a directory are system headers =====
     649You can also turn off warnings for all files in a directory, by putting the directory into the include search path with -i instead of -I
     650
     651The -idirectoryName command line option adds its argument to the list of directories to search for headers, just like -I. Any headers found in that directory will be considered system headers. It also has the side effect of changing the inclusion order, in that all files included from directories specified with -i are included ''after'' files included from directories specified via -I.  If the directory is specified with both -I and -i it is still only searched after normal includes as part of the system include directories.  This may be appropriate if you have to deal with other's spotty code that generates a lot of warnings that you can't fix.
     652
     653If you turn off warnings for files that are shared with your users, you need to be able to see the warnings yourself so that as new problems arise you will see them.  You can turn on warnings back on for system headers when you compile with:
     654
     655-Wsystem-headers
     656
     657This makes GCC print warning messages for constructs found in system header files that would normally not be seen. Using -Wall in conjunction with this option will not warn about unknown pragmas in system headers.  For that, -Wunknown-pragmas must also be used.
     658
     659==== Turning off warnings locally with gcc ====
     660So.  Suppose you are getting a warning and have checked the code and are ''sure'' that it's a spurious warning.  There's nothing wrong.  ''If'' the warning is controllable via a command line -W option, then you can (if you have GCC version ''4.2'' or newer) turn it off temporarily.  First you need to find out what the option might be, then if it exists turn it off via a pragma.  How you do this varies a bit with GCC version.
     661===== Finding out what option controls the warning
     662 -fdiagnostics-show-option::
     663  In GCC, for versions 4.2 and higher, this option instructs the diagnostic machinery to add text to each diagnostic emitted, which indicates which command line option directly controls that diagnostic, when such an option is known to the diagnostic machinery.  The added text will look similar to [-Wsign-compare].  If you see this, that tells you that the -Wsign-compare command line option turns this warning on.
     664===== Turning the warnings off and on
     665GCC provides the following pragmas to control warnings.
     666 #pragma GCC diagnostic push::
     667  Available since GCC version 4.6, this pragma lets you remember diagnostic options in place at a particular time.  This pragma can occur on any line of a file.  The number of nested pushes is limited only by the size of memory and the size of an int index into the diagnostic information.
     668 #pragma GCC diagnostic pop::
     669  Available since GCC version 4.6, this pragma lets you restore diagnostic options that were remembered by a diagnostic push. This pragma can occur on any line of a file.  The number of pops is limited by memory and the size of an int index into the diagnostic information.  At a pop information is moved from the table used by push into a history.  An unbalanced pop, i.e. popping when nothing is on the stack is harmless and will simply reassert the user's command line diagnostic choices.
     670 #pragma GCC diagnostic [warning|error|ignored] OPTION::
     671  From GCC version 4.2.4 and before GCC version 4.6 this could be specified at file scope outside of any functions, classes, unions, structs, or methods, to change the behavior when a particular class of error was seen.  For GCC version 4.6 and later, it can be put in any line of a file, and affects from that position forward.  For any supported version, it only works with warnings that have explicit -W arguments, use -fdiagnostic-show-option to find out which one to use.  An example: #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     672====== version 4.2.  You can turn them off but then what?
     673So starting from 4.2 but before 4.6, just put near the top of the file something like:
     674
     675#pragma GCC diagnostic ignored "-Wdeprecated-declarations
     676
     677to turn off warnings from that point forward in the file of the use of deprecated declarations.  Problematically, you have no way of knowing what the user had this option set to.  They might have already had the warnings turned on, they might have had them set to ignore, or they might have had them set to cause an error.  At the end of the file, if you do nothing else, the diagnostic for deprecated declarations stays ignored for anything that includes your file.  You can set them to ignored, error, or warning at the end of the file before exiting, but you don't know which to use.  This is sure to cause angst.
     678====== version 4.6 Now you can restore the user's flags
     679For version 4.6 or later, you can save the state of the user's diagnostic flags.  You can insert this around the line that causes the spurious warning:
     680
     681#pragma GCC diagnostic push[[BR]]
     682#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     683
     684// Next you would have any amount of code for which you'd like to suppress that warning
     685
     686#pragma GCC diagnostic pop
     687
     688Of course this could cover everything from a line up to the whole file, and in between the push and the pop you could make multiple changes to each of multiple options.
     689
     690====== A handy macro to help you do some of this
     691Jonathan Wakely came up with a nice macro set to control this and I'm sharing a slightly modified version of it with you.  It defines:
     692 GCC_DIAG_OFF(FLAG)::
     693  For versions 4.2-4.5 will turn warnings off for a particular error if controllable via a -W command line flag.  If -fdiagostics-show-option told you that the warning was controlled by [-Wsign-compare], then you could say GCC_DIAG_OFF(sign_compare).  Beginning at version 4.6, it will push the current state of the diagnostic flags and then turning warning off.  Prior to version 4.2 it has no effect.
     694 GCC_DIAG_ON(FLAG)::
     695  For versions 4.2-4.5 will arbitrarily turn warnings on.  This may not be what the user wanted.  Beginning at version 4.6 it will simply pop the saved diagnostic stack.  Prior to version 4.2 it has no effect.
     696
     697Both of them should be used only at file scope for versions 4.2-4.5.  Beginning at version 4.6 they can be used at any scope.  If you want to turn multiple things from warning to error to ignored between the push and the pop then this will not be effective for you.
     698
     699It allows you to do things like:
     700{{{
     701    GCC_DIAG_OFF(sign-compare);
     702    if(a < b){
     703    GCC_DIAG_ON(sign-compare);
     704}}}
     705to turn off warnings that you know are spurious.  (Probably a cast of one to the other's type or changing the declaration of the type of one to the other's would be a better fix.)
     706
     707{{{
     708#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
     709#define GCC_DIAG_STR(s) #s
     710#define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y)
     711# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
     712# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
     713# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
     714#  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
     715          GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
     716#  define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
     717# else
     718#  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
     719#  define GCC_DIAG_ON(x)  GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x))
     720# endif
     721#else
     722# define GCC_DIAG_OFF(x)
     723# define GCC_DIAG_ON(x)
     724#endif
     725}}}
     726
     727These are perhaps not the best choice of names for the macros since they risk future collision with GCC macros.  In your domain you should probably prefix every instance of GCC_ with YOURDOMAIN_ to make YOURDOMAIN_GCC_, for example YOURDOMAIN_GCC_DIAG_OFF(x).
     728----
    686729'''Intel'''
    687730