+ lexer->buffer->length ()
                      - 1;
 
+  if (lexer->buffer->length () != 1)
+    {
+      /* Set the EOF token's location to be the just after the previous
+         token's range.  That way 'at-eof' diagnostics point at something
+        meaninful.  */
+      auto range = get_range_from_loc (line_table, tok[-1].location);
+      tok[0].location
+       = linemap_position_for_loc_and_offset (line_table, range.m_finish, 1);
+    }
+
   if (filter)
     module_token_cdtor (parse_in, filter);
 
 
 foo ()
 {
 #pragma acc routine /* { dg-error ".#pragma acc routine. must be at file scope" } */
-// { dg-error "expected" "end" { target c } .-1 }
-// { dg-error "-:expected" "end" { target c++ } .+1 }
+// { dg-error "expected" "end" { target *-*-* } .-1 }
+
 
 {
 #pragma omp sections
 #pragma omp section /* { dg-error "'#pragma omp section' may only be used in '#pragma omp sections' construct|not allowed" } */
-// { dg-error "expected" "end" { target c } .-1 }
-// { dg-error "-:expected" "end" { target c++ } .+1 }
+// { dg-error "expected" "end" { target *-*-* } .-1 }
 
 // { dg-options "-std=c++0x" { target c++ } }
 
 const void *s0 = R"ouch()ouCh";        // { dg-error "unterminated raw string" "unterminated" }
-// { dg-error "at end of input" "end" { target c } .-1 }
-// { dg-error "-:at end of input" "end" { target c++ } .+1 }
+// { dg-error "at end of input" "end" { target *-*-* } .-1 }
 
 template<typename T>
 class C{
  T t;
-  decltype(t)::a:: // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+  decltype(t)::a:: // { dg-error "expected"  }
 
 // { dg-do compile { target c++11 } }
 
 namespace alignas() N  {} // { dg-error "expected"  }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
   template <typename... _Args>
   using __has_construct typename __construct_helper<_Args...>::type;  // { dg-error "expected" }
 } struct : A<int> {   // { dg-error "expected" }
-  // { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 // { dg-do compile { target c++11 } }
 
 alignas (alignas double // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 {
     foo<ns::bar> f;
     adl::swap(f, f) // { dg-error "expected ';'" }
-}
-// { dg-error "-:expected '.'" "expected end of namespace" { target *-*-* } .+1 }
+} // { dg-error "2:expected" }
 
 }
 auto &traverse = constant < functors :: traverse > ;
 operator()()->decltype(traverse(0, 0))// { dg-error "no match"  }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "39:expected" "" { target *-*-* } .-1 }
 
 // { dg-do compile { target c++14 } }
 
 template <typename> struct bar foo; template <> struct foo<>:  // { dg-error "class template|redeclared" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "62:expected" "" { target *-*-* } .-1 }
 
 
 template <typename> struct A;
 template <typename> struct B : A < B { , // { dg-error ""  }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
--- /dev/null
+// PR 96045  EOF location
+
+template <class> class A {};
+struct A <int> // { dg-error "15:" }
 
--- /dev/null
+// PR 96045  EOF location
+
+template <class> class A {};
+struct A <int> // { dg-error "15:" }
+/* A comment */
+  
 
--- /dev/null
+// PR 96045  EOF location
+
+#define BORKED <int> // { dg-error "20:" }
+
+template <class> class A {};
+struct A BORKED // { dg-message "10: in expansion of" }
 
 
 void test (void);
 // { message "12: to match this '.'" "" { target *-*-* } open_extern_c }
-/* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+/* { dg-error "18:expected '.' at end of input" "" { target *-*-* } .-2 } */
 
 void test (void)
 { /* { dg-message "1: to match this '.'" } */
-  int filler;
-  /* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+  int filler; /* { dg-error "14:expected '.' at end of input"  } */
 
 namespace unclosed { /* { dg-message "20: to match this '.'" } */
-int filler;
-/* { dg-error "-:expected '.' at end of input" "" { target *-*-* } .+1 } */
+int filler; /* { dg-error "12:expected '.' at end of input" } */
 
 struct unclosed { /* { dg-message "17: to match this '.'" } */
-  int dummy;
-  // { dg-error "-:expected" "" { target *-*-* } .+1 }
+  int dummy; // { dg-error "13:expected"  }
 
 // { dg-options "-fpermissive -w" }
 
-template<int b> __attribute__ a([] { class c, __attribute__(vector_size(operator+()))) d; // { dg-error "" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+template<int b> __attribute__ a([] { class c, __attribute__(vector_size(operator+()))) d; // { dg-error "before" }
+// { dg-error "90:expected" "" { target *-*-* } .-1 }
 
 class a b;  // { dg-error "aggregate" }
 void c() {
   switch ()  // { dg-error "expected" }
-  case b  // { dg-error "expected" }
-    // { dg-error "-:expected" "" { target *-*-* } .+1 }
+  case b  // { dg-error "9:expected" }
 
 // PR c++/93684 - ICE-on-invalid with broken attribute.
 
 [[a:: // { dg-error "expected" }
-  // { dg-error "-:expected" "" { target c++11 } .+1 }
 
 
 void foo()                                                                                                                              
 {                                                                                                                                       
-  if (struct A{}// { dg-error "types may not be defined|expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+  if (struct A{}// { dg-error "" }
 
 {
   typename::
 ; // { dg-error "expected" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 // PR 18095: ICE
 // Origin: Volker Reichelt <reichelt@gcc.gnu.org>
 
-struct A // { dg-error "-:expected" "" { target *-*-* } .+1 }
+struct A // { dg-error "9:expected" }
 
 
 void Dispatcher()
         (__builtin_offsetof (ArgsType, largeMsgLen)) // { dg-error "initialize" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "54:expected" "" { target *-*-* } .-1 }
 
 void foo()
 {
   namespace N { /* { dg-error "is not allowed" } */
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "16:expected" "" { target *-*-* } .-1 }
 
 struct a {};
 
 class foo : public a, a                // { dg-error "duplicate base" }
-{ // { dg-error "-:at end of input" "" { target *-*-* } .+1 } 
+{ // { dg-error "2:at end of input" } 
 
 // PR c++/39053
 
 void foo() = // { dg-error "initialized" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "13:expected" "" { target *-*-* } .-1 }
 
 // PR c++/53003
 
 struct A{ void a{} return b  // { dg-error "16:function definition" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "28:expected" "" { target *-*-* } .-1 }
 
 struct pair { constexpr pair (const) : }; // { dg-error "" }
 template <0> make_pair () {}             // { dg-error "" }
 pair prefix[] = { 0, make_pair }         // { dg-error "" }
-// { dg-error "-:expected" "" { target c++11 } .+1 }
 
 class x0;
 template <x1> x2() {  // { dg-error "declared|type" }
 x0 x3 = x3. // { dg-error "incomplete type" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "12:expected" "" { target *-*-* } .-1 }
 
                  //    }
 
 };   // { dg-error "1:expected primary-expression before '.' token" "primary"  }
-// { dg-error "-:expected" "at end of input" { target *-*-* } .+1 }
+// { dg-error "3:expected" "at end of input" { target *-*-* } .-1 }
 
 class {
 // { dg-error "forbids" "" { target *-*-* } .+1 }
     friend __copy_streambufs_eof <> ( // { dg-error "" }
- // { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 // { dg-options "-w" }
 
 int foo ( foo += *[ // { dg-error "expected" }
-// { dg-error "-:invalid|expected" "" { target *-*-* } .+1 }
+// { dg-error "20:invalid|expected" "" { target *-*-* } .-1 }
 
 // { dg-do compile }
 
 struct {
-  a(void = 0; a(0), a(0) // { dg-error "" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+  a(void = 0; a(0), a(0) // { dg-error "invalid|cannot|before|forbid|member" }
+// { dg-error "25:end of input" "" { target *-*-* } .-1 }
 
 
   z = __complex__ (1.90000007326203904e+19, 0.0);   // { dg-error "expected primary-expression before '__complex__'" "primary-expression" } 
   z = __complex__ (1.0e+0, 0.0) / z;    // { dg-error "expected primary-expression before '__complex__'" "primaty-expression" } 
-  // { dg-error "-:at end of input" "end" { target *-*-* } .+1 }
+  // { dg-error "37:at end of input" "end" { target *-*-* } .-1 }
 
 
   z = _Complex (1.90000007326203904e+19, 0.0);   // { dg-error "expected primary-expression before '_Complex'" "primary-expression" } 
   z = _Complex (1.0e+0, 0.0) / z;    // { dg-error "expected primary-expression before '_Complex'" "primary-expression" } 
-  // { dg-error "-:at end of input" "end" { target *-*-* } .+1 }
+  // { dg-error "34:at end of input" "end" { target *-*-* } .-1 }
 
   A _M_ios_locale ios_base(ios_base &) template <_Traits> class basic_ios {  // { dg-error "" }
     basic_ios basic_ios = operator= // { dg-error "" }
 // { dg-prune-output "file ends in default argument" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 // { dg-additional-options -fopenmp }
 // { dg-require-effective-target fopenmp } 
-#pragma omp declare simd // { dg-error "not immediately followed by" }
-
-// { dg-error "-:expected unqualified-id" "" { target *-*-* } .+1 }
+#pragma omp declare simd // { dg-error "" }
 
 <
 class
 { // { dg-error "" }
-// { dg-error "-:" "" { target *-*-* } .+1 }
 
 // { dg-do compile }
 
 template < int > struct S { S < // { dg-error "" }
-  // { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 // PR c++/56534
 
 template < struct template rebind < > // { dg-error "expected|must follow" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
   struct ___is_pod {
     enum {
       __value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "expected|declared"  }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 template < typename >
 struct B ;
 template < typename T , A < B < T > {} // { dg-error "parse error|non-type|initializer" }
-
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "39:expected" "" { target *-*-* } .-1 }
 
   template < bool > struct T < S > // { dg-error "" }
   {
     void f () { // { dg-error "expected" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
 
 
 template <int()> struct a;
 template <int(b)> a < b                // { dg-error "int" }
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+// { dg-error "expected" "" { target *-*-* } .-1 }
 
 struct foo
 {
   foo();
-};
-// { dg-error "-:expected" "" { target *-*-* } .+1 }
+}; // { dg-error "3:expected"  }