Kaydet (Commit) 59076a98 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Improve loplugin:implicitboolconversion cond. expr. handling

...so that

  ... ? isdigit(...) : true

will not trigger a warning (where isdigit is the standard C function returning
int).  (Odd code like that will fall out of the improved
loplugin:literaltoboolconversion rewriter shortly.)

Change-Id: If51402bd5f4b3f8b0630e874988f4b836ae246f8
üst 2bf87d29
...@@ -278,6 +278,11 @@ public: ...@@ -278,6 +278,11 @@ public:
bool VisitImplicitCastExpr(ImplicitCastExpr const * expr); bool VisitImplicitCastExpr(ImplicitCastExpr const * expr);
private: private:
bool isExternCFunctionCall(
CallExpr const * expr, FunctionProtoType const ** functionType);
bool isExternCFunctionCallReturningInt(Expr const * expr);
void checkCXXConstructExpr(CXXConstructExpr const * expr); void checkCXXConstructExpr(CXXConstructExpr const * expr);
void reportWarning(ImplicitCastExpr const * expr); void reportWarning(ImplicitCastExpr const * expr);
...@@ -291,32 +296,8 @@ bool ImplicitBoolConversion::TraverseCallExpr(CallExpr * expr) { ...@@ -291,32 +296,8 @@ bool ImplicitBoolConversion::TraverseCallExpr(CallExpr * expr) {
nested.push(std::vector<ImplicitCastExpr const *>()); nested.push(std::vector<ImplicitCastExpr const *>());
calls.push(expr); calls.push(expr);
bool ret = RecursiveASTVisitor::TraverseCallExpr(expr); bool ret = RecursiveASTVisitor::TraverseCallExpr(expr);
Decl const * d = expr->getCalleeDecl(); FunctionProtoType const * t;
bool ext = false; bool ext = isExternCFunctionCall(expr, &t);
FunctionProtoType const * t = nullptr;
if (d != nullptr) {
FunctionDecl const * fd = dyn_cast<FunctionDecl>(d);
if (fd != nullptr && fd->isExternC()) {
ext = true;
PointerType const * pt = fd->getType()->getAs<PointerType>();
QualType t2(pt == nullptr ? fd->getType() : pt->getPointeeType());
t = t2->getAs<FunctionProtoType>();
assert(
t != nullptr || !compiler.getLangOpts().CPlusPlus
|| (fd->getBuiltinID() != Builtin::NotBuiltin
&& isa<FunctionNoProtoType>(t2)));
// __builtin_*s have no proto type?
} else {
VarDecl const * vd = dyn_cast<VarDecl>(d);
if (vd != nullptr && vd->isExternC())
{
ext = true;
PointerType const * pt = vd->getType()->getAs<PointerType>();
t = (pt == nullptr ? vd->getType() : pt->getPointeeType())
->castAs<FunctionProtoType>();
}
}
}
assert(!nested.empty()); assert(!nested.empty());
for (auto i: nested.top()) { for (auto i: nested.top()) {
auto j = std::find_if( auto j = std::find_if(
...@@ -512,9 +493,12 @@ bool ImplicitBoolConversion::TraverseConditionalOperator( ...@@ -512,9 +493,12 @@ bool ImplicitBoolConversion::TraverseConditionalOperator(
assert(!nested.empty()); assert(!nested.empty());
for (auto i: nested.top()) { for (auto i: nested.top()) {
if (!((i == expr->getTrueExpr()->IgnoreParens() if (!((i == expr->getTrueExpr()->IgnoreParens()
&& isBoolExpr(expr->getFalseExpr()->IgnoreParenImpCasts())) && (isBoolExpr(expr->getFalseExpr()->IgnoreParenImpCasts())
|| isExternCFunctionCallReturningInt(expr->getFalseExpr())))
|| (i == expr->getFalseExpr()->IgnoreParens() || (i == expr->getFalseExpr()->IgnoreParens()
&& isBoolExpr(expr->getTrueExpr()->IgnoreParenImpCasts())))) && (isBoolExpr(expr->getTrueExpr()->IgnoreParenImpCasts())
|| isExternCFunctionCallReturningInt(
expr->getTrueExpr())))))
{ {
reportWarning(i); reportWarning(i);
} }
...@@ -836,6 +820,47 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr( ...@@ -836,6 +820,47 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr(
return true; return true;
} }
bool ImplicitBoolConversion::isExternCFunctionCall(
CallExpr const * expr, FunctionProtoType const ** functionType)
{
assert(functionType != nullptr);
*functionType = nullptr;
Decl const * d = expr->getCalleeDecl();
if (d != nullptr) {
FunctionDecl const * fd = dyn_cast<FunctionDecl>(d);
if (fd != nullptr && fd->isExternC()) {
PointerType const * pt = fd->getType()->getAs<PointerType>();
QualType t2(pt == nullptr ? fd->getType() : pt->getPointeeType());
*functionType = t2->getAs<FunctionProtoType>();
assert(
*functionType != nullptr || !compiler.getLangOpts().CPlusPlus
|| (fd->getBuiltinID() != Builtin::NotBuiltin
&& isa<FunctionNoProtoType>(t2)));
// __builtin_*s have no proto type?
return true;
}
VarDecl const * vd = dyn_cast<VarDecl>(d);
if (vd != nullptr && vd->isExternC())
{
PointerType const * pt = vd->getType()->getAs<PointerType>();
*functionType
= ((pt == nullptr ? vd->getType() : pt->getPointeeType())
->castAs<FunctionProtoType>());
return true;
}
}
return false;
}
bool ImplicitBoolConversion::isExternCFunctionCallReturningInt(
Expr const * expr)
{
CallExpr const * e = dyn_cast<CallExpr>(expr->IgnoreParenImpCasts());
FunctionProtoType const * t;
return e != nullptr && e->getType()->isSpecificBuiltinType(BuiltinType::Int)
&& isExternCFunctionCall(e, &t);
}
void ImplicitBoolConversion::checkCXXConstructExpr( void ImplicitBoolConversion::checkCXXConstructExpr(
CXXConstructExpr const * expr) CXXConstructExpr const * expr)
{ {
......
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