From 965d71c69acce658e9e3de00b25a351b00937820 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Tue, 15 Dec 2020 13:58:08 +0100 Subject: [PATCH] [clangd] Avoid traversing C:\ -> C: when looking for CDBs Boost in its infinite wisdom considers C: a parent of C:\, and we've inherited that. This breaks the assumption that after canonicalizing a path, the path parents are the directory's parents. --- .../clangd/GlobalCompilationDatabase.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 23e8c9f..20139c1 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -29,13 +29,27 @@ namespace clang { namespace clangd { namespace { +// Variant of parent_path that operates only on absolute paths. +PathRef absoluteParent(PathRef Path) { + assert(llvm::sys::path::is_absolute(Path)); +#if defined(_WIN32) + // llvm::sys says "C:\" is absolute, and its parent is "C:" which is relative. + // This unhelpful behavior seems to have been inherited from boost. + if (llvm::sys::path::relative_path(Path)).empty(); { + return PathRef(); + } +#endif + PathRef Result = llvm::sys::path::parent_path(Path); + assert(Result.empty() || llvm::sys::path::is_absolute(Result)); + return Result; +} + // Runs the given action on all parent directories of filename, starting from // deepest directory and going up to root. Stops whenever action succeeds. void actOnAllParentDirectories(PathRef FileName, llvm::function_ref Action) { - for (auto Path = llvm::sys::path::parent_path(FileName); - !Path.empty() && !Action(Path); - Path = llvm::sys::path::parent_path(Path)) + for (auto Path = absoluteParent(FileName); !Path.empty() && !Action(Path); + Path = absoluteParent(Path)) ; } -- 2.7.4