Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -470,10 +470,11 @@ } std::string CGDebugInfo::remapDIPath(StringRef Path) const { + SmallString<256> P = Path; for (const auto &Entry : DebugPrefixMap) - if (Path.startswith(Entry.first)) - return (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - return Path.str(); + if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) + break; + return P.str().str(); } unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -1456,10 +1456,8 @@ const std::map> &MacroPrefixMap) { for (const auto &Entry : MacroPrefixMap) - if (Path.startswith(Entry.first)) { - Path = (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); + if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second)) break; - } } /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded @@ -1543,8 +1541,8 @@ } else { FN += PLoc.getFilename(); } - Lexer::Stringify(FN); remapMacroPath(FN, PPOpts->MacroPrefixMap); + Lexer::Stringify(FN); OS << '"' << FN << '"'; } Tok.setKind(tok::string_literal); Index: clang/test/Preprocessor/file_test.c =================================================================== --- clang/test/Preprocessor/file_test.c +++ clang/test/Preprocessor/file_test.c @@ -1,4 +1,4 @@ -// XFAIL: system-windows +// UNSUPPORTED: system-windows // RUN: %clang -E -ffile-prefix-map=%p=/UNLIKELY_PATH/empty -c -o - %s | FileCheck %s // RUN: %clang -E -fmacro-prefix-map=%p=/UNLIKELY_PATH/empty -c -o - %s | FileCheck %s // RUN: %clang -E -fmacro-prefix-map=%p=/UNLIKELY_PATH=empty -c -o - %s | FileCheck %s -check-prefix CHECK-EVIL @@ -7,14 +7,14 @@ filename: __FILE__ #include "file_test.h" -// CHECK: filename: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.c" -// CHECK: filename: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.h" -// CHECK: basefile: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.c" +// CHECK: filename: "/UNLIKELY_PATH/empty/file_test.c" +// CHECK: filename: "/UNLIKELY_PATH/empty/file_test.h" +// CHECK: basefile: "/UNLIKELY_PATH/empty/file_test.c" // CHECK-NOT: filename: -// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.c" -// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.h" -// CHECK-EVIL: basefile: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.c" +// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty/file_test.c" +// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty/file_test.h" +// CHECK-EVIL: basefile: "/UNLIKELY_PATH=empty/file_test.c" // CHECK-EVIL-NOT: filename: // CHECK-REMOVE: filename: "file_test.c" Index: clang/test/Preprocessor/file_test_windows.c =================================================================== --- /dev/null +++ clang/test/Preprocessor/file_test_windows.c @@ -0,0 +1,23 @@ +// REQUIRES: system-windows +// RUN: %clang -E -ffile-prefix-map=%p=A:\UNLIKELY_PATH\empty -c -o - %s | FileCheck %s +// RUN: %clang -E -fmacro-prefix-map=%p=A:\UNLIKELY_PATH\empty -c -o - %s | FileCheck %s +// RUN: %clang -E -fmacro-prefix-map=%p=A:\UNLIKELY_PATH=empty -c -o - %s | FileCheck %s -check-prefix CHECK-EVIL +// RUN: %clang -E -fmacro-prefix-map=%p\= -c -o - %s | FileCheck %s --check-prefix CHECK-REMOVE + +filename: __FILE__ +#include "file_test.h" + +// CHECK: filename: "A:\\UNLIKELY_PATH\\empty{{/|\\\\}}file_test_windows.c" +// CHECK: filename: "A:\\UNLIKELY_PATH\\empty{{/|\\\\}}file_test.h" +// CHECK: basefile: "A:\\UNLIKELY_PATH\\empty{{/|\\\\}}file_test_windows.c" +// CHECK-NOT: filename: + +// CHECK-EVIL: filename: "A:\\UNLIKELY_PATH=empty{{/|\\\\}}file_test_windows.c" +// CHECK-EVIL: filename: "A:\\UNLIKELY_PATH=empty{{/|\\\\}}file_test.h" +// CHECK-EVIL: basefile: "A:\\UNLIKELY_PATH=empty{{/|\\\\}}file_test_windows.c" +// CHECK-EVIL-NOT: filename: + +// CHECK-REMOVE: filename: "file_test_windows.c" +// CHECK-REMOVE: filename: "file_test.h" +// CHECK-REMOVE: basefile: "file_test_windows.c" +// CHECK-REMOVE-NOT: filename: Index: llvm/include/llvm/Support/Path.h =================================================================== --- llvm/include/llvm/Support/Path.h +++ llvm/include/llvm/Support/Path.h @@ -176,9 +176,9 @@ /// separators will only be matched and stripped when present /// in \a OldPrefix. /// @result true if \a Path begins with OldPrefix -bool replace_path_prefix(SmallVectorImpl &Path, - const StringRef &OldPrefix, const StringRef &NewPrefix, - Style style = Style::native, bool strict = false); +bool replace_path_prefix(SmallVectorImpl &Path, StringRef OldPrefix, + StringRef NewPrefix, Style style = Style::native, + bool strict = false); /// Append to path. /// Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1920,10 +1920,12 @@ static std::string remapPath(StringRef Path, const objectPrefixMap &ObjectPrefixMap) { + + SmallString<256> p = Path; for (const auto &Entry : ObjectPrefixMap) - if (Path.startswith(Entry.first)) - return (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - return Path.str(); + if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) + break; + return p.str().str(); } bool DWARFLinker::registerModuleReference( Index: llvm/lib/MC/MCContext.cpp =================================================================== --- llvm/lib/MC/MCContext.cpp +++ llvm/lib/MC/MCContext.cpp @@ -589,13 +589,17 @@ void MCContext::RemapDebugPaths() { const auto &DebugPrefixMap = this->DebugPrefixMap; + if (DebugPrefixMap.empty()) + return; + const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) { - for (const auto &Entry : DebugPrefixMap) - if (StringRef(Path).startswith(Entry.first)) { - std::string RemappedPath = - (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - Path.swap(RemappedPath); + SmallString<256> P(Path); + for (const auto &Entry : DebugPrefixMap) { + if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) { + Path = P.str().str(); + break; } + } }; // Remap compilation directory. Index: llvm/lib/Support/Path.cpp =================================================================== --- llvm/lib/Support/Path.cpp +++ llvm/lib/Support/Path.cpp @@ -496,9 +496,8 @@ path.append(ext.begin(), ext.end()); } -bool replace_path_prefix(SmallVectorImpl &Path, - const StringRef &OldPrefix, const StringRef &NewPrefix, - Style style, bool strict) { +bool replace_path_prefix(SmallVectorImpl &Path, StringRef OldPrefix, + StringRef NewPrefix, Style style, bool strict) { if (OldPrefix.empty() && NewPrefix.empty()) return false; @@ -509,11 +508,13 @@ return false; // Ensure OldPrefixDir does not have a trailing separator. - if (!OldPrefix.empty() && is_separator(OldPrefix.back())) + if (!OldPrefix.empty() && is_separator(OldPrefix.back(), style)) OldPrefixDir = parent_path(OldPrefix, style); else OldPrefixDir = OldPrefix; + StringRef OldPrefixSep = OldPrefix.substr(OldPrefixDir.size()); + if (!OrigPath.startswith(OldPrefixDir)) return false; @@ -528,13 +529,12 @@ } StringRef RelPath = OrigPath.substr(OldPrefixDir.size()); - SmallString<256> NewPath; - path::append(NewPath, style, NewPrefix); + SmallString<256> NewPath = NewPrefix; if (!RelPath.empty()) { - if (!is_separator(RelPath[0], style) || !strict) + if (!is_separator(RelPath[0], style) || (!strict && OldPrefixSep.empty())) path::append(NewPath, style, RelPath); else - path::append(NewPath, style, relative_path(RelPath, style)); + path::append(NewPath, style, relative_path(RelPath, style)); } Path.swap(NewPath); Index: llvm/unittests/Support/Path.cpp =================================================================== --- llvm/unittests/Support/Path.cpp +++ llvm/unittests/Support/Path.cpp @@ -1254,6 +1254,9 @@ path::replace_path_prefix(Path, OldPrefix, EmptyPrefix); EXPECT_EQ(Path, "/foo"); Path = Path2; + path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix); + EXPECT_EQ(Path, "foo"); + Path = Path2; path::replace_path_prefix(Path, OldPrefix, EmptyPrefix, path::Style::native, true); EXPECT_EQ(Path, "foo");