如何在宏中使用_Pragma运算符?

时间:2018-04-06 18:03:10

标签: c++ c++11 gcc clang gcc-warning

我试图使用_Pragma运算符来忽略宏内的警告:

#define RAII_BLOCK() \
    _Pragma("GCC diagnostic push \"-Wshadow\"") \
    _Pragma("GCC diagnostic ignored \"-Wshadow\"") \
    auto a = RAII(); \
    _Pragma("GCC diagnostic pop")

void foo() {
    RAII_BLOCK();
    {
        RAII_BLOCK();    
    }
}

但是我从gcc看到了非常奇怪的行为。如果RAII_BLOCK是没有参数的宏,则按预期工作:https://godbolt.org/g/J6RxDV

但是如果我添加括号(在我的用例中我实际上需要传递一个真实的参数),gcc开始抱怨:https://godbolt.org/g/tbNtje

请注意,clang在两种情况下都按预期工作。有谁知道如何解决这个问题(同时保留其余代码的阴影警告)?

1 个答案:

答案 0 :(得分:2)

看看https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53469https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=715271,GCC在宏调用中对_Pragma诊断指令的处理似乎在过去有一些问题,可能仍然存在。

我建议另一条路线,完全避免在RAII_BLOCK定义中覆盖诊断设置:

#include <iostream>
using namespace std;

struct RAII{
    RAII() { cout << "acquired" << endl; }
    ~RAII() { cout << "released" << endl; }
};

#define CONCAT_(a, b) a ## b
#define CONCAT(a, b) CONCAT_(a, b)
#define RAII_BLOCK() auto CONCAT(a,__COUNTER__) = RAII();

void foo() {
    RAII_BLOCK();
    {
        RAII_BLOCK();
    }
}

这样,所有范围保护变量名称将始终是唯一的,从而消除了保护自己免受阴影定义的必要性。