aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h13
-rw-r--r--lib/StaticAnalyzer/Core/ConstraintManager.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp25
3 files changed, 38 insertions, 10 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index adb4d3ac16..9af59e4b38 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -16,6 +16,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/Support/SaveAndRestore.h"
namespace llvm {
class APSInt;
@@ -97,8 +98,12 @@ public:
virtual void EndPath(ProgramStateRef state) {}
/// Convenience method to query the state to see if a symbol is null or
- /// not null, or neither assumption can be made.
- ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym);
+ /// not null, or if neither assumption can be made.
+ ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {
+ llvm::SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
+
+ return checkNull(State, Sym);
+ }
protected:
/// A flag to indicate that clients should be notified of assumptions.
@@ -115,6 +120,10 @@ protected:
/// ExprEngine to determine if the value should be replaced with a
/// conjured symbolic value in order to recover some precision.
virtual bool canReasonAbout(SVal X) const = 0;
+
+ /// Returns whether or not a symbol is known to be null ("true"), known to be
+ /// non-null ("false"), or may be either ("underconstrained").
+ virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
};
ConstraintManager* CreateRangeConstraintManager(ProgramStateManager& statemgr,
diff --git a/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/lib/StaticAnalyzer/Core/ConstraintManager.cpp
index 5dd1392bde..4dec526005 100644
--- a/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/ConstraintManager.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace ento;
@@ -26,13 +25,8 @@ static DefinedSVal getLocFromSymbol(const ProgramStateRef &State,
return loc::MemRegionVal(R);
}
-/// Convenience method to query the state to see if a symbol is null or
-/// not null, or neither assumption can be made.
-ConditionTruthVal ConstraintManager::isNull(ProgramStateRef State,
- SymbolRef Sym) {
- // Disable recursive notification of clients.
- llvm::SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
-
+ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State,
+ SymbolRef Sym) {
QualType Ty = Sym->getType();
DefinedSVal V = Loc::isLocType(Ty) ? getLocFromSymbol(State, Sym)
: nonloc::SymbolVal(Sym);
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index a4c841eb6b..467abd0837 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -324,6 +324,7 @@ public:
const llvm::APSInt& Adjustment);
const llvm::APSInt* getSymVal(ProgramStateRef St, SymbolRef sym) const;
+ ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
ProgramStateRef removeDeadBindings(ProgramStateRef St, SymbolReaper& SymReaper);
@@ -347,6 +348,30 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St,
return T ? T->getConcreteValue() : NULL;
}
+ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
+ SymbolRef Sym) {
+ const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
+
+ // If we don't have any information about this symbol, it's underconstrained.
+ if (!Ranges)
+ return ConditionTruthVal();
+
+ // If we have a concrete value, see if it's zero.
+ if (const llvm::APSInt *Value = Ranges->getConcreteValue())
+ return *Value == 0;
+
+ BasicValueFactory &BV = getBasicVals();
+ APSIntType IntType = BV.getAPSIntType(Sym->getType());
+ llvm::APSInt Zero = IntType.getZeroValue();
+
+ // Check if zero is in the set of possible values.
+ if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
+ return false;
+
+ // Zero is a possible value, but it is not the /only/ possible value.
+ return ConditionTruthVal();
+}
+
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
ProgramStateRef