summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-12-18 13:52:04 +0100
committerStephan Bergmann <sbergman@redhat.com>2016-12-18 22:43:26 +0100
commit0f22790e6bc936b6de588c30816d6fa59f4a14dc (patch)
tree8c845be4b234748af298c62f5ef2f0f120ef4e0b /compilerplugins
parentec0665ac8b427b16f1ebc118496d7d2b1831f3fd (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.cxx36
-rw-r--r--compilerplugins/clang/check.hxx8
-rw-r--r--compilerplugins/clang/redundantcast.cxx53
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,