[llvm] r336967 - [FileCheck] Implement -v and -vv for tracing matches

Joel E. Denny via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 12 20:08:23 PDT 2018


Author: jdenny
Date: Thu Jul 12 20:08:23 2018
New Revision: 336967

URL: http://llvm.org/viewvc/llvm-project?rev=336967&view=rev
Log:
[FileCheck] Implement -v and -vv for tracing matches

-v prints all directive pattern matches.

-vv additionally prints info that might be noise to users but that can
be helpful to FileCheck developers.

To maximize code reuse and to make diagnostics more consistent, this
patch also adjusts and extends some of the existing diagnostics.
CHECK-NOT failures now report variables uses.  Many more diagnostics
now report the check prefix and kind of directive.

Reviewed By: probinson

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

Added:
    llvm/trunk/test/FileCheck/verbose.txt
Modified:
    llvm/trunk/docs/CommandGuide/FileCheck.rst
    llvm/trunk/test/FileCheck/check-empty.txt
    llvm/trunk/test/FileCheck/check-label-dag.txt
    llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch-2.txt
    llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch.txt
    llvm/trunk/test/FileCheck/check-not-diaginfo.txt
    llvm/trunk/test/FileCheck/defines.txt
    llvm/trunk/test/FileCheck/implicit-check-not.txt
    llvm/trunk/test/FileCheck/match-full-lines.txt
    llvm/trunk/utils/FileCheck/FileCheck.cpp

Modified: llvm/trunk/docs/CommandGuide/FileCheck.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/FileCheck.rst?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/FileCheck.rst (original)
+++ llvm/trunk/docs/CommandGuide/FileCheck.rst Thu Jul 12 20:08:23 2018
@@ -95,6 +95,16 @@ OPTIONS
 
  Show the version number of this program.
 
+.. option:: -v
+
+  Print directive pattern matches.
+
+.. option:: -vv
+
+  Print information helpful in diagnosing internal FileCheck issues, such as
+  discarded overlapping ``CHECK-DAG:`` matches, implicit EOF pattern matches,
+  and ``CHECK-NOT:`` patterns that do not have matches.  Implies ``-v``.
+
 .. option:: --allow-deprecated-dag-overlap
 
   Enable overlapping among matches in a group of consecutive ``CHECK-DAG:``

Modified: llvm/trunk/test/FileCheck/check-empty.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/check-empty.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/check-empty.txt (original)
+++ llvm/trunk/test/FileCheck/check-empty.txt Thu Jul 12 20:08:23 2018
@@ -9,4 +9,4 @@
 ; EMPTY-ERR: FileCheck error: '-' is empty.
 ; EMPTY-ERR-NEXT: FileCheck command line: {{.*}}FileCheck{{.*}}-check-prefix={{.*}}FOO {{.*}}check-empty.txt
 ; NO-EMPTY-ERR-NOT: FileCheck error: '-' is empty.
-; NOT-FOUND: error: expected string not found in input
+; NOT-FOUND: error: FOO: expected string not found in input

Modified: llvm/trunk/test/FileCheck/check-label-dag.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/check-label-dag.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/check-label-dag.txt (original)
+++ llvm/trunk/test/FileCheck/check-label-dag.txt Thu Jul 12 20:08:23 2018
@@ -7,5 +7,5 @@ CHECK-LABEL: {{^}}bar
 CHECK-DAG: {{^}}foo
 CHECK-LABEL: {{^}}zed
 
-ERROR: error: expected string not found in input
+ERROR: error: CHECK-DAG: expected string not found in input
 ERROR-NEXT: CHECK-DAG: {{.....}}foo

Modified: llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch-2.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch-2.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch-2.txt (original)
+++ llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch-2.txt Thu Jul 12 20:08:23 2018
@@ -8,5 +8,5 @@ bar
 ; FOO: fo{{o}}
 ; BAR: ba{{r}}
 
-; CHECK: {{error: expected string not found in input}}
+; CHECK: {{error: FOO: expected string not found in input}}
 ; CHECK-NEXT: {{F}}OO: fo{{[{][{]o[}][}]}}

Modified: llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch.txt (original)
+++ llvm/trunk/test/FileCheck/check-multiple-prefixes-nomatch.txt Thu Jul 12 20:08:23 2018
@@ -8,5 +8,5 @@ foo
 ; BAR: ba{{z}}
 ; FOO: fo{{o}}
 
-; CHECK: {{error: expected string not found in input}}
+; CHECK: {{error: BAR: expected string not found in input}}
 ; CHECK-NEXT: {{B}}AR: ba{{[{][{]z[}][}]}}

Modified: llvm/trunk/test/FileCheck/check-not-diaginfo.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/check-not-diaginfo.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/check-not-diaginfo.txt (original)
+++ llvm/trunk/test/FileCheck/check-not-diaginfo.txt Thu Jul 12 20:08:23 2018
@@ -2,6 +2,9 @@
 
 CHECK-NOT: test
 
-DIAG:         CHECK-NOT: pattern specified here
+DIAG:         error: CHECK-NOT: excluded string found in input
+DIAG-NEXT:    CHECK-NOT: test
+DIAG-NEXT: {{^           \^}}
+DIAG-NEXT:    note: found here
 DIAG-NEXT:    CHECK-NOT: test
 DIAG-NEXT: {{^           \^}}

Modified: llvm/trunk/test/FileCheck/defines.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/defines.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/defines.txt (original)
+++ llvm/trunk/test/FileCheck/defines.txt Thu Jul 12 20:08:23 2018
@@ -1,9 +1,18 @@
 ; RUN: FileCheck -DVALUE=10 -input-file %s %s
 ; RUN: not FileCheck -DVALUE=20 -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRMSG
+;
+; RUN: not FileCheck -DVALUE=10 -check-prefix NOT -input-file %s %s 2>&1 | FileCheck %s -check-prefix NOT-ERRMSG
+; RUN: FileCheck -DVALUE=20 -check-prefix NOT -input-file %s %s
 
 Value = 10
 ; CHECK: Value = [[VALUE]]
+; NOT-NOT: Value = [[VALUE]]
 
-; ERRMSG: defines.txt:5:10: error: expected string not found in input
+; ERRMSG: defines.txt:8:10: error: CHECK: expected string not found in input
+; ERRMSG: defines.txt:1:1: note: scanning from here
 ; ERRMSG: defines.txt:1:1: note: with variable "VALUE" equal to "20"
-; ERRMSG: defines.txt:4:1: note: possible intended match here
+; ERRMSG: defines.txt:7:1: note: possible intended match here
+
+; NOT-ERRMSG: defines.txt:9:12: error: {{NOT}}-NOT: excluded string found in input
+; NOT-ERRMSG: defines.txt:7:1: note: found here
+; NOT-ERRMSG: defines.txt:7:1: note: with variable "VALUE" equal to "10"
\ No newline at end of file

Modified: llvm/trunk/test/FileCheck/implicit-check-not.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/implicit-check-not.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/implicit-check-not.txt (original)
+++ llvm/trunk/test/FileCheck/implicit-check-not.txt Thu Jul 12 20:08:23 2018
@@ -9,36 +9,36 @@
 
 warning: aaa
 ; CHECK-PASS: warning: aaa
-; CHECK-ERROR1: error: CHECK-FAIL1-NOT: string occurred!
-; CHECK-ERROR1: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
+; CHECK-ERROR1: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
 ; CHECK-ERROR1-NEXT: -implicit-check-not='warning:'
+; CHECK-ERROR1: note: found here
 ; CHECK-FAIL2: warning: aaa
 ; CHECK-FAIL3: warning: aaa
-; CHECK-ERROR4: error: CHECK-FAIL1-NOT: string occurred!
-; CHECK-ERROR4: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
+; CHECK-ERROR4: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
 ; CHECK-ERROR4-NEXT: {{-implicit-check-not='\{\{aaa\|bbb\|ccc\}\}'}}
-; CHECK-ERROR5: error: CHECK-FAIL1-NOT: string occurred!
-; CHECK-ERROR5: command line:1:22: note: CHECK-FAIL1-NOT: pattern specified here
+; CHECK-ERROR4: note: found here
+; CHECK-ERROR5: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
 ; CHECK-ERROR5-NEXT: -implicit-check-not='aaa'
+; CHECK-ERROR5: note: found here
 
 warning: bbb
 ; CHECK-PASS: warning: bbb
 ; CHECK-FAIL1: warning: bbb
-; CHECK-ERROR2: error: CHECK-FAIL2-NOT: string occurred!
-; CHECK-ERROR2: command line:1:22: note: CHECK-FAIL2-NOT: pattern specified here
+; CHECK-ERROR2: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
 ; CHECK-ERROR2-NEXT: -implicit-check-not='warning:'
+; CHECK-ERROR2: note: found here
 ; CHECK-FAIL3: warning: bbb
-; CHECK-ERROR6: error: CHECK-FAIL2-NOT: string occurred!
-; CHECK-ERROR6: command line:1:22: note: CHECK-FAIL2-NOT: pattern specified here
+; CHECK-ERROR6: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
 ; CHECK-ERROR6-NEXT: -implicit-check-not='bbb'
+; CHECK-ERROR6: note: found here
 
 warning: ccc
 ; CHECK-PASS: warning: ccc
 ; CHECK-FAIL1: warning: ccc
 ; CHECK-FAIL2: warning: ccc
-; CHECK-ERROR3: error: CHECK-FAIL3-NOT: string occurred!
-; CHECK-ERROR3: command line:1:22: note: CHECK-FAIL3-NOT: pattern specified here
+; CHECK-ERROR3: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
 ; CHECK-ERROR3-NEXT: -implicit-check-not='warning:'
-; CHECK-ERROR7: error: CHECK-FAIL3-NOT: string occurred!
-; CHECK-ERROR7: command line:1:22: note: CHECK-FAIL3-NOT: pattern specified here
+; CHECK-ERROR3: note: found here
+; CHECK-ERROR7: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
 ; CHECK-ERROR7-NEXT: -implicit-check-not='ccc'
+; CHECK-ERROR7: note: found here

Modified: llvm/trunk/test/FileCheck/match-full-lines.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/match-full-lines.txt?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/test/FileCheck/match-full-lines.txt (original)
+++ llvm/trunk/test/FileCheck/match-full-lines.txt Thu Jul 12 20:08:23 2018
@@ -26,28 +26,28 @@ Label 66
 // CHECK:a line
 // CHECK:trailing whitespace
 // CHECK:trailing more whitespace   
-// ERROR-STRICT:error: expected string not found in input
+// ERROR-STRICT:error: {{C}}HECK: expected string not found in input
 // ERROR-STRICT:// {{C}}HECK:trailing whitespace
 
 // CHECK-LABEL:Label 2
 // CHECK:a line
 // CHECK-NEXT:leading whitespace
 // CHECK-NEXT:   leading more whitespace
-// ERROR-STRICT:error: expected string not found in input
+// ERROR-STRICT:error: {{C}}HECK-NEXT: expected string not found in input
 // ERROR-STRICT:// {{C}}HECK-NEXT:leading whitespace
 
 // CHECK-LABEL:Label 3
 // CHECK:line
-// ERROR:error: expected string not found in input
+// ERROR:error: {{C}}HECK: expected string not found in input
 // ERROR:// {{C}}HECK:line
 
 // CHECK-LABEL:Label 4
 // CHECK:a line
 // CHECK-NOT:random
-// ERROR:error: {{C}}HECK-NOT: string occurred!
+// ERROR:error: {{C}}HECK-NOT: excluded string found in input
 // ERROR:a random thing
 
 // CHECK-LABEL:Label 5
 // CHECK-LABEL:Label 6
-// ERROR:error: expected string not found in input
+// ERROR:error: {{C}}HECK-LABEL: expected string not found in input
 // ERROR:{{C}}HECK-LABEL:Label 6

Added: llvm/trunk/test/FileCheck/verbose.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/verbose.txt?rev=336967&view=auto
==============================================================================
--- llvm/trunk/test/FileCheck/verbose.txt (added)
+++ llvm/trunk/test/FileCheck/verbose.txt Thu Jul 12 20:08:23 2018
@@ -0,0 +1,115 @@
+; RUN: FileCheck -input-file %s %s 2>&1 | FileCheck -check-prefix QUIET --allow-empty %s
+; RUN: FileCheck -v -input-file %s %s 2>&1 | FileCheck -check-prefix V %s
+; RUN: FileCheck -vv -input-file %s %s 2>&1 | FileCheck -check-prefixes V,VV %s
+
+foo
+bar
+CHECK: foo
+CHECK-NOT: raboof
+CHECK-NEXT: bar
+
+V:      verbose.txt:[[@LINE-4]]:8: remark: {{C}}HECK: expected string found in input
+V-NEXT: {{C}}HECK: foo{{$}}
+V-NEXT:  {{^       \^$}}
+V-NEXT: verbose.txt:[[@LINE-9]]:1: note: found here
+V-NEXT: {{^}}foo{{$}}
+V-NEXT: {{^}}^~~{{$}}
+
+V-NEXT: verbose.txt:[[@LINE-9]]:13: remark: {{C}}HECK-NEXT: expected string found in input
+V-NEXT: {{C}}HECK-NEXT: bar{{$}}
+V-NEXT:  {{^            \^$}}
+V-NEXT: verbose.txt:[[@LINE-15]]:1: note: found here
+V-NEXT: {{^}}bar{{$}}
+V-NEXT: {{^}}^~~{{$}}
+
+VV-NEXT: verbose.txt:[[@LINE-17]]:12: remark: {{C}}HECK-NOT: excluded string not found in input
+VV-NEXT: {{C}}HECK-NOT: raboof{{$}}
+VV-NEXT:  {{^           \^$}}
+VV-NEXT: verbose.txt:[[@LINE-22]]:1: note: scanning from here
+VV-NEXT: {{^}}bar{{$}}
+VV-NEXT: {{^}}^{{$}}
+
+before empty
+
+after empty
+CHECK: before empty
+CHECK-EMPTY:
+CHECK-NEXT: after empty
+
+V:      verbose.txt:[[@LINE-4]]:8: remark: {{C}}HECK: expected string found in input
+V-NEXT: {{C}}HECK: before empty{{$}}
+V-NEXT:  {{^       \^$}}
+V-NEXT: verbose.txt:[[@LINE-10]]:1: note: found here
+V-NEXT: {{^}}before empty{{$}}
+V-NEXT: {{^}}^~~~~~~~~~~~{{$}}
+
+V-NEXT:  verbose.txt:[[@LINE-10]]:13: remark: {{C}}HECK-EMPTY: expected string found in input
+V-NEXT:  {{C}}HECK-EMPTY:{{$}}
+V-NEXT:   {{^            \^$}}
+V-NEXT:  verbose.txt:[[@LINE-16]]:1: note: found here
+V-EMPTY:
+V-NEXT:  {{^}}^{{$}}
+
+V-NEXT: verbose.txt:[[@LINE-16]]:13: remark: {{C}}HECK-NEXT: expected string found in input
+V-NEXT: {{C}}HECK-NEXT: after empty{{$}}
+V-NEXT:  {{^            \^$}}
+V-NEXT: verbose.txt:[[@LINE-22]]:1: note: found here
+V-NEXT: {{^}}after empty{{$}}
+V-NEXT: {{^}}^~~~~~~~~~~{{$}}
+
+abcdef
+abcdef
+CHECK-DAG: abcdef
+CHECK-DAG: def
+
+V-NEXT: verbose.txt:[[@LINE-3]]:12: remark: {{C}}HECK-DAG: expected string found in input
+V-NEXT: {{C}}HECK-DAG: abcdef
+V-NEXT:  {{^           \^$}}
+V-NEXT: verbose.txt:[[@LINE-8]]:1: note: found here
+V-NEXT: {{^}}abcdef{{$}}
+V-NEXT: {{^}}^~~~~~{{$}}
+
+VV-NEXT: verbose.txt:[[@LINE-9]]:12: remark: {{C}}HECK-DAG: expected string found in input
+VV-NEXT: {{C}}HECK-DAG: def
+VV-NEXT:  {{^           \^$}}
+VV-NEXT: verbose.txt:[[@LINE-15]]:4: note: found here
+VV-NEXT: {{^abcdef$}}
+VV-NEXT: {{^   \^~~$}}
+VV-NEXT: verbose.txt:[[@LINE-18]]:1: note: match discarded, overlaps earlier DAG match here
+VV-NEXT: {{^}}abcdef{{$}}
+VV-NEXT: {{^}}^~~~~~{{$}}
+
+V-NEXT: verbose.txt:[[@LINE-19]]:12: remark: {{C}}HECK-DAG: expected string found in input
+V-NEXT: {{C}}HECK-DAG: def
+V-NEXT:  {{^           \^$}}
+V-NEXT: verbose.txt:[[@LINE-24]]:4: note: found here
+V-NEXT: {{^abcdef$}}
+V-NEXT: {{^   \^~~$}}
+
+xyz
+CHECK: xyz
+CHECK-NOT: {{z}}yx
+
+V:      verbose.txt:[[@LINE-3]]:8: remark: {{C}}HECK: expected string found in input
+V-NEXT: {{C}}HECK: xyz{{$}}
+V-NEXT:  {{^       \^$}}
+V-NEXT: verbose.txt:[[@LINE-7]]:1: note: found here
+V-NEXT: {{^}}xyz{{$}}
+V-NEXT: {{^}}^~~{{$}}
+
+VV-NEXT: verbose.txt:[[@LINE-9]]:19: remark: implicit EOF: expected string found in input
+VV-NEXT: {{C}}HECK-NOT: {{[{][{]z[}][}]yx$}}
+VV-NEXT:   {{^                 \^$}}
+VV-NEXT: verbose.txt:[[@LINE+13]]:1: note: found here
+VV-NOT:  {{.}}
+VV:      {{^\^$}}
+
+VV-NEXT: verbose.txt:[[@LINE-16]]:12: remark: {{C}}HECK-NOT: excluded string not found in input
+VV-NEXT: {{C}}HECK-NOT: {{[{][{]z[}][}]yx$}}
+VV-NEXT:  {{^           \^$}}
+VV-NEXT: verbose.txt:[[@LINE-20]]:1: note: scanning from here
+VV-NEXT: {{^C}}HECK: xyz{{$}}
+VV-NEXT: {{^\^$}}
+
+QUIET-NOT: {{.}}
+V-NOT: {{.}}

Modified: llvm/trunk/utils/FileCheck/FileCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=336967&r1=336966&r2=336967&view=diff
==============================================================================
--- llvm/trunk/utils/FileCheck/FileCheck.cpp (original)
+++ llvm/trunk/utils/FileCheck/FileCheck.cpp Thu Jul 12 20:08:23 2018
@@ -90,6 +90,14 @@ static cl::opt<bool> AllowDeprecatedDagO
              "provided for convenience as old tests are migrated to the new\n"
              "non-overlapping CHECK-DAG implementation.\n"));
 
+static cl::opt<bool> Verbose("v", cl::init(false),
+                             cl::desc("Print directive pattern matches.\n"));
+
+static cl::opt<bool> VerboseVerbose(
+    "vv", cl::init(false),
+    cl::desc("Print information helpful in diagnosing internal FileCheck\n"
+             "issues.  Implies -v.\n"));
+
 typedef cl::list<std::string>::const_iterator prefix_iterator;
 
 //===----------------------------------------------------------------------===//
@@ -154,8 +162,11 @@ public:
                     unsigned LineNumber);
   size_t Match(StringRef Buffer, size_t &MatchLen,
                StringMap<StringRef> &VariableTable) const;
-  void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
-                        const StringMap<StringRef> &VariableTable) const;
+  void PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
+                         const StringMap<StringRef> &VariableTable,
+                         SMRange MatchRange = None) const;
+  void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
+                       const StringMap<StringRef> &VariableTable) const;
 
   bool hasVariable() const {
     return !(VariableUses.empty() && VariableDefs.empty());
@@ -484,8 +495,12 @@ size_t Pattern::Match(StringRef Buffer,
     VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
   }
 
-  MatchLen = FullMatch.size();
-  return FullMatch.data() - Buffer.data();
+  // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
+  // the required preceding newline, which is consumed by the pattern in the
+  // case of CHECK-EMPTY but not CHECK-NEXT.
+  size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
+  MatchLen = FullMatch.size() - MatchStartSkip;
+  return FullMatch.data() - Buffer.data() + MatchStartSkip;
 }
 
 
@@ -511,11 +526,9 @@ Pattern::ComputeMatchDistance(StringRef
   return BufferPrefix.edit_distance(ExampleString);
 }
 
-/// Prints additional information about a failure to match involving this
-/// pattern.
-void Pattern::PrintFailureInfo(
-    const SourceMgr &SM, StringRef Buffer,
-    const StringMap<StringRef> &VariableTable) const {
+void Pattern::PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
+                                const StringMap<StringRef> &VariableTable,
+                                SMRange MatchRange) const {
   // If this was a regular expression using variables, print the current
   // variable values.
   if (!VariableUses.empty()) {
@@ -547,11 +560,19 @@ void Pattern::PrintFailureInfo(
         }
       }
 
-      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
-                      OS.str());
+      if (MatchRange.isValid())
+        SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
+                        {MatchRange});
+      else
+        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
+                        SourceMgr::DK_Note, OS.str());
     }
   }
+}
 
+void Pattern::PrintFuzzyMatch(
+    const SourceMgr &SM, StringRef Buffer,
+    const StringMap<StringRef> &VariableTable) const {
   // Attempt to find the closest/best fuzzy match.  Usually an error happens
   // because some string in the output didn't exactly match. In these cases, we
   // would like to show the user a best guess at what "should have" matched, to
@@ -741,6 +762,33 @@ static size_t CheckTypeSize(Check::Check
   llvm_unreachable("Bad check type");
 }
 
+// Get a description of the type.
+static std::string CheckTypeName(StringRef Prefix, Check::CheckType Ty) {
+  switch (Ty) {
+  case Check::CheckNone:
+    return "invalid";
+  case Check::CheckPlain:
+    return Prefix;
+  case Check::CheckNext:
+    return Prefix.str() + "-NEXT";
+  case Check::CheckSame:
+    return Prefix.str() + "-SAME";
+  case Check::CheckNot:
+    return Prefix.str() + "-NOT";
+  case Check::CheckDAG:
+    return Prefix.str() + "-DAG";
+  case Check::CheckLabel:
+    return Prefix.str() + "-LABEL";
+  case Check::CheckEmpty:
+    return Prefix.str() + "-EMPTY";
+  case Check::CheckEOF:
+    return "implicit EOF";
+  case Check::CheckBadNot:
+    return "bad NOT";
+  }
+  llvm_unreachable("unknown CheckType");
+}
+
 static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
   if (Buffer.size() <= Prefix.size())
     return Check::CheckNone;
@@ -990,12 +1038,49 @@ static bool ReadCheckFile(SourceMgr &SM,
   return false;
 }
 
-static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
-                             StringRef Buffer,
-                             StringMap<StringRef> &VariableTable) {
+static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
+                       StringRef Prefix, SMLoc Loc, const Pattern &Pat,
+                       StringRef Buffer, StringMap<StringRef> &VariableTable,
+                       size_t MatchPos, size_t MatchLen) {
+  if (ExpectedMatch) {
+    if (!Verbose)
+      return;
+    if (!VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
+      return;
+  }
+  SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + MatchPos);
+  SMLoc MatchEnd = SMLoc::getFromPointer(Buffer.data() + MatchPos + MatchLen);
+  SMRange MatchRange(MatchStart, MatchEnd);
+  SM.PrintMessage(
+      Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error,
+      CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
+          (ExpectedMatch ? "expected" : "excluded") +
+          " string found in input");
+  SM.PrintMessage(MatchStart, SourceMgr::DK_Note, "found here", {MatchRange});
+  Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange);
+}
+
+static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
+                       const CheckString &CheckStr, StringRef Buffer,
+                       StringMap<StringRef> &VariableTable, size_t MatchPos,
+                       size_t MatchLen) {
+  PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
+             Buffer, VariableTable, MatchPos, MatchLen);
+}
+
+static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
+                         StringRef Prefix, SMLoc Loc, const Pattern &Pat,
+                         StringRef Buffer,
+                         StringMap<StringRef> &VariableTable) {
+  if (!ExpectedMatch && !VerboseVerbose)
+    return;
+
   // Otherwise, we have an error, emit an error message.
-  SM.PrintMessage(Loc, SourceMgr::DK_Error,
-                  "expected string not found in input");
+  SM.PrintMessage(Loc,
+                  ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
+                  CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
+                      (ExpectedMatch ? "expected" : "excluded") +
+                      " string not found in input");
 
   // Print the "scanning from here" line.  If the current position is at the
   // end of a line, advance to the start of the next line.
@@ -1005,13 +1090,16 @@ static void PrintCheckFailed(const Sourc
                   "scanning from here");
 
   // Allow the pattern to print additional information if desired.
-  Pat.PrintFailureInfo(SM, Buffer, VariableTable);
+  Pat.PrintVariableUses(SM, Buffer, VariableTable);
+  if (ExpectedMatch)
+    Pat.PrintFuzzyMatch(SM, Buffer, VariableTable);
 }
 
-static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
-                             StringRef Buffer,
-                             StringMap<StringRef> &VariableTable) {
-  PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
+static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
+                         const CheckString &CheckStr, StringRef Buffer,
+                         StringMap<StringRef> &VariableTable) {
+  PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
+               Buffer, VariableTable);
 }
 
 /// Count the number of newlines in the specified range.
@@ -1059,9 +1147,10 @@ size_t CheckString::Check(const SourceMg
   StringRef MatchBuffer = Buffer.substr(LastPos);
   size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
   if (MatchPos == StringRef::npos) {
-    PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
+    PrintNoMatch(true, SM, *this, MatchBuffer, VariableTable);
     return StringRef::npos;
   }
+  PrintMatch(true, SM, *this, MatchBuffer, VariableTable, MatchPos, MatchLen);
 
   // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
   // or CHECK-NOT
@@ -1107,11 +1196,6 @@ bool CheckString::CheckNext(const Source
   const char *FirstNewLine = nullptr;
   unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
 
-  // For CHECK-EMPTY, the preceding new line is consumed by the pattern, so
-  // this needs to be re-added.
-  if (Pat.getCheckTy() == Check::CheckEmpty)
-    ++NumNewLines;
-
   if (NumNewLines == 0) {
     SM.PrintMessage(Loc, SourceMgr::DK_Error,
                     CheckName + ": is on the same line as previous match");
@@ -1177,13 +1261,15 @@ bool CheckString::CheckNot(const SourceM
     size_t MatchLen = 0;
     size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
 
-    if (Pos == StringRef::npos)
+    if (Pos == StringRef::npos) {
+      PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer,
+                   VariableTable);
       continue;
+    }
+
+    PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer, VariableTable,
+               Pos, MatchLen);
 
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
-                    SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
-    SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
-                    Prefix + "-NOT: pattern specified here");
     return true;
   }
 
@@ -1230,11 +1316,15 @@ size_t CheckString::CheckDag(const Sourc
       // With a group of CHECK-DAGs, a single mismatching means the match on
       // that group of CHECK-DAGs fails immediately.
       if (MatchPosBuf == StringRef::npos) {
-        PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
+        PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, MatchBuffer,
+                     VariableTable);
         return StringRef::npos;
       }
       // Re-calc it as the offset relative to the start of the original string.
       MatchPos += MatchPosBuf;
+      if (VerboseVerbose)
+        PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
+                   MatchPos, MatchLen);
       if (AllowDeprecatedDagOverlap)
         break;
       // Iterate previous matches until overlapping match or insertion point.
@@ -1253,8 +1343,19 @@ size_t CheckString::CheckDag(const Sourc
         Matches.insert(MI, M);
         break;
       }
+      if (VerboseVerbose) {
+        SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
+        SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
+        SMRange OldRange(OldStart, OldEnd);
+        SM.PrintMessage(OldStart, SourceMgr::DK_Note,
+                        "match discarded, overlaps earlier DAG match here",
+                        {OldRange});
+      }
       MatchPos = MI->End;
     }
+    if (!VerboseVerbose)
+      PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
+                 MatchPos, MatchLen);
 
     if (!NotStrings.empty()) {
       if (MatchPos < LastPos) {
@@ -1455,6 +1556,9 @@ int main(int argc, char **argv) {
     return 2;
   }
 
+  if (VerboseVerbose)
+    Verbose = true;
+
   SourceMgr SM;
 
   // Read the expected strings from the check file.




More information about the llvm-commits mailing list