1 //===- ExpandModularHeadersPPCallbacks.h - clang-tidy -----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_ 10 #define LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_ 11 12 #include "clang/Lex/PPCallbacks.h" 13 #include "clang/Lex/Preprocessor.h" 14 #include "llvm/ADT/DenseSet.h" 15 16 namespace llvm::vfs { 17 class OverlayFileSystem; 18 class InMemoryFileSystem; 19 } // namespace llvm::vfs 20 21 namespace clang { 22 class CompilerInstance; 23 24 namespace serialization { 25 class ModuleFile; 26 } // namespace serialization 27 28 namespace tooling { 29 30 /// Handles PPCallbacks and re-runs preprocessing of the whole 31 /// translation unit with modules disabled. 32 /// 33 /// This way it's possible to get PPCallbacks for the whole translation unit 34 /// including the contents of the modular headers and all their transitive 35 /// includes. 36 /// 37 /// This allows existing tools based on PPCallbacks to retain their functionality 38 /// when running with C++ modules enabled. This only works in the backwards 39 /// compatible modules mode, i.e. when code can still be parsed in non-modular 40 /// way. 41 class ExpandModularHeadersPPCallbacks : public PPCallbacks { 42 public: 43 ExpandModularHeadersPPCallbacks( 44 CompilerInstance *CI, 45 IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS); 46 ~ExpandModularHeadersPPCallbacks(); 47 48 /// Returns the preprocessor that provides callbacks for the whole 49 /// translation unit, including the main file, textual headers, and modular 50 /// headers. 51 /// 52 /// This preprocessor is separate from the one used by the rest of the 53 /// compiler. 54 Preprocessor *getPreprocessor() const; 55 56 private: 57 class FileRecorder; 58 59 void handleModuleFile(serialization::ModuleFile *MF); 60 void parseToLocation(SourceLocation Loc); 61 62 // Handle PPCallbacks. 63 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 64 SrcMgr::CharacteristicKind FileType, 65 FileID PrevFID) override; 66 67 void InclusionDirective(SourceLocation DirectiveLoc, 68 const Token &IncludeToken, StringRef IncludedFilename, 69 bool IsAngled, CharSourceRange FilenameRange, 70 OptionalFileEntryRef IncludedFile, 71 StringRef SearchPath, StringRef RelativePath, 72 const Module *SuggestedModule, bool ModuleImported, 73 SrcMgr::CharacteristicKind FileType) override; 74 75 void EndOfMainFile() override; 76 77 // Handle all other callbacks. 78 // Just parse to the corresponding location to generate PPCallbacks for the 79 // corresponding range 80 void Ident(SourceLocation Loc, StringRef) override; 81 void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override; 82 void PragmaComment(SourceLocation Loc, const IdentifierInfo *, 83 StringRef) override; 84 void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override; 85 void PragmaDebug(SourceLocation Loc, StringRef) override; 86 void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind, 87 StringRef) override; 88 void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override; 89 void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override; 90 void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity, 91 StringRef) override; 92 void HasInclude(SourceLocation Loc, StringRef, bool, OptionalFileEntryRef, 93 SrcMgr::CharacteristicKind) override; 94 void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *, 95 SourceLocation StateLoc, unsigned) override; 96 void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier, 97 ArrayRef<int>) override; 98 void PragmaWarningPush(SourceLocation Loc, int) override; 99 void PragmaWarningPop(SourceLocation Loc) override; 100 void PragmaAssumeNonNullBegin(SourceLocation Loc) override; 101 void PragmaAssumeNonNullEnd(SourceLocation Loc) override; 102 void MacroExpands(const Token &MacroNameTok, const MacroDefinition &, 103 SourceRange Range, const MacroArgs *) override; 104 void MacroDefined(const Token &MacroNameTok, 105 const MacroDirective *MD) override; 106 void MacroUndefined(const Token &, const MacroDefinition &, 107 const MacroDirective *Undef) override; 108 void Defined(const Token &MacroNameTok, const MacroDefinition &, 109 SourceRange Range) override; 110 void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; 111 void If(SourceLocation Loc, SourceRange, ConditionValueKind) override; 112 void Elif(SourceLocation Loc, SourceRange, ConditionValueKind, 113 SourceLocation) override; 114 void Ifdef(SourceLocation Loc, const Token &, 115 const MacroDefinition &) override; 116 void Ifndef(SourceLocation Loc, const Token &, 117 const MacroDefinition &) override; 118 void Else(SourceLocation Loc, SourceLocation) override; 119 void Endif(SourceLocation Loc, SourceLocation) override; 120 121 std::unique_ptr<FileRecorder> Recorder; 122 // Set of all the modules visited. Avoids processing a module more than once. 123 llvm::DenseSet<serialization::ModuleFile *> VisitedModules; 124 125 CompilerInstance &Compiler; 126 // Additional filesystem for replay. Provides all input files from modules. 127 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs; 128 129 SourceManager &Sources; 130 DiagnosticsEngine Diags; 131 LangOptions LangOpts; 132 TrivialModuleLoader ModuleLoader; 133 134 std::unique_ptr<HeaderSearch> HeaderInfo; 135 std::unique_ptr<Preprocessor> PP; 136 bool EnteredMainFile = false; 137 bool StartedLexing = false; 138 Token CurrentToken; 139 }; 140 141 } // namespace tooling 142 } // namespace clang 143 144 #endif // LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_ 145