C语言 -Werror导致编译器在#warning时停止,我能做些什么来防止这种情况?

g6baxovj  于 2023-06-21  发布在  其他
关注(0)|答案(7)|浏览(335)

首先,我希望它在警告时停止。但我也想打印出一些信息性的消息(比如“回来实现这个!“).
不幸的是,我的编译器不支持#info#message#pragma message()等。
我知道有-Wno-error=<something>,但我的google-foo很弱,我似乎找不到#warning<something>。我试过-Wno-error=warning,它只是说“没有-Wwarning”。与“warn”相同。
有什么建议吗?
就其价值而言,我使用的是Tensilica Xtensa编译器xt-xcc,它似乎是GNU的衍生物,或者至少使用了GNU的前端。版本是8.0.0。

klsxnrf1

klsxnrf11#

我不熟悉Tensilica Xtensa编译器(xt-xcc),但可以使用标准GCC

#pragma GCC diagnostic warning "-Wcpp"

使#warning成为一个简单的警告(而不是因为-Werror而产生的错误)。为了使效果暂时,您可以包含这个#pragma#pragma GCC diagnostic push#pragma GCC diagnostic pop之间的#warning
当我编译包含以下内容的文件时

#pragma GCC diagnostic push
    #pragma GCC diagnostic warning "-Wcpp"
    #warning one
    #pragma GCC diagnostic pop

    #warning two

使用-Werror使用GCC 4.6.1(命令gcc -c -Werror warning-test.c),我得到以下输出:

```lang-none
warning-test.c:3:2: warning: #warning one [-Wcpp]
warning-test.c:6:2: error: #warning two [-Werror=cpp]
cc1: all warnings being treated as errors

当我删除第二个`#warning`时,编译不会因错误而中断。
您还可以将`-Werror`编译器选项替换为`-Werror -Wno-error=cpp`。我不知道`cpp`警告类别还包括哪些其他影响(你可能在其他地方有一个合法的`#warning`,你想捕捉为错误),所以暂时禁用特定`#warning`的错误并立即恢复设置似乎更准确的方法来满足你的要求。
使用GCC版本4.8.4和4.9.2给出了几乎相同的行为(只是额外打印了源代码行)。但是使用GCC版本5.0.1(Ubuntu 15.04(Vivid Vervet)中包含的预发布版本)将给予两个警告,除非同时包含`-Werror=cpp`选项。因此,带有较新GCC的`-Werror`似乎不再像以前那样意味着`-Werror=cpp`,如果需要,需要单独提供。
wbgh16ku

wbgh16ku2#

十年后,发出警告并避免这些来自-Wpedantic的额外消息/错误的正确方法是使用#pragma message。GCC至少从GCC 4.5开始支持此语法,并且至少从Clang 6开始支持Clang。
这些编译器的现代版本甚至支持#pragma GCC error "message"#pragma GCC warning "message"GCC 9,在Clang 6中已经支持)。

mefy6pfw

mefy6pfw3#

有什么不好的:

#warning "Come back and implement this"
#warning "Do not do that!"
#warning "Must fix this before release"

通常情况下,编译器会在错误或警告消息中包含-#warning的参数或-#warning之后的材料。
而且,通常情况下,如果编译器检测到需要警告的内容,它会相当清楚地报告它。
考虑到这些要求,我认为处理这个问题的唯一方法是保护#warning指令。

#ifdef DO_WARNINGS
#warning "Some warning"
#endif /* DO_WARNINGS */

大多数情况下,编译时不使用-DDO_WARNINGS;当你需要检查#warning警告(使用-Werror)时,那么你最终还是包括了-DDO_WARNINGS,接受编译将失败的事实。请记住,即使存在个别编译错误,make -k也会尽可能地执行。
GCC 4.4.1手册的第5.52.9节(部分)指出:

5.52.9诊断pragma

GCC允许用户选择性地启用或禁用某些类型的诊断,并更改诊断的种类。例如,项目的策略可能要求所有源代码都使用“-Werror”编译,但某些文件可能有允许特定类型警告的例外。或者,项目可能有选择地启用诊断,并根据定义的预处理器宏将其视为错误。

#pragma GCC diagnostic kind option

修改诊断程序的处置。请注意,并非所有诊断都是可修改的;此时,只有警告(通常由“-W…”控制)可以被控制,而不是所有的警告。使用“-fdiagnostics-show-option”确定哪些诊断程序是可控的,以及哪个选项控制它们。kind是'error'将此诊断视为错误,'warning'将其视为警告(即使'-Werror'有效),或'ignored'如果诊断将被忽略。option是与命令行选项匹配的双引号字符串。

#pragma GCC diagnostic warning "-Wformat"
#pragma GCC diagnostic error "-Wformat"
#pragma GCC diagnostic ignored "-Wformat"

请注意,这些杂注会覆盖任何命令行选项。此外,虽然将这些杂注放在源代码中的任何位置在语法上都是有效的,但它们唯一受支持的位置是在定义任何数据或函数之前。否则可能会导致不可预知的结果,具体取决于优化器管理源的方式。如果多次列出相同的选项,则最后指定的选项将有效。此杂注不打算作为命令行选项的通用替代品,而是用于实现对项目策略的严格控制。
GCC还提供了一种简单的机制,用于在编译期间打印消息。

#pragma message string

在编译时将字符串打印为编译器消息。该消息仅供参考,既不是编译警告,也不是错误。

#pragma message "Compiling " __FILE__ "..."

字符串可以用括号括起来,并打印出位置信息。
我不确定您是否愿意将#warning行编辑为#pragma message行。它可以解决这个问题,而且只比在#warning周围添加条件编译更糟糕,因为#pragma message可能由更少的编译器支持。这取决于您的可移植性要求是什么。

1bqhqjot

1bqhqjot4#

假设#warning是由预处理器处理的,你可以单独运行预处理器而不使用-Werror,然后在pro-processor输出上禁止预处理的情况下运行编译器。
为此,使用除-Werror之外的所有常规选项通过预处理器运行.c文件,并将输出生成为.i文件(C++为.ii)。编译器会将这些文件识别为 not to be pre-processed,因此您可以使用-Werror编译它们,并且假设预处理器丢弃了#警告并且编译器本身没有处理它,这可能会解决您的问题。
我没有测试过这个;当我遇到同样的问题时,我只是选择接受它,而不使用-Werror。解决方案似乎比问题更复杂!

qyzbxkaa

qyzbxkaa5#

不幸的是,我的特定工具链没有答案,Tensilica的工程师说。它们不支持#message或#pragma message(),也不知道如何在出现-Werror时将#warning作为error禁止。
GCC工具链允许使用-Wno-error=[code]来表示“this warning is not an error”,但我还没有找到一个列表,将#warning对应于任何可能的代码(甚至是可能的代码列表)。
我可能会找时间深入研究标准GCC命令行和预处理器源代码,试图找到一个列表,列出-Wno-error=可以等于什么,或者是否有一个-Werror=代码对应于#warning。

gstyhher

gstyhher6#

如果你的编译器支持它,你可以尝试使用constructor function属性来定义一个在程序开始时(在main之前)运行的函数,该函数将一条消息打印到stdout:

#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
#define TOKENPASTE2(x, y) x ## y
#define WARNING(message) \
  static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \
  static void TOKENPASTE(_print_warning, __LINE__)() \
  { \
    puts(message); \
  }

WARNING("fix this before ship")  // prints out a message at runtime before main

这会导致在运行时而不是编译时打印出消息,这几乎是一样好的,特别是如果你没有其他选择的话。唯一的限制是你必须在函数定义之外的全局范围内使用它。

yzuktlbb

yzuktlbb7#

-Wno-error=#warnings似乎可以处理最近的clangs(测试14..17)
G++(11 & 12)不支持等价的,建议使用--no-warnings-这不是你想要的。
唯一的问题可能是让你的构建工具消化散列,所以它会进入编译器……

相关问题