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);
136 for (
auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {
137 Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
139 Recorder->checkAllFilesRecorded();
141 if (!StartedLexing) {
142 StartedLexing =
true;
143 PP->Lex(CurrentToken);
145 while (!CurrentToken.is(tok::eof) &&
146 Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
147 PP->Lex(CurrentToken);
151void ExpandModularHeadersPPCallbacks::FileChanged(
152 SourceLocation Loc, FileChangeReason Reason,
153 SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
154 if (!EnteredMainFile) {
155 EnteredMainFile =
true;
156 PP->EnterMainSourceFile();
160void ExpandModularHeadersPPCallbacks::InclusionDirective(
161 SourceLocation DirectiveLoc,
const Token &IncludeToken,
162 StringRef IncludedFilename,
bool IsAngled, CharSourceRange FilenameRange,
163 OptionalFileEntryRef IncludedFile, StringRef SearchPath,
164 StringRef RelativePath,
const Module *SuggestedModule,
bool ModuleImported,
165 SrcMgr::CharacteristicKind FileType) {
166 if (ModuleImported) {
167 serialization::ModuleFile *MF =
168 Compiler.getASTReader()->getModuleManager().lookup(
169 *SuggestedModule->getASTFile());
170 handleModuleFile(MF);
172 parseToLocation(DirectiveLoc);
175void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
176 while (!CurrentToken.is(tok::eof))
177 PP->Lex(CurrentToken);
183void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
184 parseToLocation(Loc);
186void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
187 PragmaIntroducerKind) {
188 parseToLocation(Loc);
190void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
191 const IdentifierInfo *,
193 parseToLocation(Loc);
195void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
198 parseToLocation(Loc);
200void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
202 parseToLocation(Loc);
204void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
208 parseToLocation(Loc);
210void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
212 parseToLocation(Loc);
214void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
216 parseToLocation(Loc);
218void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
222 parseToLocation(Loc);
224void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
225 bool, OptionalFileEntryRef,
226 SrcMgr::CharacteristicKind) {
227 parseToLocation(Loc);
229void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
230 SourceLocation NameLoc,
const IdentifierInfo *, SourceLocation StateLoc,
233 parseToLocation(NameLoc);
235void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
236 PragmaWarningSpecifier,
238 parseToLocation(Loc);
240void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
242 parseToLocation(Loc);
244void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
245 parseToLocation(Loc);
247void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
248 SourceLocation Loc) {
249 parseToLocation(Loc);
251void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
252 SourceLocation Loc) {
253 parseToLocation(Loc);
255void ExpandModularHeadersPPCallbacks::MacroExpands(
const Token &MacroNameTok,
256 const MacroDefinition &,
260 parseToLocation(Range.getBegin());
262void ExpandModularHeadersPPCallbacks::MacroDefined(
const Token &MacroNameTok,
263 const MacroDirective *MD) {
264 parseToLocation(MD->getLocation());
266void ExpandModularHeadersPPCallbacks::MacroUndefined(
267 const Token &,
const MacroDefinition &,
const MacroDirective *Undef) {
269 parseToLocation(Undef->getLocation());
271void ExpandModularHeadersPPCallbacks::Defined(
const Token &MacroNameTok,
272 const MacroDefinition &,
275 parseToLocation(Range.getBegin());
277void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
278 SourceRange Range, SourceLocation EndifLoc) {
280 parseToLocation(EndifLoc);
282void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
283 ConditionValueKind) {
284 parseToLocation(Loc);
286void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
287 ConditionValueKind, SourceLocation) {
288 parseToLocation(Loc);
290void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc,
const Token &,
291 const MacroDefinition &) {
292 parseToLocation(Loc);
294void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc,
const Token &,
295 const MacroDefinition &) {
296 parseToLocation(Loc);
298void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
299 parseToLocation(Loc);
301void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
303 parseToLocation(Loc);
Some operations such as code completion produce a set of candidates.