Clang MatchResult 没有绑定 AST 节点?
Clang MatchResult has no AST nodes bound?
我正在编写我的第一个 AST 匹配器来检测指针到整数的转换,但是 MatchResult
中的 BoundedNodes
的大小是 0。这怎么可能?为什么即使 MatchResult 为空,AST Matcher 也会调用我的回调?有没有可能一段代码匹配到某个Matcher而不作为节点出现在AST中?
这是我的全部代码:
class PtoICallback : public clang::ast_matchers::MatchFinder::MatchCallback {
clang::Rewriter rewriter;
public:
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult& result) override final {
llvm::outs() << result.Nodes.getMap().size() << " nodes matched\n";
}
};
int main(int argc, const char** argv) {
llvm::cl::OptionCategory findPtoICategory("find-ptoi options");
clang::tooling::CommonOptionsParser options(argc, argv, findPtoICategory);
clang::tooling::ClangTool tool(options.getCompilations(), options.getSourcePathList());
auto matcher = clang::ast_matchers::castExpr(clang::ast_matchers::hasCastKind(clang::CastKind::CK_PointerToIntegral));
PtoICallback callback;
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(matcher, &callback);
return tool.run(clang::tooling::newFrontendActionFactory(&finder).get());
}
这输出
0 nodes matched
在包含 1 个整数转换指针的文件上调用时:
#include <stdint.h>
int main() {
int i = 0;
intptr_t a = reinterpret_cast<intptr_t>(&i);
return 0;
}
同样,我不明白为什么会检测到匹配,但找不到节点?如果我转储上面代码的 AST,它会给出:
`-FunctionDecl 0x55765ad54520 <example.cpp:5:1, line:9:1> line:5:5 main 'int ()'
`-CompoundStmt 0x55765ad62010 <col:12, line:9:1>
|-DeclStmt 0x55765ad61e40 <line:6:5, col:14>
| `-VarDecl 0x55765ad54648 <col:5, col:13> col:9 used i 'int' cinit
| `-IntegerLiteral 0x55765ad61e20 <col:13> 'int' 0
|-DeclStmt 0x55765ad61fc8 <line:7:5, col:48>
| `-VarDecl 0x55765ad61e90 <col:5, col:47> col:14 a 'intptr_t':'long' cinit
| `-CXXReinterpretCastExpr 0x55765ad61f98 <col:18, col:47> 'intptr_t':'long' reinterpret_cast<intptr_t> <PointerToIntegral>
| `-UnaryOperator 0x55765ad61f48 <col:45, col:46> 'int *' prefix '&' cannot overflow
| `-DeclRefExpr 0x55765ad61ef8 <col:46> 'int' lvalue Var 0x55765ad54648 'i' 'int'
`-ReturnStmt 0x55765ad62000 <line:8:5, col:12>
`-IntegerLiteral 0x55765ad61fe0 <col:12> 'int' 0
所以我想 result.Nodes.getMap()
至少会产生 AST 转储中显示的 CXXReinterpretCastExpr
?然而它是空的。
找到了。显然你必须 bind
你的匹配器到一些字符串,否则它匹配的节点将不会出现在绑定节点中。这么说还挺有道理的,不过我也找了很久。
对于阅读本文的任何人,如果您在匹配器的末尾调用 bind
方法,您基本上可以指定一个由您定义的字符串,该字符串将标识您发现的匹配节点那个特定的匹配器。似乎没有通配符字符串之类的东西,这就是为什么如果您不将匹配器绑定到某些东西,它就不会将 AST 节点绑定到您的结果。
我认为这是一种区分匹配器的方法,如果多个匹配器要查找结果并且它们使用相同的回调并且 MatchResults 以某种方式包含同时匹配的多个节点?我还不太清楚匹配是如何工作的。它是否将多个 'matchings' 批处理在一起以避免调用 run()
太多?我不知道。对我来说,节点中一次总是只有一个条目。
我正在编写我的第一个 AST 匹配器来检测指针到整数的转换,但是 MatchResult
中的 BoundedNodes
的大小是 0。这怎么可能?为什么即使 MatchResult 为空,AST Matcher 也会调用我的回调?有没有可能一段代码匹配到某个Matcher而不作为节点出现在AST中?
这是我的全部代码:
class PtoICallback : public clang::ast_matchers::MatchFinder::MatchCallback {
clang::Rewriter rewriter;
public:
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult& result) override final {
llvm::outs() << result.Nodes.getMap().size() << " nodes matched\n";
}
};
int main(int argc, const char** argv) {
llvm::cl::OptionCategory findPtoICategory("find-ptoi options");
clang::tooling::CommonOptionsParser options(argc, argv, findPtoICategory);
clang::tooling::ClangTool tool(options.getCompilations(), options.getSourcePathList());
auto matcher = clang::ast_matchers::castExpr(clang::ast_matchers::hasCastKind(clang::CastKind::CK_PointerToIntegral));
PtoICallback callback;
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(matcher, &callback);
return tool.run(clang::tooling::newFrontendActionFactory(&finder).get());
}
这输出
0 nodes matched
在包含 1 个整数转换指针的文件上调用时:
#include <stdint.h>
int main() {
int i = 0;
intptr_t a = reinterpret_cast<intptr_t>(&i);
return 0;
}
同样,我不明白为什么会检测到匹配,但找不到节点?如果我转储上面代码的 AST,它会给出:
`-FunctionDecl 0x55765ad54520 <example.cpp:5:1, line:9:1> line:5:5 main 'int ()'
`-CompoundStmt 0x55765ad62010 <col:12, line:9:1>
|-DeclStmt 0x55765ad61e40 <line:6:5, col:14>
| `-VarDecl 0x55765ad54648 <col:5, col:13> col:9 used i 'int' cinit
| `-IntegerLiteral 0x55765ad61e20 <col:13> 'int' 0
|-DeclStmt 0x55765ad61fc8 <line:7:5, col:48>
| `-VarDecl 0x55765ad61e90 <col:5, col:47> col:14 a 'intptr_t':'long' cinit
| `-CXXReinterpretCastExpr 0x55765ad61f98 <col:18, col:47> 'intptr_t':'long' reinterpret_cast<intptr_t> <PointerToIntegral>
| `-UnaryOperator 0x55765ad61f48 <col:45, col:46> 'int *' prefix '&' cannot overflow
| `-DeclRefExpr 0x55765ad61ef8 <col:46> 'int' lvalue Var 0x55765ad54648 'i' 'int'
`-ReturnStmt 0x55765ad62000 <line:8:5, col:12>
`-IntegerLiteral 0x55765ad61fe0 <col:12> 'int' 0
所以我想 result.Nodes.getMap()
至少会产生 AST 转储中显示的 CXXReinterpretCastExpr
?然而它是空的。
找到了。显然你必须 bind
你的匹配器到一些字符串,否则它匹配的节点将不会出现在绑定节点中。这么说还挺有道理的,不过我也找了很久。
对于阅读本文的任何人,如果您在匹配器的末尾调用 bind
方法,您基本上可以指定一个由您定义的字符串,该字符串将标识您发现的匹配节点那个特定的匹配器。似乎没有通配符字符串之类的东西,这就是为什么如果您不将匹配器绑定到某些东西,它就不会将 AST 节点绑定到您的结果。
我认为这是一种区分匹配器的方法,如果多个匹配器要查找结果并且它们使用相同的回调并且 MatchResults 以某种方式包含同时匹配的多个节点?我还不太清楚匹配是如何工作的。它是否将多个 'matchings' 批处理在一起以避免调用 run()
太多?我不知道。对我来说,节点中一次总是只有一个条目。