Implemented simple check in <rdar://problem/6600344>: When the receiver of a
message expression is nil and the return type is struct then the returned value
is undefined or potentially garbage.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65003 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index b055415..60bef6e 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1514,8 +1514,7 @@
     
     SVal L = GetSVal(state, Receiver);
     
-    // Check for undefined control-flow or calls to NULL.
-    
+    // Check for undefined control-flow.    
     if (L.isUndef()) {
       NodeTy* N = Builder->generateNode(ME, state, Pred);
       
@@ -1527,6 +1526,33 @@
       return;
     }
     
+    // "Assume" that the receiver is not NULL.    
+    bool isFeasibleNotNull = false;
+    Assume(state, L, true, isFeasibleNotNull);
+    
+    // "Assume" that the receiver is NULL.    
+    bool isFeasibleNull = false;
+    const GRState *StNull = Assume(state, L, false, isFeasibleNull);
+    
+    if (isFeasibleNull) {
+      // Check if the receiver was nil and the return value a struct.
+      if (ME->getType()->isRecordType()) {
+        // The [0 ...] expressions will return garbage.  Flag either an
+        // explicit or implicit error.  Because of the structure of this
+        // function we currently do not bifurfacte the state graph at
+        // this point.
+        // FIXME: We should bifurcate and fill the returned struct with
+        //  garbage.                
+        if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
+          N->markAsSink();
+          if (isFeasibleNotNull)
+            NilReceiverStructRetImplicit.insert(N);
+          else
+            NilReceiverStructRetExplicit.insert(N);
+        }
+      }
+    }
+    
     // Check if the "raise" message was sent.
     if (ME->getSelector() == RaiseSel)
       RaisesException = true;