Kaydet (Commit) 1c782778 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

const_cast: convert some C-style casts and remove some redundant ones

Change-Id: I876736d18db6676629c283fccd65e1b6fb2bb2be
üst c5f1e8c3
...@@ -53,6 +53,7 @@ private: ...@@ -53,6 +53,7 @@ private:
static const char * recommendedFix(clang::CastKind ck) { static const char * recommendedFix(clang::CastKind ck) {
switch(ck) { switch(ck) {
case CK_NoOp: return "const_cast";
case CK_IntegralToPointer: return "reinterpret_cast"; case CK_IntegralToPointer: return "reinterpret_cast";
case CK_PointerToIntegral: return "reinterpret_cast"; case CK_PointerToIntegral: return "reinterpret_cast";
case CK_BaseToDerived: return "static_cast"; case CK_BaseToDerived: return "static_cast";
...@@ -89,7 +90,26 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { ...@@ -89,7 +90,26 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
return true; return true;
} }
if( expr->getCastKind() == CK_NoOp ) { if( expr->getCastKind() == CK_NoOp ) {
return true; QualType t1 = expr->getSubExpr()->getType();
QualType t2 = expr->getType();
if (t1->isPointerType() && t2->isPointerType()) {
t1 = t1->getAs<PointerType>()->getPointeeType();
t2 = t2->getAs<PointerType>()->getPointeeType();
if (t2->isVoidType()) {
return true;
}
} else if (t1->isLValueReferenceType() && t2->isLValueReferenceType()) {
t1 = t1->getAs<LValueReferenceType>()->getPointeeType();
t2 = t2->getAs<LValueReferenceType>()->getPointeeType();
} else {
return true;
}
if (!t1.isMoreQualifiedThan(t2)
|| (t1.getUnqualifiedType().getCanonicalType().getTypePtr()
!= t2.getUnqualifiedType().getCanonicalType().getTypePtr()))
{
return true;
}
} }
std::string incompFrom; std::string incompFrom;
std::string incompTo; std::string incompTo;
......
...@@ -15,11 +15,16 @@ ...@@ -15,11 +15,16 @@
// * A static_cast<T*>(e) where e is of void pointer type and whose result is // * A static_cast<T*>(e) where e is of void pointer type and whose result is
// then implicitly cast to a void pointer // then implicitly cast to a void pointer
// //
// * Various const_casts that are either not needed (like casting away constness
// in a delete expression) or are implicitly cast back afterwards
//
// C-style casts are ignored because it makes this plugin simpler, and they // C-style casts are ignored because it makes this plugin simpler, and they
// should eventually be eliminated via loplugin:cstylecast and/or // should eventually be eliminated via loplugin:cstylecast and/or
// -Wold-style-cast. That implies that this plugin is only relevant for C++ // -Wold-style-cast. That implies that this plugin is only relevant for C++
// code. // code.
#include "clang/Sema/Sema.h"
#include "plugin.hxx" #include "plugin.hxx"
namespace { namespace {
...@@ -42,37 +47,185 @@ public: ...@@ -42,37 +47,185 @@ public:
} }
bool VisitImplicitCastExpr(ImplicitCastExpr const * expr); bool VisitImplicitCastExpr(ImplicitCastExpr const * expr);
bool VisitCallExpr(CallExpr const * expr);
bool VisitCXXDeleteExpr(CXXDeleteExpr const * expr);
bool VisitBinSub(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinLT(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinGT(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinLE(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinGE(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinEQ(BinaryOperator const * expr)
{ return visitBinOp(expr); }
bool VisitBinNE(BinaryOperator const * expr)
{ return visitBinOp(expr); }
private:
bool visitBinOp(BinaryOperator const * expr);
}; };
bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) { bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
if (ignoreLocation(expr) || expr->getCastKind() != CK_BitCast if (ignoreLocation(expr)) {
|| !isVoidPointer(expr->getType()) return true;
|| !expr->getSubExpr()->getType()->isPointerType()) }
switch (expr->getCastKind()) {
case CK_NoOp:
if (expr->getType()->isPointerType()
|| expr->getType()->isObjectType())
{
auto e = dyn_cast<CXXConstCastExpr>(
expr->getSubExpr()->IgnoreParenImpCasts());
if (e != nullptr) {
auto t1 = e->getSubExpr()->getType().getCanonicalType();
auto t2 = expr->getType().getCanonicalType();
bool ObjCLifetimeConversion;
if (t1.getTypePtr() == t2.getTypePtr()
|| compiler.getSema().IsQualificationConversion(
t1, t2, false, ObjCLifetimeConversion))
{
report(
DiagnosticsEngine::Warning,
("redundant const_cast from %0 to %1, result is"
" implictly cast to %2"),
e->getExprLoc())
<< e->getSubExprAsWritten()->getType() << e->getType()
<< expr->getType() << expr->getSourceRange();
}
}
}
break;
case CK_BitCast:
if (isVoidPointer(expr->getType())
&& expr->getSubExpr()->getType()->isPointerType())
{
Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts();
while (isa<CXXConstCastExpr>(e)) {
auto cc = dyn_cast<CXXConstCastExpr>(e);
if(!cc->getSubExpr()->getType()->isPointerType()){
report(DiagnosticsEngine::Warning,"TODO",cc->getExprLoc())<<expr->getSourceRange();
return true;
}
if (expr->getType()->getAs<PointerType>()->getPointeeType()
.isAtLeastAsQualifiedAs(
cc->getSubExpr()->getType()
->getAs<PointerType>()->getPointeeType()))
{
report(
DiagnosticsEngine::Warning,
("redundant const_cast from %0 to %1, result is"
" ultimately implictly cast to %2"),
cc->getExprLoc())
<< cc->getSubExprAsWritten()->getType() << cc->getType()
<< expr->getType() << expr->getSourceRange();
}
e = cc->getSubExpr()->IgnoreParenImpCasts();
}
if (isa<CXXReinterpretCastExpr>(e)) {
report(
DiagnosticsEngine::Warning,
("redundant reinterpret_cast, result is implicitly cast to"
" void pointer"),
e->getExprLoc())
<< e->getSourceRange();
} else if (isa<CXXStaticCastExpr>(e)
&& isVoidPointer(
dyn_cast<CXXStaticCastExpr>(e)->getSubExpr()
->IgnoreParenImpCasts()->getType()))
{
report(
DiagnosticsEngine::Warning,
("redundant static_cast from void pointer, result is"
" implicitly cast to void pointer"),
e->getExprLoc())
<< e->getSourceRange();
}
}
break;
default:
break;
}
return true;
}
bool RedundantCast::VisitCallExpr(CallExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
}
auto f = expr->getDirectCallee();
if (f == nullptr || !f->isVariadic()
|| expr->getNumArgs() <= f->getNumParams())
{ {
return true; return true;
} }
Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts(); for (auto i = f->getNumParams(); i != expr->getNumArgs(); ++i) {
while (isa<CXXConstCastExpr>(e)) { auto a = expr->getArg(i);
e = dyn_cast<CXXConstCastExpr>(e)->getSubExpr()->IgnoreParenImpCasts(); if (a->getType()->isPointerType()) {
auto e = dyn_cast<CXXConstCastExpr>(a->IgnoreParenImpCasts());
if (e != nullptr) {
report(
DiagnosticsEngine::Warning,
"redundant const_cast of variadic function argument",
e->getExprLoc())
<< expr->getSourceRange();
}
}
}
return true;
}
bool RedundantCast::VisitCXXDeleteExpr(CXXDeleteExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
} }
if (isa<CXXReinterpretCastExpr>(e)) { auto e = dyn_cast<CXXConstCastExpr>(
expr->getArgument()->IgnoreParenImpCasts());
if (e != nullptr) {
report( report(
DiagnosticsEngine::Warning, DiagnosticsEngine::Warning,
("redundant reinterpret_cast, result is implicitly cast to void" "redundant const_cast in delete expression", e->getExprLoc())
" pointer"), << expr->getSourceRange();
e->getExprLoc()) }
<< e->getSourceRange(); return true;
} else if (isa<CXXStaticCastExpr>(e) }
&& isVoidPointer(
dyn_cast<CXXStaticCastExpr>(e)->getSubExpr() bool RedundantCast::visitBinOp(BinaryOperator const * expr) {
->IgnoreParenImpCasts()->getType())) if (ignoreLocation(expr)) {
return true;
}
if (expr->getLHS()->getType()->isPointerType()
&& expr->getRHS()->getType()->isPointerType())
{ {
report( auto e = dyn_cast<CXXConstCastExpr>(
DiagnosticsEngine::Warning, expr->getLHS()->IgnoreParenImpCasts());
("redundant static_cast from void pointer, result is implicitly" if (e != nullptr) {
" cast to void pointer"), report(
e->getExprLoc()) DiagnosticsEngine::Warning,
<< e->getSourceRange(); "redundant const_cast on lhs of pointer %select{comparison|subtraction}0 expression",
e->getExprLoc())
<< (expr->getOpcode() == BO_Sub) << expr->getSourceRange();
}
e = dyn_cast<CXXConstCastExpr>(
expr->getRHS()->IgnoreParenImpCasts());
if (e != nullptr) {
report(
DiagnosticsEngine::Warning,
"redundant const_cast on rhs of pointer %select{comparison|subtraction}0 expression",
e->getExprLoc())
<< (expr->getOpcode() == BO_Sub) << expr->getSourceRange();
}
} }
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment