如何使用libclang获取枚举元素的数值?

时间:2015-03-24 15:24:14

标签: c++ enums libclang

假设我有一个枚举定义,例如:

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

我想以编程方式从任何给定的枚举定义生成一个映射,其中键是枚举元素的名称,值是枚举元素的数值 (例如myMap["TwoAgain"] == 2

到目前为止,我知道如何使用clang_visitChildren()遍历源文件,并使用clang_tokenize()提取单个令牌。通过AST递归,我按顺序获得游标/标记:

  1. " MyEnum" (CXType_Enum)
    • "首先" (CXToken_Identifier)
    • " =" (CXToken_Punctuation)
    • " 1" (CXToken_Literal)
  2. " unsigned int" (CXType_UInt)
    • " 1" (CXToken_Literal)
  3. " MyEnum" (CXType_Enum)
    • "第二" (CXToken_Identifier)
  4. " MyEnum" (CXType_Enum)
    • "第三" (CXToken_Identifier)
  5. " MyEnum" (CXType_Enum)
    • " TwoAgain" (CXToken_Identifier)
    • " =" (CXToken_Punctuation)
    • "第二" (CXToken_Identifier)
  6. " unsigned int" (CXType_UInt)
    • "第二" (CXToken_Identifier)
  7. 我想我可以编写一个使用此信息计算每个值的算法。但是,我想知道是否有更简单的方法? 我可以直接从libclang API获取数值吗?

3 个答案:

答案 0 :(得分:6)

libclang通过clang_getEnumConstantDeclValueclang_getEnumConstantDeclUnsignedValue公开此信息。您可以通过访问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;
}

答案 1 :(得分:1)

正如id256所说,我不认为你可以用libclang做到这一点。但是,Clang的libtooling and plugin interface允许您访问AST并直接对其进行操作。对于枚举,您将要查看EnumDecl类,它允许您迭代内部decls。然后,这只是建立一个地图的案例,如:

for (auto declIterator = myEnumDecl.decls_begin();
     declIterator != myEnumDecl.decls_end();
     ++declIterator)
{
    myMap[declIterator->getNameAsString()] = declIterator->getInitVal;
}

答案 2 :(得分: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;
      }