如何为 AST 匹配器设置 LangOptions(bool vs _Bool)
How to set LangOptions for AST Matcher (bool vs _Bool)
有什么方法可以为 AST 匹配器设置 LangOptions 吗?我们有以下匹配器:
using namespace clang;
using namespace clang::ast_matchers;
static llvm::cl::OptionCategory OptionCategory("options");
class CMatcherCallback : public MatchFinder::MatchCallback
{
public:
virtual void run(const MatchFinder::MatchResult& result) override
{
if (const CXXMethodDecl* method = result.Nodes.getNodeAs<CXXMethodDecl>("id"))
{
method->dumpColor();
}
}
};
int main(int argc, const char** argv)
{
tooling::CommonOptionsParser optionsParser(argc, argv, OptionCategory);
tooling::ClangTool tool(optionsParser.getCompilations(),
optionsParser.getSourcePathList());
CMatcherCallback callback;
MatchFinder finder;
finder.addMatcher(cxxMethodDecl(
hasName("Method"),
hasParameter(0, parmVarDecl(hasType(asString("bool")))))
.bind("id"),
&callback);
int ret = tool.run(tooling::newFrontendActionFactory(&finder).get());
return ret;
}
不符合此方法:
class CTest
{
void Method(bool);
};
当我们从 hasParameter(0, parmVarDecl(hasType(asString("bool")))))
更改类型时它确实匹配
至 _Bool
。所以匹配器似乎是 C 而不是 C++ 模式?
回答实际问题
这个答案不会解决原来的问题(下面的解释),但是解决了问题中陈述的问题。如果有人会搜索设置选项的方法,这可能会有用。
using namespace clang;
using namespace clang::ast_matchers;
static llvm::cl::OptionCategory OptionCategory("options");
class CMatcherCallback : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &result) override {
if (const CXXMethodDecl *method =
result.Nodes.getNodeAs<CXXMethodDecl>("id")) {
method->dumpColor();
}
}
};
class FinderFrontendAction : public clang::ASTFrontendAction {
public:
FinderFrontendAction() {
Finder.addMatcher(
cxxMethodDecl(hasName("Method"),
hasParameter(0, parmVarDecl(hasType(asString("bool")))))
.bind("id"),
&Callback);
}
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override {
auto &LO = CI.getLangOpts();
LO.CPlusPlus = true;
LO.Bool = true; // this is the actual option you are interested in
return Finder.newASTConsumer();
}
private:
MatchFinder Finder;
CMatcherCallback Callback;
};
int main(int argc, const char **argv) {
tooling::CommonOptionsParser optionsParser(argc, argv, OptionCategory);
tooling::ClangTool tool(optionsParser.getCompilations(),
optionsParser.getSourcePathList());
int ret =
tool.run(tooling::newFrontendActionFactory<FinderFrontendAction>().get());
return ret;
}
为什么它不会改变结果
Clang 知道这是一个 C++ 代码并且它自己有 bool
类型。所以这段代码实际上没有任何改变。你可以看到当你打印 AST 时,它实际上打印了 bool
.
那么_Bool从何而来
这是asString
匹配器如何实现的问题。它使用 QualType::getAsString() method (without parameters). Parametrized version of this function accepts PrintingPolicy,它定义了不同类型应该如何打印出来。
LangOpts
定义某些类型的打印方式,因为 PrintingPolicy
是从它构造的,但当您在没有打印策略的情况下调用 QualType::getAsString
时则不会。它使用默认的 LangOpts
构造函数并且 bool
变为 "_Bool"
.
建议的解决方案
处理一下就用"_Bool"
。否则你可以实现你自己的匹配器来克服这个缺点。
我希望这能回答您的问题!
毕竟自定义 AST 匹配器很简单,感谢 Valeriy 指出。
namespace my_matchers
{
AST_MATCHER_P2(QualType, asString, std::string, Name, PrintingPolicy, PP)
{
return Name == Node.getAsString(PP);
}
}
...
PrintingPolicy printingPolicy(LangOptions{});
printingPolicy.Bool = 1;
...
hasParameter(0, parmVarDecl(hasType(my_matchers::asString("bool", printingPolicy))))
有什么方法可以为 AST 匹配器设置 LangOptions 吗?我们有以下匹配器:
using namespace clang;
using namespace clang::ast_matchers;
static llvm::cl::OptionCategory OptionCategory("options");
class CMatcherCallback : public MatchFinder::MatchCallback
{
public:
virtual void run(const MatchFinder::MatchResult& result) override
{
if (const CXXMethodDecl* method = result.Nodes.getNodeAs<CXXMethodDecl>("id"))
{
method->dumpColor();
}
}
};
int main(int argc, const char** argv)
{
tooling::CommonOptionsParser optionsParser(argc, argv, OptionCategory);
tooling::ClangTool tool(optionsParser.getCompilations(),
optionsParser.getSourcePathList());
CMatcherCallback callback;
MatchFinder finder;
finder.addMatcher(cxxMethodDecl(
hasName("Method"),
hasParameter(0, parmVarDecl(hasType(asString("bool")))))
.bind("id"),
&callback);
int ret = tool.run(tooling::newFrontendActionFactory(&finder).get());
return ret;
}
不符合此方法:
class CTest
{
void Method(bool);
};
当我们从 hasParameter(0, parmVarDecl(hasType(asString("bool")))))
更改类型时它确实匹配
至 _Bool
。所以匹配器似乎是 C 而不是 C++ 模式?
回答实际问题
这个答案不会解决原来的问题(下面的解释),但是解决了问题中陈述的问题。如果有人会搜索设置选项的方法,这可能会有用。
using namespace clang;
using namespace clang::ast_matchers;
static llvm::cl::OptionCategory OptionCategory("options");
class CMatcherCallback : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &result) override {
if (const CXXMethodDecl *method =
result.Nodes.getNodeAs<CXXMethodDecl>("id")) {
method->dumpColor();
}
}
};
class FinderFrontendAction : public clang::ASTFrontendAction {
public:
FinderFrontendAction() {
Finder.addMatcher(
cxxMethodDecl(hasName("Method"),
hasParameter(0, parmVarDecl(hasType(asString("bool")))))
.bind("id"),
&Callback);
}
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef) override {
auto &LO = CI.getLangOpts();
LO.CPlusPlus = true;
LO.Bool = true; // this is the actual option you are interested in
return Finder.newASTConsumer();
}
private:
MatchFinder Finder;
CMatcherCallback Callback;
};
int main(int argc, const char **argv) {
tooling::CommonOptionsParser optionsParser(argc, argv, OptionCategory);
tooling::ClangTool tool(optionsParser.getCompilations(),
optionsParser.getSourcePathList());
int ret =
tool.run(tooling::newFrontendActionFactory<FinderFrontendAction>().get());
return ret;
}
为什么它不会改变结果
Clang 知道这是一个 C++ 代码并且它自己有 bool
类型。所以这段代码实际上没有任何改变。你可以看到当你打印 AST 时,它实际上打印了 bool
.
那么_Bool从何而来
这是asString
匹配器如何实现的问题。它使用 QualType::getAsString() method (without parameters). Parametrized version of this function accepts PrintingPolicy,它定义了不同类型应该如何打印出来。
LangOpts
定义某些类型的打印方式,因为 PrintingPolicy
是从它构造的,但当您在没有打印策略的情况下调用 QualType::getAsString
时则不会。它使用默认的 LangOpts
构造函数并且 bool
变为 "_Bool"
.
建议的解决方案
处理一下就用"_Bool"
。否则你可以实现你自己的匹配器来克服这个缺点。
我希望这能回答您的问题!
毕竟自定义 AST 匹配器很简单,感谢 Valeriy 指出。
namespace my_matchers
{
AST_MATCHER_P2(QualType, asString, std::string, Name, PrintingPolicy, PP)
{
return Name == Node.getAsString(PP);
}
}
...
PrintingPolicy printingPolicy(LangOptions{});
printingPolicy.Bool = 1;
...
hasParameter(0, parmVarDecl(hasType(my_matchers::asString("bool", printingPolicy))))