aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/RegionStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index a37223a528..06218664f7 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1384,9 +1384,31 @@ RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
SVal RegionStoreManager::getLazyBinding(const MemRegion *LazyBindingRegion,
RegionBindingsRef LazyBinding) {
+ SVal Result;
if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
- return getBindingForElement(LazyBinding, ER);
- return getBindingForField(LazyBinding, cast<FieldRegion>(LazyBindingRegion));
+ Result = getBindingForElement(LazyBinding, ER);
+ else
+ Result = getBindingForField(LazyBinding,
+ cast<FieldRegion>(LazyBindingRegion));
+
+ // This is a hack to deal with RegionStore's inability to distinguish a
+ // default value for /part/ of an aggregate from a default value for the
+ // /entire/ aggregate. The most common case of this is when struct Outer
+ // has as its first member a struct Inner, which is copied in from a stack
+ // variable. In this case, even if the Outer's default value is symbolic, 0,
+ // or unknown, it gets overridden by the Inner's default value of undefined.
+ //
+ // This is a general problem -- if the Inner is zero-initialized, the Outer
+ // will now look zero-initialized. The proper way to solve this is with a
+ // new version of RegionStore that tracks the extent of a binding as well
+ // as the offset.
+ //
+ // This hack only takes care of the undefined case because that can very
+ // quickly result in a warning.
+ if (Result.isUndef())
+ Result = UnknownVal();
+
+ return Result;
}
SVal