diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -152,6 +152,18 @@ return false; } +/// Append components to path, applying style. +static void AppendPathComponents(FileSpec &path, llvm::StringRef components, + llvm::sys::path::Style style) { + auto component = llvm::sys::path::begin(components, style); + auto e = llvm::sys::path::end(components); + while (component != e && + llvm::sys::path::is_separator(*component->data(), style)) + ++component; + for (; component != e; ++component) + path.AppendPathComponent(*component); +} + llvm::Optional PathMappingList::RemapPath(llvm::StringRef path) const { if (m_pairs.empty() || path.empty()) @@ -175,7 +187,9 @@ continue; } FileSpec remapped(it.second.GetStringRef()); - remapped.AppendPathComponent(path); + auto orig_style = FileSpec::GuessPathStyle(prefix).getValueOr( + llvm::sys::path::Style::native); + AppendPathComponents(remapped, path, orig_style); return remapped; } return {}; @@ -187,8 +201,11 @@ for (const auto &it : m_pairs) { if (!path_ref.consume_front(it.second.GetStringRef())) continue; - fixed.SetFile(it.first.GetStringRef(), FileSpec::Style::native); - fixed.AppendPathComponent(path_ref); + auto orig_file = it.first.GetStringRef(); + auto orig_style = FileSpec::GuessPathStyle(orig_file).getValueOr( + llvm::sys::path::Style::native); + fixed.SetFile(orig_file, orig_style); + AppendPathComponents(fixed, path_ref, orig_style); return true; } return false; diff --git a/lldb/unittests/Target/PathMappingListTest.cpp b/lldb/unittests/Target/PathMappingListTest.cpp --- a/lldb/unittests/Target/PathMappingListTest.cpp +++ b/lldb/unittests/Target/PathMappingListTest.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" #include "lldb/Target/PathMappingList.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/ADT/ArrayRef.h" #include "gtest/gtest.h" #include @@ -19,6 +19,8 @@ FileSpec original; FileSpec remapped; Matches(const char *o, const char *r) : original(o), remapped(r) {} + Matches(const char *o, llvm::sys::path::Style style, const char *r) + : original(o, style), remapped(r) {} }; } // namespace @@ -112,3 +114,27 @@ }; TestPathMappings(map, matches, fails); } + +#ifndef _WIN32 +TEST(PathMappingListTest, CrossPlatformTests) { + PathMappingList map; + map.Append(ConstString(R"(C:\old)"), ConstString("/new"), false); + Matches matches[] = { + {R"(C:\old)", llvm::sys::path::Style::windows, "/new"}, + {R"(C:\old\)", llvm::sys::path::Style::windows, "/new"}, + {R"(C:\old\foo\.)", llvm::sys::path::Style::windows, "/new/foo"}, + {R"(C:\old\foo.c)", llvm::sys::path::Style::windows, "/new/foo.c"}, + {R"(C:\old\foo.c\.)", llvm::sys::path::Style::windows, "/new/foo.c"}, + {R"(C:\old\.\foo.c)", llvm::sys::path::Style::windows, "/new/foo.c"}, + }; + ConstString fails[] = { + ConstString("/foo"), + ConstString("/"), + ConstString("foo.c"), + ConstString("./foo.c"), + ConstString("../foo.c"), + ConstString("../bar/foo.c"), + }; + TestPathMappings(map, matches, fails); +} +#endif