-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Minimize unnecessary casts and check for overflows in witness invariants #1665
base: apron-invariant-simplify
Are you sure you want to change the base?
Conversation
…ants not fitting into long in invariants
Nice, I think it's good to have better readable assertions! However, I'm a bit worried about one of these aspects:
This breaks invariants about the CIL AST, where all arguments to BinOp (except some Pointer + Integer ones) are supposed to have the same type as the resulting type. I don't think creating such illegal expressions is a good idea, especially given that @DrMichaelPetter's inter-domain refinement and similar features will likely also rely on the Could such logic not be moved to the pretty-printer where we know that the CIL expressions will not be fed to anything in Goblint before going through CIL parsing again? It seems printing one cast in general is enough to force the effective type to what we want it to be, regardless of overflow? |
This concern is already handled by constructing two
That's not so simple in general. All the variables in an invariant may have different integer types. Sure, when cast to I don't think this could be done while pretty-printing because this relies on overflow queries. The secondary goal is to never return invariant expressions that we cannot guarantee overflow-free when going from mathematical integers from Apron to C. |
Where is this handling? Currently it looks to be like we have modified the function If you want such things I suggest stringifying them immediately so the invariant about Cil expressions is violated only locally in the function they originate from.
Why? Either no cast is necessary and then the expression with all casts should also not contain any casts (because everything already is of the right type), or at least one of the arguments needs to be cast because the usual arithmetic promotions are not enough. In this case, CIL has both casts and your pretty printer could forgo the cast in one of the branches? What am I missing? |
Casts are also unnecessary for invariants, where char-type variables are used in an arithmetic expression; however, for CIL, they are cast to |
CIL expressions without implicit casts turned explicit are not invalid! CIL has the option
Of course they could cause problems if used in unintended contexts, but that's not the case. These CIL expressions (with or without implicit casts) are passed to
Witness invariants are intentionally wrapped into the Invariant.t type and cannot be accidentally used as normal CIL expressions.So the cast-less CIL expressions do only exist in that local scope of the conversion and the rest of Goblint just sees an Invariant.t .
Right now there isn't For non-witness use of such domains converted to expressions, there should be a separate query anyway ( |
I now tried that in #1668 and that revealed a problem with precondition loop invariants instead. |
Removing unnecessary casts
LL
suffix for constant values that fit theint
range:1LL
→1
int
range, it is not cast:(long long )h
→h
int
range, its subexpressions are not cast:(long long )j + 1LL
→j + 1
Dealing with overflows
int
range but does not overflow inlong long
, only one of the variables or constants is cast:((long long )k + (long long )d) + 2147483647LL
→((long long )k + d) + 2147483647
long long
range, it is discarded with a warningTODO
n != (unsigned char)0 → n != 0(unsigned long )arg == 0UL → arg == 0Invariant
#1668 before merging this.I also observed that using the relational domain for overflow checks would be beneficial for eliminating some of the unnecessary casts. I.e. in
36-apron/52-queuesize.c
, we can successfully verify that assertion__goblint_check(used + free == capacity)
succeeds. However, as the overflow query only queriesIntDomain
values, the additionused+free
will overflow theint
range and is thus cast in the invariant. Furthermore, making the overflow queries use the information fromrelationAnalysis
could also increase our precision. However, this should be addressed in a separate PR.