libclang得到原始值(libclang get primitive value)

2019-07-29 11:57发布

我怎样才能得到一个原始的文字使用libclang的价值?

举例来说,如果我有那种光标的CXCursor_IntegerLiteral一个CXCursor,我怎么能提取文本值。


更新:

我碰到的使用libclang这么多的问题。 我强烈建议避免它完全,而是使用C ++接口铛提供。 在C ++接口是高度可用的和很好的记录: http://clang.llvm.org/doxygen/annotated.html

我现在看到libclang的唯一目的是为您生成ASTUnit对象用下面的代码(这不太容易,否则):

ASTUnit * astUnit;
{
    index = clang_createIndex(0, 0);
    tu = clang_parseTranslationUnit(
        index, 0,
        clangArgs, nClangArgs,
        0, 0, CXTranslationUnit_None
        );
    astUnit = static_cast<ASTUnit *>(tu->TUData);
}

现在你可能会说,libclang稳定和C ++接口不是。 这并不重要,因为时间你花搞清楚与libclang的AST和创造组装机与它浪费了你这么多时间呢。 我倒宁愿花几个小时修复了代码,没有一个版本升级后编译(如果连需要)。

Answer 1:

相反,重新分析原始的,你已经拥有你所需要的翻译单元内的所有信息:

if (kind == CXCursor_IntegerLiteral)
{
    CXSourceRange range = clang_getCursorExtent(cursor);
    CXToken *tokens = 0;
    unsigned int nTokens = 0;
    clang_tokenize(tu, range, &tokens, &nTokens);
    for (unsigned int i = 0; i < nTokens; i++)
    {
        CXString spelling = clang_getTokenSpelling(tu, tokens[i]);
        printf("token = %s\n", clang_getCString(spelling));
        clang_disposeString(spelling);
    }
    clang_disposeTokens(tu, tokens, nTokens);
}

你将看到第一个标记是整数本身,下一个是不相关的(例如,它是;int i = 42;



Answer 2:

实际上,你可以使用libclang的组合和C ++接口。

所述libclang CXCursor类型包含data ,其包含对基础AST节点的引用字段。 我能够成功地访问IntegerLiteral通过铸造值data[1]IntegerLiteral类型。

我在实施这一稔 ,所以我将提供稔代码,但你可能可以做同样的在C ++中。

let literal = cast[clang.IntegerLiteral](cursor.data[1])
echo literal.getValue().getLimitedValue()

所述IntegerLiteral类型被包裹像这样:

type
  APIntObj* {.importcpp: "llvm::APInt", header: "llvm/ADT/APInt.h".} = object
    # https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/APInt.h
  APInt* = ptr APIntObj

  IntegerLiteralObj* {.importcpp: "clang::IntegerLiteral", header: "clang/AST/Expr.h".} = object
  IntegerLiteral* = ptr IntegerLiteralObj


proc getValue*(i: IntegerLiteral): APIntObj {.importcpp: "#.getValue()".}
  # This is implemented by the superclass: https://clang.llvm.org/doxygen/classclang_1_1APIntStorage.html
proc getLimitedValue*(a: APInt | APIntObj): culonglong {.importcpp: "#.getLimitedValue()".}

希望这可以帮助别人:)



Answer 3:

我找到了一种方法参照原始文件要做到这一点:

std::string getCursorText (CXCursor cur) {
    CXSourceRange range = clang_getCursorExtent(cur);
    CXSourceLocation begin = clang_getRangeStart(range);
    CXSourceLocation end = clang_getRangeEnd(range);
    CXFile cxFile;
    unsigned int beginOff;
    unsigned int endOff;
    clang_getExpansionLocation(begin, &cxFile, 0, 0, &beginOff);
    clang_getExpansionLocation(end, 0, 0, 0, &endOff);
    ClangString filename = clang_getFileName(cxFile);
    unsigned int textSize = endOff - beginOff;

    FILE * file = fopen(filename.c_str(), "r");
    if (file == 0) {
        exit(ExitCode::CANT_OPEN_FILE);
    }
    fseek(file, beginOff, SEEK_SET);
    char buff[4096];
    char * pBuff = buff;
    if (textSize + 1 > sizeof(buff)) {
        pBuff = new char[textSize + 1];
    }
    pBuff[textSize] = '\0';
    fread(pBuff, 1, textSize, file);
    std::string res(pBuff);
    if (pBuff != buff) {
        delete [] pBuff;
    }
    fclose(file);
    return res;
}


文章来源: libclang get primitive value
标签: c++ libclang