LegalizeAdulthood created this revision.
LegalizeAdulthood added a reviewer: ymandel.
Herald added subscribers: carlosgalvezp, kbarton, mgorny, nemanjai.
LegalizeAdulthood requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

This code is disgusting and meant only as an object
of discussion.


https://reviews.llvm.org/D118711

Files:
  clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
  clang-tools-extra/clang-tidy/ClangTidyCheck.h
  clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
  clang-tools-extra/clang-tidy/utils/CMakeLists.txt
  clang-tools-extra/clang-tidy/utils/PPTree.cpp
  clang-tools-extra/clang-tidy/utils/PPTree.h

Index: clang-tools-extra/clang-tidy/utils/PPTree.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/utils/PPTree.h
@@ -0,0 +1,258 @@
+//===---------- PPTree.h - clang-tidy -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PPTREE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PPTREE_H
+
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Token.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+struct PPDirective {
+  virtual ~PPDirective() = default;
+};
+
+using PPDirectiveStorage = std::vector<PPDirective *>;
+
+class PPDirectiveList {
+public:
+  void add(PPDirective *Dir) { Directives.emplace_back(Dir); }
+
+  ~PPDirectiveList() {
+    for (PPDirective *Dir : Directives)
+      delete Dir;
+    Directives.clear();
+  }
+
+  PPDirectiveStorage::iterator begin() { return Directives.begin(); }
+  PPDirectiveStorage::iterator end() { return Directives.end(); }
+
+  PPDirectiveStorage::const_iterator begin() const { return Directives.begin(); }
+  PPDirectiveStorage::const_iterator end() const { return Directives.end(); }
+
+  size_t size() const { return Directives.size(); }
+
+private:
+  PPDirectiveStorage Directives;
+};
+
+struct PPInclusion : PPDirective {
+  PPInclusion(SourceLocation HashLoc, Token IncludeTok, StringRef FileName,
+              bool IsAngled, CharSourceRange FilenameRange,
+              const FileEntry *File, StringRef SearchPath,
+              StringRef RelativePath, const Module *Imported,
+              SrcMgr::CharacteristicKind FileType)
+      : HashLoc(HashLoc), IncludeTok(IncludeTok), FileName(FileName.str()),
+        IsAngled(IsAngled), FilenameRange(FilenameRange), File(File),
+        SearchPath(SearchPath.str()), RelativePath(RelativePath.str()),
+        Imported(Imported), FileType(FileType) {}
+
+  SourceLocation HashLoc;
+  Token IncludeTok;
+  std::string FileName;
+  bool IsAngled;
+  CharSourceRange FilenameRange;
+  const FileEntry *File;
+  std::string SearchPath;
+  std::string RelativePath;
+  const Module *Imported;
+  SrcMgr::CharacteristicKind FileType;
+};
+
+struct PPIdent : PPDirective {
+  PPIdent(SourceLocation Loc, StringRef Str) : Loc(Loc), Str(Str.str()) {}
+
+  SourceLocation Loc;
+  std::string Str;
+};
+
+struct PPPragma : PPDirective {
+  PPPragma(SourceLocation Loc, PragmaIntroducerKind Introducer)
+      : Loc(Loc), Introducer(Introducer) {}
+
+  SourceLocation Loc;
+  PragmaIntroducerKind Introducer;
+};
+
+struct PPPragmaComment : PPDirective {
+  PPPragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+      StringRef Str) : Loc(Loc), Kind(Kind), Str(Str.str()) {}
+
+  SourceLocation Loc;
+  const IdentifierInfo *Kind;
+  std::string Str;
+};
+
+struct PPPragmaMark : PPDirective {
+  PPPragmaMark(SourceLocation Loc, StringRef Trivia)
+      : Loc(Loc), Trivia(Trivia.str()) {}
+
+  SourceLocation Loc;
+  std::string Trivia;
+};
+
+struct PPPragmaDetectMismatch : PPDirective {
+  PPPragmaDetectMismatch(SourceLocation Loc, StringRef Name, StringRef Value)
+      : Loc(Loc), Name(Name.str()), Value(Value.str()) {}
+
+  SourceLocation Loc;
+  std::string Name;
+  std::string Value;
+};
+
+struct PPPragmaDebug : PPDirective {
+  PPPragmaDebug(SourceLocation Loc, StringRef DebugType)
+      : Loc(Loc), DebugType(DebugType.str()) {}
+
+  SourceLocation Loc;
+  std::string DebugType;
+};
+
+struct PPPragmaMessage : PPDirective {
+  PPPragmaMessage(SourceLocation Loc, StringRef Namespace,
+                  PPCallbacks::PragmaMessageKind Kind, StringRef Str)
+      : Loc(Loc), Namespace(Namespace.str()), Kind(Kind), Str(Str.str()) {}
+
+  SourceLocation Loc;
+  std::string Namespace;
+  PPCallbacks::PragmaMessageKind Kind;
+  std::string Str;
+};
+
+struct PPMacroDefined : PPDirective {
+  PPMacroDefined(const Token &MacroNameTok, const MacroDirective *MD) : Name(MacroNameTok), MD(MD) {}
+
+  Token Name;
+  const MacroDirective *MD;
+};
+
+struct PPMacroUndefined : PPDirective {
+  PPMacroUndefined(Token Name, const MacroDefinition *MD,
+                   const MacroDirective *Undef)
+      : Name(Name), MD(MD), Undef(Undef) {}
+
+  Token Name;
+  const MacroDefinition *MD;
+  const MacroDirective *Undef;
+};
+
+struct PPIf : PPDirective {
+  PPIf(SourceLocation Loc, SourceRange ConditionRange,
+       PPCallbacks::ConditionValueKind ConditionValue)
+      : Loc(Loc), ConditionRange(ConditionRange),
+        ConditionValue(ConditionValue) {}
+
+  SourceLocation Loc;
+  SourceRange ConditionRange;
+  PPCallbacks::ConditionValueKind ConditionValue;
+  PPDirectiveList Directives;
+};
+
+struct PPElseIf : PPDirective {
+  PPElseIf(SourceLocation Loc, SourceRange ConditionRange,
+         PPCallbacks::ConditionValueKind ConditionValue, SourceLocation IfLoc)
+      : Loc(Loc), ConditionRange(ConditionRange),
+        ConditionValue(ConditionValue), IfLoc(IfLoc) {}
+
+  SourceLocation Loc;
+  SourceRange ConditionRange;
+  PPCallbacks::ConditionValueKind ConditionValue;
+  SourceLocation IfLoc;
+  PPDirectiveList Directives;
+};
+
+struct PPIfDef : PPDirective {
+  PPIfDef(SourceLocation Loc, const Token &MacroNameTok,
+          const MacroDefinition &MD)
+      : Loc(Loc), Name(MacroNameTok), MD(&MD) {}
+
+  SourceLocation Loc;
+  Token Name;
+  const MacroDefinition *MD;
+  PPDirectiveList Directives;
+};
+
+struct PPIfNotDef : PPDirective {
+  PPIfNotDef(SourceLocation Loc, const Token &MacroNameTok,
+             const MacroDefinition &MD)
+      : Loc(Loc), Name(MacroNameTok), MD(&MD) {}
+
+  SourceLocation Loc;
+  Token Name;
+  const MacroDefinition *MD;
+  PPDirectiveList Directives;
+};
+
+struct PPElseIfDef : PPDirective {
+  PPElseIfDef(SourceLocation Loc, const Token &MacroNameTok,
+          const MacroDefinition &MD)
+      : Loc(Loc), Name(MacroNameTok), MD(&MD) {}
+
+  SourceLocation Loc;
+  Token Name;
+  const MacroDefinition *MD;
+  PPDirectiveList Directives;
+};
+
+struct PPElseIfNotDef : PPDirective {
+  PPElseIfNotDef(SourceLocation Loc, const Token &MacroNameTok,
+                 const MacroDefinition &MD)
+      : Loc(Loc), Name(MacroNameTok), MD(&MD) {}
+
+  SourceLocation Loc;
+  Token Name;
+  const MacroDefinition *MD;
+  PPDirectiveList Directives;
+};
+
+struct PPEndIf : PPDirective {
+  PPEndIf(SourceLocation Loc, SourceLocation IfLoc) : Loc(Loc), IfLoc(IfLoc) {}
+
+  SourceLocation Loc;
+  SourceLocation IfLoc;
+};
+
+struct PPElse : PPDirective {
+  PPElse(SourceLocation Loc, SourceLocation IfLoc) : Loc(Loc), IfLoc(IfLoc) {}
+
+  SourceLocation Loc;
+  SourceLocation IfLoc;
+  PPDirectiveList Directives;
+};
+
+struct PPTree {
+  PPDirectiveList Directives;
+};
+
+class PPTreeConsumer {
+public:
+  virtual ~PPTreeConsumer() = default;
+
+  virtual void endOfMainFile(const utils::PPTree *Tree) = 0;
+};
+
+class PPTreeBuilder {
+public:
+  PPTreeBuilder(PPTreeConsumer *Callback, Preprocessor *PP, const SourceManager &SM, const LangOptions &LangOpts);
+
+private:
+  Preprocessor *PP;
+  PPTreeConsumer *Callback;
+  const SourceManager &SM;
+  const LangOptions &LangOpts;
+};
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PPTREE_H
Index: clang-tools-extra/clang-tidy/utils/PPTree.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/utils/PPTree.cpp
@@ -0,0 +1,257 @@
+//===-------- PPTree.cpp - clang-tidy -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPTree.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include <memory>
+
+namespace clang {
+namespace tidy {
+namespace utils {
+namespace {
+
+class PPTreeBuilderCallbacks : public PPCallbacks {
+public:
+  PPTreeBuilderCallbacks(PPTreeConsumer *Callback, const SourceManager &SM,
+                         const LangOptions &LangOpts)
+      : Callback(Callback), SM(SM), LangOpts(LangOpts) {}
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported,
+                          SrcMgr::CharacteristicKind FileType) override;
+  void EndOfMainFile() override;
+  void Ident(SourceLocation Loc, StringRef Str) override;
+  void PragmaDirective(SourceLocation Loc,
+                       PragmaIntroducerKind Introducer) override;
+  void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+                     StringRef Str) override;
+  void PragmaMark(SourceLocation Loc, StringRef Trivia) override;
+  void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+                            StringRef Value) override;
+  void PragmaDebug(SourceLocation Loc, StringRef DebugType) override;
+  void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+                     PragmaMessageKind Kind, StringRef Str) override;
+
+  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+                    SourceRange Range, const MacroArgs *Args) override;
+  void MacroDefined(const Token &MacroNameTok,
+                    const MacroDirective *MD) override;
+  void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
+                      const MacroDirective *Undef) override;
+  void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+               SourceRange Range) override;
+
+  void If(SourceLocation Loc, SourceRange ConditionRange,
+          ConditionValueKind ConditionValue) override;
+  void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+             const MacroDefinition &MD) override;
+  void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+              const MacroDefinition &MD) override;
+  void Else(SourceLocation Loc, SourceLocation IfLoc) override;
+  void Elif(SourceLocation Loc, SourceRange ConditionRange,
+            ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
+  void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+               const MacroDefinition &MD) override;
+  void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+                const MacroDefinition &MD) override;
+  void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
+  void pushDirectiveStack(PPDirectiveList *List);
+
+private:
+  void popDirectiveStack();
+
+  PPTreeConsumer *Callback;
+  const SourceManager &SM;
+  const LangOptions &LangOpts;
+  PPTree Tree;
+  std::vector<PPDirectiveList *> DirectiveStack{&Tree.Directives};
+  PPDirectiveList *Directives = DirectiveStack.back();
+};
+
+void PPTreeBuilderCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+    SrcMgr::CharacteristicKind FileType) {
+  auto Directive{std::make_unique<PPInclusion>(
+      HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath,
+      RelativePath, Imported, FileType)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::EndOfMainFile() {
+  Callback->endOfMainFile(&Tree);
+}
+
+void PPTreeBuilderCallbacks::Ident(SourceLocation Loc, StringRef Str) {
+  auto Directive{std::make_unique<PPIdent>(Loc, Str)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaDirective(SourceLocation Loc,
+                                             PragmaIntroducerKind Introducer) {
+  auto Directive{std::make_unique<PPPragma>(Loc, Introducer)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaComment(SourceLocation Loc,
+                                           const IdentifierInfo *Kind,
+                                           StringRef Str) {
+  auto Directive{std::make_unique<PPPragmaComment>(Loc, Kind, Str)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaMark(SourceLocation Loc, StringRef Trivia) {
+  auto Directive{std::make_unique<PPPragmaMark>(Loc, Trivia)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaDetectMismatch(SourceLocation Loc,
+                                                  StringRef Name,
+                                                  StringRef Value) {
+  auto Directive{std::make_unique<PPPragmaDetectMismatch>(Loc, Name, Value)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaDebug(SourceLocation Loc,
+                                         StringRef DebugType) {
+  auto Directive{std::make_unique<PPPragmaDebug>(Loc, DebugType)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::PragmaMessage(SourceLocation Loc,
+                                           StringRef Namespace,
+                                           PragmaMessageKind Kind,
+                                           StringRef Str) {
+  auto Directive{std::make_unique<PPPragmaMessage>(Loc, Namespace, Kind, Str)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::MacroExpands(const Token &MacroNameTok,
+                                          const MacroDefinition &MD,
+                                          SourceRange Range,
+                                          const MacroArgs *Args) {
+}
+
+void PPTreeBuilderCallbacks::MacroDefined(const Token &MacroNameTok,
+                                          const MacroDirective *MD) {
+  auto Directive{std::make_unique<PPMacroDefined>(MacroNameTok, MD)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::MacroUndefined(const Token &MacroNameTok,
+                                            const MacroDefinition &MD,
+                                            const MacroDirective *Undef) {
+  auto Directive{std::make_unique<PPMacroUndefined>(MacroNameTok, &MD, Undef)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::Defined(const Token &MacroNameTok,
+                                     const MacroDefinition &MD,
+                                     SourceRange Range) {
+}
+
+void PPTreeBuilderCallbacks::If(SourceLocation Loc, SourceRange ConditionRange,
+                                ConditionValueKind ConditionValue) {
+  auto Directive{std::make_unique<PPIf>(Loc, ConditionRange, ConditionValue)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Ifdef(SourceLocation Loc,
+                                   const Token &MacroNameTok,
+                                   const MacroDefinition &MD) {
+  auto Directive{std::make_unique<PPIfDef>(Loc, MacroNameTok, MD)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Ifndef(SourceLocation Loc,
+                                    const Token &MacroNameTok,
+                                    const MacroDefinition &MD) {
+  auto Directive{std::make_unique<PPIfNotDef>(Loc, MacroNameTok, MD)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Else(SourceLocation Loc, SourceLocation IfLoc) {
+  auto Directive{std::make_unique<PPElse>(Loc, IfLoc)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  popDirectiveStack();
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Elif(SourceLocation Loc,
+                                  SourceRange ConditionRange,
+                                  ConditionValueKind ConditionValue,
+                                  SourceLocation IfLoc) {
+  auto Directive{std::make_unique<PPElseIf>(Loc, ConditionRange, ConditionValue, IfLoc)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  popDirectiveStack();
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Elifdef(SourceLocation Loc,
+                                     const Token &MacroNameTok,
+                                     const MacroDefinition &MD) {
+  auto Directive{std::make_unique<PPElseIfDef>(Loc, MacroNameTok, MD)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  popDirectiveStack();
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Elifndef(SourceLocation Loc,
+                                      const Token &MacroNameTok,
+                                      const MacroDefinition &MD) {
+  auto Directive{std::make_unique<PPElseIfNotDef>(Loc, MacroNameTok, MD)};
+  PPDirectiveList *NewContext = &Directive->Directives;
+  popDirectiveStack();
+  Directives->add(Directive.release());
+  pushDirectiveStack(NewContext);
+}
+
+void PPTreeBuilderCallbacks::Endif(SourceLocation Loc, SourceLocation IfLoc) {
+  popDirectiveStack();
+  auto Directive{std::make_unique<PPEndIf>(Loc, IfLoc)};
+  Directives->add(Directive.release());
+}
+
+void PPTreeBuilderCallbacks::pushDirectiveStack(PPDirectiveList *List) {
+  DirectiveStack.push_back(List);
+  Directives = DirectiveStack.back();
+}
+
+void PPTreeBuilderCallbacks::popDirectiveStack() {
+  assert(DirectiveStack.size() > 1);
+  DirectiveStack.pop_back();
+  Directives = DirectiveStack.back();
+}
+
+} // namespace
+
+PPTreeBuilder::PPTreeBuilder(PPTreeConsumer *Callback, Preprocessor *PP,
+                             const SourceManager &SM, const LangOptions &LangOpts)
+    : PP(PP), Callback(Callback), SM(SM), LangOpts(LangOpts) {
+  PP->addPPCallbacks(
+      std::make_unique<PPTreeBuilderCallbacks>(Callback, SM, LangOpts));
+}
+
+} // namespace utils
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/utils/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/utils/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -17,6 +17,7 @@
   LexerUtils.cpp
   NamespaceAliaser.cpp
   OptionsUtils.cpp
+  PPTree.cpp
   RenamerClangTidyCheck.cpp
   TransformerClangTidyCheck.cpp
   TypeTraits.cpp
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
@@ -74,6 +74,7 @@
 void MacroUsageCheck::registerPPCallbacks(const SourceManager &SM,
                                           Preprocessor *PP,
                                           Preprocessor *ModuleExpanderPP) {
+  ClangTidyCheck::registerPPCallbacks(SM, PP, ModuleExpanderPP);
   PP->addPPCallbacks(std::make_unique<MacroUsageCallbacks>(
       this, SM, AllowedRegexp, CheckCapsOnly, IgnoreCommandLineMacros));
 }
Index: clang-tools-extra/clang-tidy/ClangTidyCheck.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyCheck.h
+++ clang-tools-extra/clang-tidy/ClangTidyCheck.h
@@ -89,7 +89,7 @@
   ///    When modules are not enabled ModuleExpanderPP just points to the real
   ///    preprocessor.
   virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
-                                   Preprocessor *ModuleExpanderPP) {}
+                                   Preprocessor *ModuleExpanderPP);
 
   /// Override this to register AST matchers with \p Finder.
   ///
Index: clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
@@ -11,10 +11,26 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/YAMLParser.h"
+#include "utils/PPTree.h"
+
+#include <iostream>
 
 namespace clang {
 namespace tidy {
 
+namespace {
+class CheckPPTreeConsumer : public utils::PPTreeConsumer {
+public:
+  void endOfMainFile(const utils::PPTree *Tree) override {
+    std::cout << "End of main file: " << Tree->Directives.size() << " directives.\n";
+  }
+};
+
+}
+
+CheckPPTreeConsumer TreeConsumer;
+static std::unique_ptr<utils::PPTreeBuilder> TreeBuilder;
+
 ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
     : CheckName(CheckName), Context(Context),
       Options(CheckName, Context->getOptions().CheckOptions, Context) {
@@ -22,6 +38,11 @@
   assert(!CheckName.empty());
 }
 
+void ClangTidyCheck::registerPPCallbacks(const SourceManager &SM,
+    Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+  TreeBuilder.reset(new utils::PPTreeBuilder(&TreeConsumer, PP, SM, getLangOpts()));
+}
+
 DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
                                        DiagnosticIDs::Level Level) {
   return Context->diag(CheckName, Loc, Message, Level);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to