This revision was automatically updated to reflect the committed changes.
Closed by commit rL258562: [clang-tidy] Handle decayed types and other
improvements in VirtualNearMiss… (authored by xazax).
Changed prior to commit:
http://reviews.llvm.org/D16179?vs=45482&id=45739#toc
Repository:
rL LLVM
http://reviews.llvm.org/D16179
Files:
clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
Index: clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
===================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
+++ clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
@@ -34,7 +34,7 @@
private:
/// Check if the given method is possible to be overridden by some other
- /// method.
+ /// method. Operators and destructors are excluded.
///
/// Results are memoized in PossibleMap.
bool isPossibleToBeOverridden(const CXXMethodDecl *BaseMD);
Index: clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
===================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
@@ -45,31 +45,20 @@
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 @@
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 @@
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 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 @@
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 @@
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();
Index: clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
@@ -3,6 +3,8 @@
struct Base {
virtual void func();
virtual void gunk();
+ virtual ~Base();
+ virtual Base &operator=(const Base &);
};
struct Derived : Base {
@@ -20,6 +22,8 @@
void fun();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Derived::fun' has {{.*}} 'Base::func'
+
+ Derived &operator==(const Base &); // Should not warn: operators are ignored.
};
class Father {
@@ -36,6 +40,7 @@
static void method();
virtual int method(int argc, const char **argv);
virtual int method(int argc) const;
+ virtual int decay(const char *str);
};
class Child : private Father, private Mother {
@@ -47,7 +52,8 @@
int methoe(int x, char **strs); // Should not warn: parameter types don't match.
- int methoe(int x); // Should not warn: method is not const.
+ int methoe(int x);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::methoe' has {{.*}} 'Mother::method'
void methof(int x, const char **strs); // Should not warn: return types don't match.
@@ -60,6 +66,10 @@
virtual Derived &&generat();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::generat' has {{.*}} 'Father::generate'
+ int decaz(const char str[]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::decaz' has {{.*}} 'Mother::decay'
+
private:
- void funk(); // Should not warn: access qualifers don't match.
+ void funk();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::funk' has {{.*}} 'Father::func'
};
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits