@@ -1634,6 +1634,60 @@ static size_t SkipWord(StringRef Str, size_t Loc) {
1634
1634
return Loc;
1635
1635
}
1636
1636
1637
+ static const char *DefaultCheckPrefixes[] = {" CHECK" };
1638
+ static const char *DefaultCommentPrefixes[] = {" COM" , " RUN" };
1639
+
1640
+ static void addDefaultPrefixes (FileCheckRequest &Req) {
1641
+ if (Req.CheckPrefixes .empty ()) {
1642
+ for (const char *Prefix : DefaultCheckPrefixes)
1643
+ Req.CheckPrefixes .push_back (Prefix);
1644
+ Req.IsDefaultCheckPrefix = true ;
1645
+ }
1646
+ if (Req.CommentPrefixes .empty ())
1647
+ for (const char *Prefix : DefaultCommentPrefixes)
1648
+ Req.CommentPrefixes .push_back (Prefix);
1649
+ }
1650
+
1651
+ struct PrefixMatcher {
1652
+ // / Prefixes and their first occurrence past the current position.
1653
+ SmallVector<std::pair<StringRef, size_t >> Prefixes;
1654
+ StringRef Input;
1655
+
1656
+ PrefixMatcher (ArrayRef<StringRef> CheckPrefixes,
1657
+ ArrayRef<StringRef> CommentPrefixes, StringRef Input)
1658
+ : Input(Input) {
1659
+ for (StringRef Prefix : CheckPrefixes)
1660
+ Prefixes.push_back ({Prefix, Input.find (Prefix)});
1661
+ for (StringRef Prefix : CommentPrefixes)
1662
+ Prefixes.push_back ({Prefix, Input.find (Prefix)});
1663
+
1664
+ // Sort by descending length.
1665
+ llvm::sort (Prefixes,
1666
+ [](auto A, auto B) { return A.first .size () > B.first .size (); });
1667
+ }
1668
+
1669
+ // / Find the next match of a prefix in Buffer.
1670
+ // / Returns empty StringRef if not found.
1671
+ StringRef match (StringRef Buffer) {
1672
+ assert (Buffer.data () >= Input.data () &&
1673
+ Buffer.data () + Buffer.size () == Input.data () + Input.size () &&
1674
+ " Buffer must be suffix of Input" );
1675
+
1676
+ size_t From = Buffer.data () - Input.data ();
1677
+ StringRef Match;
1678
+ for (auto &[Prefix, Pos] : Prefixes) {
1679
+ // If the last occurrence was before From, find the next one after From.
1680
+ if (Pos < From)
1681
+ Pos = Input.find (Prefix, From);
1682
+ // Find the first prefix with the lowest position.
1683
+ if (Pos != StringRef::npos &&
1684
+ (Match.empty () || size_t (Match.data () - Input.data ()) > Pos))
1685
+ Match = StringRef (Input.substr (Pos, Prefix.size ()));
1686
+ }
1687
+ return Match;
1688
+ }
1689
+ };
1690
+
1637
1691
// / Searches the buffer for the first prefix in the prefix regular expression.
1638
1692
// /
1639
1693
// / This searches the buffer using the provided regular expression, however it
@@ -1658,20 +1712,16 @@ static size_t SkipWord(StringRef Str, size_t Loc) {
1658
1712
// / If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1659
1713
// / is unspecified.
1660
1714
static std::pair<StringRef, StringRef>
1661
- FindFirstMatchingPrefix (const FileCheckRequest &Req, Regex &PrefixRE ,
1715
+ FindFirstMatchingPrefix (const FileCheckRequest &Req, PrefixMatcher &Matcher ,
1662
1716
StringRef &Buffer, unsigned &LineNumber,
1663
1717
Check::FileCheckType &CheckTy) {
1664
- SmallVector<StringRef, 2 > Matches;
1665
-
1666
1718
while (!Buffer.empty ()) {
1667
- // Find the first (longest) match using the RE.
1668
- if (!PrefixRE.match (Buffer, &Matches))
1719
+ // Find the first (longest) prefix match.
1720
+ StringRef Prefix = Matcher.match (Buffer);
1721
+ if (Prefix.empty ())
1669
1722
// No match at all, bail.
1670
1723
return {StringRef (), StringRef ()};
1671
1724
1672
- StringRef Prefix = Matches[0 ];
1673
- Matches.clear ();
1674
-
1675
1725
assert (Prefix.data () >= Buffer.data () &&
1676
1726
Prefix.data () < Buffer.data () + Buffer.size () &&
1677
1727
" Prefix doesn't start inside of buffer!" );
@@ -1720,7 +1770,7 @@ FileCheck::FileCheck(FileCheckRequest Req)
1720
1770
FileCheck::~FileCheck () = default ;
1721
1771
1722
1772
bool FileCheck::readCheckFile (
1723
- SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
1773
+ SourceMgr &SM, StringRef Buffer,
1724
1774
std::pair<unsigned , unsigned > *ImpPatBufferIDRange) {
1725
1775
if (ImpPatBufferIDRange)
1726
1776
ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0 ;
@@ -1769,6 +1819,8 @@ bool FileCheck::readCheckFile(
1769
1819
// found.
1770
1820
unsigned LineNumber = 1 ;
1771
1821
1822
+ addDefaultPrefixes (Req);
1823
+ PrefixMatcher Matcher (Req.CheckPrefixes , Req.CommentPrefixes , Buffer);
1772
1824
std::set<StringRef> PrefixesNotFound (Req.CheckPrefixes .begin (),
1773
1825
Req.CheckPrefixes .end ());
1774
1826
const size_t DistinctPrefixes = PrefixesNotFound.size ();
@@ -1779,7 +1831,7 @@ bool FileCheck::readCheckFile(
1779
1831
StringRef UsedPrefix;
1780
1832
StringRef AfterSuffix;
1781
1833
std::tie (UsedPrefix, AfterSuffix) =
1782
- FindFirstMatchingPrefix (Req, PrefixRE , Buffer, LineNumber, CheckTy);
1834
+ FindFirstMatchingPrefix (Req, Matcher , Buffer, LineNumber, CheckTy);
1783
1835
if (UsedPrefix.empty ())
1784
1836
break ;
1785
1837
if (CheckTy != Check::CheckComment)
@@ -2431,9 +2483,6 @@ static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes,
2431
2483
return true ;
2432
2484
}
2433
2485
2434
- static const char *DefaultCheckPrefixes[] = {" CHECK" };
2435
- static const char *DefaultCommentPrefixes[] = {" COM" , " RUN" };
2436
-
2437
2486
bool FileCheck::ValidateCheckPrefixes () {
2438
2487
StringSet<> UniquePrefixes;
2439
2488
// Add default prefixes to catch user-supplied duplicates of them below.
@@ -2454,33 +2503,6 @@ bool FileCheck::ValidateCheckPrefixes() {
2454
2503
return true ;
2455
2504
}
2456
2505
2457
- Regex FileCheck::buildCheckPrefixRegex () {
2458
- if (Req.CheckPrefixes .empty ()) {
2459
- for (const char *Prefix : DefaultCheckPrefixes)
2460
- Req.CheckPrefixes .push_back (Prefix);
2461
- Req.IsDefaultCheckPrefix = true ;
2462
- }
2463
- if (Req.CommentPrefixes .empty ()) {
2464
- for (const char *Prefix : DefaultCommentPrefixes)
2465
- Req.CommentPrefixes .push_back (Prefix);
2466
- }
2467
-
2468
- // We already validated the contents of CheckPrefixes and CommentPrefixes so
2469
- // just concatenate them as alternatives.
2470
- SmallString<32 > PrefixRegexStr;
2471
- for (size_t I = 0 , E = Req.CheckPrefixes .size (); I != E; ++I) {
2472
- if (I != 0 )
2473
- PrefixRegexStr.push_back (' |' );
2474
- PrefixRegexStr.append (Req.CheckPrefixes [I]);
2475
- }
2476
- for (StringRef Prefix : Req.CommentPrefixes ) {
2477
- PrefixRegexStr.push_back (' |' );
2478
- PrefixRegexStr.append (Prefix);
2479
- }
2480
-
2481
- return Regex (PrefixRegexStr);
2482
- }
2483
-
2484
2506
Error FileCheckPatternContext::defineCmdlineVariables (
2485
2507
ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) {
2486
2508
assert (GlobalVariableTable.empty () && GlobalNumericVariableTable.empty () &&
0 commit comments