Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you detect the difference between an enum and a scoped enum using libclang?

I have been writing a C++ AST parser using the excellent C interface libclang (http://clang.llvm.org/doxygen/group__CINDEX.html). Unfortunately there appears to be no disambiguation between C++ 11 scoped enums and old fashioned enums: both have a cursor kind of CXCursor_EnumDecl and a type of CXType_Enum I.e. identical.

I have tried visiting the children to see if their parent type is different - sadly no. I have tried asking for the underlying type, I get back an integer for both. I have examined all items declared after the Enum to see if maybe for old fashioned Enums a bind or typedef might appear, again no difference is obvious.

I am beginning to think I must be missing something. Do I have to use the code completion API to figure out which kind of Enum it is or something?

like image 370
Niall Douglas Avatar asked Oct 02 '14 19:10

Niall Douglas


1 Answers

So here is one solution, though it is not great, but it may help others. A CXCursor is a struct looking like this:

typedef struct {
  enum CXCursorKind kind;
  int xdata;
  const void *data[3];
} CXCursor;

Currently, the void *data[3] maps onto { const clang::Decl *Parent, const clang::Stmt *S, CXTranslationUnit TU }. Knowing this, we can write code which extracts the internal clang C++ objects from the libclang C state:

#include "clang/AST/Decl.h"
bool isScoped=false;
{
  using namespace clang;
  const Decl *D = static_cast<const Decl *>(cursor.data[0]);
  if(const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D))
  {
    isScoped=TD->isScoped();
  }
}

Lots of bad things could happen with this solution if your clang headers deviate from your libclang. I don't much care for this solution, but it does work.

like image 89
Niall Douglas Avatar answered Nov 04 '22 23:11

Niall Douglas