Search code examples
c++enumslibclang

How do I get an enum element's numerical value using libclang?


Suppose I have an enum definition, e.g.:

// myenum.h
enum MyEnum {
    First = 1,
    Second,
    Third,
    TwoAgain = Second
};

I would like to programmatically generate a map from any given enum definition, where the key is the enum element's name, and the value is the enum element's numerical value (e.g. myMap["TwoAgain"] == 2)

So far, I know how to traverse the source file using clang_visitChildren(), and extract individual tokens using clang_tokenize(). Recursing through the AST, I get cursors/tokens in this order:

  1. "MyEnum" (CXType_Enum)
    • "First" (CXToken_Identifier)
    • "=" (CXToken_Punctuation)
    • "1" (CXToken_Literal)
  2. "unsigned int" (CXType_UInt)
    • "1" (CXToken_Literal)
  3. "MyEnum" (CXType_Enum)
    • "Second" (CXToken_Identifier)
  4. "MyEnum" (CXType_Enum)
    • "Third" (CXToken_Identifier)
  5. "MyEnum" (CXType_Enum)
    • "TwoAgain" (CXToken_Identifier)
    • "=" (CXToken_Punctuation)
    • "Second" (CXToken_Identifier)
  6. "unsigned int" (CXType_UInt)
    • "Second" (CXToken_Identifier)

I guess I could write an algorithm that uses this information to calculate every value. However, I was wondering if there's a simpler way? Can I get the numerical values directly from the libclang API?


Solution

  • libclang exposes this information through clang_getEnumConstantDeclValue and clang_getEnumConstantDeclUnsignedValue. A map like you describe can be built by visiting the children of a CXCursor_EnumDecl:

    static enum CXChildVisitResult VisitCursor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
        if (cursor.kind == CXCursor_EnumConstantDecl) {
            CXString spelling = clang_getCursorSpelling(cursor);
            myMap[clang_getCString(spelling)] = clang_getEnumConstantDeclValue(cursor);
            clang_disposeString(spelling);
        }
    
        return CXChildVisit_Continue;
    }