-
Notifications
You must be signed in to change notification settings - Fork 273
Improve style in goto_program_template.h #859
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
Conversation
targett target, | ||
targetst &successors) | ||
template <typename Target> | ||
std::list<Target> goto_program_templatet<codeT, guardT>::get_successors( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This returns a list, which should either use move semantics (fast), or be constructed directly in the calling scope via RVO (really fast), so I doubt there's any penalty to this vs. modifying a list through a mutable reference.
if(target==instructions.end()) | ||
return; | ||
return std::list<Target>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By using early returns, we can restrict the scope of mutable state, which makes it easier to reason about the behaviour of this method.
I'm aware of the failing tests - I'll fix this up when I get an opportunity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall, except for the bugs as noted. Those fixes might address the failing tests. (Looking at them: actually that isn't sufficient as there are various build problems.)
|
||
if(!i.guard.is_true() && next!=instructions.end()) | ||
if(i.guard.is_false() && next!=instructions.end()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong - a guard
is an expression an can be true, false, or something non-constant. Thus !i.guard.is_true()
is not the same as i.guard.is_false()
. That might well fix failing tests.
const instructiont &i=*target; | ||
|
||
if(i.is_goto()) | ||
if(i.is_assume() && i.guard.is_true() && next!=instructions.end()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above, this is wrong.
c9066ff
to
007a911
Compare
const auto op=std::bind1st( | ||
std::mem_fun(static_cast<ftype>(&goto_programt::insert_before)), &body); | ||
return insert_preserving_source_location(pos, op); | ||
return insert_preserving_source_location( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was broken due to insert_before
changing to take a const_targett
instead of a targett
. I could just fix the typedef, but Meyers recommends in 'Effective Modern C++' that we prefer lambdas over std::bind
, so I've made that change too.
|
||
if(i.is_goto()) | ||
if(i.is_assume() && !i.guard.is_false() && next!=instructions.end()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You must not conflate i.is_assume()
and the remainder of the test into one condition as this would yield a single-entry list either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Fixed now.
The biggest change is to `goto_program_templatet::get_successors`, which now returns a list of targets instead of modifying a list which was passed in. With move semantics, there should be no performance penalty. It also cleans up call sites of this method, which no longer need to have a preceding list declaration. This change was made because there were two version of `get_successors`, one `const` and one not, with slightly different implementations. By templating the method on the `Target` type, we can reduce duplication, and avoid bugs where const- and non-const-methods have different behaviours. Also replaced a few iterator increments/decrements with `std::next` and `std::prev`, and made some const-correctness fixes.
The biggest change is to
goto_program_templatet::get_successors
, which now returns a list of targets instead of modifying a list which was passed-by-reference. With move semantics, there should be no performance penalty. It also cleans up call sites of this method, which no longer need to have a preceding list declaration.This change was made because there were two version of
get_successors
, oneconst
and one not, with slightly different implementations. By templating the method on theTarget
type, we can reduce duplication, and avoid bugs where const- and non-const-methods have different behaviours.Also replaced a few iterator increments/decrements with
std::next
andstd::prev
, and made some const-correctness fixes.