我试图在从宏展开的代码中禁用g++警告。根据我的理解,_Pragma应该遵循宏用法,在用g++编译时不应该触发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。
发布于 2017-12-17 10:31:22
在g++处理_Pragma的过程中存在一些长期存在的错误,这些bug在使用gcc前端时并不存在。唯一的解决方案是要么使用足够现代的g++ (IIRC 6+)版本,要么禁用整个TU的警告。
发布于 2019-06-21 11:59:15
Xarn的回答对于理解为什么我们在用g++ < 9.0编译宏时遇到同样的问题很有帮助,但幸运的是,我很固执,没有拿“唯一的解决方案”作为答案。一些更多的挖掘显示,GCC的受影响版本有一个解决办法。
在GNU上,针对这个问题的2012年原始报告中有一位记者随口提到,如果在编译命令中添加-save-temps或-no-integrated-cpp,_Pragma()将按预期的方式处理。
结果发现,这两个选项中的任何一个都会导致g++ 而不是在默认的流线型模式下运行,这会将预处理和编译阶段折叠为一次。来自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() bug是由单程流线型引入的。)
唯一真正的折衷是,如果您使用启用该选项进行编译,那么编译确实要慢一些。虽然当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()(如果您的target_compile_options()设置比我们的要好的话,那么用适当的现代调用来代替CMAKE_CXX_FLAGS这种丑陋的野蛮强制。)
发布于 2017-03-28 08:24:33
通常,您只使用警告抑制来处理来自第三方代码的不可避免的警告,这样它们就不会扰乱编译日志。在你的情况下最好是
1)使用正则函数,因为宏是邪恶的。
2)处理警告,在可能中断的表达式周围添加圆括号。
if (a <= (expr)) { https://stackoverflow.com/questions/43063596
复制相似问题