summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2017-06-03 07:54:55 +0200
committerStephan Bergmann <sbergman@redhat.com>2017-06-05 21:17:59 +0200
commit0f84a32f5b1dbc9f3751b4f8432283867932e155 (patch)
treede28a3c35ec1bce988b69657c4521b1146cc399d /compilerplugins
parent8301695f8fd16338128261b1edbf60852f2d0a68 (diff)
Improved loplugin:redundantcast, const/static_cast combinations
Change-Id: I3b24327835cd4e1842ee6e9b87ab06efa25a4bbf
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/redundantcast.cxx52
-rw-r--r--compilerplugins/clang/test/redundantcast.cxx7
2 files changed, 58 insertions, 1 deletions
diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx
index 4e79415c4850..2a66f8ff0704 100644
--- a/compilerplugins/clang/redundantcast.cxx
+++ b/compilerplugins/clang/redundantcast.cxx
@@ -513,8 +513,8 @@ bool RedundantCast::VisitCXXConstCastExpr(CXXConstCastExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
}
+ auto const sub = compat::getSubExprAsWritten(expr);
if (isRedundantConstCast(expr)) {
- auto const sub = compat::getSubExprAsWritten(expr);
report(
DiagnosticsEngine::Warning,
"redundant const_cast from %0 %1 to %2 %3", expr->getExprLoc())
@@ -522,6 +522,56 @@ bool RedundantCast::VisitCXXConstCastExpr(CXXConstCastExpr const * expr) {
<< expr->getTypeAsWritten()
<< printExprValueKind(expr->getValueKind())
<< expr->getSourceRange();
+ return true;
+ }
+ if (auto const dce = dyn_cast<CXXStaticCastExpr>(
+ sub->IgnoreParenImpCasts()))
+ {
+ auto const sub2 = compat::getSubExprAsWritten(dce);
+ auto t1 = sub2->getType().getCanonicalType();
+ auto isNullptr = t1->isNullPtrType();
+ auto t2 = dce->getType().getCanonicalType();
+ auto t3 = expr->getType().getCanonicalType();
+ auto redundant = false;
+ for (;;) {
+ if ((t2.isConstQualified()
+ && (isNullptr || !t1.isConstQualified())
+ && !t3.isConstQualified())
+ || (t2.isVolatileQualified()
+ && (isNullptr || !t1.isVolatileQualified())
+ && !t3.isVolatileQualified()))
+ {
+ redundant = true;
+ break;
+ }
+ if (!isNullptr) {
+ auto const p1 = t1->getAs<clang::PointerType>();
+ if (p1 == nullptr) {
+ break;
+ }
+ t1 = p1->getPointeeType();
+ isNullptr = t1->isNullPtrType();
+ }
+ auto const p2 = t2->getAs<clang::PointerType>();
+ if (p2 == nullptr) {
+ break;
+ }
+ t2 = p2->getPointeeType();
+ auto const p3 = t3->getAs<clang::PointerType>();
+ if (p3 == nullptr) {
+ break;
+ }
+ t3 = p3->getPointeeType();
+ }
+ if (redundant) {
+ report(
+ DiagnosticsEngine::Warning,
+ ("redundant static_cast/const_cast combination from %0 via %1"
+ " to %2"),
+ expr->getExprLoc())
+ << sub2->getType() << dce->getTypeAsWritten()
+ << expr->getTypeAsWritten() << expr->getSourceRange();
+ }
}
return true;
}
diff --git a/compilerplugins/clang/test/redundantcast.cxx b/compilerplugins/clang/test/redundantcast.cxx
index 78624810fda9..9eda22a04b0f 100644
--- a/compilerplugins/clang/test/redundantcast.cxx
+++ b/compilerplugins/clang/test/redundantcast.cxx
@@ -12,6 +12,8 @@
void f1(char *) {}
void f2(char const *) {}
+struct D: S {};
+
enum Enum1 { X };
void testConstCast() {
@@ -32,6 +34,11 @@ void testConstCast() {
f2(const_cast<char const *>(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *' prvalue [loplugin:redundantcast]}}
f2(const_cast<char const * const>(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *const' prvalue [loplugin:redundantcast]}}
+ void * vp = nullptr;
+ (void) const_cast<char *>(static_cast<char const *>(vp)); // expected-error {{redundant static_cast/const_cast combination from 'void *' via 'const char *' to 'char *' [loplugin:redundantcast]}}
+ (void) const_cast<char *>(static_cast<char const *>(nullptr)); // expected-error {{redundant static_cast/const_cast combination from 'nullptr_t' via 'const char *' to 'char *' [loplugin:redundantcast]}}
+ (void) const_cast<S &>(static_cast<S const &>(D{})); // expected-error {{redundant static_cast/const_cast combination from 'D' via 'const S &' to 'S &' [loplugin:redundantcast]}}
+
S const s{};
const_cast<S &>(s).f1();
const_cast<S &>(s).f2(); // expected-error {{redundant const_cast from 'const S' to 'S', result is implicitly cast to 'const S' [loplugin:redundantcast]}}