diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -527,6 +527,16 @@ // don't intersect the selection may be recursively skipped. bool canSafelySkipNode(const DynTypedNode &N) { SourceRange S = N.getSourceRange(); + if (auto *TL = N.get()) { + // DecltypeTypeLoc only contains the SourceRange for `decltype` keyword. + // We are extending the SourceRange up until the end of the expression + // inside decltype. Note that this will not include the closing + // parenthese. + // FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get + // rid of this patch. + if (auto DT = TL->getAs()) + 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)); diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -323,6 +323,12 @@ 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);