我得到了函数定义的FunctionDecl。此功能没有声明。
例如:
int foo(char c, double d)
{
...
}
如何将签名(限定符,返回类型,函数名称,参数)作为可用于声明的有效签名?
答案 0 :(得分:1)
我发现最简单的方法是使用词法分析器获取函数的签名。由于我想从定义中做出声明,我希望声明看起来与定义完全一样。
因此,我从函数的开头到函数体的开头(减去开头“{”)定义了一个SourceRange
,让lexer给我这个范围作为字符串。
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
是一个定义(有一个正文)。
答案 1 :(得分:0)
也许这就是您想要的...
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
类(例如FunctionDecl
或ParmVarDecl
)的基类。因此,允许重新解释指针,并使您可以访问该特定AST节点的属性。由于这些更特定的AST节点继承了NamedDecl
和ValueDecl
类,因此获得函数名称和函数类型(签名)非常简单。可以将同样的方法应用于基类Stmt
和其他继承的类,例如OtherExpr
类。