diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2016-12-18 13:52:04 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2016-12-18 22:43:26 +0100 |
commit | 0f22790e6bc936b6de588c30816d6fa59f4a14dc (patch) | |
tree | 8c845be4b234748af298c62f5ef2f0f120ef4e0b /compilerplugins | |
parent | ec0665ac8b427b16f1ebc118496d7d2b1831f3fd (diff) |
Generalize typedef-to-void* check in loplugin:redundantcast
...to also cover cases like conversion betwen LPVOID and HANDLE in Windows-only
code
Change-Id: I934fe89372ee7a12462e7ad4284b9ea2cc73ce5a
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/check.cxx | 36 | ||||
-rw-r--r-- | compilerplugins/clang/check.hxx | 8 | ||||
-rw-r--r-- | compilerplugins/clang/redundantcast.cxx | 53 |
3 files changed, 74 insertions, 23 deletions
diff --git a/compilerplugins/clang/check.cxx b/compilerplugins/clang/check.cxx index 33be502c3e1c..43a7edf2bef4 100644 --- a/compilerplugins/clang/check.cxx +++ b/compilerplugins/clang/check.cxx @@ -14,6 +14,16 @@ namespace loplugin { +TypeCheck TypeCheck::NonConstVolatile() const { + return + (!type_.isNull() && !type_.isConstQualified() + && !type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + TypeCheck TypeCheck::Const() const { return (!type_.isNull() && type_.isConstQualified() @@ -24,6 +34,32 @@ TypeCheck TypeCheck::Const() const { // checking for } +TypeCheck TypeCheck::Volatile() const { + return + (!type_.isNull() && !type_.isConstQualified() + && type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TypeCheck TypeCheck::ConstVolatile() const { + return + (!type_.isNull() && type_.isConstQualified() + && type_.isVolatileQualified()) + ? *this : TypeCheck(); + // returning TypeCheck(type_.getUnqualifiedType()) instead of *this + // may look tempting, but could remove sugar we might be interested in + // checking for +} + +TerminalCheck TypeCheck::Void() const { + return TerminalCheck( + !type_.isNull() + && type_->isSpecificBuiltinType(clang::BuiltinType::Void)); +} + TerminalCheck TypeCheck::Char() const { return TerminalCheck( !type_.isNull() diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx index 9bfc458354a7..40f205d977fa 100644 --- a/compilerplugins/clang/check.hxx +++ b/compilerplugins/clang/check.hxx @@ -35,8 +35,16 @@ public: explicit operator bool() const { return !type_.isNull(); } + TypeCheck NonConstVolatile() const; + TypeCheck Const() const; + TypeCheck Volatile() const; + + TypeCheck ConstVolatile() const; + + TerminalCheck Void() const; + TerminalCheck Char() const; TerminalCheck AnyBoolean() const; diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx index 5215b39b18e5..6d18f2abffd8 100644 --- a/compilerplugins/clang/redundantcast.cxx +++ b/compilerplugins/clang/redundantcast.cxx @@ -291,29 +291,36 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) { { return true; } - // Don't warn about - // - // *pResult = static_cast<oslModule>(RTLD_DEFAULT); - // - // in osl_getModuleHandle (sal/osl/unx/module.cxx) (where oslModule is a - // typedef to void *): - if (loplugin::TypeCheck(t2).Typedef("oslModule").GlobalNamespace() - && !loplugin::TypeCheck(t1).Typedef()) - { - return true; - } - // Dont't warn about - // - // curl_easy_setopt(static_cast<CURL*>(pData), - // CURLOPT_HEADERFUNCTION, - // memory_write_dummy); - // - // in delete_CURL (ucb/source/ucp/ftp/ftploaderthread.cxx) (where CURL is a - // typedef to void): - if (loplugin::TypeCheck(t2).Pointer().Typedef("CURL").GlobalNamespace() - && !loplugin::TypeCheck(t1).Pointer().Typedef()) - { - return true; + // Don't warn if the types are 'void *' and at least one involves a typedef + // (and if both involve typedefs, they're different) (this covers cases like + // 'oslModule', or 'CURL *', or casts between 'LPVOID' and 'HANDLE' in + // Windows-only code): + if (loplugin::TypeCheck(t1).Pointer().NonConstVolatile().Void()) { + if (auto const td1 = t1->getAs<TypedefType>()) { + auto const td2 = t2->getAs<TypedefType>(); + if (td2 == nullptr || td2 != td1) { + return true; + } + } else if (auto const td2 = t2->getAs<TypedefType>()) { + auto const td1 = t1->getAs<TypedefType>(); + if (td1 == nullptr || td1 != td2) { + return true; + } + } else { + auto const pt1 = t1->getAs<clang::PointerType>()->getPointeeType(); + auto const pt2 = t2->getAs<clang::PointerType>()->getPointeeType(); + if (auto const ptd1 = pt1->getAs<TypedefType>()) { + auto const ptd2 = pt2->getAs<TypedefType>(); + if (ptd2 == nullptr || ptd2 != ptd1) { + return true; + } + } else if (auto const ptd2 = pt2->getAs<TypedefType>()) { + auto const ptd1 = pt1->getAs<TypedefType>(); + if (ptd1 == nullptr || ptd1 != ptd2) { + return true; + } + } + } } report( DiagnosticsEngine::Warning, |