Wyłącz pojedynczy błąd ostrzegawczy

115

Czy istnieje sposób na wyłączenie tylko jednego wiersza ostrzeżenia w pliku CPP w programie Visual Studio?

Na przykład, jeśli złapię wyjątek i go nie obsłużę, otrzymam błąd 4101 (zmienna lokalna bez odniesienia). Czy istnieje sposób, aby zignorować to tylko w tej funkcji, ale w przeciwnym razie zgłosić to w jednostce kompilacji? W tej chwili umieszczam #pragma warning (disable : 4101)na górze pliku, ale to oczywiście wyłącza go dla całego urządzenia.

Ciastko
źródło
19
jeśli podasz tylko typ i nie nazwiesz wyjątku, nie będzie ostrzeżenia. Np catch (const std::exception& /* unnamed */) {.... }. Nie odpowiada na Twoje pytanie, ale może rozwiązać Twój problem.
Sjoerd

Odpowiedzi:

182
#pragma warning( push )
#pragma warning( disable : 4101)
// Your function
#pragma warning( pop ) 
Andreas Brinck
źródło
1
@Cookie: tak, działa dla każdego fragmentu kodu, który przechodzi przez kompilator.
Matteo Italia
Aby uzyskać nowszą, zwięzłą odpowiedź, zobacz odpowiedź Daniela Seithera poniżej.
Dan Nissenbaum
4
clangnie wydaje się wspierać ten pragmy, ale można osiągnąć ten sam efekt z #pragma clang diagnostic push, #pragma clang diagnostic ignored "-Wunused-variable", i #pragma clang diagnostic pop. Zobacz „Kontrolowanie diagnostyki poprzez pragmy” w podręczniku użytkownika Clang
rampion
Ponieważ rzadko używam tej funkcji, kiedy to robię, zwykle kończę na tej stronie, aby przypomnieć sobie składnię. Po prostu umieściłem to wokół wywołania przestarzałej funkcji, która może nigdy nie zostać zaktualizowana, aby ostrzeżenie nie denerwowało mnie na listach kompilatora, które skanuję religijnie.
David A. Gray
W przypadku programu Visual Studio argument wiersza polecenia to /wd4101. Zauważ, że :między flagą a liczbą nie ma normy i nie możesz utworzyć listy liczb oddzielonych przecinkami. W przypadku innych kompilatorów może to być /nowarn:4101zamiast tego.
Jesse Chisholm
89

Jeśli chcesz pominąć ostrzeżenie tylko w jednym wierszu kodu, możesz użyć specyfikatora suppress ostrzeżenia :

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

W przypadku pojedynczego wiersza kodu działa to tak samo, jak napisanie następującego:

#pragma warning(push)
#pragma warning(disable: 4101)
// here goes your code where the warning occurs
#pragma warning(pop)
Daniel Seither
źródło
8
Bardzo przydatne! Niestety, nie działa to dla pojedynczej linii zawierającej nagłówek, który generuje ostrzeżenie.
Marko Popovic
2
@MarkoPopovic: suppressspecyfikator działa na pojedynczej, wstępnie przetworzonej linii kodu. Jeśli następująca po niej linia #pragma warning(suppress: ...)jest #includedyrektywą (która rozszerza plik, do którego odwołuje się jej parametr, do aktualnej jednostki kompilacji), efekt dotyczy tylko pierwszej linii tego pliku. Powinno to być oczywiste, ponieważ ostrzeżenia są generowane przez kompilator. Kompilator działa na wstępnie przetworzonym kodzie.
Niespodziewane
@IInspectable W takim przypadku nazwałbym to post-przetworzoną linią kodu. wstępnie przetworzone oznacza, że ​​nie zostało jeszcze przetłumaczone przez preprocesor.
void.pointer
2
@voi: Zakończenie „-ed” oznacza imiesłów czasu przeszłego . Służy do wyrażenia, że ​​coś się skończyło w przeszłości. Linia „wstępnie przetworzona” to linia, która została w pełni przetworzona.
Niespodziewane
29

#pragma push / pop są często rozwiązaniem tego rodzaju problemów, ale w takim przypadku dlaczego po prostu nie usuniesz zmiennej, do której nie ma odniesienia?

try
{
    // ...
}
catch(const your_exception_type &) // type specified but no variable declared
{
    // ...
}
Matteo Italia
źródło
6
To nie jest odpowiedź na pytanie. To prawda, może to rozwiązać problem OP, ale nie pomoże przyszłym czytelnikom w zadaniu prostego pytania: „jak wyłączyć określone ostrzeżenie dotyczące określonej części kodu?”
Sjoerd
1
@Sjoerd: trzy osoby odpowiedziały już na „oficjalne pytanie”, które mogą być przeszukiwane przez inne osoby, więc zamiast tego próbowałem czytać między wierszami i rozwiązać jego rzeczywisty problem (przybył minutę po Twoim komentarzu :P).
Matteo Italia
11
@Sjoerd jako przyszły czytelnik zaświadczam, że ta odpowiedź faktycznie mi pomogła.
Mołot 07.07.15
2
@ Mołot: jako były pisarz cieszę się, że pomogło. =)
Matteo Italia
9

Użyj #pragma warning ( push ), następnie #pragma warning ( disable )umieść kod, a następnie użyj #pragma warning ( pop )zgodnie z opisem tutaj :

#pragma warning( push )
#pragma warning( disable : WarningCode)
// code with warning
#pragma warning( pop ) 
ostry
źródło
8

Przykład:

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

Ta pragma dotyczy języka C ++, począwszy od programu Visual Studio 2005.
https://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

Pragma NIE jest poprawna dla języków C # za pośrednictwem programu Visual Studio 2005 do programu Visual Studio 2015.
Błąd: „Oczekiwano wyłączenia lub przywrócenia”.
(Myślę, że nigdy nie zaimplementowali suppress...)
https://msdn.microsoft.com/en-us/library/441722ys(v=vs.140).aspx

C # wymaga innego formatu. Wyglądałoby to tak (ale nie działało):

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

Zamiast tego suppressmusisz disablei enable:

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

To jest TAK brzydkie, myślę, że mądrzej jest po prostu zmienić styl:

if (condition)
{
    // Do nothing (because blah blah blah).
}
else
A876
źródło
5

Zamiast umieszczać go na górze pliku (lub nawet pliku nagłówkowego), po prostu zawiń kod, o który chodzi #pragma warning (push), #pragma warning (disable)i dopasuj #pragma warning (pop), jak pokazano tutaj .

Chociaż istnieje kilka innych opcji, w tym #pramga warning (once).

Christian.K
źródło
5

Można również użyć UNREFERENCED_PARAMETERzdefiniowanego w WinNT.H. Definicja jest po prostu:

#define UNREFERENCED_PARAMETER(P)          (P)

I używaj go jak:

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

Dlaczego miałbyś go używać, możesz argumentować, że możesz po prostu pominąć samą nazwę zmiennej. Cóż, są przypadki (inna konfiguracja projektu, kompilacje debugowania / wydania), w których zmienna może być faktycznie używana. W innej konfiguracji zmienna ta nie jest używana (stąd ostrzeżenie).

Niektóre statyczne analizy kodu mogą nadal dawać ostrzeżenie o tej nieuzasadnionej instrukcji ( wParam;). W takim przypadku możesz użyć DBG_UNREFERENCED_PARAMETERtego samego, co UNREFERENCED_PARAMETERw kompilacjach do debugowania i robi to P=Pw kompilacji wydania.

#define DBG_UNREFERENCED_PARAMETER(P)      (P) = (P)
Ajay
źródło
1
zauważ, że od C ++ 11 mamy [[maybe_unused]]atrybut
metablaster
2

Jeśli chcesz wyłączyć unreferenced local variablezapis w jakimś nagłówku

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

I użyć

catch(const Except & excpt) {
    ignore(excpt); // No warning
    // ...  
} 
Alexey Malistov
źródło
2
Wywołanie funkcji, tylko po to, aby usunąć ostrzeżenie? Dlaczego nie można tego zrobić w zamian: (void)unusedVar;?
Nawaz
@Nawaz: Myślę, że (void)unusedVar;?nie jest zgodny ze standardem C ++.
Alexey Malistov
2
To wyrażenie, którego wartość jest niczym. W C ++ możesz to zrobić static_cast<void>(unusedVar).
Nawaz
2
@Nawaz. Wyjaśnienie Herb Suttera: Herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings
Alexey Malistov
2
§5.2.9 / 4 mówi, Any expression can be explicitly converted to type “cv void.” The expression value is discardedzgodnie z którym możesz pisać static_cast<void>(unusedVar)i static_cast<const void>(unusedVar)i static_cast<volatile void>(unusedVar). Wszystkie formularze są ważne. Mam nadzieję, że to wyjaśnia twoje wątpliwości.
Nawaz
2

W niektórych sytuacjach musisz mieć nazwany parametr, ale nie używasz go bezpośrednio.
Na przykład, natknąłem się na to w VS2010, kiedy 'e' jest używane tylko w decltypeinstrukcji, kompilator skarży się, ale musisz mieć nazwaną zmienną e.

Wszystkie powyższe nie- #pragmasugestie sprowadzają się do dodania jednego stwierdzenia:

bool f(int e)
{ 
   // code not using e
   return true;
   e; // use without doing anything
}
Adi Shavit
źródło
1
teraz (w kompilatorze MS VS2015) powoduje to nieosiągalny kod
C4702
2

jak wspomniał @rampion, jeśli jesteś w clang gcc, ostrzeżenia są wyświetlane według nazwy, a nie numeru i musisz to zrobić:

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

ta informacja pochodzi stąd

orion elenzil
źródło