Index: tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
==================================================================
--- tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -74,10 +74,15 @@
 def err_verify_invalid_content : Error<
     "invalid expected %0: %1">;
 def err_verify_inconsistent_diags : Error<
     "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: "
     "%2">;
+def err_verify_invalid_no_diags : Error<
+    "%select{expected|'expected-no-diagnostics'}0 directive cannot follow "
+    "%select{'expected-no-diagnostics' directive|other expected directives}0">;
+def err_verify_no_directives : Error<
+    "no expected directives found: consider use of 'expected-no-diagnostics'">;
 
 def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
 def note_fixit_in_macro : Note<
     "FIX-IT unable to apply suggested code changes in a macro">;
 def note_fixit_failed : Note<

Index: tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
==================================================================
--- tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -31,11 +31,13 @@
 /// USING THE DIAGNOSTIC CHECKER:
 ///
 /// Indicating that a line expects an error or a warning is simple. Put a
 /// comment on the line that has the diagnostic, use:
 ///
-///     expected-{error,warning,note}
+/// \code
+///   expected-{error,warning,note}
+/// \endcode
 ///
 /// to tag if it's an expected error or warning, and place the expected text
 /// between {{ and }} markers. The full text doesn't have to be included, only
 /// enough to ensure that the correct diagnostic was emitted.
 ///
@@ -92,23 +94,35 @@
 ///   void f(); // expected-note 0-1 {{previous declaration is here}}
 /// \endcode
 ///
 /// In this example, the diagnostic may appear only once, if at all.
 ///
-/// Regex matching mode may be selected by appending '-re' to type. Example:
+/// Regex matching mode may be selected by appending '-re' to type, such as:
 ///
+/// \code
 ///   expected-error-re
+/// \endcode
 ///
 /// Examples matching error: "variable has incomplete type 'struct s'"
 ///
+/// \code
 ///   // expected-error {{variable has incomplete type 'struct s'}}
 ///   // expected-error {{variable has incomplete type}}
 ///
 ///   // expected-error-re {{variable has has type 'struct .'}}
 ///   // expected-error-re {{variable has has type 'struct .*'}}
 ///   // expected-error-re {{variable has has type 'struct (.*)'}}
 ///   // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
+/// \endcode
+///
+/// VerifyDiagnosticConsumer expects at least one expected-* directive to
+/// be found inside the source code.  If no diagnostics are expected the
+/// following directive can be used to indicate this:
+///
+/// \code
+///   // expected-no-diagnostics
+/// \endcode
 ///
 class VerifyDiagnosticConsumer: public DiagnosticConsumer,
                                 public CommentHandler {
 public:
   /// Directive - Abstract class representing a parsed verify directive.
@@ -163,10 +177,17 @@
       llvm::DeleteContainerPointers(Errors);
       llvm::DeleteContainerPointers(Warnings);
       llvm::DeleteContainerPointers(Notes);
     }
   };
+
+  enum DirectiveStatus {
+    HasNoDirectives,
+    HasNoDirectivesReported,
+    HasExpectedNoDiagnostics,
+    HasOtherExpectedDirectives
+  };
 
 private:
   DiagnosticsEngine &Diags;
   DiagnosticConsumer *PrimaryClient;
   bool OwnsPrimaryClient;
@@ -173,10 +194,11 @@
   OwningPtr<TextDiagnosticBuffer> Buffer;
   const Preprocessor *CurrentPreprocessor;
   const LangOptions *LangOpts;
   SourceManager *SrcManager;
   unsigned ActiveSourceFiles;
+  DirectiveStatus Status;
   ExpectedData ED;
 
   void CheckDiagnostics();
   void setSourceManager(SourceManager &SM) {
     assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");

Index: tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
==================================================================
--- tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -29,11 +29,11 @@
 
 VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
   : Diags(_Diags),
     PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
     Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0),
-    LangOpts(0), SrcManager(0), ActiveSourceFiles(0)
+    LangOpts(0), SrcManager(0), ActiveSourceFiles(0), Status(HasNoDirectives)
 {
   Diags.takeClient();
   if (Diags.hasSourceManager())
     setSourceManager(Diags.getSourceManager());
 }
@@ -275,11 +275,12 @@
 /// ParseDirective - Go through the comment and see if it indicates expected
 /// diagnostics. If so, then put them in the appropriate directive list.
 ///
 /// Returns true if any valid directives were found.
 static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
-                           SourceLocation Pos, DiagnosticsEngine &Diags) {
+                           SourceLocation Pos, DiagnosticsEngine &Diags,
+                           VerifyDiagnosticConsumer::DirectiveStatus &Status) {
   // A single comment may contain multiple directives.
   bool FoundDirective = false;
   for (ParseHelper PH(S); !PH.Done();) {
     // Search for token: expected
     if (!PH.Search("expected", true))
@@ -297,13 +298,27 @@
       DL = ED ? &ED->Errors : NULL;
     else if (PH.Next("warning"))
       DL = ED ? &ED->Warnings : NULL;
     else if (PH.Next("note"))
       DL = ED ? &ED->Notes : NULL;
-    else
+    else if (PH.Next("no-diagnostics")) {
+      if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
+        Diags.Report(Pos, diag::err_verify_invalid_no_diags)
+          << /*IsExpectedNoDiagnostics=*/true;
+      else
+        Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
+      continue;
+    } else
       continue;
     PH.Advance();
+
+    if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
+      Diags.Report(Pos, diag::err_verify_invalid_no_diags)
+        << /*IsExpectedNoDiagnostics=*/false;
+      continue;
+    }
+    Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives;
 
     // If a directive has been found but we're not interested
     // in storing the directive information, return now.
     if (!DL)
       return true;
@@ -447,11 +462,11 @@
     return false;
 
   // Fold any "\<EOL>" sequences
   size_t loc = C.find('\\');
   if (loc == StringRef::npos) {
-    ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics());
+    ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
     return false;
   }
 
   std::string C2;
   C2.reserve(C.size());
@@ -477,11 +492,11 @@
       C2 += '\\';
     }
   }
 
   if (!C2.empty())
-    ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics());
+    ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
   return false;
 }
 
 #ifndef NDEBUG
 /// \brief Lex the specified source file to determine whether it contains
@@ -502,20 +517,22 @@
   // Return comments as tokens, this is how we find expected diagnostics.
   RawLex.SetCommentRetentionState(true);
 
   Token Tok;
   Tok.setKind(tok::comment);
+  VerifyDiagnosticConsumer::DirectiveStatus Status =
+    VerifyDiagnosticConsumer::HasNoDirectives;
   while (Tok.isNot(tok::eof)) {
     RawLex.Lex(Tok);
     if (!Tok.is(tok::comment)) continue;
 
     std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts);
     if (Comment.empty()) continue;
 
     // Find first directive.
     if (ParseDirective(Comment, 0, SM, Tok.getLocation(),
-                       SM.getDiagnostics()))
+                       SM.getDiagnostics(), Status))
       return true;
   }
   return false;
 }
 #endif // !NDEBUG
@@ -715,10 +732,18 @@
     UnparsedFiles.clear();
   }
 #endif // !NDEBUG
 
   if (SrcManager) {
+    // Produce an error if no expected-* directives could be found in the
+    // source file(s) processed.
+    if (Status == HasNoDirectives) {
+      Diags.Report(diag::err_verify_no_directives).setForceEmit();
+      ++NumErrors;
+      Status = HasNoDirectivesReported;
+    }
+
     // Check that the expected diagnostics occurred.
     NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
   } else {
     NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
                                   Buffer->err_end(), "error") +

Index: tools/clang/test/ARCMT/verify.m
==================================================================
--- tools/clang/test/ARCMT/verify.m
+++ tools/clang/test/ARCMT/verify.m
@@ -6,8 +6,9 @@
 #endif
 
 #error should not be ignored
 // expected-error@-1 {{should not be ignored}}
 
-//      CHECK: error: 'error' diagnostics seen but not expected:
+//      CHECK: error: no expected directives found: consider use of 'expected-no-diagnostics'
+// CHECK-NEXT: error: 'error' diagnostics seen but not expected:
 // CHECK-NEXT:   (frontend): error reading '{{.*}}verify.m.tmp.invalid'
-// CHECK-NEXT: 1 error generated.
+// CHECK-NEXT: 2 errors generated.

Index: tools/clang/test/Frontend/verify.c
==================================================================
--- tools/clang/test/Frontend/verify.c
+++ tools/clang/test/Frontend/verify.c
@@ -109,17 +109,18 @@
 #endif
 
 #if 0
 // RUN: %clang_cc1 -verify %t.invalid 2>&1 | FileCheck -check-prefix=CHECK6 %s
 
-//      CHECK6: error: 'error' diagnostics seen but not expected:
+//      CHECK6: error: no expected directives found: consider use of 'expected-no-diagnostics'
+// CHECK6-NEXT: error: 'error' diagnostics seen but not expected:
 // CHECK6-NEXT:   (frontend): error reading '{{.*}}verify.c.tmp.invalid'
-// CHECK6-NEXT: 1 error generated.
+// CHECK6-NEXT: 2 errors generated.
 
 // RUN: echo -e '//expected-error@2{{1}}\n#error 2' | %clang_cc1 -verify 2>&1 | FileCheck -check-prefix=CHECK7 %s
 
 //      CHECK7: error: 'error' diagnostics expected but not seen:
 // CHECK7-NEXT:   Line 2 (directive at <stdin>:1): 1
 // CHECK7-NEXT: error: 'error' diagnostics seen but not expected:
 // CHECK7-NEXT:   Line 2: 2
 // CHECK7-NEXT: 2 errors generated.
 #endif

Index: tools/clang/test/Frontend/verify2.c
==================================================================
--- tools/clang/test/Frontend/verify2.c
+++ tools/clang/test/Frontend/verify2.c
@@ -1,19 +1,20 @@
 #if 0
 // RUN: %clang_cc1 -verify %s 2>&1 | FileCheck %s
 
 // Please note that all comments are inside "#if 0" blocks so that
 // VerifyDiagnosticConsumer sees no comments while processing this
-// test-case.
+// test-case (and hence no expected-* directives).
 #endif
 
 #include "verify2.h"
 #error source
 
 #if 0
 // expected-error {{should be ignored}}
 
-//      CHECK: error: 'error' diagnostics seen but not expected:
+//      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 10: source
-// CHECK-NEXT: 2 errors generated.
+// CHECK-NEXT: 3 errors generated.
 #endif

ADDED   tools/clang/test/Frontend/verify3.c
Index: tools/clang/test/Frontend/verify3.c
==================================================================
--- tools/clang/test/Frontend/verify3.c
+++ tools/clang/test/Frontend/verify3.c
@@ -0,0 +1,41 @@
+// This test-case runs several sub-tests on -verify to ensure that correct
+// diagnostics are generated in relation to the mis-use and non-use of the
+// 'expected-no-diagnostics' directive.
+
+// RUN: %clang_cc1 -DTEST1 -verify %s 2>&1 | FileCheck -check-prefix=CHECK1 %s
+#ifdef TEST1
+// expected-no-diagnostics
+// expected-note {{}}
+
+//      CHECK1: error: 'error' diagnostics seen but not expected:
+// CHECK1-NEXT:   Line 8: expected directive cannot follow 'expected-no-diagnostics' directive
+// CHECK1-NEXT: 1 error generated.
+#endif
+
+// RUN: %clang_cc1 -DTEST2 -verify %s 2>&1 | FileCheck -check-prefix=CHECK2 %s
+#ifdef TEST2
+#warning X
+// expected-warning@-1 {{X}}
+// expected-no-diagnostics
+
+//      CHECK2: error: 'error' diagnostics seen but not expected:
+// CHECK2-NEXT:   Line 19: 'expected-no-diagnostics' directive cannot follow other expected directives
+// CHECK2-NEXT: 1 error generated.
+#endif
+
+// RUN: %clang_cc1 -DTEST3 -verify %s 2>&1 | FileCheck -check-prefix=CHECK3 %s
+// RUN: %clang_cc1 -verify 2>&1 | FileCheck -check-prefix=CHECK3 %s
+#ifdef TEST3
+// no directives
+
+//      CHECK3: error: no expected directives found: consider use of 'expected-no-diagnostics'
+// CHECK3-NEXT: 1 error generated.
+#endif
+
+// RUN: %clang_cc1 -E -DTEST4 -verify %s 2>&1 | FileCheck -check-prefix=CHECK4 %s
+#ifdef TEST4
+#warning X
+// expected-warning@-1 {{X}}
+
+// CHECK4-NOT: error: no expected directives found: consider use of 'expected-no-diagnostics'
+#endif

Index: tools/clang/docs/InternalsManual.html
==================================================================
--- tools/clang/docs/InternalsManual.html
+++ tools/clang/docs/InternalsManual.html
@@ -500,11 +500,13 @@
 <p>Another implementation of the DiagnosticClient interface is the
 'TextDiagnosticBuffer' class, which is used when Clang is in -verify mode.
 Instead of formatting and printing out the diagnostics, this implementation just
 captures and remembers the diagnostics as they fly by.  Then -verify compares
 the list of produced diagnostics to the list of expected ones.  If they disagree,
-it prints out its own output.
+it prints out its own output.  Full documentation for the -verify mode can be
+found in the Clang API documentation for VerifyDiagnosticConsumer, <a
+href="/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details">here</a>.
 </p>
 
 <p>There are many other possible implementations of this interface, and this is
 why we prefer diagnostics to pass down rich structured information in arguments.
 For example, an HTML output might want declaration names be linkified to where


