c = pMem->flags;
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype));
You could have say: sqlite3VdbeMemRelease(struct foo pMem) {
*(some_other_type *)&pMem->flags = bar;
}
In which case the C aliasing rules would allow the compiler to assume that the assignment through "some_other_type" does not affect the assignment through whatever type pMem->flags is.I have seen this bug happen before, when compilers got better at inlining, where it was something like
void getAddressOfSomething(intptr_t *address);
...
char *p;
getAddressOfSomething((intptr_t *)&p)
*p=foo
The compiler could reorder the \*p=foo line to be before the getAddressOfSomething call for the same reason.TL;DR: Turn of strict aliasing via compiler flags (-fno-strict-aliasing on gcc) if you ever type-pun anywhere without using a union.