Skip to content

Commit 466f691

Browse files
authored
[SpecialCaseList] Remove ./ from file path (#162437)
This extends approach used in WarningsSpecialCaseList on other types of SpecialCaseList. SpecialCaseList will remove leading "./" from the Query for prefixes which looks like file names. Now affected prefixes are "src", "!src", "mainfile", "source". To avoid breaking users, this behavior is enabled for files starting "#!special-case-list-v3".
1 parent 98ce434 commit 466f691

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

llvm/include/llvm/Support/SpecialCaseList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class SpecialCaseList {
156156

157157
std::vector<std::unique_ptr<Matcher::Glob>> Globs;
158158
std::vector<std::unique_ptr<Reg>> RegExes;
159+
bool RemoveDotSlash = false;
159160
};
160161

161162
using SectionEntries = StringMap<StringMap<Matcher>>;

llvm/lib/Support/SpecialCaseList.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/Support/VirtualFileSystem.h"
2323
#include <algorithm>
2424
#include <limits>
25+
#include <memory>
2526
#include <stdio.h>
2627
#include <string>
2728
#include <system_error>
@@ -72,6 +73,8 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, unsigned LineNumber,
7273
void SpecialCaseList::Matcher::match(
7374
StringRef Query,
7475
llvm::function_ref<void(StringRef Rule, unsigned LineNo)> Cb) const {
76+
if (RemoveDotSlash)
77+
Query = llvm::sys::path::remove_leading_dotslash(Query);
7578
for (const auto &Glob : reverse(Globs))
7679
if (Glob->Pattern.match(Query))
7780
Cb(Glob->Name, Glob->LineNo);
@@ -164,12 +167,18 @@ bool SpecialCaseList::parse(unsigned FileIdx, const MemoryBuffer *MB,
164167
// https://discourse.llvm.org/t/use-glob-instead-of-regex-for-specialcaselists/71666
165168
bool UseGlobs = Version > 1;
166169

170+
bool RemoveDotSlash = Version > 2;
171+
167172
Section *CurrentSection;
168173
if (auto Err = addSection("*", FileIdx, 1).moveInto(CurrentSection)) {
169174
Error = toString(std::move(Err));
170175
return false;
171176
}
172177

178+
// This is the current list of prefixes for all existing users matching file
179+
// path. We may need parametrization in constructor in future.
180+
constexpr StringRef PathPrefixes[] = {"src", "!src", "mainfile", "source"};
181+
173182
for (line_iterator LineIt(*MB, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
174183
!LineIt.is_at_eof(); LineIt++) {
175184
unsigned LineNo = LineIt.line_number();
@@ -205,6 +214,8 @@ bool SpecialCaseList::parse(unsigned FileIdx, const MemoryBuffer *MB,
205214

206215
auto [Pattern, Category] = Postfix.split("=");
207216
auto &Entry = CurrentSection->Entries[Prefix][Category];
217+
Entry.RemoveDotSlash =
218+
RemoveDotSlash && llvm::is_contained(PathPrefixes, Prefix);
208219
if (auto Err = Entry.insert(Pattern, LineNo, UseGlobs)) {
209220
Error =
210221
(Twine("malformed ") + (UseGlobs ? "glob" : "regex") + " in line " +

llvm/unittests/Support/SpecialCaseListTest.cpp

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,31 @@ namespace {
2222

2323
class SpecialCaseListTest : public ::testing::Test {
2424
protected:
25-
std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List,
26-
std::string &Error,
27-
bool UseGlobs = true) {
25+
std::unique_ptr<SpecialCaseList>
26+
makeSpecialCaseList(StringRef List, std::string &Error, int Version = 0) {
2827
auto S = List.str();
29-
if (!UseGlobs)
30-
S = (Twine("#!special-case-list-v1\n") + S).str();
28+
if (Version)
29+
S = (Twine("#!special-case-list-v") + Twine(Version) + "\n" + S).str();
3130
std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(S);
3231
return SpecialCaseList::create(MB.get(), Error);
3332
}
3433

3534
std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List,
36-
bool UseGlobs = true) {
35+
int Version = 0) {
3736
std::string Error;
38-
auto SCL = makeSpecialCaseList(List, Error, UseGlobs);
37+
auto SCL = makeSpecialCaseList(List, Error, Version);
3938
assert(SCL);
4039
assert(Error == "");
4140
return SCL;
4241
}
4342

44-
std::string makeSpecialCaseListFile(StringRef Contents,
45-
bool UseGlobs = true) {
43+
std::string makeSpecialCaseListFile(StringRef Contents, int Version = 0) {
4644
int FD;
4745
SmallString<64> Path;
4846
sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path);
4947
raw_fd_ostream OF(FD, true, true);
50-
if (!UseGlobs)
51-
OF << "#!special-case-list-v1\n";
48+
if (Version)
49+
OF << "#!special-case-list-v" << Version << "\n";
5250
OF << Contents;
5351
OF.close();
5452
return std::string(Path.str());
@@ -261,7 +259,7 @@ TEST_F(SpecialCaseListTest, Version1) {
261259
"fun:foo.*\n"
262260
"fun:abc|def\n"
263261
"fun:b.r\n",
264-
/*UseGlobs=*/false);
262+
/*Version=*/1);
265263

266264
EXPECT_TRUE(SCL->inSection("sect1", "fun", "fooz"));
267265
EXPECT_TRUE(SCL->inSection("sect2", "fun", "fooz"));
@@ -309,6 +307,46 @@ TEST_F(SpecialCaseListTest, Version2) {
309307
EXPECT_FALSE(SCL->inSection("sect3", "fun", "bar"));
310308
}
311309

310+
TEST_F(SpecialCaseListTest, DotSlash) {
311+
std::unique_ptr<SpecialCaseList> SCL2 = makeSpecialCaseList("[dot]\n"
312+
"fun:./foo\n"
313+
"src:./bar\n"
314+
"[not]\n"
315+
"fun:foo\n"
316+
"src:bar\n");
317+
std::unique_ptr<SpecialCaseList> SCL3 = makeSpecialCaseList("[dot]\n"
318+
"fun:./foo\n"
319+
"src:./bar\n"
320+
"[not]\n"
321+
"fun:foo\n"
322+
"src:bar\n",
323+
/*Version=*/3);
324+
325+
EXPECT_TRUE(SCL2->inSection("dot", "fun", "./foo"));
326+
EXPECT_TRUE(SCL3->inSection("dot", "fun", "./foo"));
327+
328+
EXPECT_FALSE(SCL2->inSection("dot", "fun", "foo"));
329+
EXPECT_FALSE(SCL3->inSection("dot", "fun", "foo"));
330+
331+
EXPECT_TRUE(SCL2->inSection("dot", "src", "./bar"));
332+
EXPECT_FALSE(SCL3->inSection("dot", "src", "./bar"));
333+
334+
EXPECT_FALSE(SCL2->inSection("dot", "src", "bar"));
335+
EXPECT_FALSE(SCL3->inSection("dot", "src", "bar"));
336+
337+
EXPECT_FALSE(SCL2->inSection("not", "fun", "./foo"));
338+
EXPECT_FALSE(SCL3->inSection("not", "fun", "./foo"));
339+
340+
EXPECT_TRUE(SCL2->inSection("not", "fun", "foo"));
341+
EXPECT_TRUE(SCL3->inSection("not", "fun", "foo"));
342+
343+
EXPECT_FALSE(SCL2->inSection("not", "src", "./bar"));
344+
EXPECT_TRUE(SCL3->inSection("not", "src", "./bar"));
345+
346+
EXPECT_TRUE(SCL2->inSection("not", "src", "bar"));
347+
EXPECT_TRUE(SCL3->inSection("not", "src", "bar"));
348+
}
349+
312350
TEST_F(SpecialCaseListTest, LinesInSection) {
313351
std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:foo\n"
314352
"fun:bar\n"

0 commit comments

Comments
 (0)