summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/implicitboolconversion.cxx52
1 files changed, 41 insertions, 11 deletions
diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx
index 0327f9fbbef0..6503ca8d2860 100644
--- a/compilerplugins/clang/implicitboolconversion.cxx
+++ b/compilerplugins/clang/implicitboolconversion.cxx
@@ -26,6 +26,14 @@ template<> struct std::iterator_traits<ExprIterator> {
typedef std::random_access_iterator_tag iterator_category;
};
+template<> struct std::iterator_traits<ConstExprIterator> {
+ typedef std::ptrdiff_t difference_type;
+ typedef Expr const * value_type;
+ typedef Expr const ** pointer;
+ typedef Expr const & reference;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+
namespace {
bool isBool(Expr const * expr, bool allowTypedefs = true) {
@@ -147,11 +155,13 @@ private:
void reportWarning(ImplicitCastExpr const * expr);
std::stack<std::vector<ImplicitCastExpr const *>> nested;
+ std::stack<CallExpr const *> calls;
bool externCIntFunctionDefinition = false;
};
bool ImplicitBoolConversion::TraverseCallExpr(CallExpr * expr) {
nested.push(std::vector<ImplicitCastExpr const *>());
+ calls.push(expr);
bool ret = RecursiveASTVisitor::TraverseCallExpr(expr);
Decl const * d = expr->getCalleeDecl();
bool ext = false;
@@ -203,6 +213,7 @@ bool ImplicitBoolConversion::TraverseCallExpr(CallExpr * expr) {
reportWarning(i);
}
}
+ calls.pop();
nested.pop();
return ret;
}
@@ -540,21 +551,40 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr(
} else {
nested.top().push_back(expr);
}
- } else {
- ExplicitCastExpr const * sub = dyn_cast<ExplicitCastExpr>(
- expr->getSubExpr()->IgnoreParenImpCasts());
- if (sub != nullptr
- && (sub->getSubExpr()->IgnoreParenImpCasts()->getType().IgnoreParens()
- == expr->getType().IgnoreParens())
- && isBool(sub->getSubExpr()->IgnoreParenImpCasts()))
+ return true;
+ }
+ ExplicitCastExpr const * sub = dyn_cast<ExplicitCastExpr>(
+ expr->getSubExpr()->IgnoreParenImpCasts());
+ if (sub != nullptr
+ && (sub->getSubExpr()->IgnoreParenImpCasts()->getType().IgnoreParens()
+ == expr->getType().IgnoreParens())
+ && isBool(sub->getSubExpr()->IgnoreParenImpCasts()))
+ {
+ report(
+ DiagnosticsEngine::Warning,
+ "explicit conversion (%0) from %1 to %2 implicitly cast back to %3",
+ expr->getLocStart())
+ << sub->getCastKindName()
+ << sub->getSubExpr()->IgnoreParenImpCasts()->getType()
+ << sub->getType() << expr->getType() << expr->getSourceRange();
+ return true;
+ }
+ if (expr->getType()->isBooleanType() && !isBool(expr->getSubExpr())
+ && !calls.empty())
+ {
+ CallExpr const * call = calls.top();
+ if (std::find_if(
+ call->arg_begin(), call->arg_end(),
+ [expr](Expr const * e) { return expr == e->IgnoreParens(); })
+ != call->arg_end())
{
report(
DiagnosticsEngine::Warning,
- "explicit conversion (%0) from %1 to %2 implicitly cast back to %3",
+ "implicit conversion (%0) of call argument from %1 to %2",
expr->getLocStart())
- << sub->getCastKindName()
- << sub->getSubExpr()->IgnoreParenImpCasts()->getType()
- << sub->getType() << expr->getType() << expr->getSourceRange();
+ << expr->getCastKindName() << expr->getSubExpr()->getType()
+ << expr->getType() << expr->getSourceRange();
+ return true;
}
}
return true;