зеркало из https://github.com/microsoft/clang-1.git
[analyzer] Use SymExprs to represent '<loc> - <loc>' and '<loc> == <loc>'.
We just treat this as opaque symbols, but even that allows us to handle simple cases where the same condition is tested twice. This is very common in the STL, which means that any project using the STL gets spurious errors. Part of <rdar://problem/13239003>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177800 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
168613735d
Коммит
8958efacf8
|
@ -508,22 +508,21 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
|
|||
// Otherwise, make a SymIntExpr out of the expression.
|
||||
return MakeSymIntVal(symIntExpr, op, *RHSValue, resultTy);
|
||||
}
|
||||
|
||||
|
||||
} else if (isa<SymbolData>(Sym)) {
|
||||
// Does the symbol simplify to a constant? If so, "fold" the constant
|
||||
// by setting 'lhs' to a ConcreteInt and try again.
|
||||
if (const llvm::APSInt *Constant = state->getConstraintManager()
|
||||
.getSymVal(state, Sym)) {
|
||||
lhs = nonloc::ConcreteInt(*Constant);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is the RHS a constant?
|
||||
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
|
||||
return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
|
||||
}
|
||||
|
||||
// Does the symbolic expression simplify to a constant?
|
||||
// If so, "fold" the constant by setting 'lhs' to a ConcreteInt
|
||||
// and try again.
|
||||
ConstraintManager &CMgr = state->getConstraintManager();
|
||||
if (const llvm::APSInt *Constant = CMgr.getSymVal(state, Sym)) {
|
||||
lhs = nonloc::ConcreteInt(*Constant);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is the RHS a constant?
|
||||
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
|
||||
return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
|
||||
|
||||
// Give up -- this is not a symbolic expression we can handle.
|
||||
return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
|
||||
}
|
||||
|
@ -682,11 +681,11 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
// regions, though.
|
||||
return UnknownVal();
|
||||
|
||||
const MemSpaceRegion *LeftMS = LeftMR->getMemorySpace();
|
||||
const MemSpaceRegion *RightMS = RightMR->getMemorySpace();
|
||||
const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion();
|
||||
const MemRegion *LeftBase = LeftMR->getBaseRegion();
|
||||
const MemRegion *RightBase = RightMR->getBaseRegion();
|
||||
const MemSpaceRegion *LeftMS = LeftBase->getMemorySpace();
|
||||
const MemSpaceRegion *RightMS = RightBase->getMemorySpace();
|
||||
const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion();
|
||||
|
||||
// If the two regions are from different known memory spaces they cannot be
|
||||
// equal. Also, assume that no symbolic region (whose memory space is
|
||||
|
@ -789,7 +788,6 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
}
|
||||
|
||||
// If we get here, we have no way of comparing the ElementRegions.
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
// See if both regions are fields of the same structure.
|
||||
|
@ -842,6 +840,13 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
|
|||
llvm_unreachable("Fields not found in parent record's definition");
|
||||
}
|
||||
|
||||
// At this point we're not going to get a good answer, but we can try
|
||||
// conjuring an expression instead.
|
||||
SymbolRef LHSSym = lhs.getAsLocSymbol();
|
||||
SymbolRef RHSSym = rhs.getAsLocSymbol();
|
||||
if (LHSSym && RHSSym)
|
||||
return makeNonLoc(LHSSym, op, RHSSym, resultTy);
|
||||
|
||||
// If we get here, we have no way of comparing the regions.
|
||||
return UnknownVal();
|
||||
}
|
||||
|
|
|
@ -167,3 +167,15 @@ void PR7527 (int *p) {
|
|||
if (((int) p) & 1) // not crash
|
||||
return;
|
||||
}
|
||||
|
||||
void use_symbols(int *lhs, int *rhs) {
|
||||
clang_analyzer_eval(lhs < rhs); // expected-warning{{UNKNOWN}}
|
||||
if (lhs < rhs)
|
||||
return;
|
||||
clang_analyzer_eval(lhs < rhs); // expected-warning{{FALSE}}
|
||||
|
||||
clang_analyzer_eval(lhs - rhs); // expected-warning{{UNKNOWN}}
|
||||
if ((lhs - rhs) != 5)
|
||||
return;
|
||||
clang_analyzer_eval((lhs - rhs) == 5); // expected-warning{{TRUE}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче