Skip to content

Commit 105e148

Browse files
committed
Interface with explicit cloneFor(FileManager&) API
1 parent 00099cc commit 105e148

File tree

7 files changed

+78
-76
lines changed

7 files changed

+78
-76
lines changed

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ class CompilerInstance : public ModuleLoader {
100100
/// The cache of PCM files.
101101
IntrusiveRefCntPtr<ModuleCache> ModCache;
102102

103-
/// Function for getting the dependency preprocessor directives of a file.
104-
GetDependencyDirectivesFn GetDependencyDirectives;
103+
/// Functor for getting the dependency preprocessor directives of a file.
104+
std::unique_ptr<DependencyDirectivesGetter> GetDependencyDirectives;
105105

106106
/// The preprocessor.
107107
std::shared_ptr<Preprocessor> PP;
@@ -701,8 +701,9 @@ class CompilerInstance : public ModuleLoader {
701701
/// and replace any existing one with it.
702702
void createPreprocessor(TranslationUnitKind TUKind);
703703

704-
void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
705-
GetDependencyDirectives = Fn;
704+
void setDependencyDirectivesGetter(
705+
std::unique_ptr<DependencyDirectivesGetter> Getter) {
706+
GetDependencyDirectives = std::move(Getter);
706707
}
707708

708709
std::string getSpecificModuleCachePath(StringRef ModuleHash);

clang/include/clang/Lex/DependencyDirectivesScanner.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,19 @@ void printDependencyDirectivesAsSource(
136136
ArrayRef<dependency_directives_scan::Directive> Directives,
137137
llvm::raw_ostream &OS);
138138

139-
// FIXME: Allow returning an error.
140-
using GetDependencyDirectivesFn = std::function<
141-
std::optional<ArrayRef<dependency_directives_scan::Directive>>(
142-
FileManager &, FileEntryRef)>;
143-
139+
/// Functor that returns the dependency directives for a given file.
140+
class DependencyDirectivesGetter {
141+
public:
142+
/// Clone the getter for a new \c FileManager instance.
143+
virtual std::unique_ptr<DependencyDirectivesGetter>
144+
cloneFor(FileManager &FileMgr) = 0;
145+
146+
/// Get the dependency directives for the given file.
147+
virtual std::optional<ArrayRef<dependency_directives_scan::Directive>>
148+
operator()(FileEntryRef File) = 0;
149+
150+
virtual ~DependencyDirectivesGetter() = default;
151+
};
144152
} // end namespace clang
145153

146154
#endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,12 @@ class Preprocessor {
140140
friend class VariadicMacroScopeGuard;
141141

142142
llvm::unique_function<void(const clang::Token &)> OnToken;
143-
/// Function for getting the dependency preprocessor directives of a file.
143+
/// Functor for getting the dependency preprocessor directives of a file.
144144
///
145145
/// These are directives derived from a special form of lexing where the
146146
/// source input is scanned for the preprocessor directives that might have an
147147
/// effect on the dependencies for a compilation unit.
148-
GetDependencyDirectivesFn GetDependencyDirectives;
148+
DependencyDirectivesGetter *GetDependencyDirectives = nullptr;
149149
const PreprocessorOptions &PPOpts;
150150
DiagnosticsEngine *Diags;
151151
const LangOptions &LangOpts;
@@ -1332,8 +1332,8 @@ class Preprocessor {
13321332
OnToken = std::move(F);
13331333
}
13341334

1335-
void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
1336-
GetDependencyDirectives = Fn;
1335+
void setDependencyDirectivesGetter(DependencyDirectivesGetter &Get) {
1336+
GetDependencyDirectives = &Get;
13371337
}
13381338

13391339
void setPreprocessToken(bool Preprocess) { PreprocessToken = Preprocess; }

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
537537
}
538538

539539
if (GetDependencyDirectives)
540-
PP->setDependencyDirectivesGetter(GetDependencyDirectives);
540+
PP->setDependencyDirectivesGetter(*GetDependencyDirectives);
541541
}
542542

543543
std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) {
@@ -1240,7 +1240,9 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
12401240
// Make a copy for the new instance.
12411241
Instance.FailedModules = FailedModules;
12421242

1243-
Instance.GetDependencyDirectives = GetDependencyDirectives;
1243+
if (GetDependencyDirectives)
1244+
Instance.GetDependencyDirectives =
1245+
GetDependencyDirectives->cloneFor(Instance.getFileManager());
12441246

12451247
// If we're collecting module dependencies, we need to share a collector
12461248
// between all of the module CompilerInstances. Other than that, we don't

clang/lib/Lex/PPLexerChange.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ bool Preprocessor::EnterSourceFile(FileID FID, ConstSearchDirIterator CurDir,
9494
Lexer *TheLexer = new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile);
9595
if (GetDependencyDirectives && FID != PredefinesFileID)
9696
if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID))
97-
if (auto MaybeDepDirectives = GetDependencyDirectives(FileMgr, *File))
97+
if (auto MaybeDepDirectives = (*GetDependencyDirectives)(*File))
9898
TheLexer->DepDirectives = *MaybeDepDirectives;
9999

100100
EnterSourceFileWithLexer(TheLexer, CurDir);

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -357,56 +357,31 @@ static void canonicalizeDefines(PreprocessorOptions &PPOpts) {
357357
std::swap(PPOpts.Macros, NewMacros);
358358
}
359359

360-
static GetDependencyDirectivesFn makeDepDirectivesGetter() {
361-
/// This is a functor that conforms to \c GetDependencyDirectivesFn.
362-
/// It ensures it's always invoked with the same \c FileManager and caches the
363-
/// extraction of the scanning VFS for better performance.
364-
struct DepDirectivesGetter {
365-
DepDirectivesGetter() : DepFS(nullptr), FM(nullptr) {}
366-
367-
/// It's important copies do not carry over the cached members. The copies
368-
/// are likely to be used from distinct \c CompilerInstance objects with
369-
/// distinct \c FileManager \c llvm::vfs::FileSystem.
370-
DepDirectivesGetter(const DepDirectivesGetter &)
371-
: DepFS(nullptr), FM(nullptr) {}
372-
DepDirectivesGetter &operator=(const DepDirectivesGetter &) {
373-
DepFS = nullptr;
374-
FM = nullptr;
375-
return *this;
376-
}
377-
378-
auto operator()(FileManager &FileMgr, FileEntryRef File) {
379-
ensureConsistentFileManager(FileMgr);
380-
ensurePopulatedFileSystem(FileMgr);
381-
return DepFS->getDirectiveTokens(File.getName());
382-
}
360+
class ActualDependencyDirectivesGetter : public DependencyDirectivesGetter {
361+
DependencyScanningWorkerFilesystem *DepFS;
383362

384-
private:
385-
DependencyScanningWorkerFilesystem *DepFS;
386-
FileManager *FM;
387-
388-
void ensureConsistentFileManager(FileManager &FileMgr) {
389-
if (!FM)
390-
FM = &FileMgr;
391-
assert(&FileMgr == FM);
392-
}
363+
public:
364+
ActualDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) {
365+
FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
366+
auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
367+
if (DFS) {
368+
assert(!DepFS && "Found multiple scanning VFSs");
369+
DepFS = DFS;
370+
}
371+
});
372+
assert(DepFS && "Did not find scanning VFS");
373+
}
393374

394-
void ensurePopulatedFileSystem(FileManager &FM) {
395-
if (DepFS)
396-
return;
397-
FM.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
398-
auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
399-
if (DFS) {
400-
assert(!DepFS && "Found multiple scanning VFSs");
401-
DepFS = DFS;
402-
}
403-
});
404-
assert(DepFS && "Did not find scanning VFS");
405-
}
406-
};
375+
std::unique_ptr<DependencyDirectivesGetter>
376+
cloneFor(FileManager &FileMgr) override {
377+
return std::make_unique<ActualDependencyDirectivesGetter>(FileMgr);
378+
}
407379

408-
return DepDirectivesGetter{};
409-
}
380+
std::optional<ArrayRef<dependency_directives_scan::Directive>>
381+
operator()(FileEntryRef File) override {
382+
return DepFS->getDirectiveTokens(File.getName());
383+
}
384+
};
410385

411386
/// A clang tool that runs the preprocessor in a mode that's optimized for
412387
/// dependency scanning for the given compiler invocation.
@@ -475,6 +450,9 @@ class DependencyScanningAction : public tooling::ToolAction {
475450
ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
476451
DriverFileMgr->getVirtualFileSystemPtr());
477452

453+
// Create a new FileManager to match the invocation's FileSystemOptions.
454+
auto *FileMgr = ScanInstance.createFileManager(FS);
455+
478456
// Use the dependency scanning optimized file system if requested to do so.
479457
if (DepFS) {
480458
StringRef ModulesCachePath =
@@ -484,11 +462,10 @@ class DependencyScanningAction : public tooling::ToolAction {
484462
if (!ModulesCachePath.empty())
485463
DepFS->setBypassedPathPrefix(ModulesCachePath);
486464

487-
ScanInstance.setDependencyDirectivesGetter(makeDepDirectivesGetter());
465+
ScanInstance.setDependencyDirectivesGetter(
466+
std::make_unique<ActualDependencyDirectivesGetter>(*FileMgr));
488467
}
489468

490-
// Create a new FileManager to match the invocation's FileSystemOptions.
491-
auto *FileMgr = ScanInstance.createFileManager(FS);
492469
ScanInstance.createSourceManager(*FileMgr);
493470

494471
// Store a mapping of prebuilt module files and their properties like header

clang/unittests/Lex/PPDependencyDirectivesTest.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,31 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
103103
SmallVector<dependency_directives_scan::Token> Tokens;
104104
SmallVector<dependency_directives_scan::Directive> Directives;
105105
};
106-
SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
107-
108-
auto GetDependencyDirectives = [&](FileManager &FileMgr, FileEntryRef File) {
109-
DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
110-
StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
111-
bool Err = scanSourceForDependencyDirectives(
112-
Input, DepDirectivesObjects.back()->Tokens,
113-
DepDirectivesObjects.back()->Directives);
114-
EXPECT_FALSE(Err);
115-
return llvm::ArrayRef(DepDirectivesObjects.back()->Directives);
106+
107+
class TestDependencyDirectivesGetter : public DependencyDirectivesGetter {
108+
FileManager &FileMgr;
109+
SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
110+
111+
public:
112+
TestDependencyDirectivesGetter(FileManager &FileMgr) : FileMgr(FileMgr) {}
113+
114+
std::unique_ptr<DependencyDirectivesGetter>
115+
cloneFor(FileManager &FileMgr) override {
116+
return std::make_unique<TestDependencyDirectivesGetter>(FileMgr);
117+
}
118+
119+
std::optional<ArrayRef<dependency_directives_scan::Directive>>
120+
operator()(FileEntryRef File) override {
121+
DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
122+
StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
123+
bool Err = scanSourceForDependencyDirectives(
124+
Input, DepDirectivesObjects.back()->Tokens,
125+
DepDirectivesObjects.back()->Directives);
126+
EXPECT_FALSE(Err);
127+
return DepDirectivesObjects.back()->Directives;
128+
}
116129
};
130+
TestDependencyDirectivesGetter GetDependencyDirectives(FileMgr);
117131

118132
PreprocessorOptions PPOpts;
119133
HeaderSearchOptions HSOpts;

0 commit comments

Comments
 (0)