Skip to content

Commit 9aaaa9f

Browse files
committed
[ASTUnit] Use createPhysicalFileSystem if no VFS was provided
Use `createPhysicalFileSystem` instead of `getRealFileSystem` to avoid affecting the process' current working directory, and set it at the top of `ASTUnit::LoadFromCommandLine` such that the driver used for argument parsing and the ASTUnit share the same VFS. This ensures that '-working-directory' correctly sets the VFS working directory in addition to the FileManager working directory.
1 parent ee591a9 commit 9aaaa9f

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,12 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
17521752
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
17531753
assert(Diags.get() && "no DiagnosticsEngine was provided");
17541754

1755+
// If no VFS was provided, create one that tracks the physical file system.
1756+
// If '-working-directory' was passed as an argument, 'createInvocation' will
1757+
// set this as the current working directory of the VFS.
1758+
if (!VFS)
1759+
VFS = llvm::vfs::createPhysicalFileSystem();
1760+
17551761
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
17561762

17571763
std::shared_ptr<CompilerInvocation> CI;
@@ -1801,8 +1807,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
18011807
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
18021808
AST->Diagnostics = Diags;
18031809
AST->FileSystemOpts = CI->getFileSystemOpts();
1804-
if (!VFS)
1805-
VFS = llvm::vfs::getRealFileSystem();
18061810
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
18071811
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
18081812
AST->ModuleCache = new InMemoryModuleCache;

clang/unittests/Frontend/ASTUnitTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,36 @@ TEST_F(ASTUnitTest, LoadFromCommandLineEarlyError) {
178178
ASSERT_NE(ErrUnit->stored_diag_size(), 0U);
179179
}
180180

181+
TEST_F(ASTUnitTest, LoadFromCommandLineWorkingDirectory) {
182+
EXPECT_FALSE(
183+
llvm::sys::fs::createTemporaryFile("bar", "c", FD, InputFileName));
184+
auto Input = std::make_unique<ToolOutputFile>(InputFileName, FD);
185+
Input->os() << "";
186+
187+
SmallString<128> WorkingDir;
188+
ASSERT_FALSE(sys::fs::createUniqueDirectory("foo", WorkingDir));
189+
const char *Args[] = {"clang", "-working-directory", WorkingDir.c_str(),
190+
InputFileName.c_str()};
191+
192+
auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
193+
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
194+
std::unique_ptr<clang::ASTUnit> ErrUnit;
195+
196+
auto *AST = ASTUnit::LoadFromCommandLine(
197+
&Args[0], &Args[4], PCHContainerOps, Diags, "", false,
198+
CaptureDiagsKind::All, None, true, 0, TU_Complete, false, false, false,
199+
SkipFunctionBodiesScope::None, false, true, false, false, None, &ErrUnit,
200+
nullptr);
201+
202+
ASSERT_NE(AST, nullptr);
203+
ASSERT_FALSE(Diags->hasErrorOccurred());
204+
205+
// Make sure '-working-directory' sets both the FileSystemOpts and underlying
206+
// VFS working directory.
207+
const auto &FM = AST->getFileManager();
208+
const auto &VFS = FM.getVirtualFileSystem();
209+
ASSERT_EQ(*VFS.getCurrentWorkingDirectory(), WorkingDir.str());
210+
ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir.str());
211+
}
212+
181213
} // anonymous namespace

0 commit comments

Comments
 (0)