如何为 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))))