From e1b7f22b3482be5a0cc4b1ed2d73202ef904f25b Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Fri, 30 Aug 2019 22:59:25 +0000 Subject: ASTReader: Bypass overridden files when reading PCHs If contents of a file that is part of a PCM are overridden when reading it, but weren't overridden when the PCM was being built, the ASTReader will emit an error. Now it creates a separate FileEntry for recovery, bypassing the overridden content instead of discarding it. The pre-existing testcase clang/test/PCH/remap-file-from-pch.cpp confirms that the new recovery method works correctly. This resolves a long-standing FIXME to avoid hypothetically invalidating another precompiled module that's already using the overridden contents. This also removes ContentCache-related API that would be unsafe to use across `CompilerInstance`s in an implicit modules build. This helps to unblock us sinking it from SourceManager into FileManager in the future, which would allow us to delete `InMemoryModuleCache`. https://reviews.llvm.org/D66710 llvm-svn: 370546 --- clang/unittests/Basic/FileManagerTest.cpp | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'clang/unittests/Basic/FileManagerTest.cpp') diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index c55403a..9195cc0 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -397,4 +397,54 @@ TEST_F(FileManagerTest, getFileDontOpenRealPath) { EXPECT_EQ((*file)->tryGetRealPathName(), ExpectedResult); } +TEST_F(FileManagerTest, getBypassFile) { + SmallString<64> CustomWorkingDir; +#ifdef _WIN32 + CustomWorkingDir = "C:/"; +#else + CustomWorkingDir = "/"; +#endif + + auto FS = IntrusiveRefCntPtr( + new llvm::vfs::InMemoryFileSystem); + // setCurrentworkingdirectory must finish without error. + ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir)); + + FileSystemOptions Opts; + FileManager Manager(Opts, FS); + + // Inject fake files into the file system. + auto Cache = std::make_unique(); + Cache->InjectDirectory("/tmp", 42); + Cache->InjectFile("/tmp/test", 43); + Manager.setStatCache(std::move(Cache)); + + // Set up a virtual file with a different size than FakeStatCache uses. + const FileEntry *File = Manager.getVirtualFile("/tmp/test", /*Size=*/10, 0); + ASSERT_TRUE(File); + FileEntryRef Ref("/tmp/test", *File); + EXPECT_TRUE(Ref.isValid()); + EXPECT_EQ(Ref.getSize(), 10); + + // Calling a second time should not affect the UID or size. + unsigned VirtualUID = Ref.getUID(); + EXPECT_EQ(*expectedToOptional(Manager.getFileRef("/tmp/test")), Ref); + EXPECT_EQ(Ref.getUID(), VirtualUID); + EXPECT_EQ(Ref.getSize(), 10); + + // Bypass the file. + llvm::Optional BypassRef = Manager.getBypassFile(Ref); + ASSERT_TRUE(BypassRef); + EXPECT_TRUE(BypassRef->isValid()); + EXPECT_EQ(BypassRef->getName(), Ref.getName()); + + // Check that it's different in the right ways. + EXPECT_NE(&BypassRef->getFileEntry(), File); + EXPECT_NE(BypassRef->getUID(), VirtualUID); + EXPECT_NE(BypassRef->getSize(), Ref.getSize()); + + // The virtual file should still be returned when searching. + EXPECT_EQ(*expectedToOptional(Manager.getFileRef("/tmp/test")), Ref); +} + } // anonymous namespace -- cgit v1.1