获得clang的AST背后的来源

时间:2012-06-18 12:38:02

标签: c++ clang

在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时会发生同样的现象。

如何打印并查看构成声明的整个原始字符串?

4 个答案:

答案 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)

除了涉及宏之外,Elazar的方法对我有用。以下更正解决了这个问题:

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));
}