如何禁用几行代码的GCC警告?

时间:2022-09-06 08:08:01

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?

在visualc++中,可以使用#pragma警告(禁用:…)。我还发现,在GCC中,您可以覆盖每个文件编译器标志。我要如何为“下一行”做这个操作,或者在使用GCC的代码区域中使用push/pop语义?

8 个解决方案

#1


157  

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.

看来这是可以做到的。我无法确定它所添加的GCC版本,但它是在2010年6月之前的某个时间。

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


71  

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.

您可以查看GCC文档关于诊断实用程序的更多细节。

#3


14  

#pragma GCC diagnostic ignored "-Wformat"

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

将“-Wformat”替换为警告标志的名称。

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

AFAIK没有办法为这个选项使用push/pop语义。

#4


11  

#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

这应该对gcc、clang和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

参见https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html, http://clang.llvm.org/docs/usersmanues.html # controller -诊断-via-pragmas和https://msdn.microsoft.com/de/library/d9x1s805.aspx,了解更多细节。

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

您至少需要4.02版本来使用gcc的这些实用程序,不确定msvc和clang的版本。

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.

看起来对gcc的push pop pragma处理有一点损坏。如果您再次启用了警告,您仍然会得到在DISABLE_WARNING/ENABLE_WARNING块内的块的警告。对于某些版本的gcc,它是有效的,对于一些版本则不然。

#5


5  

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

DR:如果它能工作,避免,或者使用像__attribute__这样的说明符,否则就是“pragma”。

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

这是我的博客文章的一个简短版本,在GCC和Clang中压制警告。

Consider the following Makefile

考虑下面的Makefile

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

.PHONY: all
all: puts

for building the following puts.c source code

用于构建以下内容。c源代码

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

它不会编译,因为argc是未使用的,而设置是硬核(-W -Wall -pedantic -Werror)。

There are 5 things you could do:

你可以做5件事:

  • Improve the source code, if possible
  • 如果可能的话,改进源代码。
  • Use a declaration specifier, like __attribute__
  • 使用声明说明符,如__attribute__。
  • Use _Pragma
  • 使用_Pragma
  • Use #pragma
  • 使用# 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).

第一次尝试应该检查源代码是否可以改进以消除警告。在这种情况下,我们不希望仅仅因为这一点而改变算法,因为argc是冗余的!*argv(在最后一个元素之后是NULL)。

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.

如果幸运的话,这个标准为你的情况提供了一个说明符,比如: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.

__attribute__是专有的GCC扩展(由Clang和其他一些编译器支持,比如armcc),并且不会被其他编译器理解。如果需要可移植代码,则在宏中放置__attribute__((未使用的))。

_Pragma operator

_Pragma can be used as an alternative to #pragma.

_Pragma可以作为#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.

_Pragma操作符的主要优点是可以将它放入宏中,这在#pragma指令中是不可能的。

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

缺点:它几乎是一种战术核武器,因为它是基于线的,而不是声明- - -baesd。

The _Pragma operator was introduced in C99.

在C99中引入了_Pragma操作符。

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

缺点:它几乎是一种战术核武器,因为它是基于线的,而不是声明- - -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:

我们可以在Makefile中添加以下行,以抑制特定于put的警告:

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


4  

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

我对类似ROS头的外部库也有同样的问题。我喜欢在CMakeLists中使用以下选项。txt更严格的编译:

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:

然而,这样做会导致外部的所有类型的pedantic错误,包括库。解决方案是在包含外部库之前禁用所有的pedantic警告,并像这样重新启用:

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


2  

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.

gcc的风格通常是使用标准C结构或__attribute__扩展来告诉编译器您的意图,而不是沉默警告。例如,将赋值用作条件的警告被放在括号中,即if ((p=malloc(cnt)))而不是if (p=malloc(cnt))。关于未使用的函数参数的警告可能会被一些奇怪的__attribute__(我永远不会记住,或者通过自我分配等等)来抑制,但是通常我更喜欢全局禁用任何警告选项,它会生成对正确代码中发生的事情的警告。

#8


2  

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

对于那些发现这个页面想要在IAR中这样做的人来说,试试这个:

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

看到http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html供参考。

#1


157  

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.

看来这是可以做到的。我无法确定它所添加的GCC版本,但它是在2010年6月之前的某个时间。

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


71  

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.

您可以查看GCC文档关于诊断实用程序的更多细节。

#3


14  

#pragma GCC diagnostic ignored "-Wformat"

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

将“-Wformat”替换为警告标志的名称。

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

AFAIK没有办法为这个选项使用push/pop语义。

#4


11  

#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

这应该对gcc、clang和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

参见https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html, http://clang.llvm.org/docs/usersmanues.html # controller -诊断-via-pragmas和https://msdn.microsoft.com/de/library/d9x1s805.aspx,了解更多细节。

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

您至少需要4.02版本来使用gcc的这些实用程序,不确定msvc和clang的版本。

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.

看起来对gcc的push pop pragma处理有一点损坏。如果您再次启用了警告,您仍然会得到在DISABLE_WARNING/ENABLE_WARNING块内的块的警告。对于某些版本的gcc,它是有效的,对于一些版本则不然。

#5


5  

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

DR:如果它能工作,避免,或者使用像__attribute__这样的说明符,否则就是“pragma”。

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

这是我的博客文章的一个简短版本,在GCC和Clang中压制警告。

Consider the following Makefile

考虑下面的Makefile

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

.PHONY: all
all: puts

for building the following puts.c source code

用于构建以下内容。c源代码

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

它不会编译,因为argc是未使用的,而设置是硬核(-W -Wall -pedantic -Werror)。

There are 5 things you could do:

你可以做5件事:

  • Improve the source code, if possible
  • 如果可能的话,改进源代码。
  • Use a declaration specifier, like __attribute__
  • 使用声明说明符,如__attribute__。
  • Use _Pragma
  • 使用_Pragma
  • Use #pragma
  • 使用# 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).

第一次尝试应该检查源代码是否可以改进以消除警告。在这种情况下,我们不希望仅仅因为这一点而改变算法,因为argc是冗余的!*argv(在最后一个元素之后是NULL)。

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.

如果幸运的话,这个标准为你的情况提供了一个说明符,比如: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.

__attribute__是专有的GCC扩展(由Clang和其他一些编译器支持,比如armcc),并且不会被其他编译器理解。如果需要可移植代码,则在宏中放置__attribute__((未使用的))。

_Pragma operator

_Pragma can be used as an alternative to #pragma.

_Pragma可以作为#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.

_Pragma操作符的主要优点是可以将它放入宏中,这在#pragma指令中是不可能的。

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

缺点:它几乎是一种战术核武器,因为它是基于线的,而不是声明- - -baesd。

The _Pragma operator was introduced in C99.

在C99中引入了_Pragma操作符。

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

缺点:它几乎是一种战术核武器,因为它是基于线的,而不是声明- - -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:

我们可以在Makefile中添加以下行,以抑制特定于put的警告:

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


4  

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

我对类似ROS头的外部库也有同样的问题。我喜欢在CMakeLists中使用以下选项。txt更严格的编译:

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:

然而,这样做会导致外部的所有类型的pedantic错误,包括库。解决方案是在包含外部库之前禁用所有的pedantic警告,并像这样重新启用:

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


2  

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.

gcc的风格通常是使用标准C结构或__attribute__扩展来告诉编译器您的意图,而不是沉默警告。例如,将赋值用作条件的警告被放在括号中,即if ((p=malloc(cnt)))而不是if (p=malloc(cnt))。关于未使用的函数参数的警告可能会被一些奇怪的__attribute__(我永远不会记住,或者通过自我分配等等)来抑制,但是通常我更喜欢全局禁用任何警告选项,它会生成对正确代码中发生的事情的警告。

#8


2  

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

对于那些发现这个页面想要在IAR中这样做的人来说,试试这个:

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

看到http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html供参考。