|
@@ -1139,6 +1139,31 @@ private:
|
|
return {};
|
|
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.
|
|
/// Try and evaluate an expression to an integer constant.
|
|
bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
|
|
bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
|
|
if (!BuildOpts.PruneTriviallyFalseEdges)
|
|
if (!BuildOpts.PruneTriviallyFalseEdges)
|
|
@@ -1156,7 +1181,7 @@ private:
|
|
return {};
|
|
return {};
|
|
|
|
|
|
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
|
|
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
|
|
- if (Bop->isLogicalOp()) {
|
|
|
|
|
|
+ if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
|
|
// Check the cache first.
|
|
// Check the cache first.
|
|
CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
|
|
CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
|
|
if (I != CachedBoolEvals.end())
|
|
if (I != CachedBoolEvals.end())
|
|
@@ -1240,6 +1265,10 @@ private:
|
|
TryResult BopRes = checkIncorrectRelationalOperator(Bop);
|
|
TryResult BopRes = checkIncorrectRelationalOperator(Bop);
|
|
if (BopRes.isKnown())
|
|
if (BopRes.isKnown())
|
|
return BopRes.isTrue();
|
|
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);
|
|
appendStmt(Block, U);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (U->getOpcode() == UO_LNot)
|
|
|
|
+ tryEvaluateBool(U->getSubExpr()->IgnoreParens());
|
|
|
|
+
|
|
return Visit(U->getSubExpr(), AddStmtChoice());
|
|
return Visit(U->getSubExpr(), AddStmtChoice());
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2474,6 +2506,9 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
|
|
appendStmt(Block, B);
|
|
appendStmt(Block, B);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (B->isEqualityOp() || B->isRelationalOp())
|
|
|
|
+ tryEvaluateBool(B);
|
|
|
|
+
|
|
CFGBlock *RBlock = Visit(B->getRHS());
|
|
CFGBlock *RBlock = Visit(B->getRHS());
|
|
CFGBlock *LBlock = Visit(B->getLHS());
|
|
CFGBlock *LBlock = Visit(B->getLHS());
|
|
// If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
|
|
// 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();
|
|
autoCreateBlock();
|
|
appendStmt(Block, E);
|
|
appendStmt(Block, E);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (E->getCastKind() == CK_IntegralToBoolean)
|
|
|
|
+ tryEvaluateBool(E->getSubExpr()->IgnoreParens());
|
|
|
|
+
|
|
return Visit(E->getSubExpr(), AddStmtChoice());
|
|
return Visit(E->getSubExpr(), AddStmtChoice());
|
|
}
|
|
}
|
|
|
|
|