diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -33,6 +33,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" @@ -48,8 +49,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -124,6 +125,7 @@ friend class VAOptDefinitionContext; friend class VariadicMacroScopeGuard; + llvm::unique_function OnToken; std::shared_ptr PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; @@ -911,6 +913,14 @@ } /// \} + /// Register a function that would be called on each token seen by the + /// preprocessor. This is a very low-level hook, the produced token stream is + /// tied to the internals of the preprocessor so interpreting result of the + /// callback is hard. + void setTokenWatcher(llvm::unique_function F) { + OnToken = std::move(F); + } + bool isMacroDefined(StringRef Id) { return isMacroDefined(&Identifiers.get(Id)); } diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -864,6 +864,7 @@ void Preprocessor::Lex(Token &Result) { // We loop here until a lex function returns a token; this avoids recursion. bool ReturnedToken; + bool Cached = false; do { switch (CurLexerKind) { case CLK_Lexer: @@ -875,6 +876,7 @@ case CLK_CachingLexer: CachingLex(Result); ReturnedToken = true; + Cached = true; break; case CLK_LexAfterModuleImport: LexAfterModuleImport(Result); @@ -893,6 +895,8 @@ } LastTokenWasAt = Result.is(tok::at); + if (OnToken && ReturnedToken && !Cached) + OnToken(Result); } /// Lex a header-name token (including one formed from header-name-tokens if