Libclang gets a primitive value

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

For example, if I have a CX cursor type cursor CXCursor_IntegerLiteral, how can I extract a literal value.


UPDATE:

I had a lot of problems using libclang. I highly recommend completely abandoning it and using the C ++ interface instead. The C ++ interface is very useful and very well documented: http://clang.llvm.org/doxygen/annotated.html

The only goal that I see now in libclang is to create an ASTUnit object for you, as with the following code (this is not entirely simple):

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 can say that libclang is stable, but the C ++ interface is not. This hardly matters, since the time spent figuring out AST using libclang and creating kludges with it spends so much of your time anyway. I would also spend several hours fixing the code that does not compile after updating the version (if necessary).

+4
source share
3 answers

Instead of reprocessing the original, you already have all the necessary information 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 does not matter (for example int i = 42; for int i = 42;

+7
source

In fact, you can use a combination of libclang and a C ++ interface.

The libclang type CXCursor contains a data field that contains links to AST base nodes. I was able to successfully access the IntegerLiteral value by selecting data[1] as the type IntegerLiteral .

I implement this in Nim , so I provided the Nim code, but you can probably do the same in C ++.

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

The IntegerLiteral type IntegerLiteral wrapped as follows:

 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 :)

+1
source

I found a way to do this by accessing the source 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; } 
0
source

Source: https://habr.com/ru/post/1413611/


All Articles