G ++忽略_Pragma诊断忽略

时间:2017-03-28 07:48:11

标签: c++ c++11 gcc g++ c-preprocessor

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

#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。

3 个答案:

答案 0 :(得分:0)

通常,您仅使用警告抑制来处理来自第三方代码的不可避免的警告,因此它们不会使编译日志混乱。在你的情况下,

会更好

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

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

if (a <= (expr)) { 

答案 1 :(得分:0)

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

答案 2 :(得分:0)

Xarn的答案对于弄清为什么在使用g++ <9.0进行编译时为什么在宏中遇到相同的问题非常有帮助,但幸运的是我很固执并且不采取“唯一的解决方案”来解决问题。回答。进一步的挖掘表明,对于受影响的GCC版本,存在 解决方法。

在GNU的bugzilla中,此问题的original 2012 reports之一包括了记者的随笔提述,即_Pragma()如果添加了-save-temps或{{1} }编译命令。

结果表明,这两个选项中的任何一个都会导致-no-integrated-cpp 以其默认的简化模式运行,该模式将预处理和编译阶段折叠在一起。在g++ 9.1.1的手册页中:

g++

这意味着添加 -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错误-到目前为止是5.4、7.3,我认为是8.1-但除此之外没有对构建最终结果的影响。 (由此可以推断出_Pragma()错误是通过单次通过简化而引入的。)

唯一的折衷是,如果在启用该选项的情况下进行编译,编译的速度确实会慢一些。当您的GCC是受影响的版本之一时,这当然是值得的,但我们在CMake构建设置中使用了条件,以确保仅在必要时设置_Pragma()

-no-integrated-cpp

(如果您的CMake设置优于我们的设置,请用适当的现代调用替换#### 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() 以进行target_compile_options()的丑陋暴力破解。)