diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp b/clang/lib/Tooling/Transformer/RangeSelector.cpp index 753e89e0e1f33..7370baf010834 100644 --- a/clang/lib/Tooling/Transformer/RangeSelector.cpp +++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp @@ -232,9 +232,11 @@ RangeSelector transformer::name(std::string ID) { if (const auto *T = Node.get()) { TypeLoc Loc = *T; auto ET = Loc.getAs(); - if (!ET.isNull()) { + if (!ET.isNull()) Loc = ET.getNamedTypeLoc(); - } + if (auto SpecLoc = Loc.getAs(); + !SpecLoc.isNull()) + return CharSourceRange::getTokenRange(SpecLoc.getTemplateNameLoc()); return CharSourceRange::getTokenRange(Loc.getSourceRange()); } return typeError(ID, Node.getNodeKind(), diff --git a/clang/unittests/Tooling/RangeSelectorTest.cpp b/clang/unittests/Tooling/RangeSelectorTest.cpp index a7fea004c3d3b..cbb8e25bb92f2 100644 --- a/clang/unittests/Tooling/RangeSelectorTest.cpp +++ b/clang/unittests/Tooling/RangeSelectorTest.cpp @@ -486,6 +486,22 @@ TEST(RangeSelectorTest, NameOpTypeLoc) { EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("Foo")); } +TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) { + StringRef Code = R"cc( + namespace ns { + template + struct Foo {}; + } // namespace ns + + ns::Foo a; + )cc"; + const char *Loc = "tyloc"; + // Matches declaration of `a`. + TestMatch MatchA = + matchCode(Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc)))); + EXPECT_THAT_EXPECTED(select(name(Loc), MatchA), HasValue("Foo")); +} + TEST(RangeSelectorTest, NameOpErrors) { EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")), Failed(withUnboundNodeMessage()));