diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-12-11 11:13:50 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-12-11 16:03:17 +0100 |
commit | 1586241344faf329a9b9b0e969d43fe186906b74 (patch) | |
tree | 78eb5c64d1da88000c68266da92616096fdfd796 | |
parent | 128dabf58a535d422eb27f8dc760c81e54c6b354 (diff) |
Extend loplugin:unusedmember "layout heuristic" to base classes
With clang-cl on Windows, where CPPU_GCC3_ALIGN expands to nothing, there were
warnings about unsued Char1::c1 and Char2::c2 in cppu/source/uno/check.cxx
(which were suppressed on Linux thanks to CPPU_GCC3_ALIGN(T) making the plugin's
"layout heuristic" kick in for T). But Char1 and Char2 are also (indirect)
bases of Char3, for which the heuristic kicks in thanks to a sizeof(Char3)
expression. Extending the heuristic to base classes seems like a good
improvement anyway, and happens to make the unwanted warnings on Windows go
away.
Change-Id: I1fac3104aa7a1745ccf2f23972953eaacbd45104
Reviewed-on: https://gerrit.libreoffice.org/84927
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
-rw-r--r-- | compilerplugins/clang/test/unusedmember.cxx | 20 | ||||
-rw-r--r-- | compilerplugins/clang/unusedmember.cxx | 28 |
2 files changed, 41 insertions, 7 deletions
diff --git a/compilerplugins/clang/test/unusedmember.cxx b/compilerplugins/clang/test/unusedmember.cxx index 84802414f47b..d40d87b2d29b 100644 --- a/compilerplugins/clang/test/unusedmember.cxx +++ b/compilerplugins/clang/test/unusedmember.cxx @@ -145,6 +145,25 @@ void f() } } +namespace Bases +{ +namespace +{ +struct S1 +{ + int i1; +}; +struct S2 : S1 +{ + int i2; +}; +struct S3 : S2 +{ +}; +} +void f() { (void)sizeof(S3); } +} + int main() { (void)&Enum::f; @@ -153,6 +172,7 @@ int main() (void)&UnusedDataMember::f; (void)&Alignof::f; (void)&Aligned::f; + (void)&Bases::f; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/unusedmember.cxx b/compilerplugins/clang/unusedmember.cxx index c8a536c79f53..ed7096ecbc1e 100644 --- a/compilerplugins/clang/unusedmember.cxx +++ b/compilerplugins/clang/unusedmember.cxx @@ -241,11 +241,7 @@ public: { return true; } - layout_.insert(expr->getTypeSourceInfo() - ->getType() - ->castAs<RecordType>() - ->getDecl() - ->getCanonicalDecl()); + recordRecordDeclAndBases(expr->getTypeSourceInfo()->getType()->castAs<RecordType>()); return true; } @@ -281,7 +277,7 @@ public: } if (auto const t1 = t->getAs<RecordType>()) { - layout_.insert(t1->getDecl()->getCanonicalDecl()); + recordRecordDeclAndBases(t1); } return true; } @@ -385,6 +381,24 @@ private: return t.isTrivialType(compiler.getASTContext()) || isWarnUnusedType(t); } + void recordRecordDeclAndBases(RecordType const* type) + { + auto const d1 = type->getDecl(); + if (!layout_.insert(d1->getCanonicalDecl()).second) + { + return; + } + if (auto const d2 = dyn_cast_or_null<CXXRecordDecl>(d1->getDefinition())) + { + for (auto i = d2->bases_begin(); i != d2->bases_end(); ++i) + { + recordRecordDeclAndBases(i->getType()->castAs<RecordType>()); + } + //TODO: doesn't iterate vbases, but presence of such would run counter to the layout + // heuristic anyway + } + } + void recordCastedRecordDecl(QualType type) { for (auto t = type;;) @@ -396,7 +410,7 @@ private: } if (auto const t1 = t->getAs<RecordType>()) { - layout_.insert(t1->getDecl()->getCanonicalDecl()); + recordRecordDeclAndBases(t1); } break; } |