diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp b/clang/lib/Tooling/Transformer/RangeSelector.cpp --- a/clang/lib/Tooling/Transformer/RangeSelector.cpp +++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp @@ -232,9 +232,12 @@ 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(), + 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 --- a/clang/unittests/Tooling/RangeSelectorTest.cpp +++ b/clang/unittests/Tooling/RangeSelectorTest.cpp @@ -486,6 +486,22 @@ EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("Foo")); } +TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) { + StringRef Code = R"cc( + namespace ns { + template + struct Foo { T x; }; + } // 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()));