LibTooling简介

LibTooling简介

环境clang版本为8.0.0,Visual Studio 2019

参数解析

使用clang解析C++文件需要传入编译参数,llvm提供类CommonOptionsParser,可以添加自定义解析规则

1
CommonOptionsParser parser(argc, argv, GeneralCategory);

ClangTool

ClangTool获得解析后的参数即可分析文件

1
ClangTool tool(parser.getCompilations(), parser.getSourcePathList());

FrontendAction与ASTConsumer

FrontendAction创建一个ASTConsumer,编译过程触发的事件通过重写ASTConsumer的虚函数可以进行处理,其中HandleTranslationUnit在每一个单元编译完成后调用,HandleTranslationUnit函数参数为ASTContext(可以看作AST树),RecursiveASTVisitor可以遍历ASTContext,完成AST树的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor>
{
public:
ExampleVisitor(SourceManager& pSM) :
_source_manager(pSM) {
}
bool VisitCXXRecordDecl(CXXRecordDecl* pDecl) {
if (_source_manager.isInMainFile(pDecl->getLocation())) {
_class_name.emplace_back(pDecl->getName());
if (pDecl->isTemplateDecl())
std::cout << "template ";
std::cout << pDecl->getNameAsString() << std::endl;
}
return true;
}
bool VisitCXXMethodDecl(CXXMethodDecl* pDecl) {
if (_source_manager.isInMainFile(pDecl->getLocation()))
std::cout << pDecl->getNameAsString() << std::endl;
return true;
}
bool TraverseNamespaceDecl(NamespaceDecl* pDecl) {
if (_source_manager.isInMainFile(pDecl->getLocation())) {
std::cout << pDecl->getNameAsString() << " Start" << std::endl;
RecursiveASTVisitor::TraverseNamespaceDecl(pDecl);
std::cout << pDecl->getNameAsString() << " End" << std::endl;
}
return true;
}
std::vector<std::string> _class_name;
SourceManager& _source_manager;
};

class ExampleConsumer : public ASTConsumer
{
public:
ExampleConsumer(SourceManager& pSM) :
_visitor(pSM) {
}
void HandleTranslationUnit(ASTContext& pContext) override {
_visitor.TraverseDecl(pContext.getTranslationUnitDecl());
}
private:
ExampleVisitor _visitor;
};

class ExampleAction : public ASTFrontendAction
{
public:
std::unique_ptr<ASTConsumer> CreateASTConsumer(
CompilerInstance& pCompiler, StringRef pFile) override {
return std::unique_ptr<ASTConsumer>(new ExampleConsumer(pCompiler.getSourceManager()));
}
};

RecursiveASTVisitor

VisitCXXMethodDecl在遍历到类的成员方法时调用,Visit后可以跟节点名称

TraverseNamespaceDecl遍历该节点时调用,Traverse后可以跟节点名称,可以跳过某些类型节点

SourceManager

可以找到节点对应源文件的位置

运行FrontendAction

1
tool.run(newFrontendActionFactory<ExampleAction>().get());

MatchFinder

当只需要查询某些节点,可以使用clang提供的MatchFinder类,则不需要自己去创建ASTConsumer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Printer : public MatchFinder::MatchCallback
{
void run(const MatchFinder::MatchResult& pRes) {
auto node = pRes.Nodes.getNodeAs<CXXRecordDecl>("");
if (node &&
pRes.SourceManager->isInMainFile(node->getLocation()) &&
!node->isImplicit()) {
std::cout << node->getName().str() << std::endl;
}
}
};

MatchFinder finder;
Printer printer;
finder.addMatcher(cxxRecordDecl().bind(""), &printer);
tool.run(newFrontendActionFactory(&finder).get());

附录

查看AST树

1
clang++ -Xclang -ast-dump main.cpp

ASTMatcher和AST结点文档

https://clang.llvm.org/docs/LibASTMatchersReference.html

引入

头文件

1
2
3
4
5
6
7
8
9
10
11
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/CompilerInstance.h>
using namespace clang::tooling;
using namespace clang;
using namespace clang::ast_matchers;
using namespace llvm;
using namespace llvm::cl;

库文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
clangAST.lib
clangBasic.lib
clangFrontend.lib
clangIndex.lib
clangLex.lib
clangSema.lib
clangSerialization.lib
clangTooling.lib
clangARCMigrate.lib
LLVMAArch64CodeGen.lib
LLVMAArch64AsmParser.lib
LLVMAArch64AsmPrinter.lib
LLVMAArch64Desc.lib
LLVMAArch64Disassembler.lib
LLVMAArch64Info.lib
LLVMAArch64Utils.lib
LLVMAMDGPUCodeGen.lib
LLVMAMDGPUAsmParser.lib
LLVMAMDGPUAsmPrinter.lib
LLVMAMDGPUDesc.lib
LLVMAMDGPUDisassembler.lib
LLVMAMDGPUInfo.lib
LLVMAMDGPUUtils.lib
LLVMARMCodeGen.lib
LLVMARMAsmParser.lib
LLVMARMAsmPrinter.lib
LLVMARMDesc.lib
LLVMARMDisassembler.lib
LLVMARMInfo.lib
LLVMARMUtils.lib
LLVMBPFCodeGen.lib
LLVMBPFAsmParser.lib
LLVMBPFAsmPrinter.lib
LLVMBPFDesc.lib
LLVMBPFDisassembler.lib
LLVMBPFInfo.lib
LLVMHexagonCodeGen.lib
LLVMHexagonAsmParser.lib
LLVMHexagonDesc.lib
LLVMHexagonDisassembler.lib
LLVMHexagonInfo.lib
LLVMLanaiCodeGen.lib
LLVMLanaiAsmParser.lib
LLVMLanaiAsmPrinter.lib
LLVMLanaiDesc.lib
LLVMLanaiDisassembler.lib
LLVMLanaiInfo.lib
LLVMMipsCodeGen.lib
LLVMMipsAsmParser.lib
LLVMMipsAsmPrinter.lib
LLVMMipsDesc.lib
LLVMMipsDisassembler.lib
LLVMMipsInfo.lib
LLVMMSP430CodeGen.lib
LLVMMSP430AsmParser.lib
LLVMMSP430AsmPrinter.lib
LLVMMSP430Desc.lib
LLVMMSP430Disassembler.lib
LLVMMSP430Info.lib
LLVMNVPTXCodeGen.lib
LLVMNVPTXAsmPrinter.lib
LLVMNVPTXDesc.lib
LLVMNVPTXInfo.lib
LLVMPowerPCCodeGen.lib
LLVMPowerPCAsmParser.lib
LLVMPowerPCAsmPrinter.lib
LLVMPowerPCDesc.lib
LLVMPowerPCDisassembler.lib
LLVMPowerPCInfo.lib
LLVMSparcCodeGen.lib
LLVMSparcAsmParser.lib
LLVMSparcAsmPrinter.lib
LLVMSparcDesc.lib
LLVMSparcDisassembler.lib
LLVMSparcInfo.lib
LLVMSystemZCodeGen.lib
LLVMSystemZAsmParser.lib
LLVMSystemZAsmPrinter.lib
LLVMSystemZDesc.lib
LLVMSystemZDisassembler.lib
LLVMSystemZInfo.lib
LLVMWebAssemblyCodeGen.lib
LLVMWebAssemblyAsmParser.lib
LLVMWebAssemblyAsmPrinter.lib
LLVMWebAssemblyDesc.lib
LLVMWebAssemblyDisassembler.lib
LLVMWebAssemblyInfo.lib
LLVMX86CodeGen.lib
LLVMX86AsmParser.lib
LLVMX86AsmPrinter.lib
LLVMX86Desc.lib
LLVMX86Disassembler.lib
LLVMX86Info.lib
LLVMX86Utils.lib
LLVMXCoreCodeGen.lib
LLVMXCoreAsmPrinter.lib
LLVMXCoreDesc.lib
LLVMXCoreDisassembler.lib
LLVMXCoreInfo.lib
LLVMCore.lib
LLVMSupport.lib
clangStaticAnalyzerCheckers.lib
clangStaticAnalyzerCore.lib
clangCrossTU.lib
clangDriver.lib
version.lib
clangParse.lib
LLVMOption.lib
clangEdit.lib
clangAnalysis.lib
clangASTMatchers.lib
clangFormat.lib
clangToolingInclusions.lib
clangToolingCore.lib
clangRewrite.lib
LLVMipo.lib
LLVMVectorize.lib
LLVMIRReader.lib
LLVMAsmParser.lib
LLVMInstrumentation.lib
LLVMLinker.lib
LLVMGlobalISel.lib
LLVMAsmPrinter.lib
LLVMSelectionDAG.lib
LLVMCodeGen.lib
LLVMScalarOpts.lib
LLVMAggressiveInstCombine.lib
LLVMInstCombine.lib
LLVMBitWriter.lib
LLVMTarget.lib
LLVMTransformUtils.lib
LLVMAnalysis.lib
LLVMProfileData.lib
LLVMObject.lib
LLVMBitReader.lib
LLVMMCParser.lib
LLVMMCDisassembler.lib
LLVMMC.lib
LLVMBinaryFormat.lib
LLVMDebugInfoCodeView.lib
LLVMDebugInfoMSF.lib
psapi.lib
uuid.lib
advapi32.lib
delayimp.lib
LLVMDemangle.lib
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
oleaut32.lib
comdlg32.lib