[clangd] Include expression in DecltypeTypeLoc sourcerange while building SelectionTree
authorKadir Cetinkaya <kadircet@google.com>
Mon, 13 Jan 2020 11:09:30 +0000 (12:09 +0100)
committerKadir Cetinkaya <kadircet@google.com>
Mon, 13 Jan 2020 19:33:13 +0000 (20:33 +0100)
Summary:
Currently AST only contains the location for `decltype` keyword,
therefore we were skipping expressions inside decltype while building selection
tree.

This patch extends source range in such cases to contain the expression as well.
A proper fix would require changes to Sema and DecltypeTypeLoc to contain these
location information.

Fixes https://github.com/clangd/clangd/issues/250.

Reviewers: sammccall

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

Tags: #clang

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

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

index ffa48f3..14c05d1 100644 (file)
@@ -527,6 +527,19 @@ private:
   // don't intersect the selection may be recursively skipped.
   bool canSafelySkipNode(const DynTypedNode &N) {
     SourceRange S = N.getSourceRange();
+    if (auto *TL = N.get<TypeLoc>()) {
+      // DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to
+      // failing
+      // to descend into the child expression.
+      // decltype(2+2);
+      // ~~~~~~~~~~~~~ <-- correct range
+      // ~~~~~~~~      <-- range reported by getSourceRange()
+      // ~~~~~~~~~~~~  <-- range with this hack(i.e, missing closing paren)
+      // FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get
+      // rid of this patch.
+      if (auto DT = TL->getAs<DecltypeTypeLoc>())
+        S.setEnd(DT.getUnderlyingExpr()->getEndLoc());
+    }
     if (!SelChecker.mayHit(S)) {
       dlog("{1}skip: {0}", printNodeToString(N, PrintPolicy), indent());
       dlog("{1}skipped range = {0}", S.printToString(SM), indent(1));
index 9e1a90b..581309b 100644 (file)
@@ -323,6 +323,12 @@ TEST(SelectionTest, CommonAncestor) {
             Foo x = [[^12_ud]];
           )cpp",
           "UserDefinedLiteral"},
+      {
+          R"cpp(
+        int a;
+        decltype([[^a]] + a) b;
+        )cpp",
+          "DeclRefExpr"},
   };
   for (const Case &C : Cases) {
     Annotations Test(C.Code);