Wybiórczo wyłączyć ostrzeżenia GCC tylko dla części jednostki tłumaczeniowej?

85

Jaki jest najbliższy odpowiednik GCC do tego kodu preprocesora MSVC?

#pragma warning( push )                    // Save the current warning state.
#pragma warning( disable : 4723 )          // C4723: potential divide by 0
// Code which would generate warning 4723.
#pragma warning( pop )                     // Restore warnings to previous state.

Mamy kod w często dołączanych nagłówkach, których nie chcemy generować specjalnego ostrzeżenia. Chcemy jednak, aby pliki zawierające te nagłówki nadal generowały to ostrzeżenie (jeśli projekt ma włączone to ostrzeżenie).

Jon-Eric
źródło
Jeśli nagłówki są zainstalowane w / usr / include lub co masz, gcc domyślnie nie generuje dla nich ostrzeżeń.
Spudd86

Odpowiedzi:

95

Jest to możliwe w GCC od wersji 4.6 lub około czerwca 2010 w bagażniku.

Oto przykład:

#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wuninitialized"
    foo(a);         /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
    foo(b);         /* no diagnostic for this one */
#pragma GCC diagnostic pop
    foo(c);         /* error is given for this one */
#pragma GCC diagnostic pop
    foo(d);         /* depends on command line options */
Matt Joiner
źródło
8
Funkcjonalność push i pop została dodana w gcc 4.6 ( gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html ).
Dave Johansen
Prawdopodobnie będziesz chciał naciskać dwa razy, jeśli zamierzasz strzelić dwa razy.
Dan
2
@Dan: Przeczytaj instrukcję i skomentuj. Zwróć uwagę na pochodzenie przykładu.
Matt Joiner
Do Twojej wiadomości dla starszych wersji, takich jak 4.4.7 , możesz nadal używać, #pragma GCC diagnostic [error|warning|ignored]ale popnie jest zaimplementowany / obsługiwany.
Trevor Boyd Smith
36

Najbliższy rzeczą jest Pragma diagnostyczny GCC , #pragma GCC diagnostic [warning|error|ignored] "-Wwhatever". Nie jest bardzo zbliżony do tego, czego chcesz, i zobacz link, aby uzyskać szczegółowe informacje i zastrzeżenia.

chaos
źródło
1
Czy wiesz, jakie może być uzasadnienie niedodawania tej funkcji? (Nie mogłem go znaleźć.) Uważam, że przydatne jest ostrzeżenie push-disable-pop.
1
Naprawdę nie wyobrażam sobie, że „nie dodawanie funkcji” do gcc wydaje się mieć takie samo uzasadnienie, jak nieobecność kogokolwiek, kto przesłałby działającą łatkę.
chaos
14
Nie chodzi o to, że nikt nie jest skłonny wykonywać pracy dla tego rodzaju drobnoziarnistej kontroli ostrzegawczej w gcc ani przesyłać kodu - znam jedną dużą korporację z Doliny Krzemowej, która już to zrobiła, i inną, która byłaby zachwycona, gdyby komuś zapłacić aby to zrobić i umieścić kod w strumieniu. Raczej, podczas dyskusji z gościem, który (jako jeden z opiekunów gdb) jest podłączony do tych rzeczy, opiekunowie gcc mają filozofię: „Jeśli jest ostrzeżenie, jest to błąd i musisz to naprawić”. Więc (imo) jest to argument religijny, a oni kontrolują kod, aby wygrać.
Bob Murphy
Aby dodać do komentarza Boba, programiści GCC nie lubili tej #pragmadyrektywy, więc wszystko, co jest specyficzne dla GCC, prawdopodobnie zostanie zaimplementowane jako __attribute__((foo)).
Tom
10
nowy gcc (> = 4.4) ma, #pragma GCC push_optionswięc możesz grzebać w
czymś
33

Zrobiłem coś podobnego. W przypadku kodu innej firmy nie chciałem w ogóle widzieć żadnych ostrzeżeń. Więc zamiast określać -I/path/to/libfoo/include, użyłem -isystem /path/to/libfoo/include. To sprawia, że ​​kompilator traktuje te pliki nagłówkowe jako „nagłówki systemowe” na potrzeby ostrzeżeń i dopóki tego nie włączysz -Wsystem-headers, jesteś w większości bezpieczny. Wciąż widziałem wyciekające stamtąd kilka ostrzeżeń, ale ogranicza to większość śmieci.

Zauważ, że jest to pomocne tylko wtedy, gdy możesz wyodrębnić niewłaściwy kod za pomocą katalogu include. Jeśli jest to tylko podzbiór twojego własnego projektu lub zmieszany z innym kodem, nie masz szczęścia.

Tomek
źródło
1
Świetna wskazówka. Jeśli używasz LLVM, dodaj flagę -isystem w sekcji „Inne flagi C” w sekcji „Kompilator Apple LLVM - język”.
Nestor,
@Tom Dzięki za udostępnienie. Nie rozumiem, gdzie użyć twojego rozwiązania. Możesz powiedzieć trochę więcej?
Lorenzo B
1

To jest rozszerzenie odpowiedzi Matta Joinera .

Jeśli nie chcesz odradzać pragm w całym kodzie, możesz użyć operatora _Pragma :

#ifdef __GNUC__
#  define DIAGNOSTIC_ERROR(w) _Pragma("GCC diagnostic error \"" w "\"")
#  define DIAGNOSTIC_IGNORE(w) _Pragma("GCC diagnostic ignore \"" w "\"")
#  define DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
#  define DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
#endif
// (...)

DIAGNOSTIC_ERROR("-Wuninitialized")
foo(a); // Error

DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE("-Wuninitialized")
foo(a); // No error

DIAGNOSTIC_POP
foo(a); // Error
Cássio Renan
źródło