Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2697,12 +2697,9 @@ AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs) { - if (DS.getSourceRange().isInvalid()) { - // Start the range at the current token but make the end of the range - // invalid. This will make the entire range invalid unless we successfully - // consume a token. + if (DS.getSourceRange().isInvalid() && !Tok.is(tok::eof)) { DS.SetRangeStart(Tok.getLocation()); - DS.SetRangeEnd(SourceLocation()); + DS.SetRangeEnd(Tok.getLocation()); } bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -2042,7 +2042,9 @@ } // Give up, we can't recover. - Diag(R.getNameLoc(), diagnostic) << Name; + auto Builder = Diag(R.getNameLoc(), diagnostic) << Name; + if (Name.isIdentifier()) + Builder << SourceRange(R.getNameLoc()); return true; } Index: test/Index/diagnostic-ranges.cpp =================================================================== --- /dev/null +++ test/Index/diagnostic-ranges.cpp @@ -0,0 +1,23 @@ +// RUN: c-index-test -test-load-source all %s > /dev/null 2> %t.err +// RUN: FileCheck < %t.err -check-prefix=CHECK-RANGE %s + +struct Foo { + someIdentifierLeadingToAnInvalidRange; +}; + +template +struct Bar { + Bar(const T&) {} +}; + +void f() +{ + for (Bar<__typeof__(v.x)> container(v.x); true; ) + return; +} + +// CHECK-RANGE: diagnostic-ranges.cpp:5:3: error: C++ requires a type specifier for all declarations +// CHECK-RANGE: diagnostic-ranges.cpp:15:39: error: use of undeclared identifier 'v' +// CHECK-RANGE: diagnostic-ranges.cpp:5:3:{5:3-5:40}: error: C++ requires a type specifier for all declarations +// CHECK-RANGE: diagnostic-ranges.cpp:15:23:{15:23-15:24}: error: use of undeclared identifier 'v' +