[Frontend] Honor UserFilesAreVolatile flag getting file buffer in ASTUnit

Do not memory map the main file if the flag UserFilesAreVolatile is set to true
in ASTUnit when calling FileSystem::getBufferForFile.

Differential Revision: https://reviews.llvm.org/D47460

llvm-svn: 334070
This commit is contained in:
Ivan Donchevskii 2018-06-06 07:17:26 +00:00
parent cb5b004a9b
commit 2ebe3a0240
4 changed files with 64 additions and 36 deletions

View File

@ -239,7 +239,7 @@ public:
getBufferForFile(const FileEntry *Entry, bool isVolatile = false, getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
bool ShouldCloseOpenFile = true); bool ShouldCloseOpenFile = true);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(StringRef Filename); getBufferForFile(StringRef Filename, bool isVolatile = false);
/// Get the 'stat' information for the given \p Path. /// Get the 'stat' information for the given \p Path.
/// ///

View File

@ -450,13 +450,13 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
} }
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(StringRef Filename) { FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
if (FileSystemOpts.WorkingDir.empty()) if (FileSystemOpts.WorkingDir.empty())
return FS->getBufferForFile(Filename); return FS->getBufferForFile(Filename, -1, true, isVolatile);
SmallString<128> FilePath(Filename); SmallString<128> FilePath(Filename);
FixupRelativePath(FilePath); FixupRelativePath(FilePath);
return FS->getBufferForFile(FilePath.c_str()); return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile);
} }
/// getStatValue - Get the 'stat' information for the specified path, /// getStatValue - Get the 'stat' information for the specified path,

View File

@ -156,7 +156,8 @@ static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
static std::unique_ptr<llvm::MemoryBuffer> static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
vfs::FileSystem *VFS, vfs::FileSystem *VFS,
StringRef FilePath) { StringRef FilePath,
bool isVolatile) {
const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();
// Try to determine if the main file has been remapped, either from the // Try to determine if the main file has been remapped, either from the
@ -176,7 +177,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
if (MainFileID == MID) { if (MainFileID == MID) {
// We found a remapping. Try to load the resulting, remapped source. // We found a remapping. Try to load the resulting, remapped source.
BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second)); BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));
if (!BufferOwner) if (!BufferOwner)
return nullptr; return nullptr;
} }
@ -201,7 +202,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
// If the main source file was not remapped, load it now. // If the main source file was not remapped, load it now.
if (!Buffer && !BufferOwner) { if (!Buffer && !BufferOwner) {
BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath)); BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));
if (!BufferOwner) if (!BufferOwner)
return nullptr; return nullptr;
} }
@ -707,7 +708,7 @@ ASTDeserializationListener *ASTUnit::getDeserializationListener() {
std::unique_ptr<llvm::MemoryBuffer> std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
assert(FileMgr); assert(FileMgr);
auto Buffer = FileMgr->getBufferForFile(Filename); auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);
if (Buffer) if (Buffer)
return std::move(*Buffer); return std::move(*Buffer);
if (ErrorStr) if (ErrorStr)
@ -1278,7 +1279,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile(); PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer = std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(), getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),
MainFilePath); MainFilePath, UserFilesAreVolatile);
if (!MainFileBuffer) if (!MainFileBuffer)
return nullptr; return nullptr;

View File

@ -23,7 +23,41 @@ using namespace clang;
namespace { namespace {
TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) { class ASTUnitTest : public ::testing::Test {
protected:
int FD;
llvm::SmallString<256> InputFileName;
std::unique_ptr<ToolOutputFile> input_file;
IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
std::shared_ptr<CompilerInvocation> CInvok;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
std::unique_ptr<ASTUnit> createASTUnit(bool isVolatile) {
EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD,
InputFileName));
input_file = std::make_unique<ToolOutputFile>(InputFileName, FD);
input_file->os() << "";
const char *Args[] = {"clang", "-xc++", InputFileName.c_str()};
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
CInvok = createInvocationFromCommandLine(Args, Diags);
if (!CInvok)
return nullptr;
FileManager *FileMgr =
new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
PCHContainerOps = std::make_shared<PCHContainerOperations>();
return ASTUnit::LoadFromCompilerInvocation(
CInvok, PCHContainerOps, Diags, FileMgr, false, false, 0, TU_Complete,
false, false, isVolatile);
}
};
TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) {
// Check that the printing policy is restored with the correct language // Check that the printing policy is restored with the correct language
// options when loading an ASTUnit from a file. To this end, an ASTUnit // options when loading an ASTUnit from a file. To this end, an ASTUnit
// for a C++ translation unit is set up and written to a temporary file. // for a C++ translation unit is set up and written to a temporary file.
@ -38,29 +72,7 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams); EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams);
} }
int FD; std::unique_ptr<ASTUnit> AST = createASTUnit(false);
llvm::SmallString<256> InputFileName;
ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD, InputFileName));
ToolOutputFile input_file(InputFileName, FD);
input_file.os() << "";
const char* Args[] = {"clang", "-xc++", InputFileName.c_str()};
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions());
std::shared_ptr<CompilerInvocation> CInvok =
createInvocationFromCommandLine(Args, Diags);
if (!CInvok)
FAIL() << "could not create compiler invocation";
FileManager *FileMgr =
new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
CInvok, PCHContainerOps, Diags, FileMgr);
if (!AST) if (!AST)
FAIL() << "failed to create ASTUnit"; FAIL() << "failed to create ASTUnit";
@ -68,15 +80,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams); EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
llvm::SmallString<256> ASTFileName; llvm::SmallString<256> ASTFileName;
ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName)); ASSERT_FALSE(
llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
ToolOutputFile ast_file(ASTFileName, FD); ToolOutputFile ast_file(ASTFileName, FD);
AST->Save(ASTFileName.str()); AST->Save(ASTFileName.str());
EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName)); EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile( std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
ASTFileName.str(), PCHContainerOps->getRawReader(), ASTUnit::LoadEverything, Diags, ASTFileName.str(), PCHContainerOps->getRawReader(),
FileSystemOptions(), /*UseDebugInfo=*/false); ASTUnit::LoadEverything, Diags, FileSystemOptions(),
/*UseDebugInfo=*/false);
if (!AU) if (!AU)
FAIL() << "failed to load ASTUnit"; FAIL() << "failed to load ASTUnit";
@ -84,4 +98,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams); EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
} }
TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
std::unique_ptr<ASTUnit> AST = createASTUnit(true);
if (!AST)
FAIL() << "failed to create ASTUnit";
std::unique_ptr<llvm::MemoryBuffer> memoryBuffer =
AST->getBufferForFile(InputFileName);
EXPECT_NE(memoryBuffer->getBufferKind(),
llvm::MemoryBuffer::MemoryBuffer_MMap);
}
} // anonymous namespace } // anonymous namespace