SlideShare une entreprise Scribd logo
1  sur  56
Télécharger pour lire hors ligne
Clang-tidy:
путешествие внутрь AST С++
Юрий Ефимочев
Обо мне
Solarwinds
Lead Developer
MSP Backup & Recovery
Что такое clang-tidy?
Инструмент для статического анализа кода и
поиска типичных ошибок программирования
Встроенные правила(~200)
● ClangAnalyzer
● Readability/Modernize/Performance
● CppCoreGuidelines
● LLVM/Google-style
Пример запуска
class TestClass
{
public:
TestClass() :
m_B(),
m_C()
{
}
private:
int m_A;
int m_B;
int m_C;
};
Пример запуска
$ clang-tidy -checks="cppcoreguidelines-*" ./test.cpp
1 warning generated.
./test.cpp:4:5: warning: constructor does not initialize these fields: m_A
[cppcoreguidelines-pro-type-member-init]
TestClass() :
^
m_A(),
Code review
Цели code review
● Соответствие реализации задаче
● Поиск ошибок и неоптимальностей реализации
● Соответствие guidelines и best practices
Clang-tidy и code review?
Платформа для построения собственных
инструментов статического анализа кода
Расширяемость
● Полный доступ к AST и препроцессору
● Модульная архитектура
● Инфраструктура для разработки и
тестирования
Что необходимо для использования?
● Код должен собираться clang
● Необходима compilation database
Алгоритм разработки правила
1. Подготовить пример
2. Посмотреть в AST
3. ???
4. Profit
Пример 1
#include <iostream>
class TestClass
{
public:
static int const Constant;
int m_public;
private:
int m_private;
};
struct TestStruct
{
int Field;
};
// style: class public field
Clang-check: визуализация AST
$ clang-check -ast-dump -ast-dump-filter="Test" ./test.cpp
Dumping TestClass:
CXXRecordDecl 0xaf665da8 <test.cpp:3:1, line:12:1> line:3:7 class TestClass definition
|-CXXRecordDecl 0xaf665ec0 <col:1, col:7> col:7 implicit class TestClass
|-AccessSpecDecl 0xaf665f50 <line:5:1, col:7> col:1 public
|-VarDecl 0xaf665f88 <line:6:5, col:22> col:22 Constant 'const int' static
|-FieldDecl 0xaf665ff8 <line:8:5, col:9> col:9 m_public 'int'
|-AccessSpecDecl 0xaf666040 <line:10:1, col:8> col:1 private
`-FieldDecl 0xaf666078 <line:11:5, col:9> col:9 m_private 'int'
Dumping TestStruct:
CXXRecordDecl 0xaf6660c0 <test.cpp:14:1, line:17:1> line:14:8 struct TestStruct definition
|-CXXRecordDecl 0xaf6661d0 <col:1, col:8> col:8 implicit struct TestStruct
`-FieldDecl 0xaf666270 <line:16:5, col:9> col:9 Field 'int'
AST Nodes
● Decl
● Stmt
● Type
AST Nodes
● Decl
CXXRecordDecl
CXXMethodDecl
VarDecl
● Stmt
● Type
AST Nodes
● Decl
● Stmt
ifStmt
CXXTryStmt
BinaryOperator
● Type
AST Nodes
● Decl
● Stmt
● Type
PointerType
ReferenceType
LValueReferenceType
Пример 1: AST
$ clang-check -ast-dump -ast-dump-filter="Test" ./test.cpp
Dumping TestClass:
CXXRecordDecl 0xaf665da8 <test.cpp:3:1, line:12:1> line:3:7 class TestClass definition
|-CXXRecordDecl 0xaf665ec0 <col:1, col:7> col:7 implicit class TestClass
|-AccessSpecDecl 0xaf665f50 <line:5:1, col:7> col:1 public
|-VarDecl 0xaf665f88 <line:6:5, col:22> col:22 Constant 'const int' static
|-FieldDecl 0xaf665ff8 <line:8:5, col:9> col:9 m_public 'int'
|-AccessSpecDecl 0xaf666040 <line:10:1, col:8> col:1 private
`-FieldDecl 0xaf666078 <line:11:5, col:9> col:9 m_private 'int'
Dumping TestStruct:
CXXRecordDecl 0xaf6660c0 <test.cpp:14:1, line:17:1> line:14:8 struct TestStruct definition
|-CXXRecordDecl 0xaf6661d0 <col:1, col:8> col:8 implicit struct TestStruct
`-FieldDecl 0xaf666270 <line:16:5, col:9> col:9 Field 'int'
AST Matchers
● Node Matchers
cxxRecordDecl, cxxMethodDecl, namespaceDecl, ifStmt, ...
● Narrowing Matchers
isConstant, isFinal, hasName, matchesName, unless, ...
● Traversal Matchers
hasDescendant, hasParent, hasBody, ...
cxxMethodDecl(matchesName(“Get.*”), hasParent(cxxRecordDecl(isStruct()))
Пример 1
clang-query> match fieldDecl()
Match #1:
/home/yury/Projects/test.cpp:8:5: note: "root" binds here
int m_public;
^~~~~~~~~~~~
Match #2:
/home/yury/Projects/test.cpp:11:5: note: "root" binds here
int m_private;
^~~~~~~~~~~~~
Match #3:
/home/yury/Projects/test.cpp:16:5: note: "root" binds here
int Field;
^~~~~~~~~
3 matches.
Пример 1
clang-query> match fieldDecl(isPublic())
Match #1:
/home/yury/Projects/test.cpp:8:5: note: "root" binds here
int m_public;
^~~~~~~~~~~~
Match #2:
/home/yury/Projects/test.cpp:16:5: note: "root" binds here
int Field;
^~~~~~~~~
2 matches.
Пример 1
clang-query> match fieldDecl(isPublic(), hasParent(cxxRecordDecl(isClass())))
Match #1:
/home/yury/Projects/test.cpp:8:5: note: "root" binds here
int m_public;
^~~~~~~~~~~~
1 match.
Добавление правила
$ ./add_new_check.py misc field-visibility
Updating ./misc/CMakeLists.txt...
Creating ./misc/FieldVisibilityCheck.h...
Creating ./misc/FieldVisibilityCheck.cpp...
Updating ./misc/MiscTidyModule.cpp...
Creating ../test/clang-tidy/misc-field-visibility.cpp...
Creating ../docs/clang-tidy/checks/misc-field-visibility.rst...
Updating ../docs/clang-tidy/checks/list.rst...
Done. Now it's your turn!
Пример 1: шаблон реализации
class FieldVisibilityCheck : public ClangTidyCheck
{
public:
FieldVisibilityCheck(StringRef name, ClangTidyContext* context) :
ClangTidyCheck(name, context)
{
}
private:
void registerMatchers(ast_matchers::MatchFinder* finder) override
{
}
void check(ast_matchers::MatchFinder::MatchResult const& result) override
{
}
};
Пример 1: реализация
class FieldVisibilityCheck : public ClangTidyCheck
{
public:
FieldVisibilityCheck(StringRef name, ClangTidyContext* context) :
ClangTidyCheck(name, context)
{
}
private:
void registerMatchers(ast_matchers::MatchFinder* finder) override
{
finder->addMatcher(fieldDecl(isPublic(), hasParent(cxxRecordDecl(isClass()))).bind("field"), this);
}
void check(ast_matchers::MatchFinder::MatchResult const& result) override
{
FieldDecl const& field = *result.Nodes.getNodeAs<FieldDecl const>("field");
diag(field.getLocStart(), "Class field should be private");
}
};
Пример 1: результат
$ clang-tidy -checks="misc-field-visibility-check" ./test.cpp
1 warning generated.
./test.cpp:8:5: warning: Class field should be private [misc-field-visibility-check]
int m_public;
^
Пример 2
int Function(int a)
{
// ...
a = something;
// ...
return a;
}
// style: mutable parameter
Пример 2
struct Test
{
virtual int VirtualMethod(int a) = 0;
int Method(int a, int const b, int& c, int* d)
{
a = b;
return a;
}
};
Пример 2: AST
Dumping Test:
CXXRecordDecl 0x46b1b20 <test.cpp:1:1, line:9:1> line:1:8 struct Test definition
|-CXXRecordDecl 0x46b1c30 <col:1, col:8> col:8 implicit struct Test
|-CXXMethodDecl 0x46b1d90 <line:3:5, col:32> col:9 VirtualMethod 'int (int)'
| `-ParmVarDecl 0x46b1cd0 <col:23, col:27> col:27 a 'int'
`-CXXMethodDecl 0x46b2140 <line:4:5, line:8:5> line:4:9 Method 'int (int, const int, int &, int *)'
|-ParmVarDecl 0x46b1e50 <col:16, col:20> col:20 used a 'int'
|-ParmVarDecl 0x46b1ec0 <col:23, col:33> col:33 used b 'const int'
|-ParmVarDecl 0x46b1f60 <col:36, col:41> col:41 c 'int &'
|-ParmVarDecl 0x46b2000 <col:44, col:49> col:49 d 'int *'
`-CompoundStmt 0x46b2320 <line:5:5, line:8:5>
|-BinaryOperator 0x46b22a0 <line:6:9, col:13> 'int' lvalue '='
| |-DeclRefExpr 0x46b2238 <col:9> 'int' lvalue ParmVar 0x46b1e50 'a' 'int'
| `-ImplicitCastExpr 0x46b2288 <col:13> 'int' <LValueToRValue>
| `-DeclRefExpr 0x46b2260 <col:13> 'const int' lvalue ParmVar 0x46b1ec0 'b' 'const int'
`-ReturnStmt 0x46b2308 <line:7:9, col:16>
`-ImplicitCastExpr 0x46b22f0 <col:16> 'int' <LValueToRValue>
`-DeclRefExpr 0x46b22c8 <col:16> 'int' lvalue ParmVar 0x46b1e50 'a' 'int'
Пример 2: реализация
void ImmutableParamsCheck::registerMatchers(MatchFinder* finder)
{
finder->addMatcher(
parmVarDecl(
hasAncestor(functionDecl(hasBody(stmt()))),
unless(anyOf(
hasType(isConstQualified()),
hasType(referenceType()),
hasType(pointerType())))).bind("parameter"), this);
}
void ImmutableParamsCheck::check(MatchFinder::MatchResult const& result)
{
ParmVarDecl const& parameter = *result.Nodes.getNodeAs<ParmVarDecl const>("parameter");
SourceLocation const location = parameter.getSourceRange().getEnd();
diag(location, "Consider making constant") <<
FixItHint::CreateInsertion(location, "const ");
}
Пример 2: результат
$ clang-tidy -checks="misc-immutable-parameters-check" -fix ./test.cpp
2 warnings generated.
./test.cpp:4:20: warning: Consider making constant [iaso-immutable-params]
int Method(int a, int const b, int& c, int* d)
^
const
./test.cpp:4:20: note: FIX-IT applied suggested code changes
int Method(int a, int const b, int& c, int* d)
^
clang-tidy applied 1 of 1 suggested fixes.
Пример 2: результат
struct Test
{
virtual int VirtualMethod(int a) = 0;
int Method(int a, int const b, int& c, int* d)
{
a = b;
return a;
}
};
Пример 2: результат
struct Test
{
virtual int VirtualMethod(int a) = 0;
int Method(int const a, int const b, int& c, int* d)
{
a = b;
return a;
}
};
Пример 3
// cxxRecordDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$")))
class TestClass
{
public:
// cxxMethodDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$")))
// parmVarDecl(unless(matchesName("::[a-z][a-zA-Z0-9]*$")))
void Method(int arg);
private:
// fieldDecl(unless(matchesName("::m_[a-z][a-zA-Z0-9]*$")),
// hasParent(cxxRecordDecl(isClass())))
int m_field;
};
struct TestStruct
{
// fieldDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$")),
// hasParent(cxxRecordDecl(isStruct())))
int Field;
};
Пример 3
// varDecl(hasLocalStorage(), unless(matchesName("::[a-z][a-zA-Z0-9]*$")))
int localVariable;
// varDecl(hasGlobalStorage(),
// unless(anyOf(matchesName("::s_[a-z][a-zA-Z0-9]*$"), hasType(isConstQualified()))))
static int s_staticVariable;
// varDecl(hasGlobalStorage(),
// unless(anyOf(matchesName("::[A-Z][a-zA-Z0-9]*$"), unless(hasType(isConstQualified())))))
static int const Constant = 42;
Пример 4
Можно ли бросать исключение из
деструктора?
Пример 4
class Test
{
public:
~Test()
{
throw Exception();
}
};
// c++11: terminate
Пример 4
class Test
{
public:
~Test() noexcept(true)
{
throw Exception();
}
};
// c++11: terminate
Пример 4
class Test
{
public:
~Test() noexcept(false)
{
throw Exception();
}
};
Пример 4
class Test
{
public:
~Test() noexcept(false)
{
throw Exception();
}
};
int main()
{
std::unique_ptr<Test> test(new Test());
test.reset();
}
// c++11: terminate
Пример 4
class Parent
{
public:
~Parent() noexcept(false);
};
class Child : public Parent
{
public:
~Child()
{
}
};
int main()
{
std::unique_ptr<Child> test(new Child());
test.reset();
}
// c++11: terminate
Пример 4
class Parent
{
public:
~Parent() noexcept(false);
};
class Child : public Parent
{
public:
~Child() noexcept(true)
{
}
};
int main()
{
std::unique_ptr<Child> test(new Child());
test.reset();
}
// c++11: terminate
Пример 4
● Не бросать исключения из деструкторов
● Обозначить бросающие деструкторы
‘noexcept(false)’
● Не использовать ‘noexcept(true)’ для
деструкторов
Пример 4: реализация
void ExplicitThrowSpecificationCheck::registerMatchers(MatchFinder* finder)
{
finder->addMatcher(cxxDestructorDecl().bind("destructor"), this);
}
void ExplicitThrowSpecificationCheck::check(MatchFinder::MatchResult const& result)
{
FunctionDecl const& declaration = *result.Nodes.getNodeAs<FunctionDecl>("destructor");
FunctionProtoType const& prototype = *declaration.getType()->getAs<FunctionProtoType>();
bool const destructorCanThrow = prototype.getNoexceptSpec(*result.Context) == FunctionProtoType::NR_Throw;
bool const isSpecificationExplicit = declaration.getExceptionSpecSourceRange().isValid();
if (destructorCanThrow && !isSpecificationExplicit)
{
diag(declaration.getSourceRange().getEnd(), "This destructor should be marked with 'noexcept(false)'");
}
if (!destructorCanThrow && isSpecificationExplicit)
{
diag(declaration.getSourceRange().getEnd(), "Do not mark destructor with 'noexcept(true)'");
}
}
Пример 4: результат
class Parent
{
public:
~Parent() noexcept(false);
};
class Child : public Parent
{
public:
~Child() noexcept(true)
{
}
};
// do not use ‘noexept(true)’
Пример 4: результат
class Parent
{
public:
~Parent() noexcept(false);
};
class Child : public Parent
{
public:
~Child()
{
}
};
// can throw, mark with ‘noexcept(false)’
Пример 4: результат
class Parent
{
public:
~Parent() noexcept(false);
};
class Child : public Parent
{
public:
~Child() noexcept(false)
{
}
};
Пример 4
void Function();
struct Object
{
Object();
bool operator<(Object const& right) const;
};
struct Test
{
Test()
{
Object a, b;
if (a < b)
{
Function();
}
int* p = new int(42);
}
};
Пример 4: реализация
void ThrowFromDestructorCheck::registerMatchers(MatchFinder* finder)
{
finder->addMatcher(expr(hasAncestor(cxxDestructorDecl().bind("destructor"))).bind("expression"), this);
}
void ThrowFromDestructorCheck::check(MatchFinder::MatchResult const& result)
{
FunctionDecl const& declaration = *result.Nodes.getNodeAs<FunctionDecl>("destructor");
FunctionProtoType const& prototype = *declaration.getType()->getAs<FunctionProtoType>();
bool const destructorCanThrow = prototype.getNoexceptSpec(*result.Context) == FunctionProtoType::NR_Throw;
if (destructorCanThrow)
{
return;
}
Expr const& expression = *result.Nodes.getNodeAs<Expr>("expression");
bool const expressionCanThrow = m_compiler->getSema().canThrow(&expression) != CT_Cannot;
if (expressionCanThrow)
{
diag(expression.getExprLoc(), "Expression can throw exception");
}
}
Пример 4: результат
void Function();
struct Object
{
Object();
bool operator<(Object const& right) const;
};
struct Test
{
Test()
{
Object a, b;
if (a < b)
{
Function();
}
int* p = new int(42);
}
};
// can throw: constructor
// can throw: operator <
// can throw: Function call
// can throw: operator new
Пример 4: результат
void Function() noexcept(true);
struct Object
{
Object() noexcept(true);
bool operator<(Object const& right) const noexcept(true);
};
struct Test
{
Test()
{
Object a, b;
if (a < b)
{
Function();
}
}
};
Clang-tidy: итоги
Clang-tidy: итоги
● Простая реализация сложных проверок
● Автоматизация рутинных проверок
● Отличный способ лучше узнать C++
Полезные ссылки
http://clang.llvm.org/extra/clang-tidy
http://clang.llvm.org/docs/LibASTMatchersReference.html
http://clang.llvm.org/docs/IntroductionToTheClangAST.html
?
efimyury@gmail.com
yury.efimochev@solarwinds.com

Contenu connexe

Tendances

Apache Flink Crash Course by Slim Baltagi and Srini Palthepu
Apache Flink Crash Course by Slim Baltagi and Srini PalthepuApache Flink Crash Course by Slim Baltagi and Srini Palthepu
Apache Flink Crash Course by Slim Baltagi and Srini PalthepuSlim Baltagi
 
Best Practices for Middleware and Integration Architecture Modernization with...
Best Practices for Middleware and Integration Architecture Modernization with...Best Practices for Middleware and Integration Architecture Modernization with...
Best Practices for Middleware and Integration Architecture Modernization with...Claus Ibsen
 
HTTP/2 and Java: Current Status
HTTP/2 and Java: Current StatusHTTP/2 and Java: Current Status
HTTP/2 and Java: Current StatusSimone Bordet
 
[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들NHN FORWARD
 
Java SE 9 modules (JPMS) - an introduction
Java SE 9 modules (JPMS) - an introductionJava SE 9 modules (JPMS) - an introduction
Java SE 9 modules (JPMS) - an introductionStephen Colebourne
 
Numeric Range Queries in Lucene and Solr
Numeric Range Queries in Lucene and SolrNumeric Range Queries in Lucene and Solr
Numeric Range Queries in Lucene and SolrVadim Kirilchuk
 
ReactJS presentation
ReactJS presentationReactJS presentation
ReactJS presentationThanh Tuong
 
Anchor tag HTML Presentation
Anchor tag HTML PresentationAnchor tag HTML Presentation
Anchor tag HTML PresentationNimish Gupta
 
Introduction to ReactJS
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJSHoang Long
 
The JavaScript Programming Language
The JavaScript Programming LanguageThe JavaScript Programming Language
The JavaScript Programming Languageguestceb98b
 
Text field and textarea
Text field and textareaText field and textarea
Text field and textareamyrajendra
 
Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Sid Anand
 

Tendances (20)

Apache Flink Crash Course by Slim Baltagi and Srini Palthepu
Apache Flink Crash Course by Slim Baltagi and Srini PalthepuApache Flink Crash Course by Slim Baltagi and Srini Palthepu
Apache Flink Crash Course by Slim Baltagi and Srini Palthepu
 
jQuery
jQueryjQuery
jQuery
 
Best Practices for Middleware and Integration Architecture Modernization with...
Best Practices for Middleware and Integration Architecture Modernization with...Best Practices for Middleware and Integration Architecture Modernization with...
Best Practices for Middleware and Integration Architecture Modernization with...
 
HTTP/2 and Java: Current Status
HTTP/2 and Java: Current StatusHTTP/2 and Java: Current Status
HTTP/2 and Java: Current Status
 
Sessions and cookies
Sessions and cookiesSessions and cookies
Sessions and cookies
 
[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들
 
Tomcat
TomcatTomcat
Tomcat
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Intro to React
Intro to ReactIntro to React
Intro to React
 
Java SE 9 modules (JPMS) - an introduction
Java SE 9 modules (JPMS) - an introductionJava SE 9 modules (JPMS) - an introduction
Java SE 9 modules (JPMS) - an introduction
 
Tomcat Server
Tomcat ServerTomcat Server
Tomcat Server
 
Numeric Range Queries in Lucene and Solr
Numeric Range Queries in Lucene and SolrNumeric Range Queries in Lucene and Solr
Numeric Range Queries in Lucene and Solr
 
ReactJS presentation
ReactJS presentationReactJS presentation
ReactJS presentation
 
Anchor tag HTML Presentation
Anchor tag HTML PresentationAnchor tag HTML Presentation
Anchor tag HTML Presentation
 
Introduction to ReactJS
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
 
Java memory model
Java memory modelJava memory model
Java memory model
 
The JavaScript Programming Language
The JavaScript Programming LanguageThe JavaScript Programming Language
The JavaScript Programming Language
 
Text field and textarea
Text field and textareaText field and textarea
Text field and textarea
 
Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016
 
Reactjs
ReactjsReactjs
Reactjs
 

Similaire à Clang tidy

Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer developmentAndrey Karpov
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2PVS-Studio
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmAndrey Karpov
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsPVS-Studio
 
The operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerThe operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerAndrey Karpov
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerAndrey Karpov
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitAndrey Karpov
 
Nyc open-data-2015-andvanced-sklearn-expanded
Nyc open-data-2015-andvanced-sklearn-expandedNyc open-data-2015-andvanced-sklearn-expanded
Nyc open-data-2015-andvanced-sklearn-expandedVivian S. Zhang
 
Basic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmersBasic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmersJen Yee Hong
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
 
Let's talks about string operations in C++17
Let's talks about string operations in C++17Let's talks about string operations in C++17
Let's talks about string operations in C++17Bartlomiej Filipek
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたAkira Maruoka
 
PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...Andrey Karpov
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareAndrey Karpov
 
Manipulators in c++
Manipulators in c++Manipulators in c++
Manipulators in c++Ashok Raj
 
Anomalies in X-Ray Engine
Anomalies in X-Ray EngineAnomalies in X-Ray Engine
Anomalies in X-Ray EnginePVS-Studio
 
Basic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersBasic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersAppier
 
Semmle Codeql
Semmle Codeql Semmle Codeql
Semmle Codeql M. S.
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xAndrey Karpov
 

Similaire à Clang tidy (20)

Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer development
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the Microcosm
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code Contracts
 
The operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerThe operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzer
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzer
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGit
 
Nyc open-data-2015-andvanced-sklearn-expanded
Nyc open-data-2015-andvanced-sklearn-expandedNyc open-data-2015-andvanced-sklearn-expanded
Nyc open-data-2015-andvanced-sklearn-expanded
 
Basic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmersBasic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmers
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
 
Let's talks about string operations in C++17
Let's talks about string operations in C++17Let's talks about string operations in C++17
Let's talks about string operations in C++17
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 
PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
Manipulators in c++
Manipulators in c++Manipulators in c++
Manipulators in c++
 
C language
C languageC language
C language
 
Anomalies in X-Ray Engine
Anomalies in X-Ray EngineAnomalies in X-Ray Engine
Anomalies in X-Ray Engine
 
Basic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersBasic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python Programmers
 
Semmle Codeql
Semmle Codeql Semmle Codeql
Semmle Codeql
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
 

Dernier

Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
 
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptJohnWilliam111370
 
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating SystemRashmi Bhat
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Sumanth A
 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmDeepika Walanjkar
 
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfPaper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfNainaShrivastava14
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionSneha Padhiar
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsResearcher Researcher
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodManicka Mamallan Andavar
 
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONTHE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONjhunlian
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...Erbil Polytechnic University
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionMebane Rash
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfalene1
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Erbil Polytechnic University
 
Main Memory Management in Operating System
Main Memory Management in Operating SystemMain Memory Management in Operating System
Main Memory Management in Operating SystemRashmi Bhat
 
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.elesangwon
 

Dernier (20)

Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
 
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
 
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
Stork Webinar | APM Transformational planning, Tool Selection & Performance T...
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating System
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
 
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfPaper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based question
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending Actuators
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument method
 
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTIONTHE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
THE SENDAI FRAMEWORK FOR DISASTER RISK REDUCTION
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of Action
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
 
Main Memory Management in Operating System
Main Memory Management in Operating SystemMain Memory Management in Operating System
Main Memory Management in Operating System
 
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
 

Clang tidy

  • 3. Что такое clang-tidy? Инструмент для статического анализа кода и поиска типичных ошибок программирования
  • 4. Встроенные правила(~200) ● ClangAnalyzer ● Readability/Modernize/Performance ● CppCoreGuidelines ● LLVM/Google-style
  • 5. Пример запуска class TestClass { public: TestClass() : m_B(), m_C() { } private: int m_A; int m_B; int m_C; };
  • 6. Пример запуска $ clang-tidy -checks="cppcoreguidelines-*" ./test.cpp 1 warning generated. ./test.cpp:4:5: warning: constructor does not initialize these fields: m_A [cppcoreguidelines-pro-type-member-init] TestClass() : ^ m_A(),
  • 8. Цели code review ● Соответствие реализации задаче ● Поиск ошибок и неоптимальностей реализации ● Соответствие guidelines и best practices
  • 9. Clang-tidy и code review? Платформа для построения собственных инструментов статического анализа кода
  • 10. Расширяемость ● Полный доступ к AST и препроцессору ● Модульная архитектура ● Инфраструктура для разработки и тестирования
  • 11. Что необходимо для использования? ● Код должен собираться clang ● Необходима compilation database
  • 12. Алгоритм разработки правила 1. Подготовить пример 2. Посмотреть в AST 3. ??? 4. Profit
  • 13. Пример 1 #include <iostream> class TestClass { public: static int const Constant; int m_public; private: int m_private; }; struct TestStruct { int Field; }; // style: class public field
  • 14. Clang-check: визуализация AST $ clang-check -ast-dump -ast-dump-filter="Test" ./test.cpp Dumping TestClass: CXXRecordDecl 0xaf665da8 <test.cpp:3:1, line:12:1> line:3:7 class TestClass definition |-CXXRecordDecl 0xaf665ec0 <col:1, col:7> col:7 implicit class TestClass |-AccessSpecDecl 0xaf665f50 <line:5:1, col:7> col:1 public |-VarDecl 0xaf665f88 <line:6:5, col:22> col:22 Constant 'const int' static |-FieldDecl 0xaf665ff8 <line:8:5, col:9> col:9 m_public 'int' |-AccessSpecDecl 0xaf666040 <line:10:1, col:8> col:1 private `-FieldDecl 0xaf666078 <line:11:5, col:9> col:9 m_private 'int' Dumping TestStruct: CXXRecordDecl 0xaf6660c0 <test.cpp:14:1, line:17:1> line:14:8 struct TestStruct definition |-CXXRecordDecl 0xaf6661d0 <col:1, col:8> col:8 implicit struct TestStruct `-FieldDecl 0xaf666270 <line:16:5, col:9> col:9 Field 'int'
  • 15. AST Nodes ● Decl ● Stmt ● Type
  • 17. AST Nodes ● Decl ● Stmt ifStmt CXXTryStmt BinaryOperator ● Type
  • 18. AST Nodes ● Decl ● Stmt ● Type PointerType ReferenceType LValueReferenceType
  • 19. Пример 1: AST $ clang-check -ast-dump -ast-dump-filter="Test" ./test.cpp Dumping TestClass: CXXRecordDecl 0xaf665da8 <test.cpp:3:1, line:12:1> line:3:7 class TestClass definition |-CXXRecordDecl 0xaf665ec0 <col:1, col:7> col:7 implicit class TestClass |-AccessSpecDecl 0xaf665f50 <line:5:1, col:7> col:1 public |-VarDecl 0xaf665f88 <line:6:5, col:22> col:22 Constant 'const int' static |-FieldDecl 0xaf665ff8 <line:8:5, col:9> col:9 m_public 'int' |-AccessSpecDecl 0xaf666040 <line:10:1, col:8> col:1 private `-FieldDecl 0xaf666078 <line:11:5, col:9> col:9 m_private 'int' Dumping TestStruct: CXXRecordDecl 0xaf6660c0 <test.cpp:14:1, line:17:1> line:14:8 struct TestStruct definition |-CXXRecordDecl 0xaf6661d0 <col:1, col:8> col:8 implicit struct TestStruct `-FieldDecl 0xaf666270 <line:16:5, col:9> col:9 Field 'int'
  • 20. AST Matchers ● Node Matchers cxxRecordDecl, cxxMethodDecl, namespaceDecl, ifStmt, ... ● Narrowing Matchers isConstant, isFinal, hasName, matchesName, unless, ... ● Traversal Matchers hasDescendant, hasParent, hasBody, ... cxxMethodDecl(matchesName(“Get.*”), hasParent(cxxRecordDecl(isStruct()))
  • 21. Пример 1 clang-query> match fieldDecl() Match #1: /home/yury/Projects/test.cpp:8:5: note: "root" binds here int m_public; ^~~~~~~~~~~~ Match #2: /home/yury/Projects/test.cpp:11:5: note: "root" binds here int m_private; ^~~~~~~~~~~~~ Match #3: /home/yury/Projects/test.cpp:16:5: note: "root" binds here int Field; ^~~~~~~~~ 3 matches.
  • 22. Пример 1 clang-query> match fieldDecl(isPublic()) Match #1: /home/yury/Projects/test.cpp:8:5: note: "root" binds here int m_public; ^~~~~~~~~~~~ Match #2: /home/yury/Projects/test.cpp:16:5: note: "root" binds here int Field; ^~~~~~~~~ 2 matches.
  • 23. Пример 1 clang-query> match fieldDecl(isPublic(), hasParent(cxxRecordDecl(isClass()))) Match #1: /home/yury/Projects/test.cpp:8:5: note: "root" binds here int m_public; ^~~~~~~~~~~~ 1 match.
  • 24. Добавление правила $ ./add_new_check.py misc field-visibility Updating ./misc/CMakeLists.txt... Creating ./misc/FieldVisibilityCheck.h... Creating ./misc/FieldVisibilityCheck.cpp... Updating ./misc/MiscTidyModule.cpp... Creating ../test/clang-tidy/misc-field-visibility.cpp... Creating ../docs/clang-tidy/checks/misc-field-visibility.rst... Updating ../docs/clang-tidy/checks/list.rst... Done. Now it's your turn!
  • 25. Пример 1: шаблон реализации class FieldVisibilityCheck : public ClangTidyCheck { public: FieldVisibilityCheck(StringRef name, ClangTidyContext* context) : ClangTidyCheck(name, context) { } private: void registerMatchers(ast_matchers::MatchFinder* finder) override { } void check(ast_matchers::MatchFinder::MatchResult const& result) override { } };
  • 26. Пример 1: реализация class FieldVisibilityCheck : public ClangTidyCheck { public: FieldVisibilityCheck(StringRef name, ClangTidyContext* context) : ClangTidyCheck(name, context) { } private: void registerMatchers(ast_matchers::MatchFinder* finder) override { finder->addMatcher(fieldDecl(isPublic(), hasParent(cxxRecordDecl(isClass()))).bind("field"), this); } void check(ast_matchers::MatchFinder::MatchResult const& result) override { FieldDecl const& field = *result.Nodes.getNodeAs<FieldDecl const>("field"); diag(field.getLocStart(), "Class field should be private"); } };
  • 27. Пример 1: результат $ clang-tidy -checks="misc-field-visibility-check" ./test.cpp 1 warning generated. ./test.cpp:8:5: warning: Class field should be private [misc-field-visibility-check] int m_public; ^
  • 28. Пример 2 int Function(int a) { // ... a = something; // ... return a; } // style: mutable parameter
  • 29. Пример 2 struct Test { virtual int VirtualMethod(int a) = 0; int Method(int a, int const b, int& c, int* d) { a = b; return a; } };
  • 30. Пример 2: AST Dumping Test: CXXRecordDecl 0x46b1b20 <test.cpp:1:1, line:9:1> line:1:8 struct Test definition |-CXXRecordDecl 0x46b1c30 <col:1, col:8> col:8 implicit struct Test |-CXXMethodDecl 0x46b1d90 <line:3:5, col:32> col:9 VirtualMethod 'int (int)' | `-ParmVarDecl 0x46b1cd0 <col:23, col:27> col:27 a 'int' `-CXXMethodDecl 0x46b2140 <line:4:5, line:8:5> line:4:9 Method 'int (int, const int, int &, int *)' |-ParmVarDecl 0x46b1e50 <col:16, col:20> col:20 used a 'int' |-ParmVarDecl 0x46b1ec0 <col:23, col:33> col:33 used b 'const int' |-ParmVarDecl 0x46b1f60 <col:36, col:41> col:41 c 'int &' |-ParmVarDecl 0x46b2000 <col:44, col:49> col:49 d 'int *' `-CompoundStmt 0x46b2320 <line:5:5, line:8:5> |-BinaryOperator 0x46b22a0 <line:6:9, col:13> 'int' lvalue '=' | |-DeclRefExpr 0x46b2238 <col:9> 'int' lvalue ParmVar 0x46b1e50 'a' 'int' | `-ImplicitCastExpr 0x46b2288 <col:13> 'int' <LValueToRValue> | `-DeclRefExpr 0x46b2260 <col:13> 'const int' lvalue ParmVar 0x46b1ec0 'b' 'const int' `-ReturnStmt 0x46b2308 <line:7:9, col:16> `-ImplicitCastExpr 0x46b22f0 <col:16> 'int' <LValueToRValue> `-DeclRefExpr 0x46b22c8 <col:16> 'int' lvalue ParmVar 0x46b1e50 'a' 'int'
  • 31. Пример 2: реализация void ImmutableParamsCheck::registerMatchers(MatchFinder* finder) { finder->addMatcher( parmVarDecl( hasAncestor(functionDecl(hasBody(stmt()))), unless(anyOf( hasType(isConstQualified()), hasType(referenceType()), hasType(pointerType())))).bind("parameter"), this); } void ImmutableParamsCheck::check(MatchFinder::MatchResult const& result) { ParmVarDecl const& parameter = *result.Nodes.getNodeAs<ParmVarDecl const>("parameter"); SourceLocation const location = parameter.getSourceRange().getEnd(); diag(location, "Consider making constant") << FixItHint::CreateInsertion(location, "const "); }
  • 32. Пример 2: результат $ clang-tidy -checks="misc-immutable-parameters-check" -fix ./test.cpp 2 warnings generated. ./test.cpp:4:20: warning: Consider making constant [iaso-immutable-params] int Method(int a, int const b, int& c, int* d) ^ const ./test.cpp:4:20: note: FIX-IT applied suggested code changes int Method(int a, int const b, int& c, int* d) ^ clang-tidy applied 1 of 1 suggested fixes.
  • 33. Пример 2: результат struct Test { virtual int VirtualMethod(int a) = 0; int Method(int a, int const b, int& c, int* d) { a = b; return a; } };
  • 34. Пример 2: результат struct Test { virtual int VirtualMethod(int a) = 0; int Method(int const a, int const b, int& c, int* d) { a = b; return a; } };
  • 35. Пример 3 // cxxRecordDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$"))) class TestClass { public: // cxxMethodDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$"))) // parmVarDecl(unless(matchesName("::[a-z][a-zA-Z0-9]*$"))) void Method(int arg); private: // fieldDecl(unless(matchesName("::m_[a-z][a-zA-Z0-9]*$")), // hasParent(cxxRecordDecl(isClass()))) int m_field; }; struct TestStruct { // fieldDecl(unless(matchesName("::[A-Z][a-zA-Z0-9]*$")), // hasParent(cxxRecordDecl(isStruct()))) int Field; };
  • 36. Пример 3 // varDecl(hasLocalStorage(), unless(matchesName("::[a-z][a-zA-Z0-9]*$"))) int localVariable; // varDecl(hasGlobalStorage(), // unless(anyOf(matchesName("::s_[a-z][a-zA-Z0-9]*$"), hasType(isConstQualified())))) static int s_staticVariable; // varDecl(hasGlobalStorage(), // unless(anyOf(matchesName("::[A-Z][a-zA-Z0-9]*$"), unless(hasType(isConstQualified()))))) static int const Constant = 42;
  • 37. Пример 4 Можно ли бросать исключение из деструктора?
  • 38. Пример 4 class Test { public: ~Test() { throw Exception(); } }; // c++11: terminate
  • 39. Пример 4 class Test { public: ~Test() noexcept(true) { throw Exception(); } }; // c++11: terminate
  • 40. Пример 4 class Test { public: ~Test() noexcept(false) { throw Exception(); } };
  • 41. Пример 4 class Test { public: ~Test() noexcept(false) { throw Exception(); } }; int main() { std::unique_ptr<Test> test(new Test()); test.reset(); } // c++11: terminate
  • 42. Пример 4 class Parent { public: ~Parent() noexcept(false); }; class Child : public Parent { public: ~Child() { } }; int main() { std::unique_ptr<Child> test(new Child()); test.reset(); } // c++11: terminate
  • 43. Пример 4 class Parent { public: ~Parent() noexcept(false); }; class Child : public Parent { public: ~Child() noexcept(true) { } }; int main() { std::unique_ptr<Child> test(new Child()); test.reset(); } // c++11: terminate
  • 44. Пример 4 ● Не бросать исключения из деструкторов ● Обозначить бросающие деструкторы ‘noexcept(false)’ ● Не использовать ‘noexcept(true)’ для деструкторов
  • 45. Пример 4: реализация void ExplicitThrowSpecificationCheck::registerMatchers(MatchFinder* finder) { finder->addMatcher(cxxDestructorDecl().bind("destructor"), this); } void ExplicitThrowSpecificationCheck::check(MatchFinder::MatchResult const& result) { FunctionDecl const& declaration = *result.Nodes.getNodeAs<FunctionDecl>("destructor"); FunctionProtoType const& prototype = *declaration.getType()->getAs<FunctionProtoType>(); bool const destructorCanThrow = prototype.getNoexceptSpec(*result.Context) == FunctionProtoType::NR_Throw; bool const isSpecificationExplicit = declaration.getExceptionSpecSourceRange().isValid(); if (destructorCanThrow && !isSpecificationExplicit) { diag(declaration.getSourceRange().getEnd(), "This destructor should be marked with 'noexcept(false)'"); } if (!destructorCanThrow && isSpecificationExplicit) { diag(declaration.getSourceRange().getEnd(), "Do not mark destructor with 'noexcept(true)'"); } }
  • 46. Пример 4: результат class Parent { public: ~Parent() noexcept(false); }; class Child : public Parent { public: ~Child() noexcept(true) { } }; // do not use ‘noexept(true)’
  • 47. Пример 4: результат class Parent { public: ~Parent() noexcept(false); }; class Child : public Parent { public: ~Child() { } }; // can throw, mark with ‘noexcept(false)’
  • 48. Пример 4: результат class Parent { public: ~Parent() noexcept(false); }; class Child : public Parent { public: ~Child() noexcept(false) { } };
  • 49. Пример 4 void Function(); struct Object { Object(); bool operator<(Object const& right) const; }; struct Test { Test() { Object a, b; if (a < b) { Function(); } int* p = new int(42); } };
  • 50. Пример 4: реализация void ThrowFromDestructorCheck::registerMatchers(MatchFinder* finder) { finder->addMatcher(expr(hasAncestor(cxxDestructorDecl().bind("destructor"))).bind("expression"), this); } void ThrowFromDestructorCheck::check(MatchFinder::MatchResult const& result) { FunctionDecl const& declaration = *result.Nodes.getNodeAs<FunctionDecl>("destructor"); FunctionProtoType const& prototype = *declaration.getType()->getAs<FunctionProtoType>(); bool const destructorCanThrow = prototype.getNoexceptSpec(*result.Context) == FunctionProtoType::NR_Throw; if (destructorCanThrow) { return; } Expr const& expression = *result.Nodes.getNodeAs<Expr>("expression"); bool const expressionCanThrow = m_compiler->getSema().canThrow(&expression) != CT_Cannot; if (expressionCanThrow) { diag(expression.getExprLoc(), "Expression can throw exception"); } }
  • 51. Пример 4: результат void Function(); struct Object { Object(); bool operator<(Object const& right) const; }; struct Test { Test() { Object a, b; if (a < b) { Function(); } int* p = new int(42); } }; // can throw: constructor // can throw: operator < // can throw: Function call // can throw: operator new
  • 52. Пример 4: результат void Function() noexcept(true); struct Object { Object() noexcept(true); bool operator<(Object const& right) const noexcept(true); }; struct Test { Test() { Object a, b; if (a < b) { Function(); } } };
  • 54. Clang-tidy: итоги ● Простая реализация сложных проверок ● Автоматизация рутинных проверок ● Отличный способ лучше узнать C++