]> granicus.if.org Git - clang/commitdiff
[analyzer] a few helper methods for getting and comparing symbolic values
authorGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 18 Jan 2018 03:18:36 +0000 (03:18 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 18 Jan 2018 03:18:36 +0000 (03:18 +0000)
API calls should express intent, and that's a motivation behind this patch.

Differential Revision: https://reviews.llvm.org/D42218

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@322809 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
lib/StaticAnalyzer/Core/ProgramState.cpp
lib/StaticAnalyzer/Core/SValBuilder.cpp

index c01600d5c969e2b3b0fdcb9ed018032f76b41000..1e1bbc876b203a80e9cb750423286300b9135d6a 100644 (file)
@@ -37,6 +37,12 @@ public:
   /// Construct a ConstraintVal indicating the constraint is underconstrained.
   ConditionTruthVal() {}
 
+  /// \return Stored value, assuming that the value is known.
+  /// Crashes otherwise.
+  bool getValue() const {
+    return *Val;
+  }
+
   /// Return true if the constraint is perfectly constrained to 'true'.
   bool isConstrainedTrue() const {
     return Val.hasValue() && Val.getValue();
index dd2564b0a3c3ea7c6a9513cce837deff525392d8..f1283996e567a51939d566237f3f51d0c8954929 100644 (file)
@@ -212,10 +212,17 @@ public:
   assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
                        const llvm::APSInt &To) const;
 
+  /// \brief Check if the given SVal is not constrained to zero and is not
+  ///        a zero constant.
+  ConditionTruthVal isNonNull(SVal V) const;
+
   /// \brief Check if the given SVal is constrained to zero or is a zero
   ///        constant.
   ConditionTruthVal isNull(SVal V) const;
 
+  /// \return Whether values \p Lhs and \p Rhs are equal.
+  ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const;
+
   /// Utility method for getting regions.
   const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
 
index d58d0a690c88eec8f055d9654f06d29b7cd15675..dae5b5495b2752e8b8bb6db12dd4d2cad9b4b627 100644 (file)
@@ -29,6 +29,8 @@ class CXXBoolLiteralExpr;
 
 namespace ento {
 
+class ConditionTruthVal;
+
 class SValBuilder {
   virtual void anchor();
 protected:
@@ -124,7 +126,12 @@ public:
 
   SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
                  SVal lhs, SVal rhs, QualType type);
-  
+
+  /// \return Whether values in \p lhs and \p rhs are equal at \p state.
+  ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs);
+
+  SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs);
+
   DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
                               DefinedOrUnknownSVal rhs);
 
index 871bbf0b6cb13ea82df02613cf76e670231bddd7..34d4970df2d439f1620b781ca55823f12906bb0c 100644 (file)
@@ -354,6 +354,17 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
   return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
 }
 
+ConditionTruthVal ProgramState::isNonNull(SVal V) const {
+  ConditionTruthVal IsNull = isNull(V);
+  if (IsNull.isUnderconstrained())
+    return IsNull;
+  return ConditionTruthVal(!IsNull.getValue());
+}
+
+ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
+  return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
+}
+
 ConditionTruthVal ProgramState::isNull(SVal V) const {
   if (V.isZeroConstant())
     return true;
index 04452e3e7cc22f2a0cfb2756cda08699de69d57f..f49995d50ccd7ab083a93628585258b5c89a6479 100644 (file)
@@ -413,10 +413,19 @@ SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
                      type);
 }
 
+ConditionTruthVal SValBuilder::areEqual(ProgramStateRef state, SVal lhs,
+                                        SVal rhs) {
+  return state->isNonNull(evalEQ(state, lhs, rhs));
+}
+
+SVal SValBuilder::evalEQ(ProgramStateRef state, SVal lhs, SVal rhs) {
+  return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType());
+}
+
 DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
                                          DefinedOrUnknownSVal lhs,
                                          DefinedOrUnknownSVal rhs) {
-  return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType())
+  return evalEQ(state, static_cast<SVal>(lhs), static_cast<SVal>(rhs))
       .castAs<DefinedOrUnknownSVal>();
 }