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/ValueManager.cpp b/Analysis/ValueManager.cpp
index 64f4b27..2a8d23d 100644
--- a/Analysis/ValueManager.cpp
+++ b/Analysis/ValueManager.cpp
@@ -76,7 +76,7 @@
   return *C;
 }
 
-const llvm::APSInt&
+const llvm::APSInt*
 ValueManager::EvaluateAPSInt(BinaryOperator::Opcode Op,
                              const llvm::APSInt& V1, const llvm::APSInt& V2) {
   
@@ -85,53 +85,83 @@
       assert (false && "Invalid Opcode.");
       
     case BinaryOperator::Mul:
-      return getValue( V1 * V2 );
+      return &getValue( V1 * V2 );
       
     case BinaryOperator::Div:
-      return getValue( V1 / V2 );
+      return &getValue( V1 / V2 );
       
     case BinaryOperator::Rem:
-      return getValue( V1 % V2 );
+      return &getValue( V1 % V2 );
       
     case BinaryOperator::Add:
-      return getValue( V1 + V2 );
+      return &getValue( V1 + V2 );
       
     case BinaryOperator::Sub:
-      return getValue( V1 - V2 );
+      return &getValue( V1 - V2 );
       
-    case BinaryOperator::Shl:
-      return getValue( V1.operator<<( (unsigned) V2.getZExtValue() ));
+    case BinaryOperator::Shl: {
+
+      // FIXME: This logic should probably go higher up, where we can
+      // test these conditions symbolically.
       
-    case BinaryOperator::Shr:
-      return getValue( V1.operator>>( (unsigned) V2.getZExtValue() ));
+      // FIXME: Expand these checks to include all undefined behavior.
+      
+      if (V2.isSigned() && V2.isNegative())
+        return NULL;
+      
+      uint64_t Amt = V2.getZExtValue();
+      
+      if (Amt > V1.getBitWidth())
+        return NULL;
+      
+      return &getValue( V1.operator<<( (unsigned) Amt ));
+    }
+      
+    case BinaryOperator::Shr: {
+      
+      // FIXME: This logic should probably go higher up, where we can
+      // test these conditions symbolically.
+      
+      // FIXME: Expand these checks to include all undefined behavior.
+      
+      if (V2.isSigned() && V2.isNegative())
+        return NULL;
+      
+      uint64_t Amt = V2.getZExtValue();
+      
+      if (Amt > V1.getBitWidth())
+        return NULL;
+      
+      return &getValue( V1.operator>>( (unsigned) Amt ));
+    }
       
     case BinaryOperator::LT:
-      return getTruthValue( V1 < V2 );
+      return &getTruthValue( V1 < V2 );
       
     case BinaryOperator::GT:
-      return getTruthValue( V1 > V2 );
+      return &getTruthValue( V1 > V2 );
       
     case BinaryOperator::LE:
-      return getTruthValue( V1 <= V2 );
+      return &getTruthValue( V1 <= V2 );
       
     case BinaryOperator::GE:
-      return getTruthValue( V1 >= V2 );
+      return &getTruthValue( V1 >= V2 );
       
     case BinaryOperator::EQ:
-      return getTruthValue( V1 == V2 );
+      return &getTruthValue( V1 == V2 );
       
     case BinaryOperator::NE:
-      return getTruthValue( V1 != V2 );
+      return &getTruthValue( V1 != V2 );
       
       // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
       
     case BinaryOperator::And:
-      return getValue( V1 & V2 );
+      return &getValue( V1 & V2 );
       
     case BinaryOperator::Or:
-      return getValue( V1 | V2 );
+      return &getValue( V1 | V2 );
       
     case BinaryOperator::Xor:
-      return getValue( V1 ^ V2 );
+      return &getValue( V1 ^ V2 );
   }
 }