10#include "clang/Basic/FileManager.h"
11#include "clang/Basic/TargetInfo.h"
12#include "clang/Frontend/CompilerInstance.h"
13#include "clang/Lex/PreprocessorOptions.h"
14#include "clang/Serialization/ASTReader.h"
17#define DEBUG_TYPE "clang-tidy"
26 if (!(File.getName().ends_with(
"module.modulemap") ||
27 File.getName().ends_with(
"module.private.modulemap") ||
28 File.getName().ends_with(
"module.map") ||
29 File.getName().ends_with(
"module_private.map")))
30 FilesToRecord.insert(File);
35 const SrcMgr::ContentCache &ContentCache,
36 llvm::vfs::InMemoryFileSystem &InMemoryFs) {
38 if (!FilesToRecord.contains(File))
42 std::optional<StringRef> Data = ContentCache.getBufferDataIfLoaded();
46 InMemoryFs.addFile(File.getName(), 0,
47 llvm::MemoryBuffer::getMemBufferCopy(*Data));
49 FilesToRecord.erase(File);
56 for (
auto FileEntry : FilesToRecord)
57 llvm::dbgs() <<
"Did not record contents for input file: "
58 << FileEntry.getName() <<
"\n";
64 llvm::DenseSet<FileEntryRef> FilesToRecord;
69 IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
70 : Recorder(std::make_unique<
FileRecorder>()), Compiler(*CI),
71 InMemoryFs(new
llvm::vfs::InMemoryFileSystem),
72 Sources(Compiler.getSourceManager()),
74 Diags(DiagnosticIDs::create(), DiagOpts,
75 new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
76 LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) {
79 OverlayFS->pushOverlay(InMemoryFs);
81 Diags.setSourceManager(&Sources);
84 ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts(),
85 Compiler.getVirtualFileSystem());
87 LangOpts.Modules =
false;
89 HeaderInfo = std::make_unique<HeaderSearch>(HSOpts, Sources, Diags, LangOpts,
90 &Compiler.getTarget());
92 PP = std::make_unique<clang::Preprocessor>(Compiler.getPreprocessorOpts(),
93 Diags, LangOpts, Sources,
94 *HeaderInfo, ModuleLoader,
97 PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
98 InitializePreprocessor(*PP, Compiler.getPreprocessorOpts(),
99 Compiler.getPCHContainerReader(),
100 Compiler.getFrontendOpts(), Compiler.getCodeGenOpts());
101 ApplyHeaderSearchOptions(*HeaderInfo, HSOpts, LangOpts,
102 Compiler.getTarget().getTriple());
111void ExpandModularHeadersPPCallbacks::handleModuleFile(
112 serialization::ModuleFile *MF) {
116 if (!VisitedModules.insert(MF).second)
121 Compiler.getASTReader()->visitInputFiles(
123 [
this](
const serialization::InputFile &IF,
bool ) {
124 Recorder->addNecessaryFile(*IF.getFile());
127 for (
auto *Import : MF->Imports)
128 handleModuleFile(Import);
131void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {
133 for (
unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) {
134 Sources.getLoadedSLocEntry(I,
nullptr);
137 for (
auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {
138 Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
140 Recorder->checkAllFilesRecorded();
142 if (!StartedLexing) {
143 StartedLexing =
true;
144 PP->Lex(CurrentToken);
146 while (!CurrentToken.is(tok::eof) &&
147 Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
148 PP->Lex(CurrentToken);
152void ExpandModularHeadersPPCallbacks::FileChanged(
153 SourceLocation Loc, FileChangeReason Reason,
154 SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
155 if (!EnteredMainFile) {
156 EnteredMainFile =
true;
157 PP->EnterMainSourceFile();
161void ExpandModularHeadersPPCallbacks::InclusionDirective(
162 SourceLocation DirectiveLoc,
const Token &IncludeToken,
163 StringRef IncludedFilename,
bool IsAngled, CharSourceRange FilenameRange,
164 OptionalFileEntryRef IncludedFile, StringRef SearchPath,
165 StringRef RelativePath,
const Module *SuggestedModule,
bool ModuleImported,
166 SrcMgr::CharacteristicKind FileType) {
167 if (ModuleImported) {
168 serialization::ModuleFile *MF =
169 Compiler.getASTReader()->getModuleManager().lookup(
170 *SuggestedModule->getASTFile());
171 handleModuleFile(MF);
173 parseToLocation(DirectiveLoc);
176void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
177 while (!CurrentToken.is(tok::eof))
178 PP->Lex(CurrentToken);
184void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
185 parseToLocation(Loc);
187void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
188 PragmaIntroducerKind) {
189 parseToLocation(Loc);
191void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
192 const IdentifierInfo *,
194 parseToLocation(Loc);
196void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
199 parseToLocation(Loc);
201void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
203 parseToLocation(Loc);
205void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
209 parseToLocation(Loc);
211void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
213 parseToLocation(Loc);
215void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
217 parseToLocation(Loc);
219void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
223 parseToLocation(Loc);
225void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
226 bool, OptionalFileEntryRef,
227 SrcMgr::CharacteristicKind) {
228 parseToLocation(Loc);
230void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
231 SourceLocation NameLoc,
const IdentifierInfo *, SourceLocation StateLoc,
234 parseToLocation(NameLoc);
236void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
237 PragmaWarningSpecifier,
239 parseToLocation(Loc);
241void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
243 parseToLocation(Loc);
245void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
246 parseToLocation(Loc);
248void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
249 SourceLocation Loc) {
250 parseToLocation(Loc);
252void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
253 SourceLocation Loc) {
254 parseToLocation(Loc);
256void ExpandModularHeadersPPCallbacks::MacroExpands(
const Token &MacroNameTok,
257 const MacroDefinition &,
261 parseToLocation(Range.getBegin());
263void ExpandModularHeadersPPCallbacks::MacroDefined(
const Token &MacroNameTok,
264 const MacroDirective *MD) {
265 parseToLocation(MD->getLocation());
267void ExpandModularHeadersPPCallbacks::MacroUndefined(
268 const Token &,
const MacroDefinition &,
const MacroDirective *Undef) {
270 parseToLocation(Undef->getLocation());
272void ExpandModularHeadersPPCallbacks::Defined(
const Token &MacroNameTok,
273 const MacroDefinition &,
276 parseToLocation(Range.getBegin());
278void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
279 SourceRange Range, SourceLocation EndifLoc) {
281 parseToLocation(EndifLoc);
283void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
284 ConditionValueKind) {
285 parseToLocation(Loc);
287void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
288 ConditionValueKind, SourceLocation) {
289 parseToLocation(Loc);
291void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc,
const Token &,
292 const MacroDefinition &) {
293 parseToLocation(Loc);
295void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc,
const Token &,
296 const MacroDefinition &) {
297 parseToLocation(Loc);
299void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
300 parseToLocation(Loc);
302void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
304 parseToLocation(Loc);
Some operations such as code completion produce a set of candidates.