[clang-tools-extra] r258562 - [clang-tidy] Handle decayed types and other improvements in VirtualNearMiss check.

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 22 13:45:51 PST 2016


Author: xazax
Date: Fri Jan 22 15:45:51 2016
New Revision: 258562

URL: http://llvm.org/viewvc/llvm-project?rev=258562&view=rev
Log:
[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 

Modified:
    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

Modified: clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp?rev=258562&r1=258561&r2=258562&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.cpp Fri Jan 22 15:45:51 2016
@@ -45,31 +45,20 @@ static bool checkOverridingFunctionRetur
     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 checkOverridingFunctionRetur
   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 CXXMet
     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 CXXMet
 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::isPossibleToB
     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::registerMatch
   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();

Modified: clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h?rev=258562&r1=258561&r2=258562&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/VirtualNearMissCheck.h Fri Jan 22 15:45:51 2016
@@ -34,7 +34,7 @@ public:
 
 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);

Modified: clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp?rev=258562&r1=258561&r2=258562&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-virtual-near-miss.cpp Fri Jan 22 15:45:51 2016
@@ -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 @@ struct Derived : Base {
 
   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 @@ public:
   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 @@ public:
 
   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 @@ public:
   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'
 };




More information about the cfe-commits mailing list