Skip to content

Commit 7a8edcb

Browse files
committed
[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
1 parent 33d96bf commit 7a8edcb

File tree

10 files changed

+125
-39
lines changed

10 files changed

+125
-39
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,14 @@ CGDebugInfo::createFile(StringRef FileName,
470470
}
471471

472472
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
473+
if (DebugPrefixMap.empty())
474+
return Path.str();
475+
476+
SmallString<256> P = Path;
473477
for (const auto &Entry : DebugPrefixMap)
474-
if (Path.startswith(Entry.first))
475-
return (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
476-
return Path.str();
478+
if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second))
479+
break;
480+
return P.str().str();
477481
}
478482

479483
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {

clang/lib/Lex/PPMacroExpansion.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1456,10 +1456,8 @@ static void remapMacroPath(
14561456
const std::map<std::string, std::string, std::greater<std::string>>
14571457
&MacroPrefixMap) {
14581458
for (const auto &Entry : MacroPrefixMap)
1459-
if (Path.startswith(Entry.first)) {
1460-
Path = (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
1459+
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
14611460
break;
1462-
}
14631461
}
14641462

14651463
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
@@ -1543,8 +1541,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
15431541
} else {
15441542
FN += PLoc.getFilename();
15451543
}
1546-
Lexer::Stringify(FN);
15471544
remapMacroPath(FN, PPOpts->MacroPrefixMap);
1545+
Lexer::Stringify(FN);
15481546
OS << '"' << FN << '"';
15491547
}
15501548
Tok.setKind(tok::string_literal);

clang/test/Preprocessor/file_test.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
// XFAIL: system-windows
1+
// UNSUPPORTED: system-windows
22
// RUN: %clang -E -ffile-prefix-map=%p=/UNLIKELY_PATH/empty -c -o - %s | FileCheck %s
33
// RUN: %clang -E -fmacro-prefix-map=%p=/UNLIKELY_PATH/empty -c -o - %s | FileCheck %s
44
// RUN: %clang -E -fmacro-prefix-map=%p=/UNLIKELY_PATH=empty -c -o - %s | FileCheck %s -check-prefix CHECK-EVIL
55
// RUN: %clang -E -fmacro-prefix-map=%p/= -c -o - %s | FileCheck %s --check-prefix CHECK-REMOVE
66

77
filename: __FILE__
8-
#include "file_test.h"
8+
#include "Inputs/include-file-test/file_test.h"
99

10-
// CHECK: filename: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.c"
11-
// CHECK: filename: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.h"
12-
// CHECK: basefile: "/UNLIKELY_PATH/empty{{/|\\\\}}file_test.c"
10+
// CHECK: filename: "/UNLIKELY_PATH/empty/file_test.c"
11+
// CHECK: filename: "/UNLIKELY_PATH/empty/Inputs/include-file-test/file_test.h"
12+
// CHECK: basefile: "/UNLIKELY_PATH/empty/file_test.c"
1313
// CHECK-NOT: filename:
1414

15-
// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.c"
16-
// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.h"
17-
// CHECK-EVIL: basefile: "/UNLIKELY_PATH=empty{{/|\\\\}}file_test.c"
15+
// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty/file_test.c"
16+
// CHECK-EVIL: filename: "/UNLIKELY_PATH=empty/Inputs/include-file-test/file_test.h"
17+
// CHECK-EVIL: basefile: "/UNLIKELY_PATH=empty/file_test.c"
1818
// CHECK-EVIL-NOT: filename:
1919

2020
// CHECK-REMOVE: filename: "file_test.c"
21-
// CHECK-REMOVE: filename: "file_test.h"
21+
// CHECK-REMOVE: filename: "Inputs/include-file-test/file_test.h"
2222
// CHECK-REMOVE: basefile: "file_test.c"
2323
// CHECK-REMOVE-NOT: filename:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// REQUIRES: system-windows
2+
// RUN: %clang -E -ffile-prefix-map=%p=A:\UNLIKELY_PATH\empty -c -o - %s | FileCheck %s
3+
// RUN: %clang -E -fmacro-prefix-map=%p=A:\UNLIKELY_PATH\empty -c -o - %s | FileCheck %s
4+
// RUN: %clang -E -fmacro-prefix-map=%p=A:\UNLIKELY_PATH=empty -c -o - %s | FileCheck %s -check-prefix CHECK-EVIL
5+
// 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
6+
// RUN: %clang -E -fmacro-prefix-map=%p\= -c -o - %s | FileCheck %s --check-prefix CHECK-REMOVE
7+
8+
filename: __FILE__
9+
#include "Inputs/include-file-test/file_test.h"
10+
11+
// CHECK: filename: "A:\\UNLIKELY_PATH\\empty\\file_test_windows.c"
12+
// CHECK: filename: "A:\\UNLIKELY_PATH\\empty/Inputs/include-file-test/file_test.h"
13+
// CHECK: basefile: "A:\\UNLIKELY_PATH\\empty\\file_test_windows.c"
14+
// CHECK-NOT: filename:
15+
16+
// CHECK-EVIL: filename: "A:\\UNLIKELY_PATH=empty\\file_test_windows.c"
17+
// CHECK-EVIL: filename: "A:\\UNLIKELY_PATH=empty/Inputs/include-file-test/file_test.h"
18+
// CHECK-EVIL: basefile: "A:\\UNLIKELY_PATH=empty\\file_test_windows.c"
19+
// CHECK-EVIL-NOT: filename:
20+
21+
// CHECK-CASE: filename: "A:\\UNLIKELY_PATH_BASE\\file_test_windows.c"
22+
// CHECK-CASE: filename: "A:\\UNLIKELY_PATH_INC\\include-file-test/file_test.h"
23+
// CHECK-CASE: basefile: "A:\\UNLIKELY_PATH_BASE\\file_test_windows.c"
24+
// CHECK-CASE-NOT: filename:
25+
26+
// CHECK-REMOVE: filename: "file_test_windows.c"
27+
// CHECK-REMOVE: filename: "Inputs/include-file-test/file_test.h"
28+
// CHECK-REMOVE: basefile: "file_test_windows.c"
29+
// CHECK-REMOVE-NOT: filename:

llvm/include/llvm/Support/Path.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,12 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
167167
/// start with \a NewPrefix.
168168
/// @param OldPrefix The path prefix to strip from \a Path.
169169
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
170+
/// @param style The style used to match the prefix. Exact match using
171+
/// Posix style, case/separator insensitive match for Windows style.
170172
/// @result true if \a Path begins with OldPrefix
171173
bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
172-
StringRef NewPrefix);
174+
StringRef NewPrefix,
175+
Style style = Style::native);
173176

174177
/// Append to path.
175178
///

llvm/lib/DWARFLinker/DWARFLinker.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -1941,10 +1941,14 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) {
19411941

19421942
static std::string remapPath(StringRef Path,
19431943
const objectPrefixMap &ObjectPrefixMap) {
1944+
if (ObjectPrefixMap.empty())
1945+
return Path.str();
1946+
1947+
SmallString<256> p = Path;
19441948
for (const auto &Entry : ObjectPrefixMap)
1945-
if (Path.startswith(Entry.first))
1946-
return (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
1947-
return Path.str();
1949+
if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
1950+
break;
1951+
return p.str().str();
19481952
}
19491953

19501954
bool DWARFLinker::registerModuleReference(

llvm/lib/MC/MCContext.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -642,13 +642,17 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From,
642642

643643
void MCContext::RemapDebugPaths() {
644644
const auto &DebugPrefixMap = this->DebugPrefixMap;
645+
if (DebugPrefixMap.empty())
646+
return;
647+
645648
const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) {
646-
for (const auto &Entry : DebugPrefixMap)
647-
if (StringRef(Path).startswith(Entry.first)) {
648-
std::string RemappedPath =
649-
(Twine(Entry.second) + Path.substr(Entry.first.size())).str();
650-
Path.swap(RemappedPath);
649+
SmallString<256> P(Path);
650+
for (const auto &Entry : DebugPrefixMap) {
651+
if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) {
652+
Path = P.str().str();
653+
break;
651654
}
655+
}
652656
};
653657

654658
// Remap compilation directory.

llvm/lib/Support/Path.cpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -496,13 +496,32 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
496496
path.append(ext.begin(), ext.end());
497497
}
498498

499+
static bool starts_with(StringRef Path, StringRef Prefix,
500+
Style style = Style::native) {
501+
// Windows prefix matching : case and separator insensitive
502+
if (real_style(style) == Style::windows) {
503+
if (Path.size() < Prefix.size())
504+
return false;
505+
for (size_t I = 0, E = Prefix.size(); I != E; ++I) {
506+
bool SepPath = is_separator(Path[I], style);
507+
bool SepPrefix = is_separator(Prefix[I], style);
508+
if (SepPath != SepPrefix)
509+
return false;
510+
if (!SepPath && toLower(Path[I]) != toLower(Prefix[I]))
511+
return false;
512+
}
513+
return true;
514+
}
515+
return Path.startswith(Prefix);
516+
}
517+
499518
bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
500-
StringRef NewPrefix) {
519+
StringRef NewPrefix, Style style) {
501520
if (OldPrefix.empty() && NewPrefix.empty())
502521
return false;
503522

504523
StringRef OrigPath(Path.begin(), Path.size());
505-
if (!OrigPath.startswith(OldPrefix))
524+
if (!starts_with(OrigPath, OldPrefix, style))
506525
return false;
507526

508527
// If prefixes have the same size we can simply copy the new one over.

llvm/unittests/Support/Path.cpp

+37-12
Original file line numberDiff line numberDiff line change
@@ -1311,48 +1311,73 @@ TEST(Support, ReplacePathPrefix) {
13111311
SmallString<64> Path1("/foo");
13121312
SmallString<64> Path2("/old/foo");
13131313
SmallString<64> Path3("/oldnew/foo");
1314+
SmallString<64> Path4("C:\\old/foo\\bar");
13141315
SmallString<64> OldPrefix("/old");
13151316
SmallString<64> OldPrefixSep("/old/");
1317+
SmallString<64> OldPrefixWin("c:/oLD/F");
13161318
SmallString<64> NewPrefix("/new");
13171319
SmallString<64> NewPrefix2("/longernew");
13181320
SmallString<64> EmptyPrefix("");
1321+
bool Found;
13191322

13201323
SmallString<64> Path = Path1;
1321-
path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1324+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1325+
EXPECT_FALSE(Found);
13221326
EXPECT_EQ(Path, "/foo");
13231327
Path = Path2;
1324-
path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1328+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1329+
EXPECT_TRUE(Found);
13251330
EXPECT_EQ(Path, "/new/foo");
13261331
Path = Path2;
1327-
path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
1332+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
1333+
EXPECT_TRUE(Found);
13281334
EXPECT_EQ(Path, "/longernew/foo");
13291335
Path = Path1;
1330-
path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
1336+
Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
1337+
EXPECT_TRUE(Found);
13311338
EXPECT_EQ(Path, "/new/foo");
13321339
Path = Path2;
1333-
path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
1340+
Found = path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
1341+
EXPECT_TRUE(Found);
13341342
EXPECT_EQ(Path, "/foo");
13351343
Path = Path2;
1336-
path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix);
1344+
Found = path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix);
1345+
EXPECT_TRUE(Found);
13371346
EXPECT_EQ(Path, "foo");
13381347
Path = Path3;
1339-
path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1348+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1349+
EXPECT_TRUE(Found);
13401350
EXPECT_EQ(Path, "/newnew/foo");
13411351
Path = Path3;
1342-
path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
1352+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
1353+
EXPECT_TRUE(Found);
13431354
EXPECT_EQ(Path, "/longernewnew/foo");
13441355
Path = Path1;
1345-
path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
1356+
Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
1357+
EXPECT_TRUE(Found);
13461358
EXPECT_EQ(Path, "/new/foo");
13471359
Path = OldPrefix;
1348-
path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1360+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1361+
EXPECT_TRUE(Found);
13491362
EXPECT_EQ(Path, "/new");
13501363
Path = OldPrefixSep;
1351-
path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1364+
Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix);
1365+
EXPECT_TRUE(Found);
13521366
EXPECT_EQ(Path, "/new/");
13531367
Path = OldPrefix;
1354-
path::replace_path_prefix(Path, OldPrefixSep, NewPrefix);
1368+
Found = path::replace_path_prefix(Path, OldPrefixSep, NewPrefix);
1369+
EXPECT_FALSE(Found);
13551370
EXPECT_EQ(Path, "/old");
1371+
Path = Path4;
1372+
Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix,
1373+
path::Style::windows);
1374+
EXPECT_TRUE(Found);
1375+
EXPECT_EQ(Path, "/newoo\\bar");
1376+
Path = Path4;
1377+
Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix,
1378+
path::Style::posix);
1379+
EXPECT_FALSE(Found);
1380+
EXPECT_EQ(Path, "C:\\old/foo\\bar");
13561381
}
13571382

13581383
TEST_F(FileSystemTest, OpenFileForRead) {

0 commit comments

Comments
 (0)