The refutation manager is removing a true bug from the following program:
typedef struct o p; struct o { struct { } s; }; void q(*r, p2) { r < p2; } void k(l, node) { struct { p *node; } * n, *nodep, path[sizeof(void)]; path->node = l; for (n = path; node != l;) { q(node, n->node); nodep = n; } if (nodep) n[1].node->s; // warning: Dereference of undefined pointer value }
The problem is that the following constraint:
(conj_$1{struct o *}) - (reg_$3<int * r>): [-9223372036854775808, 0]
is encoded as:
(and (bvuge (bvsub $1 $3) #x8000000000000000) (bvule (bvsub $1 $3) #x0000000000000000))
The issue is that unsigned comparisons (bvuge and bvule) are being generated instead of signed comparisons (bvsge and bvsle).
When generating the expressions:
(conj_$1{p *}) - (reg_$3<int * r>) >= -9223372036854775808
and
(conj_$1{p *}) - (reg_$3<int * r>) <= 0
both -9223372036854775808 and 0 are casted to pointer type and LTy->isSignedIntegerOrEnumerationType() in Z3ConstraintManager::getZ3BinExpr only checks if the type is signed, not if it's a pointer.
~
I created this PR to discuss the solution, as this change is currently breaking some regressions (Analysis/ptr-arith.c).
I'll add the test to this PR as soon as I can remove all the unrelated warning that are being produced in the example (incompatible types, discarded results, etc).