Is there any way how to setup LangOptions for AST matcher? We have following matcher:
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;
}
It doesn't match this method:
class CTest
{
void Method(bool);
};
It does match when we change type from hasParameter(0, parmVarDecl(hasType(asString("bool")))))
to _Bool
. So it seems matcher is in C instead of C++ mode?
This answer won't solve the original problem (explanation below), but solves the problem stated in the question. It might be useful if someone will search for a way to set the options.
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 understands that this is a C++ code and that it has bool
type on its own. So this code literally changes nothing. You can see that when you print the AST, it actually prints bool
.
This is a problem of how asString
matcher is implemented. It uses QualType::getAsString() method (without parameters). Parametrized version of this function accepts PrintingPolicy, which defines how different types should be printed out.
LangOpts
define the way certain types are printed because PrintingPolicy
is constructed from it, but not when you call QualType::getAsString
without a printing policy. It uses default LangOpts
constructor and bool
becomes "_Bool"
.
Just deal with it and use "_Bool"
. Otherwise you can implement your own matcher that combats this shortcoming.
I hope this answers your question!