diff options
author | Richard Trieu <rtrieu@google.com> | 2019-10-19 00:57:23 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2019-10-19 00:57:23 +0000 |
commit | 8b0d14a8f0cc085afa2a9c86c237da81c74517fc (patch) | |
tree | 10b826bafb00b240997f245466199e6350a9edd1 /clang/lib/Analysis | |
parent | b081220cfd46965fa25dbf826cd3f42f4f9e54cd (diff) | |
download | bcm5719-llvm-8b0d14a8f0cc085afa2a9c86c237da81c74517fc.tar.gz bcm5719-llvm-8b0d14a8f0cc085afa2a9c86c237da81c74517fc.zip |
New tautological warning for bitwise-or with non-zero constant always true.
Taking a value and the bitwise-or it with a non-zero constant will always
result in a non-zero value. In a boolean context, this is always true.
if (x | 0x4) {} // always true, intended '&'
This patch creates a new warning group -Wtautological-bitwise-compare for this
warning. It also moves in the existing tautological bitwise comparisons into
this group. A few other changes were needed to the CFGBuilder so that all bool
contexts would be checked. The warnings in -Wtautological-bitwise-compare will
be off by default due to using the CFG.
Fixes: https://bugs.llvm.org/show_bug.cgi?id=42666
Differential Revision: https://reviews.llvm.org/D66046
llvm-svn: 375318
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 54fb388b0c6..a533a8d97b8 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1139,6 +1139,31 @@ private: return {}; } + /// A bitwise-or with a non-zero constant always evaluates to true. + TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) { + const Expr *LHSConstant = + tryTransformToIntOrEnumConstant(B->getLHS()->IgnoreParenImpCasts()); + const Expr *RHSConstant = + tryTransformToIntOrEnumConstant(B->getRHS()->IgnoreParenImpCasts()); + + if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant)) + return {}; + + const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant; + + Expr::EvalResult Result; + if (!Constant->EvaluateAsInt(Result, *Context)) + return {}; + + if (Result.Val.getInt() == 0) + return {}; + + if (BuildOpts.Observer) + BuildOpts.Observer->compareBitwiseOr(B); + + return TryResult(true); + } + /// Try and evaluate an expression to an integer constant. bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { if (!BuildOpts.PruneTriviallyFalseEdges) @@ -1156,7 +1181,7 @@ private: return {}; if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { - if (Bop->isLogicalOp()) { + if (Bop->isLogicalOp() || Bop->isEqualityOp()) { // Check the cache first. CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); if (I != CachedBoolEvals.end()) @@ -1240,6 +1265,10 @@ private: TryResult BopRes = checkIncorrectRelationalOperator(Bop); if (BopRes.isKnown()) return BopRes.isTrue(); + } else if (Bop->getOpcode() == BO_Or) { + TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop); + if (BopRes.isKnown()) + return BopRes.isTrue(); } } @@ -2340,6 +2369,9 @@ CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, appendStmt(Block, U); } + if (U->getOpcode() == UO_LNot) + tryEvaluateBool(U->getSubExpr()->IgnoreParens()); + return Visit(U->getSubExpr(), AddStmtChoice()); } @@ -2474,6 +2506,9 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, appendStmt(Block, B); } + if (B->isEqualityOp() || B->isRelationalOp()) + tryEvaluateBool(B); + CFGBlock *RBlock = Visit(B->getRHS()); CFGBlock *LBlock = Visit(B->getLHS()); // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr @@ -4527,6 +4562,10 @@ CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, autoCreateBlock(); appendStmt(Block, E); } + + if (E->getCastKind() == CK_IntegralToBoolean) + tryEvaluateBool(E->getSubExpr()->IgnoreParens()); + return Visit(E->getSubExpr(), AddStmtChoice()); } |