From 917acac960d40280ea02ea453e594034b1be1f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Duncan=20P=2E=20N=2E=20Exon=C2=A0Smith?= Date: Thu, 15 Oct 2020 11:39:07 -0400 Subject: FileManager: Shrink FileEntryRef to the size of a pointer Shrink `FileEntryRef` to the size of a pointer, by having it directly reference the `StringMapEntry` the same way that `DirectoryEntryRef` does. This makes `FileEntryRef::FileEntryRef` private as a side effect (`FileManager` is a friend!). There are two helper types added within `FileEntryRef`: - `FileEntryRef::MapValue` is the type stored in `FileManager::SeenFileEntries`. It's a replacement for `SeenFileEntryOrRedirect`, where the second pointer type has been changed from `StringRef*` to `MapEntry*` (see next bullet). - `FileEntryRef::MapEntry` is the instantiation of `StringMapEntry<>` where `MapValue` is stored. This is what `FileEntryRef` has a pointer to, in order to grab the name in addition to the value. Differential Revision: https://reviews.llvm.org/D89488 --- clang/unittests/Basic/FileManagerTest.cpp | 43 ++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'clang/unittests/Basic/FileManagerTest.cpp') diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index dfb79b4..43680d5 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -285,9 +285,18 @@ TEST_F(FileManagerTest, getFileRefReturnsCorrectNameForDifferentStatPath) { StatCache->InjectFile("dir/f1-alias.cpp", 41, "dir/f1.cpp"); StatCache->InjectFile("dir/f2.cpp", 42); StatCache->InjectFile("dir/f2-alias.cpp", 42, "dir/f2.cpp"); + + // This unintuitive rename-the-file-on-stat behaviour supports how the + // RedirectingFileSystem VFS layer responds to stats. However, even if you + // have two layers, you should only get a single filename back. As such the + // following stat cache behaviour is not supported (the correct stat entry + // for a double-redirection would be "dir/f1.cpp") and the getFileRef below + // should assert. + StatCache->InjectFile("dir/f1-alias-alias.cpp", 41, "dir/f1-alias.cpp"); + manager.setStatCache(std::move(StatCache)); - // With F2, test accessing the non-redirected name first. + // With F1, test accessing the non-redirected name first. auto F1 = manager.getFileRef("dir/f1.cpp"); auto F1Alias = manager.getFileRef("dir/f1-alias.cpp"); auto F1Alias2 = manager.getFileRef("dir/f1-alias.cpp"); @@ -301,6 +310,11 @@ TEST_F(FileManagerTest, getFileRefReturnsCorrectNameForDifferentStatPath) { EXPECT_EQ(&F1->getFileEntry(), &F1Alias->getFileEntry()); EXPECT_EQ(&F1->getFileEntry(), &F1Alias2->getFileEntry()); +#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST + EXPECT_DEATH((void)manager.getFileRef("dir/f1-alias-alias.cpp"), + "filename redirected to a non-canonical filename?"); +#endif + // With F2, test accessing the redirected name first. auto F2Alias = manager.getFileRef("dir/f2-alias.cpp"); auto F2 = manager.getFileRef("dir/f2.cpp"); @@ -487,29 +501,34 @@ TEST_F(FileManagerTest, getBypassFile) { // 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); + const FileEntry &FE = *File; + EXPECT_TRUE(FE.isValid()); + EXPECT_EQ(FE.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); + unsigned VirtualUID = FE.getUID(); + EXPECT_EQ( + &FE, + &expectedToOptional(Manager.getFileRef("/tmp/test"))->getFileEntry()); + EXPECT_EQ(FE.getUID(), VirtualUID); + EXPECT_EQ(FE.getSize(), 10); // Bypass the file. - llvm::Optional BypassRef = Manager.getBypassFile(Ref); + llvm::Optional BypassRef = + Manager.getBypassFile(File->getLastRef()); ASSERT_TRUE(BypassRef); EXPECT_TRUE(BypassRef->isValid()); - EXPECT_EQ(BypassRef->getName(), Ref.getName()); + EXPECT_EQ("/tmp/test", BypassRef->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()); + EXPECT_NE(BypassRef->getSize(), FE.getSize()); // The virtual file should still be returned when searching. - EXPECT_EQ(*expectedToOptional(Manager.getFileRef("/tmp/test")), Ref); + EXPECT_EQ( + &FE, + &expectedToOptional(Manager.getFileRef("/tmp/test"))->getFileEntry()); } } // anonymous namespace -- cgit v1.1