From 7afd71e4ff5d13fdea68cd1261a96b19488d39db Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Tue, 20 May 2014 17:31:11 +0000 Subject: Add a check for tautological bitwise comparisons to -Wtautological-compare. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This catches issues like: if ((x & 8) == 4) { ... } if ((x | 4) != 3) { ... } Patch by Anders Rönnholm! llvm-svn: 209221 --- clang/lib/Analysis/CFG.cpp | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'clang/lib/Analysis') diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 3139ae4c5d3..5d2926c0f0e 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -534,9 +534,10 @@ private: } } - /// Find a equality comparison with an expression evaluating to a boolean and - /// a constant other than 0 and 1. - /// e.g. if (!x == 10) + /// Find an incorrect equality comparison. Either with an expression + /// evaluating to a boolean and a constant other than 0 and 1. + /// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to + /// true/false e.q. (x & 8) == 4. TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) { const Expr *LHSExpr = B->getLHS()->IgnoreParens(); const Expr *RHSExpr = B->getRHS()->IgnoreParens(); @@ -549,15 +550,41 @@ private: BoolExpr = LHSExpr; } - if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue()) + if (!IntLiteral) return TryResult(); - llvm::APInt IntValue = IntLiteral->getValue(); - if ((IntValue == 1) || (IntValue == 0)) { - return TryResult(); + const BinaryOperator *BitOp = dyn_cast(BoolExpr); + if (BitOp && (BitOp->getOpcode() == BO_And || + BitOp->getOpcode() == BO_Or)) { + const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens(); + const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens(); + + const IntegerLiteral *IntLiteral2 = dyn_cast(LHSExpr2); + + if (!IntLiteral2) + IntLiteral2 = dyn_cast(RHSExpr2); + + if (!IntLiteral2) + return TryResult(); + + llvm::APInt L1 = IntLiteral->getValue(); + llvm::APInt L2 = IntLiteral2->getValue(); + if ((BitOp->getOpcode() == BO_And && (L2 & L1) != L1) || + (BitOp->getOpcode() == BO_Or && (L2 | L1) != L1)) { + if (BuildOpts.Observer) + BuildOpts.Observer->compareBitwiseEquality(B, + B->getOpcode() != BO_EQ); + TryResult(B->getOpcode() != BO_EQ); + } + } else if (BoolExpr->isKnownToHaveBooleanValue()) { + llvm::APInt IntValue = IntLiteral->getValue(); + if ((IntValue == 1) || (IntValue == 0)) { + return TryResult(); + } + return TryResult(B->getOpcode() != BO_EQ); } - return TryResult(B->getOpcode() != BO_EQ); + return TryResult(); } TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation, -- cgit v1.2.3