9

我正在编写一个 libtooling 重构工具。我有一个类,比方说Foo,定义在一个名为foo.h. 我想看看是否foo.h包含在文件中。目前,要检查是否bar.cc包含foo.h,我只是使用recordDecl(hasName("Foo")). 这是有效的,因为在预处理class Foo { ... };后将存在于bar.cc的 AST 中,如果bar.cc包括foo.h.

bar.cc但是,例如,如果包含cat.hwhich includes ,这将不起作用foo.h。我想bar.cc明确包括foo.h.

此外,我希望能够匹配#define宏。

我编写工具的方式使这两个目标成为不可能,因为我匹配的 AST 已经过预处理。我想要做的甚至可能吗?我Preprocessor在 Clang 的 Doxygen 页面上搜索了类参考,但我还没有完全找到我要找的东西。

4

2 回答 2

13

在研究了 Clang 的 Doxygen 和代码后,我发现了这一点。我需要与PPCallbacks班级一起使用Preprocessor班级。下面是一个例子。请注意,这不保证是功能代码片段,但它说明了一般用法。有关更多信息,请参阅 Clang 的PPCallbacks文档以及clang::Preprocessor中的addPPCallbacksgetPPCallbacks文档。

class Find_Includes : public PPCallbacks
{
public:
  bool has_include;

  void InclusionDirective(
    SourceLocation hash_loc,
    const Token &include_token,
    StringRef file_name,
    bool is_angled,
    CharSourceRange filename_range,
    const FileEntry *file,
    StringRef search_path,
    StringRef relative_path,
    const Module *imported)
  {
    // do something with the include
    has_include = true;
  }
};

class Include_Matching_Action : public ASTFrontendAction
{
  bool BeginSourceFileAction(CompilerInstance &ci, StringRef)
  {
    std::unique_ptr<Find_Includes> find_includes_callback(new Find_Includes());

    Preprocessor &pp = ci.getPreprocessor();
    pp.addPPCallbacks(std::move(find_includes_callback));

    return true;
  }

  void EndSourceFileAction()
  {
    CompilerInstance &ci = getCompilerInstance();
    Preprocessor &pp = ci.getPreprocessor();
    Find_Includes *find_includes_callback = static_cast<Find_Includes>(pp.getPPCallbacks());

    // do whatever you want with the callback now
    if (find_includes_callback->has_include)
      std::cout << "Found at least one include" << std::endl;
  }
};
于 2014-11-22T08:23:38.027 回答
1

我成功地实现了它。我认为 EndSourceFileAction() 方法不应包含与 Find_Includes 相关的任何内容。

void InclusionDirective( SourceLocation hash_loc, const Token &include_token, StringRef file_name, bool is_angled, CharSourceRange filename_range,
                            const FileEntry *file, StringRef search_path, StringRef relative_path, const Module *imported)
              {
                  // Add your code here.
              }
bool BeginSourceFileAction(CompilerInstance &CI) 
{     std::unique_ptr<Find_Includes> find_includes_callback(new Find_Includes(TheRewriter));
      Preprocessor &pp = CI.getPreprocessor();
      pp.addPPCallbacks(std::move(find_includes_callback));
      return true;
}
于 2018-01-06T03:49:06.260 回答