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