Added checking for undefined results of '<<' and '>>' (shifting by too many bits, etc.)
This current implementation only works when both operands are concrete values; later we will add support for symbolic values.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47726 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp
index 6106ef3..74f3a9a 100644
--- a/Analysis/GRExprEngine.cpp
+++ b/Analysis/GRExprEngine.cpp
@@ -1008,14 +1008,11 @@
           bool isFeasible = false;
           ValueState* ZeroSt =  Assume(St, RightV, false, isFeasible);
           
-          if (isFeasible) {
-            NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
-            
-            if (DivZeroNode) {
+          if (isFeasible)
+            if (NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2)) {
               DivZeroNode->markAsSink();
               BadDivides.insert(DivZeroNode);
             }
-          }
           
           // Second, "assume" that the denominator cannot be 0.
           
@@ -1029,6 +1026,7 @@
         // Fall-through.  The logic below processes the divide.
       }
       
+      
       if (Op <= BinaryOperator::Or) {
         
         // Process non-assignements except commas or short-circuited
@@ -1041,6 +1039,18 @@
           continue;
         }
         
+        if (Result.isUndef() && !LeftV.isUndef() && !RightV.isUndef()) {
+          
+          // The operands were not undefined, but the result is undefined.
+          
+          if (NodeTy* UndefNode = Builder->generateNode(B, St, N2)) {
+            UndefNode->markAsSink();            
+            UndefResults.insert(UndefNode);
+          }
+          
+          continue;
+        }
+        
         Nodify(Dst, B, N2, SetRVal(St, B, Result));
         continue;
       }
@@ -1195,6 +1205,19 @@
           }
 
           RVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType());
+          
+          if (Result.isUndef()) {
+            
+            // The operands were not undefined, but the result is undefined.
+            
+            if (NodeTy* UndefNode = Builder->generateNode(B, St, N2)) {
+              UndefNode->markAsSink();            
+              UndefResults.insert(UndefNode);
+            }
+            
+            continue;
+          }
+          
           St = SetRVal(SetRVal(St, B, Result), LeftLV, Result);
         }
       }
@@ -1591,9 +1614,13 @@
         GraphPrintCheckerState->isUndefDeref(N) ||
         GraphPrintCheckerState->isUndefStore(N) ||
         GraphPrintCheckerState->isUndefControlFlow(N) ||
-        GraphPrintCheckerState->isBadDivide(N))
+        GraphPrintCheckerState->isBadDivide(N) ||
+        GraphPrintCheckerState->isUndefResult(N))
       return "color=\"red\",style=\"filled\"";
     
+    if (GraphPrintCheckerState->isNoReturnCall(N))
+      return "color=\"blue\",style=\"filled\"";
+    
     return "";
   }
     
@@ -1635,6 +1662,11 @@
         else if (GraphPrintCheckerState->isBadDivide(N)) {
           Out << "\\|Divide-by zero or undefined value.";
         }
+        else if (GraphPrintCheckerState->isUndefResult(N)) {
+          Out << "\\|Result of operation is undefined.";
+        }
+        else if (GraphPrintCheckerState->isNoReturnCall(N))
+          Out << "\\|Call to function marked \"noreturn\".";
         
         break;
       }