aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/GRExprEngine.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-03-13 16:32:54 +0000
committerTed Kremenek <kremenek@apple.com>2009-03-13 16:32:54 +0000
commit6ae8a3600656c478d27f25639bed765f4fe71732 (patch)
tree72e6c24e666270695621194acb6c5dd04f070937 /lib/Analysis/GRExprEngine.cpp
parentd8eb456289a81728f9aac77ac0a4db0ea9cc231a (diff)
Add a hack in the analyzer to recover some path-sensitivity at branch
conditions. Currently the analyzer does not reason well about promotions/truncations of symbolic values, so at branch conditions when we see: if (condition) and condition is something like a 'short' or 'char', essentially ignore the promotion to 'int' so that we track constraints on the original symbolic value. We only ignore the casts if the underlying type has the same or fewer bits as the converted type. This fixes: <rdar://problem/6619921> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66899 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r--lib/Analysis/GRExprEngine.cpp59
1 files changed, 58 insertions, 1 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 6ff01fc5c9..6d360ed503 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -540,6 +540,45 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
}
}
+/// RecoverCastedSymbol - A helper function for ProcessBranch that is used
+/// to try to recover some path-sensitivity for casts of symbolic
+/// integers that promote their values (which are currently not tracked well).
+/// This function returns the SVal bound to Condition->IgnoreCasts if all the
+// cast(s) did was sign-extend the original value.
+static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
+ Stmt* Condition, ASTContext& Ctx) {
+
+ Expr *Ex = dyn_cast<Expr>(Condition);
+ if (!Ex)
+ return UnknownVal();
+
+ uint64_t bits = 0;
+ bool bitsInit = false;
+
+ while (CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ QualType T = CE->getType();
+
+ if (!T->isIntegerType())
+ return UnknownVal();
+
+ uint64_t newBits = Ctx.getTypeSize(T);
+ if (!bitsInit || newBits < bits) {
+ bitsInit = true;
+ bits = newBits;
+ }
+
+ Ex = CE->getSubExpr();
+ }
+
+ // We reached a non-cast. Is it a symbolic value?
+ QualType T = Ex->getType();
+
+ if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
+ return UnknownVal();
+
+ return StateMgr.GetSVal(state, Ex);
+}
+
void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
BranchNodeBuilder& builder) {
@@ -563,10 +602,28 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
default:
break;
- case SVal::UnknownKind:
+ case SVal::UnknownKind: {
+ if (Expr *Ex = dyn_cast<Expr>(Condition)) {
+ if (Ex->getType()->isIntegerType()) {
+ // Try to recover some path-sensitivity. Right now casts of symbolic
+ // integers that promote their values are currently not tracked well.
+ // If 'Condition' is such an expression, try and recover the
+ // underlying value and use that instead.
+ SVal recovered = RecoverCastedSymbol(getStateManager(),
+ builder.getState(), Condition,
+ getContext());
+
+ if (!recovered.isUnknown()) {
+ V = recovered;
+ break;
+ }
+ }
+ }
+
builder.generateNode(MarkBranch(PrevState, Term, true), true);
builder.generateNode(MarkBranch(PrevState, Term, false), false);
return;
+ }
case SVal::UndefinedKind: {
NodeTy* N = builder.generateNode(PrevState, true);