@@ -590,14 +590,77 @@ SMLoc SourceMgrDiagnosticHandler::convertLocToSMLoc(FileLineColLoc loc) {
590
590
591
591
namespace mlir {
592
592
namespace detail {
593
- // Record the expected diagnostic's position, substring and whether it was
594
- // seen.
593
+ // / This class represents an expected output diagnostic.
595
594
struct ExpectedDiag {
595
+ ExpectedDiag (DiagnosticSeverity kind, unsigned lineNo, SMLoc fileLoc,
596
+ StringRef substring)
597
+ : kind(kind), lineNo(lineNo), fileLoc(fileLoc), substring(substring) {}
598
+
599
+ // / Emit an error at the location referenced by this diagnostic.
600
+ LogicalResult emitError (raw_ostream &os, llvm::SourceMgr &mgr,
601
+ const Twine &msg) {
602
+ SMRange range (fileLoc, SMLoc::getFromPointer (fileLoc.getPointer () +
603
+ substring.size ()));
604
+ mgr.PrintMessage (os, fileLoc, llvm::SourceMgr::DK_Error, msg, range);
605
+ return failure ();
606
+ }
607
+
608
+ // / Returns true if this diagnostic matches the given string.
609
+ bool match (StringRef str) const {
610
+ // If this isn't a regex diagnostic, we simply check if the string was
611
+ // contained.
612
+ if (substringRegex)
613
+ return substringRegex->match (str);
614
+ return str.contains (substring);
615
+ }
616
+
617
+ // / Compute the regex matcher for this diagnostic, using the provided stream
618
+ // / and manager to emit diagnostics as necessary.
619
+ LogicalResult computeRegex (raw_ostream &os, llvm::SourceMgr &mgr) {
620
+ std::string regexStr;
621
+ llvm::raw_string_ostream regexOS (regexStr);
622
+ StringRef strToProcess = substring;
623
+ while (!strToProcess.empty ()) {
624
+ // Find the next regex block.
625
+ size_t regexIt = strToProcess.find (" {{" );
626
+ if (regexIt == StringRef::npos) {
627
+ regexOS << llvm::Regex::escape (strToProcess);
628
+ break ;
629
+ }
630
+ regexOS << llvm::Regex::escape (strToProcess.take_front (regexIt));
631
+ strToProcess = strToProcess.drop_front (regexIt + 2 );
632
+
633
+ // Find the end of the regex block.
634
+ size_t regexEndIt = strToProcess.find (" }}" );
635
+ if (regexEndIt == StringRef::npos)
636
+ return emitError (os, mgr, " found start of regex with no end '}}'" );
637
+ StringRef regexStr = strToProcess.take_front (regexEndIt);
638
+
639
+ // Validate that the regex is actually valid.
640
+ std::string regexError;
641
+ if (!llvm::Regex (regexStr).isValid (regexError))
642
+ return emitError (os, mgr, " invalid regex: " + regexError);
643
+
644
+ regexOS << ' (' << regexStr << ' )' ;
645
+ strToProcess = strToProcess.drop_front (regexEndIt + 2 );
646
+ }
647
+ substringRegex = llvm::Regex (regexOS.str ());
648
+ return success ();
649
+ }
650
+
651
+ // / The severity of the diagnosic expected.
596
652
DiagnosticSeverity kind;
653
+ // / The line number the expected diagnostic should be on.
597
654
unsigned lineNo;
598
- StringRef substring;
655
+ // / The location of the expected diagnostic within the input file.
599
656
SMLoc fileLoc;
600
- bool matched;
657
+ // / A flag indicating if the expected diagnostic has been matched yet.
658
+ bool matched = false ;
659
+ // / The substring that is expected to be within the diagnostic.
660
+ StringRef substring;
661
+ // / An optional regex matcher, if the expected diagnostic sub-string was a
662
+ // / regex string.
663
+ Optional<llvm::Regex> substringRegex;
601
664
};
602
665
603
666
struct SourceMgrDiagnosticVerifierHandlerImpl {
@@ -608,7 +671,8 @@ struct SourceMgrDiagnosticVerifierHandlerImpl {
608
671
609
672
// / Computes the expected diagnostics for the given source buffer.
610
673
MutableArrayRef<ExpectedDiag>
611
- computeExpectedDiags (const llvm::MemoryBuffer *buf);
674
+ computeExpectedDiags (raw_ostream &os, llvm::SourceMgr &mgr,
675
+ const llvm::MemoryBuffer *buf);
612
676
613
677
// / The current status of the verifier.
614
678
LogicalResult status;
@@ -617,8 +681,9 @@ struct SourceMgrDiagnosticVerifierHandlerImpl {
617
681
llvm::StringMap<SmallVector<ExpectedDiag, 2 >> expectedDiagsPerFile;
618
682
619
683
// / Regex to match the expected diagnostics format.
620
- llvm::Regex expected = llvm::Regex(" expected-(error|note|remark|warning) "
621
- " *(@([+-][0-9]+|above|below))? *{{(.*)}}" );
684
+ llvm::Regex expected =
685
+ llvm::Regex (" expected-(error|note|remark|warning)(-re)? "
686
+ " *(@([+-][0-9]+|above|below))? *{{(.*)}}$" );
622
687
};
623
688
} // namespace detail
624
689
} // namespace mlir
@@ -638,7 +703,6 @@ static StringRef getDiagKindStr(DiagnosticSeverity kind) {
638
703
llvm_unreachable (" Unknown DiagnosticSeverity" );
639
704
}
640
705
641
- // / Returns the expected diagnostics for the given source file.
642
706
Optional<MutableArrayRef<ExpectedDiag>>
643
707
SourceMgrDiagnosticVerifierHandlerImpl::getExpectedDiags (StringRef bufName) {
644
708
auto expectedDiags = expectedDiagsPerFile.find (bufName);
@@ -647,10 +711,9 @@ SourceMgrDiagnosticVerifierHandlerImpl::getExpectedDiags(StringRef bufName) {
647
711
return llvm::None;
648
712
}
649
713
650
- // / Computes the expected diagnostics for the given source buffer.
651
714
MutableArrayRef<ExpectedDiag>
652
715
SourceMgrDiagnosticVerifierHandlerImpl::computeExpectedDiags (
653
- const llvm::MemoryBuffer *buf) {
716
+ raw_ostream &os, llvm::SourceMgr &mgr, const llvm::MemoryBuffer *buf) {
654
717
// If the buffer is invalid, return an empty list.
655
718
if (!buf)
656
719
return llvm::None;
@@ -667,7 +730,7 @@ SourceMgrDiagnosticVerifierHandlerImpl::computeExpectedDiags(
667
730
buf->getBuffer ().split (lines, ' \n ' );
668
731
for (unsigned lineNo = 0 , e = lines.size (); lineNo < e; ++lineNo) {
669
732
SmallVector<StringRef, 4 > matches;
670
- if (!expected.match (lines[lineNo], &matches)) {
733
+ if (!expected.match (lines[lineNo]. rtrim () , &matches)) {
671
734
// Check for designators that apply to this line.
672
735
if (!designatorsForNextLine.empty ()) {
673
736
for (unsigned diagIndex : designatorsForNextLine)
@@ -679,7 +742,7 @@ SourceMgrDiagnosticVerifierHandlerImpl::computeExpectedDiags(
679
742
}
680
743
681
744
// Point to the start of expected-*.
682
- auto expectedStart = SMLoc::getFromPointer (matches[0 ].data ());
745
+ SMLoc expectedStart = SMLoc::getFromPointer (matches[0 ].data ());
683
746
684
747
DiagnosticSeverity kind;
685
748
if (matches[1 ] == " error" )
@@ -692,9 +755,15 @@ SourceMgrDiagnosticVerifierHandlerImpl::computeExpectedDiags(
692
755
assert (matches[1 ] == " note" );
693
756
kind = DiagnosticSeverity::Note;
694
757
}
758
+ ExpectedDiag record (kind, lineNo + 1 , expectedStart, matches[5 ]);
695
759
696
- ExpectedDiag record{kind, lineNo + 1 , matches[4 ], expectedStart, false };
697
- auto offsetMatch = matches[2 ];
760
+ // Check to see if this is a regex match, i.e. it includes the `-re`.
761
+ if (!matches[2 ].empty () && failed (record.computeRegex (os, mgr))) {
762
+ status = failure ();
763
+ continue ;
764
+ }
765
+
766
+ StringRef offsetMatch = matches[3 ];
698
767
if (!offsetMatch.empty ()) {
699
768
offsetMatch = offsetMatch.drop_front (1 );
700
769
@@ -722,7 +791,7 @@ SourceMgrDiagnosticVerifierHandlerImpl::computeExpectedDiags(
722
791
record.lineNo = e;
723
792
}
724
793
}
725
- expectedDiags.push_back ( record);
794
+ expectedDiags.emplace_back ( std::move ( record) );
726
795
}
727
796
return expectedDiags;
728
797
}
@@ -734,7 +803,7 @@ SourceMgrDiagnosticVerifierHandler::SourceMgrDiagnosticVerifierHandler(
734
803
// Compute the expected diagnostics for each of the current files in the
735
804
// source manager.
736
805
for (unsigned i = 0 , e = mgr.getNumBuffers (); i != e; ++i)
737
- (void )impl->computeExpectedDiags (mgr.getMemoryBuffer (i + 1 ));
806
+ (void )impl->computeExpectedDiags (out, mgr, mgr.getMemoryBuffer (i + 1 ));
738
807
739
808
// Register a handler to verify the diagnostics.
740
809
setHandler ([&](Diagnostic &diag) {
@@ -765,14 +834,10 @@ LogicalResult SourceMgrDiagnosticVerifierHandler::verify() {
765
834
for (auto &err : expectedDiagsPair.second ) {
766
835
if (err.matched )
767
836
continue ;
768
- SMRange range (err.fileLoc ,
769
- SMLoc::getFromPointer (err.fileLoc .getPointer () +
770
- err.substring .size ()));
771
- mgr.PrintMessage (os, err.fileLoc , llvm::SourceMgr::DK_Error,
772
- " expected " + getDiagKindStr (err.kind ) + " \" " +
773
- err.substring + " \" was not produced" ,
774
- range);
775
- impl->status = failure ();
837
+ impl->status =
838
+ err.emitError (os, mgr,
839
+ " expected " + getDiagKindStr (err.kind ) + " \" " +
840
+ err.substring + " \" was not produced" );
776
841
}
777
842
}
778
843
impl->expectedDiagsPerFile .clear ();
@@ -799,8 +864,10 @@ void SourceMgrDiagnosticVerifierHandler::process(FileLineColLoc loc,
799
864
DiagnosticSeverity kind) {
800
865
// Get the expected diagnostics for this file.
801
866
auto diags = impl->getExpectedDiags (loc.getFilename ());
802
- if (!diags)
803
- diags = impl->computeExpectedDiags (getBufferForFile (loc.getFilename ()));
867
+ if (!diags) {
868
+ diags = impl->computeExpectedDiags (os, mgr,
869
+ getBufferForFile (loc.getFilename ()));
870
+ }
804
871
805
872
// Search for a matching expected diagnostic.
806
873
// If we find something that is close then emit a more specific error.
@@ -809,7 +876,7 @@ void SourceMgrDiagnosticVerifierHandler::process(FileLineColLoc loc,
809
876
// If this was an expected error, remember that we saw it and return.
810
877
unsigned line = loc.getLine ();
811
878
for (auto &e : *diags) {
812
- if (line == e.lineNo && msg. contains (e. substring )) {
879
+ if (line == e.lineNo && e. match (msg )) {
813
880
if (e.kind == kind) {
814
881
e.matched = true ;
815
882
return ;
0 commit comments