Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libclang get primitive value

Tags:

c++

libclang

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

like image 658
Thomas Eding Avatar asked May 21 '12 20:05

Thomas Eding


2 Answers

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

like image 192
speps Avatar answered Oct 01 '22 02:10

speps


If you have access to a CXCursor, you can make use of the clang_Cursor_Evaluate function, for example:

CXChildVisitResult var_decl_visitor(
    CXCursor cursor, CXCursor parent, CXClientData data) {
  auto kind = clang_getCursorKind(cursor);

  switch (kind) {
  case CXCursor_IntegerLiteral: {
    auto res = clang_Cursor_Evaluate(cursor);
    auto value = clang_EvalResult_getAsInt(res);
    clang_EvalResult_dispose(res);

    std::cout << "IntegerLiteral " << value << std::endl;

    break;
  }
  default:
    break;
  }

  return CXChildVisit_Recurse;
}

Outputs:

IntegerLiteral 42
like image 24
Vlad Faust Avatar answered Oct 01 '22 01:10

Vlad Faust