summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Core/Store.cpp26
-rw-r--r--clang/test/Analysis/casts.c11
-rw-r--r--clang/test/Analysis/pointer-to-member.cpp7
3 files changed, 34 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp
index 794fd843647..ac9cb4bc425 100644
--- a/clang/lib/StaticAnalyzer/Core/Store.cpp
+++ b/clang/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) {
diff --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c
index 45ce1940dfa..dd14b8a6e30 100644
--- a/clang/test/Analysis/casts.c
+++ b/clang/test/Analysis/casts.c
@@ -213,3 +213,14 @@ void no_crash_on_symsym_cast_to_long() {
}
#endif
+
+char no_crash_SymbolCast_of_float_type_aux(int *p) {
+ *p += 1;
+ return *p;
+}
+
+void no_crash_SymbolCast_of_float_type() {
+ extern float x;
+ char (*f)() = no_crash_SymbolCast_of_float_type_aux;
+ f(&x);
+}
diff --git a/clang/test/Analysis/pointer-to-member.cpp b/clang/test/Analysis/pointer-to-member.cpp
index 65882527d2d..7f196558400 100644
--- a/clang/test/Analysis/pointer-to-member.cpp
+++ b/clang/test/Analysis/pointer-to-member.cpp
@@ -253,11 +253,10 @@ void test() {
clang_analyzer_eval(&A::y); // expected-warning{{TRUE}}
clang_analyzer_eval(&A::z); // expected-warning{{TRUE}}
- // FIXME: These should be true.
int A::*l = &A::x, A::*m = &A::y, A::*n = &A::z;
- clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(m); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(n); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(l); // expected-warning{{TRUE}}
+ clang_analyzer_eval(m); // expected-warning{{TRUE}}
+ clang_analyzer_eval(n); // expected-warning{{TRUE}}
// FIXME: These should be true as well.
A a;
OpenPOWER on IntegriCloud