diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2019-10-28 18:21:37 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2019-10-28 20:17:02 +0100 |
commit | 4b91b7dfa75d710d6845fd98b491889ec80d9da8 (patch) | |
tree | 6b042f3358b83295f0827eb5db1f509b63343ef3 /compilerplugins | |
parent | 036d2653d1005b1c5a0b4ca323513557b1cc7d52 (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')
-rw-r--r-- | compilerplugins/clang/finalclasses.cxx | 20 |
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(); |