diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-04-26 21:42:55 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-04-26 21:42:55 +0000 |
commit | 5e6c06bc7deaaefe130b730032a9acb9cd38bf0c (patch) | |
tree | 8e421a4cae28be86511b2f22ec3e2e2986ee5177 /lib/StaticAnalyzer/Core/SValBuilder.cpp | |
parent | ed6847ee6944757dfc4911abb29c6fc2d7cf9d79 (diff) |
[analyzer] Model casts to bool differently from other numbers.
Casts to bool (and _Bool) are equivalent to checks against zero,
not truncations to 1 bit or 8 bits.
This improved reasoning does cause a change in the behavior of the alpha
BoolAssignment checker. Previously, this checker complained about statements
like "bool x = y" if 'y' was known not to be 0 or 1. Now it does not, since
that conversion is well-defined. It's hard to say what the "best" behavior
here is: this conversion is safe, but might be better written as an explicit
comparison against zero.
More usefully, besides improving our model of booleans, this fixes spurious
warnings when returning the address of a local variable cast to bool.
<rdar://problem/13296133>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180638 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/SValBuilder.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/SValBuilder.cpp | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 309230ebed..5bab986ed0 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -327,6 +327,22 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { if (val.isUnknownOrUndef() || castTy == originalTy) return val; + if (castTy->isBooleanType()) { + if (val.isUnknownOrUndef()) + return val; + if (val.isConstant()) + return makeTruthVal(!val.isZeroConstant(), castTy); + if (SymbolRef Sym = val.getAsSymbol()) { + BasicValueFactory &BVF = getBasicValueFactory(); + // FIXME: If we had a state here, we could see if the symbol is known to + // be zero, but we don't. + return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy); + } + + assert(val.getAs<Loc>()); + return makeTruthVal(true, castTy); + } + // For const casts, casts to void, just propagate the value. if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType()) if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy), |