Index: include/clang/Frontend/VerifyDiagnosticConsumer.h
===================================================================
--- include/clang/Frontend/VerifyDiagnosticConsumer.h	(revision 158299)
+++ include/clang/Frontend/VerifyDiagnosticConsumer.h	(working copy)
@@ -11,12 +11,16 @@
 #define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
 
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/OwningPtr.h"
+#include <climits>
+#include <set>
 
 namespace clang {
 
 class DiagnosticsEngine;
 class TextDiagnosticBuffer;
+class FileEntry;
 
 /// VerifyDiagnosticConsumer - Create a diagnostic client which will use
 /// markers in the input source to check that all the emitted diagnostics match
@@ -40,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@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
@@ -48,6 +61,16 @@
 ///
 ///   void f(); // expected-note 2 {{previous declaration is here}}
 ///
+/// Where the diagnostic is expected to occur a minimum number of times, this
+/// can be specified by appending a '+' to the number. Example:
+///
+///   void f(); // expected-note 0+ {{previous declaration is here}}
+///
+/// In this example, the diagnostic becomes optional, i.e. it will be swallowed
+/// if it occurs, but will not generate an error if it does not occur.  A range
+/// can also be specified by <n>-<m>.  As a short-hand, "one or more" can be
+/// specified simply by '+' instead of <n>.
+///
 /// Regex matching mode may be selected by appending '-re' to type. Example:
 ///
 ///   expected-error-re
@@ -62,16 +85,72 @@
 ///   // expected-error-re {{variable has has type 'struct (.*)'}}
 ///   // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
 ///
-class VerifyDiagnosticConsumer: public DiagnosticConsumer {
+class VerifyDiagnosticConsumer: public DiagnosticConsumer, public CommentHandler {
 public:
+  /// Directive - Abstract class representing a parsed verify directive.
+  ///
+  class Directive {
+  public:
+    static Directive* Create(bool RegexKind, const SourceLocation &Location,
+                             const std::string &Text, unsigned Min, unsigned Max);
+  public:
+    /// Constant representing n or more matches.
+    static const unsigned MaxCount = UINT_MAX;
+
+    SourceLocation Location;
+    const std::string Text;
+    unsigned Min, Max;
+
+    virtual ~Directive() { }
+
+    // Returns true if directive text is valid.
+    // Otherwise returns false and populates E.
+    virtual bool isValid(std::string &Error) = 0;
+
+    // Returns true on match.
+    virtual bool Match(const std::string &S) = 0;
+
+  protected:
+    Directive(const SourceLocation &Location, const std::string &Text,
+              unsigned Min, unsigned Max)
+      : Location(Location), Text(Text), Min(Min), Max(Max) { }
+
+  private:
+    Directive(const Directive&); // DO NOT IMPLEMENT
+    void operator=(const Directive&); // DO NOT IMPLEMENT
+  };
+
+  typedef std::vector<Directive*> DirectiveList;
+
+  /// ExpectedData - owns directive objects and deletes on destructor.
+  ///
+  struct ExpectedData {
+    DirectiveList Errors;
+    DirectiveList Warnings;
+    DirectiveList Notes;
+
+    ~ExpectedData() {
+      DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 };
+      for (DirectiveList **PL = Lists; *PL; ++PL) {
+        DirectiveList * const L = *PL;
+        for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I)
+          delete *I;
+      }
+    }
+  };
+
+private:
+  typedef std::set<FileID> UnseenSet;
+  typedef std::set<const FileEntry*> SeenSet;
+
   DiagnosticsEngine &Diags;
   DiagnosticConsumer *PrimaryClient;
   bool OwnsPrimaryClient;
   OwningPtr<TextDiagnosticBuffer> Buffer;
   Preprocessor *CurrentPreprocessor;
-
-private:
-  FileID FirstErrorFID; // FileID of first diagnostic
+  UnseenSet Unseen;
+  SeenSet Seen;
+  ExpectedData ED;
   void CheckDiagnostics();
 
 public:
@@ -86,9 +165,15 @@
 
   virtual void EndSourceFile();
 
+  virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
+
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info);
   
+  virtual CommentHandler *getCommentHandler() {
+    return this;
+  }
+
   virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const;
 };
 
Index: include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- include/clang/Basic/DiagnosticFrontendKinds.td	(revision 158299)
+++ include/clang/Basic/DiagnosticFrontendKinds.td	(working copy)
@@ -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<
Index: include/clang/Basic/Diagnostic.h
===================================================================
--- include/clang/Basic/Diagnostic.h	(revision 158299)
+++ include/clang/Basic/Diagnostic.h	(working copy)
@@ -34,6 +34,7 @@
   class Preprocessor;
   class DiagnosticErrorTrap;
   class StoredDiagnostic;
+  class CommentHandler;
 
 /// \brief Annotates a diagnostic with some code that should be
 /// inserted, removed, or replaced to fix the problem.
@@ -1193,6 +1194,11 @@
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info);
   
+  /// getCommentHandler - Return the CommentHandler for this instance.
+  virtual CommentHandler *getCommentHandler() {
+    return 0;
+  }
+
   /// \brief Clone the diagnostic consumer, producing an equivalent consumer
   /// that can be used in a different context.
   virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
Index: lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- lib/Frontend/VerifyDiagnosticConsumer.cpp	(revision 158299)
+++ lib/Frontend/VerifyDiagnosticConsumer.cpp	(working copy)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/FileManager.h"
 #include "clang/Frontend/VerifyDiagnosticConsumer.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
@@ -18,9 +19,11 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/raw_ostream.h"
-#include <climits>
 
 using namespace clang;
+typedef VerifyDiagnosticConsumer::Directive Directive;
+typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
+typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
 
 VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
   : Diags(_Diags), PrimaryClient(Diags.getClient()),
@@ -45,11 +48,13 @@
   // because it doesn't get reused. It would be better if we could make a copy
   // though.
   CurrentPreprocessor = const_cast<Preprocessor*>(PP);
+  if (CurrentPreprocessor) CurrentPreprocessor->AddCommentHandler(this);
 
   PrimaryClient->BeginSourceFile(LangOpts, PP);
 }
 
 void VerifyDiagnosticConsumer::EndSourceFile() {
+  if (CurrentPreprocessor) CurrentPreprocessor->RemoveCommentHandler(this);
   CheckDiagnostics();
 
   PrimaryClient->EndSourceFile();
@@ -59,9 +64,9 @@
 
 void VerifyDiagnosticConsumer::HandleDiagnostic(
       DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
-  if (FirstErrorFID.isInvalid() && Info.hasSourceManager()) {
+  if (Info.hasSourceManager()) {
     const SourceManager &SM = Info.getSourceManager();
-    FirstErrorFID = SM.getFileID(Info.getLocation());
+    Unseen.insert(SM.getFileID(Info.getLocation()));
   }
   // Send the diagnostic to the buffer, we will check it once we reach the end
   // of the source file (or are destructed).
@@ -77,46 +82,13 @@
 
 namespace {
 
-/// Directive - Abstract class representing a parsed verify directive.
-///
-class Directive {
-public:
-  static Directive* Create(bool RegexKind, const SourceLocation &Location,
-                           const std::string &Text, unsigned Count);
-public:
-  /// Constant representing one or more matches aka regex "+".
-  static const unsigned OneOrMoreCount =  UINT_MAX;
-
-  SourceLocation Location;
-  const std::string Text;
-  unsigned Count;
-
-  virtual ~Directive() { }
-
-  // Returns true if directive text is valid.
-  // Otherwise returns false and populates E.
-  virtual bool isValid(std::string &Error) = 0;
-
-  // Returns true on match.
-  virtual bool Match(const std::string &S) = 0;
-
-protected:
-  Directive(const SourceLocation &Location, const std::string &Text,
-            unsigned Count)
-    : Location(Location), Text(Text), Count(Count) { }
-
-private:
-  Directive(const Directive&); // DO NOT IMPLEMENT
-  void operator=(const Directive&); // DO NOT IMPLEMENT
-};
-
 /// StandardDirective - Directive with string matching.
 ///
 class StandardDirective : public Directive {
 public:
   StandardDirective(const SourceLocation &Location, const std::string &Text,
-                    unsigned Count)
-    : Directive(Location, Text, Count) { }
+                    unsigned Min, unsigned Max)
+    : Directive(Location, Text, Min, Max) { }
 
   virtual bool isValid(std::string &Error) {
     // all strings are considered valid; even empty ones
@@ -133,8 +105,8 @@
 class RegexDirective : public Directive {
 public:
   RegexDirective(const SourceLocation &Location, const std::string &Text,
-                 unsigned Count)
-    : Directive(Location, Text, Count), Regex(Text) { }
+                 unsigned Min, unsigned Max)
+    : Directive(Location, Text, Min, Max), Regex(Text) { }
 
   virtual bool isValid(std::string &Error) {
     if (Regex.isValid(Error))
@@ -150,25 +122,6 @@
   llvm::Regex Regex;
 };
 
-typedef std::vector<Directive*> DirectiveList;
-
-/// ExpectedData - owns directive objects and deletes on destructor.
-///
-struct ExpectedData {
-  DirectiveList Errors;
-  DirectiveList Warnings;
-  DirectiveList Notes;
-
-  ~ExpectedData() {
-    DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 };
-    for (DirectiveList **PL = Lists; *PL; ++PL) {
-      DirectiveList * const L = *PL;
-      for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I)
-        delete *I;
-    }
-  }
-};  
-
 class ParseHelper
 {
 public:
@@ -243,6 +196,8 @@
 static void ParseDirective(const char *CommentStart, unsigned CommentLen,
                            ExpectedData &ED, Preprocessor &PP,
                            SourceLocation Pos) {
+  SourceManager &SM = PP.getSourceManager();
+
   // A single comment may contain multiple directives.
   for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {
     // search for token: expected
@@ -278,15 +233,69 @@
       KindStr = "regex";
     }
 
+    // next optional token: @
+    SourceLocation RealPos = Pos;
+    if (PH.Next("@")) {
+      PH.Advance();
+      unsigned Line = 0;
+      if (PH.Next("-")) { // previous to current line
+        PH.Advance();
+        bool Invalid = false;
+        unsigned CurrentLine = SM.getSpellingLineNumber(Pos, &Invalid);
+        if (Invalid || !PH.Next(Line) || Line >= CurrentLine ||
+              (RealPos = SM.translateLineCol(SM.getFileID(Pos),
+                                             CurrentLine - Line, 1)).isInvalid()) {
+          PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
+                  diag::err_verify_missing_line) << KindStr;
+          continue;
+        }
+      } else if (PH.Next("+")) { // subsequent to current line
+        PH.Advance();
+        bool Invalid = false;
+        unsigned CurrentLine = SM.getSpellingLineNumber(Pos, &Invalid);
+        if (Invalid || !PH.Next(Line) ||
+              (RealPos = SM.translateLineCol(SM.getFileID(Pos),
+                                             CurrentLine + Line, 1)).isInvalid()) {
+          PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
+                  diag::err_verify_missing_line) << KindStr;
+          continue;
+        }
+      } else { // absolute line number
+        if (!PH.Next(Line) || Line < 1 ||
+                (RealPos = SM.translateLineCol(SM.getFileID(Pos),
+                                               Line, 1)).isInvalid()) {
+          PP.Diag(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 '+'.
-    unsigned Count = 1;
-    if (PH.Next(Count))
+    unsigned Min = 1;
+    unsigned Max = 1;
+    if (PH.Next(Min)) {
       PH.Advance();
-    else if (PH.Next("+")) {
-      Count = Directive::OneOrMoreCount;
+      // a positive integer can be followed by a '+'
+      // meaning min or more, or by a '-' meaning a
+      // range from min to max.
+      if (PH.Next("+")) {
+        Max = Directive::MaxCount;
+        PH.Advance();
+      } else if (PH.Next("-")) {
+        PH.Advance();
+        if (PH.Next(Max)) PH.Advance();
+        if (Max < Min) Max = Min;
+      } else {
+        Max = Min;
+      }
+    } else if (PH.Next("+")) {
+      // '+' on its own means "1 or more"
+      Max = Directive::MaxCount;
       PH.Advance();
     }
 
@@ -326,7 +335,7 @@
       Text.assign(ContentBegin, ContentEnd);
 
     // construct new directive
-    Directive *D = Directive::Create(RegexKind, Pos, Text, Count);
+    Directive *D = Directive::Create(RegexKind, RealPos, Text, Min, Max);
     std::string Error;
     if (D->isValid(Error))
       DL->push_back(D);
@@ -338,8 +347,43 @@
   }
 }
 
-/// FindExpectedDiags - Lex the main source file to find all of the
+/// HandleComment - Hook into the preprocessor and extract comments containing
 //   expected errors and warnings.
+bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, SourceRange Comment) {
+  SourceManager &SM = PP.getSourceManager();
+  if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Comment.getBegin())))
+    Seen.insert(E);
+
+  std::string C(SM.getCharacterData(Comment.getBegin()),
+                SM.getCharacterData(Comment.getEnd()));
+
+  // Fold any "\<EOL>" sequences
+  std::string C2;
+  C2.reserve(C.size());
+
+  for (size_t last = 0, loc = C.find('\\');; loc = C.find('\\', last)) {
+    if (loc == std::string::npos) {
+      C2 += C.substr(last);
+      break;
+    }
+    C2 += C.substr(last, loc-last);
+    if (C[loc+1] == '\n')
+      last = loc+2;
+    else if (C[loc+1] == '\r' && C[loc+2] == '\n')
+      last = loc+3;
+    else {
+      C2 += '\\';
+      last = loc+1;
+    }
+  }
+
+  if (!C2.empty())
+    ParseDirective(&C2[0], C2.size(), ED, PP, Comment.getBegin());
+  return false;
+}
+
+/// FindExpectedDiags - Lex the specified source file to find all of the
+//   expected errors and warnings.
 static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {
   // Create a raw lexer to pull all the comments out of FID.
   if (FID.isInvalid())
@@ -429,9 +473,8 @@
   for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
     Directive& D = **I;
     unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);
-    bool FoundOnce = false;
 
-    for (unsigned i = 0; i < D.Count; ++i) {
+    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);
@@ -443,18 +486,12 @@
           break;
       }
       if (II == IE) {
-        if (D.Count == D.OneOrMoreCount) {
-          if (!FoundOnce)
-            LeftOnly.push_back(*I);
-          // We are only interested in at least one match, so exit the loop.
-          break;
-        }
         // Not found.
+        if (i >= D.Min) break;
         LeftOnly.push_back(*I);
       } else {
         // Found. The same cannot be found twice.
         Right.erase(II);
-        FoundOnce = true;
       }
     }
   }
@@ -495,8 +532,6 @@
 }
 
 void VerifyDiagnosticConsumer::CheckDiagnostics() {
-  ExpectedData ED;
-
   // Ensure any diagnostics go to the primary client.
   bool OwnsCurClient = Diags.ownsClient();
   DiagnosticConsumer *CurClient = Diags.takeClient();
@@ -506,18 +541,19 @@
   // markers. If not then any diagnostics are unexpected.
   if (CurrentPreprocessor) {
     SourceManager &SM = CurrentPreprocessor->getSourceManager();
-    // Extract expected-error strings from main file.
-    FindExpectedDiags(*CurrentPreprocessor, ED, SM.getMainFileID());
+
     // Only check for expectations in other diagnostic locations
     // if they are not the main file (via ID or FileEntry) - the main
     // file has already been looked at, and its expectations must not
     // be added twice.
-    if (!FirstErrorFID.isInvalid() && FirstErrorFID != SM.getMainFileID()
-        && (!SM.getFileEntryForID(FirstErrorFID)
-            || (SM.getFileEntryForID(FirstErrorFID) !=
-                SM.getFileEntryForID(SM.getMainFileID())))) {
-      FindExpectedDiags(*CurrentPreprocessor, ED, FirstErrorFID);
-      FirstErrorFID = FileID();
+    const SeenSet::iterator NotSeen = Seen.end();
+    for (UnseenSet::iterator I = Unseen.begin(),
+                           End = Unseen.end(); I != End; ++I) {
+      const FileEntry *E = SM.getFileEntryForID(*I);
+      if (!E || Seen.find(E) == NotSeen) {
+        if (E) Seen.insert(E);
+        FindExpectedDiags(*CurrentPreprocessor, ED, *I);
+      }
     }
 
     // Check that the expected diagnostics occurred.
@@ -550,8 +586,8 @@
 }
 
 Directive* Directive::Create(bool RegexKind, const SourceLocation &Location,
-                             const std::string &Text, unsigned Count) {
+                             const std::string &Text, unsigned Min, unsigned Max) {
   if (RegexKind)
-    return new RegexDirective(Location, Text, Count);
-  return new StandardDirective(Location, Text, Count);
+    return new RegexDirective(Location, Text, Min, Max);
+  return new StandardDirective(Location, Text, Min, Max);
 }
Index: lib/ARCMigrate/ARCMT.cpp
===================================================================
--- lib/ARCMigrate/ARCMT.cpp	(revision 158299)
+++ lib/ARCMigrate/ARCMT.cpp	(working copy)
@@ -89,14 +89,48 @@
 
 namespace {
 
-class CaptureDiagnosticConsumer : public DiagnosticConsumer {
+class CaptureDiagnosticConsumer : public DiagnosticConsumer, public CommentHandler {
+  typedef std::vector<SourceRange> CommentList;
   DiagnosticsEngine &Diags;
   CapturedDiagList &CapturedDiags;
+  CommentList Comments;
+  Preprocessor *PP;
 public:
   CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
                            CapturedDiagList &capturedDiags)
-    : Diags(diags), CapturedDiags(capturedDiags) { }
+    : Diags(diags), CapturedDiags(capturedDiags), PP(0) { }
 
+  void BeginSourceFile(const LangOptions &, const Preprocessor *PP) {
+    // FIXME: Const hack, we screw up the preprocessor but in practice its ok
+    // because it doesn't get reused. It would be better if we could make a copy
+    // though.
+    if (PP) {
+      this->PP = const_cast<Preprocessor*>(PP);
+      this->PP->AddCommentHandler(this);
+    }
+  }
+
+  void EndSourceFile() {
+    if (PP) PP->RemoveCommentHandler(this);
+  }
+
+  bool HandleComment(Preprocessor& PP, SourceRange Comment) {
+    assert(&PP == this->PP && "Preprocessor changed!");
+    Comments.push_back(Comment);
+    return false;
+  }
+
+  void ForwardComments(CommentHandler *Target) {
+    bool ret;
+    if (Target && PP) {
+      for (CommentList::iterator I = Comments.begin(), End = Comments.end();
+            I != End; ++I) {
+        ret = Target->HandleComment(*PP, *I);
+        assert(!ret && "CommentCapture cannot handle CommentHandlers that push tokens");
+      }
+    }
+  }
+
   virtual void HandleDiagnostic(DiagnosticsEngine::Level level,
                                 const Diagnostic &Info) {
     if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
@@ -265,6 +299,7 @@
   if (Diags->hasFatalErrorOccurred()) {
     Diags->Reset();
     DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
+    errRec.ForwardComments(DiagClient->getCommentHandler());
     capturedDiags.reportDiagnostics(*Diags);
     DiagClient->EndSourceFile();
     return true;
@@ -288,6 +323,7 @@
   // diagnostics with source range information are emitted only in between
   // BeginSourceFile() and EndSourceFile().
   DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
+  errRec.ForwardComments(DiagClient->getCommentHandler());
 
   // No macros will be added since we are just checking and we won't modify
   // source code.
@@ -573,6 +609,7 @@
   if (Diags->hasFatalErrorOccurred()) {
     Diags->Reset();
     DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
+    errRec.ForwardComments(DiagClient->getCommentHandler());
     capturedDiags.reportDiagnostics(*Diags);
     DiagClient->EndSourceFile();
     return true;
@@ -584,6 +621,7 @@
   // diagnostics with source range information are emitted only in between
   // BeginSourceFile() and EndSourceFile().
   DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
+  errRec.ForwardComments(DiagClient->getCommentHandler());
 
   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
   TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
Index: test/Preprocessor/warning_tests.c
===================================================================
--- test/Preprocessor/warning_tests.c	(revision 158299)
+++ test/Preprocessor/warning_tests.c	(working copy)
@@ -7,7 +7,8 @@
 #endif
 
 #if __has_warning("-Wparentheses")
-#warning Should have -Wparentheses // expected-warning {{Should have -Wparentheses}}
+#warning Should have -Wparentheses
+// expected-warning@-1 {{Should have -Wparentheses}}
 #endif
 
 #if __has_warning(-Wfoo) // expected-error {{builtin warning check macro requires a parenthesized string}}
@@ -15,5 +16,6 @@
 
 #if __has_warning("-Wnot-a-valid-warning-flag-at-all")
 #else
-#warning Not a valid warning flag // expected-warning {{Not a valid warning flag}}
+#warning Not a valid warning flag
+// expected-warning@-1 {{Not a valid warning flag}}
 #endif
\ No newline at end of file
Index: test/Preprocessor/line-directive.c
===================================================================
--- test/Preprocessor/line-directive.c	(revision 158299)
+++ test/Preprocessor/line-directive.c	(working copy)
@@ -33,10 +33,12 @@
 
 // These are checked by the RUN line.
 #line 92 "blonk.c"
-#error ABC  // expected-error {{#error ABC}}
-#error DEF  // expected-error {{#error DEF}}
+#error ABC
+#error DEF
+// expected-error@-2 {{ABC}}
+#line 150
+// expected-error@-3 {{DEF}}
 
-
 // Verify that linemarker diddling of the system header flag works.
 
 # 192 "glomp.h" // not a system header.
Index: test/Preprocessor/macro_paste_c_block_comment.c
===================================================================
--- test/Preprocessor/macro_paste_c_block_comment.c	(revision 158299)
+++ test/Preprocessor/macro_paste_c_block_comment.c	(working copy)
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -Eonly -verify
 
+// expected-error@+2 {{pasting formed '/*', an invalid preprocessing token}}
 #define COMM / ## *
-COMM // expected-error {{pasting formed '/*', an invalid preprocessing token}}
+COMM
 
Index: test/Preprocessor/if_warning.c
===================================================================
--- test/Preprocessor/if_warning.c	(revision 158299)
+++ test/Preprocessor/if_warning.c	(working copy)
@@ -3,7 +3,8 @@
 
 extern int x;
 
-#if foo   // expected-error {{'foo' is not defined, evaluates to 0}}
+// expected-error@+1 {{'foo' is not defined, evaluates to 0}}
+#if foo
 #endif
 
 #ifdef foo
@@ -22,8 +23,9 @@
 
 // rdar://9475098
 #if 0
-#else 1   // expected-warning {{extra tokens}}
+#else 1
 #endif
+// expected-warning@-2 {{extra tokens}}
 
 // PR6852
 #if 'somesillylongthing'  // expected-warning {{character constant too long for its type}} \
Index: test/PCH/variables.c
===================================================================
--- test/PCH/variables.c	(revision 158299)
+++ test/PCH/variables.c	(working copy)
@@ -11,12 +11,12 @@
 extern float y;
 extern int *ip, x;
 
-float z; // expected-note{{previous}}
+float z;
 
-int z2 = 17; // expected-note{{previous}}
+int z2 = 17;
 
 #define MAKE_HAPPY(X) X##Happy
-int MAKE_HAPPY(Very); // expected-note{{previous definition is here}}
+int MAKE_HAPPY(Very);
 
 #define A_MACRO_IN_THE_PCH 492
 #define FUNCLIKE_MACRO(X, Y) X ## Y
@@ -32,9 +32,9 @@
 
 int *ip2 = &x;
 float *fp = &ip; // expected-warning{{incompatible pointer types}}
-double z; // expected-error{{redefinition}}
-int z2 = 18; // expected-error{{redefinition}}
-double VeryHappy; // expected-error{{redefinition}}
+double z; // expected-error{{redefinition}} expected-note@14{{previous}}
+int z2 = 18; // expected-error{{redefinition}} expected-note@16{{previous}}
+double VeryHappy; // expected-error{{redefinition}} expected-note@19{{previous definition is here}}
 
 int Q = A_MACRO_IN_THE_PCH;
 
Index: test/PCH/attrs.c
===================================================================
--- test/PCH/attrs.c	(revision 158299)
+++ test/PCH/attrs.c	(working copy)
@@ -8,10 +8,11 @@
 #ifndef HEADER
 #define HEADER
 
-int f(int) __attribute__((visibility("default"), overloadable)); // expected-note{{previous overload}}
+int f(int) __attribute__((visibility("default"), overloadable));
 
 #else
 
 double f(double); // expected-error{{overloadable}}
+                  // expected-note@11{{previous overload}}
 
 #endif
Index: test/PCH/cxx-static_assert.cpp
===================================================================
--- test/PCH/cxx-static_assert.cpp	(revision 158299)
+++ test/PCH/cxx-static_assert.cpp	(working copy)
@@ -9,11 +9,12 @@
 #define HEADER
 
 template<int N> struct T {
-    static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}}
+    static_assert(N == 2, "N is not 2!");
 };
 
 #else
 
+// expected-error@12 {{static_assert failed "N is not 2!"}}
 T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
 T<2> t2;
 
Index: test/PCH/cxx11-user-defined-literals.cpp
===================================================================
--- test/PCH/cxx11-user-defined-literals.cpp	(revision 158299)
+++ test/PCH/cxx11-user-defined-literals.cpp	(working copy)
@@ -8,7 +8,7 @@
 using size_t = decltype(sizeof(int));
 int operator"" _foo(const char *p, size_t);
 
-template<typename T> auto f(T t) -> decltype(t + ""_foo) { return 0; } // expected-note {{substitution failure}}
+template<typename T> auto f(T t) -> decltype(t + ""_foo) { return 0; }
 
 #else
 
@@ -17,5 +17,6 @@
 int *l = f(&k);
 struct S {};
 int m = f(S()); // expected-error {{no matching}}
+                // expected-note@11 {{substitution failure}}
 
 #endif
Index: test/PCH/replaced-decl.m
===================================================================
--- test/PCH/replaced-decl.m	(revision 158299)
+++ test/PCH/replaced-decl.m	(working copy)
@@ -12,11 +12,12 @@
 #elif !defined(HEADER2)
 #define HEADER2
 
-@interface I // expected-note {{previous}}
+@interface I
 @end
 
 #else
 
 typedef int I; // expected-error {{redefinition}}
+               // expected-note@15 {{previous}}
 
 #endif
Index: test/PCH/ms-if-exists.cpp
===================================================================
--- test/PCH/ms-if-exists.cpp	(revision 158299)
+++ test/PCH/ms-if-exists.cpp	(working copy)
@@ -11,7 +11,7 @@
   }
 
   __if_not_exists(T::bar) {
-    int *i = t; // expected-error{{no viable conversion from 'HasFoo' to 'int *'}}
+    int *i = t;
     { }
   }
 }
@@ -25,5 +25,6 @@
 };
 
 template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}}
+                         // expected-error@14{{no viable conversion from 'HasFoo' to 'int *'}}
 template void f(HasBar);
 #endif
Index: test/PCH/cxx11-enum-template.cpp
===================================================================
--- test/PCH/cxx11-enum-template.cpp	(revision 158299)
+++ test/PCH/cxx11-enum-template.cpp	(working copy)
@@ -7,7 +7,7 @@
 
 template<typename T> struct S {
   enum class E {
-    e = T() // expected-error {{conversion from 'double' to 'int'}}
+    e = T()
   };
 };
 
@@ -20,7 +20,7 @@
 
 int k1 = (int)S<int>::E::e;
 int k2 = (int)decltype(b)::e;
-int k3 = (int)decltype(c)::e; // expected-note {{here}}
+int k3 = (int)decltype(c)::e; // expected-error@10 {{conversion from 'double' to 'int'}} expected-note {{here}}
 int k4 = (int)S<char>::E::e;
 
 #endif
Index: test/PCH/cxx-trailing-return.cpp
===================================================================
--- test/PCH/cxx-trailing-return.cpp	(revision 158299)
+++ test/PCH/cxx-trailing-return.cpp	(working copy)
@@ -4,12 +4,14 @@
 #ifndef HEADER_INCLUDED
 
 #define HEADER_INCLUDED
-typedef auto f() -> int; // expected-note {{here}}
-typedef int g(); // expected-note {{here}}
+typedef auto f() -> int;
+typedef int g();
 
 #else
 
 typedef void f; // expected-error {{typedef redefinition with different types ('void' vs 'auto () -> int')}}
+                // expected-note@7 {{here}}
 typedef void g; // expected-error {{typedef redefinition with different types ('void' vs 'int ()')}}
+                // expected-note@8 {{here}}
 
 #endif
Index: test/PCH/cxx0x-default-delete.cpp
===================================================================
--- test/PCH/cxx0x-default-delete.cpp	(revision 158299)
+++ test/PCH/cxx0x-default-delete.cpp	(working copy)
@@ -9,15 +9,15 @@
 
 struct foo {
   foo() = default;
-  void bar() = delete; // expected-note{{deleted here}}
+  void bar() = delete;
 };
 
 struct baz {
-  ~baz() = delete; // expected-note{{deleted here}}
+  ~baz() = delete;
 };
 
 class quux {
-  ~quux() = default; // expected-note{{private here}}
+  ~quux() = default;
 };
 
 #else
@@ -25,10 +25,10 @@
 foo::foo() { } // expected-error{{definition of explicitly defaulted default constructor}}
 foo f;
 void fn() {
-  f.bar(); // expected-error{{deleted function}}
+  f.bar(); // expected-error{{deleted function}} expected-note@12{{deleted here}}
 }
 
-baz bz; // expected-error{{deleted function}}
-quux qx; // expected-error{{private destructor}}
+baz bz; // expected-error{{deleted function}} expected-note@16{{deleted here}}
+quux qx; // expected-error{{private destructor}} expected-note@20{{private here}}
 
 #endif
Index: test/PCH/cxx0x-delegating-ctors.cpp
===================================================================
--- test/PCH/cxx0x-delegating-ctors.cpp	(revision 158299)
+++ test/PCH/cxx0x-delegating-ctors.cpp	(working copy)
@@ -8,13 +8,17 @@
 #ifndef PASS1
 #define PASS1
 struct foo {
-  foo(int) : foo() { } // expected-note{{it delegates to}}
+  foo(int) : foo() { }
   foo();
-  foo(bool) : foo('c') { } // expected-note{{it delegates to}}
-  foo(char) : foo(true) { } // expected-error{{creates a delegation cycle}} \
-                            // expected-note{{which delegates to}}
+  foo(bool) : foo('c') { }
+  foo(char) : foo(true) { }
 };
 #else
 foo::foo() : foo(1) { } // expected-error{{creates a delegation cycle}} \
                         // expected-note{{which delegates to}}
+
+// expected-note@11{{it delegates to}}
+// expected-note@13{{it delegates to}}
+// expected-error@14{{creates a delegation cycle}}
+// expected-note@14{{which delegates to}}
 #endif
Index: test/PCH/typo2.cpp
===================================================================
--- test/PCH/typo2.cpp	(revision 158299)
+++ test/PCH/typo2.cpp	(working copy)
@@ -4,10 +4,11 @@
 #ifndef HEADER_INCLUDED
 #define HEADER_INCLUDED
 
-void func(struct Test);  // expected-note{{'Test' declared here}}
+void func(struct Test);
 
 #else
 
 ::Yest *T;  // expected-error{{did you mean 'Test'}}
+            // expected-note@7{{'Test' declared here}}
 
 #endif
Index: test/PCH/cxx11-constexpr.cpp
===================================================================
--- test/PCH/cxx11-constexpr.cpp	(revision 158299)
+++ test/PCH/cxx11-constexpr.cpp	(working copy)
@@ -6,11 +6,11 @@
 #define HEADER_INCLUDED
 
 struct B {
-  B(); // expected-note {{here}}
+  B();
   constexpr B(char) {}
 };
 
-struct C { // expected-note {{not an aggregate and has no constexpr constructors}}
+struct C {
   B b;
   double d = 0.0;
 };
@@ -24,6 +24,8 @@
 
 static_assert(D(4).k == 9, "");
 constexpr int f(C c) { return 0; } // expected-error {{not a literal type}}
+// expected-note@13 {{not an aggregate and has no constexpr constructors}}
 constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}}
+               // expected-note@9 {{here}}
 
 #endif
Index: test/Frontend/verify.c
===================================================================
--- test/Frontend/verify.c	(revision 0)
+++ test/Frontend/verify.c	(working copy)
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify %s
+
+#if 0
+// expected-error {{should be ignored}}
+#endif
+
+#error should not be ignored
+// expected-error@-1 1+ {{should not be ignored}}
+
+#line 90
+// expected-error@+1 + {{unknown type}}
+unexpected a;
+
+#line 30
+unexpected b;
+// expected-error@15 1-1 {{unknown type}}
+
+// expected-warning@ malformed
+// expected-error@18 1 {{missing or invalid line number}}
+
+// expected-warning@0 malformed
+// expected-error@21 {{missing or invalid line number}}
+
+// expected-warning@-50 malformed
+// expected-error@24 {{missing or invalid line number}}
+
+// expected-warning malformed
+// expected-error@27 {{cannot find start}}
+
+// expected-error 0+ {{should also be ignored}}
Index: test/Lexer/bcpl-escaped-newline.c
===================================================================
--- test/Lexer/bcpl-escaped-newline.c	(revision 158299)
+++ test/Lexer/bcpl-escaped-newline.c	(working copy)
@@ -5,7 +5,8 @@
 #error bar
 
 //??/
-#error qux // expected-error {{qux}}
+#error qux
+// expected-error@-1 {{qux}}
 
 // Trailing whitespace!
 //\ 
Index: test/Lexer/conflict-marker.c
===================================================================
--- test/Lexer/conflict-marker.c	(revision 158299)
+++ test/Lexer/conflict-marker.c	(working copy)
@@ -3,8 +3,8 @@
 // Test that we recover gracefully from conflict markers left in input files.
 // PR5238
 
-// diff3 style
-<<<<<<< .mine      // expected-error {{version control conflict marker in file}}
+// diff3 style expected-error@+1 {{version control conflict marker in file}}
+<<<<<<< .mine
 int x = 4;
 |||||||
 int x = 123;
@@ -12,15 +12,15 @@
 float x = 17;
 >>>>>>> .r91107
 
-// normal style.
-<<<<<<< .mine     // expected-error {{version control conflict marker in file}}
+// normal style expected-error@+1 {{version control conflict marker in file}}
+<<<<<<< .mine
 typedef int y;
 =======
 typedef struct foo *y;
 >>>>>>> .r91107
 
-// Perforce style.
->>>> ORIGINAL conflict-marker.c#6 // expected-error {{version control conflict marker in file}}
+// Perforce style expected-error@+1 {{version control conflict marker in file}}
+>>>> ORIGINAL conflict-marker.c#6
 int z = 1;
 ==== THEIRS conflict-marker.c#7
 int z = 0;
Index: test/ARCMT/verify.m
===================================================================
--- test/ARCMT/verify.m	(revision 0)
+++ test/ARCMT/verify.m	(working copy)
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -arcmt-check -verify %s
+
+#if 0
+// expected-error {{should be ignored}}
+#endif
+
+#error should not be ignored
+// expected-error@-1 {{should not be ignored}}
Index: test/SemaCXX/warn-deprecated-header.cpp
===================================================================
--- test/SemaCXX/warn-deprecated-header.cpp	(revision 158299)
+++ test/SemaCXX/warn-deprecated-header.cpp	(working copy)
@@ -2,5 +2,6 @@
 // RUN: %clang_cc1 -fsyntax-only -Werror %s
 
 #ifdef __DEPRECATED
-#warning This file is deprecated. // expected-warning {{This file is deprecated.}}
+#warning This file is deprecated.
+// expected-warning@-1 {{This file is deprecated.}}
 #endif
Index: test/Modules/Inputs/Module.framework/Headers/Module.h
===================================================================
--- test/Modules/Inputs/Module.framework/Headers/Module.h	(revision 158299)
+++ test/Modules/Inputs/Module.framework/Headers/Module.h	(working copy)
@@ -1,4 +1,4 @@
-// expected-warning{{umbrella header}}
+// expected-warning 0-1 {{umbrella header}}
 
 #ifndef MODULE_H
 #define MODULE_H
