summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp81
-rw-r--r--clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp4
2 files changed, 43 insertions, 42 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
index c62ba86f6bc..8f40dc671f1 100644
--- a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp
@@ -98,32 +98,30 @@ bool areCorrespondingOverloads(const FunctionDecl *LHS,
return RHS->getOverloadedOperator() == getCorrespondingOverload(LHS);
}
-bool hasCorrespondingOverloadInOneClass(const CXXRecordDecl *RD,
- const CXXMethodDecl *MD) {
- // Check the methods in the given class and accessible to derived classes.
- for (const auto *BMD : RD->methods())
- if (BMD->isOverloadedOperator() && BMD->getAccess() != AS_private &&
- areCorrespondingOverloads(MD, BMD))
- return true;
-
- // Check base classes.
- for (const auto &BS : RD->bases())
- if (hasCorrespondingOverloadInOneClass(BS.getType()->getAsCXXRecordDecl(),
- MD))
- return true;
+bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
+ const CXXRecordDecl *RD = nullptr) {
+ if (RD) {
+ // Check the methods in the given class and accessible to derived classes.
+ for (const auto *BMD : RD->methods())
+ if (BMD->isOverloadedOperator() && BMD->getAccess() != AS_private &&
+ areCorrespondingOverloads(MD, BMD))
+ return true;
+ } else {
+ // Get the parent class of the method; we do not need to care about checking
+ // the methods in this class as the caller has already done that by looking
+ // at the declaration contexts.
+ RD = MD->getParent();
+ }
- return false;
-}
-bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD) {
- // Get the parent class of the method; we do not need to care about checking
- // the methods in this class as the caller has already done that by looking
- // at the declaration contexts.
- const CXXRecordDecl *RD = MD->getParent();
-
- for (const auto &BS : RD->bases())
- if (hasCorrespondingOverloadInOneClass(BS.getType()->getAsCXXRecordDecl(),
- MD))
+ for (const auto &BS : RD->bases()) {
+ // We can't say much about a dependent base class, but to avoid false
+ // positives assume it can have a corresponding overload.
+ if (BS.getType()->isDependentType())
return true;
+ if (const auto *BaseRD = BS.getType()->getAsCXXRecordDecl())
+ if (hasCorrespondingOverloadInBaseClass(MD, BaseRD))
+ return true;
+ }
return false;
}
@@ -174,24 +172,23 @@ void NewDeleteOverloadsCheck::onEndOfTranslationUnit() {
// to shard the overloads by declaration context to reduce the algorithmic
// complexity when searching for corresponding free store functions.
for (const auto *Overload : RP.second) {
- const auto *Match = std::find_if(
- RP.second.begin(), RP.second.end(), [&](const FunctionDecl *FD) {
- if (FD == Overload)
- return false;
- // If the declaration contexts don't match, we don't
- // need to check
- // any further.
- if (FD->getDeclContext() != Overload->getDeclContext())
- return false;
-
- // Since the declaration contexts match, see whether
- // the current
- // element is the corresponding operator.
- if (!areCorrespondingOverloads(Overload, FD))
- return false;
-
- return true;
- });
+ const auto *Match =
+ std::find_if(RP.second.begin(), RP.second.end(),
+ [&Overload](const FunctionDecl *FD) {
+ if (FD == Overload)
+ return false;
+ // If the declaration contexts don't match, we don't
+ // need to check any further.
+ if (FD->getDeclContext() != Overload->getDeclContext())
+ return false;
+
+ // Since the declaration contexts match, see whether
+ // the current element is the corresponding operator.
+ if (!areCorrespondingOverloads(Overload, FD))
+ return false;
+
+ return true;
+ });
if (Match == RP.second.end()) {
// Check to see if there is a corresponding overload in a base class
diff --git a/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp b/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
index 32323a58cc8..3e60537ef65 100644
--- a/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
+++ b/clang-tools-extra/test/clang-tidy/misc-new-delete-overloads.cpp
@@ -75,3 +75,7 @@ struct H : G {
// CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope
void *operator new(size_t) noexcept; // base class operator is inaccessible
};
+
+template <typename Base> struct Derived : Base {
+ void operator delete(void *);
+};
OpenPOWER on IntegriCloud