G++ 忽略 _Pragma 诊断被忽略

Posted

技术标签:

【中文标题】G++ 忽略 _Pragma 诊断被忽略【英文标题】:G++ ignores _Pragma diagnostic ignored 【发布时间】:2017-03-28 07:48:11 【问题描述】:

我正在尝试禁用从宏扩展的代码中的 g++ 警告。据我了解,_Pragma 应遵循宏用法,并且在使用 g++ 编译时不应触发 Wparentheses

#include <stdio.h>

#define TEST(expr) \
    int a = 1; \
    _Pragma( "GCC diagnostic push" ) \
    _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) \
    if (a <= expr)  \
        printf("filler\n"); \
     \
    _Pragma( "GCC diagnostic pop" )

int main()
    int b = 2, c = 3;
    TEST(b == c);

当我用g++ 编译它时,我收到Wparentheses 警告,我正在尝试禁用它。

xarn@DESKTOP-B2A3CNC:/mnt/c/ubuntu$ g++ -Wall -Wextra test3.c
test3.c: In function ‘int main()’:
test3.c:8:11: warning: suggest parentheses around comparison in operand of ‘==’ [-Wparentheses]
     if (a <= expr)  \
           ^
test3.c:15:5: note: in expansion of macro ‘TEST’
     TEST(b == c);
     ^

但是在使用gcc 时它按预期工作:

xarn@DESKTOP-B2A3CNC:/mnt/c/ubuntu$ gcc -Wall -Wextra test3.c
test3.c: In function ‘main’:
test3.c:16:1: warning: control reaches end of non-void function [-Wreturn-type]
 
 ^

我使用的是g++ 4.8.5 版。

【问题讨论】:

gcc 4.8.5 不会编译带有gcc -Wall -Wextra test3.c 的发布源代码。由于iostream 不是C 头文件,因此它应该以fatal error: iostream: No such file or directory 失败。请贴出真实代码。 @MikeKinghan 抱歉,从引发问题的 .cpp 文件中复制粘贴。现在它使用printf 【参考方案1】:

在 g++ 处理_Pragmas 中存在长期存在的错误,使用 gcc 前端时不存在这些错误。唯一的解决方案是继续使用足够现代的 g++ (IIRC 6+) 版本,或者禁用整个 TU 的警告。

【讨论】:

我确实设法为受影响的 GCC 版本找到了解决方案,请参阅 my answer。 (不过,这对我指出正确的方向很有帮助!)【参考方案2】:

Xarn 的回答非常有助于找出为什么我们在使用 g++ 有一种解决方法。

在 GNU 的 bugzilla 中,针对此问题的 original 2012 reports 之一包括来自记者的临时提及,如果他们将 -save-temps-no-integrated-cpp 添加到编译命令中,_Pragma() 将按预期进行处理。

事实证明,这些选项中的任何一个都会导致 g++ NOT 以默认的流线型模式运行,该模式将预处理和编译阶段合并为一个通道。来自g++ 9.1.1 的手册页:

    -no-integrated-cpp

       Perform preprocessing as a separate pass before compilation.  By
       default, GCC performs preprocessing as an integrated part of input
       tokenization and parsing.  If this option is provided, the
       appropriate language front end (cc1, cc1plus, or cc1obj for C, C++,
       and Objective-C, respectively) is instead invoked twice, once for
       preprocessing only and once for actual compilation of the
       preprocessed input.  This option may be useful in conjunction with
       the -B or -wrapper options to specify an alternate preprocessor or
       perform additional processing of the program source between normal
       preprocessing and compilation.

这意味着在我们测试过的每个受影响的 GCC 版本中添加 -no-integrated-cpp 确实可以解决 _Pragma() 错误 - 到目前为止是 5.4、7.3,我相信是 8.1 - 但对最终版本没有影响构建的结果。 (由此可以推断,_Pragma() 错误是由单通道简化引入的。)

唯一真正的权衡是编译确实会慢一些,如果你在构建时启用了该选项。虽然当您的 GCC 是受影响的版本之一时这当然是值得的,但我们在 CMake 构建设置中使用条件来确保仅在必要时设置 -no-integrated-cpp

#### Work around a GCC < 9 bug with handling of _Pragma() in macros
#### See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
if (($CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND
    ($CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0"))
        set(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -no-integrated-cpp")
endif()

(如果您的 CMake 设置比我们的更好,请适当地替换对 target_compile_options() 的现代调用来代替 CMAKE_CXX_FLAGS 的丑陋暴力破解。)

【讨论】:

【参考方案3】:

通常,您只使用警告抑制来处理来自第三方代码的不可避免的警告,这样它们就不会弄乱编译日志。在你的情况下,它会更好

1) 使用常规函数,因为宏是邪恶的

2) 通过在可能损坏的表达式周围添加圆括号来处理警告

if (a <= (expr))  

【讨论】:

有问题的代码是一个最小的例子。在实际代码中,a 是一种特殊类型的实例,它使用重载的&lt;= 运算符来执行魔术。 operator overloading guideline 建议让重载的运算符执行魔术(我猜在你的情况下 我很确定Catch 和朋友们不同意。

以上是关于G++ 忽略 _Pragma 诊断被忽略的主要内容,如果未能解决你的问题,请参考以下文章

编译器处理警告错误 #pragma GCC diagnostic ignored "-Wunused"

可以将 GCC 配置为忽略 #pragma 指令吗?

各个层次的gcc警告

带有“#”的 Clang 诊断标志会导致构建错误

经典/基础BFS+略微复杂的题意PAT-L3-004. 肿瘤诊断

#include 被忽略