Implement analyzer support for OSCompareAndSwap. This required pushing "tagged"
ProgramPoints all the way through to GRCoreEngine.

NSString.m now fails with RegionStoreManager because of the void** cast.
Disabling use of region store for that test for now.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68845 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 41776ed..566c197 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -282,6 +282,23 @@
     return UnknownVal();
 }
 
+static bool isHigherOrderVoidPtr(QualType T, ASTContext &C) {
+  bool foundPointer = false;
+  while (1) {  
+    const PointerType *PT = T->getAsPointerType();
+    if (!PT) {
+      if (!foundPointer)
+        return false;
+      
+      QualType X = C.getCanonicalType(T).getUnqualifiedType();
+      return X == C.VoidTy;
+    }
+    
+    foundPointer = true;
+    T = PT->getPointeeType();
+  }  
+}
+
 SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
   
   if (isa<UnknownVal>(loc))
@@ -294,6 +311,20 @@
     case loc::MemRegionKind: {
       const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
       
+      if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
+        // Just support void**, void***, etc., for now.  This is needed
+        // to handle OSCompareAndSwapPtr().
+        ASTContext &Ctx = StateMgr.getContext();
+        QualType T = TR->getLValueType(Ctx);
+
+        if (!isHigherOrderVoidPtr(T, Ctx))
+          return UnknownVal();
+        
+        // Otherwise, strip the views.
+        // FIXME: Should we layer a TypedView on the result?
+        R = TR->removeViews();
+      }
+      
       if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
         return UnknownVal();