diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -17,6 +17,7 @@ #include "support/Trace.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Tooling/Syntax/Tokens.h" #include "llvm/ADT/None.h" @@ -141,10 +142,25 @@ return Candidate->getCanonicalDecl(); elog("FieldParent should have field with the same name as Field."); } + // This handles static fields - it's similar to FieldDecl handling above but + // the AST looks different for static fields (starting with the node type + // being VarDecl). if (const auto *VD = dyn_cast(D)) { if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember()) VD = OriginalVD; - return VD->getCanonicalDecl(); + VD = VD->getCanonicalDecl(); + const auto *Context = VD->getDeclContext()->getParent(); + // VarDecl is not instantiation of static field. + if (!dyn_cast_or_null( + VD->getDeclContext()) || + !Context || Context->getDeclKind() != Decl::Kind::CXXRecord) + return VD; + const auto LookupResult = Context->lookup(D->getDeclName()); + if (LookupResult.size() != 1) + return VD; + if (const auto *Result = dyn_cast(LookupResult.front())) + return Result->getCanonicalDecl(); + return VD; } return dyn_cast(D->getCanonicalDecl()); } 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 @@ -627,6 +627,30 @@ bool LocalBool = Foo::[[Var^iable]]; } )cpp", + R"cpp( + template struct Foo { static T Variable; }; + + template struct Foo { + static T [[Var^iable]]; + }; + + void test() { + Foo::[[Var^iable]] = 5; + } + )cpp", + R"cpp( + template struct Foo { + static T [[Var^iable]]; + }; + + template struct Foo { + static T Variable; + }; + + void test() { + Foo::[[Var^iable]] = 5; + } + )cpp", // Template parameters. R"cpp(