Add corner case logic to BasicStoreManager and GRSimpleVals::EvalBinOp to enable
reasoning about OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. Essentially
the address of reference to a region (pointer-to-pointer) can be casted to
(int32_t*), and we need to handle the logic to convert the involved locations
back and forth from nonloc::LocAsInteger, nonloc::ConcreteInt, to Loc and
loc::ConcreteInt respectively. This adds some potentially suspect logic to
BasicStoreManager that allows the analyzer to reason about abuses of the C type
system. This should probably be refined, be ported over to RegionStoreManager,
and extended with "path-sensitive type checking" to flag bugs in clearly
incoherent code.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70382 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index 413ef7b..8600138 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -262,7 +262,22 @@
}
SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
- Loc L, NonLoc R) {
+ Loc L, NonLoc R) {
+
+ // Special case: 'R' is an integer that has the same width as a pointer and
+ // we are using the integer location in a comparison. Normally this cannot be
+ // triggered, but transfer functions like those for OSCommpareAndSwapBarrier32
+ // can generate comparisons that trigger this code.
+ // FIXME: Are all locations guaranteed to have pointer width?
+ if (BinaryOperator::isEqualityOp(Op)) {
+ if (nonloc::ConcreteInt *RInt = dyn_cast<nonloc::ConcreteInt>(&R)) {
+ const llvm::APSInt &X = RInt->getValue();
+ ASTContext &C = Eng.getContext();
+ if (C.getTypeSize(C.VoidPtrTy) == X.getBitWidth())
+ return EvalBinOp(Eng, Op, L, loc::ConcreteInt(X));
+ }
+ }
+
// Delegate pointer arithmetic to store manager.
return Eng.getStoreManager().EvalBinOp(Op, L, R);
}