[analyzer] Add a simple check for initializing reference variables with null.

There's still more work to be done here; this doesn't catch reference
parameters or return values. But it's a step in the right direction.

Part of <rdar://problem/11212286>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161214 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index 3f008ff..f7a6fd7 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -43,3 +43,24 @@
   IndirectMember obj(3);
   clang_analyzer_eval(obj.getX() == 3); // expected-warning{{TRUE}}
 }
+
+
+// ------------------------------------
+// False negatives
+// ------------------------------------
+
+struct RefWrapper {
+  RefWrapper(int *p) : x(*p) {}
+  RefWrapper(int &r) : x(r) {}
+  int &x;
+};
+
+void testReferenceMember() {
+  int *p = 0;
+  RefWrapper X(p); // should warn in the constructor
+}
+
+void testReferenceMember2() {
+  int *p = 0;
+  RefWrapper X(*p); // should warn here
+}
diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp
index 381aa03..fcffe07 100644
--- a/test/Analysis/misc-ps-region-store.cpp
+++ b/test/Analysis/misc-ps-region-store.cpp
@@ -271,13 +271,27 @@
 const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) {
   const Rdar9212495_A& val = dynamic_cast<const Rdar9212495_A&>(*ptr);
   
+  // This is not valid C++; dynamic_cast with a reference type will throw an
+  // exception if the pointer does not match the expected type.
   if (&val == 0) {
-    val.bar(); // FIXME: This should eventually be a null dereference.
+    val.bar(); // no warning (unreachable)
+    int *p = 0;
+    *p = 0xDEAD; // no warning (unreachable)
   }
   
   return val;
 }
 
+const Rdar9212495_A* rdar9212495_ptr(const Rdar9212495_C* ptr) {
+  const Rdar9212495_A* val = dynamic_cast<const Rdar9212495_A*>(ptr);
+
+  if (val == 0) {
+    val->bar(); // expected-warning{{Called C++ object pointer is null}}
+  }
+
+  return val;
+}
+
 // Test constructors invalidating arguments.  Previously this raised
 // an uninitialized value warning.
 extern "C" void __attribute__((noreturn)) PR9645_exit(int i);
diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp
index a12e0bd..c9bfadc 100644
--- a/test/Analysis/reference.cpp
+++ b/test/Analysis/reference.cpp
@@ -90,3 +90,29 @@
     clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}}
   }
 }
+
+void testRef() {
+  int *x = 0;
+  int &y = *x; // expected-warning{{Dereference of null pointer}}
+  y = 5;
+}
+
+
+// ------------------------------------
+// False negatives
+// ------------------------------------
+
+namespace rdar11212286 {
+  class B{};
+
+  B test() {
+    B *x = 0;
+    return *x; // should warn here!
+  }
+
+  B &testRef() {
+    B *x = 0;
+    return *x; // should warn here!
+  }
+
+}