]> granicus.if.org Git - clang/commitdiff
Provide -verify support to match "any" line for diagnostics in included files.
authorAndy Gibbs <andyg1001@hotmail.co.uk>
Thu, 10 Jul 2014 16:43:29 +0000 (16:43 +0000)
committerAndy Gibbs <andyg1001@hotmail.co.uk>
Thu, 10 Jul 2014 16:43:29 +0000 (16:43 +0000)
Allow diagnostic checks that originate in included files to be matched without necessarily determining the line number that the diagnostic occurs on.  The new syntax replaces the line number with '*'.  This extension is limited to diagnostics in included files and may be used where the include file is not part of the test-suite itself.

Expected uses are for diagnostics originating in system headers, or for users who use -verify in testing 3rd-party library code where the location of diagnostics in header files may change from revision to revision and their precise location is not important to the success of the test-case.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212735 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/VerifyDiagnosticConsumer.h
lib/Frontend/VerifyDiagnosticConsumer.cpp
test/Frontend/verify.c
test/Frontend/verify2.c
test/Frontend/verify2.h

index 084eb66d859ead6d27573f368b27e66ee9f8395d..9273fac50910d739c9a4c82180741dda68fbedbe 100644 (file)
@@ -71,7 +71,10 @@ class FileEntry;
 /// \endcode
 ///
 /// The path can be absolute or relative and the same search paths will be used
-/// as for #include directives.
+/// as for #include directives.  The line number in an external file may be
+/// substituted with '*' meaning that any line number will match (useful where
+/// the included file is, for example, a system header where the actual line
+/// number may change and is not critical).
 ///
 /// The simple syntax above allows each specification to match exactly one
 /// error.  You can use the extended syntax to customize this. The extended
@@ -143,7 +146,7 @@ public:
   class Directive {
   public:
     static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,
-                             SourceLocation DiagnosticLoc,
+                             SourceLocation DiagnosticLoc, bool MatchAnyLine,
                              StringRef Text, unsigned Min, unsigned Max);
   public:
     /// Constant representing n or more matches.
@@ -153,6 +156,7 @@ public:
     SourceLocation DiagnosticLoc;
     const std::string Text;
     unsigned Min, Max;
+    bool MatchAnyLine;
 
     virtual ~Directive() { }
 
@@ -165,9 +169,9 @@ public:
 
   protected:
     Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
-              StringRef Text, unsigned Min, unsigned Max)
+              bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
       : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
-        Text(Text), Min(Min), Max(Max) {
+        Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
     assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
     assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
     }
index 856b51db3dcdc2861f6e0deb82cad47be58c076a..b50950e9b300b57eb81e6675493152acf2b51e49 100644 (file)
@@ -164,8 +164,9 @@ namespace {
 class StandardDirective : public Directive {
 public:
   StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
-                    StringRef Text, unsigned Min, unsigned Max)
-    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }
+                    bool MatchAnyLine, StringRef Text, unsigned Min,
+                    unsigned Max)
+    : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { }
 
   bool isValid(std::string &Error) override {
     // all strings are considered valid; even empty ones
@@ -182,8 +183,10 @@ public:
 class RegexDirective : public Directive {
 public:
   RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
-                 StringRef Text, unsigned Min, unsigned Max, StringRef RegexStr)
-    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(RegexStr) { }
+                 bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
+                 StringRef RegexStr)
+    : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
+      Regex(RegexStr) { }
 
   bool isValid(std::string &Error) override {
     if (Regex.isValid(Error))
@@ -371,6 +374,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
 
     // Next optional token: @
     SourceLocation ExpectedLoc;
+    bool MatchAnyLine = false;
     if (!PH.Next("@")) {
       ExpectedLoc = Pos;
     } else {
@@ -411,6 +415,10 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
 
         if (PH.Next(Line) && Line > 0)
           ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
+        else if (PH.Next("*")) {
+          MatchAnyLine = true;
+          ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
+        }
       }
 
       if (ExpectedLoc.isInvalid()) {
@@ -495,7 +503,8 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
 
     // Construct new directive.
     std::unique_ptr<Directive> D(
-        Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max));
+        Directive::create(RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text,
+                          Min, Max));
 
     std::string Error;
     if (D->isValid(Error)) {
@@ -644,8 +653,11 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr
   llvm::raw_svector_ostream OS(Fmt);
   for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
     Directive &D = **I;
-    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc)
-          << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
+    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc);
+    if (D.MatchAnyLine)
+      OS << " Line *";
+    else
+      OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
     if (D.DirectiveLoc != D.DiagnosticLoc)
       OS << " (directive at "
          << SourceMgr.getFilename(D.DirectiveLoc) << ':'
@@ -692,9 +704,11 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
     for (unsigned i = 0; i < D.Max; ++i) {
       DiagList::iterator II, IE;
       for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
-        unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
-        if (LineNo1 != LineNo2)
-          continue;
+        if (!D.MatchAnyLine) {
+          unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
+          if (LineNo1 != LineNo2)
+            continue;
+        }
 
         if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
           continue;
@@ -859,10 +873,11 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
 }
 
 Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
-                             SourceLocation DiagnosticLoc, StringRef Text,
-                             unsigned Min, unsigned Max) {
+                             SourceLocation DiagnosticLoc, bool MatchAnyLine,
+                             StringRef Text, unsigned Min, unsigned Max) {
   if (!RegexKind)
-    return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
+    return new StandardDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine,
+                                 Text, Min, Max);
 
   // Parse the directive into a regular expression.
   std::string RegexStr;
@@ -887,6 +902,6 @@ Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
     }
   }
 
-  return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max,
-                            RegexStr);
+  return new RegexDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text,
+                            Min, Max, RegexStr);
 }
index 4bd0c90b4aea3a3fa3beb081d3b76a2faae5b081..e2e7894f3b9ed41bcce076c953c7897e140fd19c 100644 (file)
@@ -134,9 +134,18 @@ unexpected b; // expected-error@33 1-1 {{unknown type}}
 // expected-warning@verify-directive.h: {{ }}
 // expected-error@-1 {{missing or invalid line number}}
 
+// expected-warning@verify-directive.h:0 {{ }}
+// expected-error@-1 {{missing or invalid line number}}
+
+// expected-warning@verify-directive.h:0*{{ }}
+// expected-error@-1 {{missing or invalid line number}}
+
+// expected-warning@verify-directive.h:*0{{ }}
+// syntactically ok -- means match in any line for 0 occurrences.
+
 // expected-warning@verify-directive.h:1 {{diagnostic}}
 
 //      CHECK8: error: 'warning' diagnostics expected but not seen:
-// CHECK8-NEXT:   File {{.*}}verify-directive.h Line 1 (directive at {{.*}}verify.c:137): diagnostic
+// CHECK8-NEXT:   File {{.*}}verify-directive.h Line 1 (directive at {{.*}}verify.c:146): diagnostic
 // CHECK8-NEXT: 1 error generated.
 #endif
index 73eda4d815de8a1ea5aa9dbbcacc05f23518bb41..075a2ab6e0f01ca3181ae40f11787b92f59c4acc 100644 (file)
 
 //      CHECK: error: no expected directives found: consider use of 'expected-no-diagnostics'
 // CHECK-NEXT: error: 'error' diagnostics seen but not expected:
-// CHECK-NEXT:   Line 1: header
+// CHECK-NEXT:   Line 5: header
 // CHECK-NEXT:   Line 10: source
 // CHECK-NEXT: 3 errors generated.
 #endif
+
+#ifdef CHECK2
+// RUN: not %clang_cc1 -DCHECK2 -verify %s 2>&1 | FileCheck -check-prefix=CHECK2 %s
+
+// The following checks that -verify can match "any line" in an included file.
+// The location of the diagnostic need therefore only match in the file, not to
+// a specific line number.  This is useful where -verify is used as a testing
+// tool for 3rd-party libraries where headers may change and the specific line
+// number of a diagnostic in a header is not important.
+
+// expected-error@verify2.h:* {{header}}
+// expected-error@verify2.h:* {{unknown}}
+
+//      CHECK2: error: 'error' diagnostics expected but not seen:
+// CHECK2-NEXT:   File {{.*}}verify2.h Line * (directive at {{.*}}verify2.c:32): unknown
+// CHECK2-NEXT: error: 'error' diagnostics seen but not expected:
+// CHECK2-NEXT:   File {{.*}}verify2.c Line 10: source
+// CHECK2-NEXT: 2 errors generated.
+#endif
index 8acbf6efdfe2c0812712faa95fefc9015710de98..a426722ee6e7a5856978ff68f30bb3f4643de0b6 100644 (file)
@@ -1,5 +1,5 @@
-#error header
-
 #if 0
 // expected-error {{should be ignored}}
 #endif
+
+#error header