diff --git a/clang/lib/Tooling/FileMatchTrie.cpp b/clang/lib/Tooling/FileMatchTrie.cpp --- a/clang/lib/Tooling/FileMatchTrie.cpp +++ b/clang/lib/Tooling/FileMatchTrie.cpp @@ -105,8 +105,13 @@ StringRef FileName, bool &IsAmbiguous, unsigned ConsumedLength = 0) const { + // Note: we support only directory symlinks for performance reasons. if (Children.empty()) { - if (Comparator.equivalent(StringRef(Path), FileName)) + // As far as we do not support file symlinks, compare + // basenames here to avoid request to file system. + if (llvm::sys::path::filename(Path) == + llvm::sys::path::filename(FileName) && + Comparator.equivalent(StringRef(Path), FileName)) return StringRef(Path); return {}; } @@ -121,6 +126,13 @@ if (!Result.empty() || IsAmbiguous) return Result; } + + // If `ConsumedLength` is zero, this is the root and we have no filename + // match. Give up in this case, we don't try to find symlinks with + // different names. + if (ConsumedLength == 0) + return {}; + std::vector AllChildren; getAll(AllChildren, MatchingChild); StringRef Result; diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp --- a/clang/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp @@ -281,6 +281,15 @@ EXPECT_EQ("Cannot resolve relative paths", Error); } +TEST_F(FileMatchTrieTest, SingleFile) { + Trie.insert("/root/RootFile.cc"); + EXPECT_EQ("", find("/root/rootfile.cc")); + // Add subpath to avoid `if (Children.empty())` special case + // which we hit at previous `find()`. + Trie.insert("/root/otherpath/OtherFile.cc"); + EXPECT_EQ("", find("/root/rootfile.cc")); +} + TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) { std::string ErrorMessage; CompileCommand NotFound = findCompileArgsInJsonDatabase(