Index: clang/lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/Store.cpp +++ clang/lib/StaticAnalyzer/Core/Store.cpp @@ -426,12 +426,17 @@ // 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())) { QualType sr = SR->getSymbol()->getType(); if (!hasSameUnqualifiedPointeeType(sr, castTy)) - return loc::MemRegionVal(castRegion(SR, castTy)); + return loc::MemRegionVal(castRegion(SR, castTy)); } + // Next fixes pointer dereference using type different from its initial one. + // See PR37503 for details + if (const auto *SR = dyn_cast_or_null(V.getAsRegion())) + return loc::MemRegionVal(castRegion(SR, castTy)); + } return svalBuilder.dispatchCast(V, castTy); } Index: clang/test/Analysis/casts.c =================================================================== --- clang/test/Analysis/casts.c +++ clang/test/Analysis/casts.c @@ -245,3 +245,8 @@ return a * a; } +void no_crash_reinterpret_char_as_uchar(char ***a, int *b) { + *(unsigned char **)a = (unsigned char *)b; + if (**a == 0) // no-crash + ; +} Index: clang/test/Analysis/string.c =================================================================== --- clang/test/Analysis/string.c +++ clang/test/Analysis/string.c @@ -363,6 +363,14 @@ strcpy(x, y); // no-warning } +// PR37503 +void *get_void_ptr(); +char ***type_punned_ptr; +void strcpy_no_assertion(char c) { + *(unsigned char **)type_punned_ptr = (unsigned char *)(get_void_ptr()); + strcpy(**type_punned_ptr, &c); // no-crash +} + //===----------------------------------------------------------------------=== // stpcpy() //===----------------------------------------------------------------------===