@@ -94,7 +94,8 @@ struct ExpectedDiagnosticInfo {
94
94
unsigned LineNo = ~0U ;
95
95
Optional<unsigned > ColumnNo;
96
96
97
- std::vector<ExpectedFixIt> Fixits;
97
+ using AlternativeExpectedFixIts = std::vector<ExpectedFixIt>;
98
+ std::vector<AlternativeExpectedFixIts> Fixits = {};
98
99
99
100
// Loc of {{none}}
100
101
const char *noneMarkerStartLoc = nullptr ;
@@ -284,34 +285,36 @@ verifyUnknown(SourceManager &SM,
284
285
285
286
// / Return true if the given \p ExpectedFixIt is in the fix-its emitted by
286
287
// / diagnostic \p D.
287
- bool DiagnosticVerifier::checkForFixIt (const ExpectedFixIt &Expected,
288
- const CapturedDiagnosticInfo &D ,
289
- unsigned BufferID) const {
288
+ bool DiagnosticVerifier::checkForFixIt (
289
+ const ExpectedDiagnosticInfo::AlternativeExpectedFixIts &ExpectedAlts ,
290
+ const CapturedDiagnosticInfo &D, unsigned BufferID) const {
290
291
for (auto &ActualFixIt : D.FixIts ) {
291
- if (ActualFixIt.getText () != Expected.Text )
292
- continue ;
292
+ for (auto &Expected : ExpectedAlts) {
293
+ if (ActualFixIt.getText () != Expected.Text )
294
+ continue ;
293
295
294
- LineColumnRange ActualRange = ActualFixIt.getLineColumnRange (
295
- SM, BufferID,
296
- // Don't compute line numbers unless we have to.
297
- /* ComputeStartLocLine=*/ Expected.Range .StartLine !=
298
- LineColumnRange::NoValue,
299
- /* ComputeEndLocLine=*/ Expected.Range .EndLine !=
300
- LineColumnRange::NoValue);
296
+ LineColumnRange ActualRange = ActualFixIt.getLineColumnRange (
297
+ SM, BufferID,
298
+ // Don't compute line numbers unless we have to.
299
+ /* ComputeStartLocLine=*/ Expected.Range .StartLine !=
300
+ LineColumnRange::NoValue,
301
+ /* ComputeEndLocLine=*/ Expected.Range .EndLine !=
302
+ LineColumnRange::NoValue);
301
303
302
- if (Expected.Range .StartCol != ActualRange.StartCol ||
303
- Expected.Range .EndCol != ActualRange.EndCol ) {
304
- continue ;
305
- }
306
- if (Expected.Range .StartLine != LineColumnRange::NoValue &&
307
- Expected.Range .StartLine != ActualRange.StartLine ) {
308
- continue ;
309
- }
310
- if (Expected.Range .EndLine != LineColumnRange::NoValue &&
311
- Expected.Range .EndLine != ActualRange.EndLine ) {
312
- continue ;
304
+ if (Expected.Range .StartCol != ActualRange.StartCol ||
305
+ Expected.Range .EndCol != ActualRange.EndCol ) {
306
+ continue ;
307
+ }
308
+ if (Expected.Range .StartLine != LineColumnRange::NoValue &&
309
+ Expected.Range .StartLine != ActualRange.StartLine ) {
310
+ continue ;
311
+ }
312
+ if (Expected.Range .EndLine != LineColumnRange::NoValue &&
313
+ Expected.Range .EndLine != ActualRange.EndLine ) {
314
+ continue ;
315
+ }
316
+ return true ;
313
317
}
314
- return true ;
315
318
}
316
319
317
320
return false ;
@@ -521,7 +524,8 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
521
524
MatchStart = MatchStart.substr (MatchStart.find_first_not_of (" \t " ));
522
525
523
526
size_t TextStartIdx = MatchStart.find (" {{" );
524
- if (TextStartIdx == StringRef::npos) {
527
+ if (TextStartIdx >=
528
+ MatchStart.find (" \n " )) { // Either not found, or found beyond next \n
525
529
addError (MatchStart.data (),
526
530
" expected {{ in expected-warning/note/error line" );
527
531
continue ;
@@ -580,7 +584,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
580
584
581
585
unsigned Count = 1 ;
582
586
if (TextStartIdx > 0 ) {
583
- StringRef CountStr = MatchStart.substr (0 , TextStartIdx).trim ();
587
+ StringRef CountStr = MatchStart.substr (0 , TextStartIdx).trim (" \t " );
584
588
if (CountStr == " *" ) {
585
589
Expected.mayAppear = true ;
586
590
} else {
@@ -630,6 +634,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
630
634
631
635
632
636
// Scan for fix-its: {{10-14=replacement text}}
637
+ bool startNewAlternatives = true ;
633
638
StringRef ExtraChecks = MatchStart.substr (End+2 ).ltrim (" \t " );
634
639
while (ExtraChecks.startswith (" {{" )) {
635
640
// First make sure we have a closing "}}".
@@ -658,7 +663,23 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
658
663
}
659
664
660
665
// Prepare for the next round of checks.
661
- ExtraChecks = ExtraChecks.substr (EndIndex + 2 ).ltrim ();
666
+ ExtraChecks = ExtraChecks.substr (EndIndex + 2 ).ltrim (" \t " );
667
+
668
+ // Handle fix-it alternation.
669
+ // If two fix-its are separated by `||`, we can match either of the two.
670
+ // This is represented by putting them in the same subarray of `Fixits`.
671
+ // If they are not separated by `||`, we must match both of them.
672
+ // This is represented by putting them in separate subarrays of `Fixits`.
673
+ if (startNewAlternatives &&
674
+ (Expected.Fixits .empty () || !Expected.Fixits .back ().empty ()))
675
+ Expected.Fixits .push_back ({});
676
+
677
+ if (ExtraChecks.startswith (" ||" )) {
678
+ startNewAlternatives = false ;
679
+ ExtraChecks = ExtraChecks.substr (2 ).ltrim (" \t " );
680
+ } else {
681
+ startNewAlternatives = true ;
682
+ }
662
683
663
684
// If this check starts with 'educational-notes=', check for one or more
664
685
// educational notes instead of a fix-it.
@@ -747,10 +768,14 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
747
768
FixIt.Text += *current++;
748
769
}
749
770
}
750
-
751
- Expected.Fixits .push_back (FixIt);
771
+
772
+ Expected.Fixits .back (). push_back (FixIt);
752
773
}
753
774
775
+ // If there's a trailing empty alternation, remove it.
776
+ if (!Expected.Fixits .empty () && Expected.Fixits .back ().empty ())
777
+ Expected.Fixits .pop_back ();
778
+
754
779
Expected.ExpectedEnd = ExtraChecks.data ();
755
780
756
781
// Don't include trailing whitespace in the expected-foo{{}} range.
@@ -762,7 +787,6 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
762
787
ExpectedDiagnostics.push_back (Expected);
763
788
}
764
789
765
-
766
790
// Make sure all the expected diagnostics appeared.
767
791
std::reverse (ExpectedDiagnostics.begin (), ExpectedDiagnostics.end ());
768
792
@@ -807,10 +831,12 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
807
831
808
832
const char *missedFixitLoc = nullptr ;
809
833
// Verify that any expected fix-its are present in the diagnostic.
810
- for (auto fixit : expected.Fixits ) {
834
+ for (auto fixitAlternates : expected.Fixits ) {
835
+ assert (!fixitAlternates.empty () && " an empty alternation survived" );
836
+
811
837
// If we found it, we're ok.
812
- if (!checkForFixIt (fixit , FoundDiagnostic, BufferID)) {
813
- missedFixitLoc = fixit .StartLoc ;
838
+ if (!checkForFixIt (fixitAlternates , FoundDiagnostic, BufferID)) {
839
+ missedFixitLoc = fixitAlternates. front () .StartLoc ;
814
840
break ;
815
841
}
816
842
}
@@ -844,8 +870,8 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
844
870
assert (!expected.Fixits .empty () &&
845
871
" some fix-its should be expected here" );
846
872
847
- const char *replStartLoc = expected.Fixits .front ().StartLoc ;
848
- const char *replEndLoc = expected.Fixits .back ().EndLoc ;
873
+ const char *replStartLoc = expected.Fixits .front ().front (). StartLoc ;
874
+ const char *replEndLoc = expected.Fixits .back ().back (). EndLoc ;
849
875
850
876
std::string message = " expected fix-it not seen" ;
851
877
std::string actualFixits;
@@ -886,8 +912,8 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
886
912
replEndLoc = expected.noneMarkerStartLoc ;
887
913
} else {
888
914
message = " unexpected fix-it seen" ;
889
- replStartLoc = expected.Fixits .front ().StartLoc ;
890
- replEndLoc = expected.Fixits .back ().EndLoc ;
915
+ replStartLoc = expected.Fixits .front ().front (). StartLoc ;
916
+ replEndLoc = expected.Fixits .back ().back (). EndLoc ;
891
917
}
892
918
893
919
auto phrase = makeActualFixitsPhrase (FoundDiagnostic.FixIts );
0 commit comments