1.clang-query 文件目录 -p json文件目录(用于调用clang-query 工具对匹配器语法进行验证)
2.match functionDecl(isExpansionInMainFile())(用于匹配主文件中的函数节点)
3. 匹配器的工作步骤
3.1 通过匹配表达式描述一项具体任务中感兴趣的抽象语法树
3.2 匹配器匹配到抽象语法树具体节点并将节点绑定到指定字符串上
3.3 在回调函数中对匹配到的节点进行处理
3.4 示例:functionDecl(hasName("test_checkWhileLoopCondition")).bind("funcDecl")将匹配的functionDecl节点绑定到字符串“funcDecl”
4. AST匹配器的类型
节点匹配器:匹配特定节点
eg: objcPropertyDecl() :匹配 OC 属性声明节点(如@interface Foo)
缩小匹配器:匹配具有相应属性的节点
eg: hasName():用于匹配具有指定名称的节点
hasAttr():匹配具有指定属性的节点
遍历匹配器:允许在节点之间递归匹配
eg:hasAncestor():匹配祖先节点
hasDescendant():匹配后代节点
5.遍历模式
当使用 C++ API 时,例如在 clang-tidy 检查中,traverse() 匹配器用于设置模式:
Finder->addMatcher(traverse(TK_IgnoreUnlessSpelledInSource,returnStmt(hasReturnArgument(integerLiteral(equals(0))))), this);
6.节点匹配器
节点匹配器是匹配器表达式的核心——它们指定预期的节点类型。每个匹配表达式都以一个节点匹配器开始,然后可以使用缩小或遍历匹配器进一步细化。
为方便起见,所有节点匹配器都采用任意数量的参数并隐式充当 allOf 匹配器。
节点匹配器是唯一支持bind(“id”)调用的匹配器,用于将匹配的节点绑定到给定的字符串,稍后将从匹配回调中检索。
7.缩小匹配器
缩小匹配器匹配当前节点上的某些属性,从而缩小要匹配的当前类型的节点集。
有特殊的逻辑缩小匹配器(allOf、anyOf、anything 和unless)允许用户创建更强大的匹配表达式
8.遍历匹配器
遍历匹配器指定与当前节点可达的其他节点的关系。
注意,有特殊的遍历匹配器(has、hasDescendant、forEach 和 forEachDescendant)适用于所有节点,并允许用户编写更通用的匹配表达式。
m decl(has(functionDecl(hasName("test_FloatEqualChecker"))))
9.举例说明
recordDecl(hasName("Foo"), isDerivedFrom("Bar"))
recordDecl 、hasName 、isDerivedFrom都属于 clang matcher 提供给我们的功能函数。
recordDecl用来匹配类、结构体、联合体声明的节点
hasName 可以知道它是用来匹配具有指定名称的节点
isDerivedFrom(xxx) 是匹配从 xxx 派生的类
缩小定位的方位,匹配所有类、结构体、联合体声明的节点中名称为 Foo 的节点且必须是从 Bar 派生出来的节点
recordDecl(anyOf(hasName("Foo"), isDerivedFrom("Bar")))
allOf(A, B) 标识 A 与 B 要同时成立才可以(类似 & )
unless(A) 匹配 A 不成立的节点(类似 ! )
anyOf(A,B) 标识A与B任一成立即可 (类似 or)
10.实际截图
// 基类 class Animal { // eat() 函数 // sleep() 函数 };
//派生类 class Dog : public Animal { // bark() 函数 };
m cxxRecordDecl()
m cxxRecordDecl(hasName("Dog"))
m cxxRecordDecl(allOf(hasName("Dog"), isDerivedFrom("Animal")))
11.其他语句
首先将程序代码设置如下
使用m functionDecl(isMain())语句进行匹配,结果如下
随后将程序更改为
调用m decl(has(functionDecl(hasName("test_FloatEqualChecker"))))对程序进行检测
将程序修改为
使用m binaryOperator(hasOperatorName("=="))进行匹配