2015-07-20 28 views
19

Abbiamo recentemente abilitato -Wall per un progetto. È abilitato quando GCC è a 4.7 o superiore (o Clang) perché possiamo usare GCC diagnostic per gestire l'output dagli avvisi elevati. Vogliamo gestirli dal codice sorgente e non tramite argomenti della riga di comando. (Non vogliamo inquinare la linea di comando, o chiedere agli utenti della biblioteca di riscoprire ciò che è necessario).GCC non onora 'pragma GCC diagnostic' per tacitare gli avvisi

Sotto GCC 4.8 e 5.1, stiamo recuperando gli avvertimenti che sono stati disattivati ​​in un blocco di diagnostica GCC per -Wunused-variable, -Wunused-value, -Wunused-function e -Wunknown-pragmas. Entrambi GCCS accettano -fopenmp, ed entrambi definiscono _OPENMP in risposta ad esso, quindi sono abbastanza certo che non dovremmo mai vedere un -Wunknown-pragmas in risposta ad #prgam omp ...è disabilitato, ma non è sconosciuto).

g++ -DNDEBUG -g2 -O3 -Wall -march=native -pipe -c nbtheory.cpp 
nbtheory.cpp:655:0: warning: ignoring #pragma omp parallel [-Wunknown-pragmas] 
    #pragma omp parallel 
^ 
nbtheory.cpp:656:0: warning: ignoring #pragma omp sections [-Wunknown-pragmas] 
    #pragma omp sections 
^ 
... 

In questo caso particolare, il file nbtheroy.cpp ha il seguente guardia in atto per aiutare a gestire questo avvertimento (solo le parti interessate sono mostrati, ma si può vedere tutto da the GitHub link):

// Defines GCC_DIAGNOSTIC_AWARE if GCC 4.7 or above. 
#include <misc.h> 
... 

#if GCC_DIAGNOSTIC_AWARE 
# pragma GCC diagnostic ignored "-Wunknown-pragmas" 
#endif 

... 
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, 
        const Integer &p, const Integer &q, const Integer &u) 
{ 
    Integer p2, q2; 
    #pragma omp parallel 
     #pragma omp sections 
     { 
      #pragma omp section 
       p2 = ModularExponentiation((a % p), dp, p); 
      #pragma omp section 
       q2 = ModularExponentiation((a % q), dq, q); 
     } 
    return CRT(p2, p, q2, q, u); 
} 
... 

Perché il file è *.cpp (la sua efficacia l'unità di traduzione), abbiamo non ad effettuare un #pragma GCC diagnostic push all'inizio e #pragma GCC diagnostic pop alla fine. (Lo facciamo per i file di intestazione che sono inclusi, tuttavia). (Abbiamo anche provato a farlo, ma non è stato d'aiuto).

Ed ecco GCC_DIAGNOSTIC_AWARE (da misc.h):

// Used to suppress some warnings in some header and implementation files. 
// Some platforms, like CentOS and OpenBSD, use old compilers that don't understand -Wno-unknown-pragma. 
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)) 

So che la guardia sta lavorando perché l'aggiunta di un #error nel blocco causa un errore. Inoltre, commentando la guardia e chiamando #pragma GCC diagnostic ignored "-Wunknown-pragmas" non aiuta. Finalmente funziona bene sotto Clang.

Lo sto riscontrando anche per altri avvisi, come -Wunused-variable, -Wunused-value e -Wunused-function. I in realtà non si vuole inquinare la riga di comando come suggerito dal potenziale duplicato.

In che modo è possibile far funzionare il meccanismo GCC pragma diagnostic per disattivare gli avvisi in GCC quando si utilizza -Wall?


correlati, se si desidera riprodurlo (il suo GNUmakefile based, e non richiede configurazioni o autotools):

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn 
cd cryptopp-warn 
make 

EDIT: abbiamo controllato in una patch che disabilita -Wall eccezione per Clang. Se si desidera riprodurre il vecchio comportamento, quindi:

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn 
cd cryptopp-warn 
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall" 
make 
+1

Suggerisco di rimuovere prima il comando # # if/# endif' (lasciando solo il '#pragma GCC ...') per vedere se c'è un problema con 'GCC_DIAGNOSTIC_AWARE'. – paxdiablo

+0

possibile duplicato di [Sopprimere -avvertimenti praga-Wnownnown in GCC] (http://stackoverflow.com/questions/12842306/suppress-wunknown-pragmas-warning-in-gcc) – nneonneo

+0

@paxdiablo - Nessuna gioia. Ho disabilitato la guardia e ho chiamato '#pragma GCC diagnostic ignored" -Wunknown-pragmas "' direttamente. – jww

risposta

9

Questo sembra essere un bug in gcc almeno.Il seguente codice:

#pragma GCC diagnostic ignored "-Wunknown-pragmas" 
#pragma GCC diagnostic ignored "-Wuninitialized" 

int fn(void) { 
    #pragma xyzzy 
    int x; 
    return x; 
} 

int main (void) { 
    return fn(); 
} 

non ha problemi ignorando il valore Non inizializzato x ma ancora si lamenta il pragma (senza il uninitialized pragma, si genera un avvertimento per x come ci si aspetterebbe).

Se si modificano le opzioni della riga di comando per essere -Wall -Wno-unknown-pragmas, quindi lo ignora perfettamente. Va bene per il tuo caso specifico, dal momento che vuoi applicarlo all'intera unità di traduzione, ma non consentirà il controllo a grana fine che otterresti dal metodo #pragma (se funzionasse).


sono andato a sollevare un bug report su GCC, ma ha scoperto che già esiste (#53431).

Mentre quello specifico bug ha a che fare con -Wundef, un frammento in uno dei commenti indica che probabilmente si applica a tutte le varianti che interessano il preprocessore (leggermente modificato per enfasi):

I ++ Lexes parser C (e preprocessi) prima di gestire il pragma, mentre il parser C elabora i pragma come li vede.

Dobbiamo in qualche modo analizzare questa direttiva anche in cp/parser.c:631. Forse si può fare qualcosa di simile a quello che facciamo per cp_parser_initial_pragma, ma all'interno del ciclo e gestire solo la diagnostica pragma. Sicuramente, avrà bisogno di prove ed errori per farlo bene. Se qualcuno di voi vuole fare un tentativo e ha bisogno di aiuto, basta chiedere qui o nella mailing list.

che spiega il motivo per cui non vediamo lo stesso problema con -Wuninitialized, perché è rilevato durante le fasi successive del processo di compilazione, dopo che i pragma sono stati attivati ​​al termine di pre-elaborazione.

Quindi, se si desidera vederlo corretto in un modo più tempestivo (è stato sollevato più di tre anni fa), suggerirei (come ho) di infastidire il sito di bugzilla GCC per cercare di ottenere un po 'di visibilità.

+0

Sì, il problema più grande è che questo è il codice della libreria. Quindi dobbiamo sistemarlo per lavorare sulla libreria stessa. È un oggetto di convenienza per noi. Ma gli utenti si aspettano che "funzioni" solo quando includono la libreria. Se includono la libreria e quindi devono passare attraverso i cerchi a riga di comando perché le cose non funzionano, allora questo è un problema. – jww

+0

@jww, se stai rilasciando una libreria ('.o/.a/.so/etc'), allora l'avvertimento non avverrà sicuramente. O la tua libreria è in realtà composta da fonti compilabili? – paxdiablo

+0

Sì, i sorgenti vengono rilasciati.Inoltre, alcune intestazioni producono avvertimenti e tentiamo di zittirle con lo stesso metodo. – jww