Tests?<br><br><div class="gmail_quote">On Mon, Jul 9, 2012 at 7:57 PM, Jordan Rose <span dir="ltr"><<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@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: jrose<br>
Date: Mon Jul  9 21:57:03 2012<br>
New Revision: 159978<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=159978&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=159978&view=rev</a><br>
Log:<br>
Allow line numbers on -verify directives.<br>
<br>
// expected-warning@10 {{some text}}<br>
<br>
The line number may be absolute (as above), or relative to the current<br>
line by prefixing the number with either '+' or '-'.<br>
<br>
Patch by Andy Gibbs!<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td<br>
    cfe/trunk/include/clang/Basic/SourceManager.h<br>
    cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h<br>
    cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=159978&r1=159977&r2=159978&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Mon Jul  9 21:57:03 2012<br>
@@ -63,6 +63,8 @@<br>
     "unable to open file %0 for serializing diagnostics (%1)">,<br>
     InGroup<DiagGroup<"serialized-diagnostics">>;<br>
<br>
+def err_verify_missing_line : Error<<br>
+    "missing or invalid line number following '@' in expected %0">;<br>
 def err_verify_missing_start : Error<<br>
     "cannot find start ('{{') of expected %0">;<br>
 def err_verify_missing_end : Error<<br>
<br>
Modified: cfe/trunk/include/clang/Basic/SourceManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=159978&r1=159977&r2=159978&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)<br>
+++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Jul  9 21:57:03 2012<br>
@@ -36,6 +36,7 @@<br>
 #define LLVM_CLANG_SOURCEMANAGER_H<br>
<br>
 #include "clang/Basic/LLVM.h"<br>
+#include "clang/Basic/FileManager.h"<br>
 #include "clang/Basic/SourceLocation.h"<br>
 #include "llvm/Support/Allocator.h"<br>
 #include "llvm/Support/DataTypes.h"<br>
@@ -897,6 +898,13 @@<br>
     return getFileIDSlow(SLocOffset);<br>
   }<br>
<br>
+  /// \brief Return the filename of the file containing a SourceLocation.<br>
+  StringRef getFilename(SourceLocation SpellingLoc) const {<br>
+    if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))<br>
+      return F->getName();<br>
+    return StringRef();<br>
+  }<br>
+<br>
   /// \brief Return the source location corresponding to the first byte of<br>
   /// the specified file.<br>
   SourceLocation getLocForStartOfFile(FileID FID) const {<br>
<br>
Modified: cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h?rev=159978&r1=159977&r2=159978&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h (original)<br>
+++ cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h Mon Jul  9 21:57:03 2012<br>
@@ -44,6 +44,15 @@<br>
 /// You can place as many diagnostics on one line as you wish. To make the code<br>
 /// more readable, you can use slash-newline to separate out the diagnostics.<br>
 ///<br>
+/// Alternatively, it is possible to specify the line on which the diagnostic<br>
+/// should appear by appending "@<line>" to "expected-<type>", for example:<br>
+///<br>
+///   #warning some text<br>
+///   // expected-warning@10 {{some text}}<br>
+///<br>
+/// The line number may be absolute (as above), or relative to the current<br>
+/// line by prefixing the number with either '+' or '-'.<br>
+///<br>
 /// The simple syntax above allows each specification to match exactly one<br>
 /// error.  You can use the extended syntax to customize this. The extended<br>
 /// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of<br>
@@ -74,13 +83,15 @@<br>
   ///<br>
   class Directive {<br>
   public:<br>
-    static Directive *create(bool RegexKind, const SourceLocation &Location,<br>
+    static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,<br>
+                             SourceLocation DiagnosticLoc,<br>
                              StringRef Text, unsigned Count);<br>
   public:<br>
     /// Constant representing one or more matches aka regex "+".<br>
     static const unsigned OneOrMoreCount = UINT_MAX;<br>
<br>
-    SourceLocation Location;<br>
+    SourceLocation DirectiveLoc;<br>
+    SourceLocation DiagnosticLoc;<br>
     const std::string Text;<br>
     unsigned Count;<br>
<br>
@@ -94,9 +105,10 @@<br>
     virtual bool match(StringRef S) = 0;<br>
<br>
   protected:<br>
-    Directive(const SourceLocation &Location, StringRef Text,<br>
-              unsigned Count)<br>
-      : Location(Location), Text(Text), Count(Count) { }<br>
+    Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+              StringRef Text, unsigned Count)<br>
+      : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),<br>
+        Text(Text), Count(Count) { }<br>
<br>
   private:<br>
     Directive(const Directive&); // DO NOT IMPLEMENT<br>
<br>
Modified: cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=159978&r1=159977&r2=159978&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp Mon Jul  9 21:57:03 2012<br>
@@ -83,9 +83,9 @@<br>
 ///<br>
 class StandardDirective : public Directive {<br>
 public:<br>
-  StandardDirective(const SourceLocation &Location, StringRef Text,<br>
-                    unsigned Count)<br>
-    : Directive(Location, Text, Count) { }<br>
+  StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+                    StringRef Text, unsigned Count)<br>
+    : Directive(DirectiveLoc, DiagnosticLoc, Text, Count) { }<br>
<br>
   virtual bool isValid(std::string &Error) {<br>
     // all strings are considered valid; even empty ones<br>
@@ -101,9 +101,9 @@<br>
 ///<br>
 class RegexDirective : public Directive {<br>
 public:<br>
-  RegexDirective(const SourceLocation &Location, StringRef Text,<br>
-                 unsigned Count)<br>
-    : Directive(Location, Text, Count), Regex(Text) { }<br>
+  RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+                 StringRef Text, unsigned Count)<br>
+    : Directive(DirectiveLoc, DiagnosticLoc, Text, Count), Regex(Text) { }<br>
<br>
   virtual bool isValid(std::string &Error) {<br>
     if (Regex.isValid(Error))<br>
@@ -195,17 +195,17 @@<br>
                            SourceLocation Pos, DiagnosticsEngine &Diags) {<br>
   // A single comment may contain multiple directives.<br>
   for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {<br>
-    // search for token: expected<br>
+    // Search for token: expected<br>
     if (!PH.Search("expected"))<br>
       break;<br>
     PH.Advance();<br>
<br>
-    // next token: -<br>
+    // Next token: -<br>
     if (!PH.Next("-"))<br>
       continue;<br>
     PH.Advance();<br>
<br>
-    // next token: { error | warning | note }<br>
+    // Next token: { error | warning | note }<br>
     DirectiveList* DL = NULL;<br>
     if (PH.Next("error"))<br>
       DL = &ED.Errors;<br>
@@ -217,21 +217,53 @@<br>
       continue;<br>
     PH.Advance();<br>
<br>
-    // default directive kind<br>
+    // Default directive kind.<br>
     bool RegexKind = false;<br>
     const char* KindStr = "string";<br>
<br>
-    // next optional token: -<br>
+    // Next optional token: -<br>
     if (PH.Next("-re")) {<br>
       PH.Advance();<br>
       RegexKind = true;<br>
       KindStr = "regex";<br>
     }<br>
<br>
-    // skip optional whitespace<br>
+    // Next optional token: @<br>
+    SourceLocation ExpectedLoc;<br>
+    if (!PH.Next("@")) {<br>
+      ExpectedLoc = Pos;<br>
+    } else {<br>
+      PH.Advance();<br>
+      unsigned Line = 0;<br>
+      bool FoundPlus = PH.Next("+");<br>
+      if (FoundPlus || PH.Next("-")) {<br>
+        // Relative to current line.<br>
+        PH.Advance();<br>
+        bool Invalid = false;<br>
+        unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);<br>
+        if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {<br>
+          if (FoundPlus) ExpectedLine += Line;<br>
+          else ExpectedLine -= Line;<br>
+          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);<br>
+        }<br>
+      } else {<br>
+        // Absolute line number.<br>
+        if (PH.Next(Line) && Line > 0)<br>
+          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);<br>
+      }<br>
+<br>
+      if (ExpectedLoc.isInvalid()) {<br>
+        Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
+                     diag::err_verify_missing_line) << KindStr;<br>
+        continue;<br>
+      }<br>
+      PH.Advance();<br>
+    }<br>
+<br>
+    // Skip optional whitespace.<br>
     PH.SkipWhitespace();<br>
<br>
-    // next optional token: positive integer or a '+'.<br>
+    // Next optional token: positive integer or a '+'.<br>
     unsigned Count = 1;<br>
     if (PH.Next(Count))<br>
       PH.Advance();<br>
@@ -240,10 +272,10 @@<br>
       PH.Advance();<br>
     }<br>
<br>
-    // skip optional whitespace<br>
+    // Skip optional whitespace.<br>
     PH.SkipWhitespace();<br>
<br>
-    // next token: {{<br>
+    // Next token: {{<br>
     if (!PH.Next("{{")) {<br>
       Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
                    diag::err_verify_missing_start) << KindStr;<br>
@@ -252,7 +284,7 @@<br>
     PH.Advance();<br>
     const char* const ContentBegin = PH.C; // mark content begin<br>
<br>
-    // search for token: }}<br>
+    // Search for token: }}<br>
     if (!PH.Search("}}")) {<br>
       Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
                    diag::err_verify_missing_end) << KindStr;<br>
@@ -261,7 +293,7 @@<br>
     const char* const ContentEnd = PH.P; // mark content end<br>
     PH.Advance();<br>
<br>
-    // build directive text; convert \n to newlines<br>
+    // Build directive text; convert \n to newlines.<br>
     std::string Text;<br>
     StringRef NewlineStr = "\\n";<br>
     StringRef Content(ContentBegin, ContentEnd-ContentBegin);<br>
@@ -275,8 +307,8 @@<br>
     if (Text.empty())<br>
       Text.assign(ContentBegin, ContentEnd);<br>
<br>
-    // construct new directive<br>
-    Directive *D = Directive::create(RegexKind, Pos, Text, Count);<br>
+    // Construct new directive.<br>
+    Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Count);<br>
     std::string Error;<br>
     if (D->isValid(Error))<br>
       DL->push_back(D);<br>
@@ -318,15 +350,12 @@<br>
   };<br>
 }<br>
<br>
-/// PrintProblem - This takes a diagnostic map of the delta between expected and<br>
-/// seen diagnostics. If there's anything in it, then something unexpected<br>
-/// happened. Print the map out in a nice format and return "true". If the map<br>
-/// is empty and we're not going to print things, then return "false".<br>
-///<br>
-static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
-                             const_diag_iterator diag_begin,<br>
-                             const_diag_iterator diag_end,<br>
-                             const char *Kind, bool Expected) {<br>
+/// \brief Takes a list of diagnostics that have been generated but not matched<br>
+/// by an expected-* directive and produces a diagnostic to the user from this.<br>
+static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
+                                const_diag_iterator diag_begin,<br>
+                                const_diag_iterator diag_end,<br>
+                                const char *Kind) {<br>
   if (diag_begin == diag_end) return 0;<br>
<br>
   SmallString<256> Fmt;<br>
@@ -340,29 +369,31 @@<br>
   }<br>
<br>
   Diags.Report(diag::err_verify_inconsistent_diags)<br>
-    << Kind << !Expected << OS.str();<br>
+    << Kind << /*Unexpected=*/true << OS.str();<br>
   return std::distance(diag_begin, diag_end);<br>
 }<br>
<br>
-static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
-                             DirectiveList &DL, const char *Kind,<br>
-                             bool Expected) {<br>
+/// \brief Takes a list of diagnostics that were expected to have been generated<br>
+/// but were not and produces a diagnostic to the user from this.<br>
+static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr,<br>
+                              DirectiveList &DL, const char *Kind) {<br>
   if (DL.empty())<br>
     return 0;<br>
<br>
   SmallString<256> Fmt;<br>
   llvm::raw_svector_ostream OS(Fmt);<br>
   for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {<br>
-    Directive& D = **I;<br>
-    if (D.Location.isInvalid() || !SourceMgr)<br>
-      OS << "\n  (frontend)";<br>
-    else<br>
-      OS << "\n  Line " << SourceMgr->getPresumedLineNumber(D.Location);<br>
+    Directive &D = **I;<br>
+    OS << "\n  Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);<br>
+    if (D.DirectiveLoc != D.DiagnosticLoc)<br>
+      OS << " (directive at "<br>
+         << SourceMgr.getFilename(D.DirectiveLoc) << ":"<br>
+         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";<br>
     OS << ": " << D.Text;<br>
   }<br>
<br>
   Diags.Report(diag::err_verify_inconsistent_diags)<br>
-    << Kind << !Expected << OS.str();<br>
+    << Kind << /*Unexpected=*/false << OS.str();<br>
   return DL.size();<br>
 }<br>
<br>
@@ -379,7 +410,7 @@<br>
<br>
   for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {<br>
     Directive& D = **I;<br>
-    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);<br>
+    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);<br>
     bool FoundOnce = false;<br>
<br>
     for (unsigned i = 0; i < D.Count; ++i) {<br>
@@ -410,9 +441,8 @@<br>
     }<br>
   }<br>
   // Now all that's left in Right are those that were not matched.<br>
-  unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true);<br>
-  num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),<br>
-                      Label, false);<br>
+  unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);<br>
+  num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);<br>
   return num;<br>
 }<br>
<br>
@@ -472,15 +502,12 @@<br>
     // Check that the expected diagnostics occurred.<br>
     NumErrors += CheckResults(Diags, SM, *Buffer, ED);<br>
   } else {<br>
-    NumErrors += (PrintProblem(Diags, 0,<br>
-                               Buffer->err_begin(), Buffer->err_end(),<br>
-                               "error", false) +<br>
-                  PrintProblem(Diags, 0,<br>
-                               Buffer->warn_begin(), Buffer->warn_end(),<br>
-                               "warn", false) +<br>
-                  PrintProblem(Diags, 0,<br>
-                               Buffer->note_begin(), Buffer->note_end(),<br>
-                               "note", false));<br>
+    NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),<br>
+                                  Buffer->err_end(), "error") +<br>
+                  PrintUnexpected(Diags, 0, Buffer->warn_begin(),<br>
+                                  Buffer->warn_end(), "warn") +<br>
+                  PrintUnexpected(Diags, 0, Buffer->note_begin(),<br>
+                                  Buffer->note_end(), "note"));<br>
   }<br>
<br>
   Diags.takeClient();<br>
@@ -498,9 +525,10 @@<br>
   return new VerifyDiagnosticConsumer(Diags);<br>
 }<br>
<br>
-Directive *Directive::create(bool RegexKind, const SourceLocation &Location,<br>
-                             StringRef Text, unsigned Count) {<br>
+Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,<br>
+                             SourceLocation DiagnosticLoc, StringRef Text,<br>
+                             unsigned Count) {<br>
   if (RegexKind)<br>
-    return new RegexDirective(Location, Text, Count);<br>
-  return new StandardDirective(Location, Text, Count);<br>
+    return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Count);<br>
+  return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Count);<br>
 }<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>