[analyzer] Teach UndefOrNullArgVisitor to track parent regions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163748 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 0d0006c..be94684 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -517,6 +517,8 @@
     // However, if the rvalue is a symbolic region, we should track it as well.
     SVal RVal = state->getSVal(L->getRegion());
     const MemRegion *RegionRVal = RVal.getAsRegion();
+    report.addVisitor(new UndefOrNullArgVisitor(L->getRegion()));
+
 
     if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
       report.markInteresting(RegionRVal);
@@ -985,8 +987,8 @@
                                  E = Call->param_end(); I != E; ++I, ++Idx) {
     const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
 
-    // Are we tracking the argument?
-    if ( !ArgReg || ArgReg != R)
+    // Are we tracking the argument or its subregion?
+    if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts())))
       continue;
 
     // Check the function parameter type.
@@ -1006,7 +1008,7 @@
 
     // Mark the call site (LocationContext) as interesting if the value of the 
     // argument is undefined or '0'/'NULL'.
-    SVal BoundVal = State->getSVal(ArgReg);
+    SVal BoundVal = State->getSVal(R);
     if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
       BR.markInteresting(CEnter->getCalleeContext());
       return 0;
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index b29327e..6d6bb20 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -990,6 +990,26 @@
   return R;
 }
 
+bool MemRegion::isSubRegionOf(const MemRegion *PR) const {
+  const MemRegion *R = this;
+  while (true) {
+    switch (R->getKind()) {
+      case MemRegion::ElementRegionKind:
+      case MemRegion::FieldRegionKind:
+      case MemRegion::ObjCIvarRegionKind:
+      case MemRegion::CXXBaseObjectRegionKind:
+        R = cast<SubRegion>(R)->getSuperRegion();
+        if (R == PR)
+          return true;
+        continue;
+      default:
+        break;
+    }
+    break;
+  }
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // View handling.
 //===----------------------------------------------------------------------===//