From 995318e2996abac01dbbbc73f61e93cbb7acd453 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Sat, 8 Oct 2016 23:55:08 +0200 Subject: loplugin:badstatics: reliably look into std container types Change-Id: Ifca7325533e3f7d5ce5c59cc6b14d4232d4fc792 Reviewed-on: https://gerrit.libreoffice.org/29614 Reviewed-by: Stephan Bergmann Tested-by: Stephan Bergmann --- compilerplugins/clang/badstatics.cxx | 61 +++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 7 deletions(-) (limited to 'compilerplugins') diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index db5b0dd8896c..7ac7820d16e6 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -7,6 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + #include "check.hxx" #include "plugin.hxx" @@ -30,20 +32,27 @@ public: QualType const& rpType, std::vector & chain, std::vector const& rParents) { - QualType const pCanonical(rpType.getUnqualifiedType().getCanonicalType()); - if (pCanonical->isPointerType() || pCanonical->isReferenceType()) { - QualType const pPointee(pCanonical->getPointeeType().getUnqualifiedType().getCanonicalType()); + QualType pt; + if (rpType->isAnyPointerType()) { + pt = rpType->getPointeeType(); + } else if (auto at = rpType->getAsArrayTypeUnsafe()) { + pt = at->getElementType(); + } else if (auto rt = rpType->getAs()) { + pt = rt->getPointeeType(); + } + if (!pt.isNull()) { + QualType const pPointee(pt.getUnqualifiedType().getCanonicalType()); auto const iter(std::find(rParents.begin(), rParents.end(), pPointee)); if (iter == rParents.end()) { std::vector copy(rParents); - copy.push_back(pCanonical); - return isBadStaticType(pPointee, chain, copy); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + return isBadStaticType(pt, chain, copy); } else { return std::make_pair(false, std::vector()); } } - RecordType const*const pRecordType(pCanonical->getAs()); + RecordType const*const pRecordType(rpType->getAs()); if (!pRecordType) { return std::make_pair(false, std::vector()); } @@ -56,6 +65,44 @@ public: { return std::make_pair(true, chain); } + if (type.Class("array").StdNamespace() + || type.Class("deque").StdNamespace() + || type.Class("forward_list").StdNamespace() + || type.Class("initializer_list").StdNamespace() + || type.Class("list").StdNamespace() + || type.Class("multiset").StdNamespace() + || type.Class("set").StdNamespace() + || type.Class("unordered_multiset").StdNamespace() + || type.Class("unordered_set").StdNamespace() + || type.Class("vector").StdNamespace()) + { + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + auto ctsd = dyn_cast( + pRecordType->getDecl()); + assert(ctsd != nullptr); + auto const & args = ctsd->getTemplateArgs(); + assert(args.size() >= 1); + return isBadStaticType(args.get(0).getAsType(), chain, copy); + } + if (type.Class("map").StdNamespace() + || type.Class("multimap").StdNamespace() + || type.Class("unordered_map").StdNamespace() + || type.Class("unordered_multimap").StdNamespace()) + { + std::vector copy(rParents); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); + auto ctsd = dyn_cast( + pRecordType->getDecl()); + assert(ctsd != nullptr); + auto const & args = ctsd->getTemplateArgs(); + assert(args.size() >= 2); + auto ret = isBadStaticType(args.get(0).getAsType(), chain, copy); + if (ret.first) { + return ret; + } + return isBadStaticType(args.get(1).getAsType(), chain, copy); + } RecordDecl const*const pDefinition(pRecordType->getDecl()->getDefinition()); if (!pDefinition) { // maybe no definition if it's a pointer/reference return std::make_pair(false, std::vector()); @@ -70,7 +117,7 @@ public: return std::make_pair(false, std::vector()); } std::vector copy(rParents); - copy.push_back(pCanonical); + copy.push_back(rpType.getUnqualifiedType().getCanonicalType()); CXXRecordDecl const*const pDecl(dyn_cast(pDefinition)); assert(pDecl); for (auto it = pDecl->field_begin(); it != pDecl->field_end(); ++it) { -- cgit