[libClang] Determining whether enum is enum class

I need to determine whether an enum is an enum class.

I found this answer:

This isn't a suitable solution for code that exclusively uses the
libClang API.

I have come up with a solution that relies on parsing the source code
surrounding the declaration:

bool IsEnumEnumClass( const CXCursor& cursor )
     auto TU = clang_getTranslationUnit( cursor );

     CXToken* pTokens = nullptr;
     unsigned int uiNumTokens = 0;

     clang_tokenize( TU, clang_getCursorExtent( cursor ), &pTokens,
&uiNumTokens );

     bool bEncounteredEnumKeyword = false;

     bool bIsStronglyScoped = false;

     //Check the declaration until we find an "enum" keyword. If it's
followed by "class", it's strongly scoped.
     //Possible input: typedef enum class {} Foo; (typedef is apparently
ignored, but can't hurt to account for it)
     for( decltype( uiNumTokens ) uiToken = 0; uiToken < uiNumTokens;
++uiToken )
         auto spelling = clang::ToStdString( clang_getTokenSpelling( TU,
pTokens[ uiToken ] ) );

         if( spelling == "enum" )
             bEncounteredEnumKeyword = true;
         else if( bEncounteredEnumKeyword )
             if( spelling == "class" )
                 bIsStronglyScoped = true;

             //No "class" keyword encountered, so it's a weakly scoped enum.

     clang_disposeTokens( TU, pTokens, uiNumTokens );

     return bIsStronglyScoped;

clang::ToStdString converts a CXString to std::string.

This solution works, but isn't very pretty and may not work properly in
all cases.

I suppose a new function int clang_isScopedEnum( CXCursor C ) would be
helpful here, implemented as:

int clang_Cursor_isScopedEnum( CXCursor C )
     if( clang_getCursorKind( C ) != CXCursor_EnumDecl )
         return 0;

     if( const EnumDecl *TD = dyn_cast_or_null<EnumDecl>( getCursorDecl(
C ) ) )
         return TD->isScoped();

     return 0;

I have no experience implementing new features in libClang, and i'd
rather not break anything. Can anyone assist with such an
implementation, if it is acceptable?

I think this kind of addition is acceptable. Your implementation looks correct.

You should send a patch to the cfe-commits mailing list with the change to libClang that you are proposing. You can use Phabricator to send the patch - http://llvm.org/docs/Phabricator.html . You might also find the developer policy document helpful: http://llvm.org/docs/DeveloperPolicy.html . Don’t forget to include a test case with your patch!

I hope this was helpful,

I happened to also have a similar modification in a local branch. I just
added a test and sent it via Phabricator: https://reviews.llvm.org/D35187
As this is one of my first contributions any input would be appreciated.