-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[clang] Fix ASTUnit working directory handling
Fix a couple of issues with the handling of the current working directory in ASTUnit: - 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. - Ensure we preserve the FileSystemOptions set on the FileManager when re-creating it (as `ASTUnit::Reparse` will clear the currently set FileManager). rdar://110697657 Reviewed By: bnbarham, benlangmuir Differential Revision: https://reviews.llvm.org/D154134
- Loading branch information
1 parent
aa964f1
commit 62e4c22
Showing
4 changed files
with
158 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
//====-- unittests/Frontend/ReparseWorkingDirTest.cpp - FrontendAction tests =// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "clang/Basic/Diagnostic.h" | ||
#include "clang/Basic/FileManager.h" | ||
#include "clang/Frontend/ASTUnit.h" | ||
#include "clang/Frontend/CompilerInstance.h" | ||
#include "clang/Frontend/CompilerInvocation.h" | ||
#include "clang/Frontend/FrontendActions.h" | ||
#include "clang/Frontend/FrontendOptions.h" | ||
#include "clang/Lex/PreprocessorOptions.h" | ||
#include "llvm/Support/FileSystem.h" | ||
#include "llvm/Support/MemoryBuffer.h" | ||
#include "llvm/Support/Path.h" | ||
#include "gtest/gtest.h" | ||
|
||
using namespace llvm; | ||
using namespace clang; | ||
|
||
namespace { | ||
class ReparseWorkingDirTest : public ::testing::Test { | ||
IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS; | ||
std::shared_ptr<PCHContainerOperations> PCHContainerOpts; | ||
|
||
public: | ||
void SetUp() override { VFS = new vfs::InMemoryFileSystem(); } | ||
void TearDown() override {} | ||
|
||
void setWorkingDirectory(StringRef Path) { | ||
VFS->setCurrentWorkingDirectory(Path); | ||
} | ||
|
||
void AddFile(const std::string &Filename, const std::string &Contents) { | ||
::time_t now; | ||
::time(&now); | ||
VFS->addFile(Filename, now, | ||
MemoryBuffer::getMemBufferCopy(Contents, Filename)); | ||
} | ||
|
||
std::unique_ptr<ASTUnit> ParseAST(StringRef EntryFile) { | ||
PCHContainerOpts = std::make_shared<PCHContainerOperations>(); | ||
auto CI = std::make_shared<CompilerInvocation>(); | ||
CI->getFrontendOpts().Inputs.push_back(FrontendInputFile( | ||
EntryFile, FrontendOptions::getInputKindForExtension( | ||
llvm::sys::path::extension(EntryFile).substr(1)))); | ||
|
||
CI->getHeaderSearchOpts().AddPath("headers", | ||
frontend::IncludeDirGroup::Quoted, | ||
/*isFramework*/ false, | ||
/*IgnoreSysRoot*/ false); | ||
|
||
CI->getFileSystemOpts().WorkingDir = *VFS->getCurrentWorkingDirectory(); | ||
CI->getTargetOpts().Triple = "i386-unknown-linux-gnu"; | ||
|
||
IntrusiveRefCntPtr<DiagnosticsEngine> Diags( | ||
CompilerInstance::createDiagnostics(new DiagnosticOptions, | ||
new DiagnosticConsumer)); | ||
|
||
FileManager *FileMgr = new FileManager(CI->getFileSystemOpts(), VFS); | ||
|
||
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation( | ||
CI, PCHContainerOpts, Diags, FileMgr, false, CaptureDiagsKind::None, | ||
/*PrecompilePreambleAfterNParses=*/1); | ||
return AST; | ||
} | ||
|
||
bool ReparseAST(const std::unique_ptr<ASTUnit> &AST) { | ||
bool reparseFailed = | ||
AST->Reparse(PCHContainerOpts, /*RemappedFiles*/ {}, VFS); | ||
return !reparseFailed; | ||
} | ||
}; | ||
|
||
TEST_F(ReparseWorkingDirTest, ReparseWorkingDir) { | ||
// Setup the working directory path. | ||
SmallString<16> WorkingDir; | ||
#ifdef _WIN32 | ||
WorkingDir = "C:\\"; | ||
#else | ||
WorkingDir = "/"; | ||
#endif | ||
llvm::sys::path::append(WorkingDir, "root"); | ||
setWorkingDirectory(WorkingDir); | ||
|
||
SmallString<32> Header; | ||
llvm::sys::path::append(Header, WorkingDir, "headers", "header.h"); | ||
|
||
SmallString<32> MainName; | ||
llvm::sys::path::append(MainName, WorkingDir, "main.cpp"); | ||
|
||
AddFile(MainName.str().str(), R"cpp( | ||
#include "header.h" | ||
int main() { return foo(); } | ||
)cpp"); | ||
AddFile(Header.str().str(), R"h( | ||
static int foo() { return 0; } | ||
)h"); | ||
|
||
// Parse the main file, ensuring we can include the header. | ||
std::unique_ptr<ASTUnit> AST(ParseAST(MainName.str())); | ||
ASSERT_TRUE(AST.get()); | ||
ASSERT_FALSE(AST->getDiagnostics().hasErrorOccurred()); | ||
|
||
// Reparse and check that the working directory was preserved. | ||
ASSERT_TRUE(ReparseAST(AST)); | ||
|
||
const auto &FM = AST->getFileManager(); | ||
const auto &FS = FM.getVirtualFileSystem(); | ||
ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir); | ||
ASSERT_EQ(*FS.getCurrentWorkingDirectory(), WorkingDir); | ||
} | ||
|
||
} // end anonymous namespace |