Extracting macro information using libclang, the C Interface to Clang

Hello all,
I’m new to libclang and using the Clang C-interface (version 3.6.0, 222169) to parse some C header files.

My goal is to extract all the #define constants from the .h files.

For example, for the following #defines:

#define FEE 12
#define FIE 34
#define FOE (FEE+FIE)
#define FUM FIE

I would like to get both the names and the resulting raw values as follows:

FEE = 12
FIE = 34
FOE = 46
FUM = 34

I’ve got as far as handling CXCursor_MacroDefinition, and getting the macro name from the cursor spelling. But after that, it’s not clear to me how I might obtain further information about the defined macro values themselves.

Is this possible using the libclang C interface?
If so, could someone please provide an example, or suggest an approach that that might work?

Thank you,

Mark.

Hello all,
I'm new to libclang and using the Clang C-interface (version 3.6.0,
222169) to parse some C header files.

My goal is to extract all the #define constants from the .h files.

For example, for the following #defines:

#define FEE 12
#define FIE 34
#define FOE (FEE+FIE)
#define FUM FIE

I would like to get both the names and the resulting raw values as follows:

FEE = 12
FIE = 34
FOE = 46
FUM = 34

I've got as far as handling /CXCursor_MacroDefinition, /and getting the
macro name from the cursor spelling. But after that, it's not clear to
me how I might obtain further information about the defined macro values
themselves.

Yep. That's where we are as well. Getting the definitions + their uses is
easy.

Context: I'm the one working on (lib)Clang integration in KDevelop.

Is this possible using the libclang C interface?
If so, could someone please provide an example, or suggest an approach
that that might work?

I was looking into this several months ago [1], too, and didn't find a
solution so far. I'd love to get some API in libclang for achieving this.

The open-source woboq code browser (code.woboq.org) has this feature, but uses
C++-API of Clang; so it's definitely possible, but I still didn't find the
time to map this implementation to libclang.

Example usage:
  http://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#108,
  hover over 'Q_OBJECT'.

The code dealing with Clang's C++ API is here:
  https://github.com/woboq/woboq_codebrowser/blob/master/generator/preprocessorcallback.cpp

Note: If you're interested in getting this into libclang I'd be glad to help
out!

[1] http://lists.cs.uiuc.edu/pipermail/cfe-dev/2014-August/038543.html

I would like to have an API in libclang for the preprocessor as well.

Hi Kevin,
Thanks for the info. Unfortunately, I'm in the same boat as you, deadlines to meet etc, no time to delve into the depths of libclang. Actually I tried to compile it with the preview version of visual studio 2015 and failed miserably, lots of errors without time to investigate. (I want a 64-bit version of libclang.dll, not the 32-bit version that's supplied pre-compiled on windows).

I've partly hacked together something that does most of what I need using the token functions, but it's certainly not a permanent solution, and not even a full solution to the problem I described. I may hack on it some more to remove extra guff in the values, but that's about as far as I'll probably be able to take it without writing a macro parser.

void translateMacro( CXCursor cursor, Generator& model )
{
     std::string name;
     std::string value;
     CXToken* tokens = nullptr;
     unsigned numTokens = 0;
     CXTranslationUnit transUnit = clang_Cursor_getTranslationUnit(cursor);
     CXSourceRange srcRange = clang_getCursorExtent(cursor);
     clang_tokenize( transUnit, srcRange, &tokens, &numTokens );
     for( unsigned n=0; n<numTokens; n++ )
     {
         CXStringWrapper tokenText = clang_getTokenSpelling( transUnit, tokens[n] );
         if( n == 0 ) {
             value.clear();
             name = tokenText.getStr();
             if( name[0] == '_' )
                 break;
         }
         else {
             CXTokenKind tokenKind = clang_getTokenKind( tokens[n] );
             if( tokenKind != CXToken_Comment )
             {
                 const char* text = tokenText.getStr();
                 if( text && (text[0]!='#') && strcmp(text,"typedef") )
                     value += text;
             }
         }
     }
     if( value.length() )
     {
         Constant c;
         c.setName( name );
         c.setValue( value );
         model.addConstant( c );
     }
     clang_disposeTokens( transUnit, tokens, numTokens );
}

Anyway, it seems there is a clear need for better preprocessing/macro functionality in libclang, so perhaps someone can add it to the C-API feature wish-list for future development?

Best regards,
Mark.