dcmm88
dcmm88

Reputation: 1515

How to use _Pragma operator in macro?

I'm trying to use the _Pragma operator in order to ignore a warning inside a macro:

#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();    
    }
}

But I see really odd behavior from gcc. If RAII_BLOCK is a macro with no arguments it works as expected: https://godbolt.org/g/J6RxDV

But if I add the parenthesis (in my use case I actually need to pass a real argument), gcc starts complaining: https://godbolt.org/g/tbNtje

Note that clang works as expected in both cases. Does anyone know how to get around this issue (while keeping the shadow warnings for the rest of the code)?

Upvotes: 2

Views: 1058

Answers (1)

Nicolas Tisserand
Nicolas Tisserand

Reputation: 488

Looking at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53469 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=715271, it seems that GCC's handling of _Pragma diagnostic directives in macro invocations had a few issues in the past, possibly still.

I would suggest another route, which is to entirely avoid having to override diagnostics settings in the RAII_BLOCK definition:

#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();
    }
}

This way, all your scope guard variable names will always be unique, removing the necessity for protecting yourself from shadow definitions.

Upvotes: 3

Related Questions