Suppressing GCC Warnings

by Patrick Horgan

Why this was written

This article was originally written by me as part of the Boost Developer Warning Guidelines along with a lot of other information about dealing with warnings from GCC. My position is strongly that warnings should be dealt with by fixing the code that causes the warning, and that all warnings should be fixed. Your code should always be built with high levels of warnings turned on and all warnings issued should be fixed. This will greatly improve the quality of your code, find real bugs, and over time make you a better developer.

I and others waged a long and successful campaign to get the boost community to adopt, as a standard, that all boost code should build with high levels of warning turned on both with Microsoft compilers and with gcc. They are looking for volunteers to write sections about what warnings mean, and how to deal with the warnings for other compilers. If you have expertise in this area, please contact them. See the link above.

I am as proud of getting that change as I am of any code I've written. Prior to that boost built with a lot of warnings. Some of the warnings were real bugs. It improved the quality of a lot of code that is used by a lot of people. People that use boost can now build with flags turned up without being deluged with noise from boost code.

Nevertheless, there are occasional warnings that you cannot or will not fix. It could be an overenthusiastic warning just trying to get you to change your coding style in a way that you know will hurt your code. It could be a bug in the compiler that makes it warn about something that is not an issue. For these extreme cases, with great reluctance, I suggest that you might suppress the warnings.

With 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.

Supressing Warnings For A File By Making GCC See It As A System Header

Using a pragma to make GCC think a file or part of a file is a system header

Beginning 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

#pragma GCC system_header

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 (all?) warnings point to real issues and should be dealt with appropriately.

Using -i to make GCC think all files in a directory are system headers

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.

-idirectoryName

The -idirectoryName command line option adds its argument to the list of directories to search for headers, just like -IdirectoryName does.

With -i, though, headers found in that directory will be considered system headers. It also has the side effect of changing the inclusion order, so 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.

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 when you compile with:

-Wsystem-headers

This 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.

Turning off warnings locally with gcc

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 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.

Finding out what option controls the warning

-fdiagnostics-show-option

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 if 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.

Turning the warnings off and on

I want to particularly thank Jonathan Wakely for his willingness to help and for the great help he offered on the gcc-help mailing list. It's people like him that make open source work. Without his help it would have taken me much longer to write this section. Any problems of course are my fault;) In addition to picking Jonathan's brain, I read the appropriate source in diagnostics.c and perused many releases of GCC documentation to get this information.

GCC provides the following pragmas to control warnings.

#pragma GCC diagnostic push

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.

#pragma GCC diagnostic pop

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.

#pragma GCC diagnostic [warning|error|ignored] OPTION

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"

version 4.2. You can turn them off but then what?

So starting from 4.2 but before 4.6, just put near the top of the file something like:

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

to 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.

version 4.6 Now you can restore the user's flags

For 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:

#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Code that causes warning goes here #pragma GCC diagnostic pop

Of 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. Be careful, though, that you don't pop too soon. In this example:

foo() { int unused,i; i=3; }

We might want to suppress the unused variable like this:

foo() { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" int unused,i; #pragma GCC diagnostic pop i=3; }

and then be surprised that we still get a warning about an unused variable. The reason is, that GCC doesn't know the variable is unused until it hits the closing brace. That means the pop has to come after the closing brace:

foo() { #pragma GCC diagnostic push #pragma GCC diagnostic "-Wunused-variable" int unused,i; i=3; } #pragma GCC diagnostic pop

A handy macro to help you do some of this

Jonathan Wakely came up with a nice macro set to control this and I'm sharing a slightly modified version of it with you.

GCC_DIAG_OFF(FLAG)

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.

GCC_DIAG_ON(FLAG)

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.

Both 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. It allows you to do things like (for GCC version 4.6 or later):

GCC_DIAG_OFF(sign-compare); if(a < b){ GCC_DIAG_ON(sign-compare);

to 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.)

Here's the macro

#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 #define GCC_DIAG_STR(s) #s #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y) # define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) # define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 # define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \ GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) # define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop) # else # define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) # define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x)) # endif #else # define GCC_DIAG_OFF(x) # define GCC_DIAG_ON(x) #endif

These macro names won't collide with GCC macros since their's start with one or two underscores.

Thanks,(especially to Erik Sjölund who caught a typo for me!)

Patrick Horgan
patrick at dbp-consulting dot com