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 @@ -76,6 +76,10 @@ ? getSourceRange(DynTypedNode::create(*ME->getBase())) : SourceRange(); } + if (const auto *TL = N.get()) { + if (const auto ATL = TL->getAs()) + return ATL.getBracketsRange(); + } return N.getSourceRange(); } @@ -510,6 +514,7 @@ bool TraverseTypeLoc(TypeLoc X) { return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); } + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) { return traverseNode(&X, [&] { return Base::TraverseTemplateArgumentLoc(X); }); @@ -661,6 +666,9 @@ // type's range. if (auto AT = TL->getAs()) S = AT.getModifiedLoc().getSourceRange(); + + if (auto AT = TL->getAs()) + S = AT.getSourceRange(); } // SourceRange often doesn't manage to accurately cover attributes. // Fortunately, attributes are rare. 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 @@ -318,6 +318,13 @@ {"[[st^ruct {int x;}]] y;", "CXXRecordDecl"}, {"[[struct {int x;} ^y]];", "VarDecl"}, {"struct {[[int ^x]];} y;", "FieldDecl"}, + + // Tricky case: nested ConstantArrayTypeLocs have the same token range. + {"const int x = 1, y = 2; int array[^[[x]]][10][y];", "DeclRefExpr"}, + {"const int x = 1, y = 2; int array[x][10][^[[y]]];", "DeclRefExpr"}, + {"const int x = 1, y = 2; int array[x][^[[10]]][y];", "IntegerLiteral"}, + {"const int x = 1, y = 2; [[i^nt]] array[x][10][y];", "BuiltinTypeLoc"}, + // FIXME: the AST has no location info for qualifiers. {"const [[a^uto]] x = 42;", "AutoTypeLoc"}, {"[[co^nst auto x = 42]];", "VarDecl"},