8

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?

4

3 に答える 3

8

libclang は、 および を介してこの情報を公開しclang_getEnumConstantDeclValueますclang_getEnumConstantDeclUnsignedValue。あなたが説明したようなマップは、 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;
}
于 2015-03-28T15:30:15.230 に答える
1

id256 が言ったように、 でこれを行うことはできないと思いますlibclang。ただし、Clanglibtoolingとプラグイン インターフェイスを使用すると、AST にアクセスして直接操作することができます。列挙型の場合はEnumDecl、内部宣言を反復処理できるクラスを確認する必要があります。次に、次のようなマップを構築する場合です。

for (auto declIterator = myEnumDecl.decls_begin();
     declIterator != myEnumDecl.decls_end();
     ++declIterator)
{
    myMap[declIterator->getNameAsString()] = declIterator->getInitVal;
}
于 2015-03-25T08:42:26.597 に答える
0

マップの名前と値を取得するには、次の方法を使用できます。私はclang 8を使用しています。

bool VisitEnumDecl(EnumDecl *ED)
      {

        for (auto it = ED->enumerator_begin(); it != ED->enumerator_end(); it++)
        {


         std::cout <<it->getNameAsString()<<" "<<it->getInitVal().getSExtValue()<<std::endl;


        }
        return true;
      }
于 2019-11-16T16:59:03.993 に答える