Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++
-
Upload
idriss-riouak -
Category
Software
-
view
27 -
download
3
Transcript of Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++
Uno studio sull’efficacia di checker automaticiper la modernizzazione di codice C++
Idriss Riouak
Universita degli studi di ParmaCorso di laurea in Informatica
22 Dicembre 2016
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Problema: la modernizzazione del codice
E’ difficile mantenere i software aggiornati alle piu recenticonvenzioni stabilite dagli standard.
Modernizzare il software rappresenta un costo. Nasce cosıl’esigenza d’avere strumenti che automatizzino (almeno in parte)tale processo.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Clang Tidy
Clang Tidy e un uno dei progetti principali della Clang & LLVMCommunity
E’ uno strumento utilizzato per individuare i piu frequenti errori diprogrammazione.
Aiuta lo sviluppatore a seguire i pattern di programmazione e inuovi costrutti dello standard C++11/C++14..
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Clang Tidy Modernize
Clang Tidy Modernize supporta 17 check tra cui:Keyword nullptrKeyword default per funzioni specialiKeyword auto (Deduzione automatica dei tipi)Keyword overrideshared ptr & unique ptrUtilizzo di lambda funzioni anziche std::bindRiferimenti RValue (move semantic)Utilizzo di Range-based for loop
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Abstract Sintax Tree
Dal codice sorgente da modernizzare viene creato un Albero diSintassi Astratta, d’ora in avanti AST.
Definition (Albero di Sintassi Astratta)L’AST e una rappresentazione piu ad alto livello del codicesorgente, utilizzata dal compilatore per ottenerne informazioni.
L’AST di Clang e composto da quattro macro classi:
Decl
Decl: dichiarazioni di variabili, campi di struct/union/class e tipi.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Abstract Sintax Tree
Dal codice sorgente da modernizzare viene creato un Albero diSintassi Astratta, d’ora in avanti AST.
Definition (Albero di Sintassi Astratta)L’AST e una rappresentazione piu ad alto livello del codicesorgente, utilizzata dal compilatore per ottenerne informazioni.
L’AST di Clang e composto da quattro macro classi:
Decl Type
Type: Tipi del C++ e i relativi qualificatori.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Abstract Sintax Tree
Dal codice sorgente da modernizzare viene creato un Albero diSintassi Astratta, d’ora in avanti AST.
Definition (Albero di Sintassi Astratta)L’AST e una rappresentazione piu ad alto livello del codicesorgente, utilizzata dal compilatore per ottenerne informazioni.
L’AST di Clang e composto da quattro macro classi:
Decl Type Stmt
Stmt: Statement del C++.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Abstract Sintax Tree
Dal codice sorgente da modernizzare viene creato un Albero diSintassi Astratta, d’ora in avanti AST.
Definition (Albero di Sintassi Astratta)L’AST e una rappresentazione piu ad alto livello del codicesorgente, utilizzata dal compilatore per ottenerne informazioni.
L’AST di Clang e composto da quattro macro classi:
Decl Type Stmt Expr
Expr: classe derivata di Stmt. Espressione del C++.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Esempio
Consideriamo il seguente esempio:
void SetStream (int);
int main(int argc , char *argv []) {
int StreamNumber = 1;
SetStream ( StreamNumber );
return 0;
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
FunctionDecl‘void (int, char**)’ main
ParamValDecl‘int’ argc
ParamValDecl‘char **’:‘char**’ argv
CompoundStmt DeclStmt
CallExpr‘void’
ReturnStmt
VarDecl‘int’ StreamNumber
IntegerLiteral‘int’ 1
ImplicitCastExpr‘void (*)()’
DeclRefExpr‘void()’ ‘SetStream’
ImplicitCastExpr‘int’
DeclRefExpr‘int’ ‘StreamNumber’
IntegerLiteral‘int’ 0
LEGENDA:
Espressione
Statement
Declaration
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Flessibilita dell’infrastruttura
ObiettivoOltre a valutare l’efficacia dei check esistenti nel modulomodernize, uno degli obiettivi era di mettere alla prova laflessibilita e la modularita dell’infrastruttura di Clang Tidy.
Sono stati presi in considerazione tre casistiche:La correzione di errori in check esistenti.La definizione di nuovi check.L’estensione delle funzionalita di check esistenti.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Struttura di un check
Per ogni check presente in Clang Tidy, esiste una classe che nedescrive il comportamento ed e cosı strutturata:# include "../ ClangTidy .h"
namespace clang {namespace tidy {namespace some_module {
class MyCheck : public ClangTidyCheck {public :
MyCheck ( StringRef Name , ClangTidyContext * Context ): ClangTidyCheck (Name , Context ) {}
// Other Methods ...};
} // namespace some_module} // namespace tidy} // namespace clang
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Definizione del comportamento del check
AST Matcher: metodo che permette di etichettare alcuni nodidell’AST senza doverlo visitare nella sua completezza
void registerMatchers ( ast_matchers ::MatchFinder * Finder ) override ;
Utilizzo dei nodi: effettuando l’overriding del seguente metodo epossibile utilizzare i nodi etichettati.
void check(constast_matchers :: MatchFinder :: MatchResult& Result ) override ;
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Correzione di errori in check esistenti:modernize-avoid-bind
Studiano il check modernize-avoid-bind, si e riscontrato un caso incui proponesse un fix errato. In particolare il check nonconsiderava in alcun modo l’operatore di risoluzione dello scope.
Consideriamo tale porzione di codice:namespace A {
int add(int x, int y);}
int main(int argc , const char * argv []) {auto clj = std :: bind(A::add , 1, 1);
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Correzione di errori in check esistenti:modernize-avoid-bind
Dopo avere applicato il fix con Clang Tidy:int main(int argc , const char * argv []) {
auto clj = [=]( auto && arg1) {return add(x, arg1);
};}
Che e completamente diverso daint main(int argc , const char * argv []) {auto clj = [=]( auto && arg1) {
return A::add(x, arg1);};
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Correzione di errori in check esistenti:modernize-avoid-bind
E’ stato modificato il metodo registerMatcher in maniera tale daetichettare il riferimento della dichiarazione della funzione.void AvoidBindCheck :: registerMatchers ( MatchFinder
* Finder ) {if (! getLangOpts (). CPlusPlus14 ) // Need C++14 for
generic lambdas .return ;
Finder -> addMatcher (callExpr ( callee ( namedDecl ( hasName (":: std :: bind"))),
declRefExpr(to( functionDecl ().bind("f"))).(bind("ref")))).bind("bind"),
this);}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Dopo di che e stato modificato il metodo che sfrutta tali nodi:void AvoidBindCheck :: check(const
MatchFinder :: MatchResult & Result ) {const auto * MatchedDecl =
Result .Nodes.getNodeAs <CallExpr >("bind");auto Diag = diag( MatchedDecl -> getLocStart (),
" prefer a lambda to std :: bind");// Some Code ...const auto *F =
Result .Nodes.getNodeAs < FunctionDecl >("f");std :: string Buffer ;llvm :: raw_string_ostream Stream ( Buffer );// Some Code ...const auto *ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref");Stream << "[" << ( HasCapturedArgument ? "=" : "")
<< "]";addPlaceholderArgs (Args , Stream );Stream << " return ";ref->printPretty(Stream, nullptr,Result.Context->getPrintingPolicy());Stream << "(";addFunctionCallArgs (Args , Stream );Stream << "); };";
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Dopo di che e stato modificato il metodo che sfrutta tali nodi:void AvoidBindCheck :: check(const
MatchFinder :: MatchResult & Result ) {const auto * MatchedDecl =
Result .Nodes.getNodeAs <CallExpr >("bind");auto Diag = diag( MatchedDecl -> getLocStart (),
" prefer a lambda to std :: bind");// Some Code ...const auto *F =
Result .Nodes.getNodeAs < FunctionDecl >("f");std :: string Buffer ;llvm :: raw_string_ostream Stream ( Buffer );// Some Code ...const auto *ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref");Stream << "[" << ( HasCapturedArgument ? "=" : "")
<< "]";addPlaceholderArgs (Args , Stream );Stream << " return ";ref->printPretty(Stream, nullptr,Result.Context->getPrintingPolicy());Stream << "(";addFunctionCallArgs (Args , Stream );Stream << "); };";
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Correzione di errori in check esistenti:modernize-avoid-bind
Compilando e rilanciando otteniamo la modifica corretta:int main(int argc , const char * argv []) {
auto clj = [=]( auto && arg1) {return A::add(x, arg1);
};}
Per evitare la regressione delle modifiche effettuate sono staticreati dei test.La patch e stata sottoposta agli sviluppatori di Clang che l’hannotestata e accettata.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Creazione di un check: modernize-use-delete
Prima dell’avvento dello standard del C++11, per non permetterel’utilizzo di costruttori/distruttori di una classe, li si definiva privatie non implementati.class MyClass {
private :MyClass (const MyClass &);MyClass & operator =( const MyClass &);
};
Con il C++11 e stata introdotta la keyword delete.class MyClass {
public :MyClass (const MyClass &) = delete ;MyClass & operator =( const MyClass &) = delete ;
};
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if ( getLangOpts (). CPlusPlus ) {// DistruttoreFinder -> addMatcher ( cxxDestructorDecl
( isPrivate ()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl (
anyOf(// Costruttore di defaultallOf( isPrivate (), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate (),isCopyConstructor (),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl ( isPrivate (),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if (getLangOpts().CPlusPlus) {// DistruttoreFinder -> addMatcher ( cxxDestructorDecl
( isPrivate ()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl (
anyOf(// Costruttore di defaultallOf( isPrivate (), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate (),isCopyConstructor (),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl ( isPrivate (),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if (getLangOpts().CPlusPlus) {// DistruttoreFinder -> addMatcher (cxxDestructorDecl
(isPrivate()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl (
anyOf(// Costruttore di defaultallOf( isPrivate (), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate (),isCopyConstructor (),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl ( isPrivate (),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if (getLangOpts().CPlusPlus) {// DistruttoreFinder -> addMatcher (cxxDestructorDecl
(isPrivate()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl(
anyOf(// Costruttore di defaultallOf(isPrivate(), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate (),isCopyConstructor (),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl ( isPrivate (),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if (getLangOpts().CPlusPlus) {// DistruttoreFinder -> addMatcher (cxxDestructorDecl
(isPrivate()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl(
anyOf(// Costruttore di defaultallOf(isPrivate(), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate(),isCopyConstructor(),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl ( isPrivate (),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: registerMatchers ( MatchFinder* Finder ) {
if (getLangOpts().CPlusPlus) {// DistruttoreFinder -> addMatcher (cxxDestructorDecl
(isPrivate()).bind( SpecialFunction ),this);Finder -> addMatcher (cxxConstructorDecl(
anyOf(// Costruttore di defaultallOf(isPrivate(), unless (
hasAnyConstructorInitializer ( anything ())),parameterCountIs (0)),
allOf(// Costruttore di copiaisPrivate(),isCopyConstructor(),
parameterCountIs (1)))).bind( SpecialFunction ),
this);Finder -> addMatcher (// Operator =
cxxMethodDecl(isPrivate(),isCopyAssignmentOperator (),
hasParameter (0, hasType ( lValueReferenceType ()))).bind( SpecialFunction ),
this);}
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl -> isDefined () ||SpecialFunctionDecl -> isDeleted () ||SpecialFunctionDecl -> isExplicitlyDefaulted () ||SpecialFunctionDecl -> isLateTemplateParsed () ||! SpecialFunctionDecl -> isUserProvided () )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl -> isDeleted () ||SpecialFunctionDecl -> isExplicitlyDefaulted () ||SpecialFunctionDecl -> isLateTemplateParsed () ||! SpecialFunctionDecl -> isUserProvided () )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl ->isDeleted() ||SpecialFunctionDecl -> isExplicitlyDefaulted () ||SpecialFunctionDecl -> isLateTemplateParsed () ||! SpecialFunctionDecl -> isUserProvided () )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl ->isDeleted() ||SpecialFunctionDecl ->isExplicitlyDefaulted() ||SpecialFunctionDecl -> isLateTemplateParsed () ||! SpecialFunctionDecl -> isUserProvided () )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl ->isDeleted() ||SpecialFunctionDecl ->isExplicitlyDefaulted() ||SpecialFunctionDecl ->isLateTemplateParsed() ||! SpecialFunctionDecl -> isUserProvided () )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl ->isDeleted() ||SpecialFunctionDecl ->isExplicitlyDefaulted() ||SpecialFunctionDecl ->isLateTemplateParsed() ||! SpecialFunctionDecl ->isUserProvided() )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint :: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
void UseDeleteCheck :: check(constMatchFinder :: MatchResult & Result ) {
const auto * SpecialFunctionDecl = Result .Nodes.getNodeAs < CXXMethodDecl >( SpecialFunction );
if ( SpecialFunctionDecl ->isDefined() ||SpecialFunctionDecl ->isDeleted() ||SpecialFunctionDecl ->isExplicitlyDefaulted() ||SpecialFunctionDecl ->isLateTemplateParsed() ||! SpecialFunctionDecl ->isUserProvided() )
return ;// Porzione di codice dove ottengo il nome della
funzione specialePresumedLoc PLoc = Result . SourceManager ->
getPresumedLoc ( SpecialFunctionDecl -> getLocEnd ());auto NewLocation = Result . SourceManager ->
translateLineCol ( Result . SourceManager ->getFileID ( SpecialFunctionDecl -> getLocEnd ()),PLoc. getLine (), PLoc. getColumn () +1);
diag( NewLocation ,"Use ’= delete ’ to disable the " +SpecialFunctionName )<<FixItHint:: CreateInsertion ( NewLocation , " =delete ");
}
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Diagnostica e Fix: modernize-use-delete
Quello che otteniamo eseguendo il check modernize-use-deletesulla seguente porzione di codice:class MyClass {
private :MyClass (const MyClass &);MyClass & operator =( const MyClass &);
};
quello che otteniamo e il seguente messaggio diagnostico::
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Testing di efficacia sulla Parma Polyhedra Library
Parma Polyhedra Library (PPL)Libreria di astrazioni numeriche concepita per le applicazioni nelcampo dell’analisi e verifica di sistemi complessi.
La PPL e composta da:78 file d’implementazione (.cc)
linee di codice 28·646 (senza commenti)366 header file (.hh)
linee di codice 129·602 (senza commenti)Numero totale di righe: 158·248
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Risultati ottenuti
Check Name Fix Corretti Fix Erratimodernize-use-nullptr 247 0modernize-use-auto 224 0modernize-use-override 114 0modernize-use-default 58 0modernize-pass-by-value 19 2modernize-use-delete 28 0modernize-use-emplace 15 0modernize-replace-auto-ptr 2 0modernize-redundant-void-arg 2 0modernize-deprecated-headers 1 0
Clang Tidy agisce su porzioni di codice relativamente semplici.Mentre la PPL per questioni di ottimizzazioni utilizza costrutticomplessi.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Conclusioni
Il lavoro di tesi ha permesso di studiare le problematiche relativealla modernizzazione del codice mediante checker automatici.
Clang Tidy si e presentato come un interessante progetto opensource la cui proprieta fondamentale e la modularita.
Un ottimo strumento di supporto al programmatore nell’attivita dimodernizzazione del codice C++, anche se ad oggi non e efficaceed affidabile per essere utilizzato in maniera automatica comesoftware gia esistenti.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Sviluppi futuri
Nel futuro continuero a contribuire allo sviluppo di Clang Tidy,proponendo nuovi check e risolvendo errori nel checker, come nelcaso di modernize-pass-by-value.
Considerata la difficolta iniziale riscontrata nell’utilizzo di ClangTidy, e ragionevole pensare allo sviluppo di un’interfaccia graficache ne semplifichi l’utilizzo.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
GRAZIE PER L’ATTENZIONE !
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Errore: modernize-pass-by-value
Nel testare modernize-pass-by-value si e riscontrato il seguenteerrore://! File iterator_to_const_defs .hh :135template <typename Container >class
Parma_Polyhedra_Library :: const_iterator_to_const {private :
//! Constructs from the lower -level const_iterator .const_iterator_to_const (const Base& b);
};
Correttamente diventa//! File iterator_to_const_defs .hh :135template <typename Container >class
Parma_Polyhedra_Library :: const_iterator_to_const {private :
//! Constructs from the lower -level const_iterator .const_iterator_to_const (Base b);};
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Errore: modernize-pass-by-value
Lasciando pero invariata la testata della definizione.//! File iterator_to_const_inline .hh :119template <typename Container >inlineconst_iterator_to_const <Container >::
const_iterator_to_const (const Base& b): base(std :: move(b)) {}
Ricompilando tutta la PPL ci accorgiamo che abbiamo degli erroridi compilazione.
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Commit LLVM Community
Figure: Link della revisione: https://reviews.llvm.org/D25649
logo.png
Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni
Commit LLVM Community
Prima di rilasciare la patch, e stato necessario testare che lemodifiche apportate al Check, non abbiano aggiunto ulteriori errorie che il checker nel suo insieme fosse ancora stabile.LLVM dispone di una suite di test. In particolari quelli delpacchetto modernize sono locati nella directory/llvm/tools/clang/tools/extra/test/clang-tidy.Nel file modernize-avoid-bind.cpp sono state aggiunte le seguentiistruzioni:namespace C {int add(int x, int y){ return x + y; }}void n(){auto clj = std :: bind(C::add , 1, 1);// CHECK - MESSAGES : :[[ @LINE -1]]:16: warning : prefer a
lambda to std :: bind// CHECK -FIXES: auto clj = [] { return C:: add (1, 1);
};}