Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -2329,6 +2329,13 @@ } FunctionDefinitionKind DefinitionKind = FDK_Declaration; + + // For explicitly deleted or defaulted declarations, we want to preserve the + // full source location of the declaration (including the "= delete" part). + // DeleteOrDefaultEndLoc saves this actual end location (end of the 'delete' + // or 'default' token). + SourceLocation DeleteOrDefaultEndLoc; + // function-definition: // // In C++11, a non-function declarator followed by an open brace is a @@ -2341,10 +2348,16 @@ DefinitionKind = FDK_Definition; } else if (Tok.is(tok::equal)) { const Token &KW = NextToken(); - if (KW.is(tok::kw_default)) + if (KW.is(tok::kw_default)) { DefinitionKind = FDK_Defaulted; - else if (KW.is(tok::kw_delete)) + DeleteOrDefaultEndLoc = + KW.getLocation().getLocWithOffset(KW.getLength() - 1); + } + else if (KW.is(tok::kw_delete)) { DefinitionKind = FDK_Deleted; + DeleteOrDefaultEndLoc = + KW.getLocation().getLocWithOffset(KW.getLength() - 1); + } } } @@ -2388,6 +2401,14 @@ for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { LateParsedAttrs[i]->addDecl(FunDecl); } + + // If the declaration is explicitly defaulted or deleted, fix up its end + // location to include the defaulting/deleting. + if (DefinitionKind == FDK_Defaulted || DefinitionKind == FDK_Deleted) { + if (auto *DeclAsFunction = dyn_cast(FunDecl)) { + DeclAsFunction->setRangeEnd(DeleteOrDefaultEndLoc); + } + } } LateParsedAttrs.clear(); Index: test/Analysis/inlining/path-notes.cpp =================================================================== --- test/Analysis/inlining/path-notes.cpp +++ test/Analysis/inlining/path-notes.cpp @@ -2458,12 +2458,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line105 -// CHECK-NEXT: col53 +// CHECK-NEXT: col63 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line105 -// CHECK-NEXT: col53 +// CHECK-NEXT: col63 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2475,7 +2475,7 @@ // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line105 -// CHECK-NEXT: col53 +// CHECK-NEXT: col63 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -2483,12 +2483,12 @@ // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line105 -// CHECK-NEXT: col53 +// CHECK-NEXT: col63 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line105 -// CHECK-NEXT: col53 +// CHECK-NEXT: col63 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: Index: test/Misc/ast-dump-decl.cpp =================================================================== --- test/Misc/ast-dump-decl.cpp +++ test/Misc/ast-dump-decl.cpp @@ -156,12 +156,12 @@ A = static_cast(B); TestMemberRanges C(static_cast(A)); } -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXDestructorDecl{{.*}} -// CHECK: CXXMethodDecl{{.*}} -// CHECK: CXXMethodDecl{{.*}} +// CHECK: CXXConstructorDecl{{.*}} +// CHECK: CXXConstructorDecl{{.*}} +// CHECK: CXXConstructorDecl{{.*}} +// CHECK: CXXDestructorDecl{{.*}} +// CHECK: CXXMethodDecl{{.*}} +// CHECK: CXXMethodDecl{{.*}} class TestCXXConversionDecl { operator int() { return 0; } Index: unittests/AST/SourceLocationTest.cpp =================================================================== --- unittests/AST/SourceLocationTest.cpp +++ unittests/AST/SourceLocationTest.cpp @@ -122,6 +122,18 @@ EXPECT_TRUE(Verifier.match("class C { C(); };", functionDecl())); } +TEST(CXXConstructorDecl, DefaultedCtorLocRange) { + RangeVerifier Verifier; + Verifier.expectRange(1, 11, 1, 23); + EXPECT_TRUE(Verifier.match("class C { C() = default; };", functionDecl())); +} + +TEST(CXXConstructorDecl, DeletedCtorLocRange) { + RangeVerifier Verifier; + Verifier.expectRange(1, 11, 1, 22); + EXPECT_TRUE(Verifier.match("class C { C() = delete; };", functionDecl())); +} + TEST(CompoundLiteralExpr, CompoundVectorLiteralRange) { RangeVerifier Verifier; Verifier.expectRange(2, 11, 2, 22);