libclang get primitive value

社会主义新天地 提交于 2019-12-21 01:06:19

问题


How can I get the value of a primitive literal using libclang?

For example, if I have a CXCursor of cursor kind CXCursor_IntegerLiteral, how can I extract the literal value.


UPDATE:

I've run into so many problems using libclang. I highly recommend avoiding it entirely and instead use the C++ interface clang provides. The C++ interface is highly useable and very well documented: http://clang.llvm.org/doxygen/annotated.html

The only purpose I see of libclang now is to generate the ASTUnit object for you as with the following code (it's not exactly easy otherwise):

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

Now you might say that libclang is stable and the C++ interface isn't. That hardly matters, as the time you spend figuring out the AST with libclang and creating kludges with it wastes so much of your time anyway. I'd just as soon spend a few hours fixing up code that does not compile after a version upgrade (if even needed).


回答1:


Instead of reparsing the original, you already have all the information you need inside the translation unit :

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

You will see that the first token is the integer itself, the next one is not relevant (eg. it's ; for int i = 42;.




回答2:


You can actually use a combination of libclang and the C++ interface.

The libclang CXCursor type contains a data field which contains references to the underlying AST nodes. I was able to successfully access the IntegerLiteral value by casting data[1] to the IntegerLiteral type.

I'm implementing this in Nim so I will provide Nim code, but you can likely do the same in C++.

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

The IntegerLiteral type is wrapped like so:

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()".}

Hope this helps someone :)




回答3:


I found a way to do this by referring to the original files:

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


来源:https://stackoverflow.com/questions/10692015/libclang-get-primitive-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!