GCC不遵守“pragma GCC diagnostic”来消除警告

37
我们最近为一个项目启用了-Wall。它在GCC 4.7或以上版本(或Clang)时启用,因为我们可以使用GCC Diagnostic来管理升级警告的输出。我们想要从源代码中管理它们,而不是通过命令行参数。(我们不想污染命令行,或者要求库用户重新发现所需内容)。
在GCC 4.8和5.1下,我们正在捕获被禁用的警告,这些警告在GCC诊断块中被禁用,如-Wunused-variable-Wunused-value-Wunused-function-Wunknown-pragmas。这两个GCC都接受-fopenmp,并且都会在响应它时定义_OPENMP,所以我非常确定我们永远不会在#prgam omp ...的响应中看到一个-Wunknown-pragmas(它已经被禁用,但它不是未知的)。
g++ -DNDEBUG -g2 -O3 -Wall -march=native -pipe -c nbtheory.cpp
nbtheory.cpp:655:0: warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
  #pragma omp parallel
 ^
nbtheory.cpp:656:0: warning: ignoring #pragma omp sections [-Wunknown-pragmas]
   #pragma omp sections
 ^
...

在这种情况下,文件nbtheroy.cpp中设置了以下保护措施来帮助管理该警告(仅显示相关部分,但您可以从GitHub链接中查看全部内容):
// Defines GCC_DIAGNOSTIC_AWARE if GCC 4.7 or above.
#include <misc.h>
...

#if GCC_DIAGNOSTIC_AWARE
# pragma GCC diagnostic ignored "-Wunknown-pragmas"
#endif

...
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
                    const Integer &p, const Integer &q, const Integer &u)
{
    Integer p2, q2;
    #pragma omp parallel
        #pragma omp sections
        {
            #pragma omp section
                p2 = ModularExponentiation((a % p), dp, p);
            #pragma omp section
                q2 = ModularExponentiation((a % q), dq, q);
        }
    return CRT(p2, p, q2, q, u);
}
...

因为该文件是 *.cpp 文件(实际上是翻译单元),所以我们在开头不执行 #pragma GCC diagnostic push,也不在结尾执行 #pragma GCC diagnostic pop(但对于被包含的头文件我们会这样做)。我们也曾尝试过这样做,但没有帮助。
下面是来自 misc.hGCC_DIAGNOSTIC_AWARE
// Used to suppress some warnings in some header and implementation files.
//   Some platforms, like CentOS and OpenBSD, use old compilers that don't understand -Wno-unknown-pragma.
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__))

我知道守卫在工作,因为在块中添加#error会导致错误。 此外,注释掉守卫并调用#pragma GCC diagnostic ignored“-Wunknown-pragmas”也无济于事。 最后,在Clang下工作正常。
我还遇到了其他警告,例如-Wunused-variable-Wunused-value-Wunused-function。 我真的不想像建议的潜在重复那样污染命令行。
当使用-Wall时,如何使GCC pragma diagnostic机制按预期工作以消除GCC下的警告?
相关的,如果您想要重现它(基于GNUmakefile,不需要配置或自动工具):
git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
make

编辑:我们提交了一个补丁,除了Clang以外,禁用了-Wall。如果您想要复制旧的行为,则:

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall"
make

1
我建议先删除 #if/#endif(只留下 #pragma GCC ...)以查看是否存在 GCC_DIAGNOSTIC_AWARE 的问题。 - paxdiablo
@paxdiablo - 没有成功。我禁用了守卫,并直接调用了 #pragma GCC diagnostic ignored "-Wunknown-pragmas" - jww
感谢@nneonneo。我也遇到了其他警告,比如“-Wunused-variable”和“-Wunused-value”。我真的很想让“GCC pragma diagnostic”正常工作,而不是用选项污染命令行。 - jww
1
为什么有人会将其标记为重复问题?这里的问题在于出现了许多警告(-Wunknown-pragmas-Wunused-variable-Wunused-value),而向命令行添加其他选项是不可接受的。根本问题是GCC的一个错误,而这甚至没有在所谓的重复问题中提到。 - jww
1个回答

20

这似乎至少是 gcc 中的一个错误。以下代码:

#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wuninitialized"

int fn(void) {
    #pragma xyzzy
    int x;
    return x;
}

int main (void) {
    return fn();
}

在忽略未初始化的x值方面没有问题,但仍然会抱怨#pragma(如果没有uninitialized pragma,则会为x生成警告,正如您所期望的那样)。

如果您将命令行选项更改为-Wall -Wno-unknown-pragmas,则它可以很好地忽略它。对于您的特定情况来说,这是可以接受的,因为您希望它应用于整个翻译单元,但它不允许您从#pragma方法中获得精细的控制(如果它起作用的话)。


我去GCC上提了一个bug报告,但发现它已经存在(#53431)。

虽然那个具体的bug与-Wundef有关,但在其中一条评论中的片段表明它可能适用于所有影响预处理器的变体(稍作修改以突出重点):

C++解析器在处理pragma之前进行词法分析(和预处理),而C解析器则在看到pragma时处理它们。

我们必须以某种方式在cp/parser.c:631中也解析这些pragma。也许可以做类似于我们对cp_parser_initial_pragma所做的事情,但在循环内部,并且只处理pragma diagnostic。当然,需要一些试错才能做到正确。如果你们中的任何人想尝试并需要帮助,只需在这里或邮件列表中询问。

这就解释了为什么我们在编译过程的后期阶段才会看到-Wuninitialized的同样问题,因为它是在预处理结束时激活pragma后的较晚阶段检测到的。

所以,如果你想更及时地解决它(它已经提出了三年多了),我建议(就像我一样)去GCC bugzilla网站上烦扰一下,试图获得一些曝光。


更新:根据链接的错误报告,看起来这个问题将在gcc-13中得到解决,但目前还没有关于该版本发布时间的具体消息。截至2023年2月22日,状态如下:

GCC开发分支将成为GCC 13,目前处于回归和文档修复模式(第四阶段),直到我们解决所有P1回归问题并为发布分支。
我们在朝着这个目标缓慢前进,新的错误以很快的速度出现。
请帮助处理未确认的报告的回归问题,并在被归因于您或您专业领域的错误被分类为目标错误时提供一些分析。
质量数据:
优先级 数量 变化 P1 32 -5 P2 492 -5 P3 77 -11 P4 255 -1 P5 24 总计P1-P3 601 -21 总计 880 -22

因此,如果您希望更及时地解决此问题,请参与到该过程中来,即使只是提供有关严重(P1)问题的更多信息。


是的,更大的问题是这是库代码。因此,我们需要修复它以使其在库本身上工作。对我们来说,这是一个方便项目。但是用户希望在包含库时它可以“正常工作”。如果他们包含库,然后必须通过命令行进行操作,因为事情不起作用,那么这就是一个问题。 - jww
@jww,如果你要发布一个库(.o/.a/.so/etc),那么这个警告肯定不会出现。或者你的库实际上是由可编译源代码组成的吗? - paxdiablo
是的,源代码已经发布。此外,一些头文件会产生警告,我们尝试使用相同的方法来消除它们。 - jww
1
@jww,去提出一个bug时发现它在三年前就被提出了。请查看更新。 - paxdiablo
2
现在相关的问题是:GCC警告OpenMP未知Pragma,尽管它支持它。这只是一个次要问题。我真的很希望能够解决pragma GCC diagnostic的主要问题。 - jww
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接