diff options
author | Michael Stahl <mstahl@redhat.com> | 2015-11-05 13:16:50 +0100 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2015-11-06 20:37:38 +0100 |
commit | 10afa00c8ce4f0de9191cd182409a3a5d8e55bb8 (patch) | |
tree | 792c791d250b7edb66ec31d498ce9cb44a2120e4 /compilerplugins/clang/badstatics.cxx | |
parent | 22fb58a6fa7764ec0045529c483693e1a81b488e (diff) |
compilerplugins: enhance "badstatics" plugin to find members
Finds static variables of types that have bad non-static members.
Change-Id: I81ee940580c0f043feb543840ea4d3dd27734202
Diffstat (limited to 'compilerplugins/clang/badstatics.cxx')
-rw-r--r-- | compilerplugins/clang/badstatics.cxx | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 136e1db90d20..c41b12d560b4 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -25,23 +25,68 @@ public: } } + /*static*/ std::pair<bool, FieldDecl const*> isBadStaticType( + QualType const& rType, FieldDecl const*const pCurrentFieldDecl) + { + QualType const pCanonical(rType.getUnqualifiedType().getCanonicalType()); + RecordType const*const pRecordType(pCanonical->getAs<RecordType>()); + if (!pRecordType) { + return std::make_pair(false, nullptr); + } + auto const type(pCanonical.getAsString()); + if ( type == "class Image" + || type == "class Bitmap" + || type == "class BitmapEx" + ) + { + return std::make_pair(true, pCurrentFieldDecl); + } + RecordDecl const*const pDefinition(pRecordType->getDecl()->getDefinition()); + assert(pDefinition); + CXXRecordDecl const*const pDecl(dyn_cast<CXXRecordDecl>(pDefinition)); + assert(pDecl); + for (auto it = pDecl->field_begin(); it != pDecl->field_end(); ++it) { + auto const ret(isBadStaticType((*it)->getType(), *it)); + if (ret.first) { + return ret; + } + } + for (auto it = pDecl->bases_begin(); it != pDecl->bases_end(); ++it) { + auto const ret(isBadStaticType((*it).getType(), pCurrentFieldDecl)); + if (ret.first) { + return ret; + } + } + for (auto it = pDecl->vbases_begin(); it != pDecl->vbases_end(); ++it) { + auto const ret(isBadStaticType((*it).getType(), pCurrentFieldDecl)); + if (ret.first) { + return ret; + } + } + return std::make_pair(false, nullptr); + } + bool VisitVarDecl(VarDecl const*const pVarDecl) { if (ignoreLocation(pVarDecl)) { return true; } - if (pVarDecl->hasGlobalStorage()) { - auto const type(pVarDecl->getType().getUnqualifiedType().getCanonicalType().getAsString()); - if ( type == "class Image" - || type == "class Bitmap" - || type == "class BitmapEx" - ) - { + if (pVarDecl->hasGlobalStorage() + && pVarDecl->isThisDeclarationADefinition()) + { + auto const ret(isBadStaticType(pVarDecl->getType(), nullptr)); + if (ret.first) { report(DiagnosticsEngine::Warning, "bad static variable causes crash on shutdown", pVarDecl->getLocation()) << pVarDecl->getSourceRange(); + if (ret.second != nullptr) { + report(DiagnosticsEngine::Remark, + "... due to this member", + ret.second->getLocation()) + << ret.second->getSourceRange(); + } } } |