Extended VerifyDiagnosticConsumer to also verify source file for diagnostic.

VerifyDiagnosticConsumer previously would not check that the diagnostic and
its matching directive referenced the same source file.  Common practice was
to create directives that referenced other files but only by line number,
and this led to problems such as when the file containing the directive
didn't have enough lines to match the location of the diagnostic in the
other file, leading to bizarre file formatting and other oddities.

This patch causes VerifyDiagnosticConsumer to match source files as well as
line numbers.  Therefore, a new syntax is made available for directives, for
example:

// expected-error@file:line {{diagnostic message}}

This extends the @line feature where "file" is the file where the diagnostic
is generated.  The @line syntax is still available and uses the current file
for the diagnostic.  "file" can be specified either as a relative or absolute
path - although the latter has less usefulness, I think!  The #include search
paths will be used to locate the file and if it is not found an error will be
generated.

The new check is not optional: if the directive is in a different file to the
diagnostic, the file must be specified.  Therefore, a number of test-cases
have been updated with regard to this.

This closes out PR15613.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179677 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 111622e..f05fb9b 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -67,6 +67,8 @@
 
 def err_verify_missing_line : Error<
     "missing or invalid line number following '@' in expected %0">;
+def err_verify_missing_file : Error<
+    "file '%0' could not be located in expected %1">;
 def err_verify_invalid_range : Error<
     "invalid range following '-' in expected %0">;
 def err_verify_missing_start : Error<
diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 06a3b24..9cd73ba 100644
--- a/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -61,6 +61,18 @@
 /// The line number may be absolute (as above), or relative to the current
 /// line by prefixing the number with either '+' or '-'.
 ///
+/// If the diagnostic is generated in a separate file, for example in a shared
+/// header file, it may be beneficial to be able to declare the file in which
+/// the diagnostic will appear, rather than placing the expected-* directive in
+/// the actual file itself.  This can be done using the following syntax:
+///
+/// \code
+///   // expected-error@path/include.h:15 {{error message}}
+/// \endcode
+///
+/// The path can be absolute or relative and the same search paths will be used
+/// as for #include directives.
+///
 /// 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
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 82f6e91..4f05aef 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -278,8 +278,10 @@
 ///
 /// Returns true if any valid directives were found.
 static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
-                           SourceLocation Pos, DiagnosticsEngine &Diags,
+                           Preprocessor *PP, SourceLocation Pos,
                            VerifyDiagnosticConsumer::DirectiveStatus &Status) {
+  DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics();
+
   // A single comment may contain multiple directives.
   bool FoundDirective = false;
   for (ParseHelper PH(S); !PH.Done();) {
@@ -353,10 +355,30 @@
           else ExpectedLine -= Line;
           ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
         }
-      } else {
+      } else if (PH.Next(Line)) {
         // Absolute line number.
-        if (PH.Next(Line) && Line > 0)
+        if (Line > 0)
           ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
+      } else if (PP && PH.Search(":")) {
+        // Specific source file.
+        StringRef Filename(PH.C, PH.P-PH.C);
+        PH.Advance();
+
+        // Lookup file via Preprocessor, like a #include.
+        const DirectoryLookup *CurDir;
+        const FileEntry *FE = PP->LookupFile(Filename, false, NULL, CurDir,
+                                             NULL, NULL, 0);
+        if (!FE) {
+          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+                       diag::err_verify_missing_file) << Filename << KindStr;
+          continue;
+        }
+
+        if (SM.translateFile(FE).isInvalid())
+          SM.createFileID(FE, Pos, SrcMgr::C_User);
+
+        if (PH.Next(Line) && Line > 0)
+          ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
       }
 
       if (ExpectedLoc.isInvalid()) {
@@ -465,7 +487,7 @@
   // Fold any "\<EOL>" sequences
   size_t loc = C.find('\\');
   if (loc == StringRef::npos) {
-    ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
+    ParseDirective(C, &ED, SM, &PP, CommentBegin, Status);
     return false;
   }
 
@@ -495,7 +517,7 @@
   }
 
   if (!C2.empty())
-    ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics(), Status);
+    ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status);
   return false;
 }
 
@@ -530,8 +552,7 @@
     if (Comment.empty()) continue;
 
     // Find first directive.
-    if (ParseDirective(Comment, 0, SM, Tok.getLocation(),
-                       SM.getDiagnostics(), Status))
+    if (ParseDirective(Comment, 0, SM, 0, Tok.getLocation(), Status))
       return true;
   }
   return false;
@@ -551,8 +572,13 @@
   for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
     if (I->first.isInvalid() || !SourceMgr)
       OS << "\n  (frontend)";
-    else
-      OS << "\n  Line " << SourceMgr->getPresumedLineNumber(I->first);
+    else {
+      OS << "\n ";
+      if (const FileEntry *File = SourceMgr->getFileEntryForID(
+                                                SourceMgr->getFileID(I->first)))
+        OS << " File " << File->getName();
+      OS << " Line " << SourceMgr->getPresumedLineNumber(I->first);
+    }
     OS << ": " << I->second;
   }
 
@@ -572,11 +598,12 @@
   llvm::raw_svector_ostream OS(Fmt);
   for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
     Directive &D = **I;
-    OS << "\n  Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
+    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc)
+          << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
     if (D.DirectiveLoc != D.DiagnosticLoc)
       OS << " (directive at "
-         << SourceMgr.getFilename(D.DirectiveLoc) << ":"
-         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";
+         << SourceMgr.getFilename(D.DirectiveLoc) << ':'
+         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
     OS << ": " << D.Text;
   }
 
@@ -585,6 +612,22 @@
   return DL.size();
 }
 
+/// \brief Determine whether two source locations come from the same file.
+static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
+                           SourceLocation DiagnosticLoc) {
+  while (DiagnosticLoc.isMacroID())
+    DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc);
+
+  if (SM.isFromSameFile(DirectiveLoc, DiagnosticLoc))
+    return true;
+
+  const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc));
+  if (!DiagFile && SM.isFromMainFile(DirectiveLoc))
+    return true;
+
+  return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc)));
+}
+
 /// CheckLists - Compare expected to seen diagnostic lists and return the
 /// the difference between them.
 ///
@@ -607,6 +650,9 @@
         if (LineNo1 != LineNo2)
           continue;
 
+        if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
+          continue;
+
         const std::string &RightText = II->second;
         if (D.match(RightText))
           break;
diff --git a/test/ASTMerge/function.c b/test/ASTMerge/function.c
index 320bca2..8a8a030 100644
--- a/test/ASTMerge/function.c
+++ b/test/ASTMerge/function.c
@@ -9,7 +9,7 @@
 // CHECK: function1.c:4:6: note: declared here with type 'void (void)'
 // CHECK: 2 errors generated
 
-// expected-error@3 {{external function 'f1' declared with incompatible types}}
-// expected-note@2 {{declared here}}
-// expected-error@5 {{external function 'f3' declared with incompatible types}}
-// expected-note@4 {{declared here}}
+// expected-error@Inputs/function2.c:3 {{external function 'f1' declared with incompatible types}}
+// expected-note@Inputs/function1.c:2 {{declared here}}
+// expected-error@Inputs/function2.c:5 {{external function 'f3' declared with incompatible types}}
+// expected-note@Inputs/function1.c:4 {{declared here}}
diff --git a/test/Analysis/diagnostics/explicit-suppression.cpp b/test/Analysis/diagnostics/explicit-suppression.cpp
index 79afeed..57d2d16 100644
--- a/test/Analysis/diagnostics/explicit-suppression.cpp
+++ b/test/Analysis/diagnostics/explicit-suppression.cpp
@@ -12,69 +12,6 @@
 void testCopyNull(int *I, int *E) {
   std::copy(I, E, (int *)0);
 #ifndef SUPPRESSED
-  // This line number comes from system-header-simulator-cxx.h.
-  // expected-warning@79 {{Dereference of null pointer}}
+  // expected-warning@../Inputs/system-header-simulator-cxx.h:80 {{Dereference of null pointer}}
 #endif
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// PR15613: expected-* can't refer to diagnostics in other source files.
-// The current implementation only matches line numbers, but has an upper limit
-// of the number of lines in the main source file.
diff --git a/test/Frontend/verify.c b/test/Frontend/verify.c
index 062e6bd..3d71e04 100644
--- a/test/Frontend/verify.c
+++ b/test/Frontend/verify.c
@@ -124,3 +124,19 @@
 // CHECK7-NEXT:   Line 2: 2
 // CHECK7-NEXT: 2 errors generated.
 #endif
+
+#ifdef TEST8
+// RUN: %clang_cc1 -DTEST8 -verify %s 2>&1 | FileCheck -check-prefix=CHECK8 %s
+
+// expected-warning@nonexistant-file:1 {{ }}
+// expected-error@-1 {{file 'nonexistant-file' could not be located}}
+
+// expected-warning@verify-directive.h: {{ }}
+// expected-error@-1 {{missing or invalid line number}}
+
+// 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: 1 error generated.
+#endif
diff --git a/test/Misc/warn-in-system-header.c b/test/Misc/warn-in-system-header.c
index 6e0237d..132f083 100644
--- a/test/Misc/warn-in-system-header.c
+++ b/test/Misc/warn-in-system-header.c
@@ -1,4 +1,4 @@
 // RUN: %clang_cc1 -isystem %S %s -fsyntax-only -verify 
 
 #include <warn-in-system-header.h>
-// expected-warning {{the cake is a lie}}
+// expected-warning@warn-in-system-header.h:4 {{the cake is a lie}}
diff --git a/test/Modules/auto-module-import.m b/test/Modules/auto-module-import.m
index 4bd3c52..7351828 100644
--- a/test/Modules/auto-module-import.m
+++ b/test/Modules/auto-module-import.m
@@ -1,10 +1,10 @@
-// other file: expected-note{{'no_umbrella_A_private' declared here}}
-
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify
 
 #include <DependsOnModule/DependsOnModule.h> // expected-warning{{treating #include as an import of module 'DependsOnModule'}}
 
+// expected-note@Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h:1{{'no_umbrella_A_private' declared here}}
+
 #ifdef MODULE_H_MACRO
 #  error MODULE_H_MACRO should have been hidden
 #endif
diff --git a/test/Modules/decldef.m b/test/Modules/decldef.m
index 7fb8a61..7ed82b5 100644
--- a/test/Modules/decldef.m
+++ b/test/Modules/decldef.m
@@ -1,8 +1,7 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
 
-
-// In other file: expected-note {{previous definition is here}}
+// expected-note@Inputs/def.h:5 {{previous definition is here}}
 
 @class Def;
 Def *def;
diff --git a/test/Modules/decldef.mm b/test/Modules/decldef.mm
index 732c2a2..593f53b 100644
--- a/test/Modules/decldef.mm
+++ b/test/Modules/decldef.mm
@@ -1,8 +1,7 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
 
-
-// In other file: expected-note {{previous definition is here}}
+// expected-note@Inputs/def.h:5 {{previous definition is here}}
 
 @class Def;
 Def *def;
diff --git a/test/Modules/diamond-pch.c b/test/Modules/diamond-pch.c
index 079f6af..e7ad02d 100644
--- a/test/Modules/diamond-pch.c
+++ b/test/Modules/diamond-pch.c
@@ -1,23 +1,3 @@
-
-
-
-// in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}}
-
-void test_diamond(int i, float f, double d, char c) {
-  top(&i);
-  left(&f);
-  right(&d);
-  bottom(&c);
-  bottom(&d); // expected-warning{{incompatible pointer types passing 'double *' to parameter of type 'char *'}}
-
-  // Names in multiple places in the diamond.
-  top_left(&c);
-
-  left_and_right(&i);
-  struct left_and_right lr;
-  lr.left = 17;
-}
-
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_top %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_left %S/Inputs/module.map
@@ -26,3 +6,20 @@
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-pch -fmodules-cache-path=%t -o %t.pch %S/Inputs/diamond.h
 // RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -include-pch %t.pch %s -verify
 // FIXME: When we have a syntax for modules in C, use that.
+
+void test_diamond(int i, float f, double d, char c) {
+  top(&i);
+  left(&f);
+  right(&d);
+  bottom(&c);
+  bottom(&d);
+  // expected-warning@-1{{incompatible pointer types passing 'double *' to parameter of type 'char *'}}
+  // expected-note@Inputs/diamond_bottom.h:4{{passing argument to parameter 'x' here}}
+
+  // Names in multiple places in the diamond.
+  top_left(&c);
+
+  left_and_right(&i);
+  struct left_and_right lr;
+  lr.left = 17;
+}
diff --git a/test/Modules/diamond.c b/test/Modules/diamond.c
index 0bac1b7..89d5bc0 100644
--- a/test/Modules/diamond.c
+++ b/test/Modules/diamond.c
@@ -1,7 +1,10 @@
-
-
-
-// in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}}
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_top %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_left %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_right %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_bottom %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t %s -verify
+// FIXME: When we have a syntax for modules in C, use that.
 
 @import diamond_bottom;
 
@@ -10,7 +13,9 @@
   left(&f);
   right(&d);
   bottom(&c);
-  bottom(&d); // expected-warning{{incompatible pointer types passing 'double *' to parameter of type 'char *'}}
+  bottom(&d);
+  // expected-warning@-1{{incompatible pointer types passing 'double *' to parameter of type 'char *'}}
+  // expected-note@Inputs/diamond_bottom.h:4{{passing argument to parameter 'x' here}}
 
   // Names in multiple places in the diamond.
   top_left(&c);
@@ -20,10 +25,3 @@
   lr.left = 17;
 }
 
-// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_top %S/Inputs/module.map
-// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_left %S/Inputs/module.map
-// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_right %S/Inputs/module.map
-// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodules-cache-path=%t -fmodule-name=diamond_bottom %S/Inputs/module.map
-// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t %s -verify
-// FIXME: When we have a syntax for modules in C, use that.
diff --git a/test/Modules/linkage-merge.cpp b/test/Modules/linkage-merge.cpp
index 4e2ecef..9cc9ae6 100644
--- a/test/Modules/linkage-merge.cpp
+++ b/test/Modules/linkage-merge.cpp
@@ -1,13 +1,12 @@
-// FIXME: we should be able to put these in the .h file :-(
-// expected-note {{target of using declaration}}
-// expected-note {{using declaration}}
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -verify -fmodules -fmodules-cache-path=%t -I %S/Inputs %s
 
 #include "linkage-merge-bar.h"
 
 static int f(int);
 int f(int);
 
-static void g(int); // expected-error {{declaration conflicts with target of using declaration already in scope}}
-
-// RUN: rm -rf %t
-// RUN: %clang_cc1 -verify -fmodules -fmodules-cache-path=%t -I %S/Inputs %s
+static void g(int);
+// expected-error@-1 {{declaration conflicts with target of using declaration already in scope}}
+// expected-note@Inputs/linkage-merge-foo.h:2 {{target of using declaration}}
+// expected-note@Inputs/linkage-merge-bar.h:3 {{using declaration}}
diff --git a/test/Modules/linkage-merge.m b/test/Modules/linkage-merge.m
index 16e2205..e838ca1 100644
--- a/test/Modules/linkage-merge.m
+++ b/test/Modules/linkage-merge.m
@@ -1,27 +1,26 @@
-// In module: expected-note{{previous declaration}}
-
-
-
-
-// In module: expected-note{{previous definition is here}}
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -emit-module -fmodule-name=linkage_merge_left %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -w %s -verify
 
 // Test redeclarations of functions where the original declaration is
 // still hidden.
 
 @import linkage_merge_left; // excludes "sub"
 
-extern int f0(float); // expected-error{{conflicting types for 'f0'}}
+extern int f0(float);
+// expected-error@-1{{conflicting types for 'f0'}}
+// expected-note@Inputs/linkage-merge-sub.h:1{{previous declaration}}
+
 static int f1(float); // okay: considered distinct
 static int f2(float); // okay: considered distinct
 extern int f3(float); // okay: considered distinct
 
-extern float v0; // expected-error{{redefinition of 'v0' with a different type: 'float' vs 'int'}}
+extern float v0;
+// expected-error@-1{{redefinition of 'v0' with a different type: 'float' vs 'int'}}
+// expected-note@Inputs/linkage-merge-sub.h:6{{previous definition is here}}
+
 static float v1;
 static float v2;
 extern float v3;
 
 typedef float T0;
-
-// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -emit-module -fmodule-name=linkage_merge_left %S/Inputs/module.map
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -w %s -verify
diff --git a/test/Modules/lookup.cpp b/test/Modules/lookup.cpp
index 002b6d1..efd88f4 100644
--- a/test/Modules/lookup.cpp
+++ b/test/Modules/lookup.cpp
@@ -5,7 +5,7 @@
 #define IMPORT(X) @import X
 IMPORT(lookup_right_cxx);
 
-// in lookup_left.hpp: expected-warning@3 {{weak identifier 'weak_identifier' never declared}}
+// expected-warning@Inputs/lookup_left.hpp:3 {{weak identifier 'weak_identifier' never declared}}
 
 void test(int i, float f) {
   // unqualified lookup
diff --git a/test/Modules/lookup.m b/test/Modules/lookup.m
index abe9542..54c7491 100644
--- a/test/Modules/lookup.m
+++ b/test/Modules/lookup.m
@@ -1,19 +1,19 @@
-
-// lookup_left.h: expected-note{{using}}
-// lookup_right.h: expected-note{{also found}}
-@import lookup_left_objc;
-@import lookup_right_objc;
-
-void test(id x) {
-  [x method]; // expected-warning{{multiple methods named 'method' found}}
-}
-
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -emit-module -x objective-c -fmodule-name=lookup_left_objc %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -emit-module -x objective-c -fmodule-name=lookup_right_objc %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -verify %s
 // RUN: %clang_cc1 -fmodules -ast-print -x objective-c -fmodules-cache-path=%t %s | FileCheck -check-prefix=CHECK-PRINT %s
 
+@import lookup_left_objc;
+@import lookup_right_objc;
+
+void test(id x) {
+  [x method];
+// expected-warning@-1{{multiple methods named 'method' found}}
+// expected-note@Inputs/lookup_left.h:2{{using}}
+// expected-note@Inputs/lookup_right.h:3{{also found}}
+}
+
 // CHECK-PRINT: - (int) method;
 // CHECK-PRINT: - (double) method
 // CHECK-PRINT: void test(id x)
diff --git a/test/Modules/macros.c b/test/Modules/macros.c
index fc448d9..433e033 100644
--- a/test/Modules/macros.c
+++ b/test/Modules/macros.c
@@ -8,13 +8,13 @@
 // FIXME: When we have a syntax for modules in C, use that.
 // These notes come from headers in modules, and are bogus.
 
-// FIXME: expected-note{{previous definition is here}}
-// FIXME: expected-note{{previous definition is here}} expected-note{{expanding this definition of 'LEFT_RIGHT_DIFFERENT'}}
-// expected-note{{other definition of 'TOP_RIGHT_REDEF'}} expected-note{{expanding this definition of 'LEFT_RIGHT_DIFFERENT2'}}
-// expected-note{{other definition of 'LEFT_RIGHT_DIFFERENT'}}
-
-
-// expected-note{{expanding this definition of 'TOP_RIGHT_REDEF'}}
+// FIXME: expected-note@Inputs/macros_left.h:11{{previous definition is here}}
+// FIXME: expected-note@Inputs/macros_right.h:12{{previous definition is here}}
+// expected-note@Inputs/macros_right.h:12{{expanding this definition of 'LEFT_RIGHT_DIFFERENT'}}
+// expected-note@Inputs/macros_top.h:13{{other definition of 'TOP_RIGHT_REDEF'}}
+// expected-note@Inputs/macros_right.h:13{{expanding this definition of 'LEFT_RIGHT_DIFFERENT2'}}
+// expected-note@Inputs/macros_left.h:14{{other definition of 'LEFT_RIGHT_DIFFERENT'}}
+// expected-note@Inputs/macros_right.h:17{{expanding this definition of 'TOP_RIGHT_REDEF'}}
 
 @import macros;
 
diff --git a/test/Modules/method_pool.m b/test/Modules/method_pool.m
index 9a8897b..6fd74b0 100644
--- a/test/Modules/method_pool.m
+++ b/test/Modules/method_pool.m
@@ -8,8 +8,8 @@
 - (void)method5:(D*)obj;
 @end
 
-// in other file: // expected-note@7{{using}}
-// in other file: expected-note@12{{also found}}
+// expected-note@Inputs/MethodPoolA.h:7{{using}}
+// expected-note@Inputs/MethodPoolB.h:12{{also found}}
 
 void testMethod1(id object) {
   [object method1]; 
@@ -51,8 +51,8 @@
 
 void testMethod3AgainAgain(id object) {
   [object method3]; // expected-warning{{multiple methods named 'method3' found}}
-  // expected-note@2{{using}}
-  // expected-note@2{{also found}}
+  // expected-note@Inputs/MethodPoolBSub.h:2{{using}}
+  // expected-note@Inputs/MethodPoolASub.h:2{{also found}}
 }
 
 void testMethod4Again(id object) {
diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp
index d4e73b5..438dcab 100644
--- a/test/Modules/module-private.cpp
+++ b/test/Modules/module-private.cpp
@@ -15,7 +15,7 @@
   HiddenStruct hidden; // \
   // expected-error{{must use 'struct' tag to refer to type 'HiddenStruct' in this scope}} \
   // expected-error{{definition of 'struct HiddenStruct' must be imported}}
-  // expected-note@3 {{previous definition is here}}
+  // expected-note@Inputs/module_private_left.h:3 {{previous definition is here}}
 
   Integer i; // expected-error{{unknown type name 'Integer'}}
 
diff --git a/test/Modules/namespaces.cpp b/test/Modules/namespaces.cpp
index 0e9dbff..426e002 100644
--- a/test/Modules/namespaces.cpp
+++ b/test/Modules/namespaces.cpp
@@ -73,5 +73,5 @@
   N12::consumeFoo(N12::getFoo()); // expected-error{{cannot initialize a parameter of type 'N12::<anonymous>::Foo *' with an rvalue of type 'N12::<anonymous>::Foo *'}}  
 }
 
-// namespaces-right.h: expected-note@60 {{passing argument to parameter here}}
-// namespaces-right.h: expected-note@67 {{passing argument to parameter here}}
+// expected-note@Inputs/namespaces-right.h:60 {{passing argument to parameter here}}
+// expected-note@Inputs/namespaces-right.h:67 {{passing argument to parameter here}}
diff --git a/test/Modules/normal-module-map.cpp b/test/Modules/normal-module-map.cpp
index 423e808..8155318 100644
--- a/test/Modules/normal-module-map.cpp
+++ b/test/Modules/normal-module-map.cpp
@@ -1,5 +1,3 @@
-// Note: inside the module. expected-note{{'nested_umbrella_a' declared here}}
-
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -x objective-c -fmodules-cache-path=%t -fmodules -I %S/Inputs/normal-module-map %s -verify
 #include "Umbrella/umbrella_sub.h"
@@ -25,7 +23,9 @@
 }
 
 int testNestedUmbrellaBFail() {
-  return nested_umbrella_b; // expected-error{{use of undeclared identifier 'nested_umbrella_b'; did you mean 'nested_umbrella_a'?}}
+  return nested_umbrella_b;
+  // expected-error@-1{{use of undeclared identifier 'nested_umbrella_b'; did you mean 'nested_umbrella_a'?}}
+  // expected-note@Inputs/normal-module-map/nested_umbrella/a.h:1{{'nested_umbrella_a' declared here}}
 }
 
 @import nested_umbrella.b;
diff --git a/test/Modules/objc-categories.m b/test/Modules/objc-categories.m
index d3ebcb7..81fb28b 100644
--- a/test/Modules/objc-categories.m
+++ b/test/Modules/objc-categories.m
@@ -8,11 +8,8 @@
 
 @import category_bottom;
 
-
-
-
-// in category_left.h: expected-note {{previous definition}}
-// in category_right.h: expected-warning@11 {{duplicate definition of category}}
+// expected-note@Inputs/category_left.h:14 {{previous definition}}
+// expected-warning@Inputs/category_right.h:11 {{duplicate definition of category}}
 
 @interface Foo(Source)
 -(void)source; 
@@ -75,7 +72,7 @@
   [p4 p4_method]; // expected-warning{{instance method '-p4_method' not found (return type defaults to 'id')}}
   id p4p = p4.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'id<P4>'}}
   p4p = foo.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'Foo *'; did you mean 'p3_prop'?}}
-  // expected-note@7{{'p3_prop' declared here}}
+  // expected-note@Inputs/category_left_sub.h:7{{'p3_prop' declared here}}
 }
 
 @import category_right.sub;
diff --git a/test/Modules/on-demand-build.m b/test/Modules/on-demand-build.m
index 31742f7..e958759 100644
--- a/test/Modules/on-demand-build.m
+++ b/test/Modules/on-demand-build.m
@@ -7,7 +7,7 @@
 @interface OtherClass
 @end
 
-// in module: expected-note@17{{class method 'alloc' is assumed to return an instance of its receiver type ('Module *')}}
+// expected-note@Inputs/Module.framework/Headers/Module.h:17{{class method 'alloc' is assumed to return an instance of its receiver type ('Module *')}}
 void test_getModuleVersion() {
   const char *version = getModuleVersion();
   const char *version2 = [Module version];
diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m
index e373667..37e5967 100644
--- a/test/Modules/redecl-merge.m
+++ b/test/Modules/redecl-merge.m
@@ -27,8 +27,8 @@
 int *call_eventually_noreturn2_again(void) {
   // noreturn and non-noreturn functions have different types
   eventually_noreturn2(); // expected-error{{call to 'eventually_noreturn2' is ambiguous}}
-  // expected-note@93{{candidate function}}
-  // expected-note@90{{candidate function}}
+  // expected-note@Inputs/redecl-merge-left.h:93{{candidate function}}
+  // expected-note@Inputs/redecl-merge-right.h:90{{candidate function}}
 }
 
 @implementation A
@@ -79,24 +79,26 @@
   T1 *ip = &i;
   // FIXME: Typedefs aren't actually merged in the sense of other merges, because
   // we should only merge them when the types are identical.
-  // in other file: expected-note@60{{candidate found by name lookup is 'T2'}}
-  // in other file: expected-note@63{{candidate found by name lookup is 'T2'}}
+  // expected-note@Inputs/redecl-merge-left.h:60{{candidate found by name lookup is 'T2'}}
+  // expected-note@Inputs/redecl-merge-right.h:63{{candidate found by name lookup is 'T2'}}
   T2 *dp = &d; // expected-error{{reference to 'T2' is ambiguous}}
 }
 
 void testFuncMerge(int i) {
   func0(i);
   func1(i);
-  // in other file: expected-note@64{{candidate function}}
-  // in other file: expected-note@70{{candidate function}}
+  // expected-note@Inputs/redecl-merge-left.h:64{{candidate function}}
+  // expected-note@Inputs/redecl-merge-right.h:70{{candidate function}}
   func2(i); // expected-error{{call to 'func2' is ambiguous}}
 }
 
 void testVarMerge(int i) {
   var1 = i;
-  // in other files: expected-note@77 2{{candidate found by name lookup is 'var2'}}
+  // expected-note@Inputs/redecl-merge-left.h:77{{candidate found by name lookup is 'var2'}}
+  // expected-note@Inputs/redecl-merge-right.h:77{{candidate found by name lookup is 'var2'}}
   var2 = i; // expected-error{{reference to 'var2' is ambiguous}}
-  // in other files: expected-note@79 2{{candidate found by name lookup is 'var3'}}
+  // expected-note@Inputs/redecl-merge-left.h:79{{candidate found by name lookup is 'var3'}}
+  // expected-note@Inputs/redecl-merge-right.h:79{{candidate found by name lookup is 'var3'}}
   var3 = i; // expected-error{{reference to 'var3' is ambiguous}}
 }
 
diff --git a/test/Modules/subframeworks.m b/test/Modules/subframeworks.m
index 22dfcca..ad70cc2 100644
--- a/test/Modules/subframeworks.m
+++ b/test/Modules/subframeworks.m
@@ -23,7 +23,7 @@
 
 @import HasSubModules;
 
-// expected-warning@1{{treating #include as an import of module 'HasSubModules.Sub.Types'}}
+// expected-warning@Inputs/HasSubModules.framework/Frameworks/Sub.framework/PrivateHeaders/SubPriv.h:1{{treating #include as an import of module 'HasSubModules.Sub.Types'}}
 #import <HasSubModules/HasSubModulesPriv.h>
 
 struct FrameworkSubStruct ss;
diff --git a/test/PCH/cxx-using.cpp b/test/PCH/cxx-using.cpp
index 2ca7dad..2cab1f0 100644
--- a/test/PCH/cxx-using.cpp
+++ b/test/PCH/cxx-using.cpp
@@ -6,10 +6,9 @@
 // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s 
 
 void m() {
-    D s;   // expected-note {{candidate function}}
+    D s;
     s.f(); // expected-error {{no matching member}}
 }
 
-
-
-// expected-note {{candidate function}}
+// expected-note@cxx-using.h:9  {{candidate function}}
+// expected-note@cxx-using.h:15 {{candidate function}}
diff --git a/test/PCH/cxx11-statement-attributes.cpp b/test/PCH/cxx11-statement-attributes.cpp
index 3bb7b40aa..722ca6e 100644
--- a/test/PCH/cxx11-statement-attributes.cpp
+++ b/test/PCH/cxx11-statement-attributes.cpp
@@ -4,8 +4,7 @@
 // RUN: %clang_cc1 -x c++-header -emit-pch -std=c++11 -o %t %S/Inputs/cxx11-statement-attributes.h
 // RUN: %clang_cc1 -include-pch %t -std=c++11 -Wimplicit-fallthrough -fsyntax-only %s -o - -verify
 
-// Warning from Inputs/cxx11-statement-attributes.h:
-// expected-warning@10 {{fallthrough annotation does not directly precede switch label}}
+// expected-warning@Inputs/cxx11-statement-attributes.h:10 {{fallthrough annotation does not directly precede switch label}}
 
 void g(int n) {
   f<1>(n);  // expected-note {{in instantiation of function template specialization 'f<1>' requested here}}
diff --git a/test/PCH/functions.c b/test/PCH/functions.c
index 35e3921..fa2ba8d 100644
--- a/test/PCH/functions.c
+++ b/test/PCH/functions.c
@@ -4,18 +4,20 @@
 // Test with pch.
 // RUN: %clang_cc1 -emit-pch -o %t %S/functions.h
 // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s 
-// expected-note{{'f1' declared here}}
+
 int f0(int x0, int y0, ...) { return x0 + y0; }
-// expected-note{{passing argument to parameter here}}
+
 float *test_f1(int val, double x, double y) {
   if (val > 5)
     return f1(x, y);
   else
     return f1(x); // expected-error{{too few arguments to function call}}
+                  // expected-note@functions.h:7{{'f1' declared here}}
 }
 
 void test_g0(int *x, float * y) {
   g0(y); // expected-warning{{incompatible pointer types passing 'float *' to parameter of type 'int *'}}
+         // expected-note@functions.h:9{{passing argument to parameter here}}
   g0(x); 
 }
 
diff --git a/test/PCH/method_pool.m b/test/PCH/method_pool.m
index 20010fb..139f8ba 100644
--- a/test/PCH/method_pool.m
+++ b/test/PCH/method_pool.m
@@ -9,13 +9,5 @@
    return [x instMethod:17]; // expected-warning{{multiple methods}}
 }
 
-
-
-
-
-/* Whitespace below is significant */
-/* expected-note{{using}} */
-
-
-
-/* expected-note{{also}} */
+/* expected-note@method_pool.h:17{{using}} */
+/* expected-note@method_pool.h:21{{also}} */
diff --git a/test/PCH/nonvisible-external-defs.c b/test/PCH/nonvisible-external-defs.c
index 49392ca..092e2c9 100644
--- a/test/PCH/nonvisible-external-defs.c
+++ b/test/PCH/nonvisible-external-defs.c
@@ -7,4 +7,4 @@
 
 int g(int, float); // expected-error{{conflicting types}}
 
-// expected-note{{previous declaration}}
+// expected-note@nonvisible-external-defs.h:10{{previous declaration}}
diff --git a/test/PCH/reloc.c b/test/PCH/reloc.c
index 4c426e4..8dabb8b 100644
--- a/test/PCH/reloc.c
+++ b/test/PCH/reloc.c
@@ -10,5 +10,5 @@
 int y = 5; // expected-error{{redefinition}}
 
 
-// expected-note{{previous definition}}
-// expected-note{{previous definition}}
+// expected-note@libroot/usr/include/reloc.h:13{{previous definition}}
+// expected-note@libroot/usr/include/reloc2.h:14{{previous definition}}
diff --git a/test/PCH/tentative-defs.c b/test/PCH/tentative-defs.c
index 0072818..4288230 100644
--- a/test/PCH/tentative-defs.c
+++ b/test/PCH/tentative-defs.c
@@ -5,5 +5,4 @@
 // RUN: grep "@variable = common global i32 0" %t | count 1
 // RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1
 
-
-// FIXME: tentative-defs.h expected-warning{{tentative}}
+// FIXME: expected-warning@tentative-defs.h:9{{tentative}}
diff --git a/test/PCH/typo.cpp b/test/PCH/typo.cpp
index f8161d1..6ab66c2 100644
--- a/test/PCH/typo.cpp
+++ b/test/PCH/typo.cpp
@@ -1,17 +1,14 @@
-
-// In header: expected-note{{'boost::function' declared here}}
-
-
-// In header: expected-note{{'boost::graph::adjacency_list' declared here}}
-
-
-
-adjacent_list<int, int> g; // expected-error{{no template named 'adjacent_list'; did you mean 'boost::graph::adjacency_list'?}}
-Function<int(int)> f; // expected-error{{no template named 'Function'; did you mean 'boost::function'?}}
-
 // Without PCH
 // RUN: %clang_cc1 -include %S/Inputs/typo.hpp -verify %s
 
 // With PCH
 // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/Inputs/typo.hpp
 // RUN: %clang_cc1 -include-pch %t -verify %s
+
+adjacent_list<int, int> g;
+// expected-error@-1{{no template named 'adjacent_list'; did you mean 'boost::graph::adjacency_list'?}}
+// expected-note@Inputs/typo.hpp:5{{'boost::graph::adjacency_list' declared here}}
+
+Function<int(int)> f;
+// expected-error@-1{{no template named 'Function'; did you mean 'boost::function'?}}
+// expected-note@Inputs/typo.hpp:2{{'boost::function' declared here}}
diff --git a/test/PCH/typo.m b/test/PCH/typo.m
index c6f0275..876b943 100644
--- a/test/PCH/typo.m
+++ b/test/PCH/typo.m
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -x objective-c-header -emit-pch -o %t %S/Inputs/typo.h
 // RUN: %clang_cc1 -include-pch %t -verify %s
-// In header: expected-note{{declared here}}
+
 void f() {
   [NSstring alloc]; // expected-error{{unknown receiver 'NSstring'; did you mean 'NSString'?}}
+                    // expected-note@Inputs/typo.h:3{{declared here}}
 }
diff --git a/test/Sema/pragma-arc-cf-code-audited.c b/test/Sema/pragma-arc-cf-code-audited.c
index b646e89..c1aa804 100644
--- a/test/Sema/pragma-arc-cf-code-audited.c
+++ b/test/Sema/pragma-arc-cf-code-audited.c
@@ -13,6 +13,6 @@
 #include "Inputs/pragma-arc-cf-code-audited.h" // expected-error {{cannot #include files inside '#pragma clang arc_cf_code_audited'}}
 
 // This is actually on the #pragma line in the header.
-// expected-error {{'#pragma clang arc_cf_code_audited' was not ended within this file}}
+// expected-error@Inputs/pragma-arc-cf-code-audited.h:16 {{'#pragma clang arc_cf_code_audited' was not ended within this file}}
 
 #pragma clang arc_cf_code_audited begin // expected-error {{'#pragma clang arc_cf_code_audited' was not ended within this file}}
diff --git a/test/SemaObjC/arc-system-header.m b/test/SemaObjC/arc-system-header.m
index 3443bda..d9392ed 100644
--- a/test/SemaObjC/arc-system-header.m
+++ b/test/SemaObjC/arc-system-header.m
@@ -1,30 +1,30 @@
-// silly workaround expected-note {{marked unavailable here}}
 // RUN: %clang_cc1 -fobjc-arc -isystem %S/Inputs %s -DNO_USE
 // RUN: %clang_cc1 -fobjc-arc -isystem %S/Inputs %s -verify
 
-// another silly workaround expected-note {{marked unavailable here}}
 #include <arc-system-header.h>
 
 #ifndef NO_USE
 void test(id op, void *cp) {
   cp = test0(op); // expected-error {{'test0' is unavailable: converts between Objective-C and C pointers in -fobjc-arc}}
   cp = *test1(&op); // expected-error {{'test1' is unavailable: converts between Objective-C and C pointers in -fobjc-arc}}
+// expected-note@arc-system-header.h:1 {{marked unavailable here}}
+// expected-note@arc-system-header.h:5 {{marked unavailable here}}
 }
 
-// workaround expected-note {{marked unavailable here}}
 void test3(struct Test3 *p) {
   p->field = 0; // expected-error {{'field' is unavailable: this system declaration uses an unsupported type}}
+                // expected-note@arc-system-header.h:14 {{marked unavailable here}}
 }
 
-// workaround expected-note {{marked unavailable here}}
 void test4(Test4 *p) {
   p->field1 = 0; // expected-error {{'field1' is unavailable: this system declaration uses an unsupported type}}
+                 // expected-note@arc-system-header.h:19 {{marked unavailable here}}
   p->field2 = 0;
 }
 
-// workaround expected-note {{marked unavailable here}}
 void test5(struct Test5 *p) {
   p->field = 0; // expected-error {{'field' is unavailable: this system field has retaining ownership}}
+                // expected-note@arc-system-header.h:25 {{marked unavailable here}}
 }
 
 id test6() {
@@ -38,12 +38,13 @@
   x = (id) (test6_helper(), kMagicConstant);
 }
 
-// workaround expected-note 4 {{marked unavailable here}} expected-note 2 {{property 'prop' is declared unavailable here}}
 void test7(Test7 *p) {
   *p.prop = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}}
   p.prop = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}}
   *[p prop] = 0; // expected-error {{'prop' is unavailable: this system declaration uses an unsupported type}}
   [p setProp: 0]; // expected-error {{'setProp:' is unavailable: this system declaration uses an unsupported type}}
+// expected-note@arc-system-header.h:41 4 {{marked unavailable here}}
+// expected-note@arc-system-header.h:41 2 {{property 'prop' is declared unavailable here}}
 }
 #endif
 
diff --git a/test/SemaObjCXX/arc-system-header.mm b/test/SemaObjCXX/arc-system-header.mm
index 107b5b5..3358e5f 100644
--- a/test/SemaObjCXX/arc-system-header.mm
+++ b/test/SemaObjCXX/arc-system-header.mm
@@ -6,5 +6,4 @@
   a->data.void_ptr = 0;
   a->data.a_b.b = 0; // expected-error{{'a_b' is unavailable: this system field has retaining ownership}}
 }
-// Silly location below
-// expected-note{{declaration has been explicitly marked unavailable here}}
+// expected-note@arc-system-header.h:10{{declaration has been explicitly marked unavailable here}}