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 we compare + // basenames here to avoid expensive 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,15 @@ if (!Result.empty() || IsAmbiguous) return Result; } + + // We failed to find the file with `Children.find()`. + // If `ConsumedLength` is equal to 0 then we have tried to find the file + // with it's basename. Thus, we do not have files with the same + // basename and could return empty result here as far as we + // do not support file symlinks. + 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(