diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -106,20 +106,22 @@ this); Finder->addMatcher(typeLoc().bind("typeLoc"), this); Finder->addMatcher(nestedNameSpecifierLoc().bind("nestedNameLoc"), this); + auto MemberOrDependent = + expr(eachOf(memberExpr().bind("memberExpr"), + cxxDependentScopeMemberExpr().bind("depMemberExpr"))); Finder->addMatcher( functionDecl(unless(cxxMethodDecl(isImplicit())), - hasBody(forEachDescendant(memberExpr().bind("memberExpr")))), + hasBody(forEachDescendant(MemberOrDependent))), this); Finder->addMatcher( - cxxConstructorDecl( - unless(isImplicit()), - forEachConstructorInitializer( - allOf(isWritten(), withInitializer(forEachDescendant( - memberExpr().bind("memberExpr")))))), + cxxConstructorDecl(unless(isImplicit()), + forEachConstructorInitializer(allOf( + isWritten(), withInitializer(forEachDescendant( + MemberOrDependent))))), + this); + Finder->addMatcher( + fieldDecl(hasInClassInitializer(forEachDescendant(MemberOrDependent))), this); - Finder->addMatcher(fieldDecl(hasInClassInitializer( - forEachDescendant(memberExpr().bind("memberExpr")))), - this); } void RenamerClangTidyCheck::registerPPCallbacks( @@ -271,6 +273,29 @@ return; } + if (const auto *DepMemberRef = + Result.Nodes.getNodeAs( + "depMemberExpr")) { + QualType BaseType = DepMemberRef->isArrow() + ? DepMemberRef->getBaseType()->getPointeeType() + : DepMemberRef->getBaseType(); + CXXRecordDecl *Base = BaseType.getTypePtr()->getAsCXXRecordDecl(); + if (!Base) + return; + StringRef DependentName = DepMemberRef->getMemberNameInfo() + .getName() + .getAsIdentifierInfo() + ->getName(); + for (const FieldDecl *Field : Base->fields()) { + if (Field->getParent() == Base && + Field->getName().equals(DependentName)) { + SourceRange Range = DepMemberRef->getMemberNameInfo().getSourceRange(); + addUsage(NamingCheckFailures, Field, Range, Result.SourceManager); + break; + } + } + } + if (const auto *Decl = Result.Nodes.getNodeAs("decl")) { if (!Decl->getIdentifier() || Decl->getName().empty() || Decl->isImplicit()) return; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -91,6 +91,11 @@ Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Improved :doc:'readability-identifier-naming + ` check. + + Now able to rename member references in class template definitions with + explicit access. Renamed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-member-decl-usage.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-member-decl-usage.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-member-decl-usage.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-member-decl-usage.cpp @@ -134,4 +134,58 @@ void foo() { Container container; } -}; // namespace CtorInits +} // namespace CtorInits + +namespace resolved_dependance { +template +class A0 { + int value; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for member 'value' + A0 &operator=(const A0 &Other) { + value = Other.value; // A0 + this->value = Other.value; // A0 + // CHECK-FIXES: {{^}} Value = Other.Value; // A0 + // CHECK-FIXES-NEXT: {{^}} this->Value = Other.Value; // A0 + return *this; + } +}; + +template +class A1 { + int value; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for member 'value' + A1 &operator=(const A1 &Other) { + value = Other.value; // A1 + this->value = Other.value; // A1 + // CHECK-FIXES: {{^}} Value = Other.Value; // A1 + // CHECK-FIXES-NEXT: {{^}} this->Value = Other.Value; // A1 + return *this; + } +}; +//create some instances to check it works +A1 AInt{}; +A1 BInt = AInt; +A1 AUnsigned{}; +A1 BUnsigned = AUnsigned; +} //namespace resolved_dependance + +namespace unresolved_dependance { +template +struct DependentBase { + int depValue; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for member 'depValue' +}; + +template +struct Derived : DependentBase { + Derived &operator=(const Derived &Other) { + this->depValue = Other.depValue; + // CHECK-FIXES-NOT: {{^}} this->DepValue = Other.DepValue; + return *this; + } +}; + +Derived AInt{}; +Derived BInt = AInt; + +} //namespace unresolved_dependance