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;
68 CompilerInstance *CI, llvm::vfs::OverlayFileSystem &OverlayFS)
69 : Recorder(std::make_unique<
FileRecorder>()), Compiler(*CI),
70 InMemoryFs(new
llvm::vfs::InMemoryFileSystem),
71 Sources(Compiler.getSourceManager()),
73 Diags(DiagnosticIDs::create(), DiagOpts,
74 new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
75 LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) {
78 OverlayFS.pushOverlay(InMemoryFs);
80 Diags.setSourceManager(&Sources);
83 ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts(),
84 Compiler.getVirtualFileSystem());
86 LangOpts.Modules =
false;
88 HeaderInfo = std::make_unique<HeaderSearch>(HSOpts, Sources, Diags, LangOpts,
89 &Compiler.getTarget());
91 PP = std::make_unique<clang::Preprocessor>(Compiler.getPreprocessorOpts(),
92 Diags, LangOpts, Sources,
93 *HeaderInfo, ModuleLoader,
96 PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
97 InitializePreprocessor(*PP, Compiler.getPreprocessorOpts(),
98 Compiler.getPCHContainerReader(),
99 Compiler.getFrontendOpts(), Compiler.getCodeGenOpts());
100 ApplyHeaderSearchOptions(*HeaderInfo, HSOpts, LangOpts,
101 Compiler.getTarget().getTriple());
110void ExpandModularHeadersPPCallbacks::handleModuleFile(
111 serialization::ModuleFile *MF) {
115 if (!VisitedModules.insert(MF).second)
120 Compiler.getASTReader()->visitInputFiles(
122 [
this](
const serialization::InputFile &IF,
bool ) {
123 Recorder->addNecessaryFile(*IF.getFile());
126 for (
auto *Import : MF->Imports)
127 handleModuleFile(Import);
130void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {
132 for (
unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I)
133 Sources.getLoadedSLocEntry(I,
nullptr);
135 for (
auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It)
136 Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
137 Recorder->checkAllFilesRecorded();
139 if (!StartedLexing) {
140 StartedLexing =
true;
141 PP->Lex(CurrentToken);
143 while (!CurrentToken.is(tok::eof) &&
144 Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
145 PP->Lex(CurrentToken);
149void ExpandModularHeadersPPCallbacks::FileChanged(
150 SourceLocation Loc, FileChangeReason Reason,
151 SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
152 if (!EnteredMainFile) {
153 EnteredMainFile =
true;
154 PP->EnterMainSourceFile();
158void ExpandModularHeadersPPCallbacks::InclusionDirective(
159 SourceLocation DirectiveLoc,
const Token &IncludeToken,
160 StringRef IncludedFilename,
bool IsAngled, CharSourceRange FilenameRange,
161 OptionalFileEntryRef IncludedFile, StringRef SearchPath,
162 StringRef RelativePath,
const Module *SuggestedModule,
bool ModuleImported,
163 SrcMgr::CharacteristicKind FileType) {
164 if (ModuleImported) {
165 serialization::ModuleFile *MF =
166 Compiler.getASTReader()->getModuleManager().lookup(
167 *SuggestedModule->getASTFile());
168 handleModuleFile(MF);
170 parseToLocation(DirectiveLoc);
173void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
174 while (!CurrentToken.is(tok::eof))
175 PP->Lex(CurrentToken);
181void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
182 parseToLocation(Loc);
184void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
185 PragmaIntroducerKind) {
186 parseToLocation(Loc);
188void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
189 const IdentifierInfo *,
191 parseToLocation(Loc);
193void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
196 parseToLocation(Loc);
198void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
200 parseToLocation(Loc);
202void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
206 parseToLocation(Loc);
208void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
210 parseToLocation(Loc);
212void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
214 parseToLocation(Loc);
216void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
220 parseToLocation(Loc);
222void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
223 bool, OptionalFileEntryRef,
224 SrcMgr::CharacteristicKind) {
225 parseToLocation(Loc);
227void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
228 SourceLocation NameLoc,
const IdentifierInfo *, SourceLocation StateLoc,
231 parseToLocation(NameLoc);
233void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
234 PragmaWarningSpecifier,
236 parseToLocation(Loc);
238void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
240 parseToLocation(Loc);
242void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
243 parseToLocation(Loc);
245void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
246 SourceLocation Loc) {
247 parseToLocation(Loc);
249void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
250 SourceLocation Loc) {
251 parseToLocation(Loc);
253void ExpandModularHeadersPPCallbacks::MacroExpands(
const Token &MacroNameTok,
254 const MacroDefinition &,
258 parseToLocation(Range.getBegin());
260void ExpandModularHeadersPPCallbacks::MacroDefined(
const Token &MacroNameTok,
261 const MacroDirective *MD) {
262 parseToLocation(MD->getLocation());
264void ExpandModularHeadersPPCallbacks::MacroUndefined(
265 const Token &,
const MacroDefinition &,
const MacroDirective *Undef) {
267 parseToLocation(Undef->getLocation());
269void ExpandModularHeadersPPCallbacks::Defined(
const Token &MacroNameTok,
270 const MacroDefinition &,
273 parseToLocation(Range.getBegin());
275void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
276 SourceRange Range, SourceLocation EndifLoc) {
278 parseToLocation(EndifLoc);
280void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
281 ConditionValueKind) {
282 parseToLocation(Loc);
284void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
285 ConditionValueKind, SourceLocation) {
286 parseToLocation(Loc);
288void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc,
const Token &,
289 const MacroDefinition &) {
290 parseToLocation(Loc);
292void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc,
const Token &,
293 const MacroDefinition &) {
294 parseToLocation(Loc);
296void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
297 parseToLocation(Loc);
299void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
301 parseToLocation(Loc);
Some operations such as code completion produce a set of candidates.