diff options
| author | Gabor Horvath <xazax.hun@gmail.com> | 2016-01-22 21:45:51 +0000 |
|---|---|---|
| committer | Gabor Horvath <xazax.hun@gmail.com> | 2016-01-22 21:45:51 +0000 |
| commit | 93bc576ec96d15001e46c8c282e1377694d934ab (patch) | |
| tree | bb97882da37f74ee8fd9cfd6750e2142a6638786 /clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp | |
| parent | 72d0d89b5955e43372bfc3289ab91c1fa4ded807 (diff) | |
| download | bcm5719-llvm-93bc576ec96d15001e46c8c282e1377694d934ab.tar.gz bcm5719-llvm-93bc576ec96d15001e46c8c282e1377694d934ab.zip | |
[clang-tidy] Handle decayed types and other improvements in VirtualNearMiss check.
Handle decayed types, ignore qualifiers and accessibility when considering a
method as a possible overload.
Differential Revision: http://reviews.llvm.org/D16179
llvm-svn: 258562
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp | 65 |
1 files changed, 30 insertions, 35 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp index def63ce1882..ba4655b16a8 100644 --- a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp @@ -45,31 +45,20 @@ static bool checkOverridingFunctionReturnType(const ASTContext *Context, return true; /// Check if the return types are covariant. - /// BTy is the class type in return type of BaseMD. For example, - /// B* Base::md() - /// While BRD is the declaration of B. - QualType BTy, DTy; - const CXXRecordDecl *BRD, *DRD; // Both types must be pointers or references to classes. - if (const auto *DerivedPT = DerivedReturnTy->getAs<PointerType>()) { - if (const auto *BasePT = BaseReturnTy->getAs<PointerType>()) { - DTy = DerivedPT->getPointeeType(); - BTy = BasePT->getPointeeType(); - } - } else if (const auto *DerivedRT = DerivedReturnTy->getAs<ReferenceType>()) { - if (const auto *BaseRT = BaseReturnTy->getAs<ReferenceType>()) { - DTy = DerivedRT->getPointeeType(); - BTy = BaseRT->getPointeeType(); - } - } - - // The return types aren't either both pointers or references to a class type. - if (DTy.isNull()) + if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) && + !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType())) return false; - DRD = DTy->getAsCXXRecordDecl(); - BRD = BTy->getAsCXXRecordDecl(); + /// BTy is the class type in return type of BaseMD. For example, + /// B* Base::md() + /// While BRD is the declaration of B. + QualType DTy = DerivedReturnTy->getPointeeType(); + QualType BTy = BaseReturnTy->getPointeeType(); + + const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl(); + const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl(); if (DRD == nullptr || BRD == nullptr) return false; @@ -116,6 +105,13 @@ static bool checkOverridingFunctionReturnType(const ASTContext *Context, return true; } +/// \returns decayed type for arrays and functions. +static QualType getDecayedType(QualType Type) { + if (const auto *Decayed = Type->getAs<DecayedType>()) + return Decayed->getDecayedType(); + return Type; +} + /// \returns true if the param types are the same. static bool checkParamTypes(const CXXMethodDecl *BaseMD, const CXXMethodDecl *DerivedMD) { @@ -125,8 +121,8 @@ static bool checkParamTypes(const CXXMethodDecl *BaseMD, return false; for (unsigned I = 0; I < NumParamA; I++) { - if (BaseMD->getParamDecl(I)->getType() != - DerivedMD->getParamDecl(I)->getType()) + if (getDecayedType(BaseMD->getParamDecl(I)->getType()) != + getDecayedType(DerivedMD->getParamDecl(I)->getType())) return false; } return true; @@ -137,15 +133,9 @@ static bool checkParamTypes(const CXXMethodDecl *BaseMD, static bool checkOverrideWithoutName(const ASTContext *Context, const CXXMethodDecl *BaseMD, const CXXMethodDecl *DerivedMD) { - if (BaseMD->getTypeQualifiers() != DerivedMD->getTypeQualifiers()) - return false; - if (BaseMD->isStatic() != DerivedMD->isStatic()) return false; - if (BaseMD->getAccess() != DerivedMD->getAccess()) - return false; - if (BaseMD->getType() == DerivedMD->getType()) return true; @@ -187,7 +177,8 @@ bool VirtualNearMissCheck::isPossibleToBeOverridden( return Iter->second; bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) && - BaseMD->isVirtual(); + !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() && + !BaseMD->isOverloadedOperator(); PossibleMap[Id] = IsPossible; return IsPossible; } @@ -218,19 +209,23 @@ void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; - Finder->addMatcher(cxxMethodDecl(unless(anyOf(isOverride(), isImplicit(), - cxxConstructorDecl()))) - .bind("method"), - this); + Finder->addMatcher( + cxxMethodDecl(unless(anyOf(isOverride(), isImplicit(), + cxxConstructorDecl(), cxxDestructorDecl()))) + .bind("method"), + this); } void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) { const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method"); - assert(DerivedMD != nullptr); + assert(DerivedMD); if (DerivedMD->isStatic()) return; + if (DerivedMD->isOverloadedOperator()) + return; + const ASTContext *Context = Result.Context; const auto *DerivedRD = DerivedMD->getParent(); |

