How I can I parse comments from macro expansion using libclang?

188 Views Asked by At

Given the following C++ program:

#define SOME_MACRO \
  (void) x; /* some comment in macro */ \

int main()
{
  int x = 0;
  /* some comment in main */
  SOME_MACRO
  SOME_MACRO
  return 0;
}

I would like libclang to call me back on the comments expanded in SOME_MACRO.

I tried the to register a comment handler, and set-up the preprocessor output options as follow:

struct CommentPrinter : clang::CommentHandler {
  bool HandleComment(Preprocessor & pp, SourceRange comment) {
    llvm::outs() << "new comment : \n";
    comment.dump(pp.getSourceManager());
    return false;
  }
};

  struct frontend_t : clang::ASTFrontendAction
  {
    std::unique_ptr<clang::ASTConsumer>
      CreateASTConsumer(clang::CompilerInstance& CI,
          clang::StringRef source_file) override
      {
        CI.getPreprocessorOutputOpts().ShowComments = 1;
        CI.getPreprocessorOutputOpts().ShowMacroComments = 1;
        CI.getPreprocessor().addCommentHandler(new CommentPrinter);
        return std::make_unique<ast_consumer_t>();
      }
  };

But my comment handler was called only on comments line 2 and 7. Do you known if it is possible to be also called on comments on line 8 and 9?

1

There are 1 best solutions below

1
Botje On

I don't think you can. The C++ standard (link to draft) defines how files are processed in "translation phases". By the time the macro processor can get to work on your #define and macro expansions, the comments have already been removed:

phase 3:
The source file is decomposed into preprocessing tokens ([lex.pptoken]) and sequences of whitespace characters (including comments). A source file shall not end in a partial preprocessing token or in a partial comment.
Each comment is replaced by one space character.

phase 4: Preprocessing directives are executed, macro invocations are expanded, and _­Pragma unary operator expressions are executed. [...] All preprocessing directives are then deleted.