[clang-tools-extra] ad9fd32 - [clangd] Fix SelectionTree behavior on constructor init-lists.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 15 08:32:25 PST 2019


Author: Sam McCall
Date: 2019-11-15T17:32:13+01:00
New Revision: ad9fd320091d44d4b8782c28b72a7be21a2bd68d

URL: https://github.com/llvm/llvm-project/commit/ad9fd320091d44d4b8782c28b72a7be21a2bd68d
DIFF: https://github.com/llvm/llvm-project/commit/ad9fd320091d44d4b8782c28b72a7be21a2bd68d.diff

LOG: [clangd] Fix SelectionTree behavior on constructor init-lists.

Summary:
For the constructor Foo() : classmember(arg) {}

The AST looks like:
 - CXXCtorInitializer  classmember(arg)
   - CXXConstructExpr  classmember(arg)
     - DeclRefExpr:                arg

We want the 'classmember' to be associated with the CXXCtorInitializer, not the
CXXConstructExpr. (CXXConstructExpr is known to have bad ranges).
So just early-claim it.

Thanks @hokein for tracking down/reducing the bug.

Reviewers: hokein

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits, hokein

Tags: #clang

Differential Revision: https://reviews.llvm.org/D70312

Added: 
    

Modified: 
    clang-tools-extra/clangd/Selection.cpp
    clang-tools-extra/clangd/unittests/SelectionTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index 1424825d82bc..04076df0c39d 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -10,6 +10,7 @@
 #include "Logger.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
@@ -397,6 +398,9 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
       // int (*[[s]])();
       else if (auto *VD = llvm::dyn_cast<VarDecl>(D))
         return VD->getLocation();
+    } else if (const auto* CCI = N.get<CXXCtorInitializer>()) {
+      // : [[b_]](42)
+      return CCI->getMemberLocation();
     }
     return SourceRange();
   }

diff  --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index 8895dd82262d..7b8b33d8a25b 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -246,6 +246,17 @@ TEST(SelectionTest, CommonAncestor) {
       // Tricky case: two VarDecls share a specifier.
       {"[[int ^a]], b;", "VarDecl"},
       {"[[int a, ^b]];", "VarDecl"},
+      // Tricky case: CXXConstructExpr wants to claim the whole init range.
+      {
+          R"cpp(
+            class X { X(int); };
+            class Y {
+              X x;
+              Y() : [[^x(4)]] {}
+            };
+          )cpp",
+          "CXXCtorInitializer", // Not the CXXConstructExpr!
+      },
       // Tricky case: anonymous struct is a sibling of the VarDecl.
       {"[[st^ruct {int x;}]] y;", "CXXRecordDecl"},
       {"[[struct {int x;} ^y]];", "VarDecl"},


        


More information about the cfe-commits mailing list