[libClang] Determining whether enum is enum class

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[libClang] Determining whether enum is enum class

Boris Kolpackov via cfe-dev
I need to determine whether an enum is an enum class.

I found this answer:
https://stackoverflow.com/questions/26168121/how-do-you-detect-the-difference-between-an-enum-and-a-scoped-enum-using-libclan

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.
             break;
         }
     }

     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?
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libClang] Determining whether enum is enum class

Boris Kolpackov via cfe-dev
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,
Alex

On 6 July 2017 at 11:05, Sam Vanheer via cfe-dev <[hidden email]> wrote:
I need to determine whether an enum is an enum class.

I found this answer:
https://stackoverflow.com/questions/26168121/how-do-you-detect-the-difference-between-an-enum-and-a-scoped-enum-using-libclan

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.
             break;
         }
     }

     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?
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libClang] Determining whether enum is enum class

Boris Kolpackov via cfe-dev

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.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev