@@ -72,6 +72,9 @@ struct ExpectedDiagnosticInfo {
72
72
// This specifies the full range of the "expected-foo {{}}" specifier.
73
73
const char *ExpectedStart, *ExpectedEnd = nullptr ;
74
74
75
+ // This specifies the full range of the classification string.
76
+ const char *ClassificationStart, *ClassificationEnd = nullptr ;
77
+
75
78
DiagnosticKind Classification;
76
79
77
80
// This is true if a '*' constraint is present to say that the diagnostic
@@ -108,8 +111,11 @@ struct ExpectedDiagnosticInfo {
108
111
Optional<ExpectedEducationalNotes> EducationalNotes;
109
112
110
113
ExpectedDiagnosticInfo (const char *ExpectedStart,
114
+ const char *ClassificationStart,
115
+ const char *ClassificationEnd,
111
116
DiagnosticKind Classification)
112
- : ExpectedStart(ExpectedStart), Classification(Classification) {}
117
+ : ExpectedStart(ExpectedStart), ClassificationStart(ClassificationStart),
118
+ ClassificationEnd (ClassificationEnd), Classification(Classification) {}
113
119
};
114
120
115
121
static std::string getDiagKindString (DiagnosticKind Kind) {
@@ -139,11 +145,15 @@ renderEducationalNotes(llvm::SmallVectorImpl<std::string> &EducationalNotes) {
139
145
return OS.str ();
140
146
}
141
147
142
- // / If we find the specified diagnostic in the list, return it.
143
- // / Otherwise return CapturedDiagnostics.end().
144
- static std::vector<CapturedDiagnosticInfo>::iterator
148
+ // / If we find the specified diagnostic in the list, return it with \c true .
149
+ // / If we find a near-match that varies only in classification, return it with
150
+ // / \c false.
151
+ // / Otherwise return \c CapturedDiagnostics.end() with \c false.
152
+ static std::tuple<std::vector<CapturedDiagnosticInfo>::iterator, bool >
145
153
findDiagnostic (std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
146
154
const ExpectedDiagnosticInfo &Expected, StringRef BufferName) {
155
+ auto fallbackI = CapturedDiagnostics.end ();
156
+
147
157
for (auto I = CapturedDiagnostics.begin (), E = CapturedDiagnostics.end ();
148
158
I != E; ++I) {
149
159
// Verify the file and line of the diagnostic.
@@ -155,15 +165,22 @@ findDiagnostic(std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
155
165
continue ;
156
166
157
167
// Verify the classification and string.
158
- if (I->Classification != Expected.Classification ||
159
- I->Message .find (Expected.MessageStr ) == StringRef::npos)
168
+ if (I->Message .find (Expected.MessageStr ) == StringRef::npos)
160
169
continue ;
161
170
171
+ // Verify the classification and, if incorrect, remember as a second choice.
172
+ if (I->Classification != Expected.Classification ) {
173
+ if (fallbackI == E && !Expected.MessageStr .empty ())
174
+ fallbackI = I;
175
+ continue ;
176
+ }
177
+
162
178
// Okay, we found a match, hurray!
163
- return I ;
179
+ return { I, true } ;
164
180
}
165
181
166
- return CapturedDiagnostics.end ();
182
+ // No perfect match; we'll return the fallback or `end()` instead.
183
+ return { fallbackI, false };
167
184
}
168
185
169
186
// / If there are any -verify errors (e.g. differences between expectations
@@ -481,20 +498,22 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
481
498
// the next match.
482
499
StringRef MatchStart = InputFile.substr (Match);
483
500
const char *DiagnosticLoc = MatchStart.data ();
501
+ MatchStart = MatchStart.substr (strlen (" expected-" ));
502
+ const char *ClassificationStartLoc = MatchStart.data ();
484
503
485
504
DiagnosticKind ExpectedClassification;
486
- if (MatchStart.startswith (" expected- note" )) {
505
+ if (MatchStart.startswith (" note" )) {
487
506
ExpectedClassification = DiagnosticKind::Note;
488
- MatchStart = MatchStart.substr (strlen (" expected- note" ));
489
- } else if (MatchStart.startswith (" expected- warning" )) {
507
+ MatchStart = MatchStart.substr (strlen (" note" ));
508
+ } else if (MatchStart.startswith (" warning" )) {
490
509
ExpectedClassification = DiagnosticKind::Warning;
491
- MatchStart = MatchStart.substr (strlen (" expected- warning" ));
492
- } else if (MatchStart.startswith (" expected- error" )) {
510
+ MatchStart = MatchStart.substr (strlen (" warning" ));
511
+ } else if (MatchStart.startswith (" error" )) {
493
512
ExpectedClassification = DiagnosticKind::Error;
494
- MatchStart = MatchStart.substr (strlen (" expected- error" ));
495
- } else if (MatchStart.startswith (" expected- remark" )) {
513
+ MatchStart = MatchStart.substr (strlen (" error" ));
514
+ } else if (MatchStart.startswith (" remark" )) {
496
515
ExpectedClassification = DiagnosticKind::Remark;
497
- MatchStart = MatchStart.substr (strlen (" expected- remark" ));
516
+ MatchStart = MatchStart.substr (strlen (" remark" ));
498
517
} else
499
518
continue ;
500
519
@@ -508,7 +527,9 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
508
527
continue ;
509
528
}
510
529
511
- ExpectedDiagnosticInfo Expected (DiagnosticLoc, ExpectedClassification);
530
+ ExpectedDiagnosticInfo Expected (DiagnosticLoc, ClassificationStartLoc,
531
+ /* ClassificationEndLoc=*/ MatchStart.data (),
532
+ ExpectedClassification);
512
533
int LineOffset = 0 ;
513
534
514
535
if (TextStartIdx > 0 && MatchStart[0 ] == ' @' ) {
@@ -750,18 +771,40 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
750
771
auto &expected = ExpectedDiagnostics[i];
751
772
752
773
// Check to see if we had this expected diagnostic.
753
- auto FoundDiagnosticIter =
774
+ auto FoundDiagnosticInfo =
754
775
findDiagnostic (CapturedDiagnostics, expected, BufferName);
776
+ auto FoundDiagnosticIter = std::get<0 >(FoundDiagnosticInfo);
755
777
if (FoundDiagnosticIter == CapturedDiagnostics.end ()) {
756
778
// Diagnostic didn't exist. If this is a 'mayAppear' diagnostic, then
757
779
// we're ok. Otherwise, leave it in the list.
758
780
if (expected.mayAppear )
759
781
ExpectedDiagnostics.erase (ExpectedDiagnostics.begin ()+i);
760
782
continue ;
761
783
}
762
-
784
+
785
+ auto emitFixItsError = [&](const char *location, const Twine &message,
786
+ const char *replStartLoc, const char *replEndLoc,
787
+ const std::string &replStr) {
788
+ llvm::SMFixIt fix (llvm::SMRange (SMLoc::getFromPointer (replStartLoc),
789
+ SMLoc::getFromPointer (replEndLoc)),
790
+ replStr);
791
+ addError (location, message, fix);
792
+ };
793
+
763
794
auto &FoundDiagnostic = *FoundDiagnosticIter;
764
795
796
+ if (!std::get<1 >(FoundDiagnosticInfo)) {
797
+ // Found a diagnostic with the right location and text but the wrong
798
+ // classification. We'll emit an error about the mismatch and
799
+ // thereafter pretend that the diagnostic fully matched.
800
+ auto expectedKind = getDiagKindString (expected.Classification );
801
+ auto actualKind = getDiagKindString (FoundDiagnostic.Classification );
802
+ emitFixItsError (expected.ClassificationStart ,
803
+ llvm::Twine (" expected " ) + expectedKind + " , not " + actualKind,
804
+ expected.ClassificationStart , expected.ClassificationEnd ,
805
+ actualKind);
806
+ }
807
+
765
808
const char *missedFixitLoc = nullptr ;
766
809
// Verify that any expected fix-its are present in the diagnostic.
767
810
for (auto fixit : expected.Fixits ) {
@@ -791,15 +834,6 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
791
834
actualFixitsStr};
792
835
};
793
836
794
- auto emitFixItsError = [&](const char *location, const Twine &message,
795
- const char *replStartLoc, const char *replEndLoc,
796
- const std::string &replStr) {
797
- llvm::SMFixIt fix (llvm::SMRange (SMLoc::getFromPointer (replStartLoc),
798
- SMLoc::getFromPointer (replEndLoc)),
799
- replStr);
800
- addError (location, message, fix);
801
- };
802
-
803
837
// If we have any expected fixits that didn't get matched, then they are
804
838
// wrong. Replace the failed fixit with what actually happened.
805
839
0 commit comments