How to disable GCC warnings for a few lines of cod

2018-12-31 23:58发布

问题:

In Visual C++, it\'s possible to use #pragma warning (disable: ...). Also I found that in GCC you can override per file compiler flags. How can I do this for \"next line\", or with push/pop semantics around areas of code using GCC?

回答1:

It appears this can be done. I\'m unable to determine the version of GCC that it was added, but it was sometime before June 2010.

Here\'s an example:

#pragma GCC diagnostic error \"-Wuninitialized\"
    foo(a);         /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored \"-Wuninitialized\"
    foo(b);         /* no diagnostic for this one */
#pragma GCC diagnostic pop
    foo(c);         /* error is given for this one */
#pragma GCC diagnostic pop
    foo(d);         /* depends on command line options */


回答2:

To net everything out, this is an example of temporarily disabling a warning:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored \"-Wunused-result\"
    write(foo, bar, baz);
#pragma GCC diagnostic pop

You can check the GCC documentation on diagnostic pragmas for more details.



回答3:

#pragma GCC diagnostic ignored \"-Wformat\"

Replace \"-Wformat\" with the name of your warning flag.

AFAIK there is no way to use push/pop semantics for this option.



回答4:

#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif

This should do the trick for gcc, clang and msvc

Can be called with e.g.:

DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)

see https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html, http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas and https://msdn.microsoft.com/de-DE/library/d9x1s805.aspx for more details

You need at least version 4.02 to use these kind of pragmas for gcc, not sure about msvc and clang about the versions.

It looks like the push pop pragma handling for gcc is a little bit broken. If you enable the warning again, you still get the warning for the block that was inside the DISABLE_WARNING/ENABLE_WARNING block. For some versions of gcc it works, for some it doesn\'t.



回答5:

TL;DR: If it works, avoid, or use specifiers like __attribute__, otherwise _Pragma.

This is a short version of my blog article Suppressing Warnings in GCC and Clang.

Consider the following Makefile

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

for building the following puts.c source code

#include <stdio.h>

int main(int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

It will not compile because argc is unused, and the settings are hardcore (-W -Wall -pedantic -Werror).

There are 5 things you could do:

  • Improve the source code, if possible
  • Use a declaration specifier, like __attribute__
  • Use _Pragma
  • Use #pragma
  • Use a command line option.

Improving the source

The first attempt should be checking if the source code can be improved to get rid of the warning. In this case we don\'t want to change the algorithm just because of that, as argc is redundant with !*argv (NULL after last element).

Using a declaration specifier, like __attribute__

#include <stdio.h>

int main(__attribute__((unused)) int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

If you\'re lucky, the standard provides a specifier for your situation, like _Noreturn.

__attribute__ is proprietary GCC extension (supported by Clang and some other compilers like armcc as well) and will not be understood by many other compilers. Put __attribute__((unused)) inside a macro if you want portable code.

_Pragma operator

_Pragma can be used as an alternative to #pragma.

#include <stdio.h>

_Pragma(\"GCC diagnostic push\")
_Pragma(\"GCC diagnostic ignored \\\"-Wunused-parameter\\\"\")

int main(int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}
_Pragma(\"GCC diagnostic pop\") \\

The main advantage of the _Pragma operator is that you could put it inside macros, which is not possible with the #pragma directive.

Downside: It\'s almost a tactical nuke, as it works line-based instead of declaration-based.

The _Pragma operator was introduced in C99.

#pragma directive.

We could change the source code to suppress the warning for a region of code, typically an entire function:

#include <stdio.h>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored \"-Wunused-parameter\"
int main(int argc, const char *argv[])
{
    while (*++argc) puts(*argv);
    return 0;
}
#pragma GCC diagnostic pop

Downside: It\'s almost a tactical nuke, as it works line-based instead of declaration-baesd.

Suppressing the warning on the command line for a single file

We could add the following line to the Makefile to suppress the warning specifically for puts:

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

puts.o: CPPFLAGS+=-Wno-unused-parameter

This is probably not want you want in your particular case, but it may help other reads who are in similar situations.



回答6:

I had same issue with external libraries like ROS headers. I like to use following options in CMakeLists.txt for stricter compilation:

set(CMAKE_CXX_FLAGS \"-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}\")

However doing this causes all kind of pedantic errors in externally included libraries as well. The solution is to disable all pedantic warnings before you include external libraries and re-enable like this:

//save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored \"-Wpedantic\"

//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

//restore compiler switches
#pragma GCC diagnostic pop


回答7:

Rather than silencing the warnings, gcc style is usually to use either standard C constructs or the __attribute__ extension to tell the compiler more about your intention. For instance, the warning about assignment used as a condition is suppressed by putting the assignment in parentheses, i.e. if ((p=malloc(cnt))) instead of if (p=malloc(cnt)). Warnings about unused function arguments can be suppressed by some odd __attribute__ I can never remember, or by self-assignment, etc. But generally I prefer just globally disabling any warning option that generates warnings for things that will occur in correct code.



回答8:

For those who found this page looking for a way to do this in IAR, try this:

#pragma diag_suppress=Pe177
void foo1( void )
{
   /* The following line of code would normally provoke diagnostic 
      message #177-D: variable \"x\" was declared but never referenced.
      Instead, we have suppressed this warning throughout the entire 
      scope of foo1(). 
   */
   int x;
}
#pragma diag_default=Pe177

See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html for reference.