In ProgramState::getSVal(Loc, QualType), the QualType parameter, which represents the type of the expected value, is optional. If it is not supplied, it is auto-detected by looking at the memory region in Loc. For typed-value regions such autodetection is trivial. For other kinds of regions (most importantly, for symbolic regions) it apparently never worked correctly: it detected the location type (pointer type), not the value type in this location (pointee type).
Our tests contain numerous cases when such autodetection was working incorrectly, but for existing tests it never mattered. There are three notable places where the type was regularly auto-detected incorrectly:
- ExprEngine::performTrivialCopy(). Trivial copy from symbolic references never worked - test case attached.
- CallAndMessageChecker::uninitRefOrPointer(). Here the code only cares if the value is Undefined or not, so autodetected type didn't matter.
- GTestChecker::modelAssertionResultBoolConstructor(). This is how the issue was found in https://bugs.llvm.org/show_bug.cgi?id=34305 - test case attached.
I added a few more sanity checks - we'd now also fail with an assertion if we are unable to autodetect the pointer type, warning the author of the checker to pass the type explicitly.
It is sometimes indeed handy to put a void-pointer-typed Loc into getSVal(Loc), as demonstrated in the exercise-ps.c's f2() test through CallAndMessageChecker (case '2.' above). I handled this on the API side in order to simplify checker API, implicitly turning void into char, though i don't mind modifying CallAndMessageChecker to pass CharTy explicitly instead.
Nit: It seems a bit odd to read the first byte here since (unless I'm misunderstanding) this would never be triggered by actual C semantics, only by a checker. Did you consider just returning UnknownVal() in this case?