@@ -70,6 +70,9 @@ struct ExpectedDiagnosticInfo {
70
70
// This specifies the full range of the "expected-foo {{}}" specifier.
71
71
const char *ExpectedStart, *ExpectedEnd = nullptr ;
72
72
73
+ // This specifies the full range of the classification string.
74
+ const char *ClassificationStart, *ClassificationEnd = nullptr ;
75
+
73
76
DiagnosticKind Classification;
74
77
75
78
// This is true if a '*' constraint is present to say that the diagnostic
@@ -106,8 +109,11 @@ struct ExpectedDiagnosticInfo {
106
109
Optional<ExpectedEducationalNotes> EducationalNotes;
107
110
108
111
ExpectedDiagnosticInfo (const char *ExpectedStart,
112
+ const char *ClassificationStart,
113
+ const char *ClassificationEnd,
109
114
DiagnosticKind Classification)
110
- : ExpectedStart(ExpectedStart), Classification(Classification) {}
115
+ : ExpectedStart(ExpectedStart), ClassificationStart(ClassificationStart),
116
+ ClassificationEnd (ClassificationEnd), Classification(Classification) {}
111
117
};
112
118
113
119
static std::string getDiagKindString (DiagnosticKind Kind) {
@@ -137,11 +143,15 @@ renderEducationalNotes(llvm::SmallVectorImpl<std::string> &EducationalNotes) {
137
143
return OS.str ();
138
144
}
139
145
140
- // / If we find the specified diagnostic in the list, return it.
141
- // / Otherwise return CapturedDiagnostics.end().
142
- static std::vector<CapturedDiagnosticInfo>::iterator
146
+ // / If we find the specified diagnostic in the list, return it with \c true .
147
+ // / If we find a near-match that varies only in classification, return it with
148
+ // / \c false.
149
+ // / Otherwise return \c CapturedDiagnostics.end() with \c false.
150
+ static std::tuple<std::vector<CapturedDiagnosticInfo>::iterator, bool >
143
151
findDiagnostic (std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
144
152
const ExpectedDiagnosticInfo &Expected, StringRef BufferName) {
153
+ auto fallbackI = CapturedDiagnostics.end ();
154
+
145
155
for (auto I = CapturedDiagnostics.begin (), E = CapturedDiagnostics.end ();
146
156
I != E; ++I) {
147
157
// Verify the file and line of the diagnostic.
@@ -153,15 +163,22 @@ findDiagnostic(std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
153
163
continue ;
154
164
155
165
// Verify the classification and string.
156
- if (I->Classification != Expected.Classification ||
157
- I->Message .find (Expected.MessageStr ) == StringRef::npos)
166
+ if (I->Message .find (Expected.MessageStr ) == StringRef::npos)
158
167
continue ;
159
168
169
+ // Verify the classification and, if incorrect, remember as a second choice.
170
+ if (I->Classification != Expected.Classification ) {
171
+ if (fallbackI == E && !Expected.MessageStr .empty ())
172
+ fallbackI = I;
173
+ continue ;
174
+ }
175
+
160
176
// Okay, we found a match, hurray!
161
- return I ;
177
+ return { I, true } ;
162
178
}
163
179
164
- return CapturedDiagnostics.end ();
180
+ // No perfect match; we'll return the fallback or `end()` instead.
181
+ return { fallbackI, false };
165
182
}
166
183
167
184
// / If there are any -verify errors (e.g. differences between expectations
@@ -372,20 +389,22 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
372
389
// the next match.
373
390
StringRef MatchStart = InputFile.substr (Match);
374
391
const char *DiagnosticLoc = MatchStart.data ();
392
+ MatchStart = MatchStart.substr (strlen (" expected-" ));
393
+ const char *ClassificationStartLoc = MatchStart.data ();
375
394
376
395
DiagnosticKind ExpectedClassification;
377
- if (MatchStart.startswith (" expected- note" )) {
396
+ if (MatchStart.startswith (" note" )) {
378
397
ExpectedClassification = DiagnosticKind::Note;
379
- MatchStart = MatchStart.substr (strlen (" expected- note" ));
380
- } else if (MatchStart.startswith (" expected- warning" )) {
398
+ MatchStart = MatchStart.substr (strlen (" note" ));
399
+ } else if (MatchStart.startswith (" warning" )) {
381
400
ExpectedClassification = DiagnosticKind::Warning;
382
- MatchStart = MatchStart.substr (strlen (" expected- warning" ));
383
- } else if (MatchStart.startswith (" expected- error" )) {
401
+ MatchStart = MatchStart.substr (strlen (" warning" ));
402
+ } else if (MatchStart.startswith (" error" )) {
384
403
ExpectedClassification = DiagnosticKind::Error;
385
- MatchStart = MatchStart.substr (strlen (" expected- error" ));
386
- } else if (MatchStart.startswith (" expected- remark" )) {
404
+ MatchStart = MatchStart.substr (strlen (" error" ));
405
+ } else if (MatchStart.startswith (" remark" )) {
387
406
ExpectedClassification = DiagnosticKind::Remark;
388
- MatchStart = MatchStart.substr (strlen (" expected- remark" ));
407
+ MatchStart = MatchStart.substr (strlen (" remark" ));
389
408
} else
390
409
continue ;
391
410
@@ -399,7 +418,9 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
399
418
continue ;
400
419
}
401
420
402
- ExpectedDiagnosticInfo Expected (DiagnosticLoc, ExpectedClassification);
421
+ ExpectedDiagnosticInfo Expected (DiagnosticLoc, ClassificationStartLoc,
422
+ /* ClassificationEndLoc=*/ MatchStart.data (),
423
+ ExpectedClassification);
403
424
int LineOffset = 0 ;
404
425
405
426
if (TextStartIdx > 0 && MatchStart[0 ] == ' @' ) {
@@ -675,18 +696,40 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
675
696
auto &expected = ExpectedDiagnostics[i];
676
697
677
698
// Check to see if we had this expected diagnostic.
678
- auto FoundDiagnosticIter =
699
+ auto FoundDiagnosticInfo =
679
700
findDiagnostic (CapturedDiagnostics, expected, BufferName);
701
+ auto FoundDiagnosticIter = std::get<0 >(FoundDiagnosticInfo);
680
702
if (FoundDiagnosticIter == CapturedDiagnostics.end ()) {
681
703
// Diagnostic didn't exist. If this is a 'mayAppear' diagnostic, then
682
704
// we're ok. Otherwise, leave it in the list.
683
705
if (expected.mayAppear )
684
706
ExpectedDiagnostics.erase (ExpectedDiagnostics.begin ()+i);
685
707
continue ;
686
708
}
687
-
709
+
710
+ auto emitFixItsError = [&](const char *location, const Twine &message,
711
+ const char *replStartLoc, const char *replEndLoc,
712
+ const std::string &replStr) {
713
+ llvm::SMFixIt fix (llvm::SMRange (SMLoc::getFromPointer (replStartLoc),
714
+ SMLoc::getFromPointer (replEndLoc)),
715
+ replStr);
716
+ addError (location, message, fix);
717
+ };
718
+
688
719
auto &FoundDiagnostic = *FoundDiagnosticIter;
689
720
721
+ if (!std::get<1 >(FoundDiagnosticInfo)) {
722
+ // Found a diagnostic with the right location and text but the wrong
723
+ // classification. We'll emit an error about the mismatch and
724
+ // thereafter pretend that the diagnostic fully matched.
725
+ auto expectedKind = getDiagKindString (expected.Classification );
726
+ auto actualKind = getDiagKindString (FoundDiagnostic.Classification );
727
+ emitFixItsError (expected.ClassificationStart ,
728
+ llvm::Twine (" expected " ) + expectedKind + " , not " + actualKind,
729
+ expected.ClassificationStart , expected.ClassificationEnd ,
730
+ actualKind);
731
+ }
732
+
690
733
const char *missedFixitLoc = nullptr ;
691
734
// Verify that any expected fix-its are present in the diagnostic.
692
735
for (auto fixit : expected.Fixits ) {
@@ -716,15 +759,6 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
716
759
actualFixitsStr};
717
760
};
718
761
719
- auto emitFixItsError = [&](const char *location, const Twine &message,
720
- const char *replStartLoc, const char *replEndLoc,
721
- const std::string &replStr) {
722
- llvm::SMFixIt fix (llvm::SMRange (SMLoc::getFromPointer (replStartLoc),
723
- SMLoc::getFromPointer (replEndLoc)),
724
- replStr);
725
- addError (location, message, fix);
726
- };
727
-
728
762
// If we have any expected fixits that didn't get matched, then they are
729
763
// wrong. Replace the failed fixit with what actually happened.
730
764
0 commit comments