[FileCheck] Annotate input dump (5/7)

This patch implements input annotations for diagnostics enabled by -v,
which report good matches for directives.  These annotations mark
match ranges using `^~~`.

For example:

```
$ FileCheck -dump-input=help
The following description was requested by -dump-input=help to
explain the input annotations printed by -dump-input=always and
-dump-input=fail:

  - L:     labels line number L of the input file
  - T:L    labels the only match result for a pattern of type T from line L of
           the check file
  - T:L'N  labels the Nth match result for a pattern of type T from line L of
           the check file
  - ^~~    marks good match (reported if -v)
  - !~~    marks bad match, such as:
           - CHECK-NEXT on same line as previous match (error)
           - CHECK-NOT found (error)
  - X~~    marks search range when no match is found, such as:
           - CHECK-NEXT not found (error)
  - ?      marks fuzzy match when no match is found
  - colors success, error, fuzzy match, unmatched input

If you are not seeing color above or in input dumps, try: -color

$ FileCheck -v -dump-input=always check3 < input3 |& sed -n '/^<<<</,$p'
<<<<<<
         1: abc foobar def
check:1     ^~~
not:2           !~~~~~     error: no match expected
check:3                ^~~
>>>>>>

$ cat check3
CHECK:     abc
CHECK-NOT: foobar
CHECK:     def

$ cat input3
abc foobar def
```

-vv enables these annotations for FileCheck's implicit EOF patterns as
well.  For an example where EOF patterns become relevant, see patch 7
in this series.

If colors are enabled, `^~~` is green to suggest success.

-v plus color enables highlighting of input text that has no final
match for any expected pattern.  The highlight uses a cyan background
to suggest a cold section.  This highlighting can make it easier to
spot text that was intended to be matched but that failed to be
matched in a long series of good matches.

CHECK-COUNT-<num> good matches are another case where there can be
multiple match results for the same directive.

Reviewed By: george.karpenkov, probinson

Differential Revision: https://reviews.llvm.org/D53897

llvm-svn: 349422
diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp
index a2f5db1..068fa96 100644
--- a/llvm/lib/Support/FileCheck.cpp
+++ b/llvm/lib/Support/FileCheck.cpp
@@ -416,14 +416,19 @@
                                   const SourceMgr &SM, SMLoc Loc,
                                   Check::FileCheckType CheckTy,
                                   StringRef Buffer, size_t Pos, size_t Len,
-                                  std::vector<FileCheckDiag> *Diags) {
+                                  std::vector<FileCheckDiag> *Diags,
+                                  bool AdjustPrevDiag = false) {
   SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
   SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
   SMRange Range(Start, End);
   // TODO: The second condition will disappear when we extend this to handle
   // more match types.
-  if (Diags && MatchTy != FileCheckDiag::MatchTypeCount)
-    Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
+  if (Diags && MatchTy != FileCheckDiag::MatchTypeCount) {
+    if (AdjustPrevDiag)
+      Diags->rbegin()->MatchTy = MatchTy;
+    else
+      Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
+  }
   return Range;
 }
 
@@ -905,7 +910,7 @@
       return;
   }
   SMRange MatchRange = ProcessMatchResult(
-      ExpectedMatch ? FileCheckDiag::MatchTypeCount
+      ExpectedMatch ? FileCheckDiag::MatchFinalAndExpected
                     : FileCheckDiag::MatchFinalButExcluded,
       SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
   std::string Message = formatv("{0}: {1} string found in input",
@@ -1060,7 +1065,7 @@
     if (CheckNext(SM, SkippedRegion)) {
       ProcessMatchResult(FileCheckDiag::MatchFinalButWrongLine, SM, Loc,
                          Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
-                         Diags);
+                         Diags, Req.Verbose);
       return StringRef::npos;
     }
 
@@ -1069,7 +1074,7 @@
     if (CheckSame(SM, SkippedRegion)) {
       ProcessMatchResult(FileCheckDiag::MatchFinalButWrongLine, SM, Loc,
                          Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
-                         Diags);
+                         Diags, Req.Verbose);
       return StringRef::npos;
     }
 
@@ -1278,6 +1283,8 @@
         SM.PrintMessage(OldStart, SourceMgr::DK_Note,
                         "match discarded, overlaps earlier DAG match here",
                         {OldRange});
+        if (Diags)
+          Diags->pop_back();
       }
       MatchPos = MI->End;
     }