summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/Store.cpp
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-12-19 23:48:44 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-12-19 23:48:44 +0000
commitb7d3d0f44d9f7c8602cd7f521a9ad586ceaf6f11 (patch)
treeff2ba73d136b49594dfb1c4c938dee6074076c65 /lib/StaticAnalyzer/Core/Store.cpp
parent0dc8ad57609f3456774040a501d5b6658b956c25 (diff)
downloadclang-b7d3d0f44d9f7c8602cd7f521a9ad586ceaf6f11.tar.gz
[analyzer] pr38668: Do not attempt to cast loaded values of non-scalar types.
It is expected to have the same object (memory region) treated as if it has different types in different program points. The correct behavior for RegionStore when an object is stored as an object of type T1 but loaded as an object of type T2 is to store the object as if it has type T1 but cast it to T2 during load. Note that the cast here is some sort of a "reinterpret_cast" (even in C). For instance, if you store a float and load an integer, you won't have your float rounded to an integer; instead, you will have garbage. Admit that we cannot perform the cast as long as types we're dealing with are non-trivial (neither integers, nor pointers). Of course, if the cast is not necessary (eg, T1 == T2), we can still load the value just fine. Differential Revision: https://reviews.llvm.org/D55875 rdar://problem/45062567 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349701 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/Store.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp26
1 files changed, 20 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index 794fd84364..ac9cb4bc42 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -394,14 +394,28 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
return UnknownVal();
}
+static bool isScalarEnoughToAttemptACast(QualType T) {
+ return T->isIntegralOrEnumerationType() || T->isAnyPointerType() ||
+ T->isReferenceType();
+}
+
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
- QualType castTy) {
- if (castTy.isNull() || V.isUnknownOrUndef())
+ QualType CastTy) {
+ if (CastTy.isNull() || V.isUnknownOrUndef())
return V;
+ QualType OrigTy = R->getValueType();
+
+ if (!isScalarEnoughToAttemptACast(OrigTy) ||
+ !isScalarEnoughToAttemptACast(CastTy)) {
+ if (OrigTy.getUnqualifiedType() == CastTy.getUnqualifiedType())
+ return V;
+ return UnknownVal();
+ }
+
// When retrieving symbolic pointer and expecting a non-void pointer,
// wrap them into element regions of the expected type if necessary.
// SValBuilder::dispatchCast() doesn't do that, but it is necessary to
@@ -410,13 +424,13 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
// We might need to do that for non-void pointers as well.
// FIXME: We really need a single good function to perform casts for us
// correctly every time we need it.
- if (castTy->isPointerType() && !castTy->isVoidPointerType())
+ if (CastTy->isPointerType() && !CastTy->isVoidPointerType())
if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
if (SR->getSymbol()->getType().getCanonicalType() !=
- castTy.getCanonicalType())
- return loc::MemRegionVal(castRegion(SR, castTy));
+ CastTy.getCanonicalType())
+ return loc::MemRegionVal(castRegion(SR, CastTy));
- return svalBuilder.dispatchCast(V, castTy);
+ return svalBuilder.dispatchCast(V, CastTy);
}
SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {