From 9a4b574dd6a07d6811356529ebb8a3f15d6e40a2 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 29 Dec 2020 13:18:57 +0000 Subject: [PATCH] [clang-itdy] Simplify virtual near-miss check Diagnose the problem in templates in the context of the template declaration instead of in the context of all of the (possibly very many) template instantiations. Differential Revision: https://reviews.llvm.org/D96224 --- .../clang-tidy/bugprone/VirtualNearMissCheck.cpp | 31 ++++++++++++---------- .../clang-tidy/bugprone/VirtualNearMissCheck.h | 3 +++ .../checkers/bugprone-virtual-near-miss.cpp | 5 ++-- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp index 150b517..dc810c6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp @@ -216,10 +216,9 @@ bool VirtualNearMissCheck::isOverriddenByDerivedClass( void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxMethodDecl( - unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(), - cxxDestructorDecl(), cxxConversionDecl(), isStatic(), - isOverloadedOperator()))) + cxxMethodDecl(unless(anyOf(isOverride(), cxxConstructorDecl(), + cxxDestructorDecl(), cxxConversionDecl(), + isStatic(), isOverloadedOperator()))) .bind("method"), this); } @@ -234,7 +233,15 @@ void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) { assert(DerivedRD); for (const auto &BaseSpec : DerivedRD->bases()) { - if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) { + const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl(); + if (const auto *TST = + dyn_cast(BaseSpec.getType())) { + auto TN = TST->getTemplateName(); + BaseRD = + dyn_cast(TN.getAsTemplateDecl()->getTemplatedDecl()); + } + + if (BaseRD) { for (const auto *BaseMD : BaseRD->methods()) { if (!isPossibleToBeOverridden(BaseMD)) continue; @@ -250,16 +257,12 @@ void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) { auto Range = CharSourceRange::getTokenRange( SourceRange(DerivedMD->getLocation())); - bool ApplyFix = !BaseMD->isTemplateInstantiation() && - !DerivedMD->isTemplateInstantiation(); - auto Diag = - diag(DerivedMD->getBeginLoc(), - "method '%0' has a similar name and the same signature as " - "virtual method '%1'; did you mean to override it?") + diag(DerivedMD->getBeginLoc(), + "method '%0' has a similar name and the same signature as " + "virtual method '%1'; did you mean to override it?") << DerivedMD->getQualifiedNameAsString() - << BaseMD->getQualifiedNameAsString(); - if (ApplyFix) - Diag << FixItHint::CreateReplacement(Range, BaseMD->getName()); + << BaseMD->getQualifiedNameAsString() + << FixItHint::CreateReplacement(Range, BaseMD->getName()); } } } diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h index 69ae278..ec90251 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h @@ -32,6 +32,9 @@ public: } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + llvm::Optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } private: /// Check if the given method is possible to be overridden by some other diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-virtual-near-miss.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-virtual-near-miss.cpp index 553d2f4..f3f8d32 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-virtual-near-miss.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-virtual-near-miss.cpp @@ -44,9 +44,8 @@ template struct TDerived : TBase { virtual void tfunk(T t); // Should not apply fix for template. - // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: method 'TDerived::tfunk' has {{.*}} 'TBase::tfunc' - // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: method 'TDerived::tfunk' has {{.*}} 'TBase::tfunc' - // CHECK-FIXES: virtual void tfunk(T t); + // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: method 'TDerived::tfunk' has {{.*}} 'TBase::tfunc' + // CHECK-FIXES: virtual void tfunc(T t); }; TDerived T1; -- 2.7.4