diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp --- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp @@ -288,11 +288,18 @@ if (Node == nullptr) return false; + // Closed range for the fully qualified name as spelled in source code. SourceRange SpelledNameRange; if (auto *D = Node->ASTNode.get()) { if (D->getDecl()->getIdentifier()) { QualifierToRemove = D->getQualifierLoc(); + // Use the name range rather than expr, as the latter can contain template + // arguments in the range. SpelledNameRange = D->getSourceRange(); + // Remove the template arguments from the name, as they shouldn't be + // spelled in the using declaration. + if (auto AngleLoc = D->getLAngleLoc(); AngleLoc.isValid()) + SpelledNameRange.setEnd(AngleLoc.getLocWithOffset(-1)); MustInsertAfterLoc = D->getDecl()->getBeginLoc(); } } else if (auto *T = Node->ASTNode.get()) { diff --git a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp --- a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp @@ -498,6 +498,30 @@ switch(one::two::ee{}) { case ee_one:break; } } )cpp"}, + {R"cpp( +#include "test.hpp" +void foo() { + one::f^unc_temp(); +})cpp", + R"cpp( +#include "test.hpp" +using one::func_temp; + +void foo() { + func_temp(); +})cpp"}, + {R"cpp( +#include "test.hpp" +void foo() { + one::va^r_temp; +})cpp", + R"cpp( +#include "test.hpp" +using one::var_temp; + +void foo() { + var_temp; +})cpp"}, }; llvm::StringMap EditedFiles; for (const auto &Case : Cases) { @@ -515,6 +539,8 @@ } using uu = two::cc; template struct vec {}; +template void func_temp(); +template T var_temp(); })cpp"; // Typo correction is disabled in msvc-compatibility mode. ExtraArgs.push_back("-fno-ms-compatibility");