7

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

不幸的是,我的编译器不支持#info, #message,#pragma message()等。

我知道有-Wno-error=<something>,但我的 google-foo 很弱,我似乎无法找到<something>for #warning。我试过-Wno-error=warning了,那只是说“没有-Wwarning”。与“ warn”相同。

有什么建议么?

对于它的价值,我正在使用 Tensilica Xtensa编译器 xt-xcc,它似乎是 GNU 的衍生产品,或者至少使用了 GNU 前端。它是 8.0.0 版本。

4

6 回答 6

3

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

  #pragma GCC diagnostic warning "-Wcpp"

#warning一个简单的警告(不是因为 的错误-Werror)。为了使效果暂时,您可以接受 this#pragma#warningbetween #pragma GCC diagnostic pushand #pragma GCC diagnostic pop

当我编译包含以下内容的文件时

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

    #warning two

使用-WerrorGCC 4.6.1 (command 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还包含选项。因此,似乎-Werror较新的 GCC 不再-Werror=cpp像以前那样暗示,如果需要,需要单独提供。

于 2012-09-24T04:53:43.377 回答
1

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

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

我可能会尝试找时间深入研究标准 GCC 命令行和预处理器源代码,以尝试找到 -Wno-error= 可以等于的列表,或者是否存在 -Werror= 代码对应于#warning。

于 2010-12-07T23:34:50.643 回答
1

有什么问题:

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

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

#pragma message string

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

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

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

我不确定你是否想把你的#warning线条编辑成#pragma message线条。它可以帮助您解决问题 - 并且只比在可能由较少编译器支持的#warningin周围添加条件编译更糟糕。#pragma message这取决于您的可移植性要求。

于 2010-12-07T04:41:23.060 回答
1

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

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

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

于 2011-05-05T10:16:01.027 回答
1

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

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

于 2021-01-31T15:12:24.227 回答
0

如果您的编译器支持它,您可以尝试使用constructorfunction 属性来定义一个在程序开始(之前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

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

于 2010-12-07T04:21:28.873 回答