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