Index: tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
==================================================================
--- tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -10,11 +10,11 @@
 #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/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include <climits>
 

@@ -164,28 +164,30 @@
       llvm::DeleteContainerPointers(Warnings);
       llvm::DeleteContainerPointers(Notes);
     }
   };
 
-#ifndef NDEBUG
-  typedef llvm::DenseSet<FileID> FilesWithDiagnosticsSet;
-  typedef llvm::SmallPtrSet<const FileEntry *, 4> FilesParsedForDirectivesSet;
-#endif
-
 private:
   DiagnosticsEngine &Diags;
   DiagnosticConsumer *PrimaryClient;
   bool OwnsPrimaryClient;
   OwningPtr<TextDiagnosticBuffer> Buffer;
   const Preprocessor *CurrentPreprocessor;
+  SourceManager *SrcManager;
   unsigned ActiveSourceFiles;
-#ifndef NDEBUG
-  FilesWithDiagnosticsSet FilesWithDiagnostics;
-  FilesParsedForDirectivesSet FilesParsedForDirectives;
-#endif
   ExpectedData ED;
   void CheckDiagnostics();
+  void setSourceManager(SourceManager &SM) {
+    assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
+    SrcManager = &SM;
+  }
+
+#ifndef NDEBUG
+  typedef llvm::DenseSet<FileID> FileIDSet;
+  FileIDSet ParsedFiles;
+  FileIDSet UnparsedFiles;
+#endif
 
 public:
   /// Create a new verifying diagnostic client, which will issue errors to
   /// the currently-attached diagnostic client when a diagnostic does not match 
   /// what is expected (as indicated in the source file).
@@ -195,16 +197,13 @@
   virtual void BeginSourceFile(const LangOptions &LangOpts,
                                const Preprocessor *PP);
 
   virtual void EndSourceFile();
 
-  /// \brief Manually register a file as parsed.
-  inline void appendParsedFile(const FileEntry *File) {
-#ifndef NDEBUG
-    FilesParsedForDirectives.insert(File);
-#endif
-  }
+  /// \brief Update list of processed files, optionally marking the file as
+  /// parsed for directives.
+  void UpdateProcessedFile(SourceManager &SM, FileID FID, bool MarkParsed);
 
   virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
 
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                 const Diagnostic &Info);

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),
-    ActiveSourceFiles(0)
+    SrcManager(0), ActiveSourceFiles(0)
 {
   Diags.takeClient();
 }
 
 VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
@@ -46,42 +46,61 @@
 }
 
 #ifndef NDEBUG
 namespace {
 class VerifyFileTracker : public PPCallbacks {
-  typedef VerifyDiagnosticConsumer::FilesParsedForDirectivesSet ListType;
-  ListType &FilesList;
+  VerifyDiagnosticConsumer &Verify;
   SourceManager &SM;
 
 public:
-  VerifyFileTracker(ListType &FilesList, SourceManager &SM)
-    : FilesList(FilesList), SM(SM) { }
+  VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
+    : Verify(Verify), SM(SM) { }
 
   /// \brief Hook into the preprocessor and update the list of parsed
   /// files when the preprocessor indicates a new file is entered.
   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
                            SrcMgr::CharacteristicKind FileType,
                            FileID PrevFID) {
-    if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Loc)))
-      FilesList.insert(E);
+    Verify.UpdateProcessedFile(SM, SM.getFileID(Loc), /*MarkParsed=*/true);
   }
 };
 } // End anonymous namespace.
 #endif
+
+void VerifyDiagnosticConsumer::UpdateProcessedFile(SourceManager &SM,
+                                                   FileID FID,
+                                                   bool MarkParsed) {
+  // Check SourceManager hasn't changed.
+  setSourceManager(SM);
+
+#ifndef NDEBUG
+  if (FID.isInvalid())
+    return;
+
+  if (MarkParsed) {
+    // Move FileID from unparsed to parsed.
+    ParsedFiles.insert(FID);
+    UnparsedFiles.erase(FID);
+  } else if (!ParsedFiles.count(FID)) {
+    // Add FileID to unparsed if not already parsed.
+    UnparsedFiles.insert(FID);
+  }
+#endif
+}
 
 // DiagnosticConsumer interface.
 
 void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
                                                const Preprocessor *PP) {
   // Attach comment handler on first invocation.
   if (++ActiveSourceFiles == 1) {
     if (PP) {
       CurrentPreprocessor = PP;
+      setSourceManager(PP->getSourceManager());
       const_cast<Preprocessor*>(PP)->addCommentHandler(this);
 #ifndef NDEBUG
-      VerifyFileTracker *V = new VerifyFileTracker(FilesParsedForDirectives,
-                                                   PP->getSourceManager());
+      VerifyFileTracker *V = new VerifyFileTracker(*this, *SrcManager);
       const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
 #endif
     }
   }
 
@@ -104,17 +123,19 @@
   }
 }
 
 void VerifyDiagnosticConsumer::HandleDiagnostic(
       DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
-#ifndef NDEBUG
   if (Info.hasSourceManager()) {
-    FileID FID = Info.getSourceManager().getFileID(Info.getLocation());
-    if (!FID.isInvalid())
-      FilesWithDiagnostics.insert(FID);
-  }
+    SourceManager &SM = Info.getSourceManager();
+    setSourceManager(SM);
+#ifndef NDEBUG
+    SourceLocation Loc = Info.getLocation();
+    if (!Loc.isMacroID())
+      UpdateProcessedFile(SM, SM.getFileID(Loc), /*MarkParsed=*/false);
 #endif
+  }
   // 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);
 }
 
@@ -605,39 +626,79 @@
   // Ensure any diagnostics go to the primary client.
   bool OwnsCurClient = Diags.ownsClient();
   DiagnosticConsumer *CurClient = Diags.takeClient();
   Diags.setClient(PrimaryClient, false);
 
-  // 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();
-
 #ifndef NDEBUG
-    // In a debug build, scan through any files that may have been missed
-    // during parsing and issue a fatal error if directives are contained
-    // within these files.  If a fatal error occurs, this suggests that
-    // this file is being parsed separately from the main file.
-    HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
-    for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(),
-                                         End = FilesWithDiagnostics.end();
-            I != End; ++I) {
-      const FileEntry *E = SM.getFileEntryForID(*I);
-      // Don't check files already parsed or those handled as modules.
-      if (E && (FilesParsedForDirectives.count(E)
-                  || HS.findModuleForHeader(E)))
-        continue;
+  // In a debug build, scan through any files that may have been missed
+  // during parsing and issue a fatal error if directives are contained
+  // within these files.  If a fatal error occurs, this suggests that
+  // this file is being parsed separately from the main file.
+  if (UnparsedFiles.size() > 0) {
+    const FileEntry *FE = 0;
+
+    if (SrcManager) {
+      // Generate a cache of parsed FileEntry instances for alias lookups.
+      llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
+      for (FileIDSet::iterator I = ParsedFiles.begin(),
+                             End = ParsedFiles.end(); I != End; ++I) {
+        if (const FileEntry *E = SrcManager->getFileEntryForID(*I))
+          ParsedFileCache.insert(E);
+      }
+
+      // Iterate through list of unparsed files.
+      for (FileIDSet::iterator I = UnparsedFiles.begin(),
+                             End = UnparsedFiles.end(); I != End; ++I) {
+        FileID FID = *I;
+        FE = SrcManager->getFileEntryForID(FID);
+
+        if (FE) {
+          // Check whether the file has been parsed under another FileID.
+          // This can happen, for example, in pre-compiled headers.
+          if (ParsedFileCache.count(FE))
+            continue;
+
+          // Or it could be a module header file.
+          if (CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) {
+            HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
+            if (HS.findModuleForHeader(FE)) {
+              ParsedFileCache.insert(FE);
+              continue;
+            }
+          }
+        }
+
+        // If there isn't a valid Preprocessor, the file cannot be checked.
+        if (!CurrentPreprocessor)
+          goto fatal_error;
+
+        // Parse file now and skip if no directives found.
+        if (!findDirectives(*CurrentPreprocessor, FID)) {
+          ParsedFileCache.insert(FE);
+          continue;
+        }
 
-      if (findDirectives(*CurrentPreprocessor, *I))
+        // Otherwise, report fatal error if directives found.
         llvm::report_fatal_error(Twine("-verify directives found after rather"
                                        " than during normal parsing of ",
-                                 StringRef(E ? E->getName() : "(unknown)")));
+                                 StringRef(FE ? FE->getName() : "(unknown)")));
+      }
+    } else {
+fatal_error:
+      llvm::report_fatal_error(Twine("presence of -verify directives cannot be "
+                                     "verified during post-processing check of ",
+                               StringRef(FE ? FE->getName() : "(unknown)")));
     }
-#endif
+
+    // UnparsedFiles has been processed now, so clear it.
+    UnparsedFiles.clear();
+  }
+#endif // !NDEBUG
 
+  if (SrcManager) {
     // Check that the expected diagnostics occurred.
-    NumErrors += CheckResults(Diags, SM, *Buffer, ED);
+    NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
   } else {
     NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
                                   Buffer->err_end(), "error") +
                   PrintUnexpected(Diags, 0, Buffer->warn_begin(),
                                   Buffer->warn_end(), "warn") +

