summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/redundantcast.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2017-04-06 18:33:20 +0200
committerStephan Bergmann <sbergman@redhat.com>2017-04-06 18:33:20 +0200
commit6b4a4bab6d21a549ed35fd045eedf7ff05130a71 (patch)
treea3af2dd2bdbe6bdb2b18511447f1ad3e5a112458 /compilerplugins/clang/redundantcast.cxx
parent06aa3dd5b47d7eedecc8dd45f12581f2e9fa14ee (diff)
Improved loplugin:redundantcast, static_cast on arithmetic types
Change-Id: I6e1f76de4b1ebf76ad02e7d0cd1374b4def83932
Diffstat (limited to 'compilerplugins/clang/redundantcast.cxx')
-rw-r--r--compilerplugins/clang/redundantcast.cxx42
1 files changed, 40 insertions, 2 deletions
diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx
index e157e05668bd..20a04b2176c7 100644
--- a/compilerplugins/clang/redundantcast.cxx
+++ b/compilerplugins/clang/redundantcast.cxx
@@ -113,6 +113,30 @@ bool isRedundantConstCast(CXXConstCastExpr const * expr) {
.getTypePtr());
}
+bool isArithmeticOp(Expr const * expr) {
+ expr = expr->IgnoreParenImpCasts();
+ if (auto const e = dyn_cast<BinaryOperator>(expr)) {
+ switch (e->getOpcode()) {
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ return true;
+ case BO_Comma:
+ return isArithmeticOp(e->getRHS());
+ default:
+ return false;
+ }
+ }
+ return isa<UnaryOperator>(expr) || isa<AbstractConditionalOperator>(expr);
+}
+
class RedundantCast:
public RecursiveASTVisitor<RedundantCast>, public loplugin::RewritePlugin
{
@@ -348,8 +372,22 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) {
}
auto t1 = getSubExprAsWritten(expr)->getType();
auto t2 = expr->getTypeAsWritten();
- if (t1.getCanonicalType() != t2.getCanonicalType()
- || t1->isArithmeticType())
+ if (t1.getCanonicalType() != t2.getCanonicalType()) {
+ return true;
+ }
+ // Don't warn if the types are arithmetic (in the C++ meaning), and: either
+ // at least one is a typedef (and if both are typedefs,they're different),
+ // or the sub-expression involves some operation that is likely to change
+ // types through promotion, or the sub-expression is an integer literal (so
+ // its type generally depends on its value and suffix if any---even with a
+ // suffix like L it could still be either long or long long):
+ if ((t1->isIntegralType(compiler.getASTContext())
+ || t1->isRealFloatingType())
+ && ((t1 != t2
+ && (loplugin::TypeCheck(t1).Typedef()
+ || loplugin::TypeCheck(t2).Typedef()))
+ || isArithmeticOp(expr->getSubExpr())
+ || isa<IntegerLiteral>(expr->getSubExpr()->IgnoreParenImpCasts())))
{
return true;
}