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 { 17 namespace vfs { 18 class OverlayFileSystem; 19 class InMemoryFileSystem; 20 } // namespace vfs 21 } // namespace llvm 22 23 namespace clang { 24 class CompilerInstance; 25 26 namespace serialization { 27 class ModuleFile; 28 } // namespace serialization 29 30 namespace tooling { 31 32 /// Handles PPCallbacks and re-runs preprocessing of the whole 33 /// translation unit with modules disabled. 34 /// 35 /// This way it's possible to get PPCallbacks for the whole translation unit 36 /// including the contents of the modular headers and all their transitive 37 /// includes. 38 /// 39 /// This allows existing tools based on PPCallbacks to retain their functionality 40 /// when running with C++ modules enabled. This only works in the backwards 41 /// compatible modules mode, i.e. when code can still be parsed in non-modular 42 /// way. 43 class ExpandModularHeadersPPCallbacks : public PPCallbacks { 44 public: 45 ExpandModularHeadersPPCallbacks( 46 CompilerInstance *Compiler, 47 IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS); 48 ~ExpandModularHeadersPPCallbacks(); 49 50 /// Returns the preprocessor that provides callbacks for the whole 51 /// translation unit, including the main file, textual headers, and modular 52 /// headers. 53 /// 54 /// This preprocessor is separate from the one used by the rest of the 55 /// compiler. 56 Preprocessor *getPreprocessor() const; 57 58 private: 59 class FileRecorder; 60 61 void handleModuleFile(serialization::ModuleFile *MF); 62 void parseToLocation(SourceLocation Loc); 63 64 // Handle PPCallbacks. 65 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 66 SrcMgr::CharacteristicKind FileType, 67 FileID PrevFID) override; 68 69 void InclusionDirective(SourceLocation DirectiveLoc, 70 const Token &IncludeToken, StringRef IncludedFilename, 71 bool IsAngled, CharSourceRange FilenameRange, 72 const FileEntry *IncludedFile, StringRef SearchPath, 73 StringRef RelativePath, const Module *Imported, 74 SrcMgr::CharacteristicKind FileType) override; 75 76 void EndOfMainFile() override; 77 78 // Handle all other callbacks. 79 // Just parse to the corresponding location to generate PPCallbacks for the 80 // corresponding range 81 void Ident(SourceLocation Loc, StringRef) override; 82 void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override; 83 void PragmaComment(SourceLocation Loc, const IdentifierInfo *, 84 StringRef) override; 85 void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override; 86 void PragmaDebug(SourceLocation Loc, StringRef) override; 87 void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind, 88 StringRef) override; 89 void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override; 90 void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override; 91 void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity, 92 StringRef) override; 93 void HasInclude(SourceLocation Loc, StringRef, bool, Optional<FileEntryRef> , 94 SrcMgr::CharacteristicKind) override; 95 void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *, 96 SourceLocation StateLoc, unsigned) override; 97 void PragmaWarning(SourceLocation Loc, StringRef, 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