diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2015-06-02 11:29:13 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2015-06-02 11:29:13 +0200 |
commit | acd4ecc38fc3aa486b7eaf8d5effa4a5ea034ccd (patch) | |
tree | e0c30ba05b993c4595c98232d584317740a4284e /compilerplugins | |
parent | 3f846cb7a40ea6226c68ff22981d6090da66e6aa (diff) |
loplugin:cstylecast: deal with those that are (technically) const_cast
Change-Id: Ice7bbdea1d0df0a92f2e1b38f033adaff2fb8b07
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/cstylecast.cxx | 117 |
1 files changed, 104 insertions, 13 deletions
diff --git a/compilerplugins/clang/cstylecast.cxx b/compilerplugins/clang/cstylecast.cxx index afbcacd9f15c..dadba429bce9 100644 --- a/compilerplugins/clang/cstylecast.cxx +++ b/compilerplugins/clang/cstylecast.cxx @@ -18,6 +18,63 @@ namespace { +bool areSimilar(QualType type1, QualType type2) { + auto t1 = type1.getCanonicalType().getTypePtr(); + auto t2 = type2.getCanonicalType().getTypePtr(); + for (;;) { + if (t1->isPointerType()) { + if (!t2->isPointerType()) { + return false; + } + auto t1a = t1->getAs<PointerType>(); + auto t2a = t2->getAs<PointerType>(); + t1 = t1a->getPointeeType().getTypePtr(); + t2 = t2a->getPointeeType().getTypePtr(); + } else if (t1->isMemberPointerType()) { + if (!t2->isMemberPointerType()) { + return false; + } + auto t1a = t1->getAs<MemberPointerType>(); + auto t2a = t2->getAs<MemberPointerType>(); + if (t1a->getClass()->getCanonicalTypeInternal() + != t2a->getClass()->getCanonicalTypeInternal()) + { + return false; + } + t1 = t1a->getPointeeType().getTypePtr(); + t2 = t2a->getPointeeType().getTypePtr(); + } else if (t1->isConstantArrayType()) { + if (!t2->isConstantArrayType()) { + return false; + } + auto t1a = static_cast<ConstantArrayType const *>( + t1->getAsArrayTypeUnsafe()); + auto t2a = static_cast<ConstantArrayType const *>( + t2->getAsArrayTypeUnsafe()); + if (t1a->getSize() != t2a->getSize()) { + return false; + } + t1 = t1a->getElementType().getTypePtr(); + t2 = t2a->getElementType().getTypePtr(); + } else if (t1->isIncompleteArrayType()) { + if (!t2->isIncompleteArrayType()) { + return false; + } + auto t1a = static_cast<IncompleteArrayType const *>( + t1->getAsArrayTypeUnsafe()); + auto t2a = static_cast<IncompleteArrayType const *>( + t2->getAsArrayTypeUnsafe()); + t1 = t1a->getElementType().getTypePtr(); + t2 = t2a->getElementType().getTypePtr(); + } else { + return false; + } + if (t1 == t2) { + return true; + } + } +} + bool hasCLanguageLinkageType(FunctionDecl const * decl) { return decl->isExternC() || compat::isInExternCContext(*decl); } @@ -48,6 +105,8 @@ public: bool VisitCStyleCastExpr(const CStyleCastExpr * expr); private: + bool isConstCast(QualType from, QualType to); + bool externCFunction; }; @@ -56,7 +115,7 @@ static const char * recommendedFix(clang::CastKind ck) { case CK_IntegralToPointer: return "reinterpret_cast"; case CK_PointerToIntegral: return "reinterpret_cast"; case CK_BaseToDerived: return "static_cast"; - default: return "???"; + default: return nullptr; } } @@ -88,6 +147,7 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { if( expr->getCastKind() == CK_IntegralCast ) { return true; } + char const * perf = nullptr; if( expr->getCastKind() == CK_NoOp ) { QualType t1 = expr->getSubExpr()->getType(); QualType t2 = expr->getType(); @@ -100,11 +160,17 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { } else { return true; } - if (expr->getSubExprAsWritten()->getType() != expr->getType() - && (!t1.isMoreQualifiedThan(t2) - || (t1.getUnqualifiedType().getCanonicalType().getTypePtr() - != (t2.getUnqualifiedType().getCanonicalType() - .getTypePtr())))) + if (isConstCast( + expr->getSubExprAsWritten()->getType(), + expr->getTypeAsWritten())) + { + perf = "const_cast"; + } else if (expr->getSubExprAsWritten()->getType() != expr->getType() + && (!t1.isMoreQualifiedThan(t2) + || ((t1.getUnqualifiedType().getCanonicalType() + .getTypePtr()) + != (t2.getUnqualifiedType().getCanonicalType() + .getTypePtr())))) { return true; } @@ -130,18 +196,43 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { return true; } } + if (perf == nullptr) { + perf = recommendedFix(expr->getCastKind()); + } + std::string performs; + if (perf != nullptr) { + performs = std::string(" (performs: ") + perf + ")"; + } report( - DiagnosticsEngine::Warning, - "c-style cast, type=%0, from=%1%2, to=%3%4, recommendedFix=%5", + DiagnosticsEngine::Warning, "%0 C-style cast from %1%2 to %3%4%5", expr->getSourceRange().getBegin()) - << expr->getCastKind() - << incompFrom << expr->getSubExprAsWritten()->getType() - << incompTo << expr->getType() - << recommendedFix(expr->getCastKind()) - << expr->getSourceRange(); + << expr->getCastKindName() << incompFrom + << expr->getSubExprAsWritten()->getType() << incompTo << expr->getType() + << performs << expr->getSourceRange(); return true; } +bool CStyleCast::isConstCast(QualType from, QualType to) { + if (to->isReferenceType() + && to->getAs<ReferenceType>()->getPointeeType()->isObjectType()) + { + if (!from->isObjectType()) { + return false; + } + from = compiler.getASTContext().getPointerType(from); + to = compiler.getASTContext().getPointerType( + to->getAs<ReferenceType>()->getPointeeType()); + } else { + if (from->isArrayType()) { + from = compiler.getASTContext().getPointerType( + from->getAsArrayTypeUnsafe()->getElementType()); + } else if (from->isFunctionType()) { + compiler.getASTContext().getPointerType(from); + } + } + return areSimilar(from, to); +} + loplugin::Plugin::Registration< CStyleCast > X("cstylecast"); } |