summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-04-23 17:18:32 +0200
committerStephan Bergmann <sbergman@redhat.com>2015-04-23 18:39:06 +0200
commit59076a982599ea391217b14d9eeff06db3a4e08e (patch)
treeac1dfabad73a582f97fffa920db32736aa41882a /compilerplugins
parent2bf87d29cceb369f030feeaeab6ee25541d8559a (diff)
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
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/implicitboolconversion.cxx81
1 files changed, 53 insertions, 28 deletions
diff --git a/compilerplugins/clang/implicitboolconversion.cxx b/compilerplugins/clang/implicitboolconversion.cxx
index 57d00165fc64..41ece58d1f7a 100644
--- a/compilerplugins/clang/implicitboolconversion.cxx
+++ b/compilerplugins/clang/implicitboolconversion.cxx
@@ -278,6 +278,11 @@ public:
bool VisitImplicitCastExpr(ImplicitCastExpr const * expr);
private:
+ bool isExternCFunctionCall(
+ CallExpr const * expr, FunctionProtoType const ** functionType);
+
+ bool isExternCFunctionCallReturningInt(Expr const * expr);
+
void checkCXXConstructExpr(CXXConstructExpr const * expr);
void reportWarning(ImplicitCastExpr const * expr);
@@ -291,32 +296,8 @@ 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;
- 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>();
- }
- }
- }
+ FunctionProtoType const * t;
+ bool ext = isExternCFunctionCall(expr, &t);
assert(!nested.empty());
for (auto i: nested.top()) {
auto j = std::find_if(
@@ -512,9 +493,12 @@ bool ImplicitBoolConversion::TraverseConditionalOperator(
assert(!nested.empty());
for (auto i: nested.top()) {
if (!((i == expr->getTrueExpr()->IgnoreParens()
- && isBoolExpr(expr->getFalseExpr()->IgnoreParenImpCasts()))
+ && (isBoolExpr(expr->getFalseExpr()->IgnoreParenImpCasts())
+ || isExternCFunctionCallReturningInt(expr->getFalseExpr())))
|| (i == expr->getFalseExpr()->IgnoreParens()
- && isBoolExpr(expr->getTrueExpr()->IgnoreParenImpCasts()))))
+ && (isBoolExpr(expr->getTrueExpr()->IgnoreParenImpCasts())
+ || isExternCFunctionCallReturningInt(
+ expr->getTrueExpr())))))
{
reportWarning(i);
}
@@ -836,6 +820,47 @@ bool ImplicitBoolConversion::VisitImplicitCastExpr(
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(
CXXConstructExpr const * expr)
{