So che la domanda riguarda GCC, ma per le persone che cercano come farlo in altri compilatori e / o multipli ...
TL; DR
Potresti dare un'occhiata a Hedley , che è una singola intestazione C / C ++ di dominio pubblico che ho scritto che fa un sacco di queste cose per te. Metterò una breve sezione su come usare Hedley per tutto questo alla fine di questo post.
Disabilitare l'avviso
#pragma warning (disable: …)
ha equivalenti nella maggior parte dei compilatori:
- MSVC:
#pragma warning(disable:4996)
- GCC:
#pragma GCC diagnostic ignored "-W…"
dove i puntini di sospensione sono il nome dell'avvertimento; es , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
.
- clang:
#pragma clang diagnostic ignored "-W…"
. La sintassi è sostanzialmente la stessa di GCC e molti dei nomi degli avvisi sono gli stessi (anche se molti non lo sono).
- Compilatore Intel C: utilizzare la sintassi MSVC, ma tenere presente che i numeri di avviso sono totalmente diversi. Esempio:
#pragma warning(disable:1478 1786)
.
- IGP: esiste un
diag_suppress
pragma:#pragma diag_suppress 1215,1444
- TI: Esiste un
diag_suppress
pragma con la stessa sintassi (ma numeri di avvertimento diversi!) Di IGP:pragma diag_suppress 1291,1718
- Oracle Developer Studio (suncc): esiste un
error_messages
pragma. Stranamente, gli avvisi sono diversi per i compilatori C e C ++. Entrambi disabilitano sostanzialmente gli stessi avvertimenti:
- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
- C ++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- IAR: usa anche
diag_suppress
come IGP e TI, ma la sintassi è diversa. Alcuni dei numeri di avviso sono gli stessi, ma altri ho diverguto:#pragma diag_suppress=Pe1444,Pe1215
- Pelles C: simile a MSVC, anche se i numeri sono ancora diversi
#pragma warn(disable:2241)
Per la maggior parte dei compilatori è spesso una buona idea controllare la versione del compilatore prima di provare a disabilitarla, altrimenti finirai per attivare un altro avviso. Ad esempio, GCC 7 ha aggiunto il supporto per l' -Wimplicit-fallthrough
avvertimento, quindi se ti interessa GCC prima di 7 dovresti fare qualcosa di simile
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Per clang e compilatori basati su clang come le versioni più recenti di XL C / C ++ e armclang, puoi verificare se il compilatore è a conoscenza di un particolare avviso utilizzando la __has_warning()
macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Ovviamente devi anche verificare se __has_warning()
esiste la macro:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
Potresti essere tentato di fare qualcosa del genere
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Quindi puoi usarlo __has_warning
un po 'più facilmente. Clang suggerisce persino qualcosa di simile per la __has_builtin()
macro nel loro manuale. Non farlo . Un altro codice può verificare __has_warning
e ricorrere al controllo delle versioni del compilatore se non esiste e, se lo definisci, __has_warning
ne spezzerai il codice. Il modo giusto per farlo è creare una macro nel tuo spazio dei nomi. Per esempio:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Quindi puoi fare cose come
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Spingendo e scoppiando
Molti compilatori supportano anche un modo per inviare e far apparire gli avvisi in una pila. Ad esempio, questo disabiliterà un avviso su GCC per una riga di codice, quindi lo restituirà al suo stato precedente:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Ovviamente non c'è molto accordo tra i compilatori sulla sintassi:
- GCC 4.6+:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
- clang:
#pragma clang diagnostic push
/#pragma diagnostic pop
- Intel 13+ (e probabilmente prima):
#pragma warning(push)
/#pragma warning(pop)
- MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)
/#pragma warning(pop)
- ARM 5.6+:
#pragma push
/#pragma pop
- TI 8.1+:
#pragma diag_push
/#pragma diag_pop
- Pelles C 2.90+ (e probabilmente prima):
#pragma warning(push)
/#pragma warning(pop)
Se la memoria serve, per alcune versioni molto vecchie di GCC (come 3.x, IIRC) i pragmi push / pop dovevano essere al di fuori della funzione.
Nascondere i dettagli cruenti
Per la maggior parte dei compilatori è possibile nascondere la logica alla base delle macro _Pragma
, introdotta in C99. Anche in modalità non C99, la maggior parte dei compilatori supporta _Pragma
; la grande eccezione è MSVC, che ha una propria __pragma
parola chiave con una sintassi diversa. Lo standard _Pragma
accetta una stringa, la versione di Microsoft no:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
È approssimativamente equivalente, una volta preelaborato, a
#pragma foo
Questo ci consente di creare macro in modo da poter scrivere codice come
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
E nascondi tutti i brutti controlli di versione nelle definizioni macro.
Il modo semplice: Hedley
Ora che hai capito la meccanica di come fare cose come questa in modo portabile mantenendo pulito il tuo codice, capisci cosa fa uno dei miei progetti, Hedley . Invece di scavare tra tonnellate di documentazione e / o installare quante più versioni di quanti compilatori puoi testare, puoi semplicemente includere Hedley (è una singola intestazione C / C ++ di dominio pubblico) e farla finita. Per esempio:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Disabiliterò l'avviso di chiamare una funzione deprecata su GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles e forse altri (probabilmente non mi preoccuperò di aggiornare questa risposta mentre aggiorno Hedley). E, sui compilatori che non sono noti per funzionare, le macro verranno preelaborate a zero, quindi il tuo codice continuerà a funzionare con qualsiasi compilatore. Naturalmente HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
non è l'unico avvertimento di cui Hedley è a conoscenza, né disabilita gli avvisi che tutto ciò che Hedley può fare, ma spero che tu abbia l'idea.