]> granicus.if.org Git - clang/commitdiff
Enhance understanding of VarRegions referenced by a block whose declarations are...
authorTed Kremenek <kremenek@apple.com>
Fri, 11 Dec 2009 06:43:27 +0000 (06:43 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 11 Dec 2009 06:43:27 +0000 (06:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91107 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/AnalysisContext.h
include/clang/Analysis/PathSensitive/MemRegion.h
lib/Analysis/AnalysisContext.cpp
lib/Analysis/MemRegion.cpp
lib/Analysis/RegionStore.cpp
lib/Analysis/Store.cpp
test/Analysis/misc-ps-region-store.m

index 0a6646e55020ab9f1a1ececc5d99827a21e9565d..abc33b7784829381defcc3ce45960791a9bdc723 100644 (file)
@@ -120,6 +120,8 @@ public:
   }
   
   const StackFrameContext *getCurrentStackFrame() const;
+  const StackFrameContext *
+    getStackFrameForDeclContext(const DeclContext *DC) const;
 
   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
 
index efe4b9bb963a70f7f68ca72fac313dc56186ed22..45dab1ec842137adebe7ba09c29d7961e951ef09 100644 (file)
@@ -53,6 +53,7 @@ public:
     StackLocalsSpaceRegionKind,
     StackArgumentsSpaceRegionKind,
     HeapSpaceRegionKind,
+    UnknownSpaceRegionKind,
     GlobalsSpaceRegionKind,
     END_MEMSPACES = GlobalsSpaceRegionKind,
     // Untyped regions.
@@ -171,6 +172,16 @@ public:
   }
 };
   
+class UnknownSpaceRegion : public MemSpaceRegion {
+  friend class MemRegionManager;
+  UnknownSpaceRegion(MemRegionManager *mgr)
+    : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+public:
+  static bool classof(const MemRegion *R) {
+    return R->getKind() == UnknownSpaceRegionKind;
+  }
+};
+  
 class StackSpaceRegion : public MemSpaceRegion {
 private:
   const StackFrameContext *SFC;
@@ -757,16 +768,23 @@ class MemRegionManager {
   llvm::FoldingSet<MemRegion> Regions;
 
   GlobalsSpaceRegion *globals;
-  StackLocalsSpaceRegion *stackLocals;
-  StackArgumentsSpaceRegion *stackArguments;
+  
+  const StackFrameContext *cachedStackLocalsFrame;
+  StackLocalsSpaceRegion *cachedStackLocalsRegion;
+  
+  const StackFrameContext *cachedStackArgumentsFrame;
+  StackArgumentsSpaceRegion *cachedStackArgumentsRegion;
+
   HeapSpaceRegion *heap;
-  MemSpaceRegion *unknown;
+  UnknownSpaceRegion *unknown;
   MemSpaceRegion *code;
 
 public:
   MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
-    : C(c), A(a), globals(0), stackLocals(0), stackArguments(0), heap(0),
-      unknown(0), code(0) {}
+    : C(c), A(a), globals(0),
+      cachedStackLocalsFrame(0), cachedStackLocalsRegion(0),
+      cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0),
+      heap(0), unknown(0), code(0) {}
 
   ~MemRegionManager();
 
index 113587f60ed69ebdefe2b03f4bdfdbfa7dfaf8e0..3a6cf42a3d75b21b8c429477cdbb38694e5e3db5 100644 (file)
@@ -179,6 +179,19 @@ const StackFrameContext *LocationContext::getCurrentStackFrame() const {
   return NULL;
 }
 
+const StackFrameContext *
+LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
+  const LocationContext *LC = this;
+  while (LC) {
+    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
+      if (cast<DeclContext>(SFC->getDecl()) == DC)
+        return SFC;
+    }
+    LC = LC->getParent();
+  }
+  return NULL;
+}
+
 //===----------------------------------------------------------------------===//
 // Lazily generated map to query the external variables referenced by a Block.
 //===----------------------------------------------------------------------===//
index 3bf3e5b28a32d09d38db1040d33f4314ceee220a..da45c4dfee067ee20364967e98d412068d7112c5 100644 (file)
@@ -381,13 +381,22 @@ const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
 }
 
 const StackLocalsSpaceRegion*
-MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {  
-  return LazyAllocate(stackLocals, STC);
+MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
+  assert(STC);
+  if (STC == cachedStackLocalsFrame)
+    return cachedStackLocalsRegion;
+  cachedStackLocalsFrame = STC;
+  return LazyAllocate(cachedStackLocalsRegion, STC);
 }
 
 const StackArgumentsSpaceRegion *
 MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
-  return LazyAllocate(stackArguments, STC);
+  assert(STC);
+  if (STC == cachedStackArgumentsFrame)
+    return cachedStackArgumentsRegion;
+  
+  cachedStackArgumentsFrame = STC;
+  return LazyAllocate(cachedStackArgumentsRegion, STC);
 }
 
 const GlobalsSpaceRegion *MemRegionManager::getGlobalsRegion() {
@@ -418,15 +427,19 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
                                                 const LocationContext *LC) {
   const MemRegion *sReg = 0;
 
-  if (D->hasLocalStorage()) {
+  if (D->hasLocalStorage()) {    
     // FIXME: Once we implement scope handling, we will need to properly lookup
     // 'D' to the proper LocationContext.
-    const StackFrameContext *STC = LC->getCurrentStackFrame();
+    const DeclContext *DC = D->getDeclContext();
+    const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
 
-    assert(STC);
-    sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
-           ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
-           : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
+    if (!STC)
+      sReg = getUnknownRegion();
+    else {
+      sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
+            ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
+            : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
+    }
   }
   else {
     sReg = getGlobalsRegion();
index c718f1fbba23372a84a8f6dcccad73cdfdbcdde1..b5eeb1ea117036e0e39da49f62657b0411c253e4 100644 (file)
@@ -728,6 +728,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
       assert(0 && "Cannot index into a MemSpace");
       return UnknownVal();
 
@@ -881,6 +882,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
       assert(0 && "Cannot perform pointer arithmetic on a MemSpace");
       return UnknownVal();
   }
@@ -1292,7 +1294,8 @@ SVal RegionStoreManager::RetrieveVar(const GRState *state,
   // Lazily derive a value for the VarRegion.
   const VarDecl *VD = R->getDecl();
 
-  if (R->hasGlobalsOrParametersStorage())
+  if (R->hasGlobalsOrParametersStorage() ||
+      isa<UnknownSpaceRegion>(R->getMemorySpace()))
     return ValMgr.getRegionValueSymbolValOrUnknown(R, VD->getType());
 
   return UndefinedVal();
index be4ce2d57c63a25bc5094ead355b7db96e15ca4a..e6ff6e5af47f43f63c6de61aebcb2a3e069444fa 100644 (file)
@@ -81,6 +81,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
     case MemRegion::StackLocalsSpaceRegionKind:
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind: {
       assert(0 && "Invalid region cast");
       break;
index ee2043c214de59d79bb69ce33a9aac440ad7e082..f0304845925eb57ff223737ef6496cae74c096d6 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -fblocks %s
-// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -fblocks %s
+// RUN: clang-cc -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s
+// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -fblocks   -analyzer-opt-analyze-nested-blocks %s
 
 typedef struct objc_selector *SEL;
 typedef signed char BOOL;
@@ -583,3 +583,38 @@ int blocks_2(int *p, int z) {
   return z;
 }
 
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7462324> - Test that variables passed using __blocks
+//  are not treated as being uninitialized.
+//===----------------------------------------------------------------------===//
+
+typedef void (^RDar_7462324_Callback)(id obj);
+
+@interface RDar7462324
+- (void) foo:(id)target;
+- (void) foo_positive:(id)target;
+
+@end
+
+@implementation RDar7462324
+- (void) foo:(id)target {
+  __block RDar_7462324_Callback builder = ((void*) 0);
+  builder = ^(id object) {
+    if (object) {
+      builder(self); // no-warning
+    }
+  };
+  builder(target);
+}
+- (void) foo_positive:(id)target {
+  __block RDar_7462324_Callback builder = ((void*) 0);
+  builder = ^(id object) {
+    id x;
+    if (object) {
+      builder(x); // expected-warning{{Pass-by-value argument in function call is undefined}}
+    }
+  };
+  builder(target);
+}
+@end
+