Appearance
Core Classes
Decl 声明系列
- CXXRecordDecl 类,struct
- VarDecl
- UnresolvedUsingTypenameDecl
cpp
template \ class A : public Base {
using typename Base ::foo;
};
Stmt
- CompoundStmt
- CXXTryStmt
- BinaryOperator
Type
- PointerType
- ParentType
- SubstTemplateTypeParmType
Glue Classes
DeclContext
TemplateArgument
NestedNameSpecifier
QualType Qualifier
- 比如
const int x
中的const
- 比如
IfStmt: getThen,getElse,getCond
CXXRecordDecl:
- getDescribedClassTemplate
Type: getAsCXXRecordDecl
Type 也很复杂
cpp
int x;
const int x;
int * const * x;
Location
SourceLocation 只有一个ID字段,因为真正的Location是被SourceManager管理的,避免重复.
Call Expressions
PointerTypeLoc返回的是int*的loc
PointerTypeLoc.getPointeeLoc返回的是int的loc
loc to Text?
- makeFileCharRange
- measureTokenLength
Template tree transformations
说的就是c++中的模板
- Nodes are shared 这点很关键
RecuisiveASTVisitor
- Trigger on Types you are care about
- Knows all the connections
- Does not give you context information
AST Matcher
- Trigger on Expressions
- Bind Context
- Get all context inside a callback
dump ast:
bash
clang-check ClangTidyToolMain.cpp --ast-dump
即使编译不过去,也可以生成ast的,只要语法正确.
比如: 注释了iostream,cstdlib,vector,编译是肯定会失败的.
cpp
//===--- tools/extra/clang-tidy/ClangTidyToolMain.cpp - Clang tidy tool ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file This file contains clang-tidy tool entry point main function.
///
/// This tool uses the Clang Tooling infrastructure, see
/// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
/// for details on setting it up with LLVM source tree.
///
//===----------------------------------------------------------------------===//
#include "ClangTidyMainxx.h"
//#include <iostream>
//#include <cstdlib>
//#include <vector>
extern char **environ; // 引入全局变量environ
using namespace std;
static void testPrintEnv() {
char **env = environ; // 将environ保存到env指针中
vector <string> envs;
while (*env != nullptr) { // 遍历环境变量
// std::cout << *env << std::endl; // 打印环境变量
envs.push_back(*env);
env++; // 移动指针
}
std::sort(envs.begin(), envs.end());
for (auto &env: envs) {
std::cout << env << std::endl;
}
}
int main(int argc, const char **argv) {
testPrintEnv();
return clang::tidy::clangTidyMain(argc, argv);
}
ast
TranslationUnitDecl 0x7fc67184a808 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7fc67184b070 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7fc67184add0 '__int128'
|-TypedefDecl 0x7fc67184b0e0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7fc67184adf0 'unsigned __int128'
|-TypedefDecl 0x7fc67184b458 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag'
| `-RecordType 0x7fc67184b1d0 '__NSConstantString_tag'
| `-CXXRecord 0x7fc67184b138 '__NSConstantString_tag'
|-TypedefDecl 0x7fc67184b4f0 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7fc67184b4b0 'char *'
| `-BuiltinType 0x7fc67184a8b0 'char'
|-TypedefDecl 0x7fc67188be58 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag[1]'
| `-ConstantArrayType 0x7fc67188be00 '__va_list_tag[1]' 1
| `-RecordType 0x7fc67184b5e0 '__va_list_tag'
| `-CXXRecord 0x7fc67184b548 '__va_list_tag'
|-VarDecl 0x7fc67188bf20 </Volumes/dev/tmp/clang-tidy-standalone/tool/ClangTidyToolMain.cpp:22:1, col:15> col:15 used environ 'char **' extern
|-UsingDirectiveDecl 0x7fc67188c040 <line:23:1, col:17> col:17 Namespace 0x7fc67188bfd0 'std'
|-FunctionDecl 0x7fc67188c0e8 <line:25:1, line:37:1> line:25:13 used testPrintEnv 'void ()' static
| `-CompoundStmt 0x7fc67188c5b0 <col:28, line:37:1>
| |-DeclStmt 0x7fc67188c240 <line:26:5, col:25>
| | `-VarDecl 0x7fc67188c1a0 <col:5, col:18> col:12 used env 'char **' cinit
| | `-ImplicitCastExpr 0x7fc67188c228 <col:18> 'char **' <LValueToRValue>
| | `-DeclRefExpr 0x7fc67188c208 <col:18> 'char **' lvalue Var 0x7fc67188bf20 'environ' 'char **'
| |-DeclStmt 0x7fc67188c2f8 <line:27:5, col:25>
| | `-VarDecl 0x7fc67188c290 <col:5, col:21> col:21 invalid envs 'int'
| `-WhileStmt 0x7fc67188c460 <line:28:5, line:32:5>
| |-BinaryOperator 0x7fc67188c3a0 <line:28:12, col:20> 'bool' '!='
| | |-ImplicitCastExpr 0x7fc67188c370 <col:12, col:13> 'char *' <LValueToRValue>
| | | `-UnaryOperator 0x7fc67188c348 <col:12, col:13> 'char *' lvalue prefix '*' cannot overflow
| | | `-ImplicitCastExpr 0x7fc67188c330 <col:13> 'char **' <LValueToRValue>
| | | `-DeclRefExpr 0x7fc67188c310 <col:13> 'char **' lvalue Var 0x7fc67188c1a0 'env' 'char **'
| | `-ImplicitCastExpr 0x7fc67188c388 <col:20> 'char *' <NullToPointer>
| | `-CXXNullPtrLiteralExpr 0x7fc67188c360 <col:20> 'std::nullptr_t'
| `-CompoundStmt 0x7fc67188c448 <col:29, line:32:5>
| `-UnaryOperator 0x7fc67188c430 <line:31:9, col:12> 'char **' postfix '++'
| `-DeclRefExpr 0x7fc67188c410 <col:9> 'char **' lvalue Var 0x7fc67188c1a0 'env' 'char **'
`-FunctionDecl 0x7fc67188c780 <line:39:1, line:42:1> line:39:5 main 'int (int, const char **)'
|-ParmVarDecl 0x7fc67188c5f0 <col:10, col:14> col:14 used argc 'int'
|-ParmVarDecl 0x7fc67188c6a0 <col:20, col:33> col:33 used argv 'const char **'
`-CompoundStmt 0x7fc67188c940 <col:39, line:42:1>
`-CallExpr 0x7fc67188c8e0 <line:40:5, col:18> 'void'
`-ImplicitCastExpr 0x7fc67188c8c8 <col:5> 'void (*)()' <FunctionToPointerDecay>
`-DeclRefExpr 0x7fc67188c878 <col:5> 'void ()' lvalue Function 0x7fc67188c0e8 'testPrintEnv' 'void ()'
如何修改源代码
简单的是Fix,
用Replacement