W Visual C ++ można używać #pragma warning (disable: ...)
. Odkryłem również, że w GCC można przesłonić flagi kompilatora plików . Jak mogę to zrobić dla „następnej linii” lub z semantyką push / pop wokół obszarów kodu za pomocą GCC?
c
gcc
compiler-warnings
pragma
Matt Joiner
źródło
źródło
Odpowiedzi:
Wygląda na to, że można to zrobić . Nie jestem w stanie określić wersji GCC, która została dodana, ale było to przed czerwcem 2010 roku.
Oto przykład:
źródło
push
i dwapop
s - może być innypush
na początku brakuje?Aby skompresować wszystko, jest to przykład tymczasowego wyłączenia ostrzeżenia:
Więcej informacji można znaleźć w dokumentacji GCC na temat pragmatyki diagnostycznej .
źródło
gcc-4.9
po prostu całkowicie ignoruje tę linię.TL; DR : Jeśli to działa, unikaj lub używaj takich specyfikatorów
__attribute__
, inaczej_Pragma
.To jest krótka wersja mojego artykułu na blogu Tłumienie ostrzeżeń w GCC i Clang .
Rozważ następujące
Makefile
do budowania następującego
puts.c
kodu źródłowegoNie będzie się kompilował, ponieważ
argc
nie jest używany, a ustawienia są hardcore (-W -Wall -pedantic -Werror
).Istnieje 5 rzeczy, które możesz zrobić:
__attribute__
_Pragma
#pragma
Ulepszanie źródła
Pierwszą próbą powinno być sprawdzenie, czy można poprawić kod źródłowy, aby pozbyć się ostrzeżenia. W tym przypadku nie chcemy zmieniać algorytmu tylko z tego powodu, ponieważ
argc
jest on zbędny z!*argv
(NULL
po ostatnim elemencie).Korzystanie ze specyfikatora deklaracji, np
__attribute__
Jeśli masz szczęście, standard określa specyfikację twojej sytuacji, np
_Noreturn
.__attribute__
jest zastrzeżonym rozszerzeniem GCC (obsługiwanym przez Clanga i niektóre inne kompilatory, jakarmcc
również) i nie będzie zrozumiały dla wielu innych kompilatorów. Wstaw__attribute__((unused))
makro, jeśli chcesz przenosić kod._Pragma
operator_Pragma
może być stosowany jako alternatywa dla#pragma
.Główną zaletą
_Pragma
operatora jest to, że można go umieścić w makrach, co nie jest możliwe w przypadku#pragma
dyrektywy.Wada: to prawie taktyczny nuke, ponieważ działa w oparciu o linię zamiast w oparciu o deklarację.
_Pragma
Operatora wprowadzono C99.#pragma
dyrektywa.Możemy zmienić kod źródłowy, aby ukryć ostrzeżenie dla regionu kodu, zwykle całej funkcji:
Wada: to prawie taktyczny nuke, ponieważ działa w oparciu o linię zamiast w oparciu o deklarację.
Zauważ, że podobna składnia występuje w clang .
Pomijanie ostrzeżenia w wierszu poleceń dla pojedynczego pliku
Możemy dodać następujący wiersz do,
Makefile
aby pominąć ostrzeżenie specjalnie dla putów:Prawdopodobnie nie jest to pożądane w konkretnym przypadku, ale może pomóc innym czytającym, którzy znajdują się w podobnych sytuacjach.
źródło
improving the source
działałoby również zmienić deklarację main naint main(int, const char* argv[]) { ... }
nie nadając argumentowi nazwy, informujesz kompilator, że będzie nieużywany.gcc
jak równieżclang
.#define UNUSED(x) ((void)x)
używane do wyciszania ostrzeżeń. Myślę, że to było w ReactOS?_Pragma("GCC diagnostic pop") \
tak powinno być_Pragma("GCC diagnostic pop")
.To powinno załatwić sprawę dla gcc, clang i msvc
Można wywołać np .:
patrz https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html , http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas i https://msdn.microsoft .pl / de-DE / library / d9x1s805.aspx aby uzyskać więcej informacji
Potrzebujesz co najmniej wersji 4.02, aby korzystać z tego rodzaju pragmów dla gcc, nie jesteś pewien msvc i brzękaj o wersjach.
Wygląda na to, że obsługa push pop dla gcc jest trochę zepsuta. Jeśli ponownie włączysz ostrzeżenie, nadal otrzymujesz ostrzeżenie dla bloku, który był w bloku DISABLE_WARNING / ENABLE_WARNING. W niektórych wersjach gcc działa, w niektórych nie.
źródło
Zamień „-Wformat” na nazwę flagi ostrzegawczej.
AFAIK nie ma możliwości użycia semantyki push / pop dla tej opcji.
źródło
Miałem ten sam problem z bibliotekami zewnętrznymi, takimi jak nagłówki ROS. Lubię używać następujących opcji w pliku CMakeLists.txt do ściślejszej kompilacji:
Powoduje to jednak wszelkiego rodzaju błędy pedantyczne również w bibliotekach zewnętrznych. Rozwiązaniem jest wyłączenie wszystkich ostrzeżeń pedantycznych przed dołączeniem bibliotek zewnętrznych i ponownym włączeniem w następujący sposób:
źródło
Wiem, że pytanie dotyczy GCC, ale dla osób szukających tego, jak to zrobić w innych i / lub wielu kompilatorach…
TL; DR
Możesz rzucić okiem na Hedley , który jest napisanym przeze mnie publicznym nagłówkiem C / C ++, który robi dużo dla ciebie z tych rzeczy. Na końcu tego postu zamieszczę krótką sekcję o tym, jak używać Hedley do tego wszystkiego.
Wyłączam ostrzeżenie
#pragma warning (disable: …)
ma odpowiedniki w większości kompilatorów:#pragma warning(disable:4996)
#pragma GCC diagnostic ignored "-W…"
gdzie elipsa jest nazwą ostrzeżenia; np ,#pragma GCC diagnostic ignored "-Wdeprecated-declarations
.#pragma clang diagnostic ignored "-W…"
. Składnia jest w zasadzie taka sama jak w GCC, a wiele nazw ostrzeżeń jest takich samych (choć wiele nie jest).#pragma warning(disable:1478 1786)
.diag_suppress
pragma:#pragma diag_suppress 1215,1444
diag_suppress
pragma o tej samej składni (ale różnych liczbach ostrzegawczych!) Jak PGI:pragma diag_suppress 1291,1718
error_messages
pragma. Irytujące ostrzeżenia są różne dla kompilatorów C i C ++. Oba wyłączają w zasadzie te same ostrzeżenia:#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
#pragma error_messages(off,symdeprecated,symdeprecated2)
diag_suppress
takich jak PGI i TI, ale składnia jest inna. Niektóre numery ostrzegawcze są takie same, ale ja inne się rozeszły:#pragma diag_suppress=Pe1444,Pe1215
#pragma warn(disable:2241)
W przypadku większości kompilatorów często dobrym pomysłem jest sprawdzenie wersji kompilatora przed próbą jej wyłączenia, w przeciwnym razie pojawi się kolejne ostrzeżenie. Na przykład GCC 7 dodał obsługę
-Wimplicit-fallthrough
ostrzeżenia, więc jeśli zależy ci na GCC przed 7, powinieneś zrobić coś takiegoW przypadku clang i kompilatorów opartych na clang, takich jak nowsze wersje XL C / C ++ i armclang, możesz sprawdzić, czy kompilator wie o danym ostrzeżeniu za pomocą
__has_warning()
makra.Oczywiście musisz również sprawdzić, czy
__has_warning()
makro istnieje:Możesz mieć ochotę zrobić coś takiego
Możesz więc użyć
__has_warning
nieco łatwiej. Clang sugeruje nawet coś podobnego dla__has_builtin()
makra w swoim podręczniku. Nie rób tego . Inny kod może__has_warning
sprawdzać wersje kompilatora i polegać na nim, jeśli nie istnieje, a jeśli go zdefiniujesz__has_warning
, złamiesz jego kod. Właściwym sposobem na to jest utworzenie makra w przestrzeni nazw. Na przykład:Następnie możesz robić takie rzeczy jak
Pchanie i strzelanie
Wiele kompilatorów obsługuje również sposób wypychania i wyrzucania ostrzeżeń na stos. Na przykład spowoduje to wyłączenie ostrzeżenia w GCC dla jednego wiersza kodu, a następnie przywrócenie go do poprzedniego stanu:
Oczywiście nie ma dużej zgody między kompilatorami na temat składni:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
#pragma clang diagnostic push
/#pragma diagnostic pop
#pragma warning(push)
/#pragma warning(pop)
#pragma warning(push)
/#pragma warning(pop)
#pragma push
/#pragma pop
#pragma diag_push
/#pragma diag_pop
#pragma warning(push)
/#pragma warning(pop)
Jeśli pamięć służy, w niektórych bardzo starych wersjach GCC (takich jak 3.x, IIRC) pragma push / pop musiała znajdować się poza funkcją.
Ukrywanie krwawych szczegółów
W przypadku większości kompilatorów możliwe jest ukrycie logiki za pomocą makr
_Pragma
, która została wprowadzona w C99. Nawet w trybie innym niż C99 większość kompilatorów obsługuje_Pragma
; dużym wyjątkiem jest MSVC, który ma własne__pragma
słowo kluczowe o innej składni. Standard_Pragma
przyjmuje ciąg, wersja Microsoft nie:Jest mniej więcej równoważny, po uprzednim przetworzeniu, z
To pozwala nam tworzyć makra, dzięki czemu możemy pisać jak kod
I ukryj wszystkie brzydkie kontrole wersji w definicjach makr.
Prosty sposób: Hedley
Teraz, gdy rozumiesz mechanikę robienia takich rzeczy przenośnie, utrzymując kod w czystości, rozumiesz, co robi jeden z moich projektów, Hedley . Zamiast przeglądać mnóstwo dokumentacji i / lub instalować tyle wersji kompilatorów, ile można testować, wystarczy dołączyć Hedley (jest to pojedynczy nagłówek C / C ++ domeny publicznej) i gotowe. Na przykład:
Wyłączy ostrzeżenie o wywołaniu przestarzałej funkcji w GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles i ewentualnie innych (prawdopodobnie nie będę zawracał sobie głowy aktualizowaniem tej odpowiedzi podczas aktualizacji Hedley). A na kompilatorach, o których nie wiadomo, że działają, makra zostaną wstępnie przetworzone do niczego, więc kod będzie kontynuował pracę z dowolnym kompilatorem. Oczywiście
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
nie jest to jedyne ostrzeżenie, o którym wie Hedley, ani też nie wyłącza ostrzeżeń, które może zrobić tylko Hedley, ale mam nadzieję, że wpadłeś na ten pomysł.źródło
Zamiast wyciszać ostrzeżenia, styl gcc zwykle polega na użyciu standardowych konstrukcji C lub
__attribute__
rozszerzenia, aby poinformować kompilator o swoich zamiarach. Na przykład ostrzeżenie o przypisaniu zastosowanym jako warunek jest tłumione poprzez umieszczenie przypisania w nawiasach, tzn.if ((p=malloc(cnt)))
Zamiastif (p=malloc(cnt))
. Ostrzeżenia o nieużywanych argumentach funkcji mogą być tłumione przez jakieś dziwne__attribute__
, których nigdy nie pamiętam, lub przez samodzielne przypisanie itp. Ale ogólnie wolę po prostu globalnie wyłączyć dowolną opcję ostrzegania, która generuje ostrzeżenia o rzeczach, które wystąpią we właściwym kodzie.źródło
if ((p=malloc(cnt)) != NULL) ...
że to właśnie robi kompilator za kulisami.Dla tych, którzy znaleźli tę stronę i szukają sposobu na zrobienie tego w IAR, spróbuj tego:
Zobacz http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html w celach informacyjnych.
źródło