SlideShare a Scribd company logo
1 of 56
Download to read offline
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

More Related Content

What's hot

JUDCon London 2011 - Bin packing with drools planner by example
JUDCon London 2011 - Bin packing with drools planner by exampleJUDCon London 2011 - Bin packing with drools planner by example
JUDCon London 2011 - Bin packing with drools planner by exampleGeoffrey De Smet
 
Generic programming and concepts that should be in C++
Generic programming and concepts that should be in C++Generic programming and concepts that should be in C++
Generic programming and concepts that should be in C++Anton Kolotaev
 
Stl Containers
Stl ContainersStl Containers
Stl Containersppd1961
 
Windows kernel basic exploit
Windows kernel basic exploitWindows kernel basic exploit
Windows kernel basic exploitKyoungseok Yang
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Takashi Hoshino
 
Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Sumant Tambe
 
Object-Oriented Programming in Java.pdf
Object-Oriented Programming in Java.pdfObject-Oriented Programming in Java.pdf
Object-Oriented Programming in Java.pdfBharath Choudhary
 
C standard library functions
C standard library functionsC standard library functions
C standard library functionsVaishnavee Sharma
 
Muduo network library
Muduo network libraryMuduo network library
Muduo network libraryShuo Chen
 
Stream classes in C++
Stream classes in C++Stream classes in C++
Stream classes in C++Shyam Gupta
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorJussi Pohjolainen
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Sameer Rathoud
 

What's hot (20)

File handling-c
File handling-cFile handling-c
File handling-c
 
Arrays in java
Arrays in javaArrays in java
Arrays in java
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
JUDCon London 2011 - Bin packing with drools planner by example
JUDCon London 2011 - Bin packing with drools planner by exampleJUDCon London 2011 - Bin packing with drools planner by example
JUDCon London 2011 - Bin packing with drools planner by example
 
Emcpp0506
Emcpp0506Emcpp0506
Emcpp0506
 
Generic programming and concepts that should be in C++
Generic programming and concepts that should be in C++Generic programming and concepts that should be in C++
Generic programming and concepts that should be in C++
 
Stl Containers
Stl ContainersStl Containers
Stl Containers
 
Windows kernel basic exploit
Windows kernel basic exploitWindows kernel basic exploit
Windows kernel basic exploit
 
C++ programming function
C++ programming functionC++ programming function
C++ programming function
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4
 
Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)
 
Object-Oriented Programming in Java.pdf
Object-Oriented Programming in Java.pdfObject-Oriented Programming in Java.pdf
Object-Oriented Programming in Java.pdf
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
C standard library functions
C standard library functionsC standard library functions
C standard library functions
 
Muduo network library
Muduo network libraryMuduo network library
Muduo network library
 
Wrapper class
Wrapper classWrapper class
Wrapper class
 
Stream classes in C++
Stream classes in C++Stream classes in C++
Stream classes in C++
 
1 puc programming using c++
1 puc programming using c++1 puc programming using c++
1 puc programming using c++
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operator
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())
 

Similar to 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
 

Similar to 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
 

Recently uploaded

COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptxJIT KUMAR GUPTA
 
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...SUHANI PANDEY
 
KubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlyKubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlysanyuktamishra911
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaOmar Fathy
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Bookingdharasingh5698
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxJuliansyahHarahap1
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptNANDHAKUMARA10
 
A Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityA Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityMorshed Ahmed Rahath
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . pptDineshKumar4165
 
Unit 2- Effective stress & Permeability.pdf
Unit 2- Effective stress & Permeability.pdfUnit 2- Effective stress & Permeability.pdf
Unit 2- Effective stress & Permeability.pdfRagavanV2
 
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoorTop Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoordharasingh5698
 
Design For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startDesign For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startQuintin Balsdon
 
22-prompt engineering noted slide shown.pdf
22-prompt engineering noted slide shown.pdf22-prompt engineering noted slide shown.pdf
22-prompt engineering noted slide shown.pdf203318pmpc
 
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756dollysharma2066
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfJiananWang21
 

Recently uploaded (20)

Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
 
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
 
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
 
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
 
KubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlyKubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghly
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS Lambda
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptx
 
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.ppt
 
A Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityA Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna Municipality
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 
Unit 2- Effective stress & Permeability.pdf
Unit 2- Effective stress & Permeability.pdfUnit 2- Effective stress & Permeability.pdf
Unit 2- Effective stress & Permeability.pdf
 
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoorTop Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
 
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
 
Design For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startDesign For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the start
 
22-prompt engineering noted slide shown.pdf
22-prompt engineering noted slide shown.pdf22-prompt engineering noted slide shown.pdf
22-prompt engineering noted slide shown.pdf
 
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 

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