This revision was automatically updated to reflect the committed changes.
Closed by commit rL259197: Fixed function params comparison. Updated docs and
tests. (authored by alexfh).
Changed prior to commit:
http://reviews.llvm.org/D16587?vs=46360&id=46382#toc
Repository:
rL LLVM
http://reviews.llvm.org/D16587
Files:
clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/misc-virtual-near-miss.rst
clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
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
@@ -19,6 +19,12 @@
namespace tidy {
namespace misc {
+AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
+
+AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
+ return Node.isOverloadedOperator();
+}
+
/// Finds out if the given method overrides some method.
static bool isOverrideMethod(const CXXMethodDecl *MD) {
return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
@@ -32,10 +38,14 @@
static bool checkOverridingFunctionReturnType(const ASTContext *Context,
const CXXMethodDecl *BaseMD,
const CXXMethodDecl *DerivedMD) {
- QualType BaseReturnTy =
- BaseMD->getType()->getAs<FunctionType>()->getReturnType();
- QualType DerivedReturnTy =
- DerivedMD->getType()->getAs<FunctionType>()->getReturnType();
+ QualType BaseReturnTy = BaseMD->getType()
+ ->getAs<FunctionType>()
+ ->getReturnType()
+ .getCanonicalType();
+ QualType DerivedReturnTy = DerivedMD->getType()
+ ->getAs<FunctionType>()
+ ->getReturnType()
+ .getCanonicalType();
if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
return false;
@@ -54,8 +64,8 @@
/// 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();
+ QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
+ QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();
const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
@@ -81,7 +91,8 @@
// Check accessibility.
// FIXME: We currently only support checking if B is accessible base class
// of D, or D is the same class which DerivedMD is in.
- bool IsItself = DRD == DerivedMD->getParent();
+ bool IsItself =
+ DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
bool HasPublicAccess = false;
for (const auto &Path : Paths) {
if (Path.Access == AS_public)
@@ -121,8 +132,9 @@
return false;
for (unsigned I = 0; I < NumParamA; I++) {
- if (getDecayedType(BaseMD->getParamDecl(I)->getType()) !=
- getDecayedType(DerivedMD->getParamDecl(I)->getType()))
+ if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
+ getDecayedType(
+ DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
return false;
}
return true;
@@ -152,42 +164,35 @@
/// DerivedMD is in.
static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
const CXXMethodDecl *DerivedMD) {
- if (BaseMD->getNameAsString() != DerivedMD->getNameAsString())
- return false;
-
- if (!checkParamTypes(BaseMD, DerivedMD))
- return false;
-
- return true;
-}
+ for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
+ E = DerivedMD->end_overridden_methods();
+ I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+ if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl()) {
+ return true;
+ }
+ }
-/// Generate unique ID for given MethodDecl.
-///
-/// The Id is used as key for 'PossibleMap'.
-/// Typical Id: "Base::func void (void)"
-static std::string generateMethodId(const CXXMethodDecl *MD) {
- return MD->getQualifiedNameAsString() + " " + MD->getType().getAsString();
+ return false;
}
bool VirtualNearMissCheck::isPossibleToBeOverridden(
const CXXMethodDecl *BaseMD) {
- std::string Id = generateMethodId(BaseMD);
- auto Iter = PossibleMap.find(Id);
+ auto Iter = PossibleMap.find(BaseMD);
if (Iter != PossibleMap.end())
return Iter->second;
bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
!isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
!BaseMD->isOverloadedOperator() &&
!isa<CXXConversionDecl>(BaseMD);
- PossibleMap[Id] = IsPossible;
+ PossibleMap[BaseMD] = IsPossible;
return IsPossible;
}
bool VirtualNearMissCheck::isOverriddenByDerivedClass(
const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
- auto Key = std::make_pair(generateMethodId(BaseMD),
- DerivedRD->getQualifiedNameAsString());
+ auto Key = std::make_pair(BaseMD, DerivedRD);
auto Iter = OverriddenMap.find(Key);
if (Iter != OverriddenMap.end())
return Iter->second;
@@ -213,24 +218,20 @@
Finder->addMatcher(
cxxMethodDecl(
unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
- cxxDestructorDecl(), cxxConversionDecl())))
+ cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
+ isOverloadedOperator())))
.bind("method"),
this);
}
void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
assert(DerivedMD);
- if (DerivedMD->isStatic())
- return;
-
- if (DerivedMD->isOverloadedOperator())
- return;
-
const ASTContext *Context = Result.Context;
- const auto *DerivedRD = DerivedMD->getParent();
+ const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
+ assert(DerivedRD);
for (const auto &BaseSpec : DerivedRD->bases()) {
if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
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
@@ -48,12 +48,13 @@
/// key: the unique ID of a method;
/// value: whether the method is possible to be overridden.
- std::map<std::string, bool> PossibleMap;
+ std::map<const CXXMethodDecl *, bool> PossibleMap;
/// key: <unique ID of base method, name of derived class>
/// value: whether the base method is overridden by some method in the derived
/// class.
- std::map<std::pair<std::string, std::string>, bool> OverriddenMap;
+ std::map<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
+ OverriddenMap;
const unsigned EditDistanceThreshold = 1;
};
Index: clang-tools-extra/trunk/docs/clang-tidy/checks/misc-virtual-near-miss.rst
===================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/misc-virtual-near-miss.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/misc-virtual-near-miss.rst
@@ -13,5 +13,5 @@
struct Derived : Base {
virtual funk();
- // warning: Do you want to override 'func'?
+ // warning: 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it?
};
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
@@ -26,12 +26,15 @@
Derived &operator==(const Base &); // Should not warn: operators are ignored.
};
+typedef Derived derived_type;
+
class Father {
public:
Father();
virtual void func();
virtual Father *create(int i);
virtual Base &&generate();
+ virtual Base *canonical(Derived D);
};
class Mother {
@@ -70,6 +73,10 @@
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::decaz' has {{.*}} 'Mother::decay'
operator bool();
+
+ derived_type *canonica(derived_type D);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: method 'Child::canonica' has {{.*}} 'Father::canonical'
+
private:
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