Index: lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- lib/StaticAnalyzer/Core/Store.cpp +++ lib/StaticAnalyzer/Core/Store.cpp @@ -394,14 +394,28 @@ 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 @@ // 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(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) { Index: test/Analysis/casts.c =================================================================== --- test/Analysis/casts.c +++ test/Analysis/casts.c @@ -213,3 +213,14 @@ } #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); +} Index: test/Analysis/pointer-to-member.cpp =================================================================== --- test/Analysis/pointer-to-member.cpp +++ test/Analysis/pointer-to-member.cpp @@ -253,11 +253,10 @@ 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;