[cfe-commits] r46528 - /cfe/trunk/Analysis/GRConstants.cpp

Ted Kremenek kremenek at apple.com
Tue Jan 29 11:43:15 PST 2008


Author: kremenek
Date: Tue Jan 29 13:43:15 2008
New Revision: 46528

URL: http://llvm.org/viewvc/llvm-project?rev=46528&view=rev
Log:
Added preliminary transfer function support for '==' and '!='.

Made some internal API cleanups with creating ConcreteInt values, which lead to
some code reduction in implementing "++", "--".


Modified:
    cfe/trunk/Analysis/GRConstants.cpp

Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46528&r1=46527&r2=46528&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Tue Jan 29 13:43:15 2008
@@ -235,8 +235,10 @@
   ~ValueManager();
   
   ASTContext& getContext() const { return Ctx; }  
-  APSInt& getValue(const APSInt& X);      
-
+  APSInt& getValue(const APSInt& X);
+  APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
+  APSInt& getValue(uint64_t X, QualType T,
+                   SourceLocation Loc = SourceLocation());
 };
 } // end anonymous namespace
 
@@ -247,8 +249,6 @@
   for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
     I->getValue().~APSInt();
 }
-  
-  
 
 APSInt& ValueManager::getValue(const APSInt& X) {
   llvm::FoldingSetNodeID ID;
@@ -267,6 +267,19 @@
   return *P;
 }
 
+APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth, bool isUnsigned) {
+  APSInt V(BitWidth, isUnsigned);
+  V = X;  
+  return getValue(V);
+}
+
+APSInt& ValueManager::getValue(uint64_t X, QualType T, SourceLocation Loc) {
+  unsigned bits = Ctx.getTypeSize(T, Loc);
+  APSInt V(bits, T->isUnsignedIntegerType());
+  V = X;
+  return getValue(V);
+}
+
 //===----------------------------------------------------------------------===//
 // Expression Values.
 //===----------------------------------------------------------------------===//
@@ -340,17 +353,6 @@
   }  
 };
 
-class VISIBILITY_HIDDEN LValue : public RValue {
-protected:
-  LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {}
-  
-public:  
-  // Implement isa<T> support.
-  static inline bool classof(const RValue* V) {
-    return V->getBaseKind() == LValueKind;
-  }
-};
-
 class VISIBILITY_HIDDEN NonLValue : public RValue {
 protected:
   NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {}
@@ -358,6 +360,7 @@
 public:
   void print(std::ostream& Out) const;
   
+  // Arithmetic operators.
   NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const;
   NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const;
   NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const;
@@ -365,16 +368,42 @@
   NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const;
   NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const;
   
-  static NonLValue GetValue(ValueManager& ValMgr, const APSInt& V);
+  // Equality operators.
+  NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const;
+  NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const;
+
+  // Utility methods to create NonLValues.
+  static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
+                            SourceLocation Loc = SourceLocation());
+  
   static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I);
-
   static NonLValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
   
+  static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) {
+    return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy);
+  }
+    
   // Implement isa<T> support.
   static inline bool classof(const RValue* V) {
     return V->getBaseKind() >= NonLValueKind;
   }
 };
+  
+class VISIBILITY_HIDDEN LValue : public RValue {
+protected:
+  LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {}
+  
+public:
+  
+  // Equality operators.
+  NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const;
+  NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
+  
+  // Implement isa<T> support.
+  static inline bool classof(const RValue* V) {
+    return V->getBaseKind() == LValueKind;
+  }
+};
     
 } // end anonymous namespace
 
@@ -395,6 +424,14 @@
     return static_cast<ValueDecl*>(getRawPtr());
   }
   
+  inline bool operator==(const LValueDecl& R) const {
+    return getDecl() == R.getDecl();
+  }
+
+  inline bool operator!=(const LValueDecl& R) const {
+    return getDecl() != R.getDecl();
+  }
+  
   // Implement isa<T> support.
   static inline bool classof(const RValue* V) {
     return V->getSubKind() == LValueDeclKind;
@@ -435,10 +472,12 @@
     return *static_cast<APSInt*>(getRawPtr());
   }
 
+  // Arithmetic operators.
+  
   ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const {
     return ValMgr.getValue(getValue() + V.getValue());
   }
-
+  
   ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const {
     return ValMgr.getValue(getValue() - V.getValue());
   }
@@ -455,6 +494,14 @@
     return ValMgr.getValue(getValue() % V.getValue());
   }
   
+  ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
+    assert (U->getType() == U->getSubExpr()->getType());  
+    assert (U->getType()->isIntegerType());  
+    return ValMgr.getValue(-getValue()); 
+  }
+  
+  // Casting.
+  
   ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const {
     assert (CastExpr->getType()->isIntegerType());
     
@@ -464,10 +511,18 @@
     return ValMgr.getValue(X);
   }
   
-  ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
-    assert (U->getType() == U->getSubExpr()->getType());  
-    assert (U->getType()->isIntegerType());  
-    return ValMgr.getValue(-getValue()); 
+  // Equality operators.
+
+  ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const {
+    const APSInt& Val = getValue();    
+    return ValMgr.getValue(Val == V.getValue() ? 1U : 0U,
+                           Val.getBitWidth(), Val.isUnsigned());
+  }
+  
+  ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const {
+    const APSInt& Val = getValue();    
+    return ValMgr.getValue(Val != V.getValue() ? 1U : 0U,
+                           Val.getBitWidth(), Val.isUnsigned());
   }
 
   // Implement isa<T> support.
@@ -479,7 +534,7 @@
 } // end anonymous namespace
 
 //===----------------------------------------------------------------------===//
-// Transfer function dispatch.
+// Transfer function dispatch for Non-LValues.
 //===----------------------------------------------------------------------===//
 
 RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const {
@@ -500,13 +555,13 @@
   }
 }
 
-#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
+#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\
 case (k1##Kind*NumNonLValueKind+k2##Kind):\
   return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
 
-#define RVALUE_DISPATCH(Op)\
+#define NONLVALUE_DISPATCH(Op)\
 switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\
-  RVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\
+  NONLVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\
   default:\
     if (getBaseKind() == UninitializedKind ||\
         RHS.getBaseKind() == UninitializedKind)\
@@ -517,35 +572,82 @@
 return cast<NonLValue>(InvalidValue());
 
 NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const {
-  RVALUE_DISPATCH(Add)
+  NONLVALUE_DISPATCH(Add)
 }
 
 NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const {
-  RVALUE_DISPATCH(Sub)
+  NONLVALUE_DISPATCH(Sub)
 }
 
 NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const {
-  RVALUE_DISPATCH(Mul)
+  NONLVALUE_DISPATCH(Mul)
 }
 
 NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const {
-  RVALUE_DISPATCH(Div)
+  NONLVALUE_DISPATCH(Div)
 }
 
 NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const {
-  RVALUE_DISPATCH(Rem)
+  NONLVALUE_DISPATCH(Rem)
 }
 
+NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const {  
+  NONLVALUE_DISPATCH(EQ)
+}
 
-#undef RVALUE_DISPATCH_CASE
-#undef RVALUE_DISPATCH
+NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const {
+  NONLVALUE_DISPATCH(NE)
+}
+
+#undef NONLVALUE_DISPATCH_CASE
+#undef NONLVALUE_DISPATCH
 
 //===----------------------------------------------------------------------===//
-// Utility methods for constructing RValues.
+// Transfer function dispatch for LValues.
 //===----------------------------------------------------------------------===//
 
-NonLValue NonLValue::GetValue(ValueManager& ValMgr, const APSInt& V) {
-  return ConcreteInt(ValMgr.getValue(V));
+
+NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
+  if (getSubKind() != RHS.getSubKind())
+    return NonLValue::GetIntTruthValue(ValMgr, false);
+  
+  switch (getSubKind()) {
+    default:
+      assert(false && "EQ not implemented for this LValue.");
+      return cast<NonLValue>(InvalidValue());
+      
+    case LValueDeclKind: {
+      bool b = cast<LValueDecl>(*this) == cast<LValueDecl>(RHS);
+      return NonLValue::GetIntTruthValue(ValMgr, b);
+    }
+  }
+}
+
+NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const {
+  if (getSubKind() != RHS.getSubKind())
+    return NonLValue::GetIntTruthValue(ValMgr, false);
+
+  switch (getSubKind()) {
+    default:
+      assert(false && "EQ not implemented for this LValue.");
+      return cast<NonLValue>(InvalidValue());
+      
+    case LValueDeclKind: {
+      bool b = cast<LValueDecl>(*this) != cast<LValueDecl>(RHS);
+      return NonLValue::GetIntTruthValue(ValMgr, b);
+    }
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Utility methods for constructing Non-LValues.
+//===----------------------------------------------------------------------===//
+
+NonLValue NonLValue::GetValue(ValueManager& ValMgr, uint64_t X, QualType T,
+                              SourceLocation Loc) {
+
+  return ConcreteInt(ValMgr.getValue(X, T, Loc));
 }
 
 NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) {
@@ -1007,11 +1109,8 @@
       case UnaryOperator::PostInc: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-
-        QualType T = U->getType();
-        unsigned bits = getContext().getTypeSize(T, U->getLocStart());
-        APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
-        NonLValue R2 = NonLValue::GetValue(ValMgr, One);
+        NonLValue R2 = NonLValue::GetValue(ValMgr, 1U, U->getType(),
+                                           U->getLocStart());
         
         NonLValue Result = R1.Add(ValMgr, R2);
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
@@ -1021,11 +1120,8 @@
       case UnaryOperator::PostDec: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        QualType T = U->getType();
-        unsigned bits = getContext().getTypeSize(T, U->getLocStart());
-        APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
-        NonLValue R2 = NonLValue::GetValue(ValMgr, One);
+        NonLValue R2 = NonLValue::GetValue(ValMgr, 1U, U->getType(),
+                                           U->getLocStart());
         
         NonLValue Result = R1.Sub(ValMgr, R2);
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
@@ -1035,11 +1131,8 @@
       case UnaryOperator::PreInc: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        QualType T = U->getType();
-        unsigned bits = getContext().getTypeSize(T, U->getLocStart());
-        APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
-        NonLValue R2 = NonLValue::GetValue(ValMgr, One);        
+        NonLValue R2 = NonLValue::GetValue(ValMgr, 1U, U->getType(),
+                                           U->getLocStart());        
         
         NonLValue Result = R1.Add(ValMgr, R2);
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
@@ -1049,11 +1142,8 @@
       case UnaryOperator::PreDec: {
         const LValue& L1 = GetLValue(St, U->getSubExpr());
         NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        QualType T = U->getType();
-        unsigned bits = getContext().getTypeSize(T, U->getLocStart());
-        APSInt One(llvm::APInt(bits, 1), T->isUnsignedIntegerType());
-        NonLValue R2 = NonLValue::GetValue(ValMgr, One);       
+        NonLValue R2 = NonLValue::GetValue(ValMgr, 1U, U->getType(),
+                                           U->getLocStart());
         
         NonLValue Result = R1.Sub(ValMgr, R2);
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
@@ -1098,6 +1188,12 @@
       const RValue& V2 = GetValue(St, B->getRHS());
 
       switch (B->getOpcode()) {
+        default: 
+          Dst.Add(N2);
+          break;
+          
+        // Arithmetic opreators.
+          
         case BinaryOperator::Add: {
           const NonLValue& R1 = cast<NonLValue>(V1);
           const NonLValue& R2 = cast<NonLValue>(V2);
@@ -1134,6 +1230,8 @@
           break;
         }
           
+        // Assignment operators.
+          
         case BinaryOperator::Assign: {
           const LValue& L1 = cast<LValue>(V1);
           const NonLValue& R2 = cast<NonLValue>(V2);
@@ -1180,9 +1278,28 @@
           Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
           break;
         }
+          
+        // Equality operators.
 
-        default: 
-          Dst.Add(N2);
+        case BinaryOperator::EQ:
+          // FIXME: should we allow XX.EQ() to return a set of values,
+          //  allowing state bifurcation?  In such cases, they will also
+          //  modify the state (meaning that a new state will be returned
+          //  as well).
+          assert (B->getType() == getContext().IntTy);
+          
+          if (isa<LValue>(V1)) {
+            const LValue& L1 = cast<LValue>(V1);
+            const LValue& L2 = cast<LValue>(V2);
+            St = SetValue(St, B, L1.EQ(ValMgr, L2));
+          }
+          else {
+            const NonLValue& R1 = cast<NonLValue>(V1);
+            const NonLValue& R2 = cast<NonLValue>(V2);
+            St = SetValue(St, B, R1.EQ(ValMgr, R2));
+          }
+          
+          Nodify(Dst, B, N2, St);
           break;
       }
     }





More information about the cfe-commits mailing list