diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h --- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -122,6 +122,17 @@ return BaseType::TraverseNestedNameSpecifierLoc(NNS); } + bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { + for (const DesignatedInitExpr::Designator &D : E->designators()) { + if (D.isFieldDesignator() && D.getField()) { + const FieldDecl *Decl = D.getField(); + if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc())) + return false; + } + } + return true; + } + private: const SourceManager &SM; const LangOptions &LangOpts; diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp --- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp @@ -226,6 +226,24 @@ return true; } + bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { + for (const DesignatedInitExpr::Designator &D : E->designators()) { + if (D.isFieldDesignator() && D.getField()) { + const FieldDecl *Decl = D.getField(); + if (isInUSRSet(Decl)) { + auto StartLoc = D.getFieldLoc(); + auto EndLoc = D.getFieldLoc(); + RenameInfos.push_back({StartLoc, EndLoc, + /*FromDecl=*/nullptr, + /*Context=*/nullptr, + /*Specifier=*/nullptr, + /*IgnorePrefixQualifiers=*/true}); + } + } + } + return true; + } + bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { // Fix the constructor initializer when renaming class members. for (const auto *Initializer : CD->inits()) { diff --git a/clang/unittests/Rename/RenameClassTest.cpp b/clang/unittests/Rename/RenameClassTest.cpp --- a/clang/unittests/Rename/RenameClassTest.cpp +++ b/clang/unittests/Rename/RenameClassTest.cpp @@ -780,6 +780,27 @@ CompareSnippets(Expected, After); } +TEST_F(ClangRenameTest, FieldDesignatedInitializers) { + std::string Before = R"( + struct S { + int a; + }; + void foo() { + S s = { .a = 10 }; + s.a = 20; + })"; + std::string Expected = R"( + struct S { + int b; + }; + void foo() { + S s = { .b = 10 }; + s.b = 20; + })"; + std::string After = runClangRenameOnCode(Before, "S::a", "S::b"); + CompareSnippets(Expected, After); +} + // FIXME: investigate why the test fails when adding a new USR to the USRSet. TEST_F(ClangRenameTest, DISABLED_NestedTemplates) { std::string Before = R"(