summaryrefslogtreecommitdiff
path: root/compilerplugins/clang
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2019-10-28 18:21:37 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2019-10-28 20:17:02 +0100
commit4b91b7dfa75d710d6845fd98b491889ec80d9da8 (patch)
tree6b042f3358b83295f0827eb5db1f509b63343ef3 /compilerplugins/clang
parent036d2653d1005b1c5a0b4ca323513557b1cc7d52 (diff)
loplugin:finalclasses look for classes with virtual members
where making them final gives the compiler freedom to de-virtualise some calls Change-Id: I5755a41c42d9f23af58b873efae37a1d240fbd89 Reviewed-on: https://gerrit.libreoffice.org/81618 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r--compilerplugins/clang/finalclasses.cxx20
1 files changed, 14 insertions, 6 deletions
diff --git a/compilerplugins/clang/finalclasses.cxx b/compilerplugins/clang/finalclasses.cxx
index 24bc814602fe..e7704ca8fc0c 100644
--- a/compilerplugins/clang/finalclasses.cxx
+++ b/compilerplugins/clang/finalclasses.cxx
@@ -15,9 +15,14 @@
#include <fstream>
/**
-Look for classes that are final i.e. nothing extends them, and have protected fields or members.
+Look for classes that are final i.e. nothing extends them, and have either
+(a) protected fields or members.
+or
+(b) virtual members
-These can be made private.
+In the case of (a), those members/fields can be made private.
+In the case of (b), making the class final means the compiler can devirtualise
+some method class.
The process goes something like this:
$ make check
@@ -88,6 +93,8 @@ bool FinalClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl)
decl = decl->getCanonicalDecl();
if (!decl->hasDefinition())
return true;
+ if (decl->hasAttr<FinalAttr>())
+ return true;
for (auto it = decl->bases_begin(); it != decl->bases_end(); ++it)
{
@@ -100,15 +107,16 @@ bool FinalClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl)
checkBase(spec.getType());
}
+ bool bFoundVirtual = false;
bool bFoundProtected = false;
for (auto it = decl->method_begin(); it != decl->method_end(); ++it) {
auto i = *it;
// ignore methods that are overriding base-class methods, making them private
// isn't useful
- if ( !i->hasAttr<OverrideAttr>() && i->getAccess() == AS_protected ) {
+ if ( !i->hasAttr<OverrideAttr>() && i->getAccess() == AS_protected )
bFoundProtected = true;
- break;
- }
+ if ( i->isVirtual() )
+ bFoundVirtual = true;
}
if (!bFoundProtected)
{
@@ -120,7 +128,7 @@ bool FinalClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl)
}
}
}
- if (!bFoundProtected)
+ if (!bFoundProtected && !bFoundVirtual)
return true;
std::string s = decl->getQualifiedNameAsString();