获取 FunctionDecl 的签名

Getting the signature of a FunctionDecl

我得到了函数定义的 FunctionDecl。此函数没有声明。

例如:

int foo(char c, double d)
{
   ...
}

如何将签名(限定符、return 类型、函数名称、参数)作为我可以用来进行声明的有效签名?

我发现最简单的方法是使用词法分析器来获取函数的签名。因为我想从定义中做出声明,所以我希望声明看起来与定义完全一样。 因此我定义了一个 SourceRange 从函数的开始到函数体的开始(减去开头的“{”)并让词法分析器将这个范围作为字符串给我。

static std::string getDeclaration(const clang::FunctionDecl* D)
{
  clang::ASTContext& ctx = D->getASTContext();
  clang::SourceManager& mgr = ctx.getSourceManager();

  clang::SourceRange range = clang::SourceRange(D->getSourceRange().getBegin(), D->getBody()->getSourceRange().getBegin());
  StringRef s = clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(range), mgr, ctx.getLangOpts());

  return s.substr(0, s.size() - 2).str().append(";");
}

此解决方案假定 FunctionDecl 是一个定义(有主体)。

也许这就是您要找的...

bool VisitDecl(Decl* D) {
  auto k = D->getDeclKindName();
  auto r = D->getSourceRange();
  auto b = r.getBegin();
  auto e = r.getEnd();
  auto& srcMgr = Context->getSourceManager();
  if (srcMgr.isInMainFile(b)) {
    auto d = depth - 2u;
    auto fname = srcMgr.getFilename(b);
    auto bOff = srcMgr.getFileOffset(b);
    auto eOff = srcMgr.getFileOffset(e);
    llvm::outs() << std::string(2*d,' ') << k << "Decl ";
    llvm::outs() << "<" << fname << ", " << bOff << ", " << eOff << "> ";
    if (D->getKind() == Decl::Kind::Function) {
      auto fnDecl = reinterpret_cast<FunctionDecl*>(D);
      llvm::outs() << fnDecl->getNameAsString() << " ";
      llvm::outs() << "'" << fnDecl->getType().getAsString() << "' ";
    } else if (D->getKind() == Decl::Kind::ParmVar) {
      auto pvDecl = reinterpret_cast<ParmVarDecl*>(D);
      llvm::outs() << pvDecl->getNameAsString() << " ";
      llvm::outs() << "'" << pvDecl->getType().getAsString() << "' ";
    }
    llvm::outs() << "\n";
  }
  return true;
}

示例输出:

FunctionDecl <foo.c, 48, 94> foo 'int (unsigned int)' 
  ParmVarDecl <foo.c, 56, 69> x 'unsigned int' 
  CompoundStmt <foo.c, 72, 94> 
    ReturnStmt <foo.c, 76, 91> 
      ParenExpr <foo.c, 83, 91> 
        BinaryOperator <foo.c, 84, 17> 
          ImplicitCastExpr <foo.c, 84, 84> 
            DeclRefExpr <foo.c, 84, 84> 
          ParenExpr <foo.c, 28, 45> 
            BinaryOperator <foo.c, 29, 43> 
              ParenExpr <foo.c, 29, 39> 
                BinaryOperator <foo.c, 30, 12> 
                  IntegerLiteral <foo.c, 30, 30> 
                  IntegerLiteral <foo.c, 12, 12> 
              IntegerLiteral <foo.c, 43, 43> 

您会注意到 reinterpret_cast<OtherDecl*>(D) 函数调用。 Decl 是所有 AST OtherDecl class 的基础 class,例如 FunctionDeclParmVarDecl。因此,允许重新解释指针并让您访问该特定 AST 节点的属性。由于这些更具体的 AST 节点继承了 NamedDeclValueDecl classes,因此获取函数名称和函数类型(签名)很简单。同样可以应用于基础 class Stmt 和其他继承的 classes,如 OtherExpr classes.