[cfe-commits] r159978 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td include/clang/Basic/SourceManager.h include/clang/Frontend/VerifyDiagnosticConsumer.h lib/Frontend/VerifyDiagnosticConsumer.cpp

Jordan Rose jordan_rose at apple.com
Mon Jul 9 19:57:03 PDT 2012


Author: jrose
Date: Mon Jul  9 21:57:03 2012
New Revision: 159978

URL: http://llvm.org/viewvc/llvm-project?rev=159978&view=rev
Log:
Allow line numbers on -verify directives.

// expected-warning at 10 {{some text}}

The line number may be absolute (as above), or relative to the current
line by prefixing the number with either '+' or '-'.

Patch by Andy Gibbs!

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h
    cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp

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

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

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

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





More information about the cfe-commits mailing list