Hi rnk, jpienaar,

Fixes https://llvm.org/bugs/show_bug.cgi?id=20744

struct A {                                                                      
                                                      
  A() = default;
};

Previously the source range of the declaration of A ended at the ')'. It should 
include the '= default' part as well. The same for '= delete'.

Note: this will break one of the clang-tidy fixers, which is going to be 
addessed in a follow-up patch.

http://reviews.llvm.org/D8465

Files:
  lib/Parse/ParseDeclCXX.cpp
  test/Analysis/inlining/path-notes.cpp
  test/Misc/ast-dump-decl.cpp
  unittests/AST/SourceLocationTest.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
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<FunctionDecl>(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:          <array>
 // CHECK-NEXT:           <dict>
 // CHECK-NEXT:            <key>line</key><integer>105</integer>
-// CHECK-NEXT:            <key>col</key><integer>53</integer>
+// CHECK-NEXT:            <key>col</key><integer>63</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:           <dict>
 // CHECK-NEXT:            <key>line</key><integer>105</integer>
-// CHECK-NEXT:            <key>col</key><integer>53</integer>
+// CHECK-NEXT:            <key>col</key><integer>63</integer>
 // CHECK-NEXT:            <key>file</key><integer>0</integer>
 // CHECK-NEXT:           </dict>
 // CHECK-NEXT:          </array>
@@ -2475,20 +2475,20 @@
 // CHECK-NEXT:      <key>location</key>
 // CHECK-NEXT:      <dict>
 // CHECK-NEXT:       <key>line</key><integer>105</integer>
-// CHECK-NEXT:       <key>col</key><integer>53</integer>
+// CHECK-NEXT:       <key>col</key><integer>63</integer>
 // CHECK-NEXT:       <key>file</key><integer>0</integer>
 // CHECK-NEXT:      </dict>
 // CHECK-NEXT:      <key>ranges</key>
 // CHECK-NEXT:      <array>
 // CHECK-NEXT:        <array>
 // CHECK-NEXT:         <dict>
 // CHECK-NEXT:          <key>line</key><integer>105</integer>
-// CHECK-NEXT:          <key>col</key><integer>53</integer>
+// CHECK-NEXT:          <key>col</key><integer>63</integer>
 // CHECK-NEXT:          <key>file</key><integer>0</integer>
 // CHECK-NEXT:         </dict>
 // CHECK-NEXT:         <dict>
 // CHECK-NEXT:          <key>line</key><integer>105</integer>
-// CHECK-NEXT:          <key>col</key><integer>53</integer>
+// CHECK-NEXT:          <key>col</key><integer>63</integer>
 // CHECK-NEXT:          <key>file</key><integer>0</integer>
 // CHECK-NEXT:         </dict>
 // CHECK-NEXT:        </array>
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<TestMemberRanges &&>(B);
   TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
 }
-// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:20>
-// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:49>
-// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:44>
-// CHECK:      CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:21>
-// CHECK:      CXXMethodDecl{{.*}} <line:{{.*}}:3, col:60>
-// CHECK:      CXXMethodDecl{{.*}} <line:{{.*}}:3, col:55>
+// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>
+// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>
+// CHECK:      CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>
+// CHECK:      CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>
+// CHECK:      CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>
+// CHECK:      CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>
 
 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<CXXConstructorDecl> Verifier;
+  Verifier.expectRange(1, 11, 1, 23);
+  EXPECT_TRUE(Verifier.match("class C { C() = default; };", functionDecl()));
+}
+
+TEST(CXXConstructorDecl, DeletedCtorLocRange) {
+  RangeVerifier<CXXConstructorDecl> Verifier;
+  Verifier.expectRange(1, 11, 1, 22);
+  EXPECT_TRUE(Verifier.match("class C { C() = delete; };", functionDecl()));
+}
+
 TEST(CompoundLiteralExpr, CompoundVectorLiteralRange) {
   RangeVerifier<CompoundLiteralExpr> Verifier;
   Verifier.expectRange(2, 11, 2, 22);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to