diff --git a/clang/lib/Checker/SValuator.cpp b/clang/lib/Checker/SValuator.cpp index 273e5742a8e2..a3bdcd77623f 100644 --- a/clang/lib/Checker/SValuator.cpp +++ b/clang/lib/Checker/SValuator.cpp @@ -122,7 +122,18 @@ SVal SValuator::EvalCast(SVal val, QualType castTy, QualType originalTy) { // FIXME: We should handle the case where we strip off view layers to get // to a desugared type. - assert(Loc::IsLocType(castTy)); + if (!Loc::IsLocType(castTy)) { + // FIXME: There can be gross cases where one casts the result of a function + // (that returns a pointer) to some other value that happens to fit + // within that pointer value. We currently have no good way to + // model such operations. When this happens, the underlying operation + // is that the caller is reasoning about bits. Conceptually we are + // layering a "view" of a location on top of those bits. Perhaps + // we need to be more lazy about mutual possible views, even on an + // SVal? This may be necessary for bit-level reasoning as well. + return UnknownVal(); + } + // We get a symbolic function pointer for a dereference of a function // pointer, but it is of function type. Example: diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m index 9b923bf0f809..902bfb6aae1c 100644 --- a/clang/test/Analysis/misc-ps.m +++ b/clang/test/Analysis/misc-ps.m @@ -1193,3 +1193,13 @@ void pr5272_test() { (*(struct pr5272*)0xBC000000).var2 += 2; // no-warning } +// Support casting the return value of function to another different type +// This previously caused a crash, although we likely need more precise +// reasoning here. +void* rdar8663544(); +typedef struct {} Val8663544; +Val8663544 bazR8663544() { + Val8663544(*func) () = (Val8663544(*) ()) rdar8663544; + return func(); +} +