Skip to content

numeric_cast_v(expr) now requires constant_expr #4004

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 1 commit into from
Feb 17, 2019

Conversation

kroening
Copy link
Member

This is follow-up from a discussion on PR #3998, and a comment by
@tautschnig.

This function always fails, with an exception, when given anything but a
constant_exprt.

This change means that the caller must do the type conversion. The benefit
is to make the caller more aware of the requirement that this must be a
constant, and to make the caller handle the error appropriately (with an
user-friendly error message) in case this is not possible.

The disadvantage is additional code at the call site.

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • n/a Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

A few redundant invariants, and two apparent changes in behaviour that should be tested or reverted

@@ -155,7 +155,9 @@ void symbol_factoryt::gen_nondet_array_init(
const recursion_sett &recursion_set)
{
auto const &array_type = to_array_type(expr.type());
auto const array_size = numeric_cast_v<size_t>(array_type.size());
const auto &size = array_type.size();
PRECONDITION(size.id() == ID_constant);
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant with to_constant_expr?

Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ Just noting this never got addressed.

@@ -72,9 +72,13 @@ bool boolbvt::literal(
std::size_t element_width=boolbv_width(index_expr.type());
CHECK_RETURN(element_width != 0);

mp_integer index = numeric_cast_v<mp_integer>(index_expr.index());
const auto &index = index_expr.index();
PRECONDITION(index.id() == ID_constant);
Copy link
Contributor

Choose a reason for hiding this comment

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

redundant

Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ Or this


std::size_t element_size=boolbv_width(subtype);

DATA_INVARIANT(
size.id() == ID_constant, "update expects constant-sized array");
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant

Copy link
Contributor

Choose a reason for hiding this comment

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

@smowton 👎 - this provides more information that just relying on the cast. But according to guidelines, should be framed in the should form, for clarity:

Array should be constant size for boolbv_update

const mp_integer size =
numeric_cast_v<mp_integer>(to_vector_type(type).size());
const mp_integer size_int =
numeric_cast_v<mp_integer>(to_constant_expr(size));
Copy link
Contributor

Choose a reason for hiding this comment

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

Change in behaviour: returning 0 vs. {}?


const std::size_t n_el = numeric_cast_v<std::size_t>(array_type.size());
if(!size.is_constant())
Copy link
Contributor

Choose a reason for hiding this comment

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

Change in behaviour: returning empty array vs. nil?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That one seems like a bugfix!

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a change in behaviour - could you add a unit test checking this and ideally put it into a separate commit in case it breaks anything (this would be a big commit to comb through!)

Presumably this change came about, because in a regression test the size here is non-const, perhaps the test could be tightened so it would have failed before too?

@@ -127,6 +127,8 @@ xmlt xml(const exprt &expr, const namespacet &ns)

if(expr.id() == ID_constant)
{
const auto &constant_expr = to_constant_expr(expr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Isn't this also in another PR? Maybe get that other one merged first?

@@ -2636,8 +2644,10 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
void smt2_convt::flatten_array(const exprt &expr)
{
const array_typet &array_type = to_array_type(expr.type());
const exprt &size_expr = array_type.size();
PRECONDITION(size_expr.id() == ID_constant);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Redundant

const auto &size = vector_type.size();

auto sub = pointer_offset_bits(vector_type.subtype(), ns);
if(!sub.has_value() || size.id() != ID_constant)
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 invariant


const std::size_t n_el = numeric_cast_v<std::size_t>(array_type.size());
if(!size.is_constant())
Copy link
Collaborator

Choose a reason for hiding this comment

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

That one seems like a bugfix!

@tautschnig tautschnig assigned kroening and unassigned tautschnig Jan 31, 2019
@kroening
Copy link
Member Author

On the preconditions: I do feel these are important as a way of documenting the contract of the function they are in.
vector size: I'll do a PR that makes that invariant part of the signature.
Yes, there are two changes of behaviour here, where the case of "size is not constant" was overlooked. I'll make these more explicit.

@kroening
Copy link
Member Author

This PR will shrink a lot with #4007.

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.

🚫
This PR failed Diffblue compatibility checks (cbmc commit: ebfb529).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/99263775
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

@kroening kroening force-pushed the numeric_cast_v_constant_expr branch 3 times, most recently from 5b1192e to 00df0f4 Compare February 1, 2019 22:07
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.

🚫
This PR failed Diffblue compatibility checks (cbmc commit: 94ec292).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/99494027
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

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.

🚫
This PR failed Diffblue compatibility checks (cbmc commit: 00df0f4).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/99498173
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

@kroening kroening assigned thk123 and tautschnig and unassigned kroening Feb 2, 2019
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.

Some small bits left, but also will need a TG bump.

@tautschnig tautschnig removed their assignment Feb 2, 2019
@majakusber majakusber assigned antlechner and unassigned thk123 and majakusber Feb 4, 2019
@antlechner
Copy link
Contributor

Some tests are still failing on the TG bump for this, I'm investigating and I'll post updates here.

@antlechner
Copy link
Contributor

The TG bump is now passing. 👍

Copy link
Contributor

@thk123 thk123 left a comment

Choose a reason for hiding this comment

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

Please fix the variable name and the test for the bug fix

@@ -155,7 +155,9 @@ void symbol_factoryt::gen_nondet_array_init(
const recursion_sett &recursion_set)
{
auto const &array_type = to_array_type(expr.type());
auto const array_size = numeric_cast_v<size_t>(array_type.size());
const auto &size = array_type.size();
PRECONDITION(size.id() == ID_constant);
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ Just noting this never got addressed.

@@ -72,9 +72,13 @@ bool boolbvt::literal(
std::size_t element_width=boolbv_width(index_expr.type());
CHECK_RETURN(element_width != 0);

mp_integer index = numeric_cast_v<mp_integer>(index_expr.index());
const auto &index = index_expr.index();
PRECONDITION(index.id() == ID_constant);
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ Or this


// constant?
if(expr.index().is_constant())
if(index.is_constant())
Copy link
Contributor

Choose a reason for hiding this comment

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

I think more idiomatic in this code base to:

if(const auto &constant_index = try_expr_dynamic_cast<constant_exprt>(index))
{
...
  numeric_cast_v<mp_integer>(constant_index);

Since seems plausible the is_constant method will go away at some point

Copy link
Contributor

Choose a reason for hiding this comment

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

or shorter using an optional:

if(const auto index_as_integer = numeric_cast<mp_integer>(index))

@@ -87,8 +87,10 @@ get_quantifier_var_max(const exprt &var_expr, const exprt &quantifier_expr)
continue;
if(expr_eq(var_expr, x.op0()) && x.op1().id()==ID_constant)
{
exprt over_expr=x.op1();
const constant_exprt &over_expr = to_constant_expr(x.op1());
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ While in the area, you might like to tidy the if to not duplicate the checking the id by using try_dynamic_cast

Copy link
Contributor

Choose a reason for hiding this comment

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

or the version of numeric_cast which returns an optional


std::size_t element_size=boolbv_width(subtype);

DATA_INVARIANT(
size.id() == ID_constant, "update expects constant-sized array");
Copy link
Contributor

Choose a reason for hiding this comment

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

@smowton 👎 - this provides more information that just relying on the cast. But according to guidelines, should be framed in the should form, for clarity:

Array should be constant size for boolbv_update


const std::size_t n_el = numeric_cast_v<std::size_t>(array_type.size());
if(!size.is_constant())
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a change in behaviour - could you add a unit test checking this and ideally put it into a separate commit in case it breaks anything (this would be a big commit to comb through!)

Presumably this change came about, because in a regression test the size here is non-const, perhaps the test could be tightened so it would have failed before too?


// constant?
if(expr.index().is_constant())
if(index.is_constant())
Copy link
Contributor

Choose a reason for hiding this comment

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

or shorter using an optional:

if(const auto index_as_integer = numeric_cast<mp_integer>(index))

@@ -87,8 +87,10 @@ get_quantifier_var_max(const exprt &var_expr, const exprt &quantifier_expr)
continue;
if(expr_eq(var_expr, x.op0()) && x.op1().id()==ID_constant)
{
exprt over_expr=x.op1();
const constant_exprt &over_expr = to_constant_expr(x.op1());
Copy link
Contributor

Choose a reason for hiding this comment

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

or the version of numeric_cast which returns an optional

@kroening kroening force-pushed the numeric_cast_v_constant_expr branch from a4dded0 to 3a6425c Compare February 16, 2019 16:36
@kroening kroening force-pushed the numeric_cast_v_constant_expr branch 3 times, most recently from 89345ef to bd13a73 Compare February 16, 2019 17:01

for(std::size_t i=0; i<n_el; ++i)
for(std::size_t i=0; i<number_of_elements; ++i)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This isn't clang-format correctly spaced out.

This is follow-up from a discussion on PR #3998, and a comment by
@tautschnig.

This function always fails, with an exception, when given anything but a
constant_exprt.

This change means that the caller must do the type conversion.  The benefit
is to make the caller more aware of the requirement that this must be a
constant, and to make the caller handle the error appropriately (with an
user-friendly error message) in case this is not possible.

The disadvantage is additional code at the call site.
@kroening kroening force-pushed the numeric_cast_v_constant_expr branch from bd13a73 to 4a133b3 Compare February 16, 2019 21:21
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: 4a133b3).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/101202288

@kroening kroening merged commit a5944a7 into develop Feb 17, 2019
@kroening kroening deleted the numeric_cast_v_constant_expr branch February 17, 2019 16:27
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.

9 participants