1

我想用 clang AST 解析自定义标签。这是我的编译单元输入的简单说明。

#include <stdio.h>
int main() {
  // \my-tags tag_A, tag_B
  printf("helloworld");
  return 0;
}

之后如何获得这些标签\my-tags

阅读clang 用户手册后,我意识到-Wdocumentation-fparse-all-comments甚至-fcomment-block-commands可以满足我的要求。但是,当我在我的 中添加这些标志之一时compile_commands.jsonASTContext.Comments.empty()仍然会输出True. 我在下面附上了我compile_commands.json和我的 clang AST 前端代码以供参考。

// compile_commands.json
[
  {
    "directory": "/home/my/project/target/directory",
    "arguments": ["/usr/local/bin/clang", "-c", "-std=c++14", "-Qunused-arguments", "-m64", "-fparse-all-comments", "-I/usr/include", "-I/usr/local/lib/clang/10.0.0/include", "-o", "build/.objs/input/linux/x86_64/release/target/target.cpp.o", "target/target.cpp"],
    "file": "target/target.cpp"
  }
]
// CommentParser.cpp
class MyPrinter : public MatchFinder::MatchCallback {
  public:
    virtual void run(const MatchFinder::MatchResult &Result) {
      ASTContext *Context = Result.Context;
      SourceManager& sm = Context->getSourceManager();
      if (!Context->Comments.empty())
        llvm::outs() << "There is no parsed comment\n";
    }
};

int main(int argc, const char **argv) {
  // CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  std::string err;
  std::unique_ptr<CompilationDatabase> cd = CompilationDatabase::autoDetectFromSource("/home/my/project/target/directory/compile_commands.json", err);

  ClangTool Tool(*cd, cd->getAllFiles());

  MyPrinter Printer;
  MatchFinder Finder;

  StatementMatcher functionMatcher =
    callExpr(callee(functionDecl(hasName("pthread_mutex_lock")))).bind("functions");

  Finder.addMatcher(functionMatcher, &Printer);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}

4

1 回答 1

0

我不确定 clang 是否可以以在 AST 中可见的方式解析评论,但您可以尝试两件事。一个是这样的: How to extract comments and match to declaration with RecursiveASTVisitor in libclang c++? ,这将使您获得声明上方的注释。

您可以尝试的另一件事是构建自己的自定义编译指示。因此,你可以有类似的东西:

#include <stdio.h>
int main() {
  #pragma mytag tagA
  printf("helloworld");
  return 0;
}

然后从 AST 中提取/识别标签。

支持自定义 pragma 需要稍微修改 clang。以下是实现此目的的一些参考: https://blog.quarkslab.com/implementing-a-custom-directive-handler-in-clang.html https://git.scc.kit.edu/CES/clang-custom -pragma

我过去在构建一个名为“igen”的自定义编译指示时尝试过这个,它的属性为“reduce”。这是它的样子:

#pragma igen reduce
a = a + 1;

和生成的AST:

-AttributedStmt 0xc792700 <<invalid sloc>, line:194:13>
  |-IGenAttr 0xc7926e8 <line:193:13, col:24> Implicit Reduce
  `-BinaryOperator 0xc7926c8 <line:194:5, col:13> 'int' '='
    |-DeclRefExpr 0xc792630 <col:5> 'int' lvalue Var 0xc7924c0 'a' 'int'
    `-BinaryOperator 0xc7926a8 <col:9, col:13> 'int' '+'
      |-ImplicitCastExpr 0xc792690 <col:9> 'int' <LValueToRValue>
      | `-DeclRefExpr 0xc792650 <col:9> 'int' lvalue Var 0xc7924c0 'a' 'int'
      `-IntegerLiteral 0xc792670 <col:13> 'int' 1

从 AST 可以看出,#pragma 指令在 AST 中生成“AttributedStmt”节点。

如果您确实需要为您的标签使用注释格式(即 // \my-tags tag_A),您可以随时制作一个小的 Python 脚本来“预处理”您的源文件,在其中将所有注释标签替换为#pragmas。这当然不是理想的,但仍然可能。

于 2020-06-25T19:00:24.107 回答