Merge remote-tracking branch 'origin/swift-3.1-branch' into stable

* origin/swift-3.1-branch:
  [analyzer] SValExplainer: Support ObjC ivars and __block variables.
  [analyzer] Minor fixes and improvements to debug.ExprInspection
  [analyzer] Fix a crash on accessing a field within a literal-initialized union.
diff --git a/docs/analyzer/DebugChecks.rst b/docs/analyzer/DebugChecks.rst
index bfa3142..ecf11ca 100644
--- a/docs/analyzer/DebugChecks.rst
+++ b/docs/analyzer/DebugChecks.rst
@@ -138,6 +138,17 @@
       clang_analyzer_warnIfReached();  // no-warning
     }
 
+- void clang_analyzer_numTimesReached();
+
+  Same as above, but include the number of times this call expression
+  gets reached by the analyzer during the current analysis.
+
+  Example usage::
+
+    for (int x = 0; x < 3; ++x) {
+      clang_analyzer_numTimesReached(); // expected-warning{{3}}
+    }
+
 - void clang_analyzer_warnOnDeadSymbol(int);
 
   Subscribe for a delayed warning when the symbol that represents the value of
@@ -180,6 +191,18 @@
         clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
     }
 
+- void clang_analyzer_dump(a single argument of any type);
+
+  Similar to clang_analyzer_explain, but produces a raw dump of the value,
+  same as SVal::dump().
+
+  Example usage::
+
+    void clang_analyzer_dump(int);
+    void foo(int x) {
+      clang_analyzer_dump(x); // expected-warning{{reg_$0<x>}}
+    }
+
 - size_t clang_analyzer_getExtent(void *);
 
   This function returns the value that represents the extent of a memory region
@@ -197,6 +220,22 @@
       clang_analyzer_explain(ys); // expected-warning{{'8'}}
     }
 
+- void clang_analyzer_printState();
+
+  Dumps the current ProgramState to the stderr. Quickly lookup the program state
+  at any execution point without ViewExplodedGraph or re-compiling the program.
+  This is not very useful for writing tests (apart from testing how ProgramState
+  gets printed), but useful for debugging tests. Also, this method doesn't
+  produce a warning, so it gets printed on the console before all other
+  ExprInspection warnings.
+
+  Example usage::
+
+    void foo() {
+      int x = 1;
+      clang_analyzer_printState(); // Read the stderr!
+    }
+
 Statistics
 ==========
 
diff --git a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 28cfbef..62bb0f6 100644
--- a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -142,6 +142,14 @@
     // TODO: Explain CXXThisRegion itself, find a way to test it.
     if (isThisObject(R))
       return "'this' object";
+    // Objective-C objects are not normal symbolic regions. At least,
+    // they're always on the heap.
+    if (R->getSymbol()->getType()
+            .getCanonicalType()->getAs<ObjCObjectPointerType>())
+      return "object at " + Visit(R->getSymbol());
+    // Other heap-based symbolic regions are also special.
+    if (isa<HeapSpaceRegion>(R->getMemorySpace()))
+      return "heap segment that starts at " + Visit(R->getSymbol());
     return "pointee of " + Visit(R->getSymbol());
   }
 
@@ -176,6 +184,8 @@
     std::string Name = VD->getQualifiedNameAsString();
     if (isa<ParmVarDecl>(VD))
       return "parameter '" + Name + "'";
+    else if (VD->hasAttr<BlocksAttr>())
+      return "block variable '" + Name + "'";
     else if (VD->hasLocalStorage())
       return "local variable '" + Name + "'";
     else if (VD->isStaticLocal())
@@ -186,6 +196,11 @@
       llvm_unreachable("A variable is either local or global");
   }
 
+  std::string VisitObjCIvarRegion(const ObjCIvarRegion *R) {
+    return "instance variable '" + R->getDecl()->getNameAsString() + "' of " +
+           Visit(R->getSuperRegion());
+  }
+
   std::string VisitFieldRegion(const FieldRegion *R) {
     return "field '" + R->getDecl()->getNameAsString() + "' of " +
            Visit(R->getSuperRegion());
diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 31e9150..2d5cb60 100644
--- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -18,25 +18,41 @@
 using namespace ento;
 
 namespace {
-class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> {
+class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
+                                             check::EndAnalysis> {
   mutable std::unique_ptr<BugType> BT;
 
+  // These stats are per-analysis, not per-branch, hence they shouldn't
+  // stay inside the program state.
+  struct ReachedStat {
+    ExplodedNode *ExampleNode;
+    unsigned NumTimesReached;
+  };
+  mutable llvm::DenseMap<const CallExpr *, ReachedStat> ReachedStats;
+
   void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
   void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
   void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const;
+  void analyzerNumTimesReached(const CallExpr *CE, CheckerContext &C) const;
   void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
   void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const;
+  void analyzerDump(const CallExpr *CE, CheckerContext &C) const;
   void analyzerExplain(const CallExpr *CE, CheckerContext &C) const;
+  void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const;
   void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const;
 
   typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
                                                  CheckerContext &C) const;
 
-  void reportBug(llvm::StringRef Msg, CheckerContext &C) const;
+  ExplodedNode *reportBug(llvm::StringRef Msg, CheckerContext &C) const;
+  ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR,
+                          ExplodedNode *N) const;
 
 public:
   bool evalCall(const CallExpr *CE, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                        ExprEngine &Eng) const;
 };
 }
 
@@ -56,7 +72,12 @@
     .Case("clang_analyzer_warnOnDeadSymbol",
           &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
     .Case("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
+    .Case("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump)
     .Case("clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent)
+    .Case("clang_analyzer_printState",
+          &ExprInspectionChecker::analyzerPrintState)
+    .Case("clang_analyzer_numTimesReached",
+          &ExprInspectionChecker::analyzerNumTimesReached)
     .Default(nullptr);
 
   if (!Handler)
@@ -98,16 +119,24 @@
   }
 }
 
-void ExprInspectionChecker::reportBug(llvm::StringRef Msg,
-                                      CheckerContext &C) const {
+ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
+                                               CheckerContext &C) const {
+  ExplodedNode *N = C.generateNonFatalErrorNode();
+  reportBug(Msg, C.getBugReporter(), N);
+  return N;
+}
+
+ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
+                                               BugReporter &BR,
+                                               ExplodedNode *N) const {
+  if (!N)
+    return nullptr;
+
   if (!BT)
     BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
-  ExplodedNode *N = C.generateNonFatalErrorNode();
-  if (!N)
-    return;
-
-  C.emitReport(llvm::make_unique<BugReport>(*BT, Msg, N));
+  BR.emitReport(llvm::make_unique<BugReport>(*BT, Msg, N));
+  return N;
 }
 
 void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
@@ -127,6 +156,15 @@
   reportBug("REACHABLE", C);
 }
 
+void ExprInspectionChecker::analyzerNumTimesReached(const CallExpr *CE,
+                                                    CheckerContext &C) const {
+  ++ReachedStats[CE].NumTimesReached;
+  if (!ReachedStats[CE].ExampleNode) {
+    // Later, in checkEndAnalysis, we'd throw a report against it.
+    ReachedStats[CE].ExampleNode = C.generateNonFatalErrorNode();
+  }
+}
+
 void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
                                                  CheckerContext &C) const {
   const LocationContext *LC = C.getPredecessor()->getLocationContext();
@@ -144,22 +182,43 @@
 
 void ExprInspectionChecker::analyzerExplain(const CallExpr *CE,
                                             CheckerContext &C) const {
-  if (CE->getNumArgs() == 0)
+  if (CE->getNumArgs() == 0) {
     reportBug("Missing argument for explaining", C);
+    return;
+  }
 
   SVal V = C.getSVal(CE->getArg(0));
   SValExplainer Ex(C.getASTContext());
   reportBug(Ex.Visit(V), C);
 }
 
+void ExprInspectionChecker::analyzerDump(const CallExpr *CE,
+                                         CheckerContext &C) const {
+  if (CE->getNumArgs() == 0) {
+    reportBug("Missing argument for dumping", C);
+    return;
+  }
+
+  SVal V = C.getSVal(CE->getArg(0));
+
+  llvm::SmallString<32> Str;
+  llvm::raw_svector_ostream OS(Str);
+  V.dumpToStream(OS);
+  reportBug(OS.str(), C);
+}
+
 void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
                                               CheckerContext &C) const {
-  if (CE->getNumArgs() == 0)
+  if (CE->getNumArgs() == 0) {
     reportBug("Missing region for obtaining extent", C);
+    return;
+  }
 
   auto MR = dyn_cast_or_null<SubRegion>(C.getSVal(CE->getArg(0)).getAsRegion());
-  if (!MR)
+  if (!MR) {
     reportBug("Obtaining extent of a non-region", C);
+    return;
+  }
 
   ProgramStateRef State = C.getState();
   State = State->BindExpr(CE, C.getLocationContext(),
@@ -167,6 +226,11 @@
   C.addTransition(State);
 }
 
+void ExprInspectionChecker::analyzerPrintState(const CallExpr *CE,
+                                               CheckerContext &C) const {
+  C.getState()->dump();
+}
+
 void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE,
                                                      CheckerContext &C) const {
   if (CE->getNumArgs() == 0)
@@ -185,15 +249,28 @@
                                              CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
+  ExplodedNode *N = C.getPredecessor();
   for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
     SymbolRef Sym = *I;
     if (!SymReaper.isDead(Sym))
       continue;
 
-    reportBug("SYMBOL DEAD", C);
+    // The non-fatal error node should be the same for all reports.
+    if (ExplodedNode *BugNode = reportBug("SYMBOL DEAD", C))
+      N = BugNode;
     State = State->remove<MarkedSymbols>(Sym);
   }
-  C.addTransition(State);
+  C.addTransition(State, N);
+}
+
+void ExprInspectionChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                                             ExprEngine &Eng) const {
+  for (auto Item: ReachedStats) {
+    unsigned NumTimesReached = Item.second.NumTimesReached;
+    ExplodedNode *N = Item.second.ExampleNode;
+
+    reportBug(std::to_string(NumTimesReached), BR, N);
+  }
 }
 
 void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 5de3af9..a19869d9 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1674,7 +1674,8 @@
 
     // Lazy bindings are usually handled through getExistingLazyBinding().
     // We should unify these two code paths at some point.
-    if (val.getAs<nonloc::LazyCompoundVal>())
+    if (val.getAs<nonloc::LazyCompoundVal>() ||
+        val.getAs<nonloc::CompoundVal>())
       return val;
 
     llvm_unreachable("Unknown default value");
diff --git a/test/Analysis/explain-svals.cpp b/test/Analysis/explain-svals.cpp
index c0ed749..ef2ebc2 100644
--- a/test/Analysis/explain-svals.cpp
+++ b/test/Analysis/explain-svals.cpp
@@ -47,7 +47,7 @@
   clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob_ptr'$}}}}
   clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re{{{{^extent of pointee of argument 'ptr'$}}}}
   int *x = new int[ext];
-  clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of pointee of symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
+  clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
   // Sic! What gets computed is the extent of the element-region.
   clang_analyzer_explain(clang_analyzer_getExtent(x)); // expected-warning-re{{{{^signed 32-bit integer '4'$}}}}
   delete[] x;
diff --git a/test/Analysis/explain-svals.m b/test/Analysis/explain-svals.m
new file mode 100644
index 0000000..34cdacf
--- /dev/null
+++ b/test/Analysis/explain-svals.m
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -w -triple i386-apple-darwin10 -fblocks -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void clang_analyzer_explain(void *);
+
+@interface Object : NSObject {
+@public
+  Object *x;
+}
+@end
+
+void test_1(Object *p) {
+  clang_analyzer_explain(p); // expected-warning-re{{{{^argument 'p'$}}}}
+  clang_analyzer_explain(p->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at argument 'p'$}}}}
+  Object *q = [[Object alloc] init];
+  clang_analyzer_explain(q); // expected-warning-re{{{{^symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
+  clang_analyzer_explain(q->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
+}
+
+void test_2() {
+  __block int x;
+  ^{
+    clang_analyzer_explain(&x); // expected-warning-re{{{{^pointer to block variable 'x'$}}}}
+  };
+  clang_analyzer_explain(&x); // expected-warning-re{{{{^pointer to block variable 'x'$}}}}
+}
diff --git a/test/Analysis/expr-inspection.c b/test/Analysis/expr-inspection.c
new file mode 100644
index 0000000..14e12ec
--- /dev/null
+++ b/test/Analysis/expr-inspection.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -verify %s 2>&1 | FileCheck %s
+
+// Self-tests for the debug.ExprInspection checker.
+
+void clang_analyzer_dump(int x);
+void clang_analyzer_printState();
+void clang_analyzer_numTimesReached();
+
+void foo(int x) {
+  clang_analyzer_dump(x); // expected-warning{{reg_$0<x>}}
+  int y = 1;
+  clang_analyzer_printState();
+  for (; y < 3; ++y)
+    clang_analyzer_numTimesReached(); // expected-warning{{2}}
+}
+
+// CHECK: Store (direct and default bindings)
+// CHECK-NEXT: (y,0,direct) : 1 S32b
+
+// CHECK: Expressions:
+// CHECK-NEXT: clang_analyzer_printState : &code{clang_analyzer_printState}
+// CHECK-NEXT: Ranges are empty.
diff --git a/test/Analysis/symbol-reaper.c b/test/Analysis/symbol-reaper.c
index 4051c38..362a22d 100644
--- a/test/Analysis/symbol-reaper.c
+++ b/test/Analysis/symbol-reaper.c
@@ -2,6 +2,7 @@
 
 void clang_analyzer_eval(int);
 void clang_analyzer_warnOnDeadSymbol(int);
+void clang_analyzer_numTimesReached();
 
 int conjure_index();
 
@@ -10,6 +11,9 @@
     int x = conjure_index();
     clang_analyzer_warnOnDeadSymbol(x);
   } while(0); // expected-warning{{SYMBOL DEAD}}
+
+  // Make sure we don't accidentally split state in ExprInspection.
+  clang_analyzer_numTimesReached(); // expected-warning{{1}}
 }
 
 // These tests verify the reaping of symbols that are only referenced as
diff --git a/test/Analysis/uninit-vals-union.c b/test/Analysis/uninit-vals-union.c
new file mode 100644
index 0000000..927dfa2
--- /dev/null
+++ b/test/Analysis/uninit-vals-union.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.builtin -analyzer-store=region -verify -Wno-unused %s
+
+typedef union {
+  int y;
+} U;
+
+typedef struct { int x; } A;
+
+void foo() {
+  U u = {};
+  A *a = &u; // expected-warning{{incompatible pointer types}}
+  a->x;      // no-crash
+}