在clang中给出一个AST对象,我怎样才能得到它背后的代码?我尝试编辑tutorial中的代码,并添加了:
clang::SourceLocation _b = d->getLocStart(), _e = d->getLocEnd();
char *b = sourceManager->getCharacterData(_b),
e = sourceManager->getCharacterData(_E);
llvm:errs() << std::string(b, e-b) << "\n";
但是,它没有打印整个typedef声明,只有大约一半!打印Expr
时会发生同样的现象。
如何打印并查看构成声明的整个原始字符串?
答案 0 :(得分:14)
使用Lexer
模块:
clang::SourceManager *sm;
clang::LangOptions lopt;
std::string decl2str(clang::Decl *d) {
clang::SourceLocation b(d->getLocStart()), _e(d->getLocEnd());
clang::SourceLocation e(clang::Lexer::getLocForEndOfToken(_e, 0, *sm, lopt));
return std::string(sm->getCharacterData(b),
sm->getCharacterData(e)-sm->getCharacterData(b));
}
答案 1 :(得分:5)
以下代码适用于我。
std::string decl2str(clang::Decl *d, SourceManager &sm) {
// (T, U) => "T,,"
string text = Lexer::getSourceText(CharSourceRange::getTokenRange(d->getSourceRange()), sm, LangOptions(), 0);
if (text.size() > 0 && (text.at(text.size()-1) == ',')) //the text can be ""
return Lexer::getSourceText(CharSourceRange::getCharRange(d->getSourceRange()), sm, LangOptions(), 0);
return text;
}
答案 2 :(得分:1)
正如答案的评论所指出的那样,所有其他答案似乎都有其缺陷,因此,我将发布自己的代码,其中似乎涵盖了注释中提到的所有缺陷。
我相信getSourceRange()
将该语句视为一个标记序列,而不是一个字符序列。这意味着,如果我们有一个与clang::Stmt
相对应的FOO + BAR
,则令牌FOO
位于字符1,令牌+
位于字符5,令牌{ {1}}在字符7处。BAR
因此返回一个getSourceRange()
,该词实际上表示“此代码以1处的令牌开始,并以7”处的令牌结束。。因此,我们必须使用SourceRange
来获取clang::Lexer::getLocForEndOfToken(stmt.getSourceRange().getEnd())
令牌结束字符的实际字符位置,并将 that 作为结束位置传递给{{ 1}}。如果我们不这样做,那么BAR
将返回clang::Lexer::getSourceText
,而不是我们可能想要的clang::Lexer::getSourceText
。
我不认为我的实现在注释中提到了@Steven Lu的问题,因为此代码使用了"FOO + "
函数,该函数according to Clang's source documentation是专门为从范围。
此实现还考虑了@Ramin Halavati的评论;我已经在一些代码上对其进行了测试,并且确实返回了宏扩展字符串。
这是我的实现:
"FOO + BAR"
答案 3 :(得分:0)
std::string decl2str(clang::Decl *d) {
clang::SourceLocation b(d->getLocStart()), _e(d->getLocEnd());
if (b.isMacroID())
b = sm->getSpellingLoc(b);
if (e.isMacroID())
e = sm->getSpellingLoc(e);
clang::SourceLocation e(clang::Lexer::getLocForEndOfToken(_e, 0, *sm, lopt));
return std::string(sm->getCharacterData(b),
sm->getCharacterData(e)-sm->getCharacterData(b));
}