Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

44
Uno studio sull’efficacia di checker automatici per la modernizzazione di codice C++ Idriss Riouak Universit` a degli studi di Parma Corso di laurea in Informatica 22 Dicembre 2016

Transcript of Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

Page 1: 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

Page 2: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 3: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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..

Page 4: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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

Page 5: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice 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

Decl: dichiarazioni di variabili, campi di struct/union/class e tipi.

Page 6: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice 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

Type: Tipi del C++ e i relativi qualificatori.

Page 7: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice 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

Stmt: Statement del C++.

Page 8: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice 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++.

Page 9: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice 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;

}

Page 10: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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

Page 11: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 12: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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

Page 13: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ;

Page 14: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);

}

Page 15: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);};

}

Page 16: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

Page 17: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 << "); };";

}

Page 18: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 << "); };";

}

Page 19: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 20: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ;

};

Page 21: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 22: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 23: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 24: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 25: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 26: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);}

}

Page 27: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 28: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 29: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 30: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 31: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 32: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 33: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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 ");

}

Page 34: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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::

Page 35: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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

Page 36: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 37: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 38: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 39: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

logo.png

Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni

GRAZIE PER L’ATTENZIONE !

Page 40: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

logo.png

Modernizzazione del Codice Clang Tidy Estendibilita dell’infrastruttura per i check Testing e Conclusioni

Page 41: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);};

Page 42: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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.

Page 43: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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

Page 44: Presentazione: uno studio sull'efficacia di checker automatici per la modernizzazione di codice C++

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);

};}