summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/redundantcast.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/redundantcast.cxx')
-rw-r--r--compilerplugins/clang/redundantcast.cxx114
1 files changed, 90 insertions, 24 deletions
diff --git a/compilerplugins/clang/redundantcast.cxx b/compilerplugins/clang/redundantcast.cxx
index 27566809494c..07efeb568606 100644
--- a/compilerplugins/clang/redundantcast.cxx
+++ b/compilerplugins/clang/redundantcast.cxx
@@ -66,6 +66,13 @@ char const * printExprValueKind(ExprValueKind k) {
llvm_unreachable("unknown ExprValueKind");
}
+QualType desugarElaboratedType(QualType type) {
+ if (auto const t = dyn_cast<ElaboratedType>(type)) {
+ return t->desugar();
+ }
+ return type;
+}
+
enum class AlgebraicType { None, Integer, FloatingPoint };
AlgebraicType algebraicType(clang::Type const & type) {
@@ -158,7 +165,7 @@ private:
bool isOverloadedFunction(FunctionDecl const * decl);
bool isInIgnoredMacroBody(Expr const * expr) {
- auto const loc = compat::getBeginLoc(expr);
+ auto const loc = expr->getBeginLoc();
return compiler.getSourceManager().isMacroBodyExpansion(loc)
&& ignoreLocation(compiler.getSourceManager().getSpellingLoc(loc));
}
@@ -205,10 +212,10 @@ bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts();
while (isa<CXXConstCastExpr>(e)) {
auto cc = dyn_cast<CXXConstCastExpr>(e);
- if (expr->getType()->getAs<clang::PointerType>()
- ->getPointeeType().isAtLeastAsQualifiedAs(
- cc->getSubExpr()->getType()
- ->getAs<clang::PointerType>()->getPointeeType()))
+ if (compat::isAtLeastAsQualifiedAs(
+ expr->getType()->getAs<clang::PointerType>()->getPointeeType(),
+ cc->getSubExpr()->getType()->getAs<clang::PointerType>()->getPointeeType(),
+ compiler.getASTContext()))
{
report(
DiagnosticsEngine::Warning,
@@ -232,7 +239,7 @@ bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
dyn_cast<CXXStaticCastExpr>(e)->getSubExpr()
->IgnoreParenImpCasts()->getType())
&& !compiler.getSourceManager().isMacroBodyExpansion(
- compat::getBeginLoc(e)))
+ e->getBeginLoc()))
{
report(
DiagnosticsEngine::Warning,
@@ -249,10 +256,10 @@ bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts();
while (isa<CXXConstCastExpr>(e)) {
auto cc = dyn_cast<CXXConstCastExpr>(e);
- if (expr->getType()->getAs<clang::PointerType>()
- ->getPointeeType().isAtLeastAsQualifiedAs(
- cc->getSubExpr()->getType()
- ->getAs<clang::PointerType>()->getPointeeType()))
+ if (compat::isAtLeastAsQualifiedAs(
+ expr->getType()->getAs<clang::PointerType>()->getPointeeType(),
+ cc->getSubExpr()->getType()->getAs<clang::PointerType>()->getPointeeType(),
+ compiler.getASTContext()))
{
report(
DiagnosticsEngine::Warning,
@@ -268,10 +275,10 @@ bool RedundantCast::VisitImplicitCastExpr(const ImplicitCastExpr * expr) {
Expr const * e = expr->getSubExpr()->IgnoreParenImpCasts();
while (isa<CXXConstCastExpr>(e)) {
auto cc = dyn_cast<CXXConstCastExpr>(e);
- if (expr->getType()->getAs<ReferenceType>()->getPointeeType()
- .isAtLeastAsQualifiedAs(
- cc->getSubExpr()->getType()
- ->getAs<ReferenceType>()->getPointeeType()))
+ if (compat::isAtLeastAsQualifiedAs(
+ expr->getType()->getAs<ReferenceType>()->getPointeeType(),
+ cc->getSubExpr()->getType()->getAs<ReferenceType>()->getPointeeType(),
+ compiler.getASTContext()))
{
report(
DiagnosticsEngine::Warning,
@@ -312,7 +319,7 @@ bool RedundantCast::VisitCStyleCastExpr(CStyleCastExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
}
- if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(compat::getBeginLoc(expr)))) {
+ if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc()))) {
return true;
}
auto t1 = compat::getSubExprAsWritten(expr)->getType();
@@ -320,7 +327,7 @@ bool RedundantCast::VisitCStyleCastExpr(CStyleCastExpr const * expr) {
if (auto templateType = dyn_cast<SubstTemplateTypeParmType>(t1)) {
t1 = templateType->desugar();
}
- if (t1 != t2) {
+ if (desugarElaboratedType(t1) != desugarElaboratedType(t2)) {
return true;
}
if (!t1->isBuiltinType() && !loplugin::TypeCheck(t1).Enum() && !loplugin::TypeCheck(t1).Typedef()) {
@@ -333,7 +340,7 @@ bool RedundantCast::VisitCStyleCastExpr(CStyleCastExpr const * expr) {
// Ignore FD_ISSET expanding to "...(SOCKET)(fd)..." in some Microsoft
// winsock2.h (TODO: improve heuristic of determining that the whole
// expr is part of a single macro body expansion):
- auto l1 = compat::getBeginLoc(expr);
+ auto l1 = expr->getBeginLoc();
while (compiler.getSourceManager().isMacroArgExpansion(l1)) {
l1 = compiler.getSourceManager().getImmediateMacroCallerLoc(l1);
}
@@ -341,7 +348,7 @@ bool RedundantCast::VisitCStyleCastExpr(CStyleCastExpr const * expr) {
while (compiler.getSourceManager().isMacroArgExpansion(l2)) {
l2 = compiler.getSourceManager().getImmediateMacroCallerLoc(l2);
}
- auto l3 = compat::getEndLoc(expr);
+ auto l3 = expr->getEndLoc();
while (compiler.getSourceManager().isMacroArgExpansion(l3)) {
l3 = compiler.getSourceManager().getImmediateMacroCallerLoc(l3);
}
@@ -366,6 +373,15 @@ bool RedundantCast::VisitVarDecl(VarDecl const * varDecl) {
if (!varDecl->getInit())
return true;
visitAssign(varDecl->getType(), varDecl->getInit());
+ if (varDecl->getInitStyle() != VarDecl::CInit
+ && isa<CXXTemporaryObjectExpr>(varDecl->getInit())
+ && !compiler.getSourceManager().isMacroBodyExpansion(varDecl->getInit()->getBeginLoc()))
+ {
+ report(
+ DiagnosticsEngine::Warning, "redundant functional cast",
+ varDecl->getBeginLoc())
+ << varDecl->getSourceRange();
+ }
return true;
}
@@ -551,7 +567,7 @@ bool RedundantCast::VisitCXXStaticCastExpr(CXXStaticCastExpr const * expr) {
// h=b5889d25e9bf944a89fdd7bcabf3b6c6f6bb6f7c> "assert: Support types
// without operator== (int) [BZ #21972]":
if (t1->isBooleanType() && t2->isBooleanType()) {
- auto loc = compat::getBeginLoc(expr);
+ auto loc = expr->getBeginLoc();
if (compiler.getSourceManager().isMacroBodyExpansion(loc)
&& (Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts())
@@ -577,13 +593,23 @@ bool RedundantCast::VisitCXXReinterpretCastExpr(
if (ignoreLocation(expr)) {
return true;
}
+ if (expr->getTypeAsWritten() == expr->getSubExprAsWritten()->getType())
+ //TODO: instead of exact QualType match, allow some variation?
+ {
+ report(
+ DiagnosticsEngine::Warning, "redundant reinterpret_cast from %0 to %1",
+ expr->getExprLoc())
+ << expr->getSubExprAsWritten()->getType() << expr->getTypeAsWritten()
+ << expr->getSourceRange();
+ return true;
+ }
if (auto const sub = dyn_cast<ImplicitCastExpr>(expr->getSubExpr())) {
if (sub->getCastKind() == CK_ArrayToPointerDecay && sub->getType() == expr->getType())
//TODO: instead of exact QualType match, allow some variation?
{
if (loplugin::TypeCheck(sub->getType()).Pointer().Const().Char()) {
if (auto const lit = dyn_cast<clang::StringLiteral>(expr->getSubExprAsWritten())) {
- if (lit->getKind() == clang::StringLiteral::UTF8) {
+ if (lit->getKind() == compat::StringLiteralKind::UTF8) {
// Don't warn about
//
// redundant_cast<char const *>(u8"...")
@@ -607,13 +633,13 @@ bool RedundantCast::VisitCXXReinterpretCastExpr(
return true;
}
if (rewriter != nullptr) {
- auto loc = compat::getBeginLoc(expr);
+ auto loc = expr->getBeginLoc();
while (compiler.getSourceManager().isMacroArgExpansion(loc)) {
loc = compiler.getSourceManager().getImmediateMacroCallerLoc(
loc);
}
if (compiler.getSourceManager().isMacroBodyExpansion(loc)) {
- auto loc2 = compat::getEndLoc(expr);
+ auto loc2 = expr->getEndLoc();
while (compiler.getSourceManager().isMacroArgExpansion(loc2)) {
loc2 = compiler.getSourceManager()
.getImmediateMacroCallerLoc(loc2);
@@ -665,6 +691,24 @@ bool RedundantCast::VisitCXXReinterpretCastExpr(
return true;
}
}
+ if (auto const t1 = expr->getSubExpr()->getType()->getAs<clang::PointerType>()) {
+ if (auto const t2 = expr->getType()->getAs<clang::PointerType>()) {
+ if (auto const d1 = t1->getPointeeCXXRecordDecl()) {
+ if (auto const d2 = t2->getPointeeCXXRecordDecl()) {
+ if (d1->hasDefinition() && d1->isDerivedFrom(d2)) {
+ report(
+ DiagnosticsEngine::Warning,
+ "suspicious reinterpret_cast from derived %0 to base %1, maybe this was"
+ " meant to be a static_cast",
+ expr->getExprLoc())
+ << expr->getSubExprAsWritten()->getType() << expr->getTypeAsWritten()
+ << expr->getSourceRange();
+ return true;
+ }
+ }
+ }
+ }
+ }
return true;
}
@@ -795,8 +839,8 @@ bool RedundantCast::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr const * exp
//
// in sal/osl/unx/socket.cxx:
//TODO: Better check that sub is exactly an expansion of FD_ISSET:
- if (compat::getEndLoc(sub).isMacroID()) {
- for (auto loc = compat::getBeginLoc(sub);
+ if (sub->getEndLoc().isMacroID()) {
+ for (auto loc = sub->getBeginLoc();
loc.isMacroID()
&& (compiler.getSourceManager()
.isAtStartOfImmediateMacroExpansion(loc));
@@ -853,6 +897,28 @@ bool RedundantCast::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) {
<< t2 << t1 << expr->getSourceRange();
return true;
}
+ if (qt1->getAsCXXRecordDecl() && qt2->getAsCXXRecordDecl() && qt2->getAsCXXRecordDecl()->isDerivedFrom(qt1->getAsCXXRecordDecl()))
+ {
+ report(
+ DiagnosticsEngine::Warning,
+ "redundant dynamic upcast from %0 to %1", expr->getExprLoc())
+ << t2 << t1 << expr->getSourceRange();
+ return true;
+ }
+ }
+ else if (qt1->isReferenceType() && qt2->isRecordType())
+ {
+ // casting from 'T&' to 'const T&' is redundant, so compare without the qualifiers
+ qt1 = qt1->getPointeeType().getUnqualifiedType();
+ qt2 = qt2.getUnqualifiedType();
+ if (qt1 == qt2)
+ {
+ report(
+ DiagnosticsEngine::Warning,
+ "redundant dynamic cast from %0 to %1", expr->getExprLoc())
+ << t2 << t1 << expr->getSourceRange();
+ return true;
+ }
if (qt1->getAsCXXRecordDecl() && qt2->getAsCXXRecordDecl()->isDerivedFrom(qt1->getAsCXXRecordDecl()))
{
report(