Как использовать оператор _Pragma в макросе?

Я пытаюсь использовать оператор _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 работает должным образом в обоих случаях. Кто-нибудь знает, как обойти эту проблему (при сохранении теневых предупреждений для остальной части кода)?

По крайней мере, объясните, почему голосование против?

dcmm88 06.04.2018 20:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
533
1

Ответы 1

Глядя на https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53469 и https://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();
    }
}

Таким образом, все имена переменных защиты вашей области видимости всегда будут уникальными, что избавит вас от необходимости защищать себя от теневых определений.

Спасибо @Nicolas. Я тоже рассматривал этот вариант, но, к сожалению, этот обходной путь у меня не работает, так как мне нужно ссылаться на переменную по имени позже в блоке. В итоге я просто попросил пользователя RAII_BLOCK определить переменную. Это означает, что пользователю нужно будет использовать auto tmp = RAII_BLOCK();, что является более распространенной идиомой в C++.

dcmm88 09.04.2018 20:26

Другие вопросы по теме