繁体   English   中英

-Werror 导致编译器停止#warning。 我能做些什么来防止这种情况?

[英]-Werror causes compiler to stop on #warning. What can I do to prevent this?

首先,我希望它停止警告。 但我也想打印一些信息性的消息(比如“回来实施这个!”)。

不幸的是,我的编译器不支持#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。

我不熟悉 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 ),我得到以下输出:

    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 -Wno-error=cpp替换-Werror编译器选项。 我不知道cpp类别的警告包括哪些其他影响(并且您可能在其他地方有一个合法的#warning想要捕获为错误),因此暂时禁用特定#warning的错误并立即恢复设置之后似乎更准确的方法来满足您的要求。

编辑(2016 年):使用gcc版本 4.8.4 和 4.9.2 给出了几乎相同的行为(仅额外打印出源代码行)。 但是使用gcc版本 5.0.1(包含在 Ubuntu 15.04 中的预发布版本)将给出两个警告,除非还包含选项-Werror=cpp 如此看来, -Werror用新的gcc已经不意味着-Werror=cpp像以前一样,它需要如果需要单独提供。

有什么问题:

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

通常,编译器会在错误或警告消息中包含参数 - 或 - #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 诊断编译指示

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"

请注意,这些编译指示会覆盖任何命令行选项。 此外,虽然将这些编译指示放在源中的任何位置在语法上是有效的,但它们唯一受支持的位置是在定义任何数据或函数之前。 否则可能会导致不可预测的结果,具体取决于优化器如何管理您的源。 如果多次列出相同的选项,则最后指定的选项是有效的选项。 此 pragma 并非旨在作为命令行选项的通用替代品,而是用于实施对项目策略的严格控制。

GCC 还提供了一种在编译期间打印消息的简单机制。

 #pragma message string

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

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

字符串可以用括号括起来,并与位置信息一起打印。

我不确定您是否愿意将#warning行编辑为#pragma message行。 它会让你解决这个问题 - 并且只比在#warning周围添加条件编译更糟糕,因为#pragma message可能被更少的编译器支持。 这取决于您的便携性要求是什么。

不幸的是,我的特定工具链没有答案,或者 Tensilica 的工程师说。 他们不支持#message 或#pramga message(),也不知道如何在存在-Werror 的情况下将#warning 抑制为错误。

GCC 工具链允许使用 -Wno-error=[code] 来表示“此警告不是错误”,但我还没有找到与 #warning 对应的任何代码的列表(甚至是这可能是代码)

我可能会尝试找时间深入研究标准 GCC 命令行和预处理器源代码,以尝试找到 -Wno-error= 可以等于的列表,或者是否有 -Werror= 代码对应于#warning。 如果我这样做,我会回来更新答案。

鉴于#warning 可能是由预处理器处理的,您可以单独运行预处理器而不使用 -Werror,然后在预处理器输出上禁止预处理的情况下运行编译器。

为此,请使用除 -Werror 之外的所有常规选项通过预处理器运行 .c 文件,并将输出生成为 .i 文件(对于 C++ 为 .ii)。 编译器将这些文件识别为未经预处理,因此您可以使用 -Werror 编译它们,并假设预处理器删除 #warning 并且编译器本身不处理它,这可能会解决您的问题。

我没有测试过这个; 当我遇到同样的问题时,我只是选择忍受它而不使用 -Werror。 解决方案似乎比问题更复杂!

十年后,发出警告并避免来自 -Wpedantic 的这些附加消息/错误的正确方法是使用#pragma message GCC 至少从GCC 4.5开始支持这种语法,至少从Clang 6开始就支持 clang。

这些编译器的现代版本甚至支持#pragma GCC error "message"#pragma GCC warning "message"GCC9 ,已在 Clang 6 中支持)

如果您的编译器支持它,您可以尝试使用constructor函数属性来定义一个在程序启动时(在main之前)运行的函数,该函数将一条消息打印到标准输出:

#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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM