From 95645cbf0a220c338600130bdeca49743b252972 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 2 Jun 2017 13:31:37 +0200 Subject: Improved loplugin:redundantcast const_cast handling Change-Id: I4c24ff5d9d5e74bef2a4040c6308c504282af55d --- compilerplugins/clang/redundantcast.cxx | 20 +++-- compilerplugins/clang/test/redundantcast.cxx | 112 +++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 13 deletions(-) diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx index 6bc97e5351a3..6d740ddca883 100644 --- a/compilerplugins/clang/redundantcast.cxx +++ b/compilerplugins/clang/redundantcast.cxx @@ -37,9 +37,12 @@ bool isVoidPointer(QualType type) { } bool isRedundantConstCast(CXXConstCastExpr const * expr) { - return expr->getTypeAsWritten().getCanonicalType().getTypePtr() - == (expr->getSubExprAsWritten()->getType().getCanonicalType() - .getTypePtr()); + auto const sub = compat::getSubExprAsWritten(expr); + return + (expr->getType().getCanonicalType() + == sub->getType().getCanonicalType()) + && (expr->getValueKind() != VK_XValue + || sub->getValueKind() == VK_XValue); } bool isArithmeticOp(Expr const * expr) { @@ -511,11 +514,14 @@ bool RedundantCast::VisitCXXConstCastExpr(CXXConstCastExpr const * expr) { return true; } if (isRedundantConstCast(expr)) { + auto const sub = compat::getSubExprAsWritten(expr); report( - DiagnosticsEngine::Warning, "redundant const_cast from %0 to %1", - expr->getExprLoc()) - << expr->getSubExprAsWritten()->getType() - << expr->getTypeAsWritten() << expr->getSourceRange(); + DiagnosticsEngine::Warning, + "redundant const_cast from %0 %1 to %2 %3", expr->getExprLoc()) + << sub->getType() << printExprValueKind(sub->getValueKind()) + << expr->getTypeAsWritten() + << printExprValueKind(expr->getValueKind()) + << expr->getSourceRange(); } return true; } diff --git a/compilerplugins/clang/test/redundantcast.cxx b/compilerplugins/clang/test/redundantcast.cxx index 6e5a8d42e589..1d2646a0f463 100644 --- a/compilerplugins/clang/test/redundantcast.cxx +++ b/compilerplugins/clang/test/redundantcast.cxx @@ -19,24 +19,124 @@ void testConstCast() { char const * p2; p1 = nullptr; p2 = ""; - f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' to 'char *' [loplugin:redundantcast]}} - f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' to 'char *const' [loplugin:redundantcast]}} + f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *' prvalue [loplugin:redundantcast]}} + f1(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *const' prvalue [loplugin:redundantcast]}} f1(const_cast(p2)); f1(const_cast(p2)); - f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' to 'char *' [loplugin:redundantcast]}} - f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' to 'char *const' [loplugin:redundantcast]}} + f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *' prvalue [loplugin:redundantcast]}} + f2(const_cast(p1)); // expected-error {{redundant const_cast from 'char *' lvalue to 'char *const' prvalue [loplugin:redundantcast]}} f2(const_cast(p1)); f2(const_cast(p1)); f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'char *', result is implicitly cast to 'const char *' [loplugin:redundantcast]}} f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'char *', result is implicitly cast to 'const char *' [loplugin:redundantcast]}} - f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'const char *' [loplugin:redundantcast]}} - f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' to 'const char *const' [loplugin:redundantcast]}} + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *' prvalue [loplugin:redundantcast]}} + f2(const_cast(p2)); // expected-error {{redundant const_cast from 'const char *' lvalue to 'const char *const' prvalue [loplugin:redundantcast]}} S const s{}; const_cast(s).f1(); const_cast(s).f2(); // expected-error {{redundant const_cast from 'const S' to 'S', result is implicitly cast to 'const S' [loplugin:redundantcast]}} const_cast(s).f3(); s.f3(); + + // non-class lvalue, non-const: + int ni{}; +// (void) const_cast(ni); + (void) const_cast(ni); // expected-error {{redundant const_cast from 'int' lvalue to 'int &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ni); +// (void) const_cast(ni); + (void) const_cast(ni); + (void) const_cast(ni); + + // non-class lvalue, const: + int const ci{}; +// (void) const_cast(ci); + (void) const_cast(ci); + (void) const_cast(ci); +// (void) const_cast(ci); + (void) const_cast(ci); // expected-error {{redundant const_cast from 'const int' lvalue to 'const int &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ci); + + // non-class xvalue, non-const: +// (void) const_cast(nix()); +// (void) const_cast(nix()); + (void) const_cast(nix()); // expected-error {{redundant const_cast from 'int' xvalue to 'int &&' xvalue [loplugin:redundantcast]}} +// (void) const_cast(nix()); +// (void) const_cast(nix()); + (void) const_cast(nix()); + + // non-class xvalue, const: +// (void) const_cast(cix()); +// (void) const_cast(cix()); + (void) const_cast(cix()); +// (void) const_cast(cix()); +// (void) const_cast(cix()); + (void) const_cast(cix()); // expected-error {{redundant const_cast from 'const int' xvalue to 'const int &&' xvalue [loplugin:redundantcast]}} + + // non-class prvalue, non-const: +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); +// (void) const_cast(nir()); + + // non-class prvalue, const: +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); +// (void) const_cast(cir()); + + // class lvalue, non-const: + S ns{}; +// (void) const_cast(ns); + (void) const_cast(ns); // expected-error {{redundant const_cast from 'S' lvalue to 'S &' lvalue [loplugin:redundantcast]}} + (void) const_cast(ns); +// (void) const_cast(ns); + (void) const_cast(ns); + (void) const_cast(ns); + + // class lvalue, const: + S const cs{}; +// (void) const_cast(cs); + (void) const_cast(cs); + (void) const_cast(cs); +// (void) const_cast(cs); + (void) const_cast(cs); // expected-error {{redundant const_cast from 'const S' lvalue to 'const S &' lvalue [loplugin:redundantcast]}} + (void) const_cast(cs); + + // class xvalue, non-const: +// (void) const_cast(nsx()); +// (void) const_cast(nsx()); + (void) const_cast(nsx()); // expected-error {{redundant const_cast from 'S' xvalue to 'S &&' xvalue [loplugin:redundantcast]}} +// (void) const_cast(nsx()); +// (void) const_cast(nsx()); + (void) const_cast(nsx()); + + // class xvalue, const: +// (void) const_cast(csx()); +// (void) const_cast(csx()); + (void) const_cast(csx()); +// (void) const_cast(csx()); +// (void) const_cast(csx()); + (void) const_cast(csx()); // expected-error {{redundant const_cast from 'const S' xvalue to 'const S &&' xvalue [loplugin:redundantcast]}} + + // class prvalue, non-const: +// (void) const_cast(nsr()); +// (void) const_cast(nsr()); + (void) const_cast(nsr()); +// (void) const_cast(nsr()); +// (void) const_cast(nsr()); + (void) const_cast(nsr()); + + // class prvalue, const: +// (void) const_cast(csr()); +// (void) const_cast(csr()); + (void) const_cast(csr()); +// (void) const_cast(csr()); +// (void) const_cast(csr()); + (void) const_cast(csr()); } void testStaticCast() { -- cgit