[analyzer] Fix symbolication for unknown unary increment/decrement results.
If the value is known, but we cannot increment it, conjure a symbol to represent the result of the operation based on the operator expression, not on the sub-expression. In particular, no longer crash on comparing a result of a LocAsInteger increment to a constant integer. rdar://problem/31067356 Differential Revision: https://reviews.llvm.org/D31289 llvm-svn: 298927
This commit is contained in:
parent
5d39a98612
commit
7333a9ea11
|
@ -1054,7 +1054,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
|
|||
// Conjure a new symbol if necessary to recover precision.
|
||||
if (Result.isUnknown()){
|
||||
DefinedOrUnknownSVal SymVal =
|
||||
svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
|
||||
svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
|
||||
currBldrCtx->blockCount());
|
||||
Result = SymVal;
|
||||
|
||||
|
|
|
@ -362,6 +362,9 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
|
|||
resultTy);
|
||||
case nonloc::ConcreteIntKind: {
|
||||
// Transform the integer into a location and compare.
|
||||
// FIXME: This only makes sense for comparisons. If we want to, say,
|
||||
// add 1 to a LocAsInteger, we'd better unpack the Loc and add to it,
|
||||
// then pack it back into a LocAsInteger.
|
||||
llvm::APSInt i = rhs.castAs<nonloc::ConcreteInt>().getValue();
|
||||
BasicVals.getAPSIntType(Context.VoidPtrTy).apply(i);
|
||||
return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
|
||||
|
@ -942,6 +945,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
|
||||
SVal index = UnknownVal();
|
||||
const MemRegion *superR = nullptr;
|
||||
// We need to know the type of the pointer in order to add an integer to it.
|
||||
// Depending on the type, different amount of bytes is added.
|
||||
QualType elementType;
|
||||
|
||||
if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
|
||||
|
@ -955,6 +960,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
|
|||
assert(op == BO_Add || op == BO_Sub);
|
||||
index = (op == BO_Add) ? rhs : evalMinus(rhs);
|
||||
superR = region;
|
||||
// TODO: Is this actually reliable? Maybe improving our MemRegion
|
||||
// hierarchy to provide typed regions for all non-void pointers would be
|
||||
// better. For instance, we cannot extend this towards LocAsInteger
|
||||
// operations, where result type of the expression is integer.
|
||||
if (resultTy->isAnyPointerType())
|
||||
elementType = resultTy->getPointeeType();
|
||||
}
|
||||
|
|
|
@ -118,3 +118,8 @@ void castsToBool() {
|
|||
extern float globalFloat;
|
||||
clang_analyzer_eval(globalFloat); // expected-warning{{UNKNOWN}}
|
||||
}
|
||||
|
||||
void locAsIntegerCasts(void *p) {
|
||||
int x = (int) p;
|
||||
clang_analyzer_eval(++x < 10); // no-crash // expected-warning{{UNKNOWN}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue