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);
 }