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).
Should we use the method you have mentioned then? (getPointerDiffType)
Just sticking with left type seems arbitrary.