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.cpp20
1 files changed, 20 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index b3cf208000..96342260a0 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1744,6 +1744,26 @@ StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R,
if (!RD->isCompleteDefinition())
return StoreRef(store, *this);
+ // Handle Loc values by automatically dereferencing the location.
+ // This is necessary because we treat all struct values as regions even if
+ // they are rvalues; we may then be asked to bind one of these
+ // "rvalue regions" to an actual struct region.
+ // (This is necessary for many of the test cases in array-struct-region.cpp.)
+ //
+ // This also handles the case of a struct argument passed by value to an
+ // inlined function. In this case, the C++ standard says that the value
+ // is copy-constructed into the parameter variable. However, the copy-
+ // constructor is processed before we actually know if we're going to inline
+ // the function, and thus we don't actually have the parameter's region
+ // available. Instead, we use a temporary-object region, then copy the
+ // bindings over by value.
+ //
+ // FIXME: This will be a problem when we handle the destructors of
+ // temporaries; the inlined function will modify the parameter region,
+ // but the destructor will act on the temporary region.
+ if (const loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&V))
+ V = getBinding(store, *MRV);
+
// Handle lazy compound values and symbolic values.
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
return BindAggregate(store, R, V);