Skip to content

Cleanup of asserts and throws under the goto-symex directory #2902

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

Merged
merged 2 commits into from
Sep 24, 2018

Conversation

NlightNFotis
Copy link
Contributor

This PR is similar in spirit to #2703 but it targets the goto-symex/ directory.

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially the same comments as I've put on other PRs related to the assert cleanup: let's please use APIs and thereby lift invariants as much as possible.

assert(tmp.operands().size()==2);
DATA_INVARIANT(
tmp.operands().size() == 2,
"byte_extract_exprt should have two operands.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please use to_byte_extract_expr, and use byte_extract_exprt's API. Otherwise we duplicate consistency checks across the code base and risk getting out-of-sync.

if(expr.operands().size()!=1)
throw "member expects one operand";
DATA_INVARIANT(
expr.operands().size() == 1, "member_exprt takes one operand.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use to_member_expr: return constant_propagation_reference(to_member_expr(expr).compound();

@@ -76,20 +76,23 @@ bool postconditiont::is_used_address_of(
}
else if(expr.id()==ID_index)
{
assert(expr.operands().size()==2);
DATA_INVARIANT(
expr.operands().size() == 2, "index_exprt takes two operands.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use to_index_expr and use its API below.


return
is_used_address_of(expr.op0(), identifier) ||
is_used(expr.op1(), identifier);
}
else if(expr.id()==ID_member)
{
assert(expr.operands().size()==1);
DATA_INVARIANT(
expr.operands().size() == 1, "member_exprt takes one operand.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use return is_used_address_of(to_member_expr(expr).compound(), identifier);

return is_used_address_of(expr.op0(), identifier);
}
else if(expr.id()==ID_dereference)
{
assert(expr.operands().size()==1);
DATA_INVARIANT(
expr.operands().size() == 1, "dereference_exprt takes one operand.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use return is_used(to_dereference_expr(expr).pointer(), identifier);

@@ -155,7 +158,8 @@ bool postconditiont::is_used(
if(expr.id()==ID_address_of)
{
// only do index!
assert(expr.operands().size()==1);
DATA_INVARIANT(
expr.operands().size() == 1, "address_of_exprt takes one operand.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above: use to_address_of_expr etc - I'll stop putting the same comments, it applies several times below.

@@ -112,7 +112,7 @@ void symex_slicet::slice(symex_target_equationt::SSA_stept &SSA_step)
void symex_slicet::slice_assignment(
symex_target_equationt::SSA_stept &SSA_step)
{
assert(SSA_step.ssa_lhs.id()==ID_symbol);
PRECONDITION(SSA_step.ssa_lhs.id() == ID_symbol);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be true by design.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still, isn't it a good idea to leave it there, even if only for documentation purposes?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal, but I think if we were to go down that route we'd have, e.g., any use of an index_exprt prefixed by expr.id() == ID_index.

@@ -283,7 +285,7 @@ void goto_symext::symex_assign_typecast(
{
// these may come from dereferencing on the lhs

assert(lhs.operands().size()==1);
PRECONDITION(lhs.operands().size() == 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True by virtue of it being a typecast_exprt


if(lhs.operands().size()!=2)
throw "index must have two operands";
DATA_INVARIANT(lhs.operands().size() == 2, "index_exprt takes two operands");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True for all index_exprt

@@ -368,7 +368,8 @@ void goto_symext::symex_assign_struct_member(
// typecasts involved? C++ does that for inheritance.
if(lhs_struct.id()==ID_typecast)
{
assert(lhs_struct.operands().size()==1);
DATA_INVARIANT(
lhs_struct.operands().size() == 1, "typecast_exprt takes one operand.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use to_typecast_expr

@NlightNFotis
Copy link
Contributor Author

@tautschnig I have implemented most of the changes you suggested. I found them to be very good suggestions. Just two observations: Don't review it yet, I need to go through the whole PR and see where else I could apply the casts with the integrated checks, and also, for some of the superfluous PRECONDITIONs, aren't they okay, even if only for documentation purposes (iirc they are not built into the release builds, so no performance overhead for a user)

@NlightNFotis
Copy link
Contributor Author

As a general update on this, I'm happy with the changes thus far. It's failing CI on some JBMC regression tests, which are expecting some particular output string to be present, alone, in one line. The exception added here makes the particular errors to be multiline, so the tests are failing. I'm going to fix the tests, but first I'm waiting for #2996 to go in, as it contains some exception classes that I think are more appropriate in a couple of cases. Once that goes in, I'm going to rebase, see the behaviour of the tests, and then I'm going to fix the tests that need fixing based on the error messages coming out of the improved exception classes.

@@ -495,12 +493,12 @@ void goto_symex_statet::rename(
}
else if(expr.id()==ID_address_of)
{
DATA_INVARIANT(
expr.type().id() == ID_pointer,
"type of expression required to be pointer");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should just be removed, as should the DATA_INVARIANT below. We don't even care whether the type of the expression is a pointer, and the subsequent invariant should be replaced by a use of to_address_of_expr

assert(dest.operands().size()==2);
DATA_INVARIANT(
dest.operands().size() == 2,
"index expression expected to have two operands");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be to_index_expr

assert(dest.operands().size()==1);
DATA_INVARIANT(
dest.operands().size() == 1,
"member expression expected to have one operand");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_member_expr

assert(dest.operands().size()==1);
DATA_INVARIANT(
dest.operands().size() == 1,
"dereference expression expected to have 1 operand");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_dereference_expr

assert(dest.operands().size()==1);
DATA_INVARIANT(
dest.operands().size() == 1,
"address_of expression expected to have one operand at this point");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_address_of_expr

@@ -155,6 +156,9 @@ exprt goto_symext::address_arithmetic(
}
else if(expr.id()==ID_dereference)
{
DATA_INVARIANT(
expr.operands().size() == 1,
"dereference expression expected to have one operand");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_dereference_expr

throw "dereference takes one operand";
DATA_INVARIANT(
expr.operands().size() == 1,
"dereference expression expected to have one operand");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_dereference_expr

throw "atomic sections differ across branches";
INVARIANT(
state.atomic_section_id == goto_state.atomic_section_id,
"atomic sections differ across branches");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be an exception as one can craft programs exhibiting this.

PRECONDITION(expr.op0().id()==ID_symbol);
DATA_INVARIANT(
expr.operands().size() == 2,
"for_all expression expected to have two operands");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_quantifier_expr

INVARIANT(
state.atomic_section_id == 0,
"spawning threads out of atomic sections is not allowed; "
"this would require amendments to ordering constraints");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be an exception as you can write input programs doing so.

@NlightNFotis
Copy link
Contributor Author

NlightNFotis commented Sep 24, 2018

@tautschnig Hi Michael, I have addressed all the comments in your review, aside from one.

You have suggested to remove some code, after advising with either Matthias or Daniel. It's not easy for me to get hold of either of them now, so I suggest we leave this for a later cleanup (I have already marked it on my todo, so it's not lost, however if you believe that it should be done now, I will see what I can do, I just thought it could be a good idea to not get hung up on this now since this work is relatively high priority).

I want a little bit of advising on a different part of the PR however. In goto_symex_state.cpp:514 there's a DATA_INVARIANT that seems suspiciously general. I thought it a good idea to move it to the transfer functions (to_if_expr), but in doing so some of the tests get broken. This happens because all the tests that use our internal malloc get to code that looks like this:

__CPROVER_deallocated =
    (malloc_res == __CPROVER_deallocated) ? 0 : __CPROVER_deallocated;

where __CPROVER_deallocated is declared as a pointer in a different file. (For a live example of this take a look here. In this case __CPROVER_deallocated's type is a symbol whereas the 0 is a constant, hence the DATA_INVARIANT failing in multiple of the tests. This seems to me that the promotion is not being handled correctly (I have also checked with the C standard n1124 and that should be typechecking, but on the condition that both the consequent and the alternative expressions are of the same type (in this case 6.5.15-3 indicates that it should typecheck on the condition that one operand is a pointer and the other is a null pointer constant).

This made me instinctively want to go and modify the parser, to do automatic implicit typecasts when it parses a conditional expression, however most of what I have tried seems to be convoluted, and most likely wrong (couldn't get them to work). Do you have any particular input on that, or maybe some pointers on what should change? If it's elaborate work, I'm happy to do it as part of a different PR and get this in as it is now if you think it's good as a cleanup PR, I just thought that moving the invariant to the transfer functions is a good piece of work in line with us not duplicating checks.

@tautschnig
Copy link
Collaborator

[...] In goto_symex_state.cpp:514 there's a DATA_INVARIANT that seems suspiciously general. I thought it a good idea to move it to the transfer functions (to_if_expr), but in doing so some of the tests get broken. [...]

This sound like a very good idea, and we should dig deeper. Would you mind creating an fresh PR doing just this (CI will fail, of course). Let's then you and I debug this - it seems that symbol types aren't uniformly expanded.

@tautschnig tautschnig merged commit 2e9e73d into diffblue:develop Sep 24, 2018
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: 8558c57).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/85748730

@NlightNFotis NlightNFotis deleted the custom_exception branch February 19, 2021 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants