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

发布于 2024-09-12 10:37:32 字数 338 浏览 4 评论 0 原文

在 Visual C++ 中,可以使用 #pragma warning(禁用:.. .)。我还发现在 GCC 中你可以 覆盖每个文件编译器标志。我该如何为“下一行”执行此操作,或者使用 GCC 在代码区域周围使用推送/弹出语义?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

忆离笙 2024-09-19 10:37:32

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

下面是一个示例:

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

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 */
π浅易 2024-09-19 10:37:32

为了解决所有问题,这是暂时禁用警告的示例:

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

您可以检查有关诊断编译指示的 GCC 文档 了解更多详细信息。

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.

孤芳又自赏 2024-09-19 10:37:32

TL;DR:如果有效,请避免或使用 _Noreturn[[nodiscard]]__attribute__ 等说明符>,否则_Pragma

这是我的博客文章的简短版本
抑制GCC 和 Clang

考虑以下 Makefile

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

.PHONY: all
all: puts

用于构建以下 puts.c 源代码:

#include <stdio.h>

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

它将无法编译,因为 argc 未使用,并且设置是硬核的(-W -Wall -pedantic -Werror)。

您可以做五件事:

  • 如果可能,改进源代码
  • 使用属性,例如 [[maybe_unused]]
  • 使用声明说明符,例如 __attribute__
  • 使用 _Pragma
  • 使用#pragma
  • 使用命令行选项。

改进源代码

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

使用属性,例如 [[maybe_unused]]

#include <stdio.h>

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

如果幸运的话,标准会为您的情况提供一个属性,例如 [[maybe_unused]]。属性是C2x的一个新特性。到目前为止,C2x 定义了四个属性,[[deprecated]][[fallthrough]][[maybe_unused]] >[[不丢弃]]

使用声明说明符,如 __attribute__

#include <stdio.h>

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

如果幸运的话,该标准会为您的情况提供一个说明符,如 _Noreturn

__attribute__ 是专有的 GCC 扩展(受 Clang 和其他一些编译器(如 armcc)支持),许多其他编译器无法理解。如果您想要可移植的代码,请将 __attribute__((unused)) 放入宏内。

_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")

_Pragma 运算符的主要优点是您可以将其放入宏中,而 #pragma 指令则无法做到这一点。

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

_Pragma 运算符是在 C99 中引入的。

#pragma 指令。

我们可以更改源代码以抑制某个代码区域(通常是整个函数)的警告:

#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

缺点:它几乎是一个战术核武器,因为它基于行而不是基于声明。

请注意,Clang 中存在类似的语法。

抑制单个文件的命令行上的警告

我们可以将以下行添加到 Makefile 中,以抑制专门针对 put 的警告:

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

.PHONY: all
all: puts

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

在您的特定情况下,这可能不是您想要的,但它可能帮助其他有类似情况的读者。

TL;DR: If it works, avoid, or use specifiers like _Noreturn, [[nodiscard]], __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 five things you could do:

  • Improve the source code, if possible
  • Use an attribute, like [[maybe_unused]]
  • 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 an attribute, like [[maybe_unused]]

#include <stdio.h>

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

If you're lucky, the standard provides an attribute for your situation, like [[maybe_unused]]. Attributes are a new feature of C2x. So far, C2x defines four attributes, [[deprecated]], [[fallthrough]], [[maybe_unused]], and [[nodiscard]].

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

Note that a similar syntax exists in Clang.

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 readers who are in similar situations.

很酷又爱笑 2024-09-19 10:37:32

我知道问题是关于 GCC 的,但是对于寻找如何在其他和/或多个编译器中执行此操作的人来说...

TL;DR

您可能想看看 Hedley,这是我编写的公共域单个 C/C++ 标头,它为您完成了很多这些工作。我将在本文末尾快速介绍如何使用 Hedley 来完成这一切。

禁用警告

#pragma warning (disable: …) 在大多数编译器中具有等效功能:

  • MSVC: #pragma warning(disable:4996)
  • GCC: #pragma GCC 诊断忽略了“-W…” 其中省略号是名称警告; 例如#pragma GCC 诊断忽略了“-Wdeprecated-declarations
  • Clang: #pragma clang Diagnosticignored "-W..."。语法与 GCC 基本相同,并且许多警告名称相同(尽管许多警告名称不同) )。
  • Intel C++ 编译器 (ICC):使用 MSVC 语法,但保留请注意,警告编号完全不同。示例:#pragma warning(disable:1478 1786)
  • 。 "noreferrer">PGI/Nvidia:有一个 diag_suppress 编译指示:#pragma diag_suppress 1215,1444 请注意 所有警告数字增加了 20.7 分之一(第一个 Nvidia HPC 版本)。
  • TI (CCS):有一个 diag_suppress 编译指示,其与 PGI 语法相同(但警告编号不同!): pragma diag_suppress 1291,1718
  • Oracle Developer Studio (ODS) (suncc):有一个 error_messages pragma。令人烦恼的是,C 和 C++ 编译器的警告是不同的。这两个都禁用基本相同的警告:
    • C:#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
    • C++:#pragma error_messages(off,symdeprecated,symdeprecated2)
  • IAR:也像 PGI 和 TI 一样使用 diag_suppress,但语法不同。一些警告数字是相同的,但其他警告数字有所不同:#pragma diag_suppress=Pe1444,Pe1215
  • Pelles C:与 MSVC 类似,但数字又不同#pragma warn(disable:2241)

对于大多数编译器来说,这通常是一个好主意在尝试禁用它之前检查编译器版本,否则您最终会触发另一个警告。例如,GCC 7 添加了对 -Wimplicit-fallthrough 警告的支持,因此如果您关心 7 之前的 GCC,您应该执行

#if defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

For Clang 和基于 Clang 的编译器之类的操作,例如较新版本的 XL C/C++ 和armclang,你可以检查一下编译器是否知道使用 __has_warning() 宏的特定警告。

#if __has_warning("-Wimplicit-fallthrough")
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif

当然,您还必须检查 __has_warning() 宏是否存在:

#if defined(__has_warning)
#  if __has_warning("-Wimplicit-fallthrough")
#    pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#  endif
#endif

您可能会想做类似的事情,

#if !defined(__has_warning)
#  define __has_warning(warning)
#endif

因此您可以更轻松地使用 __has_warning 。 Clang 甚至在其手册中为 __has_builtin() 宏提出了类似的建议。 不要这样做。其他代码可能会检查 __has_warning 并在编译器版本不存在时回退到检查编译器版本,如果您定义 __has_warning 您将破坏他们的代码。正确的方法是在您的命名空间中创建一个宏。例如:

#if defined(__has_warning)
#  define MY_HAS_WARNING(warning) __has_warning(warning)
#else
#  define MY_HAS_WARNING(warning) (0)
#endif

然后您可以执行诸如

#if MY_HAS_WARNING(warning)
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

推送和弹出之

类的操作许多编译器还支持将警告推送到堆栈并弹出警告的方法。例如,这将禁用 GCC 上一行代码的警告,然后将其返回到之前的状态:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop

当然,编译器之间对于语法没有太多共识:

  • GCC 4.6+: #pragma GCC诊断推送 / #pragma GCC 诊断弹出
  • Clang:#pragma clang 诊断推送 / #pragma clang 诊断弹出
  • Intel 13+ (可能更早):#pragma warning(push) / #pragma warning(pop)
  • MSVC 15+ (Visual Studio 9.0 / 2008): #pragma warning(push) / #pragma warning(pop)
  • ARM 5.6+:#pragma push / #pragma pop
  • TI 8.1+:#pragma diag_push / #pragma diag_pop >
  • Pelles C 2.90+(可能更早):#pragma warning(push) / #pragma warning(pop)

如果没记错的话,对于一些非常旧的 GCC 版本(像 3.x、IIRC)push/pop 编译指示必须位于函数的外部

隐藏血淋淋的细节

对于大多数编译器来说,可以使用 _Pragma 隐藏宏背后的逻辑,这是在 C99。即使在非C99模式下,大多数编译器也支持_Pragma;最大的例外是 MSVC,它有自己的 __pragma 关键字,但语法不同。标准的 _Pragma 接受一个字符串,微软的版本没有:

#if defined(_MSC_VER)
#  define PRAGMA_FOO __pragma(foo)
#else
#  define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO

经过预处理后,大致相当于

#pragma foo

这让我们创建宏,这样我们就可以编写类似的代码

MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP

并隐藏宏中所有丑陋的版本检查定义。

简单的方法:Hedley

现在您已经了解了如何在保持代码整洁的同时可移植地执行此类操作的机制,您也了解了我的项目之一 赫德利 确实如此。您无需深入挖掘大量文档和/或安装尽可能多版本的编译器来进行测试,只需包含 Hedley(它是一个公共域 C/C++ 标头)即可完成。例如:

#include "hedley.h"

HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP

将禁用有关在 GCC、Clang、ICC、PGI、MSVC、TI、IAR、ODS、Pelles C 和其他可能上调用已弃用函数的警告(我可能不会在更新 Hedley 时费心更新此答案) 。而且,在未知的编译器上,宏将被预处理为无,因此您的代码将继续与任何编译器一起工作。当然,HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 并不是 Hedley 知道的唯一警告,禁用警告也不是 Hedley 所能做的所有事情,但希望您能明白这一点。

I know the question is about GCC, but for people looking for how to do this in other and/or multiple compilers…

TL;DR

You might want to take a look at Hedley, which is a public-domain single C/C++ header I wrote which does a lot of this stuff for you. I'll put a quick section about how to use Hedley for all this at the end of this post.

Disabling the warning

#pragma warning (disable: …) has equivalents in most compilers:

  • MSVC: #pragma warning(disable:4996)
  • GCC: #pragma GCC diagnostic ignored "-W…" where the ellipsis is the name of the warning; e.g., #pragma GCC diagnostic ignored "-Wdeprecated-declarations.
  • Clang: #pragma clang diagnostic ignored "-W…". The syntax is basically the same as GCC's, and many of the warning names are the same (though many aren't).
  • Intel C++ Compiler (ICC): Use the MSVC syntax, but keep in mind that warning numbers are totally different. Example: #pragma warning(disable:1478 1786).
  • PGI/Nvidia: There is a diag_suppress pragma: #pragma diag_suppress 1215,1444. Note that all warning numbers increased by one in 20.7 (the first Nvidia HPC release).
  • TI (CCS): There is a diag_suppress pragma with the same syntax (but different warning numbers!) as PGI: pragma diag_suppress 1291,1718
  • Oracle Developer Studio (ODS) (suncc): there is an error_messages pragma. Annoyingly, the warnings are different for the C and C++ compilers. Both of these disable basically the same warnings:
    • C: #pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
    • C++: #pragma error_messages(off,symdeprecated,symdeprecated2)
  • IAR: also uses diag_suppress like PGI and TI, but the syntax is different. Some of the warning numbers are the same, but I others have diverged: #pragma diag_suppress=Pe1444,Pe1215
  • Pelles C: similar to MSVC, though again the numbers are different #pragma warn(disable:2241)

For most compilers it is often a good idea to check the compiler version before trying to disable it, otherwise you'll just end up triggering another warning. For example, GCC 7 added support for the -Wimplicit-fallthrough warning, so if you care about GCC before 7 you should do something like

#if defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

For Clang and compilers based on Clang, such as newer versions of XL C/C++ and armclang, you can check to see if the compiler knows about a particular warning using the __has_warning() macro.

#if __has_warning("-Wimplicit-fallthrough")
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif

Of course you also have to check to see if the __has_warning() macro exists:

#if defined(__has_warning)
#  if __has_warning("-Wimplicit-fallthrough")
#    pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#  endif
#endif

You may be tempted to do something like

#if !defined(__has_warning)
#  define __has_warning(warning)
#endif

So you can use __has_warning a bit more easily. Clang even suggests something similar for the __has_builtin() macro in their manual. Do not do this. Other code may check for __has_warning and fall back on checking compiler versions if it doesn't exist, and if you define __has_warning you'll break their code. The right way to do this is to create a macro in your namespace. For example:

#if defined(__has_warning)
#  define MY_HAS_WARNING(warning) __has_warning(warning)
#else
#  define MY_HAS_WARNING(warning) (0)
#endif

Then you can do stuff like

#if MY_HAS_WARNING(warning)
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

Pushing and popping

Many compilers also support a way to push and pop warnings onto a stack. For example, this will disable a warning on GCC for one line of code, then return it to its previous state:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop

Of course there isn't a lot of agreement across compilers about the syntax:

  • GCC 4.6+: #pragma GCC diagnostic push / #pragma GCC diagnostic pop
  • Clang: #pragma clang diagnostic push / #pragma clang diagnostic pop
  • Intel 13+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
  • MSVC 15+ (Visual Studio 9.0 / 2008): #pragma warning(push) / #pragma warning(pop)
  • ARM 5.6+: #pragma push / #pragma pop
  • TI 8.1+: #pragma diag_push / #pragma diag_pop
  • Pelles C 2.90+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)

If memory serves, for some very old versions of GCC (like 3.x, IIRC) the push/pop pragmas had to be outside of the function.

Hiding the gory details

For most compilers it's possible to hide the logic behind macros using _Pragma, which was introduced in C99. Even in non-C99 mode, most compilers support _Pragma; the big exception is MSVC, which has its own __pragma keyword with a different syntax. The standard _Pragma takes a string, Microsoft's version doesn't:

#if defined(_MSC_VER)
#  define PRAGMA_FOO __pragma(foo)
#else
#  define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO

Is roughly equivalent, once preprocessed, to

#pragma foo

This let’s us create macros so we can write code like

MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP

And hide away all the ugly version checks in the macro definitions.

The easy way: Hedley

Now that you understand the mechanics of how to do stuff like this portably while keeping your code clean, you understand what one of my projects, Hedley does. Instead of digging through tons of documentation and/or installing as many versions of as many compilers as you can to test with, you can just include Hedley (it is a single public domain C/C++ header) and be done with it. For example:

#include "hedley.h"

HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP

Will disable the warning about calling a deprecated function on GCC, Clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles C, and possibly others (I probably won't bother updating this answer as I update Hedley). And, on compilers which aren't known to work, the macros will be preprocessed away to nothing, so your code will continue to work with any compiler. Of course HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED isn't the only warning Hedley knows about, nor is disabling warnings all Hedley can do, but hopefully you get the idea.

离旧人 2024-09-19 10:37:32
#pragma GCC diagnostic ignored "-Wformat"

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

AFAIK 无法为此选项使用推送/弹出语义。

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

哎呦我呸! 2024-09-19 10:37:32

使用:

#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

这对于 GCC、ClangMSVC

可以使用以下命令调用它:

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

参见7 Pragmas, 通过 Pragmas 控制诊断< /em> 和 Pragma指令以及 __pragma 和 _Pragma 关键字了解更多详细信息。

您至少需要 4.02 版本才能在 GCC 中使用这些编译指示,并且我不确定 MSVC 和 Clang 的版本。

看起来 GCC 的 push pop pragma 处理有点问题。如果再次启用警告,您仍然会收到 DISABLE_WARNING/ENABLE_WARNING 块内的块的警告。对于某些版本的 GCC 它可以工作,而对于某些版本则不行。

Use:

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

It 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 7 Pragmas, Controlling Diagnostics via Pragmas and Pragma directives and the __pragma and _Pragma keywords for more details.

You need at least version 4.02 to use these kind of pragmas for GCC, and I am 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, and for some it doesn't.

风柔一江水 2024-09-19 10:37:32

我对 ROS 标头等外部库有同样的问题。我喜欢在 CMakeLists.txt 进行更严格的编译:

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

但是,这样做也会导致外部包含的库中出现各种迂腐的错误。解决方案是在包含外部库之前禁用所有迂腐的警告并重新启用它们,如下所示:

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

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

// Restore compiler switches
#pragma GCC diagnostic pop

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 them like this:

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

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

// Restore compiler switches
#pragma GCC diagnostic pop
绻影浮沉 2024-09-19 10:37:32

这是在 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

请参阅 官方文档供参考。

Here is 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 official documentation for reference.

千紇 2024-09-19 10:37:32

GCC 风格通常不是沉默警告,而是使用标准 C 结构或 __attribute__ 扩展来告诉编译器更多关于您的意图。

例如,通过将赋值放在括号中来抑制有关用作条件的赋值的警告,即 if ((p=malloc(cnt))) 而不是 if (p=malloc( cnt))

关于未使用的函数参数的警告可以通过一些我永远记不起来的奇怪的 __attribute__ 或通过自分配等来抑制。

但一般来说,我更喜欢全局禁用任何为将要发生的事情生成警告的警告选项在正确的代码中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文