When the analyzer loads a value through a given type which was previously stored with a different type, it will implicitly cast the associated value to the type in which we are trying to access it.
However, sometimes this implicit cast done by the CastRetrievedVal in RegionStoreManager::getBinding casted the value to a wrong type.
In this example, it cast to the unsigned char (which is the type of the stored value of **b, stored at #1) instead of the static type of the access (the type of **b is char*at #2).
If the analyzer wouldn't overwrite the already given non-null type, it would cast it to the correct one instead.
This patch simply modifies the code to overwrite the cast type to the underlying type of the pointee's region only if the type were null.
This also resolves a FIXME in the test suite.
This test case crashes the analyzer:
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s // expected-no-diagnostics void test(int *a, char ***b, float *c) { *(unsigned char **)b = (unsigned char *)a; // #1 if (**b == 0) // no-crash, #2 ; *(unsigned char **)b = (unsigned char *)c; if (**b == 0) // no-crash ; }
Thank you @ASDenysPetrov for raising this issue at D77062.
Nice catch!