aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/RegionStore.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-02-14 19:06:11 +0000
committerJordan Rose <jordan_rose@apple.com>2013-02-14 19:06:11 +0000
commit697a68590a75f5cd2326c8f686a6c666b51688b6 (patch)
tree83d0f0919301c58779038e92506a06d3dd9b3a10 /lib/StaticAnalyzer/Core/RegionStore.cpp
parent33ace0669393acb84c24a7ff7a80e8759777b3e8 (diff)
[analyzer] Try constant-evaluation for all variables, not just globals.
In C++, constants captured by lambdas (and blocks) are not actually stored in the closure object, since they can be expanded at compile time. In this case, they will have no binding when we go to look them up. Previously, RegionStore thought they were uninitialized stack variables; now, it checks to see if they are a constant we know how to evaluate, using the same logic as r175026. This particular code path is only for scalar variables. Constant arrays and structs are still unfortunately unhandled; we'll need a stronger solution for those. This may have a small performance impact, but only for truly-undefined local variables, captures in a non-inlined block, and non-constant globals. Even then, in the non-constant case we're only doing a quick type check. <rdar://problem/13105553> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175194 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp55
1 files changed, 34 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 9572f64865..354b55119b 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1497,6 +1497,26 @@ SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B,
return getBindingForLazySymbol(R);
}
+static Optional<SVal> getConstValue(SValBuilder &SVB, const VarDecl *VD) {
+ ASTContext &Ctx = SVB.getContext();
+ if (!VD->getType().isConstQualified())
+ return Optional<SVal>();
+
+ const Expr *Init = VD->getInit();
+ if (!Init)
+ return Optional<SVal>();
+
+ llvm::APSInt Result;
+ if (Init->EvaluateAsInt(Result, Ctx))
+ return SVB.makeIntVal(Result);
+
+ if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
+ return SVB.makeNull();
+
+ // FIXME: Handle other possible constant expressions.
+ return Optional<SVal>();
+}
+
SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
const VarRegion *R) {
@@ -1506,37 +1526,30 @@ SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
// Lazily derive a value for the VarRegion.
const VarDecl *VD = R->getDecl();
- QualType T = VD->getType();
const MemSpaceRegion *MS = R->getMemorySpace();
- if (isa<UnknownSpaceRegion>(MS) ||
- isa<StackArgumentsSpaceRegion>(MS))
+ // Arguments are always symbolic.
+ if (isa<StackArgumentsSpaceRegion>(MS))
+ return svalBuilder.getRegionValueSymbolVal(R);
+
+ // Is 'VD' declared constant? If so, retrieve the constant value.
+ if (Optional<SVal> V = getConstValue(svalBuilder, VD))
+ return *V;
+
+ // This must come after the check for constants because closure-captured
+ // constant variables may appear in UnknownSpaceRegion.
+ if (isa<UnknownSpaceRegion>(MS))
return svalBuilder.getRegionValueSymbolVal(R);
if (isa<GlobalsSpaceRegion>(MS)) {
+ QualType T = VD->getType();
+
// Function-scoped static variables are default-initialized to 0; if they
// have an initializer, it would have been processed by now.
if (isa<StaticGlobalSpaceRegion>(MS))
return svalBuilder.makeZeroVal(T);
- // Other globals
- // Is 'VD' declared constant? If so, retrieve the constant value.
- QualType CT = Ctx.getCanonicalType(T);
- if (CT.isConstQualified()) {
- if (const Expr *Init = VD->getInit()) {
- llvm::APSInt Result;
- if (Init->EvaluateAsInt(Result, Ctx))
- return svalBuilder.makeIntVal(Result);
-
- if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
- return svalBuilder.makeNull();
-
- // FIXME: Handle other possible constant expressions.
- }
- }
-
- if (const Optional<SVal> &V
- = getBindingForDerivedDefaultValue(B, MS, R, CT))
+ if (Optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T))
return V.getValue();
return svalBuilder.getRegionValueSymbolVal(R);