Improve path-sensitivity when using the logical not operator.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53752 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index cc31ddd..6cb714a 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -450,6 +450,15 @@
 
 // Binary operators.
 
+static unsigned char LNotOpMap[] = {
+  (unsigned char) BinaryOperator::GE,  /* LT => GE */
+  (unsigned char) BinaryOperator::LE,  /* GT => LE */
+  (unsigned char) BinaryOperator::GT,  /* LE => GT */
+  (unsigned char) BinaryOperator::LT,  /* GE => LT */
+  (unsigned char) BinaryOperator::NE,  /* EQ => NE */
+  (unsigned char) BinaryOperator::EQ   /* NE => EQ */
+};
+
 RVal GRSimpleVals::DetermEvalBinOpNN(ValueStateManager& StateMgr,
                                      BinaryOperator::Opcode Op,
                                      NonLVal L, NonLVal R)  {
@@ -462,6 +471,31 @@
       default:
         return UnknownVal();
         
+      case nonlval::SymIntConstraintValKind: {
+        const SymIntConstraint& C =
+          cast<nonlval::SymIntConstraintVal>(L).getConstraint();
+        
+        BinaryOperator::Opcode Opc = C.getOpcode();
+
+        if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
+          return UnknownVal();
+
+        // For comparison operators, translate the constraint by
+        // changing the opcode.
+        
+        int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
+        
+        assert (idx >= 0 && 
+                (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
+        
+        Opc = (BinaryOperator::Opcode) LNotOpMap[idx];
+        
+        const SymIntConstraint& CNew =
+          BasicVals.getConstraint(C.getSymbol(), Opc, C.getInt());
+        
+        return nonlval::SymIntConstraintVal(CNew);
+      }
+        
       case nonlval::ConcreteIntKind:
         
         if (isa<nonlval::ConcreteInt>(R)) {