Отключить одиночное предупреждение об ошибке

115

Есть ли способ отключить только одну строку предупреждения в файле cpp с помощью Visual Studio?

Например, если я поймаю исключение и не обрабатываю его, я получаю ошибку 4101 (локальная переменная без ссылки). Есть ли способ игнорировать это только в этой функции, но в противном случае сообщить об этом в модуле компиляции? На данный момент я помещаю его #pragma warning (disable : 4101)в начало файла, но это, очевидно, просто отключает его для всего устройства.

Cookie-файлы
источник
19
если вы укажете только тип и не укажете исключение, предупреждения не будет. Напр catch (const std::exception& /* unnamed */) {.... }. Он не отвечает на ваш вопрос, но может решить вашу проблему.
Sjoerd

Ответы:

182
#pragma warning( push )
#pragma warning( disable : 4101)
// Your function
#pragma warning( pop ) 
Андреас Бринк
источник
1
@Cookie: да, это работает для любого фрагмента кода, который проходит через компилятор.
Matteo Italia
Для более свежего и краткого ответа см. Ответ Дэниела Зейтера ниже.
Дэн Ниссенбаум
4
clangкажется, не поддерживают эту прагму, но вы можете достичь того же эффекта #pragma clang diagnostic push, #pragma clang diagnostic ignored "-Wunused-variable"и #pragma clang diagnostic pop. См. «Управление диагностикой с помощью прагм» в руководстве пользователя Clang
rampion
Поскольку я использую эту функцию нечасто, когда я это делаю, я обычно попадаю на эту страницу, чтобы напомнить себе о синтаксисе. Я просто поместил его вокруг вызова устаревшей функции, которая может никогда не обновиться, чтобы предупреждение не раздражало меня в списках компилятора, которые я скрупулезно просматриваю.
Дэвид А. Грей
Для Visual Studio аргумент командной строки - /wd4101. Обратите внимание, что :между флагом и числом нет нормального значения , и вы не можете составить список чисел, разделенных запятыми. Для других компиляторов это может быть /nowarn:4101вместо этого.
Джесси
90

Если вы хотите подавить предупреждение только в одной строке кода, вы можете использовать suppress спецификатор предупреждения :

#pragma warning(suppress: 4101)
// here goes your single line of code where the warning occurs

Для одной строки кода это работает так же, как написание следующего:

#pragma warning(push)
#pragma warning(disable: 4101)
// here goes your code where the warning occurs
#pragma warning(pop)
Дэниел Зайтер
источник
8
Очень полезно! К сожалению, это не работает для одной строки, содержащей заголовок, который генерирует предупреждение.
Марко Попович
2
@MarkoPopovic: suppressспецификатор работает с одной предварительно обработанной строкой кода. Если следующая строка #pragma warning(suppress: ...)является #includeдирективой (которая расширяет файл, на который ссылается его параметр, в текущую единицу компиляции), эффект применяется только к первой строке этого файла. Это должно быть очевидно, поскольку предупреждения генерируются компилятором. Компилятор работает с предварительно обработанным кодом.
IInspectable
@IInspectable В этом случае я бы назвал это после обработки строки кода. предварительно обработанный означает, что он еще не был переведен препроцессором.
void.pointer
2
@voi: Окончание "-ed" означает причастие прошедшего времени . Он используется для обозначения того, что что-то закончилось в прошлом. «Предварительно обработанные» линия представляет собой линию , которая была полностью обработана.
IInspectable
29

#pragma push / pop часто являются решением такого рода проблем, но в этом случае почему бы вам просто не удалить переменную, на которую нет ссылки?

try
{
    // ...
}
catch(const your_exception_type &) // type specified but no variable declared
{
    // ...
}
Маттео Италия
источник
6
Это не ответ на вопрос. Конечно, это может решить проблему OP, но не поможет будущим читателям ответить на типичный вопрос: «как мне отключить конкретное предупреждение для определенной части моего кода?»
Sjoerd
1
@Sjoerd: три человека уже ответили на «официальный вопрос», который могут искать другие люди, поэтому вместо этого я попытался прочитать между строк и решить его настоящую проблему (появившись через минуту после вашего комментария :P).
Matteo Italia
11
@Sjoerd, как будущий читатель, я подтверждаю, что этот ответ действительно помог мне.
Mołot 07
2
@ Mołot: как писатель в прошлом, я рад, что это помогло. =)
Matteo Italia
9

Используйте #pragma warning ( push ), затем #pragma warning ( disable ), затем поместить свой код, а затем использовать , #pragma warning ( pop )как описано здесь :

#pragma warning( push )
#pragma warning( disable : WarningCode)
// code with warning
#pragma warning( pop ) 
Sharptooth
источник
8

Пример:

#pragma warning(suppress:0000)  // (suppress one error in the next line)

Эта прагма действительна для C ++, начиная с Visual Studio 2005.
https://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

Прагма НЕ действительна для C # через Visual Studio 2005 через Visual Studio 2015.
Ошибка: «Ожидается отключение или восстановление».
(Я думаю, они так и не добрались до реализации suppress...)
https://msdn.microsoft.com/en-us/library/441722ys(v=vs.140).aspx

C # нужен другой формат. Это выглядело бы так (но не работает):

#pragma warning suppress 0642  // (suppress one error in the next line)

Вместо этого suppressвам нужно disableи enable:

if (condition)
#pragma warning disable 0642
    ;  // Empty statement HERE provokes Warning: "Possible mistaken empty statement" (CS0642)
#pragma warning restore 0642
else

Это ТАК некрасиво, я думаю, что разумнее просто изменить его стиль:

if (condition)
{
    // Do nothing (because blah blah blah).
}
else
A876
источник
5

Вместо того, чтобы помещать его поверх файла (или даже файла заголовка), просто оберните код, о котором идет речь #pragma warning (push), #pragma warning (disable)и сопоставление #pragma warning (pop), как показано здесь .

Хотя есть и другие варианты, в том числе #pramga warning (once).

Christian.K
источник
5

Также можно использовать UNREFERENCED_PARAMETERопределенные в WinNT.H. Определение просто:

#define UNREFERENCED_PARAMETER(P)          (P)

И используйте это так:

void OnMessage(WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(wParam);
    UNREFERENCED_PARAMETER(lParam);
}

Вы можете возразить, что вы можете просто опустить само имя переменной. Ну, есть случаи (другая конфигурация проекта, сборки Debug / Release), когда переменная действительно может использоваться. В другой конфигурации эта переменная не используется (отсюда и предупреждение).

Некоторый статический анализ кода может по-прежнему выдавать предупреждение для этого бессмысленного утверждения ( wParam;). В этом случае вы можете использовать то DBG_UNREFERENCED_PARAMETERже самое, что и UNREFERENCED_PARAMETERв отладочных сборках, и P=Pв сборке выпуска.

#define DBG_UNREFERENCED_PARAMETER(P)      (P) = (P)
Аджай
источник
1
обратите внимание, что, начиная с C ++ 11, у нас есть [[maybe_unused]]атрибут
Metablaster
2

Если вы хотите отключить unreferenced local variableзапись в каком-то заголовке

template<class T>
void ignore (const T & ) {}

и использовать

catch(const Except & excpt) {
    ignore(excpt); // No warning
    // ...  
} 
Алексей Малистов
источник
2
Вызов функции для подавления предупреждения? Почему бы вам не сделать это вместо: (void)unusedVar;?
Nawaz
@Nawaz: я думаю, что (void)unusedVar;?он не соответствует стандарту C ++.
Алексей Малистов
2
Это выражение, значение которого - ничто. В C ++ вы даже можете это сделать static_cast<void>(unusedVar).
Nawaz
2
@ Наваз. Объяснение Херба Саттера: grassutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings
Алексей Малистов
2
В §5.2.9 / 4 говорится, Any expression can be explicitly converted to type “cv void.” The expression value is discardedчто можно писать static_cast<void>(unusedVar)и static_cast<const void>(unusedVar)и static_cast<volatile void>(unusedVar). Все формы действительны. Надеюсь, это проясняет ваши сомнения.
Nawaz
2

В определенных ситуациях у вас должен быть именованный параметр, но вы не используете его напрямую.
Например, я столкнулся с этим на VS2010, когда 'e' используется только внутри decltypeоператора, компилятор жалуется, но у вас должна быть указанная переменная e.

Все вышеперечисленные невнесения #pragmaсводятся к простому добавлению одного оператора:

bool f(int e)
{ 
   // code not using e
   return true;
   e; // use without doing anything
}
Ади Шавит
источник
1
теперь (в компиляторе MS VS2015) это вызывает недостижимый код
C4702
2

как упоминал @rampion, если вы находитесь в clang gcc, предупреждения указываются по имени, а не по номеру, и вам нужно будет сделать:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
// ..your code..
#pragma clang diagnostic pop

эта информация взята отсюда

Орион Элензил
источник