diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -137,6 +137,17 @@ }; )cpp", + // Rename template class constructor. + R"cpp( + class [[F^oo]] { + template + [[Fo^o]](); + + template + [[F^oo]](T t); + }; + )cpp", + // Class in template argument. R"cpp( class [[F^oo]] {}; diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp --- a/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp @@ -135,6 +135,13 @@ for (const auto *CtorDecl : RecordDecl->ctors()) USRSet.insert(getUSRForDecl(CtorDecl)); + // Add template constructor decls, they are not in ctors() unfortunately. + if (RecordDecl->hasUserDeclaredConstructor()) + for (const auto *D : RecordDecl->decls()) + if (const auto *FTD = dyn_cast(D)) + if (const auto *Ctor = + dyn_cast(FTD->getTemplatedDecl())) + USRSet.insert(getUSRForDecl(Ctor)); USRSet.insert(getUSRForDecl(RecordDecl->getDestructor())); USRSet.insert(getUSRForDecl(RecordDecl)); diff --git a/clang/test/clang-rename/Ctor.cpp b/clang/test/clang-rename/Ctor.cpp --- a/clang/test/clang-rename/Ctor.cpp +++ b/clang/test/clang-rename/Ctor.cpp @@ -5,10 +5,23 @@ Foo::Foo() /* Test 2 */ {} // CHECK: Bar::Bar() /* Test 2 */ {} + +class Foo2 { /* Test 3 */ // CHECK: class Bar2 { +public: + template + Foo2(); // CHECK: Bar2(); + + template + Foo2(Foo2 &); // CHECK: Bar2(Bar2 &); +}; + + // Test 1. // RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. // RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 3. +// RUN: clang-rename -offset=187 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*'