pythoncclanglibclang

Get AST of MACRO statements usinc libclang


There are quite a few defined macros in my code that I would like to be able to get the AST of. A statement might look like this:

#define maskout_different_softening_flag(x) (x & (1 << BITFLAG_MIXED_SOFTENINGS_IN_NODE))

So if maskout_different_softening_flag is used then its cursor will be of kind BINARY_OPERATOR. I would like to be able to get all the cursors of that macro so I can replace it in the actual code. By using the PARSE_DETAILED_PROCESSING_RECORD option I can get the macros in this form

enter image description here

The only thing that I can see is extend but what would be more useful is something similar to get_children together with the ability to retrieve these children cursors every time I find a macro used in the code.

Is this possible using libclang in python?


Solution

  • Macro replacements don't correspond to AST nodes. A macro invocation is replaced with a stream of tokens, not necessarily the same stream on each invocation, and there's no requirement that the replacement be an expression or any other well-formed syntactic entity.

    If you want maskout_different_softening_flag(x) to be a single syntactic entity with a meaningful root node, you should define it as an inline function, not a macro. Macros are much rowdier denizens of the compilation process; they're not going to sit back and let you syntactically analyse their replacement text. By the time the compiler starts to analyse those tokens, the macro itself has vanished without a trace. (Ok, there is a trace, since the source locations of the token might tell you which #define they came from. But that's it.)

    As far as I know, libclang shows you the source the way a compiler would see it. So it's probably not going to correspond to the model you seem to want to view.