Index: tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
==================================================================
--- tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -9,17 +9,20 @@
 
 #ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
 #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
 /// those expected.
 ///
@@ -84,11 +87,12 @@
 ///   // 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:]](.*)'}}
 ///
-class VerifyDiagnosticConsumer: public DiagnosticConsumer {
+class VerifyDiagnosticConsumer: public DiagnosticConsumer,
+                                public CommentHandler {
 public:
   /// Directive - Abstract class representing a parsed verify directive.
   ///
   class Directive {
   public:
@@ -144,17 +148,21 @@
       }
     }
   };
 
 private:
+  typedef std::set<FileID> FilesWithDiagnosticsSet;
+  typedef std::set<const FileEntry*> FilesWithDirectivesSet;
+
   DiagnosticsEngine &Diags;
   DiagnosticConsumer *PrimaryClient;
   bool OwnsPrimaryClient;
   OwningPtr<TextDiagnosticBuffer> Buffer;
   Preprocessor *CurrentPreprocessor;
+  FilesWithDiagnosticsSet FilesWithDiagnostics;
+  FilesWithDirectivesSet FilesWithDirectives;
   ExpectedData ED;
-  FileID FirstErrorFID; // FileID of first diagnostic
   void CheckDiagnostics();
 
 public:
   /// Create a new verifying diagnostic client, which will issue errors to
   /// the currently-attached diagnostic client when a diagnostic does not match 
@@ -164,10 +172,12 @@
 
   virtual void BeginSourceFile(const LangOptions &LangOpts,
                                const Preprocessor *PP);
 
   virtual void EndSourceFile();
+
+  virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
 
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info);
   
   virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const;

Index: tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
==================================================================
--- tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -9,10 +9,11 @@
 //
 // This is a concrete diagnostic client, which buffers the diagnostic messages.
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/FileManager.h"
 #include "clang/Frontend/VerifyDiagnosticConsumer.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallString.h"
@@ -45,27 +46,29 @@
                                                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.
   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();
 
   CurrentPreprocessor = 0;
 }
 
 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());
+    FilesWithDiagnostics.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).
   Buffer->HandleDiagnostic(DiagLevel, Info);
 }
@@ -338,10 +341,46 @@
                    diag::err_verify_invalid_content)
         << KindStr << Error;
     }
   }
 }
+
+/// 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())))
+    FilesWithDirectives.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, SM, Comment.getBegin(),
+                   PP.getDiagnostics());
+  return false;
+}
 
 /// FindExpectedDiags - Lex the main 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.
@@ -513,22 +552,26 @@
 
   // If we have a preprocessor, scan the source for expected diagnostic
   // 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();
+    // Only check for expectations in other diagnostic locations not
+    // captured during normal parsing.
+    // FIXME This check is currently necessary while synthesized files may
+    // not have their expected-* directives captured during parsing.  These
+    // cases should be fixed and the following loop replaced with one which
+    // checks only during a debug build and asserts on a mismatch.
+    const FilesWithDirectivesSet::iterator NotFound
+            = FilesWithDirectives.end();
+    for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(),
+                                         End = FilesWithDiagnostics.end();
+            I != End; ++I) {
+      const FileEntry *E = SM.getFileEntryForID(*I);
+      if (!E || FilesWithDirectives.find(E) == NotFound) {
+        if (E) FilesWithDirectives.insert(E);
+        FindExpectedDiags(*CurrentPreprocessor, ED, *I);
+      }
     }
 
     // Check that the expected diagnostics occurred.
     NumErrors += CheckResults(Diags, SM, *Buffer, ED);
   } else {

