LibClang AST missing AST nodes resulting from macro expansion

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

LibClang AST missing AST nodes resulting from macro expansion

David Blaikie via cfe-dev
A question regarding LibClang:

Given this file

foo.c
================
#define FOO 13u
#define BAR ((1u << FOO) - 1u)

int foo(unsigned int x) {
  return (x > BAR);
}
================

Using a recursive visitor, I try traversing the AST and output the following:

foo.out
================
macro definition <"foo.c", 8, 15> FOO ''
macro definition <"foo.c", 24, 46> BAR ''
macro expansion <"foo.c", 88, 91> BAR ''
FunctionDecl <"foo.c", 48, 95> foo 'int (unsigned int)'
  ParmDecl <"foo.c", 56, 70> x 'unsigned int'
  CompoundStmt <"foo.c", 72, 95>  ''
    ReturnStmt <"foo.c", 76, 92>  ''
      ParenExpr <"foo.c", 83, 92>  'int'
        BinaryOperator <"foo.c", 84, 91>  'int' '>'
          UnexposedExpr <"foo.c", 84, 85> x 'unsigned int'
            DeclRefExpr <"foo.c", 84, 85> x 'unsigned int'
================

The second operand for the '>' binary operator is missing in the resulting AST traversal. If I fully preprocess foo.c, I obtain the expected AST.

bar.c
================



int foo(unsigned int x) {
  return (x > ((1u << 13u) - 1u));
}
================

bar.out
================
FunctionDecl <"bar.c", 3, 65> foo 'int (unsigned int)'
  ParmDecl <"bar.c", 11, 25> x 'unsigned int'
  CompoundStmt <"bar.c", 27, 65>  ''
    ReturnStmt <"bar.c", 31, 62>  ''
      ParenExpr <"bar.c", 38, 62>  'int'
        BinaryOperator <"bar.c", 39, 61>  'int' '>'
          UnexposedExpr <"bar.c", 39, 40> x 'unsigned int'
            DeclRefExpr <"bar.c", 39, 40> x 'unsigned int'
          ParenExpr <"bar.c", 43, 61>  'unsigned int'
            BinaryOperator <"bar.c", 44, 60>  'unsigned int' '-'
              ParenExpr <"bar.c", 44, 55>  'unsigned int'
                BinaryOperator <"bar.c", 45, 54>  'unsigned int' '<<'
                  IntegerLiteral <"bar.c", 45, 47>  'unsigned int' 1u
                  IntegerLiteral <"bar.c", 51, 54>  'unsigned int' 13u
              IntegerLiteral <"bar.c", 58, 60>  'unsigned int' 1u
================

However, if I modify foo.c such that the binary operator has macro expansions for both operands, I obtain the following ouput:

baz.c
================
#define FOO 13u
#define BAR ((1u << FOO) - 1u)

int foo(unsigned int x) {
  return (FOO > BAR);
}
================

baz.out
================
macro definition <"baz.c", 8, 15> FOO ''
macro definition <"baz.c", 24, 46> BAR ''
macro expansion <"baz.c", 84, 87> FOO ''
macro expansion <"baz.c", 90, 93> BAR ''
FunctionDecl <"baz.c", 48, 97> foo 'int (unsigned int)'
  ParmDecl <"baz.c", 56, 70> x 'unsigned int'
  CompoundStmt <"baz.c", 72, 97>  ''
    ReturnStmt <"baz.c", 76, 94>  ''
      ParenExpr <"baz.c", 83, 94>  'int'
================

Now both operands *and* the operator are missing from the resulting AST traversal.


Because of the implicit "-fsyntax-only" argument for clang_parseTranslationUnit(...), the pre-processing must be done at some point, yet I am not seeing the macro-expanded subtrees in the AST traversal.

--> Where are the macro-expanded AST subtrees? Or rather, why is clang_visitChildren(...) not visiting these subtrees?


Ryan Steele


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev