aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/GlobPattern.cpp11
-rw-r--r--llvm/lib/Support/SpecialCaseList.cpp76
2 files changed, 60 insertions, 27 deletions
diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp
index 7004adf..0ecf47d 100644
--- a/llvm/lib/Support/GlobPattern.cpp
+++ b/llvm/lib/Support/GlobPattern.cpp
@@ -143,6 +143,15 @@ GlobPattern::create(StringRef S, std::optional<size_t> MaxSubPatterns) {
return Pat;
S = S.substr(PrefixSize);
+ // Just in case we stop on unmatched opening brackets.
+ size_t SuffixStart = S.find_last_of("?*[]{}\\");
+ assert(SuffixStart != std::string::npos);
+ if (S[SuffixStart] == '\\')
+ ++SuffixStart;
+ ++SuffixStart;
+ Pat.Suffix = S.substr(SuffixStart);
+ S = S.substr(0, SuffixStart);
+
SmallVector<std::string, 1> SubPats;
if (auto Err = parseBraceExpansions(S, MaxSubPatterns).moveInto(SubPats))
return std::move(Err);
@@ -193,6 +202,8 @@ GlobPattern::SubGlobPattern::create(StringRef S) {
bool GlobPattern::match(StringRef S) const {
if (!S.consume_front(Prefix))
return false;
+ if (!S.consume_back(Suffix))
+ return false;
if (SubGlobs.empty() && S.empty())
return true;
for (auto &Glob : SubGlobs)
diff --git a/llvm/lib/Support/SpecialCaseList.cpp b/llvm/lib/Support/SpecialCaseList.cpp
index 8d4e043..6ad8d7d 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -15,9 +15,13 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include <algorithm>
+#include <limits>
#include <stdio.h>
#include <string>
#include <system_error>
@@ -48,15 +52,14 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, unsigned LineNumber,
if (!CheckRE.isValid(REError))
return createStringError(errc::invalid_argument, REError);
- RegExes.emplace_back(std::make_pair(
- std::make_unique<Regex>(std::move(CheckRE)), LineNumber));
+ auto Rg =
+ std::make_unique<Matcher::Reg>(Pattern, LineNumber, std::move(CheckRE));
+ RegExes.emplace_back(std::move(Rg));
return Error::success();
}
- auto Glob = std::make_unique<Matcher::Glob>();
- Glob->Name = Pattern.str();
- Glob->LineNo = LineNumber;
+ auto Glob = std::make_unique<Matcher::Glob>(Pattern, LineNumber);
// We must be sure to use the string in `Glob` rather than the provided
// reference which could be destroyed before match() is called
if (auto Err = GlobPattern::create(Glob->Name, /*MaxSubPatterns=*/1024)
@@ -66,14 +69,15 @@ Error SpecialCaseList::Matcher::insert(StringRef Pattern, unsigned LineNumber,
return Error::success();
}
-unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
+void SpecialCaseList::Matcher::match(
+ StringRef Query,
+ llvm::function_ref<void(StringRef Rule, unsigned LineNo)> Cb) const {
for (const auto &Glob : reverse(Globs))
if (Glob->Pattern.match(Query))
- return Glob->LineNo;
- for (const auto &[Regex, LineNumber] : reverse(RegExes))
- if (Regex->match(Query))
- return LineNumber;
- return 0;
+ Cb(Glob->Name, Glob->LineNo);
+ for (const auto &Regex : reverse(RegExes))
+ if (Regex->Rg.match(Query))
+ Cb(Regex->Name, Regex->LineNo);
}
// TODO: Refactor this to return Expected<...>
@@ -135,7 +139,7 @@ SpecialCaseList::addSection(StringRef SectionStr, unsigned FileNo,
Sections.emplace_back(SectionStr, FileNo);
auto &Section = Sections.back();
- if (auto Err = Section.SectionMatcher->insert(SectionStr, LineNo, UseGlobs)) {
+ if (auto Err = Section.SectionMatcher.insert(SectionStr, LineNo, UseGlobs)) {
return createStringError(errc::invalid_argument,
"malformed section at line " + Twine(LineNo) +
": '" + SectionStr +
@@ -147,19 +151,25 @@ SpecialCaseList::addSection(StringRef SectionStr, unsigned FileNo,
bool SpecialCaseList::parse(unsigned FileIdx, const MemoryBuffer *MB,
std::string &Error) {
+ unsigned long long Version = 2;
+
+ StringRef Header = MB->getBuffer();
+ if (Header.consume_front("#!special-case-list-v"))
+ consumeUnsignedInteger(Header, 10, Version);
+
+ // In https://reviews.llvm.org/D154014 we added glob support and planned
+ // to remove regex support in patterns. We temporarily support the
+ // original behavior using regexes if "#!special-case-list-v1" is the
+ // first line of the file. For more details, see
+ // https://discourse.llvm.org/t/use-glob-instead-of-regex-for-specialcaselists/71666
+ bool UseGlobs = Version > 1;
+
Section *CurrentSection;
if (auto Err = addSection("*", FileIdx, 1).moveInto(CurrentSection)) {
Error = toString(std::move(Err));
return false;
}
- // In https://reviews.llvm.org/D154014 we added glob support and planned to
- // remove regex support in patterns. We temporarily support the original
- // behavior using regexes if "#!special-case-list-v1" is the first line of the
- // file. For more details, see
- // https://discourse.llvm.org/t/use-glob-instead-of-regex-for-specialcaselists/71666
- bool UseGlobs = !MB->getBuffer().starts_with("#!special-case-list-v1\n");
-
for (line_iterator LineIt(*MB, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
!LineIt.is_at_eof(); LineIt++) {
unsigned LineNo = LineIt.line_number();
@@ -218,8 +228,8 @@ std::pair<unsigned, unsigned>
SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
StringRef Query, StringRef Category) const {
for (const auto &S : reverse(Sections)) {
- if (S.SectionMatcher->match(Section)) {
- unsigned Blame = inSectionBlame(S.Entries, Prefix, Query, Category);
+ if (S.SectionMatcher.matchAny(Section)) {
+ unsigned Blame = S.getLastMatch(Prefix, Query, Category);
if (Blame)
return {S.FileIdx, Blame};
}
@@ -227,17 +237,29 @@ SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
return NotFound;
}
-unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
- StringRef Prefix, StringRef Query,
- StringRef Category) const {
+const SpecialCaseList::Matcher *
+SpecialCaseList::Section::findMatcher(StringRef Prefix,
+ StringRef Category) const {
SectionEntries::const_iterator I = Entries.find(Prefix);
if (I == Entries.end())
- return 0;
+ return nullptr;
StringMap<Matcher>::const_iterator II = I->second.find(Category);
if (II == I->second.end())
- return 0;
+ return nullptr;
+
+ return &II->second;
+}
- return II->getValue().match(Query);
+unsigned SpecialCaseList::Section::getLastMatch(StringRef Prefix,
+ StringRef Query,
+ StringRef Category) const {
+ unsigned LastLine = 0;
+ if (const Matcher *M = findMatcher(Prefix, Category)) {
+ M->match(Query, [&](StringRef, unsigned LineNo) {
+ LastLine = std::max(LastLine, LineNo);
+ });
+ }
+ return LastLine;
}
} // namespace llvm