<div dir="ltr"><div>Please add a section to CommandGuide/FileCheck.rst like the other directives.<br><br></div>-- Sean Silva<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 25, 2015 at 8:53 PM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dexonsmith<br>
Date: Wed Feb 25 22:53:00 2015<br>
New Revision: 230612<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=230612&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=230612&view=rev</a><br>
Log:<br>
FileCheck: Add CHECK-SAME<br>
<br>
Add `CHECK-SAME`, which requires that the pattern matches on the *same*<br>
line as the previous `CHECK`/`CHECK-NEXT` -- in other words, no newline<br>
is allowed in the skipped region.  This is similar to `CHECK-NEXT`,<br>
which requires exactly 1 newline in the skipped region.<br>
<br>
My motivation is to simplify checking the long lines of LLVM assembly<br>
for the new debug info hierarchy.  This allows CHECK sequences like the<br>
following:<br>
<br>
    CHECK:      ![[REF]] = !SomeMDNode(<br>
    CHECK-SAME: file: ![[FILE:[0-9]+]]<br>
    CHECK-SAME: otherField: 93{{[,)]}}<br>
<br>
which is equivalent to:<br>
<br>
    CHECK: ![[REF]] = !SomeMDNode({{.*}}file: ![[FILE:[0-9]+]]{{.*}}otherField: 93{{[,)]}}<br>
<br>
While this example just has two fields, many nodes in debug info have<br>
more than that.  `CHECK-SAME` will keep the logic easy to follow.<br>
<br>
Morever, it enables interleaving `CHECK-NOT`s without allowing newlines.<br>
Consider the following:<br>
<br>
    CHECK:      ![[REF]] = !SomeMDNode(<br>
    CHECK-SAME: file: ![[FILE:[0-9]+]]<br>
    CHECK-NOT:  unexpectedField:<br>
    CHECK-SAME: otherField: 93{{[,)]}}<br>
    CHECK-NOT:  otherUnexpectedField:<br>
    CHECK-SAME: )<br>
<br>
which doesn't seem to have an equivalent `CHECK` line.<br>
<br>
Added:<br>
    llvm/trunk/test/FileCheck/same.txt<br>
Modified:<br>
    llvm/trunk/utils/FileCheck/FileCheck.cpp<br>
<br>
Added: llvm/trunk/test/FileCheck/same.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/same.txt?rev=230612&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FileCheck/same.txt?rev=230612&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/FileCheck/same.txt (added)<br>
+++ llvm/trunk/test/FileCheck/same.txt Wed Feb 25 22:53:00 2015<br>
@@ -0,0 +1,23 @@<br>
+foo bat bar<br>
+baz<br>
+<br>
+RUN: FileCheck --input-file=%s --check-prefix=PASS1 %s<br>
+PASS1: foo<br>
+PASS1-SAME: bat<br>
+PASS1-SAME: bar<br>
+PASS1-NEXT: baz<br>
+<br>
+RUN: FileCheck --input-file=%s --check-prefix=PASS2 %s<br>
+PASS2: foo<br>
+PASS2-NOT: baz<br>
+PASS2-SAME: bar<br>
+PASS2-NEXT: baz<br>
+<br>
+RUN: not FileCheck --input-file=%s --check-prefix=FAIL1 %s<br>
+FAIL1: foo<br>
+FAIL1-SAME: baz<br>
+<br>
+RUN: not FileCheck --input-file=%s --check-prefix=FAIL2 %s<br>
+FAIL2: foo<br>
+FAIL2-NOT: bat<br>
+FAIL2-SAME: bar<br>
<br>
Modified: llvm/trunk/utils/FileCheck/FileCheck.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=230612&r1=230611&r2=230612&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=230612&r1=230611&r2=230612&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/utils/FileCheck/FileCheck.cpp (original)<br>
+++ llvm/trunk/utils/FileCheck/FileCheck.cpp Wed Feb 25 22:53:00 2015<br>
@@ -73,6 +73,7 @@ namespace Check {<br>
     CheckNone = 0,<br>
     CheckPlain,<br>
     CheckNext,<br>
+    CheckSame,<br>
     CheckNot,<br>
     CheckDAG,<br>
     CheckLabel,<br>
@@ -620,6 +621,9 @@ struct CheckString {<br>
   /// CheckNext - Verify there is a single line in the given buffer.<br>
   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;<br>
<br>
+  /// CheckSame - Verify there is no newline in the given buffer.<br>
+  bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;<br>
+<br>
   /// CheckNot - Verify there's no "not strings" in the given buffer.<br>
   bool CheckNot(const SourceMgr &SM, StringRef Buffer,<br>
                 const std::vector<const Pattern *> &NotStrings,<br>
@@ -683,6 +687,9 @@ static size_t CheckTypeSize(Check::Check<br>
   case Check::CheckNext:<br>
     return sizeof("-NEXT:") - 1;<br>
<br>
+  case Check::CheckSame:<br>
+    return sizeof("-SAME:") - 1;<br>
+<br>
   case Check::CheckNot:<br>
     return sizeof("-NOT:") - 1;<br>
<br>
@@ -713,6 +720,9 @@ static Check::CheckType FindCheckType(St<br>
   if (Rest.startswith("NEXT:"))<br>
     return Check::CheckNext;<br>
<br>
+  if (Rest.startswith("SAME:"))<br>
+    return Check::CheckSame;<br>
+<br>
   if (Rest.startswith("NOT:"))<br>
     return Check::CheckNot;<br>
<br>
@@ -919,10 +929,12 @@ static bool ReadCheckFile(SourceMgr &SM,<br>
     Buffer = Buffer.substr(EOL);<br>
<br>
     // Verify that CHECK-NEXT lines have at least one CHECK line before them.<br>
-    if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) {<br>
+    if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&<br>
+        CheckStrings.empty()) {<br>
+      StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";<br>
       SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),<br>
                       SourceMgr::DK_Error,<br>
-                      "found '" + UsedPrefix + "-NEXT:' without previous '"<br>
+                      "found '" + UsedPrefix + "-" + Type + "' without previous '"<br>
                       + UsedPrefix + ": line");<br>
       return true;<br>
     }<br>
@@ -1053,6 +1065,11 @@ size_t CheckString::Check(const SourceMg<br>
     if (CheckNext(SM, SkippedRegion))<br>
       return StringRef::npos;<br>
<br>
+    // If this check is a "CHECK-SAME", verify that the previous match was on<br>
+    // the same line (i.e. that there is no newline between them).<br>
+    if (CheckSame(SM, SkippedRegion))<br>
+      return StringRef::npos;<br>
+<br>
     // If this match had "not strings", verify that they don't exist in the<br>
     // skipped region.<br>
     if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))<br>
@@ -1098,6 +1115,34 @@ bool CheckString::CheckNext(const Source<br>
     return true;<br>
   }<br>
<br>
+  return false;<br>
+}<br>
+<br>
+bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {<br>
+  if (CheckTy != Check::CheckSame)<br>
+    return false;<br>
+<br>
+  // Count the number of newlines between the previous match and this one.<br>
+  assert(Buffer.data() !=<br>
+             SM.getMemoryBuffer(SM.FindBufferContainingLoc(<br>
+                                    SMLoc::getFromPointer(Buffer.data())))<br>
+                 ->getBufferStart() &&<br>
+         "CHECK-SAME can't be the first check in a file");<br>
+<br>
+  const char *FirstNewLine = nullptr;<br>
+  unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);<br>
+<br>
+  if (NumNewLines != 0) {<br>
+    SM.PrintMessage(Loc, SourceMgr::DK_Error,<br>
+                    Prefix +<br>
+                        "-SAME: is not on the same line as the previous match");<br>
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,<br>
+                    "'next' match was here");<br>
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,<br>
+                    "previous match ended here");<br>
+    return true;<br>
+  }<br>
+<br>
   return false;<br>
 }<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>