2015-08-20 9 views
5

Attualmente sto lavorando su un progetto abbastanza grande. Al fine di aumentare la qualità del nostro codice, abbiamo deciso di applicare il trattamento dei valori di ritorno (codici di errore) per ogni funzione. GCC supporta un avviso riguardante il valore di ritorno di una funzione, tuttavia la definizione della funzione deve essere preceduta dal seguente flag.Ricerca e modifica delle definizioni di funzione (C++) tramite bash-script

static __attribute__((warn_unused_result)) ErrorCode test() { /* code goes here */ } 

Voglio realizzare un bashscript che analizza l'intero codice sorgente e emette un avviso nel caso in cui il

__attribute__((warn_unused_result)) 

manca. Si noti che tutte le funzioni che richiedono questo tipo di modifica restituiscono un tipo chiamato ErrorCode. Pensi che questo sia possibile tramite uno script bash?

+0

vi consiglio di prendere in considerazione la scrittura di questo come un plugin clang. Ho scritto un plugin che analizza l'uso dei simboli e mette in guardia su inutili include in circa 350 righe di codice, quindi non è particolarmente difficile. –

risposta

3

Un modo semplice che potrei immaginare è tramite ctags. Si crea un file di tag su tutto il codice sorgente e quindi si analizza il file di tag. Tuttavia, non sono abbastanza sicuro del formato del file dei tag. La variante che sto usando qui (Exuberant Ctags 5.8) sembra mettere uno "f" nella quarta colonna, se il tag rappresenta una funzione. Quindi in questo caso userei awk per filtrare tutti i tag che rappresentano le funzioni, e quindi grep per eliminare tutte le righe senza __attribute__((warn_unused_result)).

Quindi, in poche parole, prima si fa

$ ctags **/*.c 

Questo crea un file chiamato "tag" nella directory corrente. Il comando potrebbe anche essere ctags-exuberant, a seconda della variante. Lo **/*.c è un modello glob che potrebbe funzionare nella shell, altrimenti, è necessario fornire i file di origine in un altro modo (guarda le opzioni ctags).

Poi si filtra la Funktions:

$ cat tags | awk -F '\t' '$4 == "f" {print $0}' | grep -v "__attribute__((warn_unused_result))" 
+0

Ho dato un'occhiata a questo e sembra essere abbastanza promettente. Tuttavia, da quello che posso dire, il metodo non si preoccupa del tipo di valore di ritorno di una funzione. Tuttavia, voglio solo trattare le funzioni con valore restituito ErrorCode –

+0

Ah, mi dispiace, mi è mancato nella tua domanda. Quindi, dovrai giocare un po 'con le espressioni regolari. Un primo tentativo potrebbe assomigliare a questo: 'cat tags | awk -F '\ t' '$ 4 == "f" {print $ 3}' | grep '. * ErrorCode. * (' '. Nota che lascio' awk' solo print column '$ 3', che contiene un pattern per la funzione nella mia versione di' ctags'. Tuttavia, non sono sicuro se questo funziona in casi speciali, come quando il tipo di ritorno è su una linea diversa dal nome della funzione, dovresti giocare un po 'con esso e controllare i risultati –

+1

Funziona alla perfezione! Complimenti e grazie mille. –

1

No, non è possibile nel caso generale. La grammatica C++ è la più complessa di tutte le lingue che conosco e C++ non è analizzabile tramite espressioni regolari nel caso generale. Potresti riuscire se ti limiti a un insieme molto ristretto di usi, ma non sono sicuro di quanto sia fattibile nel tuo caso. Inoltre, non penso che l'excersise valga la pena, dal momento che a volte ignorare il risultato della funzione è una cosa OK.

+0

Non è così complesso, è un linguaggio piuttosto rigoroso. – 123

+1

Beh, qualcosa può essere molto severo e molto complesso allo stesso tempo. Come ho detto prima, l'analisi regexp di un codice C++ generale non è possibile. – SergeyA

+0

L'analisi di un file creato tramite ctags ha funzionato per me. Si occupa anche di namespace funzioni in linea, modelli ... –

5

Forse è possibile utilizzare sed con le espressioni regolari. Di seguito ha lavorato per me in un paio di file di test ho provato:

sed -r "s/ErrorCode\s+\w+\s*(.*)\s*\{/__attribute__((warn_unused_result)) \0/g" test.cpp 

Se non hai familiarità con regex, il modello si traduce essenzialmente in:

CodiceErrore, qualche spazio bianco, alcuni caratteri alfanumerici (nome della funzione), forse qualche spazio bianco, parentesi aperta, qualsiasi cosa (argomenti), parentesi chiusa, forse qualche spazio bianco, parentesi graffa aperta.

Se questo modello viene trovato, è preceduto da __attribute__((warn_unused_result)). Si noti che questo funziona solo se si mette la parentesi graffa aperta sempre nella stessa riga degli argomenti e non si hanno interruzioni di riga nelle dichiarazioni di funzione.

+0

Oh, beh, non stai usando i modelli, vero? Mi rendo conto che questo è un po 'ingenuo ... – Jonas

+0

Grazie! Credo che potrei usare questo. Tuttavia, potrebbe produrre molti errori. Da quello che ho ottenuto, questo sostituirà automaticamente le occorrenze designate. È un po 'troppo hardcore per i miei gusti. Ci sono opzioni in modo tale che il comando restituisca solo la riga e il file in cui può essere eventualmente effettuata una sostituzione, in modo tale che possa ancora decidere se farlo o meno? –

+0

Puoi 'grep -E" ErrorCode \ s + \ w + \ s * (. *) \ S * \ {"' per stampare tutte le linee che corrispondono alla regex. – Jonas

Problemi correlati