summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/unnecessaryoverride.cxx
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2017-01-12 16:27:14 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2017-01-27 09:49:04 +0000
commit4511431fb665dac192008fa063e783d9e8d7ed15 (patch)
tree3e68fac05e24f2f5bd7f2deed9a32288d7ddf64a /compilerplugins/clang/unnecessaryoverride.cxx
parent1a90a23d9fdcc4344f459b183bbafb8ba7b5bcc0 (diff)
improve "unnecessary user-declared destructor" check
to look for inline&empty destructors, where we can just let the compiler do it's thing Change-Id: Ibde8800bdfed6b77649c30ebc19921167c33dec3 Reviewed-on: https://gerrit.libreoffice.org/32999 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins/clang/unnecessaryoverride.cxx')
-rw-r--r--compilerplugins/clang/unnecessaryoverride.cxx57
1 files changed, 47 insertions, 10 deletions
diff --git a/compilerplugins/clang/unnecessaryoverride.cxx b/compilerplugins/clang/unnecessaryoverride.cxx
index 98b77d5a7b7a..8cf811b58415 100644
--- a/compilerplugins/clang/unnecessaryoverride.cxx
+++ b/compilerplugins/clang/unnecessaryoverride.cxx
@@ -78,14 +78,25 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
return true;
}
- if (isa<CXXDestructorDecl>(methodDecl)) {
- // Warn about unnecessarily user-declared overriding virtual
- // destructors; such a destructor is deemed unnecessary if
+ StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
+
+ if (isa<CXXDestructorDecl>(methodDecl)
+ && !isInUnoIncludeFile(methodDecl))
+ {
+ // the code is this method is only __compiled__ if OSL_DEBUG_LEVEL > 1
+ if (aFileName == SRCDIR "/tools/source/stream/strmunx.cxx")
+ return true;
+
+ // Warn about unnecessarily user-declared destructors.
+ // A destructor is deemed unnecessary if:
// * it is public;
// * its class is only defined in the .cxx file (i.e., the virtual
- // destructor is neither used to controll the place of vtable
+ // destructor is neither used to control the place of vtable
// emission, nor is its definition depending on types that may still
// be incomplete);
+ // or
+ // the destructor is inline, the class definition is complete,
+ // and the class has no superclasses
// * it either does not have an explicit exception specification, or has
// a non-dependent explicit exception specification that is compatible
// with a non-dependent exception specification the destructor would
@@ -102,14 +113,42 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
// implicit definition of a copy constructor and/or copy assignment
// operator to change from being an obsolete feature to being a standard
// feature. That difference is not taken into account here.
- if ((methodDecl->begin_overridden_methods()
- == methodDecl->end_overridden_methods())
- || methodDecl->getAccess() != AS_public)
+ auto cls = methodDecl->getParent();
+ if (methodDecl->isVirtual() && cls->getNumBases() == 0)
+ {
+ return true;
+ }
+ if (methodDecl->getAccess() != AS_public)
{
return true;
}
if (!compiler.getSourceManager().isInMainFile(
- methodDecl->getCanonicalDecl()->getLocation()))
+ methodDecl->getCanonicalDecl()->getLocation())
+ && !( methodDecl->isInlined()))
+ {
+ return true;
+ }
+ // if it's virtual, but it has a base-class with a non-virtual destructor
+ if (methodDecl->isVirtual())
+ {
+ for (auto baseSpecifier = cls->bases_begin(); baseSpecifier != cls->bases_end(); ++baseSpecifier)
+ {
+ const RecordType* baseRecordType = baseSpecifier->getType()->getAs<RecordType>();
+ if (baseRecordType)
+ {
+ const CXXRecordDecl* baseRecordDecl = dyn_cast<CXXRecordDecl>(baseRecordType->getDecl());
+ if (baseRecordDecl && baseRecordDecl->getDestructor()
+ && !baseRecordDecl->getDestructor()->isVirtual())
+ {
+ return true;
+ }
+ }
+ }
+ }
+ // corner case
+ if (methodDecl->isInlined()
+ && compiler.getSourceManager().isInMainFile(methodDecl->getLocation())
+ && !compiler.getSourceManager().isInMainFile(methodDecl->getCanonicalDecl()->getLocation()))
{
return true;
}
@@ -123,7 +162,6 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
}
}
//TODO: exception specification
- auto cls = methodDecl->getParent();
if (!(cls->hasUserDeclaredCopyConstructor()
|| cls->hasUserDeclaredCopyAssignment()
|| cls->hasUserDeclaredMoveConstructor()
@@ -166,7 +204,6 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const CXXMethodDecl* methodDecl)
}
}
// sometimes the disambiguation happens in a base class
- StringRef aFileName = compiler.getSourceManager().getFilename(compiler.getSourceManager().getSpellingLoc(methodDecl->getLocStart()));
if (aFileName == SRCDIR "/comphelper/source/property/propertycontainer.cxx")
return true;
// not sure what is happening here