[clang] 7a8edcb - [Clang] Restore replace_path_prefix instead of startswith
Sylvain Audi via cfe-commits
cfe-commits at lists.llvm.org
Wed May 13 10:50:45 PDT 2020
Author: Sylvain Audi
Date: 2020-05-13T13:49:14-04:00
New Revision: 7a8edcb2124b60941ef6ea4bb4b38a9eb0d70137
URL: https://github.com/llvm/llvm-project/commit/7a8edcb2124b60941ef6ea4bb4b38a9eb0d70137
DIFF: https://github.com/llvm/llvm-project/commit/7a8edcb2124b60941ef6ea4bb4b38a9eb0d70137.diff
LOG: [Clang] Restore replace_path_prefix instead of startswith
In D49466, sys::path::replace_path_prefix was used instead startswith for -f[macro/debug/file]-prefix-map options.
However those were reverted later (commit rG3bb24bf25767ef5bbcef958b484e7a06d8689204) due to broken Windows tests.
This patch restores those replace_path_prefix calls.
It also modifies the prefix matching to be case-insensitive under Windows.
Differential Revision : https://reviews.llvm.org/D76869
Added:
clang/test/Preprocessor/Inputs/include-file-test/file_test.h
clang/test/Preprocessor/file_test_windows.c
Modified:
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/Lex/PPMacroExpansion.cpp
clang/test/Preprocessor/file_test.c
llvm/include/llvm/Support/Path.h
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/lib/MC/MCContext.cpp
llvm/lib/Support/Path.cpp
llvm/unittests/Support/Path.cpp
Removed:
clang/test/Preprocessor/file_test.h
################################################################################
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0c23b16a78d8..f92b21d5e636 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -470,10 +470,14 @@ CGDebugInfo::createFile(StringRef FileName,
}
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
+ if (DebugPrefixMap.empty())
+ return Path.str();
+
+ 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) {
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index cf8bb2fbab99..4908594d6081 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1456,10 +1456,8 @@ static void remapMacroPath(
const std::map<std::string, std::string, std::greater<std::string>>
&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 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
} else {
FN += PLoc.getFilename();
}
- Lexer::Stringify(FN);
remapMacroPath(FN, PPOpts->MacroPrefixMap);
+ Lexer::Stringify(FN);
OS << '"' << FN << '"';
}
Tok.setKind(tok::string_literal);
diff --git a/clang/test/Preprocessor/file_test.h b/clang/test/Preprocessor/Inputs/include-file-test/file_test.h
similarity index 100%
rename from clang/test/Preprocessor/file_test.h
rename to clang/test/Preprocessor/Inputs/include-file-test/file_test.h
diff --git a/clang/test/Preprocessor/file_test.c b/clang/test/Preprocessor/file_test.c
index 3788db6eb090..890fa2cfcaa9 100644
--- a/clang/test/Preprocessor/file_test.c
+++ b/clang/test/Preprocessor/file_test.c
@@ -1,23 +1,23 @@
-// 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
// RUN: %clang -E -fmacro-prefix-map=%p/= -c -o - %s | FileCheck %s --check-prefix CHECK-REMOVE
filename: __FILE__
-#include "file_test.h"
+#include "Inputs/include-file-test/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/Inputs/include-file-test/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/Inputs/include-file-test/file_test.h"
+// CHECK-EVIL: basefile: "/UNLIKELY_PATH=empty/file_test.c"
// CHECK-EVIL-NOT: filename:
// CHECK-REMOVE: filename: "file_test.c"
-// CHECK-REMOVE: filename: "file_test.h"
+// CHECK-REMOVE: filename: "Inputs/include-file-test/file_test.h"
// CHECK-REMOVE: basefile: "file_test.c"
// CHECK-REMOVE-NOT: filename:
diff --git a/clang/test/Preprocessor/file_test_windows.c b/clang/test/Preprocessor/file_test_windows.c
new file mode 100644
index 000000000000..26c848469207
--- /dev/null
+++ b/clang/test/Preprocessor/file_test_windows.c
@@ -0,0 +1,29 @@
+// 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/iNPUTS\=A:\UNLIKELY_PATH_INC\ -fmacro-prefix-map=%p/=A:\UNLIKELY_PATH_BASE\ -c -o - %s | FileCheck %s -check-prefix CHECK-CASE
+// RUN: %clang -E -fmacro-prefix-map=%p\= -c -o - %s | FileCheck %s --check-prefix CHECK-REMOVE
+
+filename: __FILE__
+#include "Inputs/include-file-test/file_test.h"
+
+// CHECK: filename: "A:\\UNLIKELY_PATH\\empty\\file_test_windows.c"
+// CHECK: filename: "A:\\UNLIKELY_PATH\\empty/Inputs/include-file-test/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/Inputs/include-file-test/file_test.h"
+// CHECK-EVIL: basefile: "A:\\UNLIKELY_PATH=empty\\file_test_windows.c"
+// CHECK-EVIL-NOT: filename:
+
+// CHECK-CASE: filename: "A:\\UNLIKELY_PATH_BASE\\file_test_windows.c"
+// CHECK-CASE: filename: "A:\\UNLIKELY_PATH_INC\\include-file-test/file_test.h"
+// CHECK-CASE: basefile: "A:\\UNLIKELY_PATH_BASE\\file_test_windows.c"
+// CHECK-CASE-NOT: filename:
+
+// CHECK-REMOVE: filename: "file_test_windows.c"
+// CHECK-REMOVE: filename: "Inputs/include-file-test/file_test.h"
+// CHECK-REMOVE: basefile: "file_test_windows.c"
+// CHECK-REMOVE-NOT: filename:
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 3b712c00dc70..cdfff2aa7a51 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -167,9 +167,12 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
/// start with \a NewPrefix.
/// @param OldPrefix The path prefix to strip from \a Path.
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
+/// @param style The style used to match the prefix. Exact match using
+/// Posix style, case/separator insensitive match for Windows style.
/// @result true if \a Path begins with OldPrefix
bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
- StringRef NewPrefix);
+ StringRef NewPrefix,
+ Style style = Style::native);
/// Append to path.
///
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index fff3763aea41..12b19e77a422 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1941,10 +1941,14 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) {
static std::string remapPath(StringRef Path,
const objectPrefixMap &ObjectPrefixMap) {
+ if (ObjectPrefixMap.empty())
+ return Path.str();
+
+ 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(
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 1bc313553aff..92d99ec577b5 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -642,13 +642,17 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From,
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.
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 775629074f6c..37b3086fddf5 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -496,13 +496,32 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
path.append(ext.begin(), ext.end());
}
+static bool starts_with(StringRef Path, StringRef Prefix,
+ Style style = Style::native) {
+ // Windows prefix matching : case and separator insensitive
+ if (real_style(style) == Style::windows) {
+ if (Path.size() < Prefix.size())
+ return false;
+ for (size_t I = 0, E = Prefix.size(); I != E; ++I) {
+ bool SepPath = is_separator(Path[I], style);
+ bool SepPrefix = is_separator(Prefix[I], style);
+ if (SepPath != SepPrefix)
+ return false;
+ if (!SepPath && toLower(Path[I]) != toLower(Prefix[I]))
+ return false;
+ }
+ return true;
+ }
+ return Path.startswith(Prefix);
+}
+
bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
- StringRef NewPrefix) {
+ StringRef NewPrefix, Style style) {
if (OldPrefix.empty() && NewPrefix.empty())
return false;
StringRef OrigPath(Path.begin(), Path.size());
- if (!OrigPath.startswith(OldPrefix))
+ if (!starts_with(OrigPath, OldPrefix, style))
return false;
// If prefixes have the same size we can simply copy the new one over.
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index a577f1b744bc..8e842a95b2b2 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -1311,48 +1311,73 @@ TEST(Support, ReplacePathPrefix) {
SmallString<64> Path1("/foo");
SmallString<64> Path2("/old/foo");
SmallString<64> Path3("/oldnew/foo");
+ SmallString<64> Path4("C:\\old/foo\\bar");
SmallString<64> OldPrefix("/old");
SmallString<64> OldPrefixSep("/old/");
+ SmallString<64> OldPrefixWin("c:/oLD/F");
SmallString<64> NewPrefix("/new");
SmallString<64> NewPrefix2("/longernew");
SmallString<64> EmptyPrefix("");
+ bool Found;
SmallString<64> Path = Path1;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_FALSE(Found);
EXPECT_EQ(Path, "/foo");
Path = Path2;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/new/foo");
Path = Path2;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/longernew/foo");
Path = Path1;
- path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/new/foo");
Path = Path2;
- path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/foo");
Path = Path2;
- path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "foo");
Path = Path3;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/newnew/foo");
Path = Path3;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/longernewnew/foo");
Path = Path1;
- path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/new/foo");
Path = OldPrefix;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/new");
Path = OldPrefixSep;
- path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_TRUE(Found);
EXPECT_EQ(Path, "/new/");
Path = OldPrefix;
- path::replace_path_prefix(Path, OldPrefixSep, NewPrefix);
+ Found = path::replace_path_prefix(Path, OldPrefixSep, NewPrefix);
+ EXPECT_FALSE(Found);
EXPECT_EQ(Path, "/old");
+ Path = Path4;
+ Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix,
+ path::Style::windows);
+ EXPECT_TRUE(Found);
+ EXPECT_EQ(Path, "/newoo\\bar");
+ Path = Path4;
+ Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix,
+ path::Style::posix);
+ EXPECT_FALSE(Found);
+ EXPECT_EQ(Path, "C:\\old/foo\\bar");
}
TEST_F(FileSystemTest, OpenFileForRead) {
More information about the cfe-commits
mailing list