Index: llvm/include/llvm/Support/FileCheck.h =================================================================== --- llvm/include/llvm/Support/FileCheck.h +++ llvm/include/llvm/Support/FileCheck.h @@ -167,8 +167,9 @@ /// [0, MatchTypeCount). enum MatchType { // TODO: More members will appear with later patches in this series. + MatchFinalButIllegal, //< the final but illegal match for an expected pattern + MatchTypeFirst = MatchFinalButIllegal, MatchNoneButExpected, //< no match for an expected pattern - MatchTypeFirst = MatchNoneButExpected, MatchFuzzy, //< a fuzzy match (because no perfect match) MatchTypeCount, } MatchTy; Index: llvm/lib/Support/FileCheck.cpp =================================================================== --- llvm/lib/Support/FileCheck.cpp +++ llvm/lib/Support/FileCheck.cpp @@ -1047,17 +1047,27 @@ // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT // or CHECK-NOT if (!IsLabelScanMode) { - StringRef SkippedRegion = Buffer.substr(LastPos, FirstMatchPos - LastPos); + size_t MatchPos = FirstMatchPos - LastPos; + StringRef MatchBuffer = Buffer.substr(LastPos); + StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); // If this check is a "CHECK-NEXT", verify that the previous match was on // the previous line (i.e. that there is one newline between them). - if (CheckNext(SM, SkippedRegion)) + if (CheckNext(SM, SkippedRegion)) { + ProcessMatchResult(FileCheckDiag::MatchFinalButIllegal, SM, Loc, + Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, + Diags); return StringRef::npos; + } // If this check is a "CHECK-SAME", verify that the previous match was on // the same line (i.e. that there is no newline between them). - if (CheckSame(SM, SkippedRegion)) + if (CheckSame(SM, SkippedRegion)) { + ProcessMatchResult(FileCheckDiag::MatchFinalButIllegal, SM, Loc, + Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, + Diags); return StringRef::npos; + } // If this match had "not strings", verify that they don't exist in the // skipped region. Index: llvm/test/FileCheck/dump-input-annotations.txt =================================================================== --- llvm/test/FileCheck/dump-input-annotations.txt +++ llvm/test/FileCheck/dump-input-annotations.txt @@ -86,7 +86,7 @@ ; CNT-NOT: {{.}} ;-------------------------------------------------- -; CHECK-NEXT (also: EOF search-range) +; CHECK-NEXT (also: EOF search-range, illegal match) ;-------------------------------------------------- ; Good match and no match. @@ -113,8 +113,25 @@ ; NXT-NEXT: >>>>>> ; NXT-NOT: {{.}} +; Illegal match. + +; RUN: echo 'yonder' >> %t.in +; RUN: echo 'world' >> %t.in + +; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \ +; RUN: | FileCheck -match-full-lines %s -check-prefix=NXT2 + +; NXT2: <<<<<< +; NXT2-NEXT: 1: hello +; NXT2-NEXT: 2: again +; NXT2-NEXT: 3: yonder +; NXT2-NEXT: 4: world +; NXT2-NEXT: next:3 !~~~~ +; NXT2-NEXT: >>>>>> +; NXT2-NOT: {{.}} + ;-------------------------------------------------- -; CHECK-SAME (also: single-char search range) +; CHECK-SAME (also: single-char search range, illegal match) ;-------------------------------------------------- ; Good match and no match. @@ -138,8 +155,22 @@ ; SAM-NEXT: >>>>>> ; SAM-NOT: {{.}} +; Illegal match. + +; RUN: echo 'again' >> %t.in + +; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \ +; RUN: | FileCheck -match-full-lines %s -check-prefixes=SAM2 + +; SAM2: <<<<<< +; SAM2-NEXT: 1: hello world! +; SAM2-NEXT: 2: again +; SAM2-NEXT: same:3 !~~~~ +; SAM2-NEXT: >>>>>> +; SAM2-NOT: {{.}} + ;-------------------------------------------------- -; CHECK-EMPTY (also: search range ends at label) +; CHECK-EMPTY (also: search range ends at label, illegal match) ;-------------------------------------------------- ; Good match and no match. @@ -176,6 +207,29 @@ ; EMP-NEXT: >>>>>> ; EMP-NOT: {{.}} +; Illegal match. + +; RUN: echo 'hello' > %t.in +; RUN: echo 'world' >> %t.in + +; RUN: echo 'CHECK: hello' > %t.chk +; RUN: echo 'CHECK-EMPTY:' >> %t.chk + +; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk 2>&1 \ +; RUN: | FileCheck -match-full-lines %s -check-prefix=EMP2 +; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -v 2>&1 \ +; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP2,EMP2-V +; RUN: not FileCheck -dump-input=always -input-file %t.in %t.chk -vv 2>&1 \ +; RUN: | FileCheck -match-full-lines %s -check-prefixes=EMP2,EMP2-V,EMP2-VV + +; EMP2: <<<<<< +; EMP2-NEXT: 1: hello +; EMP2-NEXT: 2: world +; EMP2-NEXT: 3: +; EMP2-NEXT: empty:2 ! +; EMP2-NEXT: >>>>>> +; EMP2-NOT: {{.}} + ;-------------------------------------------------- ; CHECK-DAG ;-------------------------------------------------- Index: llvm/utils/FileCheck/FileCheck.cpp =================================================================== --- llvm/utils/FileCheck/FileCheck.cpp +++ llvm/utils/FileCheck/FileCheck.cpp @@ -126,6 +126,10 @@ static MatchTypeStyle GetMatchTypeStyle(unsigned MatchTy) { switch (MatchTy) { + case FileCheckDiag::MatchFinalButIllegal: + return MatchTypeStyle('!', raw_ostream::RED, + "the final but illegal match for an expected " + "pattern (e.g., CHECK-NEXT)"); case FileCheckDiag::MatchNoneButExpected: return MatchTypeStyle('X', raw_ostream::RED, "the search range for an unmatched expected " @@ -164,6 +168,9 @@ // Markers on annotation lines. OS << " - "; + WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~"; + OS << " marks bad match\n" + << " - "; WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~"; OS << " marks search range when no match is found\n" << " - ";